mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 02:39:44 +00:00
Use section linking to define httpd pages
This commit is contained in:
parent
dab244d92f
commit
84caf21969
228
httpd.c
228
httpd.c
@ -18,83 +18,44 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include "serval.h"
|
||||
#include "httpd.h"
|
||||
#include "conf.h"
|
||||
#include "overlay_address.h"
|
||||
#include "overlay_interface.h"
|
||||
#include "mem.h"
|
||||
#include "net.h"
|
||||
#include "server.h"
|
||||
#include "conf.h"
|
||||
|
||||
#define RHIZOME_SERVER_MAX_LIVE_REQUESTS 32
|
||||
|
||||
static HTTP_HANDLER root_page;
|
||||
static HTTP_HANDLER fav_icon_header;
|
||||
static HTTP_HANDLER interface_page;
|
||||
static HTTP_HANDLER neighbour_page;
|
||||
static HTTP_HANDLER static_page;
|
||||
|
||||
HTTP_HANDLER restful_rhizome_bundlelist_json;
|
||||
HTTP_HANDLER restful_rhizome_newsince;
|
||||
HTTP_HANDLER restful_rhizome_insert;
|
||||
HTTP_HANDLER restful_rhizome_append;
|
||||
HTTP_HANDLER restful_rhizome_;
|
||||
HTTP_HANDLER restful_meshms_;
|
||||
HTTP_HANDLER restful_keyring_;
|
||||
|
||||
HTTP_HANDLER rhizome_status_page;
|
||||
HTTP_HANDLER rhizome_file_page;
|
||||
HTTP_HANDLER manifest_by_prefix_page;
|
||||
|
||||
HTTP_HANDLER rhizome_direct_import;
|
||||
HTTP_HANDLER rhizome_direct_enquiry;
|
||||
HTTP_HANDLER rhizome_direct_dispatch;
|
||||
|
||||
struct http_handler {
|
||||
const char *path;
|
||||
HTTP_HANDLER *parser;
|
||||
};
|
||||
|
||||
struct http_handler paths[]={
|
||||
{"/restful/rhizome/bundlelist.json", restful_rhizome_bundlelist_json},
|
||||
{"/restful/rhizome/newsince/", restful_rhizome_newsince},
|
||||
{"/restful/rhizome/insert", restful_rhizome_insert},
|
||||
{"/restful/rhizome/append", restful_rhizome_append},
|
||||
{"/restful/rhizome/", restful_rhizome_},
|
||||
{"/restful/meshms/", restful_meshms_},
|
||||
{"/restful/keyring/", restful_keyring_},
|
||||
{"/rhizome/status", rhizome_status_page},
|
||||
{"/rhizome/file/", rhizome_file_page},
|
||||
{"/rhizome/import", rhizome_direct_import},
|
||||
{"/rhizome/enquiry", rhizome_direct_enquiry},
|
||||
{"/rhizome/manifestbyprefix/", manifest_by_prefix_page},
|
||||
{"/rhizome/", rhizome_direct_dispatch},
|
||||
{"/static/", static_page},
|
||||
{"/interface/", interface_page},
|
||||
{"/neighbour/", neighbour_page},
|
||||
{"/favicon.ico", fav_icon_header},
|
||||
{"/", root_page},
|
||||
};
|
||||
|
||||
static int httpd_dispatch(struct http_request *hr)
|
||||
{
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
INFOF("HTTP SERVER, %s %s", r->http.verb, r->http.path);
|
||||
r->http.response.content_generator = NULL;
|
||||
unsigned i;
|
||||
for (i = 0; i < NELS(paths); ++i) {
|
||||
const char *remainder;
|
||||
if (str_startswith(r->http.path, paths[i].path, &remainder)){
|
||||
int result = paths[i].parser(r, remainder);
|
||||
if (result == -1 || (result >= 200 && result < 600))
|
||||
return result;
|
||||
if (result == 1)
|
||||
return 0;
|
||||
if (result)
|
||||
return WHYF("dispatch function for %s returned invalid result %d", paths[i].path, result);
|
||||
|
||||
struct http_handler *handler, *parser=NULL;
|
||||
const char *remainder=NULL;
|
||||
size_t match_len=0;
|
||||
|
||||
for (handler = SECTION_START(httpd); handler < SECTION_END(httpd); ++handler) {
|
||||
size_t path_len = strlen(handler->path);
|
||||
if (parser && path_len < match_len)
|
||||
continue;
|
||||
|
||||
const char *p;
|
||||
if (str_startswith(r->http.path, handler->path, &p)){
|
||||
match_len = path_len;
|
||||
parser = handler;
|
||||
remainder = p;
|
||||
}
|
||||
}
|
||||
if (parser){
|
||||
int result = parser->parser(r, remainder);
|
||||
if (result == -1 || (result >= 200 && result < 600))
|
||||
return result;
|
||||
if (result == 1)
|
||||
return 0;
|
||||
if (result)
|
||||
return WHYF("dispatch function for %s returned invalid result %d", parser->path, result);
|
||||
}
|
||||
return 404;
|
||||
}
|
||||
|
||||
@ -544,142 +505,3 @@ int http_response_init_content_range(httpd_request *r, size_t resource_length)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int root_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char temp[8192];
|
||||
strbuf b = strbuf_local(temp, sizeof temp);
|
||||
strbuf_sprintf(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>"
|
||||
"<h1>Hello, I'm %s*</h1>",
|
||||
alloca_tohex_sid_t_trunc(my_subscriber->sid, 16));
|
||||
if (config.server.motd[0]) {
|
||||
strbuf_puts(b, "<p>");
|
||||
strbuf_html_escape(b, config.server.motd, strlen(config.server.motd));
|
||||
strbuf_puts(b, "</p>");
|
||||
}
|
||||
strbuf_puts(b, "Interfaces;<br />");
|
||||
int i;
|
||||
for (i=0;i<OVERLAY_MAX_INTERFACES;i++){
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
|
||||
strbuf_sprintf(b, "<a href=\"/interface/%d\">%d: %s, TX: %d, RX: %d</a><br />",
|
||||
i, i, overlay_interfaces[i].name, overlay_interfaces[i].tx_count, overlay_interfaces[i].recv_count);
|
||||
}
|
||||
strbuf_puts(b, "Neighbours;<br />");
|
||||
link_neighbour_short_status_html(b, "/neighbour");
|
||||
if (is_rhizome_http_enabled()){
|
||||
strbuf_puts(b, "<a href=\"/rhizome/status\">Rhizome Status</a><br />");
|
||||
}
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b)) {
|
||||
WHY("HTTP Root page buffer overrun");
|
||||
return 500;
|
||||
}
|
||||
http_request_response_static(&r->http, 200, CONTENT_TYPE_HTML, temp, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fav_icon_header(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
http_request_response_static(&r->http, 200, "image/vnd.microsoft.icon", (const char *)favicon_bytes, favicon_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int neighbour_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char buf[8*1024];
|
||||
strbuf b = strbuf_local(buf, sizeof buf);
|
||||
sid_t neighbour_sid;
|
||||
if (str_to_sid_t(&neighbour_sid, remainder) == -1)
|
||||
return 404;
|
||||
struct subscriber *neighbour = find_subscriber(neighbour_sid.binary, sizeof(neighbour_sid.binary), 0);
|
||||
if (!neighbour)
|
||||
return 404;
|
||||
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
|
||||
link_neighbour_status_html(b, neighbour);
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b))
|
||||
return -1;
|
||||
http_request_response_static(&r->http, 200, CONTENT_TYPE_HTML, buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int interface_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char buf[8*1024];
|
||||
strbuf b=strbuf_local(buf, sizeof buf);
|
||||
int index=atoi(remainder);
|
||||
if (index<0 || index>=OVERLAY_MAX_INTERFACES)
|
||||
return 404;
|
||||
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
|
||||
interface_state_html(b, &overlay_interfaces[index]);
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b))
|
||||
return -1;
|
||||
http_request_response_static(&r->http, 200, CONTENT_TYPE_HTML, buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void finalise_union_close_file(httpd_request *r)
|
||||
{
|
||||
if (r->u.file.fd==-1)
|
||||
return;
|
||||
close(r->u.file.fd);
|
||||
r->u.file.fd=-1;
|
||||
}
|
||||
|
||||
static int static_file_generator(struct http_request *hr, unsigned char *buf, size_t bufsz, struct http_content_generator_result *result)
|
||||
{
|
||||
struct httpd_request *r=(struct httpd_request *)hr;
|
||||
uint64_t remain = r->http.response.header.content_length + r->http.response.header.content_range_start - r->u.file.offset;
|
||||
if (bufsz < remain)
|
||||
remain = bufsz;
|
||||
ssize_t bytes = read(r->u.file.fd, buf, remain);
|
||||
if (bytes == -1)
|
||||
return -1;
|
||||
r->u.file.offset+=bytes;
|
||||
result->generated = bytes;
|
||||
return (r->u.file.offset >= r->http.response.header.content_length + r->http.response.header.content_range_start)?0:1;
|
||||
}
|
||||
|
||||
static int static_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (!*remainder)
|
||||
remainder="index.html";
|
||||
if (FORMF_SERVAL_ETC_PATH(path, "static/%s", remainder)==0)
|
||||
return 500;
|
||||
struct stat stat;
|
||||
if (lstat(path, &stat))
|
||||
return 404;
|
||||
|
||||
r->u.file.fd = open(path, O_RDONLY);
|
||||
if (r->u.file.fd==-1)
|
||||
return 404;
|
||||
|
||||
r->finalise_union=finalise_union_close_file;
|
||||
|
||||
// TODO find extension and set content type properly
|
||||
http_response_init_content_range(r, stat.st_size);
|
||||
if (r->http.response.header.content_range_start){
|
||||
if (lseek64(r->u.file.fd, r->http.response.header.content_range_start, SEEK_SET)){
|
||||
WARNF_perror("lseek(%s)", path);
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
r->u.file.offset=r->http.response.header.content_range_start;
|
||||
http_request_response_generated(&r->http, 200, CONTENT_TYPE_HTML, static_file_generator);
|
||||
return 1;
|
||||
}
|
||||
|
14
httpd.h
14
httpd.h
@ -219,6 +219,20 @@ int httpd_server_start(uint16_t port_low, uint16_t port_high);
|
||||
|
||||
typedef int HTTP_HANDLER(httpd_request *r, const char *remainder);
|
||||
|
||||
struct http_handler {
|
||||
const char *path;
|
||||
HTTP_HANDLER *parser;
|
||||
};
|
||||
|
||||
DECLARE_SECTION(struct http_handler, httpd);
|
||||
|
||||
#define DECLARE_HANDLER(PATH, FUNC) \
|
||||
static HTTP_HANDLER FUNC;\
|
||||
static struct http_handler __##FUNC IN_SECTION(httpd) = {\
|
||||
.path=PATH,\
|
||||
.parser=FUNC\
|
||||
}
|
||||
|
||||
int is_http_header_complete(const char *buf, size_t len, size_t read_since_last_call);
|
||||
int authorize_restful(struct http_request *r);
|
||||
int http_response_content_type(httpd_request *r, const char *what, const struct mime_content_type *ct);
|
||||
|
@ -27,9 +27,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define keyring_TOKEN_STRLEN (BASE64_ENCODED_LEN(sizeof(rhizome_bid_t) + sizeof(uint64_t)))
|
||||
#define alloca_keyring_token(bid, offset) keyring_ token_to_str(alloca(keyring_TOKEN_STRLEN + 1), (bid), (offset))
|
||||
|
||||
DECLARE_HANDLER("/restful/keyring/", restful_keyring_);
|
||||
|
||||
static HTTP_HANDLER restful_keyring_identitylist_json;
|
||||
|
||||
int restful_keyring_(httpd_request *r, const char *remainder)
|
||||
static int restful_keyring_(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = CONTENT_TYPE_JSON;
|
||||
if (!is_rhizome_http_enabled())
|
||||
|
@ -22,6 +22,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "httpd.h"
|
||||
#include "strbuf_helpers.h"
|
||||
|
||||
DECLARE_HANDLER("/restful/meshms/", restful_meshms_);
|
||||
|
||||
static void on_rhizome_bundle_added(httpd_request *r, rhizome_manifest *m);
|
||||
|
||||
static void finalise_union_meshms_conversationlist(httpd_request *r)
|
||||
@ -114,7 +116,7 @@ static HTTP_HANDLER restful_meshms_read_all_conversations;
|
||||
static HTTP_HANDLER restful_meshms_read_all_messages;
|
||||
static HTTP_HANDLER restful_meshms_read_to_offset;
|
||||
|
||||
int restful_meshms_(httpd_request *r, const char *remainder)
|
||||
static int restful_meshms_(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = CONTENT_TYPE_JSON;
|
||||
if (!is_rhizome_http_enabled())
|
||||
|
@ -31,6 +31,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "strbuf_helpers.h"
|
||||
#include "socket.h"
|
||||
|
||||
DECLARE_HANDLER("/rhizome/import", rhizome_direct_import);
|
||||
DECLARE_HANDLER("/rhizome/enquiry", rhizome_direct_enquiry);
|
||||
DECLARE_HANDLER("/rhizome/", rhizome_direct_dispatch);
|
||||
|
||||
static int _form_temporary_file_path(struct __sourceloc __whence, httpd_request *r, char *pathbuf, size_t bufsiz, const char *field)
|
||||
{
|
||||
@ -357,7 +360,7 @@ static int rhizome_direct_process_mime_body(struct http_request *hr, char *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rhizome_direct_import(httpd_request *r, const char *remainder)
|
||||
static int rhizome_direct_import(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -374,7 +377,7 @@ int rhizome_direct_import(httpd_request *r, const char *remainder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rhizome_direct_enquiry(httpd_request *r, const char *remainder)
|
||||
static int rhizome_direct_enquiry(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -423,7 +426,7 @@ int rhizome_direct_addfile(httpd_request *r, const char *remainder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rhizome_direct_dispatch(httpd_request *r, const char *UNUSED(remainder))
|
||||
static int rhizome_direct_dispatch(httpd_request *r, const char *UNUSED(remainder))
|
||||
{
|
||||
if ( config.rhizome.api.addfile.uri_path[0]
|
||||
&& strcmp(r->http.path, config.rhizome.api.addfile.uri_path) == 0
|
||||
|
@ -23,7 +23,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "str.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
int rhizome_file_page(httpd_request *r, const char *remainder)
|
||||
DECLARE_HANDLER("/rhizome/status", rhizome_status_page);
|
||||
DECLARE_HANDLER("/rhizome/file/", rhizome_file_page);
|
||||
DECLARE_HANDLER("/rhizome/manifestbyprefix/", manifest_by_prefix_page);
|
||||
|
||||
static int rhizome_file_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
/* Stream the specified payload */
|
||||
if (!is_rhizome_http_enabled())
|
||||
@ -46,7 +50,7 @@ int rhizome_file_page(httpd_request *r, const char *remainder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manifest_by_prefix_page(httpd_request *r, const char *remainder)
|
||||
static int manifest_by_prefix_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (!is_rhizome_http_enabled())
|
||||
return 403;
|
||||
@ -70,7 +74,7 @@ int manifest_by_prefix_page(httpd_request *r, const char *remainder)
|
||||
}
|
||||
}
|
||||
|
||||
int rhizome_status_page(httpd_request *r, const char *remainder)
|
||||
static int rhizome_status_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (!is_rhizome_http_enabled())
|
||||
return 403;
|
||||
|
@ -22,6 +22,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "httpd.h"
|
||||
#include "strbuf_helpers.h"
|
||||
|
||||
DECLARE_HANDLER("/restful/rhizome/bundlelist.json", restful_rhizome_bundlelist_json);
|
||||
DECLARE_HANDLER("/restful/rhizome/newsince/", restful_rhizome_newsince);
|
||||
DECLARE_HANDLER("/restful/rhizome/insert", restful_rhizome_insert);
|
||||
DECLARE_HANDLER("/restful/rhizome/append", restful_rhizome_append);
|
||||
DECLARE_HANDLER("/restful/rhizome/", restful_rhizome_);
|
||||
|
||||
static HTTP_RENDERER render_manifest_headers;
|
||||
static void on_rhizome_bundle_added(httpd_request *r, rhizome_manifest *m);
|
||||
|
||||
@ -148,7 +154,7 @@ static int http_request_rhizome_response(struct httpd_request *r, uint16_t resul
|
||||
|
||||
static HTTP_CONTENT_GENERATOR restful_rhizome_bundlelist_json_content;
|
||||
|
||||
int restful_rhizome_bundlelist_json(httpd_request *r, const char *remainder)
|
||||
static int restful_rhizome_bundlelist_json(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = CONTENT_TYPE_JSON;
|
||||
r->http.render_extra_headers = render_manifest_headers;
|
||||
@ -181,7 +187,7 @@ static int restful_rhizome_bundlelist_json_content(struct http_request *hr, unsi
|
||||
return ret;
|
||||
}
|
||||
|
||||
int restful_rhizome_newsince(httpd_request *r, const char *remainder)
|
||||
static int restful_rhizome_newsince(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = CONTENT_TYPE_JSON;
|
||||
if (!is_rhizome_http_enabled())
|
||||
@ -327,7 +333,7 @@ static int insert_mime_part_end(struct http_request *);
|
||||
static int insert_mime_part_header(struct http_request *, const struct mime_part_headers *);
|
||||
static int insert_mime_part_body(struct http_request *, char *, size_t);
|
||||
|
||||
int restful_rhizome_insert(httpd_request *r, const char *remainder)
|
||||
static int restful_rhizome_insert(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = CONTENT_TYPE_JSON;
|
||||
r->http.render_extra_headers = render_manifest_headers;
|
||||
@ -359,7 +365,7 @@ int restful_rhizome_insert(httpd_request *r, const char *remainder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int restful_rhizome_append(httpd_request *r, const char *remainder)
|
||||
static int restful_rhizome_append(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->u.insert.appending = 1;
|
||||
return restful_rhizome_insert(r, remainder);
|
||||
@ -750,7 +756,7 @@ static HTTP_HANDLER restful_rhizome_bid_rhm;
|
||||
static HTTP_HANDLER restful_rhizome_bid_raw_bin;
|
||||
static HTTP_HANDLER restful_rhizome_bid_decrypted_bin;
|
||||
|
||||
int restful_rhizome_(httpd_request *r, const char *remainder)
|
||||
static int restful_rhizome_(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = CONTENT_TYPE_JSON;
|
||||
r->http.render_extra_headers = render_manifest_headers;
|
||||
|
154
server_httpd.c
Normal file
154
server_httpd.c
Normal file
@ -0,0 +1,154 @@
|
||||
|
||||
#include "serval.h"
|
||||
#include "httpd.h"
|
||||
#include "conf.h"
|
||||
#include "overlay_address.h"
|
||||
#include "overlay_interface.h"
|
||||
#include "os.h"
|
||||
|
||||
DECLARE_HANDLER("/static/", static_page);
|
||||
DECLARE_HANDLER("/interface/", interface_page);
|
||||
DECLARE_HANDLER("/neighbour/", neighbour_page);
|
||||
DECLARE_HANDLER("/favicon.ico", fav_icon_header);
|
||||
DECLARE_HANDLER("/", root_page);
|
||||
|
||||
|
||||
static int root_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char temp[8192];
|
||||
strbuf b = strbuf_local(temp, sizeof temp);
|
||||
strbuf_sprintf(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>"
|
||||
"<h1>Hello, I'm %s*</h1>",
|
||||
alloca_tohex_sid_t_trunc(my_subscriber->sid, 16));
|
||||
if (config.server.motd[0]) {
|
||||
strbuf_puts(b, "<p>");
|
||||
strbuf_html_escape(b, config.server.motd, strlen(config.server.motd));
|
||||
strbuf_puts(b, "</p>");
|
||||
}
|
||||
strbuf_puts(b, "Interfaces;<br />");
|
||||
int i;
|
||||
for (i=0;i<OVERLAY_MAX_INTERFACES;i++){
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
|
||||
strbuf_sprintf(b, "<a href=\"/interface/%d\">%d: %s, TX: %d, RX: %d</a><br />",
|
||||
i, i, overlay_interfaces[i].name, overlay_interfaces[i].tx_count, overlay_interfaces[i].recv_count);
|
||||
}
|
||||
strbuf_puts(b, "Neighbours;<br />");
|
||||
link_neighbour_short_status_html(b, "/neighbour");
|
||||
if (is_rhizome_http_enabled()){
|
||||
strbuf_puts(b, "<a href=\"/rhizome/status\">Rhizome Status</a><br />");
|
||||
}
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b)) {
|
||||
WHY("HTTP Root page buffer overrun");
|
||||
return 500;
|
||||
}
|
||||
http_request_response_static(&r->http, 200, CONTENT_TYPE_HTML, temp, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fav_icon_header(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
http_request_response_static(&r->http, 200, "image/vnd.microsoft.icon", (const char *)favicon_bytes, favicon_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int neighbour_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char buf[8*1024];
|
||||
strbuf b = strbuf_local(buf, sizeof buf);
|
||||
sid_t neighbour_sid;
|
||||
if (str_to_sid_t(&neighbour_sid, remainder) == -1)
|
||||
return 404;
|
||||
struct subscriber *neighbour = find_subscriber(neighbour_sid.binary, sizeof(neighbour_sid.binary), 0);
|
||||
if (!neighbour)
|
||||
return 404;
|
||||
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
|
||||
link_neighbour_status_html(b, neighbour);
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b))
|
||||
return -1;
|
||||
http_request_response_static(&r->http, 200, CONTENT_TYPE_HTML, buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int interface_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char buf[8*1024];
|
||||
strbuf b=strbuf_local(buf, sizeof buf);
|
||||
int index=atoi(remainder);
|
||||
if (index<0 || index>=OVERLAY_MAX_INTERFACES)
|
||||
return 404;
|
||||
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
|
||||
interface_state_html(b, &overlay_interfaces[index]);
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b))
|
||||
return -1;
|
||||
http_request_response_static(&r->http, 200, CONTENT_TYPE_HTML, buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int static_file_generator(struct http_request *hr, unsigned char *buf, size_t bufsz, struct http_content_generator_result *result)
|
||||
{
|
||||
struct httpd_request *r=(struct httpd_request *)hr;
|
||||
uint64_t remain = r->http.response.header.content_length + r->http.response.header.content_range_start - r->u.file.offset;
|
||||
if (bufsz < remain)
|
||||
remain = bufsz;
|
||||
ssize_t bytes = read(r->u.file.fd, buf, remain);
|
||||
if (bytes == -1)
|
||||
return -1;
|
||||
r->u.file.offset+=bytes;
|
||||
result->generated = bytes;
|
||||
return (r->u.file.offset >= r->http.response.header.content_length + r->http.response.header.content_range_start)?0:1;
|
||||
}
|
||||
|
||||
static void finalise_union_close_file(httpd_request *r)
|
||||
{
|
||||
if (r->u.file.fd==-1)
|
||||
return;
|
||||
close(r->u.file.fd);
|
||||
r->u.file.fd=-1;
|
||||
}
|
||||
|
||||
static int static_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (!*remainder)
|
||||
remainder="index.html";
|
||||
if (FORMF_SERVAL_ETC_PATH(path, "static/%s", remainder)==0)
|
||||
return 500;
|
||||
struct stat stat;
|
||||
if (lstat(path, &stat))
|
||||
return 404;
|
||||
|
||||
r->u.file.fd = open(path, O_RDONLY);
|
||||
if (r->u.file.fd==-1)
|
||||
return 404;
|
||||
|
||||
r->finalise_union=finalise_union_close_file;
|
||||
|
||||
// TODO find extension and set content type properly
|
||||
http_response_init_content_range(r, stat.st_size);
|
||||
if (r->http.response.header.content_range_start){
|
||||
if (lseek64(r->u.file.fd, r->http.response.header.content_range_start, SEEK_SET)){
|
||||
WARNF_perror("lseek(%s)", path);
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
r->u.file.offset=r->http.response.header.content_range_start;
|
||||
http_request_response_generated(&r->http, 200, CONTENT_TYPE_HTML, static_file_generator);
|
||||
return 1;
|
||||
}
|
@ -97,6 +97,7 @@ SERVAL_DAEMON_SOURCES = \
|
||||
rhizome_sync.c \
|
||||
serval_packetvisualise.c \
|
||||
server.c \
|
||||
server_httpd.c \
|
||||
vomp.c \
|
||||
vomp_console.c \
|
||||
fec-3.0.1/ccsds_tables.c \
|
||||
|
Loading…
Reference in New Issue
Block a user