summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar snowdrop2004-09-13 07:12:33 +0000
committerGravatar snowdrop2004-09-13 07:12:33 +0000
commit3a88be29ecb1a2a67e85d8b8d8649865901b9b86 (patch)
tree807a178ff1a08a3da77d53f180ffd1f4755f370b
parent8787eed7e2ebca3aad48d85f430769e179ee2c21 (diff)
downloadcsoap-3a88be29ecb1a2a67e85d8b8d8649865901b9b86.tar.gz
csoap-3a88be29ecb1a2a67e85d8b8d8649865901b9b86.tar.bz2
made win32 threaded httpd_run not threaded againr1_0_2_beta
-rw-r--r--examples/csoap/simpleserver.c188
-rw-r--r--nanohttp/nanohttp-server.c1102
2 files changed, 625 insertions, 665 deletions
diff --git a/examples/csoap/simpleserver.c b/examples/csoap/simpleserver.c
index f4b7bef..85ea78f 100644
--- a/examples/csoap/simpleserver.c
+++ b/examples/csoap/simpleserver.c
@@ -1,103 +1,91 @@
-/******************************************************************
- * $Id: simpleserver.c,v 1.7 2004/09/07 18:43:49 rans Exp $
- *
- * CSOAP Project: CSOAP examples project
- * Copyright (C) 2003 Ferhat Ayaz
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
- *
- * Email: ayaz@jprogrammer.net
- ******************************************************************/
-
-#include <libcsoap/soap-server.h>
-
-
-static const char *url = "/csoapserver";
-static const char *urn = "urn:examples";
-static const char *method = "sayHello";
-
-
-void add_name(xmlNodePtr node, SoapEnv *env)
-{
- char *name;
- name = (char*)xmlNodeListGetString(node->doc,
- node->xmlChildrenNode, 1);
-
-
- if (!name) return;
-
- soap_env_add_itemf(env,"xsd:string", "echo",
- "Hello '%s'", name);
-
- xmlFree(BAD_CAST name);
-
-}
-
-
-SoapEnv* say_hello(SoapEnv *request)
-{
-
- SoapEnv *env;
- xmlNodePtr method, node;
-
- env = soap_env_new_with_response(request);
-
- method = soap_env_get_method(request);
- node = soap_xml_get_children(method);
-
- while (node) {
- add_name(node, env);
- node = soap_xml_get_next(node);
- }
-
- return env;
-}
-
-
-int main(int argc, char *argv[])
-{
- char c;
- SoapRouter *router;
-
- log_set_level(HLOG_VERBOSE);
-
- if (!soap_server_init_args(argc, argv)) {
- return 1;
- }
-
+/******************************************************************
+ * $Id: simpleserver.c,v 1.8 2004/09/13 07:12:33 snowdrop Exp $
+ *
+ * CSOAP Project: CSOAP examples project
+ * Copyright (C) 2003 Ferhat Ayaz
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
+ *
+ * Email: ayaz@jprogrammer.net
+ ******************************************************************/
+
+#include <libcsoap/soap-server.h>
+
+
+static const char *url = "/csoapserver";
+static const char *urn = "urn:examples";
+static const char *method = "sayHello";
+
+
+void add_name(xmlNodePtr node, SoapEnv *env)
+{
+ char *name;
+ name = (char*)xmlNodeListGetString(node->doc,
+ node->xmlChildrenNode, 1);
+
+
+ if (!name) return;
+
+ soap_env_add_itemf(env,"xsd:string", "echo",
+ "Hello '%s'", name);
+
+ xmlFree(BAD_CAST name);
+
+}
+
+
+SoapEnv* say_hello(SoapEnv *request)
+{
+
+ SoapEnv *env;
+ xmlNodePtr method, node;
+
+ env = soap_env_new_with_response(request);
+
+ method = soap_env_get_method(request);
+ node = soap_xml_get_children(method);
+
+ while (node) {
+ add_name(node, env);
+ node = soap_xml_get_next(node);
+ }
+
+ return env;
+}
+
+
+int main(int argc, char *argv[])
+{
+
+ SoapRouter *router;
+
+ log_set_level(HLOG_VERBOSE);
+
+ if (!soap_server_init_args(argc, argv)) {
+ return 1;
+ }
+
router = soap_router_new();
soap_router_register_service(router, say_hello, method, urn);
soap_server_register_router(router, url);
-
-#ifndef WIN32
- log_info1("send SIGTERM to shutdown");
-#endif
- soap_server_run();
-
-#ifdef WIN32
- log_info1("press ENTER to continue!");
- gets(&c);
-#endif
-
- log_info1("shutting down\n");
- soap_server_destroy();
-
- return 0;
-}
-
-
-
-
-
+
+ log_info1("send SIGTERM to shutdown");
+ soap_server_run();
+
+ log_info1("shutting down\n");
+ soap_server_destroy();
+
+ return 0;
+} \ No newline at end of file
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index edf9290..36cdf3b 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,565 +1,537 @@
-/******************************************************************
-* $Id: nanohttp-server.c,v 1.18 2004/09/07 18:40:38 rans Exp $
-*
-* CSOAP Project: A http client/server library in C
-* Copyright (C) 2003 Ferhat Ayaz
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Library General Public
-* License as published by the Free Software Foundation; either
-* version 2 of the License, or (at your option) any later version.
-*
-* This library 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
-* Library General Public License for more details.
-*
-* You should have received a copy of the GNU Library General Public
-* License along with this library; if not, write to the
-* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-* Boston, MA 02111-1307, USA.
-*
-* Email: ayaz@jprogrammer.net
-******************************************************************/
-#include <nanohttp/nanohttp-server.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef WIN32
-/* According to POSIX 1003.1-2001 */
-#include <sys/select.h>
-
-/* According to earlier standards */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#endif
-
-/*
- * -----------------------------------------------------
- * nano httpd
- * internally globals
- * -----------------------------------------------------
- */
-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 conndata_t *_httpd_connection;
-
-#ifdef WIN32
-#include <nanohttp/nanohttp-windows.h>
-#endif
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_init
- * NOTE: This will be called from soap_server_init_args()
- * -----------------------------------------------------
- */
-int
-httpd_init (int argc, char *argv[])
-{
- int i, status;
- status = hsocket_module_init ();
- if (status != 0)
- return status;
-
- /* write argument information */
- log_verbose1 ("Arguments:");
- for (i = 0; i < argc; 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]);
- }
- }
-
- 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]));
- }
-
-#ifdef WIN32
- 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);
-
- return status;
-}
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_register
- * -----------------------------------------------------
- */
-
-int
-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;
-}
-
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_services
- * -----------------------------------------------------
- */
-hservice_t *
-httpd_services ()
-{
- return _httpd_services_head;
-}
-
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_find_service
- * -----------------------------------------------------
- */
-static hservice_t *
-httpd_find_service (const char *ctx)
-{
- hservice_t *cur = _httpd_services_head;
-
- while (cur != NULL)
- {
- if (!strcmp (cur->ctx, ctx))
- {
- return cur;
- }
- cur = cur->next;
- }
-
- return NULL;
-}
-
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_response_set_content_type
- * -----------------------------------------------------
- */
-void
-httpd_response_set_content_type (httpd_conn_t * res, const char *content_type)
-{
- strncpy (res->content_type, content_type, 25);
-}
-
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_response_send_header
- * -----------------------------------------------------
- */
-int
-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;
-}
-
-
-int
-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";
-
- 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
- * -----------------------------------------------------
- */
-static void
-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 ("++++++++++++++++++++++++");
-
-}
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_session_main
- * -----------------------------------------------------
- */
-#ifdef WIN32
-static unsigned _stdcall
-httpd_session_main (void *data)
-#else
-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);
-
-#ifdef WIN32
- CloseHandle ((HANDLE) conn->tid);
- _endthread ();
- return 0;
-#else
- pthread_exit (NULL);
- return service;
-#endif
-}
-
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_term
- * -----------------------------------------------------
- */
-void
-httpd_term (int sig)
-{
- if (sig == _httpd_terminate_signal)
- _httpd_run = 0;
-}
-
-static void __httpd_run(void *p)
-{
- int err;
- fd_set fds;
- struct timeval timeout;
-
-
- 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;
- }
- 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;
- }
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-
- while (_httpd_run)
- {
-
-#ifdef WIN32
- Sleep(10);
-#endif
- FD_ZERO (&fds);
- FD_SET (_httpd_socket, &fds);
-
-#ifndef WIN32
- select (1, &fds, NULL, NULL, &timeout);
-#else
- if (select (1, &fds, NULL, NULL, &timeout) == SOCKET_ERROR)
- {
- err = WSAGetLastError ();
- log_error1 ("select error");
- return;
- }
-#endif
-
- while (_httpd_run && (FD_ISSET (_httpd_socket, &fds)))
- {
- if (!_httpd_run)
- {
- break;
- }
-#ifdef WIN32
- else
- {
- Sleep(10);
- }
-#endif
- }
- if (hsocket_accept
- (_httpd_socket, httpd_session_main, _httpd_connection,
- _httpd_max_connections) != 0)
- {
- continue;
- }
- }
- free (_httpd_connection);
-#ifdef WIN32
- _endthread ();
-#endif
-}
-
-/*
- * -----------------------------------------------------
- * FUNCTION: httpd_run
- * -----------------------------------------------------
- */
-
-int
-httpd_run ()
-{
-#ifdef WIN32
- if (_beginthread (__httpd_run, 0, NULL) == -1)
- {
- log_error1 ("httpd_run thread failed to start");
- return (-1);
- }
-#else
- void *p;
- __httpd_run(p);
-#endif
-}
-
-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;
-}
+/******************************************************************
+* $Id: nanohttp-server.c,v 1.19 2004/09/13 07:12:36 snowdrop Exp $
+*
+* CSOAP Project: A http client/server library in C
+* Copyright (C) 2003 Ferhat Ayaz
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library 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
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public
+* License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA.
+*
+* Email: ayaz@jprogrammer.net
+******************************************************************/
+#include <nanohttp/nanohttp-server.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+/* According to POSIX 1003.1-2001 */
+#include <sys/select.h>
+
+/* According to earlier standards */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#endif
+
+/*
+ * -----------------------------------------------------
+ * nano httpd
+ * internally globals
+ * -----------------------------------------------------
+ */
+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 conndata_t *_httpd_connection;
+
+#ifdef WIN32
+#include <nanohttp/nanohttp-windows.h>
+#endif
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_init
+ * NOTE: This will be called from soap_server_init_args()
+ * -----------------------------------------------------
+ */
+int
+httpd_init (int argc, char *argv[])
+{
+ int i, status;
+ status = hsocket_module_init ();
+ if (status != 0)
+ return status;
+
+ /* write argument information */
+ log_verbose1 ("Arguments:");
+ for (i = 0; i < argc; 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]);
+ }
+ }
+
+ 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]));
+ }
+
+#ifdef WIN32
+ 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);
+
+ return status;
+}
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_register
+ * -----------------------------------------------------
+ */
+
+int
+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;
+}
+
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_services
+ * -----------------------------------------------------
+ */
+hservice_t *
+httpd_services ()
+{
+ return _httpd_services_head;
+}
+
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_find_service
+ * -----------------------------------------------------
+ */
+static hservice_t *
+httpd_find_service (const char *ctx)
+{
+ hservice_t *cur = _httpd_services_head;
+
+ while (cur != NULL)
+ {
+ if (!strcmp (cur->ctx, ctx))
+ {
+ return cur;
+ }
+ cur = cur->next;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_response_set_content_type
+ * -----------------------------------------------------
+ */
+void
+httpd_response_set_content_type (httpd_conn_t * res, const char *content_type)
+{
+ strncpy (res->content_type, content_type, 25);
+}
+
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_response_send_header
+ * -----------------------------------------------------
+ */
+int
+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;
+}
+
+
+int
+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";
+
+ 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
+ * -----------------------------------------------------
+ */
+static void
+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 ("++++++++++++++++++++++++");
+
+}
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_session_main
+ * -----------------------------------------------------
+ */
+#ifdef WIN32
+static unsigned _stdcall
+httpd_session_main (void *data)
+#else
+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);
+
+#ifdef WIN32
+ CloseHandle ((HANDLE) conn->tid);
+ _endthread ();
+ return 0;
+#else
+ pthread_exit (NULL);
+ return service;
+#endif
+}
+
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_term
+ * -----------------------------------------------------
+ */
+void
+httpd_term (int sig)
+{
+ if (sig == _httpd_terminate_signal)
+ _httpd_run = 0;
+}
+
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_run
+ * -----------------------------------------------------
+ */
+
+int
+httpd_run ()
+{
+ int err;
+ fd_set fds;
+ struct timeval timeout;
+
+
+ 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);
+
+
+ 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)
+ {
+
+ FD_ZERO (&fds);
+ FD_SET (_httpd_socket, &fds);
+
+#ifndef WIN32
+ select (1, &fds, NULL, NULL, &timeout);
+#else
+ 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;
+}
+
+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;
+} \ No newline at end of file