summaryrefslogtreecommitdiffstats
path: root/nanohttp
diff options
context:
space:
mode:
Diffstat (limited to 'nanohttp')
-rw-r--r--nanohttp/nanohttp-server.c681
1 files changed, 362 insertions, 319 deletions
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index 467d253..0f89edc 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-server.c,v 1.16 2004/09/01 14:10:23 snowdrop Exp $
+* $Id: nanohttp-server.c,v 1.17 2004/09/01 16:03:17 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -43,17 +43,19 @@
#endif
/*
- * ----------------------------------------------------- nano httpd
- * internally globals -----------------------------------------------------
+ * -----------------------------------------------------
+ * nano httpd
+ * internally globals
+ * -----------------------------------------------------
*/
-static int _httpd_port = 10000;
-static int _httpd_max_connections = 20;
-static int _httpd_max_idle = 120;
+static int _httpd_port = 10000;
+static int _httpd_max_connections = 20;
+static int _httpd_max_idle = 120;
static hsocket_t _httpd_socket;
static hservice_t *_httpd_services_head = NULL;
static hservice_t *_httpd_services_tail = NULL;
-static int _httpd_run = 1;
-static int _httpd_terminate_signal = SIGTERM;
+static int _httpd_run = 1;
+static int _httpd_terminate_signal = SIGTERM;
static conndata_t *_httpd_connection;
#ifdef WIN32
@@ -61,434 +63,475 @@ static conndata_t *_httpd_connection;
#endif
/*
- * ----------------------------------------------------- FUNCTION: httpd_init
+ * -----------------------------------------------------
+ * FUNCTION: httpd_init
* NOTE: This will be called from soap_server_init_args()
* -----------------------------------------------------
*/
int
-httpd_init(int argc, char *argv[])
+httpd_init (int argc, char *argv[])
{
- int i, status;
- status = hsocket_module_init();
+ int i, status;
+ status = hsocket_module_init ();
if (status != 0)
return status;
/* write argument information */
- log_verbose1("Arguments:");
+ log_verbose1 ("Arguments:");
for (i = 0; i < argc; i++)
- log_verbose3("argv[%i] = '%s'", i, SAVE_STR(argv[i]));
+ log_verbose3 ("argv[%i] = '%s'", i, SAVE_STR (argv[i]));
/* initialize from arguments */
- for (i = 0; i < argc; i++) {
- if (!strcmp(argv[i], NHTTPD_ARG_PORT) && i < argc - 1) {
- _httpd_port = atoi(argv[i + 1]);
- } else if (!strcmp(argv[i], NHTTPD_ARG_TERMSIG) && i < argc - 1) {
- _httpd_terminate_signal = atoi(argv[i + 1]);
- } else if (!strcmp(argv[i], NHTTPD_ARG_MAXCONN) && i < argc - 1) {
- _httpd_max_connections = atoi(argv[i + 1]);
+ for (i = 0; i < argc; i++)
+ {
+ if (!strcmp (argv[i], NHTTPD_ARG_PORT) && i < argc - 1)
+ {
+ _httpd_port = atoi (argv[i + 1]);
+ }
+ else if (!strcmp (argv[i], NHTTPD_ARG_TERMSIG) && i < argc - 1)
+ {
+ _httpd_terminate_signal = atoi (argv[i + 1]);
+ }
+ else if (!strcmp (argv[i], NHTTPD_ARG_MAXCONN) && i < argc - 1)
+ {
+ _httpd_max_connections = atoi (argv[i + 1]);
}
}
- log_verbose2("socket bind to port '%d'", _httpd_port);
-
+ log_verbose2 ("socket bind to port '%d'", _httpd_port);
+
/* init built-in services */
- /*
- * httpd_register("/httpd/list", service_list);
- */
- _httpd_connection = calloc(_httpd_max_connections, sizeof(conndata_t));
- for (i = 0; i < _httpd_max_connections; i++) {
- memset((char *) &_httpd_connection[i], 0,
- sizeof(_httpd_connection[i]));
+
+ /* httpd_register("/httpd/list", service_list);*/
+
+ _httpd_connection = calloc (_httpd_max_connections, sizeof (conndata_t));
+ for (i = 0; i < _httpd_max_connections; i++)
+ {
+ memset ((char *) &_httpd_connection[i], 0, sizeof (_httpd_connection[i]));
}
-
+
#ifdef WIN32
- if (_beginthread(WSAReaper, 0, NULL) == -1) {
- log_error1("Winsock reaper thread failed to start");
+ if (_beginthread (WSAReaper, 0, NULL) == -1)
+ {
+ log_error1 ("Winsock reaper thread failed to start");
return (-1);
}
#endif
/* create socket */
- hsocket_init(&_httpd_socket);
- status = hsocket_bind(&_httpd_socket, _httpd_port);
-
+ hsocket_init (&_httpd_socket);
+ status = hsocket_bind (&_httpd_socket, _httpd_port);
+
return status;
}
/*
- * ----------------------------------------------------- FUNCTION:
- * httpd_register -----------------------------------------------------
+ * -----------------------------------------------------
+ * FUNCTION: httpd_register
+ * -----------------------------------------------------
*/
int
-httpd_register(const char *ctx, httpd_service func)
+httpd_register (const char *ctx, httpd_service func)
{
- hservice_t *service;
-
- service = (hservice_t *) malloc(sizeof(hservice_t));
- service->next = NULL;
- service->func = func;
- strcpy(service->ctx, ctx);
-
- log_verbose3("register service:t(%p):%s", service, SAVE_STR(ctx));
- if (_httpd_services_head == NULL) {
- _httpd_services_head = _httpd_services_tail = service;
- } else {
- _httpd_services_tail->next = service;
- _httpd_services_tail = service;
- }
-
- return 1;
+ hservice_t *service;
+
+ service = (hservice_t *) malloc (sizeof (hservice_t));
+ service->next = NULL;
+ service->func = func;
+ strcpy (service->ctx, ctx);
+
+ log_verbose3 ("register service:t(%p):%s", service, SAVE_STR (ctx));
+ if (_httpd_services_head == NULL)
+ {
+ _httpd_services_head = _httpd_services_tail = service;
+ }
+ else
+ {
+ _httpd_services_tail->next = service;
+ _httpd_services_tail = service;
+ }
+
+ return 1;
}
/*
- * ----------------------------------------------------- FUNCTION:
- * httpd_services -----------------------------------------------------
+ * -----------------------------------------------------
+ * FUNCTION: httpd_services
+ * -----------------------------------------------------
*/
-hservice_t *
-httpd_services()
+hservice_t *
+httpd_services ()
{
- return _httpd_services_head;
+ return _httpd_services_head;
}
/*
- * ----------------------------------------------------- FUNCTION:
- * httpd_find_service -----------------------------------------------------
+ * -----------------------------------------------------
+ * FUNCTION: httpd_find_service
+ * -----------------------------------------------------
*/
static hservice_t *
-httpd_find_service(const char *ctx)
+httpd_find_service (const char *ctx)
{
- hservice_t *cur = _httpd_services_head;
+ hservice_t *cur = _httpd_services_head;
- while (cur != NULL) {
- if (!strcmp(cur->ctx, ctx)) {
- return cur;
- }
- cur = cur->next;
- }
+ while (cur != NULL)
+ {
+ if (!strcmp (cur->ctx, ctx))
+ {
+ return cur;
+ }
+ cur = cur->next;
+ }
- return NULL;
+ return NULL;
}
/*
- * ----------------------------------------------------- FUNCTION:
- * httpd_response_set_content_type
+ * -----------------------------------------------------
+ * FUNCTION: httpd_response_set_content_type
* -----------------------------------------------------
*/
void
-httpd_response_set_content_type(httpd_conn_t * res, const char *content_type)
+httpd_response_set_content_type (httpd_conn_t * res, const char *content_type)
{
- strncpy(res->content_type, content_type, 25);
+ strncpy (res->content_type, content_type, 25);
}
/*
- * ----------------------------------------------------- FUNCTION:
- * httpd_response_send_header
+ * -----------------------------------------------------
+ * FUNCTION: httpd_response_send_header
* -----------------------------------------------------
*/
int
-httpd_send_header(httpd_conn_t * res,
- int code, const char *text, hpair_t * pair)
+httpd_send_header (httpd_conn_t * res,
+ int code, const char *text, hpair_t * pair)
{
- struct tm stm;
- time_t nw;
- char buffer[255];
- char header[1024];
- hpair_t *cur;
- int status;
-
- /* set status code */
- sprintf(header, "HTTP/1.1 %d %s\r\n", code, text);
-
- /* set date */
- nw = time(NULL);
- localtime_r(&nw, &stm);
- strftime(buffer, 255, "Date: %a, %d %b %y %T GMT", &stm);
- strcat(header, buffer);
- strcat(header, "\r\n");
-
- /* set content-type */
- /*
- * if (res->content_type[0] == '\0') { strcat(header, "Content-Type:
- * text/html\r\n"); } else { sprintf(buffer, "Content-Type: %s\r\n",
- * res->content_type); strcat(header, buffer); }
- */
-
- /* set server name */
- strcat(header, "Server: Nano HTTPD library\r\n");
-
- /* set _httpd_connection status */
- strcat(header, "Connection: close\r\n");
-
- /* add pairs */
- cur = pair;
- while (cur != NULL) {
- sprintf(buffer, "%s: %s\r\n", cur->key, cur->value);
- strcat(header, buffer);
- cur = cur->next;
- }
-
- /* set end of header */
- strcat(header, "\r\n");
-
- /* send header */
- status = hsocket_nsend(res->sock, header, strlen(header));
-
- return status;
+ struct tm stm;
+ time_t nw;
+ char buffer[255];
+ char header[1024];
+ hpair_t *cur;
+ int status;
+
+ /* set status code */
+ sprintf (header, "HTTP/1.1 %d %s\r\n", code, text);
+
+ /* set date */
+ nw = time (NULL);
+ localtime_r (&nw, &stm);
+ strftime (buffer, 255, "Date: %a, %d %b %y %T GMT", &stm);
+ strcat (header, buffer);
+ strcat (header, "\r\n");
+
+ /* set content-type */
+ /*
+ * if (res->content_type[0] == '\0') { strcat(header, "Content-Type:
+ * text/html\r\n"); } else { sprintf(buffer, "Content-Type: %s\r\n",
+ * res->content_type); strcat(header, buffer); }
+ */
+
+ /* set server name */
+ strcat (header, "Server: Nano HTTPD library\r\n");
+
+ /* set _httpd_connection status */
+ strcat (header, "Connection: close\r\n");
+
+ /* add pairs */
+ cur = pair;
+ while (cur != NULL)
+ {
+ sprintf (buffer, "%s: %s\r\n", cur->key, cur->value);
+ strcat (header, buffer);
+ cur = cur->next;
+ }
+
+ /* set end of header */
+ strcat (header, "\r\n");
+
+ /* send header */
+ status = hsocket_nsend (res->sock, header, strlen (header));
+
+ return status;
}
int
-httpd_send_internal_error(httpd_conn_t * conn, const char *errmsg)
+httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg)
{
- const char *template1 =
- "<html><body><h3>Error!</h3><hr> Message: '%s' </body></html>\r\n";
+ const char *template1 =
+ "<html><body><h3>Error!</h3><hr> Message: '%s' </body></html>\r\n";
- char buffer[4064];
- sprintf(buffer, template1, errmsg);
- httpd_send_header(conn, 500, "INTERNAL", NULL);
- return send(conn->sock, buffer, strlen(buffer), 0);
+ char buffer[4064];
+ sprintf (buffer, template1, errmsg);
+ httpd_send_header (conn, 500, "INTERNAL", NULL);
+ return send (conn->sock, buffer, strlen (buffer), 0);
}
/*
- * ----------------------------------------------------- FUNCTION:
- * httpd_request_print -----------------------------------------------------
+ * -----------------------------------------------------
+ * FUNCTION: httpd_request_print
+ * -----------------------------------------------------
*/
static void
-httpd_request_print(hrequest_t * req)
+httpd_request_print (hrequest_t * req)
{
- hpair_t *pair;
-
- log_verbose1("++++++ Request +++++++++");
- log_verbose2(" Method : '%s'", req->method);
- log_verbose2(" Path : '%s'", req->path);
- log_verbose2(" Spec : '%s'", req->spec);
- log_verbose1(" Parsed query string :");
-
- pair = req->query;
- while (pair != NULL) {
- log_verbose3(" %s = '%s'", pair->key, pair->value);
- pair = pair->next;
- }
- log_verbose1("++++++++++++++++++++++++");
+ hpair_t *pair;
+
+ log_verbose1 ("++++++ Request +++++++++");
+ log_verbose2 (" Method : '%s'", req->method);
+ log_verbose2 (" Path : '%s'", req->path);
+ log_verbose2 (" Spec : '%s'", req->spec);
+ log_verbose1 (" Parsed query string :");
+
+ pair = req->query;
+ while (pair != NULL)
+ {
+ log_verbose3 (" %s = '%s'", pair->key, pair->value);
+ pair = pair->next;
+ }
+ log_verbose1 ("++++++++++++++++++++++++");
}
/*
- * ----------------------------------------------------- FUNCTION:
- * httpd_session_main -----------------------------------------------------
+ * -----------------------------------------------------
+ * FUNCTION: httpd_session_main
+ * -----------------------------------------------------
*/
#ifdef WIN32
static unsigned _stdcall
-httpd_session_main(void *data)
+httpd_session_main (void *data)
#else
-static void *
-httpd_session_main(void *data)
+static void *
+httpd_session_main (void *data)
#endif
{
- conndata_t *conn = (conndata_t *) data;
- const char *msg = "SESSION 1.0\n";
- int len = strlen(msg);
- char ch[2];
- char buffer[256]; /* temp buffer for recv() */
- char header[4064]; /* received header */
- int total; /* result from recv() */
- int headerreached = 0; /* whether reach header
- * "\n\n" */
- hrequest_t *req = NULL; /* only for test */
- httpd_conn_t *rconn;
- hservice_t *service = NULL;
- long content_length = 0;
-
- header[0] = '\0';
- len = 0;
-
-
- log_verbose1("starting httpd_session_main()");
- conn->atime = time((time_t) 0);
- while (len < 4064) {
- /* printf("receiving ...\n"); */
- total = recv(conn->sock, ch, 1, 0);
- if (total == 0)
- break;
- header[len] = ch[0];
- len++;
- if (len > 3) {
- if (!strncmp(&header[len - 4], "\r\n\r\n", 4)) {
- header[len] = '\0';
- break;
- }
- }
- }
-
- /* log_verbose2("=== HEADER ===\n%s\n============\n", header); */
- /* call the service */
- req = hrequest_new_from_buffer(header);
- httpd_request_print(req);
-
-
- rconn = (httpd_conn_t *) malloc(sizeof(httpd_conn_t));
- rconn->sock = conn->sock;
- rconn->content_type[0] = '\0';
-
- service = httpd_find_service(req->path);
- if (service != NULL) {
- log_verbose2("service '%s' found", req->path);
- if (service->func != NULL) {
- service->func(rconn, req);
- } else {
- sprintf(buffer,
- "service '%s' not registered properly (func == NULL)",
- req->path);
- log_verbose1(buffer);
- httpd_send_internal_error(rconn, buffer);
- }
- } else {
- sprintf(buffer, "service '%s' not found", req->path);
- log_verbose1(buffer);
- httpd_send_internal_error(rconn, buffer);
- }
-
- close(conn->sock);
- conn->sock = 0;
-
- /* httpd_response_free(res); */
- hrequest_free(req);
+ conndata_t *conn = (conndata_t *) data;
+ const char *msg = "SESSION 1.0\n";
+ int len = strlen (msg);
+ char ch[2];
+ char buffer[256]; /* temp buffer for recv() */
+ char header[4064]; /* received header */
+ int total; /* result from recv() */
+ int headerreached = 0; /* whether reach header * "\n\n" */
+ hrequest_t *req = NULL; /* only for test */
+ httpd_conn_t *rconn;
+ hservice_t *service = NULL;
+ long content_length = 0;
+
+ header[0] = '\0';
+ len = 0;
+
+
+ log_verbose1 ("starting httpd_session_main()");
+ conn->atime = time ((time_t) 0);
+ while (len < 4064)
+ {
+ /* printf("receiving ...\n"); */
+ total = recv (conn->sock, ch, 1, 0);
+ if (total == 0)
+ break;
+ header[len] = ch[0];
+ len++;
+ if (len > 3)
+ {
+ if (!strncmp (&header[len - 4], "\r\n\r\n", 4))
+ {
+ header[len] = '\0';
+ break;
+ }
+ }
+ }
+
+ /* log_verbose2("=== HEADER ===\n%s\n============\n", header); */
+ /* call the service */
+ req = hrequest_new_from_buffer (header);
+ httpd_request_print (req);
+
+
+ rconn = (httpd_conn_t *) malloc (sizeof (httpd_conn_t));
+ rconn->sock = conn->sock;
+ rconn->content_type[0] = '\0';
+
+ service = httpd_find_service (req->path);
+ if (service != NULL)
+ {
+ log_verbose2 ("service '%s' found", req->path);
+ if (service->func != NULL)
+ {
+ service->func (rconn, req);
+ }
+ else
+ {
+ sprintf (buffer,
+ "service '%s' not registered properly (func == NULL)",
+ req->path);
+ log_verbose1 (buffer);
+ httpd_send_internal_error (rconn, buffer);
+ }
+ }
+ else
+ {
+ sprintf (buffer, "service '%s' not found", req->path);
+ log_verbose1 (buffer);
+ httpd_send_internal_error (rconn, buffer);
+ }
+
+ close (conn->sock);
+ conn->sock = 0;
+
+ /* httpd_response_free(res); */
+ hrequest_free (req);
#ifdef WIN32
- CloseHandle((HANDLE) conn->tid);
- _endthread();
- return 0;
+ CloseHandle ((HANDLE) conn->tid);
+ _endthread ();
+ return 0;
#else
- pthread_exit(NULL);
- return service;
+ pthread_exit (NULL);
+ return service;
#endif
}
/*
- * ----------------------------------------------------- FUNCTION: httpd_term
+ * -----------------------------------------------------
+ * FUNCTION: httpd_term
* -----------------------------------------------------
*/
void
-httpd_term(int sig)
+httpd_term (int sig)
{
- if (sig == _httpd_terminate_signal)
- _httpd_run = 0;
+ if (sig == _httpd_terminate_signal)
+ _httpd_run = 0;
}
/*
- * ----------------------------------------------------- FUNCTION: httpd_run
+ * -----------------------------------------------------
+ * FUNCTION: httpd_run
* -----------------------------------------------------
*/
int
-httpd_run()
+httpd_run ()
{
- int err;
- fd_set fds;
- struct timeval timeout;
+ int err;
+ fd_set fds;
+ struct timeval timeout;
- log_verbose1("starting run routine");
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ log_verbose1 ("starting run routine");
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
- /* listen to port */
- err = hsocket_listen(_httpd_socket, 15);
- if (err != HSOCKET_OK) {
- log_error2("httpd_run(): '%d'", err);
- return err;
- }
- log_verbose2("registering termination signal handler (SIGNAL:%d)",
- _httpd_terminate_signal);
- signal(_httpd_terminate_signal, httpd_term);
- log_verbose2("listening to port '%d'", _httpd_port);
+ /* listen to port */
+ err = hsocket_listen (_httpd_socket, 15);
+ if (err != HSOCKET_OK)
+ {
+ log_error2 ("httpd_run(): '%d'", err);
+ return err;
+ }
+ log_verbose2 ("registering termination signal handler (SIGNAL:%d)",
+ _httpd_terminate_signal);
+ signal (_httpd_terminate_signal, httpd_term);
+ log_verbose2 ("listening to port '%d'", _httpd_port);
- err = hsocket_makenonblock(_httpd_socket);
- if (err != HSOCKET_OK) {
- log_error2("httpd_run(): '%d'", err);
- return err;
- }
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ err = hsocket_makenonblock (_httpd_socket);
+ if (err != HSOCKET_OK)
+ {
+ log_error2 ("httpd_run(): '%d'", err);
+ return err;
+ }
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
- while (_httpd_run) {
+ while (_httpd_run)
+ {
- FD_ZERO(&fds);
- FD_SET(_httpd_socket, &fds);
+ FD_ZERO (&fds);
+ FD_SET (_httpd_socket, &fds);
#ifndef WIN32
- select(1, &fds, NULL, NULL, &timeout);
+ select (1, &fds, NULL, NULL, &timeout);
#else
- if (select(1, &fds, NULL, NULL, &timeout) == SOCKET_ERROR) {
- err = WSAGetLastError();
- log_error1("select error");
- return -1;
- }
+ if (select (1, &fds, NULL, NULL, &timeout) == SOCKET_ERROR)
+ {
+ err = WSAGetLastError ();
+ log_error1 ("select error");
+ return -1;
+ }
#endif
- while (_httpd_run && (FD_ISSET(_httpd_socket, &fds)))
- if (!_httpd_run)
- break;
-
- if (hsocket_accept
- (_httpd_socket, httpd_session_main, _httpd_connection,
- _httpd_max_connections) != 0) {
- continue;
- }
- }
- free(_httpd_connection);
- return 0;
+ while (_httpd_run && (FD_ISSET (_httpd_socket, &fds)))
+ if (!_httpd_run)
+ break;
+
+ if (hsocket_accept
+ (_httpd_socket, httpd_session_main, _httpd_connection,
+ _httpd_max_connections) != 0)
+ {
+ continue;
+ }
+ }
+ free (_httpd_connection);
+ return 0;
}
-char *
-httpd_get_postdata(httpd_conn_t * conn, hrequest_t * req, long *received,
- long max)
+char *
+httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received,
+ long max)
{
- char *content_length_str;
- long content_length = 0;
- long total = 0;
- char *postdata = NULL;
-
- if (!strcmp(req->method, "POST")) {
-
- content_length_str =
- hpairnode_get_ignore_case(req->header, HEADER_CONTENT_LENGTH);
-
- if (content_length_str != NULL)
- content_length = atol(content_length_str);
-
- } else {
- log_warn1("Not a POST method");
- return NULL;
- }
-
- if (content_length > max && max != -1)
- return NULL;
-
- if (content_length == 0) {
- *received = 0;
- postdata = (char *) malloc(1);
- postdata[0] = '\0';
- return postdata;
- }
- postdata = (char *) malloc(content_length + 1);
- if (postdata == NULL) {
- log_error1("Not enough memory");
- return NULL;
- }
- if (hsocket_read(conn->sock, postdata,
- (int) content_length, 1) == HSOCKET_OK) {
- *received = content_length;
- postdata[content_length] = '\0';
- return postdata;
- }
- free(postdata);
- return NULL;
+ char *content_length_str;
+ long content_length = 0;
+ long total = 0;
+ char *postdata = NULL;
+
+ if (!strcmp (req->method, "POST"))
+ {
+
+ content_length_str =
+ hpairnode_get_ignore_case (req->header, HEADER_CONTENT_LENGTH);
+
+ if (content_length_str != NULL)
+ content_length = atol (content_length_str);
+
+ }
+ else
+ {
+ log_warn1 ("Not a POST method");
+ return NULL;
+ }
+
+ if (content_length > max && max != -1)
+ return NULL;
+
+ if (content_length == 0)
+ {
+ *received = 0;
+ postdata = (char *) malloc (1);
+ postdata[0] = '\0';
+ return postdata;
+ }
+ postdata = (char *) malloc (content_length + 1);
+ if (postdata == NULL)
+ {
+ log_error1 ("Not enough memory");
+ return NULL;
+ }
+ if (hsocket_read (conn->sock, postdata,
+ (int) content_length, 1) == HSOCKET_OK)
+ {
+ *received = content_length;
+ postdata[content_length] = '\0';
+ return postdata;
+ }
+ free (postdata);
+ return NULL;
}