summaryrefslogtreecommitdiffstats
path: root/nanohttp/nanohttp-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'nanohttp/nanohttp-server.c')
-rw-r--r--nanohttp/nanohttp-server.c173
1 files changed, 120 insertions, 53 deletions
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index c099ed6..d1cda7c 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-server.c,v 1.34 2005/07/22 13:26:41 snowdrop Exp $
+* $Id: nanohttp-server.c,v 1.35 2005/12/19 14:06:16 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -22,6 +22,7 @@
* Email: ayaz@jprogrammer.net
******************************************************************/
#include <nanohttp/nanohttp-server.h>
+#include <nanohttp/nanohttp-ssl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -96,8 +97,12 @@ static conndata_t *_httpd_connection;
#ifdef WIN32
static void WSAReaper(void *x);
+#else
+sigset_t thrsigset;
#endif
+
+
/*
* -----------------------------------------------------
* FUNCTION: httpd_init
@@ -162,7 +167,10 @@ httpd_init (int argc, char *argv[])
#endif
/* create socket */
- hsocket_init (&_httpd_socket);
+ status = hsocket_init (&_httpd_socket);
+ if( status != H_OK ){
+ return status;
+ }
status = hsocket_bind (&_httpd_socket, _httpd_port);
return status;
@@ -292,7 +300,7 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text)
strcat (header, "Server: Nano HTTPD library\r\n");
/* set _httpd_connection status */
- strcat (header, "Connection: close\r\n");
+ //strcat (header, "Connection: close\r\n");
/* add pairs */
cur = res->header;
@@ -310,7 +318,7 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text)
status = hsocket_nsend (res->sock, header, strlen (header));
if (status != H_OK)
return status;
-
+
res->out = http_output_stream_new (res->sock, res->header);
return H_OK;
}
@@ -323,9 +331,15 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg)
"<html><body><h3>Error!</h3><hr> Message: '%s' </body></html>\r\n";
char buffer[4064];
+ char buflen[5];
sprintf (buffer, template1, errmsg);
+#ifdef WIN32
+#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2)
+#endif
+ snprintf(buflen, 5, "%d", strlen(buffer));
+ httpd_set_header (conn, HEADER_CONTENT_LENGTH, buflen);
httpd_send_header (conn, 500, "INTERNAL");
- return send (conn->sock, buffer, strlen (buffer), 0);
+ return hsocket_nsend (conn->sock, buffer, strlen (buffer));
}
/*
@@ -350,6 +364,13 @@ httpd_request_print (hrequest_t * req)
log_verbose3 (" %s = '%s'", pair->key, pair->value);
pair = pair->next;
}
+ log_verbose1 (" Parsed header :");
+ pair = req->header;
+ while (pair != NULL)
+ {
+ log_verbose3 (" %s = '%s'", pair->key, pair->value);
+ pair = pair->next;
+ }
log_verbose1 ("++++++++++++++++++++++++");
}
@@ -378,6 +399,23 @@ void httpd_free(httpd_conn_t *conn)
free(conn);
}
+void do_req_timeout(int signum){
+/*
+ struct sigaction req_timeout;
+ memset(&req_timeout, 0, sizeof(&req_timeout));
+ req_timeout.sa_handler=SIG_IGN;
+ sigaction(SIGALRM, &req_timeout, NULL);
+*/
+
+ // XXX this is not real pretty, is there a better way?
+ log_verbose1("Thread timeout.");
+#ifdef WIN32
+ _endthread ();
+ #else
+ pthread_exit(0);
+#endif
+}
+
/*
* -----------------------------------------------------
* FUNCTION: httpd_session_main
@@ -394,6 +432,7 @@ httpd_session_main (void *data)
conndata_t *conn = (conndata_t *) data;
const char *msg = "SESSION 1.0\n";
int len = strlen (msg);
+ int done=0;
char buffer[256]; /* temp buffer for recv() */
char header[4064]; /* received header */
hrequest_t *req = NULL; /* only for test */
@@ -404,55 +443,71 @@ httpd_session_main (void *data)
header[0] = '\0';
len = 0;
-
-
log_verbose1 ("starting httpd_session_main()");
conn->atime = time ((time_t) 0);
/* call the service */
/* req = hrequest_new_from_buffer (header);*/
- rconn = httpd_new(conn->sock);
- status = hrequest_new_from_socket (conn->sock, &req);
- if (status != H_OK)
- {
- httpd_send_internal_error (rconn, herror_message(status)/*"Request parse error!"*/);
- herror_release(status);
- }
- else
- {
- httpd_request_print (req);
+ do{
+ log_verbose1("starting HTTP request");
+ rconn = httpd_new(conn->sock);
+ status = hrequest_new_from_socket (conn->sock, &req);
- service = httpd_find_service (req->path);
- if (service != NULL)
- {
- log_verbose2 ("service '%s' found", req->path);
- if (service->func != NULL)
+ if (status != H_OK)
{
- service->func (rconn, req);
+ if(herror_code(status) != HSOCKET_SSL_CLOSE){
+ httpd_send_internal_error (rconn, herror_message(status)/*"Request parse error!"*/);
+ herror_release(status);
+ }
+ done=1;
}
else
{
- sprintf (buffer,
- "service '%s' not registered properly (func == NULL)",
- req->path);
- log_verbose1 (buffer);
- httpd_send_internal_error (rconn, buffer);
+ char *conn_str = hpairnode_get_ignore_case (req->header, HEADER_CONNECTION);
+#ifdef WIN32
+#define strncasecmp(s1, s2, num) strncmp(s1, s2, num)
+#endif
+ if(conn_str && strncasecmp( conn_str, "close",5 ) == 0){
+ done=1;
+ }
+ if(!done){
+ done = req->version==HTTP_1_0?1:0;
+ }
+ httpd_request_print (req);
+
+
+ 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);
+ }
+
+ /* httpd_response_free(res); */
+ /*hrequest_free (req);*/
}
- }
- else
- {
- sprintf (buffer, "service '%s' not found", req->path);
- log_verbose1 (buffer);
- httpd_send_internal_error (rconn, buffer);
- }
-
- /* httpd_response_free(res); */
- /*hrequest_free (req);*/
- }
+ }while(!done);
hsocket_close(conn->sock);
- conn->sock = 0;
+ conn->sock.sock = 0;
hrequest_free(req);
httpd_free(rconn);
#ifdef WIN32
@@ -513,7 +568,7 @@ void httpd_set_headers(httpd_conn_t *conn, hpair_t *header)
BOOL WINAPI
httpd_term (DWORD sig)
{
- log_debug2 ("Got signal %d", sig);
+ //log_debug2 ("Got signal %d", sig);
if (sig == _httpd_terminate_signal)
_httpd_run = 0;
return TRUE;
@@ -573,7 +628,7 @@ _httpd_wait_for_empty_conn ()
system_sleep (1);
i = 0;
}
- else if (_httpd_connection[i].sock == 0)
+ else if (_httpd_connection[i].sock.sock == 0)
{
break;
}
@@ -600,6 +655,7 @@ _httpd_start_thread (conndata_t * conn)
#ifdef PTHREAD_CREATE_DETACHED
pthread_attr_setdetachstate (&(conn->attr), PTHREAD_CREATE_DETACHED);
#endif
+ pthread_sigmask(SIG_BLOCK, &thrsigset, NULL);
err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main,
conn);
if (err)
@@ -625,10 +681,17 @@ httpd_run ()
fd_set fds;
struct timeval timeout;
+
log_verbose1 ("starting run routine");
timeout.tv_sec = 1;
timeout.tv_usec = 0;
+#ifdef WIN32
+#else
+ sigemptyset(&thrsigset);
+ sigaddset(&thrsigset, SIGALRM);
+#endif
+
/* listen to port */
err = hsocket_listen (_httpd_socket);
@@ -669,10 +732,10 @@ httpd_run ()
/* zero and set file descriptior */
FD_ZERO (&fds);
- FD_SET (_httpd_socket, &fds);
+ FD_SET (_httpd_socket.sock, &fds);
/* select socket descriptor */
- switch (select (_httpd_socket + 1, &fds, NULL, NULL, &timeout))
+ switch (select (_httpd_socket.sock + 1, &fds, NULL, NULL, &timeout))
{
case 0:
/* descriptor is not ready */
@@ -684,7 +747,7 @@ httpd_run ()
/* no nothing */
break;
}
- if (FD_ISSET (_httpd_socket, &fds))
+ if (FD_ISSET (_httpd_socket.sock, &fds))
{
break;
}
@@ -696,7 +759,13 @@ httpd_run ()
/* Accept a socket */
err = hsocket_accept (_httpd_socket, &(conn->sock));
- if (err != H_OK)
+ if (err != H_OK && herror_code(err) == SSL_ERROR_INIT) {
+ hsocket_close(conn->sock);
+ conn->sock.sock = -1;
+ conn->sock.ssl = NULL;
+ log_error1(herror_message(err));
+ continue;
+ } else if (err != H_OK)
{
log_error2 ("Can not accept socket: %s", herror_message(err));
return err; /* this is hard core! */
@@ -746,10 +815,10 @@ void WSAReaper(void *x)
(_httpd_connection[i].atime==0)) continue;
log_verbose3("Reaping socket %u from (runtime ~= %d seconds)",
_httpd_connection[i].sock, ctime-_httpd_connection[i].atime);
- shutdown(_httpd_connection[i].sock, 2);
- while (recv(_httpd_connection[i].sock, junk, sizeof(junk), 0)>0) { };
- closesocket(_httpd_connection[i].sock);
- _httpd_connection[i].sock = 0;
+ shutdown(_httpd_connection[i].sock.sock, 2);
+ while (recv(_httpd_connection[i].sock.sock, junk, sizeof(junk), 0)>0) { };
+ closesocket(_httpd_connection[i].sock.sock);
+ _httpd_connection[i].sock.sock = 0;
TerminateThread(_httpd_connection[i].tid, (DWORD)&rc);
CloseHandle(_httpd_connection[i].tid);
memset((char *)&_httpd_connection[i], 0, sizeof(_httpd_connection[i]));
@@ -849,9 +918,7 @@ httpd_mime_send_header (httpd_conn_t * conn,
/*
using sprintf instead of snprintf because visual c does not support snprintf
*/
-#ifdef WIN32
-#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2)
-#endif
+
sprintf (buffer, "multipart/related;");
if (related_type)