mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-04-26 13:59:52 +00:00
Refactor to rename "Rhizome HTTP server" to "HTTPD server"
Move HTTPD start/stop/dispatch logic from rhizome_httpd.c into new httpd.c Rename config.debug.httpd -> config.debug.http_server Rename config.debug.rhizome_httpd -> config.debug.httpd Rename config.debug.rhizome_nohttptx -> config.debug.nohttptx
This commit is contained in:
parent
f4249707a4
commit
015ed0b181
1
conf.h
1
conf.h
@ -232,6 +232,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "strbuf.h"
|
||||
#include "serval.h"
|
||||
#include "rhizome.h"
|
||||
#include "rhizome_http.h"
|
||||
|
||||
#define CONFIG_FILE_MAX_SIZE (32 * 1024)
|
||||
#define INTERFACE_NAME_STRLEN 40
|
||||
|
@ -153,7 +153,7 @@ int cf_opt_rhizome_peer_from_uri(struct config_rhizome_peer *rpeer, const char *
|
||||
}
|
||||
const char *host;
|
||||
size_t hostlen;
|
||||
uint16_t port = RHIZOME_HTTP_PORT;
|
||||
uint16_t port = HTTPD_PORT;
|
||||
if (!str_uri_authority_hostname(auth, &host, &hostlen))
|
||||
return CFINVALID;
|
||||
str_uri_authority_port(auth, &port);
|
||||
|
@ -233,7 +233,9 @@ ATOM(bool_t, dnaresponses, 0, boolean,, "")
|
||||
ATOM(bool_t, dnahelper, 0, boolean,, "")
|
||||
ATOM(bool_t, queues, 0, boolean,, "")
|
||||
ATOM(bool_t, timing, 0, boolean,, "")
|
||||
ATOM(bool_t, http_server, 0, boolean,, "")
|
||||
ATOM(bool_t, httpd, 0, boolean,, "")
|
||||
ATOM(bool_t, nohttptx, 0, boolean,, "")
|
||||
ATOM(bool_t, io, 0, boolean,, "")
|
||||
ATOM(bool_t, verbose_io, 0, boolean,, "")
|
||||
ATOM(bool_t, interactive_io, 0, boolean,, "")
|
||||
@ -263,11 +265,9 @@ ATOM(bool_t, packetconstruction, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_manifest, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_sql_bind, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_httpd, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_tx, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_rx, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_ads, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_nohttptx, 0, boolean,, "")
|
||||
ATOM(bool_t, rhizome_mdp_rx, 0, boolean,, "")
|
||||
ATOM(bool_t, subscriber, 0, boolean,, "")
|
||||
ATOM(bool_t, throttling, 0, boolean,, "")
|
||||
@ -367,7 +367,7 @@ END_STRUCT
|
||||
STRUCT(rhizome_peer)
|
||||
STRING(25, protocol, "http", protocol,, "Protocol name")
|
||||
STRING(256, host, "", str_nonempty, MANDATORY, "Host name or IP address")
|
||||
ATOM(uint16_t, port, RHIZOME_HTTP_PORT, uint16_nonzero,, "Port number")
|
||||
ATOM(uint16_t, port, HTTPD_PORT, uint16_nonzero,, "Port number")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(peerlist,)
|
||||
|
@ -69,12 +69,12 @@ static struct profile_total http_server_stats = {
|
||||
};
|
||||
|
||||
#define DEBUG_DUMP_PARSED(r) do { \
|
||||
if (config.debug.httpd) \
|
||||
if (config.debug.http_server) \
|
||||
DEBUGF("%s %s HTTP/%u.%u", r->verb ? r->verb : "NULL", alloca_str_toprint(r->path), r->version_major, r->version_minor);\
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_DUMP_PARSER(r) do { \
|
||||
if (config.debug.httpd) \
|
||||
if (config.debug.http_server) \
|
||||
DEBUGF("parsed %d %s cursor %d %s end %d remain %"PRIhttp_size_t, \
|
||||
(int)(r->parsed - r->received), alloca_toprint(-1, r->parsed, r->cursor - r->parsed), \
|
||||
(int)(r->cursor - r->received), alloca_toprint(50, r->cursor, r->end - r->cursor), \
|
||||
@ -1208,14 +1208,14 @@ static int http_request_parse_body_form_data(struct http_request *r)
|
||||
int at_start = 0;
|
||||
switch (r->form_data_state) {
|
||||
case START:
|
||||
if (config.debug.httpd)
|
||||
if (config.debug.http_server)
|
||||
DEBUGF("START");
|
||||
// The logic here allows for a missing initial CRLF before the first boundary line.
|
||||
at_start = 1;
|
||||
r->form_data_state = PREAMBLE;
|
||||
// fall through
|
||||
case PREAMBLE: {
|
||||
if (config.debug.httpd)
|
||||
if (config.debug.http_server)
|
||||
DEBUGF("PREAMBLE");
|
||||
char *start = r->parsed;
|
||||
for (; at_start || _skip_to_crlf(r); at_start = 0) {
|
||||
@ -1241,7 +1241,7 @@ static int http_request_parse_body_form_data(struct http_request *r)
|
||||
}
|
||||
return 100; // need more data
|
||||
case HEADER: {
|
||||
if (config.debug.httpd)
|
||||
if (config.debug.http_server)
|
||||
DEBUGF("HEADER");
|
||||
// If not at a CRLF, then we are skipping through an over-long header that didn't
|
||||
// fit into the buffer. Just discard bytes up to the next CRLF.
|
||||
@ -1365,7 +1365,7 @@ static int http_request_parse_body_form_data(struct http_request *r)
|
||||
}
|
||||
return 400;
|
||||
case BODY:
|
||||
if (config.debug.httpd)
|
||||
if (config.debug.http_server)
|
||||
DEBUGF("BODY");
|
||||
char *start = r->parsed;
|
||||
while (_skip_to_crlf(r)) {
|
||||
@ -1396,7 +1396,7 @@ static int http_request_parse_body_form_data(struct http_request *r)
|
||||
_INVOKE_HANDLER_BUF_LEN(handle_mime_body, start, r->parsed);
|
||||
return 100; // need more data
|
||||
case EPILOGUE:
|
||||
if (config.debug.httpd)
|
||||
if (config.debug.http_server)
|
||||
DEBUGF("EPILOGUE");
|
||||
r->cursor = r->end;
|
||||
assert(r->cursor >= r->parsed);
|
||||
|
395
httpd.c
Normal file
395
httpd.c
Normal file
@ -0,0 +1,395 @@
|
||||
/*
|
||||
Serval DNA HTTP external interface
|
||||
Copyright (C) 2014 Serval Project Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "serval.h"
|
||||
#include "conf.h"
|
||||
#include "rhizome_http.h"
|
||||
#include "overlay_address.h"
|
||||
#include "overlay_interface.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;
|
||||
|
||||
HTTP_HANDLER restful_rhizome_bundlelist_json;
|
||||
HTTP_HANDLER restful_rhizome_newsince;
|
||||
HTTP_HANDLER restful_rhizome_insert;
|
||||
HTTP_HANDLER restful_rhizome_;
|
||||
HTTP_HANDLER restful_meshms_;
|
||||
|
||||
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/", restful_rhizome_},
|
||||
{"/restful/meshms/", restful_meshms_},
|
||||
{"/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},
|
||||
{"/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);
|
||||
}
|
||||
}
|
||||
return 404;
|
||||
}
|
||||
|
||||
void httpd_server_poll(struct sched_ent *);
|
||||
struct sched_ent server_alarm;
|
||||
struct profile_total server_stats = {
|
||||
.name = "httpd_server_poll",
|
||||
};
|
||||
|
||||
uint16_t httpd_server_port = 0;
|
||||
unsigned int httpd_request_count = 0;
|
||||
|
||||
static int httpd_server_socket = -1;
|
||||
static time_ms_t httpd_server_last_start_attempt = -1;
|
||||
|
||||
// Format icon data using:
|
||||
// od -vt u1 ~/Downloads/favicon.ico | cut -c9- | sed 's/ */,/g'
|
||||
unsigned char favicon_bytes[]={
|
||||
0,0,1,0,1,0,16,16,16,0,0,0,0,0,40,1
|
||||
,0,0,22,0,0,0,40,0,0,0,16,0,0,0,32,0
|
||||
,0,0,1,0,4,0,0,0,0,0,128,0,0,0,0,0
|
||||
,0,0,0,0,0,0,16,0,0,0,0,0,0,0,104,158
|
||||
,168,0,163,233,247,0,104,161,118,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,17
|
||||
,17,17,17,18,34,17,17,18,34,17,17,18,34,17,17,2
|
||||
,34,17,17,18,34,17,16,18,34,1,17,17,1,17,1,17
|
||||
,1,16,1,16,17,17,17,17,1,17,16,16,17,17,17,17
|
||||
,1,17,18,34,17,17,17,16,17,17,2,34,17,17,17,16
|
||||
,17,16,18,34,17,17,17,16,17,1,17,1,17,17,17,18
|
||||
,34,17,17,16,17,17,17,18,34,17,17,18,34,17,17,18
|
||||
,34,17,17,18,34,17,17,16,17,17,17,18,34,17,17,16
|
||||
,17,17,17,17,17,0,17,1,17,17,17,17,17,17,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int favicon_len=318;
|
||||
|
||||
int is_httpd_server_running()
|
||||
{
|
||||
return httpd_server_socket != -1;
|
||||
}
|
||||
|
||||
/* Start the Rhizome HTTP server by creating a socket, binding it to an available port, and
|
||||
marking it as passive. If called repeatedly and frequently, this function will only try to start
|
||||
the server after a certain time has elapsed since the last attempt.
|
||||
Return -1 if an error occurs (message logged).
|
||||
Return 0 if the server was started.
|
||||
Return 1 if the server is already started successfully.
|
||||
Return 2 if the server was not started because it is too soon since last failed attempt.
|
||||
*/
|
||||
int httpd_server_start(uint16_t port_low, uint16_t port_high)
|
||||
{
|
||||
if (httpd_server_socket != -1)
|
||||
return 1;
|
||||
|
||||
/* Only try to start http server every five seconds. */
|
||||
time_ms_t now = gettime_ms();
|
||||
if (now < httpd_server_last_start_attempt + 5000)
|
||||
return 2;
|
||||
httpd_server_last_start_attempt = now;
|
||||
if (config.debug.httpd)
|
||||
DEBUGF("Starting HTTP server");
|
||||
|
||||
uint16_t port;
|
||||
for (port = port_low; port <= port_high; ++port) {
|
||||
/* Create a new socket, reusable and non-blocking. */
|
||||
if (httpd_server_socket == -1) {
|
||||
httpd_server_socket = socket(AF_INET,SOCK_STREAM,0);
|
||||
if (httpd_server_socket == -1) {
|
||||
WHY_perror("socket");
|
||||
goto error;
|
||||
}
|
||||
int on=1;
|
||||
if (setsockopt(httpd_server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == -1) {
|
||||
WHY_perror("setsockopt(REUSEADDR)");
|
||||
goto error;
|
||||
}
|
||||
if (ioctl(httpd_server_socket, FIONBIO, (char *)&on) == -1) {
|
||||
WHY_perror("ioctl(FIONBIO)");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
/* Bind it to the next port we want to try. */
|
||||
struct sockaddr_in address;
|
||||
bzero((char *) &address, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons(port);
|
||||
if (bind(httpd_server_socket, (struct sockaddr *) &address, sizeof(address)) == -1) {
|
||||
if (errno != EADDRINUSE) {
|
||||
WHY_perror("bind");
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
/* We bound to a port. The battle is half won. Now we have to successfully listen on that
|
||||
port, which could also fail with EADDRINUSE, in which case we have to scrap the socket and
|
||||
create a new one, because once bound, a socket stays bound.
|
||||
*/
|
||||
if (listen(httpd_server_socket, 20) != -1)
|
||||
goto success;
|
||||
if (errno != EADDRINUSE) {
|
||||
WHY_perror("listen");
|
||||
goto error;
|
||||
}
|
||||
close(httpd_server_socket);
|
||||
httpd_server_socket = -1;
|
||||
}
|
||||
}
|
||||
WHYF("No ports available in range %u to %u", HTTPD_PORT, HTTPD_PORT_MAX);
|
||||
error:
|
||||
if (httpd_server_socket != -1) {
|
||||
close(httpd_server_socket);
|
||||
httpd_server_socket = -1;
|
||||
}
|
||||
return WHY("Failed to start HTTP server");
|
||||
|
||||
success:
|
||||
INFOF("HTTP SERVER START port=%"PRIu16" fd=%d services=RESTful%s%s",
|
||||
port,
|
||||
httpd_server_socket,
|
||||
config.rhizome.http.enable ? ",Rhizome" : "",
|
||||
config.rhizome.api.addfile.uri_path[0] ? ",RhizomeDirect" : ""
|
||||
);
|
||||
httpd_server_port = port;
|
||||
/* Add Rhizome HTTPd server to list of file descriptors to watch */
|
||||
server_alarm.function = httpd_server_poll;
|
||||
server_alarm.stats = &server_stats;
|
||||
server_alarm.poll.fd = httpd_server_socket;
|
||||
server_alarm.poll.events = POLLIN;
|
||||
watch(&server_alarm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void httpd_server_finalise_http_request(struct http_request *hr)
|
||||
{
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (r->manifest) {
|
||||
rhizome_manifest_free(r->manifest);
|
||||
r->manifest = NULL;
|
||||
}
|
||||
if (r->finalise_union) {
|
||||
r->finalise_union(r);
|
||||
r->finalise_union = NULL;
|
||||
}
|
||||
if (httpd_request_count)
|
||||
--httpd_request_count;
|
||||
}
|
||||
|
||||
static int httpd_dispatch(struct http_request *);
|
||||
|
||||
static unsigned int http_request_uuid_counter = 0;
|
||||
|
||||
void httpd_server_poll(struct sched_ent *alarm)
|
||||
{
|
||||
if (alarm->poll.revents & (POLLIN | POLLOUT)) {
|
||||
struct sockaddr addr;
|
||||
unsigned int addr_len = sizeof addr;
|
||||
int sock;
|
||||
if ((sock = accept(httpd_server_socket, &addr, &addr_len)) == -1) {
|
||||
if (errno && errno != EAGAIN)
|
||||
WARN_perror("accept");
|
||||
} else {
|
||||
struct sockaddr_in *peerip=NULL;
|
||||
if (addr.sa_family == AF_INET) {
|
||||
peerip = (struct sockaddr_in *)&addr; // network order
|
||||
INFOF("RHIZOME HTTP SERVER, ACCEPT addrlen=%u family=%u port=%u addr=%u.%u.%u.%u",
|
||||
addr_len, peerip->sin_family, peerip->sin_port,
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[0],
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[1],
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[2],
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[3]
|
||||
);
|
||||
} else {
|
||||
INFOF("RHIZOME HTTP SERVER, ACCEPT addrlen=%u family=%u data=%s",
|
||||
addr_len, addr.sa_family, alloca_tohex((unsigned char *)addr.sa_data, sizeof addr.sa_data)
|
||||
);
|
||||
}
|
||||
httpd_request *request = emalloc_zero(sizeof(httpd_request));
|
||||
if (request == NULL) {
|
||||
WHY("Cannot respond to HTTP request, out of memory");
|
||||
close(sock);
|
||||
} else {
|
||||
++httpd_request_count;
|
||||
request->uuid = http_request_uuid_counter++;
|
||||
if (peerip)
|
||||
request->http.client_sockaddr_in = *peerip;
|
||||
request->http.handle_headers = httpd_dispatch;
|
||||
request->http.debug_flag = &config.debug.httpd;
|
||||
request->http.disable_tx_flag = &config.debug.nohttptx;
|
||||
request->http.finalise = httpd_server_finalise_http_request;
|
||||
request->http.free = free;
|
||||
request->http.idle_timeout = RHIZOME_IDLE_TIMEOUT;
|
||||
http_request_init(&request->http, sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alarm->poll.revents & (POLLHUP | POLLERR)) {
|
||||
INFO("Error on tcp listen socket");
|
||||
}
|
||||
}
|
||||
|
||||
int is_http_header_complete(const char *buf, size_t len, size_t read_since_last_call)
|
||||
{
|
||||
IN();
|
||||
const char *bufend = buf + len;
|
||||
const char *p = buf;
|
||||
size_t tail = read_since_last_call + 4;
|
||||
if (tail < len)
|
||||
p = bufend - tail;
|
||||
int count = 0;
|
||||
for (; p != bufend; ++p) {
|
||||
switch (*p) {
|
||||
case '\n':
|
||||
if (++count==2)
|
||||
RETURN(p - buf);
|
||||
case '\r': // ignore CR
|
||||
case '\0': // ignore NUL (telnet inserts them)
|
||||
break;
|
||||
default:
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RETURN(0);
|
||||
OUT();
|
||||
}
|
||||
|
||||
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><br>"
|
||||
"Interfaces;<br>",
|
||||
alloca_tohex_sid_t_trunc(my_subscriber->sid, 16));
|
||||
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, "text/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, "text/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, "text/html", buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
@ -137,7 +137,7 @@ schedule(&_sched_##X); }
|
||||
}
|
||||
|
||||
// start the HTTP server if enabled
|
||||
rhizome_http_server_start(RHIZOME_HTTP_PORT, RHIZOME_HTTP_PORT_MAX);
|
||||
httpd_server_start(HTTPD_PORT, HTTPD_PORT_MAX);
|
||||
|
||||
// start the dna helper if configured
|
||||
dna_helper_start();
|
||||
|
@ -85,7 +85,7 @@ int is_rhizome_advertise_enabled()
|
||||
return config.rhizome.enable
|
||||
&& config.rhizome.advertise.enable
|
||||
&& rhizome_db
|
||||
&& (is_rhizome_http_server_running() || is_rhizome_mdp_server_running());
|
||||
&& (is_httpd_server_running() || is_rhizome_mdp_server_running());
|
||||
}
|
||||
|
||||
int rhizome_fetch_delay_ms()
|
||||
|
@ -55,9 +55,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
// assumed to always be 2^n
|
||||
#define RHIZOME_CRYPT_PAGE_SIZE 4096
|
||||
|
||||
#define RHIZOME_HTTP_PORT 4110
|
||||
#define RHIZOME_HTTP_PORT_MAX 4150
|
||||
|
||||
/* Fundamental data type: Rhizome Bundle ID
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
@ -392,7 +389,6 @@ void _rhizome_manifest_del_author(struct __sourceloc, rhizome_manifest *);
|
||||
#define RHIZOME_SERVICE_MESHMS2 "MeshMS2"
|
||||
|
||||
extern int64_t rhizome_space;
|
||||
extern uint16_t rhizome_http_server_port;
|
||||
|
||||
int log2ll(uint64_t x);
|
||||
int rhizome_configure();
|
||||
|
@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "socket.h"
|
||||
|
||||
|
||||
static int _form_temporary_file_path(struct __sourceloc __whence, rhizome_http_request *r, char *pathbuf, size_t bufsiz, const char *field)
|
||||
static int _form_temporary_file_path(struct __sourceloc __whence, httpd_request *r, char *pathbuf, size_t bufsiz, const char *field)
|
||||
{
|
||||
strbuf b = strbuf_local(pathbuf, bufsiz);
|
||||
// TODO: use a temporary directory
|
||||
@ -46,7 +46,7 @@ static int _form_temporary_file_path(struct __sourceloc __whence, rhizome_http_r
|
||||
|
||||
#define form_temporary_file_path(r,buf,field) _form_temporary_file_path(__WHENCE__, (r), (buf), sizeof(buf), (field))
|
||||
|
||||
static void rhizome_direct_clear_temporary_files(rhizome_http_request *r)
|
||||
static void rhizome_direct_clear_temporary_files(httpd_request *r)
|
||||
{
|
||||
const char *fields[] = { "manifest", "data" };
|
||||
int i;
|
||||
@ -60,7 +60,7 @@ static void rhizome_direct_clear_temporary_files(rhizome_http_request *r)
|
||||
|
||||
static int rhizome_direct_import_end(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (!r->u.direct_import.received_manifest) {
|
||||
http_request_simple_response(&r->http, 400, "Missing 'manifest' part");
|
||||
return 0;
|
||||
@ -129,7 +129,7 @@ static int rhizome_direct_import_end(struct http_request *hr)
|
||||
|
||||
int rhizome_direct_enquiry_end(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (!r->u.direct_import.received_data) {
|
||||
http_request_simple_response(&r->http, 400, "Missing 'data' part");
|
||||
return 0;
|
||||
@ -189,7 +189,7 @@ int rhizome_direct_enquiry_end(struct http_request *hr)
|
||||
|
||||
static int rhizome_direct_addfile_end(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
// If given a file without a manifest, we should only accept if it we are configured to do so, and
|
||||
// the connection is from localhost. Otherwise people could cause your servald to create
|
||||
// arbitrary bundles, which would be bad.
|
||||
@ -294,7 +294,7 @@ static char PART_DATA[] = "data";
|
||||
|
||||
static int rhizome_direct_process_mime_start(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
assert(r->u.direct_import.current_part == NULL);
|
||||
assert(r->u.direct_import.part_fd == -1);
|
||||
return 0;
|
||||
@ -302,7 +302,7 @@ static int rhizome_direct_process_mime_start(struct http_request *hr)
|
||||
|
||||
static int rhizome_direct_process_mime_end(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (r->u.direct_import.part_fd != -1) {
|
||||
if (close(r->u.direct_import.part_fd) == -1) {
|
||||
WHYF_perror("close(%d)", r->u.direct_import.part_fd);
|
||||
@ -321,7 +321,7 @@ static int rhizome_direct_process_mime_end(struct http_request *hr)
|
||||
|
||||
static int rhizome_direct_process_mime_part_header(struct http_request *hr, const struct mime_part_headers *h)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (strcmp(h->content_disposition.name, PART_DATA) == 0) {
|
||||
r->u.direct_import.current_part = PART_DATA;
|
||||
strncpy(r->u.direct_import.data_file_name,
|
||||
@ -348,7 +348,7 @@ static int rhizome_direct_process_mime_part_header(struct http_request *hr, cons
|
||||
|
||||
static int rhizome_direct_process_mime_body(struct http_request *hr, char *buf, size_t len)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (r->u.direct_import.part_fd != -1) {
|
||||
if (write_all(r->u.direct_import.part_fd, buf, len) == -1) {
|
||||
http_request_simple_response(&r->http, 500, "Internal Error: Write temporary file failed");
|
||||
@ -358,7 +358,7 @@ static int rhizome_direct_process_mime_body(struct http_request *hr, char *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rhizome_direct_import(rhizome_http_request *r, const char *remainder)
|
||||
int rhizome_direct_import(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -375,7 +375,7 @@ int rhizome_direct_import(rhizome_http_request *r, const char *remainder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rhizome_direct_enquiry(rhizome_http_request *r, const char *remainder)
|
||||
int rhizome_direct_enquiry(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -397,7 +397,7 @@ int rhizome_direct_enquiry(rhizome_http_request *r, const char *remainder)
|
||||
* loop-holes here, which is part of why we leave it disabled by default, but it will be sufficient
|
||||
* for testing possible uses, including integration with OpenDataKit.
|
||||
*/
|
||||
int rhizome_direct_addfile(rhizome_http_request *r, const char *remainder)
|
||||
int rhizome_direct_addfile(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -424,7 +424,7 @@ int rhizome_direct_addfile(rhizome_http_request *r, const char *remainder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rhizome_direct_dispatch(rhizome_http_request *r, const char *UNUSED(remainder))
|
||||
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
|
||||
|
475
rhizome_http.c
475
rhizome_http.c
@ -37,217 +37,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "rhizome_http.h"
|
||||
#include "overlay_interface.h"
|
||||
|
||||
#define RHIZOME_SERVER_MAX_LIVE_REQUESTS 32
|
||||
|
||||
typedef int HTTP_HANDLER(rhizome_http_request *r, const char *remainder);
|
||||
|
||||
struct http_handler{
|
||||
const char *path;
|
||||
HTTP_HANDLER *parser;
|
||||
};
|
||||
|
||||
static HTTP_HANDLER restful_rhizome_bundlelist_json;
|
||||
static HTTP_HANDLER restful_rhizome_newsince;
|
||||
static HTTP_HANDLER restful_rhizome_insert;
|
||||
static HTTP_HANDLER restful_rhizome_;
|
||||
static HTTP_HANDLER restful_meshms_;
|
||||
|
||||
static HTTP_HANDLER rhizome_status_page;
|
||||
static HTTP_HANDLER rhizome_file_page;
|
||||
static HTTP_HANDLER manifest_by_prefix_page;
|
||||
static HTTP_HANDLER interface_page;
|
||||
static HTTP_HANDLER neighbour_page;
|
||||
static HTTP_HANDLER fav_icon_header;
|
||||
static HTTP_HANDLER root_page;
|
||||
|
||||
extern HTTP_HANDLER rhizome_direct_import;
|
||||
extern HTTP_HANDLER rhizome_direct_enquiry;
|
||||
extern HTTP_HANDLER rhizome_direct_dispatch;
|
||||
|
||||
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/", restful_rhizome_},
|
||||
{"/restful/meshms/", restful_meshms_},
|
||||
{"/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},
|
||||
{"/interface/", interface_page},
|
||||
{"/neighbour/", neighbour_page},
|
||||
{"/favicon.ico", fav_icon_header},
|
||||
{"/", root_page},
|
||||
};
|
||||
|
||||
static int rhizome_dispatch(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
INFOF("RHIZOME 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);
|
||||
}
|
||||
}
|
||||
return 404;
|
||||
}
|
||||
|
||||
static HTTP_RENDERER render_manifest_headers;
|
||||
|
||||
struct sched_ent server_alarm;
|
||||
struct profile_total server_stats = {
|
||||
.name = "rhizome_server_poll",
|
||||
};
|
||||
|
||||
/*
|
||||
HTTP server and client code for rhizome transfers and rhizome direct.
|
||||
Selection of either use is made when starting the HTTP server and
|
||||
specifying the call-back function to use on client connections.
|
||||
*/
|
||||
|
||||
uint16_t rhizome_http_server_port = 0;
|
||||
static int rhizome_server_socket = -1;
|
||||
static int request_count=0;
|
||||
static time_ms_t rhizome_server_last_start_attempt = -1;
|
||||
|
||||
// Format icon data using:
|
||||
// od -vt u1 ~/Downloads/favicon.ico | cut -c9- | sed 's/ */,/g'
|
||||
unsigned char favicon_bytes[]={
|
||||
0,0,1,0,1,0,16,16,16,0,0,0,0,0,40,1
|
||||
,0,0,22,0,0,0,40,0,0,0,16,0,0,0,32,0
|
||||
,0,0,1,0,4,0,0,0,0,0,128,0,0,0,0,0
|
||||
,0,0,0,0,0,0,16,0,0,0,0,0,0,0,104,158
|
||||
,168,0,163,233,247,0,104,161,118,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,17
|
||||
,17,17,17,18,34,17,17,18,34,17,17,18,34,17,17,2
|
||||
,34,17,17,18,34,17,16,18,34,1,17,17,1,17,1,17
|
||||
,1,16,1,16,17,17,17,17,1,17,16,16,17,17,17,17
|
||||
,1,17,18,34,17,17,17,16,17,17,2,34,17,17,17,16
|
||||
,17,16,18,34,17,17,17,16,17,1,17,1,17,17,17,18
|
||||
,34,17,17,16,17,17,17,18,34,17,17,18,34,17,17,18
|
||||
,34,17,17,18,34,17,17,16,17,17,17,18,34,17,17,16
|
||||
,17,17,17,17,17,0,17,1,17,17,17,17,17,17,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int favicon_len=318;
|
||||
|
||||
int is_rhizome_http_server_running()
|
||||
{
|
||||
return rhizome_server_socket != -1;
|
||||
}
|
||||
|
||||
/* Start the Rhizome HTTP server by creating a socket, binding it to an available port, and
|
||||
marking it as passive. If called repeatedly and frequently, this function will only try to start
|
||||
the server after a certain time has elapsed since the last attempt.
|
||||
Return -1 if an error occurs (message logged).
|
||||
Return 0 if the server was started.
|
||||
Return 1 if the server is already started successfully.
|
||||
Return 2 if the server was not started because it is too soon since last failed attempt.
|
||||
*/
|
||||
int rhizome_http_server_start(uint16_t port_low, uint16_t port_high)
|
||||
{
|
||||
if (rhizome_server_socket != -1)
|
||||
return 1;
|
||||
|
||||
/* Only try to start http server every five seconds. */
|
||||
time_ms_t now = gettime_ms();
|
||||
if (now < rhizome_server_last_start_attempt + 5000)
|
||||
return 2;
|
||||
rhizome_server_last_start_attempt = now;
|
||||
if (config.debug.rhizome_httpd)
|
||||
DEBUGF("Starting rhizome HTTP server");
|
||||
|
||||
uint16_t port;
|
||||
for (port = port_low; port <= port_high; ++port) {
|
||||
/* Create a new socket, reusable and non-blocking. */
|
||||
if (rhizome_server_socket == -1) {
|
||||
rhizome_server_socket = socket(AF_INET,SOCK_STREAM,0);
|
||||
if (rhizome_server_socket == -1) {
|
||||
WHY_perror("socket");
|
||||
goto error;
|
||||
}
|
||||
int on=1;
|
||||
if (setsockopt(rhizome_server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == -1) {
|
||||
WHY_perror("setsockopt(REUSEADDR)");
|
||||
goto error;
|
||||
}
|
||||
if (ioctl(rhizome_server_socket, FIONBIO, (char *)&on) == -1) {
|
||||
WHY_perror("ioctl(FIONBIO)");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
/* Bind it to the next port we want to try. */
|
||||
struct sockaddr_in address;
|
||||
bzero((char *) &address, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons(port);
|
||||
if (bind(rhizome_server_socket, (struct sockaddr *) &address, sizeof(address)) == -1) {
|
||||
if (errno != EADDRINUSE) {
|
||||
WHY_perror("bind");
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
/* We bound to a port. The battle is half won. Now we have to successfully listen on that
|
||||
port, which could also fail with EADDRINUSE, in which case we have to scrap the socket and
|
||||
create a new one, because once bound, a socket stays bound.
|
||||
*/
|
||||
if (listen(rhizome_server_socket, 20) != -1)
|
||||
goto success;
|
||||
if (errno != EADDRINUSE) {
|
||||
WHY_perror("listen");
|
||||
goto error;
|
||||
}
|
||||
close(rhizome_server_socket);
|
||||
rhizome_server_socket = -1;
|
||||
}
|
||||
}
|
||||
WHYF("No ports available in range %u to %u", RHIZOME_HTTP_PORT, RHIZOME_HTTP_PORT_MAX);
|
||||
error:
|
||||
if (rhizome_server_socket != -1) {
|
||||
close(rhizome_server_socket);
|
||||
rhizome_server_socket = -1;
|
||||
}
|
||||
return WHY("Failed to start rhizome HTTP server");
|
||||
|
||||
success:
|
||||
if (config.rhizome.http.enable)
|
||||
INFOF("RHIZOME HTTP SERVER, START port=%"PRIu16" fd=%d", port, rhizome_server_socket);
|
||||
else
|
||||
INFOF("HTTP SERVER (LIMITED SERVICE), START port=%"PRIu16" fd=%d", port, rhizome_server_socket);
|
||||
|
||||
rhizome_http_server_port = port;
|
||||
/* Add Rhizome HTTPd server to list of file descriptors to watch */
|
||||
server_alarm.function = rhizome_server_poll;
|
||||
server_alarm.stats = &server_stats;
|
||||
server_alarm.poll.fd = rhizome_server_socket;
|
||||
server_alarm.poll.events = POLLIN;
|
||||
watch(&server_alarm);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void finalise_union_read_state(rhizome_http_request *r)
|
||||
static void finalise_union_read_state(httpd_request *r)
|
||||
{
|
||||
rhizome_read_close(&r->u.read_state);
|
||||
}
|
||||
|
||||
static void finalise_union_rhizome_insert(rhizome_http_request *r)
|
||||
static void finalise_union_rhizome_insert(httpd_request *r)
|
||||
{
|
||||
if (r->u.insert.manifest_text) {
|
||||
free(r->u.insert.manifest_text);
|
||||
@ -257,110 +54,17 @@ static void finalise_union_rhizome_insert(rhizome_http_request *r)
|
||||
rhizome_fail_write(&r->u.insert.write);
|
||||
}
|
||||
|
||||
static void finalise_union_meshms_conversationlist(rhizome_http_request *r)
|
||||
static void finalise_union_meshms_conversationlist(httpd_request *r)
|
||||
{
|
||||
meshms_free_conversations(r->u.mclist.conv);
|
||||
r->u.mclist.conv = NULL;
|
||||
}
|
||||
|
||||
static void finalise_union_meshms_messagelist(rhizome_http_request *r)
|
||||
static void finalise_union_meshms_messagelist(httpd_request *r)
|
||||
{
|
||||
meshms_message_iterator_close(&r->u.msglist.iter);
|
||||
}
|
||||
|
||||
static void rhizome_server_finalise_http_request(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
if (r->manifest) {
|
||||
rhizome_manifest_free(r->manifest);
|
||||
r->manifest = NULL;
|
||||
}
|
||||
if (r->finalise_union) {
|
||||
r->finalise_union(r);
|
||||
r->finalise_union = NULL;
|
||||
}
|
||||
request_count--;
|
||||
}
|
||||
|
||||
static int rhizome_dispatch(struct http_request *);
|
||||
|
||||
static unsigned int rhizome_http_request_uuid_counter = 0;
|
||||
|
||||
void rhizome_server_poll(struct sched_ent *alarm)
|
||||
{
|
||||
if (alarm->poll.revents & (POLLIN | POLLOUT)) {
|
||||
struct sockaddr addr;
|
||||
unsigned int addr_len = sizeof addr;
|
||||
int sock;
|
||||
if ((sock = accept(rhizome_server_socket, &addr, &addr_len)) == -1) {
|
||||
if (errno && errno != EAGAIN)
|
||||
WARN_perror("accept");
|
||||
} else {
|
||||
struct sockaddr_in *peerip=NULL;
|
||||
if (addr.sa_family == AF_INET) {
|
||||
peerip = (struct sockaddr_in *)&addr; // network order
|
||||
INFOF("RHIZOME HTTP SERVER, ACCEPT addrlen=%u family=%u port=%u addr=%u.%u.%u.%u",
|
||||
addr_len, peerip->sin_family, peerip->sin_port,
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[0],
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[1],
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[2],
|
||||
((unsigned char*)&peerip->sin_addr.s_addr)[3]
|
||||
);
|
||||
} else {
|
||||
INFOF("RHIZOME HTTP SERVER, ACCEPT addrlen=%u family=%u data=%s",
|
||||
addr_len, addr.sa_family, alloca_tohex((unsigned char *)addr.sa_data, sizeof addr.sa_data)
|
||||
);
|
||||
}
|
||||
rhizome_http_request *request = emalloc_zero(sizeof(rhizome_http_request));
|
||||
if (request == NULL) {
|
||||
WHY("Cannot respond to HTTP request, out of memory");
|
||||
close(sock);
|
||||
} else {
|
||||
request_count++;
|
||||
request->uuid = rhizome_http_request_uuid_counter++;
|
||||
if (peerip)
|
||||
request->http.client_sockaddr_in = *peerip;
|
||||
request->http.handle_headers = rhizome_dispatch;
|
||||
request->http.debug_flag = &config.debug.rhizome_httpd;
|
||||
request->http.disable_tx_flag = &config.debug.rhizome_nohttptx;
|
||||
request->http.finalise = rhizome_server_finalise_http_request;
|
||||
request->http.free = free;
|
||||
request->http.idle_timeout = RHIZOME_IDLE_TIMEOUT;
|
||||
http_request_init(&request->http, sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alarm->poll.revents & (POLLHUP | POLLERR)) {
|
||||
INFO("Error on tcp listen socket");
|
||||
}
|
||||
}
|
||||
|
||||
int is_http_header_complete(const char *buf, size_t len, size_t read_since_last_call)
|
||||
{
|
||||
IN();
|
||||
const char *bufend = buf + len;
|
||||
const char *p = buf;
|
||||
size_t tail = read_since_last_call + 4;
|
||||
if (tail < len)
|
||||
p = bufend - tail;
|
||||
int count = 0;
|
||||
for (; p != bufend; ++p) {
|
||||
switch (*p) {
|
||||
case '\n':
|
||||
if (++count==2)
|
||||
RETURN(p - buf);
|
||||
case '\r': // ignore CR
|
||||
case '\0': // ignore NUL (telnet inserts them)
|
||||
break;
|
||||
default:
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RETURN(0);
|
||||
OUT();
|
||||
}
|
||||
|
||||
static int is_from_loopback(const struct http_request *r)
|
||||
{
|
||||
return r->client_sockaddr_in.sin_family == AF_INET
|
||||
@ -425,7 +129,7 @@ static int strn_to_list_token(const char *str, uint64_t *rowidp, const char **af
|
||||
|
||||
static HTTP_CONTENT_GENERATOR restful_rhizome_bundlelist_json_content;
|
||||
|
||||
static int restful_rhizome_bundlelist_json(rhizome_http_request *r, const char *remainder)
|
||||
int restful_rhizome_bundlelist_json(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = "application/json";
|
||||
if (!is_rhizome_http_enabled())
|
||||
@ -448,7 +152,7 @@ static HTTP_CONTENT_GENERATOR_STRBUF_CHUNKER restful_rhizome_bundlelist_json_con
|
||||
|
||||
static int restful_rhizome_bundlelist_json_content(struct http_request *hr, unsigned char *buf, size_t bufsz, struct http_content_generator_result *result)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
int ret = rhizome_list_open(&r->u.rhlist.cursor);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
@ -457,7 +161,7 @@ static int restful_rhizome_bundlelist_json_content(struct http_request *hr, unsi
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int restful_rhizome_newsince(rhizome_http_request *r, const char *remainder)
|
||||
int restful_rhizome_newsince(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = "application/json";
|
||||
if (!is_rhizome_http_enabled())
|
||||
@ -482,7 +186,7 @@ static int restful_rhizome_newsince(rhizome_http_request *r, const char *remaind
|
||||
|
||||
static int restful_rhizome_bundlelist_json_content_chunk(struct http_request *hr, strbuf b)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
const char *headers[] = {
|
||||
".token",
|
||||
"_id",
|
||||
@ -599,7 +303,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);
|
||||
|
||||
static int restful_rhizome_insert(rhizome_http_request *r, const char *remainder)
|
||||
int restful_rhizome_insert(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = "application/json";
|
||||
if (*remainder)
|
||||
@ -636,12 +340,12 @@ static char PART_SECRET[] = "bundle-secret";
|
||||
|
||||
static int insert_mime_part_start(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
assert(r->u.insert.current_part == NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int http_response_form_part(rhizome_http_request *r, const char *what, const char *partname, const char *text, size_t textlen)
|
||||
static int http_response_form_part(httpd_request *r, const char *what, const char *partname, const char *text, size_t textlen)
|
||||
{
|
||||
if (config.debug.rhizome)
|
||||
DEBUGF("%s \"%s\" form part %s", what, partname, text ? alloca_toprint(-1, text, textlen) : "");
|
||||
@ -651,7 +355,7 @@ static int http_response_form_part(rhizome_http_request *r, const char *what, co
|
||||
return 403;
|
||||
}
|
||||
|
||||
static int insert_make_manifest(rhizome_http_request *r)
|
||||
static int insert_make_manifest(httpd_request *r)
|
||||
{
|
||||
if (!r->u.insert.received_manifest)
|
||||
return http_response_form_part(r, "Missing", PART_MANIFEST, NULL, 0);
|
||||
@ -682,7 +386,7 @@ static int insert_make_manifest(rhizome_http_request *r)
|
||||
|
||||
static int insert_mime_part_header(struct http_request *hr, const struct mime_part_headers *h)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (strcmp(h->content_disposition.name, PART_AUTHOR) == 0) {
|
||||
if (r->u.insert.received_author)
|
||||
return http_response_form_part(r, "Duplicate", PART_AUTHOR, NULL, 0);
|
||||
@ -741,7 +445,7 @@ static int insert_mime_part_header(struct http_request *hr, const struct mime_pa
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int accumulate_text(rhizome_http_request *r, const char *partname, char *textbuf, size_t textsiz, size_t *textlenp, const char *buf, size_t len)
|
||||
static int accumulate_text(httpd_request *r, const char *partname, char *textbuf, size_t textsiz, size_t *textlenp, const char *buf, size_t len)
|
||||
{
|
||||
if (len) {
|
||||
size_t newlen = *textlenp + len;
|
||||
@ -763,7 +467,7 @@ static int accumulate_text(rhizome_http_request *r, const char *partname, char *
|
||||
|
||||
static int insert_mime_part_body(struct http_request *hr, char *buf, size_t len)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (r->u.insert.current_part == PART_AUTHOR) {
|
||||
accumulate_text(r, PART_AUTHOR,
|
||||
r->u.insert.author_hex,
|
||||
@ -818,7 +522,7 @@ static int insert_mime_part_body(struct http_request *hr, char *buf, size_t len)
|
||||
|
||||
static int insert_mime_part_end(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (r->u.insert.current_part == PART_AUTHOR) {
|
||||
if ( r->u.insert.author_hex_len != sizeof r->u.insert.author_hex
|
||||
|| strn_to_sid_t(&r->u.insert.author, r->u.insert.author_hex, NULL) == -1
|
||||
@ -872,7 +576,7 @@ static int insert_mime_part_end(struct http_request *hr)
|
||||
|
||||
static int restful_rhizome_insert_end(struct http_request *hr)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (!r->u.insert.received_manifest)
|
||||
return http_response_form_part(r, "Missing", PART_MANIFEST, NULL, 0);
|
||||
if (!r->u.insert.received_payload)
|
||||
@ -962,8 +666,8 @@ static int restful_rhizome_insert_end(struct http_request *hr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rhizome_response_content_init_filehash(rhizome_http_request *r, const rhizome_filehash_t *hash);
|
||||
static int rhizome_response_content_init_payload(rhizome_http_request *r, rhizome_manifest *);
|
||||
static int rhizome_response_content_init_filehash(httpd_request *r, const rhizome_filehash_t *hash);
|
||||
static int rhizome_response_content_init_payload(httpd_request *r, rhizome_manifest *);
|
||||
|
||||
static HTTP_CONTENT_GENERATOR rhizome_payload_content;
|
||||
|
||||
@ -971,7 +675,7 @@ static HTTP_HANDLER restful_rhizome_bid_rhm;
|
||||
static HTTP_HANDLER restful_rhizome_bid_raw_bin;
|
||||
static HTTP_HANDLER restful_rhizome_bid_decrypted_bin;
|
||||
|
||||
static int restful_rhizome_(rhizome_http_request *r, const char *remainder)
|
||||
int restful_rhizome_(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = "application/json";
|
||||
if (!is_rhizome_http_enabled())
|
||||
@ -1014,7 +718,7 @@ static int restful_rhizome_(rhizome_http_request *r, const char *remainder)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int restful_rhizome_bid_rhm(rhizome_http_request *r, const char *remainder)
|
||||
static int restful_rhizome_bid_rhm(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder || r->manifest == NULL)
|
||||
return 404;
|
||||
@ -1024,7 +728,7 @@ static int restful_rhizome_bid_rhm(rhizome_http_request *r, const char *remainde
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int restful_rhizome_bid_raw_bin(rhizome_http_request *r, const char *remainder)
|
||||
static int restful_rhizome_bid_raw_bin(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder || r->manifest == NULL)
|
||||
return 404;
|
||||
@ -1039,7 +743,7 @@ static int restful_rhizome_bid_raw_bin(rhizome_http_request *r, const char *rema
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int restful_rhizome_bid_decrypted_bin(rhizome_http_request *r, const char *remainder)
|
||||
static int restful_rhizome_bid_decrypted_bin(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder || r->manifest == NULL)
|
||||
return 404;
|
||||
@ -1086,7 +790,7 @@ static HTTP_HANDLER restful_meshms_conversationlist_json;
|
||||
static HTTP_HANDLER restful_meshms_messagelist_json;
|
||||
static HTTP_HANDLER restful_meshms_newsince_messagelist_json;
|
||||
|
||||
static int restful_meshms_(rhizome_http_request *r, const char *remainder)
|
||||
int restful_meshms_(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = "application/json";
|
||||
if (!is_rhizome_http_enabled())
|
||||
@ -1126,7 +830,7 @@ static int restful_meshms_(rhizome_http_request *r, const char *remainder)
|
||||
|
||||
static HTTP_CONTENT_GENERATOR restful_meshms_conversationlist_json_content;
|
||||
|
||||
static int restful_meshms_conversationlist_json(rhizome_http_request *r, const char *remainder)
|
||||
static int restful_meshms_conversationlist_json(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -1151,7 +855,7 @@ static int restful_meshms_conversationlist_json_content(struct http_request *hr,
|
||||
|
||||
static int restful_meshms_conversationlist_json_content_chunk(struct http_request *hr, strbuf b)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
// The "my_sid" and "their_sid" per-conversation fields allow the same JSON structure to be used
|
||||
// in a future, non-SID-specific request, eg, to list all conversations for all currently open
|
||||
// identities.
|
||||
@ -1217,7 +921,7 @@ static int restful_meshms_conversationlist_json_content_chunk(struct http_reques
|
||||
|
||||
static HTTP_CONTENT_GENERATOR restful_meshms_messagelist_json_content;
|
||||
|
||||
static int reopen_meshms_message_iterator(rhizome_http_request *r)
|
||||
static int reopen_meshms_message_iterator(httpd_request *r)
|
||||
{
|
||||
if (!meshms_message_iterator_is_open(&r->u.msglist.iter)) {
|
||||
if ( meshms_message_iterator_open(&r->u.msglist.iter, &r->sid1, &r->sid2) == -1
|
||||
@ -1232,7 +936,7 @@ static int reopen_meshms_message_iterator(rhizome_http_request *r)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int restful_meshms_messagelist_json(rhizome_http_request *r, const char *remainder)
|
||||
static int restful_meshms_messagelist_json(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -1246,7 +950,7 @@ static int restful_meshms_messagelist_json(rhizome_http_request *r, const char *
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int restful_meshms_newsince_messagelist_json(rhizome_http_request *r, const char *remainder)
|
||||
static int restful_meshms_newsince_messagelist_json(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
@ -1274,7 +978,7 @@ static HTTP_CONTENT_GENERATOR_STRBUF_CHUNKER restful_meshms_messagelist_json_con
|
||||
|
||||
static int restful_meshms_messagelist_json_content(struct http_request *hr, unsigned char *buf, size_t bufsz, struct http_content_generator_result *result)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
if (reopen_meshms_message_iterator(r) == -1)
|
||||
return -1;
|
||||
return generate_http_content_from_strbuf_chunks(hr, (char *)buf, bufsz, result, restful_meshms_messagelist_json_content_chunk);
|
||||
@ -1282,7 +986,7 @@ static int restful_meshms_messagelist_json_content(struct http_request *hr, unsi
|
||||
|
||||
static int restful_meshms_messagelist_json_content_chunk(struct http_request *hr, strbuf b)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
// Include "my_sid" and "their_sid" per-message, so that the same JSON structure can be used by a
|
||||
// future, non-SID-specific request (eg, to get all messages for all currently open identities).
|
||||
const char *headers[] = {
|
||||
@ -1430,67 +1134,7 @@ static int restful_meshms_messagelist_json_content_chunk(struct http_request *hr
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neighbour_page(rhizome_http_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, "text/html", buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int interface_page(rhizome_http_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, "text/html", buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rhizome_status_page(rhizome_http_request *r, const char *remainder)
|
||||
{
|
||||
if (!is_rhizome_http_enabled())
|
||||
return 403;
|
||||
if (*remainder)
|
||||
return 404;
|
||||
if (r->http.verb != HTTP_VERB_GET)
|
||||
return 405;
|
||||
char buf[32*1024];
|
||||
strbuf b = strbuf_local(buf, sizeof buf);
|
||||
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
|
||||
strbuf_sprintf(b, "%d HTTP requests<br>", request_count);
|
||||
strbuf_sprintf(b, "%d Bundles transferring via MDP<br>", rhizome_cache_count());
|
||||
rhizome_fetch_status_html(b);
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b))
|
||||
return -1;
|
||||
http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rhizome_response_content_init_read_state(rhizome_http_request *r)
|
||||
static int rhizome_response_content_init_read_state(httpd_request *r)
|
||||
{
|
||||
if (r->u.read_state.length == RHIZOME_SIZE_UNSET && rhizome_read(&r->u.read_state, NULL, 0)) {
|
||||
rhizome_read_close(&r->u.read_state);
|
||||
@ -1515,7 +1159,7 @@ static int rhizome_response_content_init_read_state(rhizome_http_request *r)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rhizome_response_content_init_filehash(rhizome_http_request *r, const rhizome_filehash_t *hash)
|
||||
static int rhizome_response_content_init_filehash(httpd_request *r, const rhizome_filehash_t *hash)
|
||||
{
|
||||
bzero(&r->u.read_state, sizeof r->u.read_state);
|
||||
r->u.read_state.blob_fd = -1;
|
||||
@ -1539,7 +1183,7 @@ static int rhizome_response_content_init_filehash(rhizome_http_request *r, const
|
||||
return rhizome_response_content_init_read_state(r);
|
||||
}
|
||||
|
||||
static int rhizome_response_content_init_payload(rhizome_http_request *r, rhizome_manifest *m)
|
||||
static int rhizome_response_content_init_payload(httpd_request *r, rhizome_manifest *m)
|
||||
{
|
||||
bzero(&r->u.read_state, sizeof r->u.read_state);
|
||||
r->u.read_state.blob_fd = -1;
|
||||
@ -1570,7 +1214,7 @@ static int rhizome_payload_content(struct http_request *hr, unsigned char *buf,
|
||||
// Ask for a large buffer for all future reads.
|
||||
const size_t preferred_bufsz = 16 * blocksz;
|
||||
// Reads the next part of the payload into the supplied buffer.
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
assert(r->u.read_state.length != RHIZOME_SIZE_UNSET);
|
||||
assert(r->u.read_state.offset < r->u.read_state.length);
|
||||
uint64_t remain = r->u.read_state.length - r->u.read_state.offset;
|
||||
@ -1591,7 +1235,7 @@ static int rhizome_payload_content(struct http_request *hr, unsigned char *buf,
|
||||
return remain ? 1 : 0;
|
||||
}
|
||||
|
||||
static int rhizome_file_page(rhizome_http_request *r, const char *remainder)
|
||||
int rhizome_file_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
/* Stream the specified payload */
|
||||
if (!is_rhizome_http_enabled())
|
||||
@ -1614,7 +1258,7 @@ static int rhizome_file_page(rhizome_http_request *r, const char *remainder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int manifest_by_prefix_page(rhizome_http_request *r, const char *remainder)
|
||||
int manifest_by_prefix_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (!is_rhizome_http_enabled())
|
||||
return 403;
|
||||
@ -1637,17 +1281,9 @@ static int manifest_by_prefix_page(rhizome_http_request *r, const char *remainde
|
||||
return 404;
|
||||
}
|
||||
|
||||
static int fav_icon_header(rhizome_http_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 void render_manifest_headers(struct http_request *hr, strbuf sb)
|
||||
{
|
||||
rhizome_http_request *r = (rhizome_http_request *) hr;
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
rhizome_manifest *m = r->manifest;
|
||||
strbuf_sprintf(sb, "Serval-Rhizome-Bundle-Id: %s\r\n", alloca_tohex_rhizome_bid_t(m->cryptoSignPublic));
|
||||
strbuf_sprintf(sb, "Serval-Rhizome-Bundle-Version: %"PRIu64"\r\n", m->version);
|
||||
@ -1678,34 +1314,23 @@ static void render_manifest_headers(struct http_request *hr, strbuf sb)
|
||||
strbuf_sprintf(sb, "Serval-Rhizome-Bundle-Inserttime: %"PRIu64"\r\n", m->inserttime);
|
||||
}
|
||||
|
||||
static int root_page(rhizome_http_request *r, const char *remainder)
|
||||
int rhizome_status_page(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (!is_rhizome_http_enabled())
|
||||
return 403;
|
||||
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><br>"
|
||||
"Interfaces;<br>",
|
||||
alloca_tohex_sid_t_trunc(my_subscriber->sid, 16));
|
||||
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>");
|
||||
}
|
||||
char buf[32*1024];
|
||||
strbuf b = strbuf_local(buf, sizeof buf);
|
||||
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
|
||||
strbuf_sprintf(b, "%d HTTP requests<br>", httpd_request_count);
|
||||
strbuf_sprintf(b, "%d Bundles transferring via MDP<br>", rhizome_cache_count());
|
||||
rhizome_fetch_status_html(b);
|
||||
strbuf_puts(b, "</body></html>");
|
||||
if (strbuf_overrun(b)) {
|
||||
WHY("HTTP Root page buffer overrun");
|
||||
return 500;
|
||||
}
|
||||
http_request_response_static(&r->http, 200, "text/html", temp, strbuf_len(b));
|
||||
if (strbuf_overrun(b))
|
||||
return -1;
|
||||
http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b));
|
||||
return 1;
|
||||
}
|
||||
|
@ -24,11 +24,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "meshms.h"
|
||||
#include "http_server.h"
|
||||
|
||||
int is_rhizome_http_server_running();
|
||||
int is_httpd_server_running();
|
||||
|
||||
#define HTTPD_PORT 4110
|
||||
#define HTTPD_PORT_MAX 4150
|
||||
|
||||
extern uint16_t httpd_server_port;
|
||||
extern unsigned int httpd_request_count;
|
||||
|
||||
enum list_phase { LIST_HEADER = 0, LIST_ROWS, LIST_END, LIST_DONE };
|
||||
|
||||
typedef struct rhizome_http_request
|
||||
typedef struct httpd_request
|
||||
{
|
||||
struct http_request http; // MUST BE FIRST ELEMENT
|
||||
|
||||
@ -57,7 +63,7 @@ typedef struct rhizome_http_request
|
||||
|
||||
/* Finaliser for union contents (below).
|
||||
*/
|
||||
void (*finalise_union)(struct rhizome_http_request *);
|
||||
void (*finalise_union)(struct httpd_request *);
|
||||
|
||||
/* Mutually exclusive response arguments.
|
||||
*/
|
||||
@ -155,16 +161,11 @@ typedef struct rhizome_http_request
|
||||
|
||||
} u;
|
||||
|
||||
} rhizome_http_request;
|
||||
} httpd_request;
|
||||
|
||||
int rhizome_server_set_response(rhizome_http_request *r, const struct http_response *h);
|
||||
int rhizome_server_free_http_request(rhizome_http_request *r);
|
||||
int rhizome_server_http_send_bytes(rhizome_http_request *r);
|
||||
int rhizome_server_parse_http_request(rhizome_http_request *r);
|
||||
int rhizome_server_simple_http_response(rhizome_http_request *r, int result, const char *response);
|
||||
int rhizome_server_http_response(rhizome_http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes);
|
||||
int rhizome_server_http_response_header(rhizome_http_request *r, int result, const char *mime_type, uint64_t bytes);
|
||||
int rhizome_http_server_start(uint16_t port_low, uint16_t port_high);
|
||||
int httpd_server_start(uint16_t port_low, uint16_t port_high);
|
||||
|
||||
typedef int HTTP_HANDLER(httpd_request *r, const char *remainder);
|
||||
|
||||
int is_http_header_complete(const char *buf, size_t len, size_t read_since_last_call);
|
||||
|
||||
|
@ -222,7 +222,7 @@ void overlay_rhizome_advertise(struct sched_ent *alarm)
|
||||
}
|
||||
ob_limitsize(frame->payload, 800);
|
||||
ob_append_byte(frame->payload, 2);
|
||||
ob_append_ui16(frame->payload, rhizome_http_server_port);
|
||||
ob_append_ui16(frame->payload, httpd_server_port);
|
||||
int64_t rowid=0;
|
||||
int count = append_bars(frame->payload, &retry,
|
||||
"SELECT BAR,ROWID FROM MANIFESTS ORDER BY ROWID DESC LIMIT 3",
|
||||
@ -263,7 +263,7 @@ int rhizome_advertise_manifest(struct subscriber *dest, rhizome_manifest *m){
|
||||
goto error;
|
||||
ob_limitsize(frame->payload, 800);
|
||||
ob_append_byte(frame->payload, HAS_PORT|HAS_MANIFESTS);
|
||||
ob_append_ui16(frame->payload, is_rhizome_http_enabled()?rhizome_http_server_port:0);
|
||||
ob_append_ui16(frame->payload, is_rhizome_http_enabled()? httpd_server_port : 0);
|
||||
ob_append_ui16(frame->payload, m->manifest_all_bytes);
|
||||
ob_append_bytes(frame->payload, m->manifestdata, m->manifest_all_bytes);
|
||||
ob_append_byte(frame->payload, 0xFF);
|
||||
@ -292,7 +292,7 @@ int overlay_rhizome_saw_advertisements(struct decode_context *context, struct ov
|
||||
int ad_frame_type=ob_get(f->payload);
|
||||
struct socket_address httpaddr = context->addr;
|
||||
if (httpaddr.addr.sa_family == AF_INET)
|
||||
httpaddr.inet.sin_port = htons(RHIZOME_HTTP_PORT);
|
||||
httpaddr.inet.sin_port = htons(HTTPD_PORT);
|
||||
rhizome_manifest *m=NULL;
|
||||
|
||||
int (*oldfunc)() = sqlite_set_tracefunc(is_debug_rhizome_ads);
|
||||
|
@ -14,6 +14,7 @@ SERVAL_SOURCES = \
|
||||
$(SERVAL_BASE)fdqueue.c \
|
||||
$(SERVAL_BASE)fifo.c \
|
||||
$(SERVAL_BASE)golay.c \
|
||||
$(SERVAL_BASE)httpd.c \
|
||||
$(SERVAL_BASE)http_server.c \
|
||||
$(SERVAL_BASE)keyring.c \
|
||||
$(SERVAL_BASE)log.c \
|
||||
|
@ -400,13 +400,13 @@ compute_filehash() {
|
||||
|
||||
rhizome_http_server_started() {
|
||||
local logvar=LOG${1#+}
|
||||
$GREP 'RHIZOME HTTP SERVER,.*START.*port=[0-9]' "${!logvar}"
|
||||
$GREP 'HTTP SERVER START.*port=[0-9].*services=[^ ]*\<Rhizome\>' "${!logvar}"
|
||||
}
|
||||
|
||||
get_rhizome_server_port() {
|
||||
local _var="$1"
|
||||
local _logvar=LOG${2#+}
|
||||
local _port=$($SED -n -e '/RHIZOME HTTP SERVER.*START/s/.*port=\([0-9]\{1,\}\).*/\1/p' "${!_logvar}" | $SED -n '$p')
|
||||
local _port=$($SED -n -e '/HTTP SERVER START/s/.*port=\([0-9]\{1,\}\).*services=[^ ]*\<Rhizome\>.*/\1/p' "${!_logvar}" | $SED -n '$p')
|
||||
assert --message="instance $2 Rhizome HTTP server port number is known" [ -n "$_port" ]
|
||||
if [ -n "$_var" ]; then
|
||||
eval "$_var=\$_port"
|
||||
|
@ -41,7 +41,7 @@ configure_servald_server() {
|
||||
set log.show_pid on \
|
||||
set log.show_time on \
|
||||
set debug.rhizome on \
|
||||
set debug.rhizome_httpd on \
|
||||
set debug.httpd on \
|
||||
set debug.rhizome_tx on \
|
||||
set debug.rhizome_rx on \
|
||||
set server.respawn_on_crash off \
|
||||
|
@ -103,8 +103,8 @@ set_extra_config() {
|
||||
|
||||
set_rhizome_config() {
|
||||
executeOk_servald config \
|
||||
set debug.http_server on \
|
||||
set debug.httpd on \
|
||||
set debug.rhizome_httpd on \
|
||||
set debug.rhizome_manifest on \
|
||||
set debug.externalblobs on \
|
||||
set debug.rhizome on \
|
||||
|
@ -42,8 +42,8 @@ configure_servald_server() {
|
||||
set log.console.show_pid on \
|
||||
set log.console.show_time on \
|
||||
set debug.rhizome on \
|
||||
set debug.http_server on \
|
||||
set debug.httpd on \
|
||||
set debug.rhizome_httpd on \
|
||||
set debug.rhizome_manifest on \
|
||||
set debug.rhizome_ads on \
|
||||
set debug.rhizome_tx on \
|
||||
@ -180,7 +180,7 @@ setup_MDPTransportFailOver() {
|
||||
setup_common
|
||||
foreach_instance +A +B \
|
||||
executeOk_servald config \
|
||||
set debug.rhizome_nohttptx 1 \
|
||||
set debug.nohttptx 1 \
|
||||
set rhizome.mdp.enable 1
|
||||
set_instance +A
|
||||
rhizome_add_file file1 2048
|
||||
@ -583,7 +583,7 @@ setup_direct() {
|
||||
set log.console.level debug \
|
||||
set log.console.show_time on \
|
||||
set debug.rhizome on \
|
||||
set debug.rhizome_httpd on \
|
||||
set debug.httpd on \
|
||||
set debug.rhizome_tx on \
|
||||
set debug.rhizome_rx on
|
||||
rhizome_add_file fileB1 2000
|
||||
|
@ -41,7 +41,7 @@ configure_servald_server() {
|
||||
set log.file.show_pid on \
|
||||
set log.file.show_time on \
|
||||
set debug.rhizome off \
|
||||
set debug.rhizome_httpd off \
|
||||
set debug.httpd off \
|
||||
set debug.rhizome_tx off \
|
||||
set debug.rhizome_rx off \
|
||||
set server.respawn_on_crash off \
|
||||
@ -149,7 +149,7 @@ setup_StressRhizomeDirect() {
|
||||
executeOk_servald config \
|
||||
set log.file.show_time on \
|
||||
set debug.rhizome off \
|
||||
set debug.rhizome_httpd off \
|
||||
set debug.httpd off \
|
||||
set debug.rhizome_tx off \
|
||||
set debug.rhizome_rx off \
|
||||
set server.respawn_on_crash off \
|
||||
|
Loading…
x
Reference in New Issue
Block a user