diff --git a/olsrd/patches/004-jsonplugin-http-headers.patch b/olsrd/patches/004-jsonplugin-http-headers.patch new file mode 100644 index 0000000..cd76006 --- /dev/null +++ b/olsrd/patches/004-jsonplugin-http-headers.patch @@ -0,0 +1,211 @@ +commit b342385531c18b8afb42db64c7a38d7879668566 +Author: Alessio Caiazza +Date: Fri May 16 12:53:15 2014 +0200 + + jsoninfo: HTTP headers with CORS (if requested) + + The new "httpheaders" parameter prepends HTTP headers to the reply. + If not set it will default to "no" and have the same behaviour as before. + Cross-origin resource sharing headers (CORS) are included in reply allowing the + json retrieval by javascript applications not served by olsrd itself. + This will allow to easily develop js applications running directly in the + browser. + + Reviewed-by: Ferry Huberts + +diff --git a/lib/jsoninfo/README_JSONINFO b/lib/jsoninfo/README_JSONINFO +index 709c975..8311ade 100644 +--- a/lib/jsoninfo/README_JSONINFO ++++ b/lib/jsoninfo/README_JSONINFO +@@ -73,6 +73,14 @@ LoadPlugin "olsrd_jsoninfo.so.0.0" + # if you set it to 0.0.0.0, it will accept all connections + #PlParam "accept" "0.0.0.0" + ++ # The "httpheaders" parameter prepends HTTP headers to the reply. ++ # If not set it will default to "no" and have the same behaviour as before. ++ # Among with a minimal set of headers also Cross-origin resource sharing ++ # headers (CORS) are included in reply allowing the json retrieval by ++ # javascript applications not served by olsrd itself. ++ # You can enable it uncommenting the following line: ++ #PlParam "httpheaders" "yes" ++ + # specify a UUID for this node to track it for debugging + #PlParam "UUIDFile" "/etc/olsrd/olsrd.uuid" + } +diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.c b/lib/jsoninfo/src/olsrd_jsoninfo.c +index 817c64a..f29a37c 100644 +--- a/lib/jsoninfo/src/olsrd_jsoninfo.c ++++ b/lib/jsoninfo/src/olsrd_jsoninfo.c +@@ -96,6 +96,9 @@ + + static int ipc_socket; + ++/* Response types */ ++#define HTTP_200 "HTTP/1.1 200 OK" ++ + /* IPC initialization function */ + static int plugin_ipc_init(void); + +@@ -126,6 +129,18 @@ static void ipc_print_interfaces(struct autobuf *); + static void ipc_print_plugins(struct autobuf *); + static void ipc_print_olsrd_conf(struct autobuf *abuf); + ++static size_t build_http_header(const char *status, const char *mime, ++ uint32_t msgsize, char *buf, uint32_t bufsize); ++ ++/* ++ * this is the size of the buffer used for build_http_header ++ * the amount of data written into the buffer will be less than ++ * 400 bytes approximatively. ++ * The size may vary because the Content-Length header contains ++ * the length of the json data ++ */ ++#define MAX_HTTPHEADER_SIZE 512 ++ + #define TXT_IPC_BUFSIZE 256 + + /* these provide all of the runtime status info */ +@@ -1282,6 +1297,9 @@ static void + send_info(unsigned int send_what, int the_socket) + { + struct autobuf abuf; ++ size_t header_len = 0; ++ char header_buf[MAX_HTTPHEADER_SIZE]; ++ const char *content_type = "application/json"; + + /* global variables for tracking when to put a comma in for JSON */ + entrynumber[0] = 0; +@@ -1320,12 +1338,17 @@ send_info(unsigned int send_what, int the_socket) + ipc_print_olsrd_conf(&abuf); + } + +- outbuffer[outbuffer_count] = olsr_malloc(abuf.len, "txt output buffer"); +- outbuffer_size[outbuffer_count] = abuf.len; ++ if(http_headers) { ++ header_len = build_http_header(HTTP_200, content_type, abuf.len, header_buf, sizeof(header_buf)); ++ } ++ ++ outbuffer[outbuffer_count] = olsr_malloc(header_len + abuf.len, "json output buffer"); ++ outbuffer_size[outbuffer_count] = header_len + abuf.len; + outbuffer_written[outbuffer_count] = 0; + outbuffer_socket[outbuffer_count] = the_socket; + +- memcpy(outbuffer[outbuffer_count], abuf.buf, abuf.len); ++ memcpy(outbuffer[outbuffer_count], header_buf, header_len); ++ memcpy((outbuffer[outbuffer_count]) + header_len, abuf.buf, abuf.len); + outbuffer_count++; + + if (outbuffer_count == 1) { +@@ -1340,6 +1363,53 @@ send_info(unsigned int send_what, int the_socket) + abuf_free(&abuf); + } + ++static size_t ++build_http_header(const char *status, const char *mime, uint32_t msgsize, ++ char *buf, uint32_t bufsize) ++{ ++ time_t currtime; ++ size_t size; ++ ++ size = snprintf(buf, bufsize, "%s\r\n", status); ++ ++ /* Date */ ++ time(&currtime); ++ size += strftime(&buf[size], bufsize - size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime)); ++ ++ /* Server version */ ++ size += snprintf(&buf[size], bufsize - size, "Server: OLSRD JSONInfo plugin\r\n"); ++ ++ /* connection-type */ ++ size += snprintf(&buf[size], bufsize - size, "Connection: closed\r\n"); ++ ++ /* MIME type */ ++ if(mime != NULL) { ++ size += snprintf(&buf[size], bufsize - size, "Content-type: %s\r\n", mime); ++ } ++ ++ /* CORS data */ ++ /**No needs to be strict here, access control is based on source IP*/ ++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Origin: *\r\n"); ++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n"); ++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Headers: Accept, Origin, X-Requested-With\r\n"); ++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Max-Age: 1728000\r\n"); ++ ++ /* Content length */ ++ if (msgsize > 0) { ++ size += snprintf(&buf[size], bufsize - size, "Content-length: %i\r\n", msgsize); ++ } ++ ++ /* Cache-control ++ * No caching dynamic pages ++ */ ++ size += snprintf(&buf[size], bufsize - size, "Cache-Control: no-cache\r\n"); ++ ++ /* End header */ ++ size += snprintf(&buf[size], bufsize - size, "\r\n"); ++ ++ return size; ++} ++ + /* + * Local Variables: + * mode: c +diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.h b/lib/jsoninfo/src/olsrd_jsoninfo.h +index 8478f62..56acb70 100644 +--- a/lib/jsoninfo/src/olsrd_jsoninfo.h ++++ b/lib/jsoninfo/src/olsrd_jsoninfo.h +@@ -62,6 +62,7 @@ extern union olsr_ip_addr jsoninfo_accept_ip; + extern union olsr_ip_addr jsoninfo_listen_ip; + extern int ipc_port; + extern int nompr; ++extern bool http_headers; + + int olsrd_plugin_interface_version(void); + int olsrd_plugin_init(void); +diff --git a/lib/jsoninfo/src/olsrd_plugin.c b/lib/jsoninfo/src/olsrd_plugin.c +index 36550a8..03aa45f 100644 +--- a/lib/jsoninfo/src/olsrd_plugin.c ++++ b/lib/jsoninfo/src/olsrd_plugin.c +@@ -64,6 +64,7 @@ union olsr_ip_addr jsoninfo_accept_ip; + union olsr_ip_addr jsoninfo_listen_ip; + int ipc_port; + int nompr; ++bool http_headers; + + static void my_init(void) __attribute__ ((constructor)); + static void my_fini(void) __attribute__ ((destructor)); +@@ -79,6 +80,7 @@ my_init(void) + + /* defaults for parameters */ + ipc_port = 9090; ++ http_headers = false; + if (olsr_cnf->ip_version == AF_INET) { + jsoninfo_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK); + jsoninfo_listen_ip.v4.s_addr = htonl(INADDR_ANY); +@@ -120,11 +122,26 @@ store_string(const char *value, void *data, set_plugin_parameter_addon addon __a + return 0; + } + ++static int ++store_boolean(const char *value, void *data, set_plugin_parameter_addon addon __attribute__ ((unused))) ++{ ++ bool *dest = data; ++ if(strcmp(value, "yes") == 0) ++ *dest = true; ++ else if (strcmp(value, "no") == 0) ++ *dest = false; ++ else ++ return 1; //error ++ ++ return 0; ++} ++ + static const struct olsrd_plugin_parameters plugin_parameters[] = { + {.name = "port",.set_plugin_parameter = &set_plugin_port,.data = &ipc_port}, + {.name = "accept",.set_plugin_parameter = &set_plugin_ipaddress,.data = &jsoninfo_accept_ip}, + {.name = "listen",.set_plugin_parameter = &set_plugin_ipaddress,.data = &jsoninfo_listen_ip}, + {.name = "uuidfile",.set_plugin_parameter = &store_string,.data = uuidfile}, ++ {.name = "httpheaders",.set_plugin_parameter = &store_boolean,.data = &http_headers}, + }; + + void