mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 10:46:23 +00:00
Refactor rhizome HTTP response headers
This commit is contained in:
parent
41f3228300
commit
dd225bbb7f
208
rhizome_http.c
208
rhizome_http.c
@ -72,13 +72,12 @@ typedef struct rhizome_http_request {
|
|||||||
|
|
||||||
} rhizome_http_request;
|
} rhizome_http_request;
|
||||||
|
|
||||||
int rhizome_server_free_http_request(rhizome_http_request *r);
|
static int rhizome_server_free_http_request(rhizome_http_request *r);
|
||||||
int rhizome_server_http_send_bytes(rhizome_http_request *r);
|
static int rhizome_server_http_send_bytes(rhizome_http_request *r);
|
||||||
int rhizome_server_parse_http_request(rhizome_http_request *r);
|
static int rhizome_server_parse_http_request(rhizome_http_request *r);
|
||||||
int rhizome_server_simple_http_response(rhizome_http_request *r,int result, char *response);
|
static int rhizome_server_simple_http_response(rhizome_http_request *r, int result, const char *response);
|
||||||
int rhizome_server_http_response_header(rhizome_http_request *r,int result,
|
static int rhizome_server_http_response_header(rhizome_http_request *r, int result, const char *mime_type, unsigned long long bytes);
|
||||||
char *mime_type,unsigned long long bytes);
|
static int rhizome_server_sql_query_fill_buffer(rhizome_http_request *r, char *table, char *column);
|
||||||
int rhizome_server_sql_query_fill_buffer(rhizome_http_request *r, char *table, char *column);
|
|
||||||
|
|
||||||
#define RHIZOME_SERVER_MAX_LIVE_REQUESTS 32
|
#define RHIZOME_SERVER_MAX_LIVE_REQUESTS 32
|
||||||
|
|
||||||
@ -283,7 +282,8 @@ void rhizome_server_poll(struct sched_ent *alarm)
|
|||||||
while ((sock = accept(rhizome_server_socket, &addr, &addr_len)) != -1) {
|
while ((sock = accept(rhizome_server_socket, &addr, &addr_len)) != -1) {
|
||||||
if (addr.sa_family == AF_INET) {
|
if (addr.sa_family == AF_INET) {
|
||||||
struct sockaddr_in *peerip = (struct sockaddr_in *)&addr;
|
struct sockaddr_in *peerip = (struct sockaddr_in *)&addr;
|
||||||
INFOF("HTTP ACCEPT addrlen=%u family=%u port=%u addr=%u.%u.%u.%u",
|
if (debug & DEBUG_RHIZOME_TX)
|
||||||
|
DEBUGF("HTTP ACCEPT addrlen=%u family=%u port=%u addr=%u.%u.%u.%u",
|
||||||
addr_len, peerip->sin_family, peerip->sin_port,
|
addr_len, peerip->sin_family, peerip->sin_port,
|
||||||
((unsigned char*)&peerip->sin_addr.s_addr)[0],
|
((unsigned char*)&peerip->sin_addr.s_addr)[0],
|
||||||
((unsigned char*)&peerip->sin_addr.s_addr)[1],
|
((unsigned char*)&peerip->sin_addr.s_addr)[1],
|
||||||
@ -291,40 +291,48 @@ void rhizome_server_poll(struct sched_ent *alarm)
|
|||||||
((unsigned char*)&peerip->sin_addr.s_addr)[3]
|
((unsigned char*)&peerip->sin_addr.s_addr)[3]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
INFOF("HTTP ACCEPT addrlen=%u family=%u data=%s",
|
if (debug & DEBUG_RHIZOME_TX)
|
||||||
|
DEBUGF("HTTP ACCEPT addrlen=%u family=%u data=%s",
|
||||||
addr_len, addr.sa_family, alloca_tohex((unsigned char *)addr.sa_data, sizeof addr.sa_data));
|
addr_len, addr.sa_family, alloca_tohex((unsigned char *)addr.sa_data, sizeof addr.sa_data));
|
||||||
}
|
}
|
||||||
rhizome_http_request *request = calloc(sizeof(rhizome_http_request),1);
|
rhizome_http_request *request = calloc(sizeof(rhizome_http_request), 1);
|
||||||
/* We are now trying to read the HTTP request */
|
if (request == NULL) {
|
||||||
request->request_type=RHIZOME_HTTP_REQUEST_RECEIVING;
|
WHYF_perror("calloc(%u, 1)", sizeof(rhizome_http_request));
|
||||||
request->alarm.function = rhizome_client_poll;
|
WHY("Cannot respond to request, out of memory");
|
||||||
connection_stats.name="rhizome_client_poll";
|
} else {
|
||||||
request->alarm.stats=&connection_stats;
|
/* We are now trying to read the HTTP request */
|
||||||
request->alarm.poll.fd=sock;
|
request->request_type=RHIZOME_HTTP_REQUEST_RECEIVING;
|
||||||
request->alarm.poll.events=POLLIN;
|
request->alarm.function = rhizome_client_poll;
|
||||||
request->alarm.alarm = overlay_gettime_ms()+RHIZOME_IDLE_TIMEOUT;
|
connection_stats.name="rhizome_client_poll";
|
||||||
// watch for the incoming http request
|
request->alarm.stats=&connection_stats;
|
||||||
watch(&request->alarm);
|
request->alarm.poll.fd=sock;
|
||||||
// set an inactivity timeout to close the connection
|
request->alarm.poll.events=POLLIN;
|
||||||
schedule(&request->alarm);
|
request->alarm.alarm = overlay_gettime_ms()+RHIZOME_IDLE_TIMEOUT;
|
||||||
|
// watch for the incoming http request
|
||||||
|
watch(&request->alarm);
|
||||||
|
// set an inactivity timeout to close the connection
|
||||||
|
schedule(&request->alarm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
WARN_perror("accept");
|
WARN_perror("accept");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int rhizome_server_free_http_request(rhizome_http_request *r)
|
static int rhizome_server_free_http_request(rhizome_http_request *r)
|
||||||
{
|
{
|
||||||
unwatch(&r->alarm);
|
unwatch(&r->alarm);
|
||||||
unschedule(&r->alarm);
|
unschedule(&r->alarm);
|
||||||
close(r->alarm.poll.fd);
|
close(r->alarm.poll.fd);
|
||||||
if (r->buffer&&r->buffer_size) free(r->buffer);
|
if (r->buffer)
|
||||||
if (r->blob) sqlite3_blob_close(r->blob);
|
free(r->buffer);
|
||||||
|
if (r->blob)
|
||||||
|
sqlite3_blob_close(r->blob);
|
||||||
free(r);
|
free(r);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rhizome_server_sql_query_http_response(rhizome_http_request *r,
|
static int rhizome_server_sql_query_http_response(rhizome_http_request *r,
|
||||||
char *column,char *table,char *query_body,
|
char *column,char *table,char *query_body,
|
||||||
int bytes_per_row,int dehexP)
|
int bytes_per_row,int dehexP)
|
||||||
{
|
{
|
||||||
@ -337,10 +345,17 @@ int rhizome_server_sql_query_http_response(rhizome_http_request *r,
|
|||||||
the body, although encryption is not yet implemented here.
|
the body, although encryption is not yet implemented here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (r->buffer) { free(r->buffer); r->buffer=NULL; }
|
if (r->buffer == NULL || r->buffer_size < 16384) {
|
||||||
r->buffer_size=16384;
|
if (r->buffer)
|
||||||
r->buffer=malloc(r->buffer_size);
|
free(r->buffer);
|
||||||
if (!r->buffer) return WHY_perror("malloc");
|
r->buffer_size = 16384;
|
||||||
|
r->buffer = malloc(r->buffer_size);
|
||||||
|
if (r->buffer == NULL) {
|
||||||
|
r->buffer_size = 0;
|
||||||
|
WHY_perror("malloc");
|
||||||
|
return WHY("Cannot send response, out of memory");
|
||||||
|
}
|
||||||
|
}
|
||||||
r->buffer_length=0;
|
r->buffer_length=0;
|
||||||
r->buffer_offset=0;
|
r->buffer_offset=0;
|
||||||
r->source_record_size=bytes_per_row;
|
r->source_record_size=bytes_per_row;
|
||||||
@ -349,10 +364,9 @@ int rhizome_server_sql_query_http_response(rhizome_http_request *r,
|
|||||||
|
|
||||||
/* Work out total response length */
|
/* Work out total response length */
|
||||||
long long response_bytes=256+r->source_count*r->source_record_size;
|
long long response_bytes=256+r->source_count*r->source_record_size;
|
||||||
rhizome_server_http_response_header(r,200,"servalproject.org/rhizome-list",
|
rhizome_server_http_response_header(r, 200, "servalproject.org/rhizome-list", response_bytes);
|
||||||
response_bytes);
|
|
||||||
if (debug & DEBUG_RHIZOME_TX)
|
if (debug & DEBUG_RHIZOME_TX)
|
||||||
DEBUGF("headers consumed %d bytes",r->buffer_length);
|
DEBUGF("headers consumed %d bytes", r->buffer_length);
|
||||||
|
|
||||||
/* Clear and prepare response header */
|
/* Clear and prepare response header */
|
||||||
bzero(&r->buffer[r->buffer_length],256);
|
bzero(&r->buffer[r->buffer_length],256);
|
||||||
@ -387,7 +401,7 @@ int rhizome_server_sql_query_http_response(rhizome_http_request *r,
|
|||||||
return rhizome_server_sql_query_fill_buffer(r, table, column);
|
return rhizome_server_sql_query_fill_buffer(r, table, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rhizome_server_sql_query_fill_buffer(rhizome_http_request *r, char *table, char *column)
|
static int rhizome_server_sql_query_fill_buffer(rhizome_http_request *r, char *table, char *column)
|
||||||
{
|
{
|
||||||
unsigned char blob_value[r->source_record_size*2+1];
|
unsigned char blob_value[r->source_record_size*2+1];
|
||||||
|
|
||||||
@ -495,7 +509,7 @@ static int strcmp_prefix(char *str, const char *prefix, char **afterp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rhizome_server_parse_http_request(rhizome_http_request *r)
|
static int rhizome_server_parse_http_request(rhizome_http_request *r)
|
||||||
{
|
{
|
||||||
/* Switching to writing, so update the call-back */
|
/* Switching to writing, so update the call-back */
|
||||||
r->alarm.poll.events=POLLOUT;
|
r->alarm.poll.events=POLLOUT;
|
||||||
@ -514,7 +528,7 @@ int rhizome_server_parse_http_request(rhizome_http_request *r)
|
|||||||
DEBUGF("GET %s", path);
|
DEBUGF("GET %s", path);
|
||||||
if (strcmp(path, "/favicon.ico") == 0) {
|
if (strcmp(path, "/favicon.ico") == 0) {
|
||||||
r->request_type = RHIZOME_HTTP_REQUEST_FAVICON;
|
r->request_type = RHIZOME_HTTP_REQUEST_FAVICON;
|
||||||
rhizome_server_http_response_header(r, 200, "image/vnd.microsoft.icon", favicon_len);
|
rhizome_server_http_response_header(r, 200, "image/vnd.microsoft.icon", favicon_len);
|
||||||
} else if (strcmp(path, "/rhizome/groups") == 0) {
|
} else if (strcmp(path, "/rhizome/groups") == 0) {
|
||||||
/* Return the list of known groups */
|
/* Return the list of known groups */
|
||||||
rhizome_server_sql_query_http_response(r, "id", "groups", "from groups", 32, 1);
|
rhizome_server_sql_query_http_response(r, "id", "groups", "from groups", 32, 1);
|
||||||
@ -560,43 +574,89 @@ int rhizome_server_parse_http_request(rhizome_http_request *r)
|
|||||||
|
|
||||||
|
|
||||||
/* Return appropriate message for HTTP response codes, both known and unknown. */
|
/* Return appropriate message for HTTP response codes, both known and unknown. */
|
||||||
#define A_VALUE_GREATER_THAN_FOUR (2+3)
|
static const char *httpResultString(int response_code) {
|
||||||
char *httpResultString(int id) {
|
switch (response_code) {
|
||||||
switch (id) {
|
case 200: return "OK";
|
||||||
case 200: return "OK"; break;
|
case 206: return "Partial Content";
|
||||||
case 206: return "Partial Content"; break;
|
case 404: return "Not found";
|
||||||
case 404: return "Not found"; break;
|
case 500: return "Internal server error";
|
||||||
default:
|
default: return "A suffusion of yellow";
|
||||||
case A_VALUE_GREATER_THAN_FOUR:
|
|
||||||
if (id>4) return "A suffusion of yellow";
|
|
||||||
/* The following MUST be the longest string returned by this function */
|
|
||||||
else return "THE JUDGEMENT OF KING WEN: Chun Signifies Difficulties At Outset, As Of Blade Of Grass Pushing Up Against Stone.";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int rhizome_server_simple_http_response(rhizome_http_request *r,int result, char *response)
|
struct http_response {
|
||||||
|
unsigned int result_code;
|
||||||
|
const char * content_type;
|
||||||
|
unsigned long long content_length;
|
||||||
|
const char * body;
|
||||||
|
};
|
||||||
|
|
||||||
|
static strbuf strbuf_build_http_response(strbuf sb, const struct http_response *h)
|
||||||
{
|
{
|
||||||
if (r->buffer) free(r->buffer);
|
strbuf_sprintf(sb, "HTTP/1.0 %03u %s\r\n", h->result_code, httpResultString(h->result_code));
|
||||||
r->buffer_size=strlen(response)+strlen("HTTP/1.0 000 \r\n\r\nContent-type: text/html\r\nContent-length: 0000\r\n\r\n")+strlen(httpResultString(result))+strlen(response)+100;
|
strbuf_sprintf(sb, "Content-type: %s\r\n", h->content_type);
|
||||||
|
strbuf_sprintf(sb, "Content-length: %llu\r\n", h->content_length);
|
||||||
|
strbuf_puts(sb, "\r\n");
|
||||||
|
if (h->body)
|
||||||
|
strbuf_puts(sb, h->body);
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
r->buffer=(unsigned char *)malloc(r->buffer_size);
|
static int rhizome_server_set_response(rhizome_http_request *r, const struct http_response *h)
|
||||||
snprintf((char *)r->buffer,r->buffer_size,"HTTP/1.0 %03d %s\r\nContent-type: text/html\r\nContent-length: %d\r\n\r\n%s",result,httpResultString(result),(int)strlen(response),response);
|
{
|
||||||
|
strbuf b = strbuf_local((char *) r->buffer, r->buffer_size);
|
||||||
r->buffer_size=strlen((char *)r->buffer)+1;
|
strbuf_build_http_response(b, h);
|
||||||
r->buffer_length=r->buffer_size-1;
|
if (r->buffer == NULL || strbuf_overrun(b)) {
|
||||||
r->buffer_offset=0;
|
// Need a bigger buffer
|
||||||
|
if (r->buffer)
|
||||||
r->request_type=RHIZOME_HTTP_REQUEST_FROMBUFFER;
|
free(r->buffer);
|
||||||
|
r->buffer_size = strbuf_count(b) + 1;
|
||||||
|
r->buffer = malloc(r->buffer_size);
|
||||||
|
if (r->buffer == NULL) {
|
||||||
|
WHYF_perror("malloc(%u)", r->buffer_size);
|
||||||
|
r->buffer_size = 0;
|
||||||
|
return WHY("Cannot send response, out of memory");
|
||||||
|
}
|
||||||
|
strbuf_init(b, (char *) r->buffer, r->buffer_size);
|
||||||
|
strbuf_build_http_response(b, h);
|
||||||
|
if (strbuf_overrun(b))
|
||||||
|
return WHYF("Bug! Cannot send response, buffer not big enough");
|
||||||
|
}
|
||||||
|
r->buffer_length = strbuf_len(b);
|
||||||
|
r->buffer_offset = 0;
|
||||||
|
r->request_type |= RHIZOME_HTTP_REQUEST_FROMBUFFER;
|
||||||
|
if (debug & DEBUG_RHIZOME_TX)
|
||||||
|
DEBUGF("Sending HTTP response: %s", alloca_toprint(120, r->buffer, r->buffer_length));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rhizome_server_simple_http_response(rhizome_http_request *r, int result, const char *response)
|
||||||
|
{
|
||||||
|
struct http_response hr;
|
||||||
|
hr.result_code = result;
|
||||||
|
hr.content_type = "text/html";
|
||||||
|
hr.content_length = strlen(response);
|
||||||
|
hr.body = response;
|
||||||
|
return rhizome_server_set_response(r, &hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rhizome_server_http_response_header(rhizome_http_request *r, int result, const char *mime_type, unsigned long long bytes)
|
||||||
|
{
|
||||||
|
struct http_response hr;
|
||||||
|
hr.result_code = result;
|
||||||
|
hr.content_type = mime_type;
|
||||||
|
hr.content_length = bytes;
|
||||||
|
hr.body = NULL;
|
||||||
|
return rhizome_server_set_response(r, &hr);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
return codes:
|
return codes:
|
||||||
1: connection still open.
|
1: connection still open.
|
||||||
0: connection finished.
|
0: connection finished.
|
||||||
<0: an error occurred.
|
<0: an error occurred.
|
||||||
*/
|
*/
|
||||||
int rhizome_server_http_send_bytes(rhizome_http_request *r)
|
static int rhizome_server_http_send_bytes(rhizome_http_request *r)
|
||||||
{
|
{
|
||||||
// keep writing until the write would block or we run out of data
|
// keep writing until the write would block or we run out of data
|
||||||
while(r->request_type){
|
while(r->request_type){
|
||||||
@ -700,33 +760,3 @@ int rhizome_server_http_send_bytes(rhizome_http_request *r)
|
|||||||
if (!r->request_type) return rhizome_server_free_http_request(r);
|
if (!r->request_type) return rhizome_server_free_http_request(r);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rhizome_server_http_response_header(rhizome_http_request *r,int result,
|
|
||||||
char *mime_type,unsigned long long bytes)
|
|
||||||
{
|
|
||||||
int min_buff = strlen("HTTP/1.0 000 \r\nContent-type: \r\nContent-length: \r\n\r\n")
|
|
||||||
+strlen(httpResultString(result))
|
|
||||||
+strlen(mime_type)+20;
|
|
||||||
|
|
||||||
if (min_buff+bytes > 65536){
|
|
||||||
min_buff = 65536;
|
|
||||||
}else{
|
|
||||||
min_buff += bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r->buffer_size < min_buff) {
|
|
||||||
if (r->buffer)
|
|
||||||
free(r->buffer);
|
|
||||||
r->buffer=(unsigned char *)malloc(min_buff);
|
|
||||||
r->buffer_size=min_buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf((char *)r->buffer,r->buffer_size,"HTTP/1.0 %03d %s\r\nContent-type: %s\r\nContent-length: %lld\r\n\r\n",result,httpResultString(result),mime_type,bytes);
|
|
||||||
|
|
||||||
r->buffer_length=strlen((char *)r->buffer);
|
|
||||||
r->buffer_offset=0;
|
|
||||||
|
|
||||||
r->request_type|=RHIZOME_HTTP_REQUEST_FROMBUFFER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
2
serval.h
2
serval.h
@ -791,7 +791,7 @@ char *catv(const char *data, char *buf, size_t len);
|
|||||||
int dump(char *name, unsigned char *addr, size_t len);
|
int dump(char *name, unsigned char *addr, size_t len);
|
||||||
char *toprint(char *dstStr, size_t dstChars, const unsigned char *srcBuf, size_t srcBytes);
|
char *toprint(char *dstStr, size_t dstChars, const unsigned char *srcBuf, size_t srcBytes);
|
||||||
|
|
||||||
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca((dstlen) + 1), (dstlen) + 1, (buf), (len) + 1)
|
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca((dstlen) + 1), (dstlen) + 1, (buf), (len))
|
||||||
|
|
||||||
#define alloca_tohex(buf,len) tohex((char *)alloca((len)*2+1), (buf), (len))
|
#define alloca_tohex(buf,len) tohex((char *)alloca((len)*2+1), (buf), (len))
|
||||||
#define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE)
|
#define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE)
|
||||||
|
Loading…
Reference in New Issue
Block a user