From 84693bb5f792e6d6accd1ad2e81fe6baeb4f4ea1 Mon Sep 17 00:00:00 2001 From: snowdrop Date: Mon, 19 Dec 2005 14:06:15 +0000 Subject: integrated with ssl (https) capability --- examples/csoap/Makefile.am | 3 +- libcsoap/soap-client.c | 25 +++--- libcsoap/soap-client.h | 4 +- libcsoap/soap-fault.c | 8 +- libcsoap/soap-server.c | 50 ++++++++--- nanohttp/Makefile.am | 3 +- nanohttp/nanohttp-client.c | 33 +++----- nanohttp/nanohttp-common.c | 65 +++++++++++---- nanohttp/nanohttp-common.h | 12 ++- nanohttp/nanohttp-request.c | 7 +- nanohttp/nanohttp-server.c | 173 ++++++++++++++++++++++++++------------ nanohttp/nanohttp-socket.c | 199 ++++++++++++++++++++++++++++++++++---------- nanohttp/nanohttp-socket.h | 15 +++- 13 files changed, 431 insertions(+), 166 deletions(-) diff --git a/examples/csoap/Makefile.am b/examples/csoap/Makefile.am index b129cff..c601791 100644 --- a/examples/csoap/Makefile.am +++ b/examples/csoap/Makefile.am @@ -1,11 +1,10 @@ noinst_PROGRAMS=simpleclient simpleserver echoattachments-client echoattachments-server - bin_PROGRAMS=soapclient INCLUDES=-I$(top_srcdir)/ $(LIBXML_CFLAGS) csoap_LDFLAG=-L$(top_builddir)/nanohttp -lnanohttp-$(GENERIC_API_VERSION) \ $(LIBSOCKET) $(LIBNSL) -lpthread\ - -L$(top_builddir)/libcsoap/ -lcsoap-$(GENERIC_API_VERSION) \ + -L$(top_builddir)/libcsoap/ -lcsoap-$(GENERIC_API_VERSION) -lssl\ $(LIBXML_LIBS) simpleclient_SOURCES=simpleclient.c diff --git a/libcsoap/soap-client.c b/libcsoap/soap-client.c index b015a9c..dfb6898 100644 --- a/libcsoap/soap-client.c +++ b/libcsoap/soap-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-client.c,v 1.17 2005/07/27 07:45:40 snowdrop Exp $ +* $Id: soap-client.c,v 1.18 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -103,6 +103,9 @@ soap_client_invoke(SoapCtx *call, SoapCtx** response, const char *url, const cha /* Transport via HTTP */ conn = httpc_new(); + if(!conn){ + return herror_new("soap_client_invoke", SOAP_ERROR_CLIENT_INIT, "Unable to create SOAP client!" ); + } conn->block = soap_client_get_blockmode(); /* Set soap action */ @@ -121,21 +124,21 @@ soap_client_invoke(SoapCtx *call, SoapCtx** response, const char *url, const cha status = httpc_post_begin(conn, url); if (status != H_OK) { - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } status = http_output_stream_write_string(conn->out, content); if (status != H_OK) { - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } status = httpc_post_end(conn, &res); if (status != H_OK) { - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } @@ -149,21 +152,21 @@ soap_client_invoke(SoapCtx *call, SoapCtx** response, const char *url, const cha sprintf(start_id, "289247829121218%d", counter++); status = httpc_mime_begin(conn, url, start_id, "", "text/xml"); if (status != H_OK) { - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } status = httpc_mime_next(conn, start_id, "text/xml", "binary"); if (status != H_OK) { - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } status = http_output_stream_write(conn->out, content, strlen(content)); if (status != H_OK) { - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } @@ -175,7 +178,7 @@ soap_client_invoke(SoapCtx *call, SoapCtx** response, const char *url, const cha part->content_type, part->transfer_encoding, part->filename); if (status != H_OK) { log_error2("Send file failed. Status:%d", status); - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } @@ -184,7 +187,7 @@ soap_client_invoke(SoapCtx *call, SoapCtx** response, const char *url, const cha status = httpc_mime_end(conn, &res); if (status != H_OK) { - httpc_close_free(conn); + httpc_free(conn); xmlBufferFree(buffer); return status; } @@ -197,7 +200,7 @@ soap_client_invoke(SoapCtx *call, SoapCtx** response, const char *url, const cha status = _soap_client_build_result(res, &res_env); if (status != H_OK) { hresponse_free(res); - httpc_close_free(conn); + httpc_free(conn); return status; } @@ -221,7 +224,7 @@ soap_client_invoke(SoapCtx *call, SoapCtx** response, const char *url, const cha hresponse_free(res); - httpc_close_free(conn); + httpc_free(conn); return H_OK; } diff --git a/libcsoap/soap-client.h b/libcsoap/soap-client.h index e0f79bf..b99d2aa 100644 --- a/libcsoap/soap-client.h +++ b/libcsoap/soap-client.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: soap-client.h,v 1.9 2004/11/02 23:09:26 snowdrop Exp $ + * $Id: soap-client.h,v 1.10 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -27,6 +27,8 @@ #include #include +#define SOAP_ERROR_CLIENT_INIT 5001 + /** Initializes the client side soap engine */ diff --git a/libcsoap/soap-fault.c b/libcsoap/soap-fault.c index a44ad37..eeb146d 100644 --- a/libcsoap/soap-fault.c +++ b/libcsoap/soap-fault.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-fault.c,v 1.5 2004/10/15 13:34:02 snowdrop Exp $ +* $Id: soap-fault.c,v 1.6 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -46,12 +46,12 @@ Parameters: " xmlns:xsi=\"%s\"" \ " xmlns:xsd=\"%s\">" \ " "\ - " "\ + " "\ " %s"\ " %s"\ " %s"\ - " %s"\ - " " \ + " %s"\ + " " \ " "\ "" diff --git a/libcsoap/soap-server.c b/libcsoap/soap-server.c index 8481bc3..591ecc0 100644 --- a/libcsoap/soap-server.c +++ b/libcsoap/soap-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-server.c,v 1.11 2005/07/30 12:43:12 snowdrop Exp $ +* $Id: soap-server.c,v 1.12 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -134,10 +134,12 @@ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) if (err != H_OK) { _soap_server_send_fault(conn, header, herror_message(err)); - if (env) soap_env_free(env); herror_release(err); + return; + } - } else if (env == NULL) { + + if (env == NULL) { _soap_server_send_fault(conn, header,"Can not receive POST data!"); @@ -165,14 +167,20 @@ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) if (!soap_env_find_urn(ctx->env, urn)) { _soap_server_send_fault(conn, header, "No URN found!"); + soap_ctx_free(ctx); + return; } else { log_verbose2("urn: '%s'", urn); + } if (!soap_env_find_methodname(ctx->env, method)) { _soap_server_send_fault(conn, header, "No method found!"); + soap_ctx_free(ctx); + return; }else { log_verbose2("method: '%s'", method); + } service = soap_router_find_service(router, urn, method); @@ -180,6 +188,8 @@ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) sprintf(buffer, "URN '%s' not found", urn); _soap_server_send_fault(conn, header, buffer); + soap_ctx_free(ctx); + return; } else { log_verbose2("func: %p", service->func); @@ -193,30 +203,33 @@ void soap_server_entry(httpd_conn_t *conn, hrequest_t *req) herror_message(err)); herror_release(err); _soap_server_send_fault(conn, header, buffer); + soap_ctx_free(ctx); + return; + } - } else if (ctxres->env == NULL) { + if (ctxres->env == NULL) { sprintf(buffer, "Service '%s' returned no envelope", urn); _soap_server_send_fault(conn, header, buffer); + soap_ctx_free(ctx); + return; + } else { /* httpd_send_header(conn, 200, "OK"); _soap_server_send_env(conn->out, ctxres->env); */ _soap_server_send_ctx(conn, ctxres); - } /* free envctx */ soap_ctx_free(ctxres); + } } - } - } } } soap_ctx_free(ctx); } - hpairnode_free (header); } @@ -252,8 +265,26 @@ void _soap_server_send_ctx(httpd_conn_t* conn, SoapCtx *ctx) } else { - httpd_send_header(conn, 200, "OK"); + char buflen[100]; + xmlXPathContextPtr xpathCtx; + xmlXPathObjectPtr xpathObj; + xpathCtx = xmlXPathNewContext(ctx->env->root->doc); + xpathObj = xmlXPathEvalExpression("//Fault", xpathCtx); +#ifdef WIN32 +#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) +#endif + snprintf(buflen,100,"%d", strlen((const char*)xmlBufferContent (buffer))); + httpd_set_header (conn, HEADER_CONTENT_LENGTH, buflen); + if((xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0){ + httpd_send_header(conn, 500, "FAILED"); + } else { + httpd_send_header(conn, 200, "OK"); + } + http_output_stream_write_string(conn->out, (const char*)xmlBufferContent(buffer)); + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + } xmlBufferFree(buffer); @@ -307,7 +338,6 @@ void _soap_server_send_fault(httpd_conn_t *conn, hpair_t *header, herror_release(err); } else { _soap_server_send_env(conn->out, envres); - soap_env_free(envres); } } diff --git a/nanohttp/Makefile.am b/nanohttp/Makefile.am index c59e0f8..e071566 100644 --- a/nanohttp/Makefile.am +++ b/nanohttp/Makefile.am @@ -17,7 +17,8 @@ nanohttp-server.c\ nanohttp-stream.c\ nanohttp-mime.c\ nanohttp-request.c\ -nanohttp-response.c +nanohttp-response.c\ +nanohttp-ssl.c library_includedir=$(includedir)/$(NANOHTTP_LIBRARY_NAME)-$(NANOHTTP_API_VERSION)/$(NANOHTTP_LIBRARY_NAME) diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c index fc1d8f5..79d6b0a 100644 --- a/nanohttp/nanohttp-client.c +++ b/nanohttp/nanohttp-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-client.c,v 1.28 2005/07/27 07:45:56 snowdrop Exp $ +* $Id: nanohttp-client.c,v 1.29 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -81,7 +81,9 @@ httpc_new() static int counter = 10000; httpc_conn_t *res = (httpc_conn_t *) malloc(sizeof(httpc_conn_t)); - hsocket_init(&res->sock); + if(hsocket_init(&res->sock)!= H_OK){ + return NULL; + } res->header = NULL; res->version = HTTP_1_1; res->out = NULL; @@ -92,19 +94,6 @@ httpc_new() return res; } -/*-------------------------------------------------- -FUNCTION: httpc_close_free -DESC: Close and free the given http client object. -----------------------------------------------------*/ -void -httpc_close_free(httpc_conn_t * conn) -{ - if (conn == NULL) - return; - - hsocket_close(conn->sock); - httpc_free(conn); -} /*-------------------------------------------------- FUNCTION: httpc_free @@ -316,11 +305,14 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, if (status != H_OK) { return status; } - status = hsocket_block(conn->sock, conn->block); - if (status != H_OK) { - log_error1("Cannot make socket non-blocking"); - return status; - } + /* TODO XXX XXX this is probably not right -- matt */ + if(!&conn->sock.ssl){ + status = hsocket_block(conn->sock, conn->block); + if (status != H_OK) { + log_error1("Cannot make socket non-blocking"); + return status; + } + } /* check method */ if (method == HTTP_REQUEST_GET) { @@ -344,6 +336,7 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); } + log_verbose1("Sending header..."); status = hsocket_send(conn->sock, buffer); if (status != H_OK) { log_error2("Can not send request (status:%d)", status); diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c index b59a4d4..a6111e6 100644 --- a/nanohttp/nanohttp-common.c +++ b/nanohttp/nanohttp-common.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-common.c,v 1.18 2005/05/27 19:28:15 snowdrop Exp $ +* $Id: nanohttp-common.c,v 1.19 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -41,6 +41,11 @@ static char _hoption_table[MAX_OPTION_SIZE][MAX_OPTION_VALUE_SIZE]; +extern char *SSLCert; +extern char *SSLPass; +extern char *SSLCA; +extern int SSLCertLess; + /* option stuff */ void hoption_set(int opt, const char* value) { @@ -81,6 +86,22 @@ void hoption_init_args(int argc, char* argv[]) { log_set_file(argv[i+1]); } + else if (!strcmp (argv[i], NHTTP_ARG_CERT) && i < argc - 1) + { + SSLCert = argv[i + 1]; + } + else if (!strcmp (argv[i], NHTTP_ARG_CERTPASS) && i < argc - 1) + { + SSLPass = argv[i + 1]; + } + else if (!strcmp (argv[i], NHTTP_ARG_CA) && i < argc - 1) + { + SSLCA = argv[i + 1]; + } + else if (!strcmp (argv[i], NHTTP_ARG_HTTPS) ) + { + SSLCertLess = 1; + } } @@ -158,6 +179,7 @@ void herror_release(herror_t err) static log_level_t loglevel = HLOG_DEBUG; static char logfile[75] = {'\0'}; +static int log_background=0; log_level_t log_set_level(log_level_t level) @@ -183,6 +205,11 @@ void log_set_file(const char *filename) logfile[0] = '\0'; } +void log_set_background(int state) +{ + log_background=state; +} + char *log_get_file() { if (logfile[0] == '\0') return NULL; @@ -201,19 +228,29 @@ log_write(log_level_t level, const char *prefix, if (level < loglevel) return; - sprintf(buffer, "*%s*: [%s] %s\n", prefix, func, format); - vsprintf(buffer2, buffer, ap); - printf(buffer2); - fflush(stdout); - - if (log_get_file()) { - f = fopen(log_get_file(), "a"); - if (!f) f = fopen(log_get_file(), "w"); - if (f) { - fprintf(f, buffer2); - fflush(f); - fclose(f); - } + if(!log_background || log_get_file()){ +#ifdef WIN32 + sprintf(buffer, "*%s*: [%s] %s\n", + prefix, func, format); +#else + sprintf(buffer, "*%s*:(%d) [%s] %s\n", + prefix, pthread_self(),func, format); +#endif + vsprintf(buffer2, buffer, ap); + if(!log_background){ + printf(buffer2); + fflush(stdout); + } + + if (log_get_file()) { + f = fopen(log_get_file(), "a"); + if (!f) f = fopen(log_get_file(), "w"); + if (f) { + fprintf(f, buffer2); + fflush(f); + fclose(f); + } + } } } diff --git a/nanohttp/nanohttp-common.h b/nanohttp/nanohttp-common.h index ef025a6..f23d165 100644 --- a/nanohttp/nanohttp-common.h +++ b/nanohttp/nanohttp-common.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-common.h,v 1.19 2005/07/23 23:14:31 snowdrop Exp $ + * $Id: nanohttp-common.h,v 1.20 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -46,6 +46,11 @@ #define NHTTP_ARG_LOGFILE "-NHTTPlog" #define NHTTP_ARG_TMPDIR "-NHTTPtmpdir" +#define NHTTP_ARG_CERT "-NHTTPcert" +#define NHTTP_ARG_CERTPASS "-NHTTPcertpass" +#define NHTTP_ARG_CA "-NHTTPCA" +#define NHTTP_ARG_HTTPS "-NHTTPS" + #ifndef SAVE_STR #define SAVE_STR(str) ((str==0)?("(null)"):(str)) #endif @@ -100,6 +105,7 @@ #define HSOCKET_ERROR_ACCEPT 1008 #define HSOCKET_ERROR_NOT_INITIALIZED 1009 #define HSOCKET_ERROR_IOCTL 1010 +#define HSOCKET_SSL_CLOSE 1011 /* URL errors */ #define URL_ERROR_UNKNOWN_PROTOCOL 1101 @@ -132,6 +138,9 @@ #define XML_ERROR_EMPTY_DOCUMENT 1600 #define XML_ERROR_PARSE 1601 +/* SSL Errors */ +#define SSL_ERROR_INIT 1700 + /* Set Sleep function platform depended */ @@ -459,7 +468,6 @@ void hoption_init_args(int argc, char* argv[]); void hoption_set(int opt, const char* value); char *hoption_get(int opt); - /* logging stuff */ typedef enum log_level { diff --git a/nanohttp/nanohttp-request.c b/nanohttp/nanohttp-request.c index 6597c10..9f4fb8b 100755 --- a/nanohttp/nanohttp-request.c +++ b/nanohttp/nanohttp-request.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-request.c,v 1.5 2005/05/27 19:28:15 snowdrop Exp $ +* $Id: nanohttp-request.c,v 1.6 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -228,13 +228,16 @@ hrequest_new_from_socket(hsocket_t sock, hrequest_t **out) char buffer[MAX_HEADER_SIZE+1]; attachments_t *mimeMessage; + memset(buffer, 0, MAX_HEADER_SIZE); /* Read header */ while (i +#include #include #include @@ -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) "

Error!


Message: '%s' \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) diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c index 69b17f3..5213b11 100644 --- a/nanohttp/nanohttp-socket.c +++ b/nanohttp/nanohttp-socket.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-socket.c,v 1.34 2005/07/27 07:45:57 snowdrop Exp $ +* $Id: nanohttp-socket.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 @@ -23,6 +23,7 @@ ******************************************************************/ #include #include +#include #ifdef WIN32 #include "wsockcompat.h" @@ -75,6 +76,11 @@ #define errno WSAGetLastError() #endif +SSL_CTX* SSLctx = NULL; +char *SSLCert = NULL; +char *SSLPass = NULL; +char *SSLCA = NULL; +int SSLCertLess = 0; /*-------------------------------------------------- @@ -113,10 +119,19 @@ hsocket_module_destroy () FUNCTION: hsocket_init ----------------------------------------------------*/ herror_t -hsocket_init (hsocket_t * sock) +hsocket_init (hsocket_t * sock ) { + log_verbose1("Starting hsocket init"); /* just set the descriptor to -1 */ - *sock = -1; + sock->sock = -1; + sock->ssl = NULL; + if(SSLCert || SSLCertLess){ + log_verbose1("calling init ctx"); + SSLctx=initialize_ctx( SSLCert,SSLPass,SSLCA); + if(SSLctx==NULL){ + return herror_new("hsocket_init", HSOCKET_ERROR_CONNECT, "Unable to initialize SSL CTX" ); + } + } return H_OK; } @@ -140,8 +155,8 @@ hsocket_open (hsocket_t * dsock, const char *hostname, int port) struct sockaddr_in address; struct hostent *host; - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock <= 0) + sock.sock = socket (AF_INET, SOCK_STREAM, 0); + if (sock.sock <= 0) return herror_new("hsocket_open", HSOCKET_ERROR_CREATE, "Socket error: %d", errno); /* Get host data */ @@ -157,11 +172,16 @@ hsocket_open (hsocket_t * dsock, const char *hostname, int port) address.sin_port = htons((unsigned short)port); /* connect to the server */ - if (connect (sock, (struct sockaddr *) &address, sizeof (address)) != 0) -/* return herror_new("hsocket_open", HSOCKET_ERROR_CONNECT, "Connect to '%s:%d' failed", hostname, port);*/ + if (connect (sock.sock, (struct sockaddr *) &address, sizeof (address)) != 0) return herror_new("hsocket_open", HSOCKET_ERROR_CONNECT, "Socket error: %d", errno); - *dsock = sock; + if( !SSLctx ){ + log_verbose1("Using HTTP"); + dsock->sock = sock.sock; + } else { + log_verbose1("Using HTTPS"); + dsock->ssl = init_ssl(SSLctx, sock.sock, SSL_CLIENT); + } return H_OK; } @@ -173,14 +193,17 @@ hsocket_bind (hsocket_t * dsock, int port) { hsocket_t sock; struct sockaddr_in addr; + int opt=1; /* create socket */ - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock == -1) + sock.sock = socket (AF_INET, SOCK_STREAM, 0); + if (sock.sock == -1) { log_error3 ("Can not create socket: '%s'", "Socket error: %d", errno); return herror_new("hsocket_bind", HSOCKET_ERROR_CREATE, "Socket error: %d", errno); } + + setsockopt( sock.sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) ); /* bind socket */ addr.sin_family = AF_INET; addr.sin_port = htons ((unsigned short)port); /* short, network byte order */ @@ -188,12 +211,12 @@ hsocket_bind (hsocket_t * dsock, int port) memset (&(addr.sin_zero), '\0', 8); /* zero the rest of the * struct */ - if (bind (sock, (struct sockaddr *) &addr, sizeof (struct sockaddr)) == -1) + if (bind (sock.sock, (struct sockaddr *) &addr, sizeof (struct sockaddr)) == -1) { log_error3 ("Can not bind: '%s'", "Socket error: %d", errno); return herror_new("hsocket_bind", HSOCKET_ERROR_BIND, "Socket error: %d", errno); } - *dsock = sock; + dsock->sock = sock.sock; return H_OK; } @@ -207,7 +230,7 @@ hsocket_accept (hsocket_t sock, hsocket_t * dest) hsocket_t sockfd; struct sockaddr_in addr; - if (sock <= 0) + if (sock.sock <= 0) return herror_new("hsocket_accept", HSOCKET_ERROR_NOT_INITIALIZED, "Called hsocket_listen() before initializing!"); @@ -215,8 +238,8 @@ hsocket_accept (hsocket_t sock, hsocket_t * dest) #ifdef WIN32 while (1) { - sockfd = accept (sock, (struct sockaddr *) &addr, &asize); - if (sockfd == INVALID_SOCKET) { + sockfd.sock = accept (sock.sock, (struct sockaddr *) &addr, &asize); + if (sockfd.sock == INVALID_SOCKET) { if (WSAGetLastError () != WSAEWOULDBLOCK) return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, "Socket error: %d", errno); } else { @@ -225,17 +248,28 @@ hsocket_accept (hsocket_t sock, hsocket_t * dest) } #else /* TODO (#1#): why not a loop like in win32? */ - sockfd = accept (sock, (struct sockaddr *) &addr, &asize); - if (sockfd == -1) { + sockfd.sock = accept (sock.sock, (struct sockaddr *) &addr, &asize); + if (sockfd.sock == -1) { return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, "Socket error: %d", errno); } #endif /* TODO (#1#): Write to access.log file */ - log_verbose3 ("accept new socket (%d) from '%s'", sockfd, + log_verbose3 ("accept new socket (%d) from '%s'", sockfd.sock, SAVE_STR (((char *) inet_ntoa (addr.sin_addr)))); - *dest = sockfd; + if( !SSLctx ){ + log_verbose1("Using HTTP"); + dest->sock = sockfd.sock; + } else { + log_verbose1("Using HTTPS"); + dest->ssl = init_ssl(SSLctx, sockfd.sock, SSL_SERVER); + dest->sock = sockfd.sock; + hsocket_block (sockfd, 0); + if( dest->ssl == NULL ){ + return herror_new("hsocket_accept", SSL_ERROR_INIT, "Unable to initialize SSL"); + } + } return H_OK; } @@ -245,11 +279,11 @@ FUNCTION: hsocket_listen herror_t hsocket_listen (hsocket_t sock) { - if (sock <= 0) + if (sock.sock <= 0) return herror_new("hsocket_listen", HSOCKET_ERROR_NOT_INITIALIZED, "Called hsocket_listen() before initializing!"); - if (listen (sock, 15) == -1) + if (listen (sock.sock, 15) == -1) { log_error3 ("Can not listen: '%s'", "Socket error: %d", errno); return herror_new("hsocket_listen", HSOCKET_ERROR_LISTEN, "Socket error: %d", errno); @@ -305,7 +339,7 @@ hsocket_close (hsocket_t sock) { char junk[10]; /* _hsocket_wait_until_receive(sock);*/ - log_verbose1 ("closing socket ..."); + log_verbose2 ("closing socket %d...", sock.sock); /* struct linger _linger; hsocket_block(sock,1); @@ -313,20 +347,32 @@ hsocket_close (hsocket_t sock) _linger.l_linger = 30000; setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&_linger, sizeof(struct linger)); */ + + #ifdef WIN32 /*shutdown(sock,SD_RECEIVE);*/ - shutdown(sock, SD_SEND); - while (recv(sock, junk, sizeof(junk), 0)>0) { }; - closesocket(sock); + shutdown(sock.sock, SD_SEND); + while (recv(sock.sock, junk, sizeof(junk), 0)>0) { }; + closesocket(sock.sock); #else - shutdown(sock, SHUT_RDWR); - while (recv(sock, junk, sizeof(junk), 0)>0) { }; - close (sock); + /* XXX m. campbell - It seems like the while loop here needs this */ + fcntl( sock.sock, F_SETFL, O_NONBLOCK); + if( sock.ssl ){ + log_verbose1("Closing SSL"); + ssl_cleanup(sock.ssl); + shutdown(sock.sock, 1); + while (recv(sock.sock, junk, sizeof(junk), 0)>0) { }; + close (sock.sock); + }else { + shutdown(sock.sock, 1); + while (recv(sock.sock, junk, sizeof(junk), 0)>0) { }; + close (sock.sock); + } #endif - log_verbose1 ("closed"); + log_verbose1 ("socket closed"); } #if 0 @@ -348,16 +394,23 @@ hsocket_nsend (hsocket_t sock, const byte_t *bytes, int n) { int size; int total=0; - if (sock <= 0) + + log_verbose1( "Starting to send" ); + if (sock.sock <= 0 && !sock.ssl) return herror_new("hsocket_nsend", HSOCKET_ERROR_NOT_INITIALIZED, "Called hsocket_listen() before initializing!"); + //log_verbose2( "SENDING %s", bytes ); /* TODO (#1#): check return value and send again until n bytes sent */ - while (1) { - size = send((int) sock, bytes + total, n, 0); + if(sock.ssl){ + size = SSL_write(sock.ssl, bytes + total, n); + } else { + size = send((int) sock.sock, bytes + total, n, 0); + } + log_verbose2("Sent %d", size ); /* size = _test_send_to_file(filename, bytes, n);*/ #ifdef WIN32 if (size == INVALID_SOCKET) @@ -366,8 +419,13 @@ hsocket_nsend (hsocket_t sock, const byte_t *bytes, int n) else return herror_new("hsocket_nsend", HSOCKET_ERROR_SEND, "Socket error: %d", errno); #else - if (size == -1) + if (size == -1){ + if(sock.ssl){ + log_error1("Send error"); + log_ssl_error(sock.ssl, size); + } return herror_new("hsocket_nsend", HSOCKET_ERROR_SEND, "Socket error: %d", errno); + } #endif n -= size; total += size; @@ -400,9 +458,53 @@ hsocket_read (hsocket_t sock, byte_t *buffer, int total, int force, int *receive /* log_verbose3("Entering hsocket_read(total=%d,force=%d)", total, force); */ - do - { - status = recv(sock, &buffer[totalRead], total - totalRead, 0); + do { + if(sock.ssl){ + struct timeval timeout; + int i=0; + fd_set fds; + FD_ZERO (&fds); + FD_SET (sock.sock, &fds); + timeout.tv_sec = 10; + timeout.tv_usec = 0; +#ifdef WIN32 +#else + fcntl( sock.sock, F_SETFL, O_NONBLOCK); +#endif + // log_verbose1("START READ LOOP"); + //do{ + //log_verbose2("DEBUG A %d",i); + status = SSL_read(sock.ssl, &buffer[totalRead], total - totalRead); + if(status < 1){ + int ret = select (sock.sock + 1, &fds, NULL, NULL, &timeout); + //log_verbose2("DEBUG %d",ret); +#ifdef WIN32 + if (status == SOCKET_ERROR) + { + wsa_error = WSAGetLastError(); + log_error2("WSAGetLastError()=%d", wsa_error); + return herror_new("hsocket_read", HSOCKET_ERROR_RECEIVE, "Socket error: %d", errno); + + } +#endif + if(ret==0){ + log_verbose1("Socket timeout"); + return herror_new("hsocket_read", HSOCKET_SSL_CLOSE, "Timeout"); + } else { + //log_verbose1("DEBUG C"); + status = SSL_read(sock.ssl, &buffer[totalRead], total - totalRead); + } + //log_verbose3("DEBUG D char: %d status: %d", + // buffer[totalRead], SSL_get_error(sock.ssl, status)); + } + //} while( SSL_get_error(sock.ssl, status) == SSL_ERROR_WANT_READ); +#ifdef WIN32 +#else + fcntl( sock.sock, F_SETFL, 0); +#endif + } else { + status = recv(sock.sock, &buffer[totalRead], total - totalRead, 0); + } #ifdef WIN32 if (status == INVALID_SOCKET) @@ -429,6 +531,19 @@ hsocket_read (hsocket_t sock, byte_t *buffer, int total, int force, int *receive return true; } */ + + if( sock.ssl && status < 1 ){ + + // XXX I'm not sure this err_syscall is right here... + if( SSL_get_shutdown( sock.ssl ) == SSL_RECEIVED_SHUTDOWN || + SSL_get_error(sock.ssl, status) == SSL_ERROR_SYSCALL){ + *received = NULL;; + return herror_new("hsocket_read", HSOCKET_SSL_CLOSE, "SSL Closed"); + } + log_error2("Read error (%d)", status); + log_ssl_error( sock.ssl, status ); + return herror_new("hsocket_read", HSOCKET_ERROR_RECEIVE, "SSL Error"); + } if (status == -1) return herror_new("hsocket_read", HSOCKET_ERROR_RECEIVE, "Socket error: %d", errno); #endif @@ -450,8 +565,7 @@ hsocket_read (hsocket_t sock, byte_t *buffer, int total, int force, int *receive */ return H_OK; } - } - while (1); + } while (1); } @@ -462,7 +576,7 @@ hsocket_block(hsocket_t sock, int block) unsigned long iMode; #endif - if (sock <= 0) + if (sock.sock <= 0) return herror_new("hsocket_block", HSOCKET_ERROR_NOT_INITIALIZED, "Called hsocket_listen() before initializing!"); @@ -472,10 +586,11 @@ hsocket_block(hsocket_t sock, int block) */ iMode = (block==0)?1:0; /* Non block mode */ - if (ioctlsocket (sock, FIONBIO, (u_long FAR *) & iMode) == INVALID_SOCKET) + if (ioctlsocket (sock.sock, FIONBIO, (u_long FAR *) & iMode) == INVALID_SOCKET) { - log_error1 ("ioctlsocket error"); - return herror_new("hsocket_block", HSOCKET_ERROR_IOCTL, "Socket error: %d", errno); + int err = WSAGetLastError(); + log_error2 ("ioctlsocket error %d", err); + return herror_new("hsocket_block", HSOCKET_ERROR_IOCTL, "Socket error: %d", err); } #else /* fcntl(sock, F_SETFL, O_NONBLOCK); */ /* TODO (#1#): check for *nix the non blocking sockets */ diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h index e9a69f6..5613ac7 100644 --- a/nanohttp/nanohttp-socket.h +++ b/nanohttp/nanohttp-socket.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-socket.h,v 1.15 2004/11/02 23:09:27 snowdrop Exp $ + * $Id: nanohttp-socket.h,v 1.16 2005/12/19 14:06:16 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -27,6 +27,7 @@ #include #include +#include #ifdef WIN32 #include @@ -34,10 +35,16 @@ #ifdef WIN32 - typedef SOCKET hsocket_t; + typedef struct hsocket_t { + SSL *ssl; + SOCKET sock; + } hsocket_t; typedef int socklen_t; #else - typedef int hsocket_t; + typedef struct hsocket_t { + SSL *ssl; + int sock; + } hsocket_t; #endif @@ -66,7 +73,7 @@ void hsocket_module_destroy(); @returns This function should always return H_OK. */ -herror_t hsocket_init(hsocket_t *sock); +herror_t hsocket_init(hsocket_t *sock ); /** -- cgit v1.1-32-gdbae