diff options
Diffstat (limited to 'nanohttp')
-rw-r--r-- | nanohttp/nanohttp-client.c | 76 | ||||
-rw-r--r-- | nanohttp/nanohttp-client.h | 5 | ||||
-rw-r--r-- | nanohttp/nanohttp-common.c | 104 | ||||
-rw-r--r-- | nanohttp/nanohttp-common.h | 59 | ||||
-rwxr-xr-x | nanohttp/nanohttp-mime.c | 14 | ||||
-rwxr-xr-x | nanohttp/nanohttp-request.c | 25 | ||||
-rwxr-xr-x | nanohttp/nanohttp-request.h | 4 | ||||
-rwxr-xr-x | nanohttp/nanohttp-response.c | 9 | ||||
-rwxr-xr-x | nanohttp/nanohttp-response.h | 4 | ||||
-rw-r--r-- | nanohttp/nanohttp-server.c | 315 | ||||
-rw-r--r-- | nanohttp/nanohttp-server.h | 12 | ||||
-rw-r--r-- | nanohttp/nanohttp-socket.c | 453 | ||||
-rw-r--r-- | nanohttp/nanohttp-socket.h | 72 | ||||
-rw-r--r-- | nanohttp/nanohttp-ssl.c | 521 | ||||
-rw-r--r-- | nanohttp/nanohttp-ssl.h | 99 | ||||
-rwxr-xr-x | nanohttp/nanohttp-stream.c | 32 | ||||
-rwxr-xr-x | nanohttp/nanohttp-stream.h | 20 |
17 files changed, 815 insertions, 1009 deletions
diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c index 09605b9..32df75f 100644 --- a/nanohttp/nanohttp-client.c +++ b/nanohttp/nanohttp-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-client.c,v 1.39 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-client.c,v 1.40 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -51,6 +51,7 @@ #include "nanohttp-client.h" #include "nanohttp-socket.h" +#include "nanohttp-base64.h" /*-------------------------------------------------- FUNCTION: httpc_init @@ -58,11 +59,9 @@ DESC: Initialize http client connection NOTE: This will be called from soap_client_init_args() ----------------------------------------------------*/ herror_t -httpc_init(int argc, char *argv[]) +httpc_init(int argc, char **argv) { - hoption_init_args(argc, argv); - - return hsocket_module_init(); + return hsocket_module_init(argc, argv); } /*-------------------------------------------------- @@ -87,13 +86,17 @@ httpc_conn_t * httpc_new(void) { static int counter = 10000; + herror_t status; httpc_conn_t *res; if (!(res = (httpc_conn_t *) malloc(sizeof(httpc_conn_t)))) return NULL; - if (hsocket_init(&res->sock) != H_OK) + if ((status = hsocket_init(&res->sock)) != H_OK) + { + log_warn("hsocket_init failed (%s)", herror_message(status)); return NULL; + } res->header = NULL; res->version = HTTP_1_1; @@ -131,7 +134,7 @@ httpc_free(httpc_conn_t * conn) conn->out = NULL; } - hsocket_free(conn->sock); + hsocket_free(&(conn->sock)); free(conn); return; @@ -214,6 +217,42 @@ httpc_set_header(httpc_conn_t *conn, const char *key, const char *value) return 0; } +static int +_httpc_set_basic_authorization_header(httpc_conn_t *conn, const char *key, const char *user, const char *password) +{ + /* XXX: use malloc/free */ + char in[64], out[64]; + + if (!user) + user = ""; + + if (!password) + password = ""; + + memset(in, 0, 64); + memset(out, 0, 64); + + sprintf(in, "%s:%s", user, password); + + base64_encode(in, out); + + sprintf(in, "Basic %s", out); + + return httpc_set_header(conn, key, in); +} + +int +httpc_set_basic_authorization(httpc_conn_t *conn, const char *user, const char *password) +{ + return _httpc_set_basic_authorization_header(conn, HEADER_AUTHORIZATION, user, password); +} + +int +httpc_set_basic_proxy_authorization(httpc_conn_t *conn, const char *user, const char *password) +{ + return _httpc_set_basic_authorization_header(conn, HEADER_PROXY_AUTHORIZATION, user, password); +} + /*-------------------------------------------------- FUNCTION: httpc_header_set_date DESC: Adds the current date to the header. @@ -252,12 +291,12 @@ httpc_send_header(httpc_conn_t * conn) if (walker->key && walker->value) { sprintf(buffer, "%s: %s\r\n", walker->key, walker->value); - if ((status = hsocket_send(conn->sock, buffer)) != H_OK) + if ((status = hsocket_send(&(conn->sock), buffer)) != H_OK) return status; } } - return hsocket_send(conn->sock, "\r\n"); + return hsocket_send(&(conn->sock), "\r\n"); } /*-------------------------------------------------- @@ -313,6 +352,7 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, hurl_t url; char buffer[4096]; herror_t status; + int ssl; if (conn == NULL) { @@ -332,8 +372,10 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, /* Set hostname */ httpc_set_header(conn, HEADER_HOST, url.host); + ssl = url.protocol == PROTOCOL_HTTPS ? 1 : 0; + /* Open connection */ - if ((status = hsocket_open(&conn->sock, url.host, url.port)) != H_OK) + if ((status = hsocket_open(&conn->sock, url.host, url.port, ssl)) != H_OK) return status; switch(method) @@ -360,9 +402,9 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, } log_verbose1("Sending request..."); - if ((status = hsocket_send(conn->sock, buffer)) != H_OK) + if ((status = hsocket_send(&(conn->sock), buffer)) != H_OK) { - log_error2("Can not send request (status:%d)", status); + log_error2("Cannot send request (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } @@ -370,7 +412,7 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, log_verbose1("Sending header..."); if ((status = httpc_send_header(conn)) != H_OK) { - log_error2("Can not send header (status:%d)", status); + log_error2("Cannot send header (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } @@ -390,7 +432,7 @@ httpc_get(httpc_conn_t * conn, hresponse_t ** out, const char *urlstr) if ((status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr)) != H_OK) return status; - if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) + if ((status = hresponse_new_from_socket(&(conn->sock), out)) != H_OK) return status; return H_OK; @@ -409,7 +451,7 @@ httpc_post_begin(httpc_conn_t * conn, const char *url) if ((status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url)) != H_OK) return status; - conn->out = http_output_stream_new(conn->sock, conn->header); + conn->out = http_output_stream_new(&(conn->sock), conn->header); return H_OK; } @@ -428,7 +470,7 @@ httpc_post_end(httpc_conn_t * conn, hresponse_t ** out) if ((status = http_output_stream_flush(conn->out)) != H_OK) return status; - if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) + if ((status = hresponse_new_from_socket(&(conn->sock), out)) != H_OK) return status; return H_OK; @@ -548,7 +590,7 @@ httpc_mime_end(httpc_conn_t * conn, hresponse_t ** out) if ((status = http_output_stream_flush(conn->out)) != H_OK) return status; - if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) + if ((status = hresponse_new_from_socket(&(conn->sock), out)) != H_OK) return status; return H_OK; diff --git a/nanohttp/nanohttp-client.h b/nanohttp/nanohttp-client.h index 5562ea6..b37001a 100644 --- a/nanohttp/nanohttp-client.h +++ b/nanohttp/nanohttp-client.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-client.h,v 1.22 2006/02/27 22:26:02 snowdrop Exp $ + * $Id: nanohttp-client.h,v 1.23 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -93,6 +93,9 @@ int httpc_set_header(httpc_conn_t * conn, const char *key, const char *value); int httpc_add_header(httpc_conn_t *conn, const char *key, const char *value); void httpc_add_headers(httpc_conn_t *conn, const hpair_t *values); +int httpc_set_basic_authorization(httpc_conn_t *conn, const char *user, const char *password); +int httpc_set_basic_proxy_authorization(httpc_conn_t *conn, const char *user, const char *password); + /** Invoke a "GET" method request and receive the response */ diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c index f49cc85..b6f0e40 100644 --- a/nanohttp/nanohttp-common.c +++ b/nanohttp/nanohttp-common.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-common.c,v 1.28 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-common.c,v 1.29 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -55,11 +55,6 @@ #include "nanohttp-common.h" -#define MAX_OPTION_SIZE 50 -#define MAX_OPTION_VALUE_SIZE 150 - -static char _hoption_table[MAX_OPTION_SIZE][MAX_OPTION_VALUE_SIZE]; - static int strcmpigcase(const char *s1, const char *s2) { @@ -83,103 +78,6 @@ strcmpigcase(const char *s1, const char *s2) return 1; } -/* option stuff */ -void -hoption_set(int opt, const char *value) -{ - if (opt >= MAX_OPTION_SIZE) - { - log_warn3("Option to high (%d >= %d)", opt, MAX_OPTION_SIZE); - return; - } - - strncpy(_hoption_table[opt], value, MAX_OPTION_VALUE_SIZE); - - return; -} - - -char * -hoption_get(int opt) -{ - if (opt >= MAX_OPTION_SIZE) - { - log_warn3("Option to high (%d >= %d)", opt, MAX_OPTION_SIZE); - return ""; - } - - return _hoption_table[opt]; -} - - -void -hoption_init_args(int argc, char *argv[]) -{ - int i; - - hoption_set(HOPTION_TMP_DIR, "."); /* default value */ - hoption_set(HOPTION_SSL_CERT, ""); - hoption_set(HOPTION_SSL_PASS, ""); - hoption_set(HOPTION_SSL_CA, ""); - - /* initialize from arguments */ - for (i = 0; i < argc; i++) - { - if (!strcmp(argv[i], NHTTP_ARG_TMPDIR) && i < argc - 1) - { - hoption_set(HOPTION_TMP_DIR, argv[i + 1]); - } - else if (!strcmp(argv[i], NHTTP_ARG_LOGFILE) && i < argc - 1) - { - log_set_file(argv[i + 1]); - } - else if (!strcmp(argv[i], NHTTP_ARG_CERT) && i < argc - 1) - { -#ifndef HAVE_SSL - fprintf(stderr, - "WARNING: csoap compiled without '--with-ssl' flag. Parameter '%s' is disabled", - NHTTP_ARG_CERT); -#else - hoption_set(HOPTION_SSL_CERT, argv[i + 1]); -#endif - } - else if (!strcmp(argv[i], NHTTP_ARG_CERTPASS) && i < argc - 1) - { -#ifndef HAVE_SSL - fprintf(stderr, - "WARNING: csoap compiled without '--with-ssl' flag. Parameter '%s' is disabled", - NHTTP_ARG_CERTPASS); -#else - hoption_set(HOPTION_SSL_PASS, argv[i + 1]); -#endif - } - else if (!strcmp(argv[i], NHTTP_ARG_CA) && i < argc - 1) - { -#ifndef HAVE_SSL - fprintf(stderr, - "WARNING: csoap compiled without '--with-ssl' flag. Parameter '%s' is disabled", - NHTTP_ARG_CA); -#else - hoption_set(HOPTION_SSL_CA, argv[i + 1]); -#endif - } - else if (!strcmp(argv[i], NHTTP_ARG_HTTPS)) - { -#ifndef HAVE_SSL - fprintf(stderr, - "WARNING: csoap compiled without '--with-ssl' flag. Parameter '%s' is disabled", - NHTTP_ARG_HTTPS); -#else - /* TODO (#1#) handle ssl arguments */ - /*SSLCertLess = 1;*/ -#endif - } - } - - -} - - #ifdef WIN32 #ifndef __MINGW32__ diff --git a/nanohttp/nanohttp-common.h b/nanohttp/nanohttp-common.h index 307f349..afdaee6 100644 --- a/nanohttp/nanohttp-common.h +++ b/nanohttp/nanohttp-common.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-common.h,v 1.27 2006/02/27 22:26:02 snowdrop Exp $ + * $Id: nanohttp-common.h,v 1.28 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -27,31 +27,33 @@ #include <stdlib.h> #include <time.h> -#define HEADER_CONTENT_LENGTH "Content-Length" -#define HEADER_CONTENT_TYPE "Content-Type" -#define HEADER_CONTENT_ID "Content-Id" -#define HEADER_CONTENT_LOCATION "Content-Location" +#define HEADER_CONTENT_LENGTH "Content-Length" +#define HEADER_CONTENT_TYPE "Content-Type" +#define HEADER_CONTENT_ID "Content-Id" +#define HEADER_CONTENT_LOCATION "Content-Location" #define HEADER_CONTENT_TRANSFER_ENCODING "Content-Transfer-Encoding" -#define HEADER_TRANSFER_ENCODING "Transfer-Encoding" -#define HEADER_CONNECTION "Connection" +#define HEADER_TRANSFER_ENCODING "Transfer-Encoding" +#define HEADER_CONNECTION "Connection" -#define HEADER_HOST "Host" -#define HEADER_DATE "Date" -#define HEADER_ACCEPT "Accept" +#define HEADER_HOST "Host" +#define HEADER_DATE "Date" +#define HEADER_ACCEPT "Accept" -#define HEADER_AUTHORIZATION "Authorization" #define HEADER_WWW_AUTHENTICATE "WWW-Authenticate" +#define HEADER_PROXY_AUTHENTICATE "Proxy-Authenticate" +#define HEADER_AUTHORIZATION "Authorization" +#define HEADER_PROXY_AUTHORIZATION "Proxy-Authorization" -#define NHTTPD_ARG_PORT "-NHTTPport" -#define NHTTPD_ARG_TERMSIG "-NHTTPtsig" -#define NHTTPD_ARG_MAXCONN "-NHTTPmaxconn" -#define NHTTP_ARG_LOGFILE "-NHTTPlog" -#define NHTTP_ARG_TMPDIR "-NHTTPtmpdir" +#define NHTTPD_ARG_PORT "-NHTTPport" +#define NHTTPD_ARG_TERMSIG "-NHTTPtsig" +#define NHTTPD_ARG_MAXCONN "-NHTTPmaxconn" -#define NHTTP_ARG_CERT "-NHTTPcert" -#define NHTTP_ARG_CERTPASS "-NHTTPcertpass" -#define NHTTP_ARG_CA "-NHTTPCA" -#define NHTTP_ARG_HTTPS "-NHTTPS" +#define NHTTP_ARG_LOGFILE "-NHTTPlog" + +#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)) @@ -142,7 +144,13 @@ #define XML_ERROR_PARSE 1601 /* SSL Errors */ -/*#define SSL_ERROR_INIT 1700*/ +#define HSSL_ERROR_CA_LIST 1710 +#define HSSL_ERROR_CONTEXT 1720 +#define HSSL_ERROR_CERTIFICATE 1730 +#define HSSL_ERROR_PEM 1740 +#define HSSL_ERROR_CLIENT 1750 +#define HSSL_ERROR_SERVER 1760 +#define HSSL_ERROR_CONNECT 1770 /* Set Sleep function platform depended @@ -459,15 +467,6 @@ void attachments_free(attachments_t * message); void attachments_add_part(attachments_t * attachments, part_t * part); -/* tmp directory for multipart/related stuff */ -#define HOPTION_TMP_DIR 2 -#define HOPTION_SSL_CERT 3 -#define HOPTION_SSL_PASS 4 -#define HOPTION_SSL_CA 5 -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-mime.c b/nanohttp/nanohttp-mime.c index 5ab5592..4733dff 100755 --- a/nanohttp/nanohttp-mime.c +++ b/nanohttp/nanohttp-mime.c @@ -3,7 +3,7 @@ * | \/ | | | | \/ | | _/ * |_''_| |_| |_''_| |_'/ PARSER * -* $Id: nanohttp-mime.c,v 1.11 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-mime.c,v 1.12 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -298,7 +298,6 @@ MIME_parse(MIME_read_function reader_function, /* Read 1 byte */ status = MIME_reader_read(&reader, ch, 1); - _log_str("buffer.log", ch, 1); if (status == MIME_READ_EOF) return MIME_PARSER_INCOMPLETE_MESSAGE; else if (status == MIME_READ_ERROR) @@ -311,7 +310,6 @@ MIME_parse(MIME_read_function reader_function, { /* Read 1 byte */ status = MIME_reader_read(&reader, ch, 1); - _log_str("buffer.log", ch, 1); if (status == MIME_READ_EOF) return MIME_PARSER_INCOMPLETE_MESSAGE; else if (status == MIME_READ_ERROR) @@ -334,7 +332,6 @@ MIME_parse(MIME_read_function reader_function, /* Read 1 byte */ status = MIME_reader_read(&reader, ch, 1); - _log_str("buffer.log", ch, 1); if (status == MIME_READ_EOF) @@ -347,7 +344,6 @@ MIME_parse(MIME_read_function reader_function, { /* Read 1 byte */ status = MIME_reader_read(&reader, ch, 1); - _log_str("buffer.log", ch, 1); if (status == MIME_READ_EOF) @@ -381,7 +377,6 @@ MIME_parse(MIME_read_function reader_function, /* Jump to marker and read bytes */ MIME_reader_jump_marker(&reader); MIME_reader_read(&reader, ch, boundary_length + 2); - _log_str("buffer.log", ch, 1); MIME_buffer_add_bytes(&buffer, ch, boundary_length + 2); @@ -404,7 +399,6 @@ MIME_parse(MIME_read_function reader_function, { /* Read 1 byte */ status = MIME_reader_read(&reader, ch, 1); - _log_str("buffer.log", ch, 1); if (status == MIME_READ_EOF) return MIME_PARSER_INCOMPLETE_MESSAGE; @@ -533,8 +527,6 @@ mime_streamreader_function(void *userdata, unsigned char *dest, int *size) *size = readed; if (*size != -1) { - /* - _log_str("reader.log", dest, *size); */ return MIME_READ_OK; } return MIME_READ_ERROR; @@ -895,8 +887,6 @@ mime_message_parse_from_file(FILE * in, const char *root_id, } } - - herror_t mime_get_attachments(content_type_t * ctype, http_input_stream_t * in, attachments_t ** dest) @@ -930,7 +920,7 @@ mime_get_attachments(content_type_t * ctype, http_input_stream_t * in, } mimeMessage = - mime_message_parse(in, root_id, boundary, hoption_get(HOPTION_TMP_DIR)); + mime_message_parse(in, root_id, boundary, "."); if (mimeMessage == NULL) { /* TODO (#1#): Handle Error in http form */ diff --git a/nanohttp/nanohttp-request.c b/nanohttp/nanohttp-request.c index 1a3e998..97a2c21 100755 --- a/nanohttp/nanohttp-request.c +++ b/nanohttp/nanohttp-request.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-request.c,v 1.11 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-request.c,v 1.12 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -45,7 +45,7 @@ #include "nanohttp-request.h" static hrequest_t * -hrequest_new() +hrequest_new(void) { hrequest_t *req; @@ -228,7 +228,6 @@ hrequest_free(hrequest_t * req) if (req == NULL) return; - hpairnode_free_deep(req->header); hpairnode_free_deep(req->query); @@ -242,13 +241,15 @@ hrequest_free(hrequest_t * req) attachments_free(req->attachments); free(req); + + return; } herror_t -hrequest_new_from_socket(hsocket_t sock, hrequest_t ** out) +hrequest_new_from_socket(hsocket_t *sock, hrequest_t ** out) { - int i = 0, readed; + int i, readed; herror_t status; hrequest_t *req; char buffer[MAX_HEADER_SIZE + 1]; @@ -256,33 +257,29 @@ hrequest_new_from_socket(hsocket_t sock, hrequest_t ** out) memset(buffer, 0, MAX_HEADER_SIZE); /* Read header */ - while (i < MAX_HEADER_SIZE) + for(i=0; i < MAX_HEADER_SIZE; i++) { - status = hsocket_read(sock, &(buffer[i]), 1, 1, &readed); - if (status != H_OK) + if ((status = hsocket_read(sock, &(buffer[i]), 1, 1, &readed)) != H_OK) { - if (herror_code(status) != HSOCKET_ERROR_SSLCLOSE) - { - log_error1("Socket read error"); - } + log_error2("hsocket_read failed (%s)", herror_message(status)); return status; } buffer[i + 1] = '\0'; /* for strmp */ +// log_error2("buffer=\"%s\"", buffer); + if (i > 3) { if (!strcmp(&(buffer[i - 1]), "\n\n") || !strcmp(&(buffer[i - 2]), "\n\r\n")) break; } - i++; } /* Create response */ req = _hrequest_parse_header(buffer); - /* Create input stream */ req->in = http_input_stream_new(sock, req->header); diff --git a/nanohttp/nanohttp-request.h b/nanohttp/nanohttp-request.h index c0c014c..03cea1e 100755 --- a/nanohttp/nanohttp-request.h +++ b/nanohttp/nanohttp-request.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-request.h,v 1.6 2006/02/27 22:26:02 snowdrop Exp $ + * $Id: nanohttp-request.h,v 1.7 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -49,7 +49,7 @@ typedef struct hrequest extern "C" { #endif -herror_t hrequest_new_from_socket(hsocket_t sock, hrequest_t ** out); +herror_t hrequest_new_from_socket(hsocket_t *sock, hrequest_t ** out); void hrequest_free(hrequest_t * req); #ifdef __cplusplus diff --git a/nanohttp/nanohttp-response.c b/nanohttp/nanohttp-response.c index 64eac44..cb24d10 100755 --- a/nanohttp/nanohttp-response.c +++ b/nanohttp/nanohttp-response.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-response.c,v 1.9 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-response.c,v 1.10 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -146,9 +146,9 @@ _hresponse_parse_header(const char *buffer) herror_t -hresponse_new_from_socket(hsocket_t sock, hresponse_t ** out) +hresponse_new_from_socket(hsocket_t *sock, hresponse_t ** out) { - int i = 0, readed; + int i = 0, count; herror_t status; hresponse_t *res; attachments_t *mimeMessage; @@ -158,8 +158,7 @@ read_header: /* for errorcode: 100 (continue) */ /* Read header */ while (i < MAX_HEADER_SIZE) { - status = hsocket_read(sock, &(buffer[i]), 1, 1, &readed); - if (status != H_OK) + if ((status = hsocket_read(sock, &(buffer[i]), 1, 1, &count)) != H_OK) { log_error1("Socket read error"); return status; diff --git a/nanohttp/nanohttp-response.h b/nanohttp/nanohttp-response.h index 3b3f532..622ef63 100755 --- a/nanohttp/nanohttp-response.h +++ b/nanohttp/nanohttp-response.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-response.h,v 1.6 2006/02/27 22:26:02 snowdrop Exp $ + * $Id: nanohttp-response.h,v 1.7 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -47,7 +47,7 @@ typedef struct hresponse extern "C" { #endif -herror_t hresponse_new_from_socket(hsocket_t sock, hresponse_t ** out); +herror_t hresponse_new_from_socket(hsocket_t *sock, hresponse_t ** out); void hresponse_free(hresponse_t * res); #ifdef __cplusplus diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c index d60c797..9a2c721 100644 --- a/nanohttp/nanohttp-server.c +++ b/nanohttp/nanohttp-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-server.c,v 1.51 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-server.c,v 1.52 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -83,6 +83,7 @@ typedef struct _conndata { + volatile int flag; hsocket_t sock; #ifdef WIN32 HANDLE tid; @@ -91,8 +92,10 @@ typedef struct _conndata pthread_attr_t attr; #endif time_t atime; -} -conndata_t; +} conndata_t; + +#define CONNECTION_FREE 0 +#define CONNECTION_IN_USE 1 /* * ----------------------------------------------------- @@ -109,7 +112,12 @@ static int _httpd_max_connections = 20; static hservice_t *_httpd_services_default = NULL; static hservice_t *_httpd_services_head = NULL; static hservice_t *_httpd_services_tail = NULL; + static conndata_t *_httpd_connection; +static pthread_mutex_t _httpd_connection_lock; + +static int _httpd_enable_service_list = 0; +static int _httpd_enable_statistics = 0; #ifdef WIN32 static DWORD _httpd_terminate_signal = CTRL_C_EVENT; @@ -127,24 +135,19 @@ _httpd_parse_arguments(int argc, char **argv) { int i; - /* write argument information */ - log_verbose1 ("Arguments:"); - for (i = 0; i < argc; i++) - log_verbose3 ("argv[%i] = '%s'", i, SAVE_STR (argv[i])); - - for (i = 1; i < argc; i++) + for (i=1; i < argc; i++) { - if (!strcmp (argv[i-1], NHTTPD_ARG_PORT)) + if (!strcmp(argv[i-1], NHTTPD_ARG_PORT)) { - _httpd_port = atoi (argv[i]); + _httpd_port = atoi(argv[i]); } - else if (!strcmp (argv[i-1], NHTTPD_ARG_TERMSIG)) + else if (!strcmp(argv[i-1], NHTTPD_ARG_TERMSIG)) { - _httpd_terminate_signal = atoi (argv[i]); + _httpd_terminate_signal = atoi(argv[i]); } - else if (!strcmp (argv[i-1], NHTTPD_ARG_MAXCONN)) + else if (!strcmp(argv[i-1], NHTTPD_ARG_MAXCONN)) { - _httpd_max_connections = atoi (argv[i]); + _httpd_max_connections = atoi(argv[i]); } } @@ -153,6 +156,33 @@ _httpd_parse_arguments(int argc, char **argv) return; } + +static void +_httpd_connection_slots_init(void) +{ + int i; + + pthread_mutex_init(&_httpd_connection_lock, NULL); + _httpd_connection = calloc (_httpd_max_connections, sizeof (conndata_t)); + for (i = 0; i < _httpd_max_connections; i++) + hsocket_init(&(_httpd_connection[i].sock)); + + return; +} + +static void +_httpd_register_builtin_services(void) +{ + + if (_httpd_enable_service_list) +;// httpd_register("/httpd/services", _httpd_list_services); + + if (_httpd_enable_statistics) +;// httpd_register("/httpd/statistics", _httpd_statistics); + + return; +} + /* * ----------------------------------------------------- * FUNCTION: httpd_init @@ -162,29 +192,18 @@ _httpd_parse_arguments(int argc, char **argv) herror_t httpd_init (int argc, char *argv[]) { - int i; herror_t status; -#ifdef HAVE_SSL - char *SSLCert = NULL, *SSLPass = NULL, *SSLCA = NULL; -#endif - - /* XXX: two times argument parsing... */ - hoption_init_args (argc, argv); _httpd_parse_arguments(argc, argv); - if ((status = hsocket_module_init()) != H_OK) + if ((status = hsocket_module_init(argc, argv)) != H_OK) return status; log_verbose2 ("socket bind to port '%d'", _httpd_port); - /* init built-in services */ + _httpd_connection_slots_init(); - /* httpd_register("/httpd/list", service_list); */ - - _httpd_connection = calloc (_httpd_max_connections, sizeof (conndata_t)); - for (i = 0; i < _httpd_max_connections; i++) - hsocket_init(&(_httpd_connection[i].sock)); + _httpd_register_builtin_services(); #ifdef WIN32 /* @@ -194,29 +213,13 @@ httpd_init (int argc, char *argv[]) */ #endif - /* XXX: move SSL stuff to nanohttp-socket.c and handle this transparently */ -#ifdef HAVE_SSL - SSLCert = hoption_get(HOPTION_SSL_CERT); - SSLPass = hoption_get(HOPTION_SSL_PASS); - SSLCA = hoption_get(HOPTION_SSL_CA); - log_verbose3("SSL: %s %s", SSLCert, SSLCA); - if (SSLCert[0] != '\0'){ - - start_ssl(); - status = hsocket_init_ssl(&_httpd_socket, SSLCert, SSLPass, SSLCA); - } - else -#endif - { - status = hsocket_init (&_httpd_socket); - } - - if (status != H_OK) + if ((status = hsocket_init (&_httpd_socket)) != H_OK) { + log_error2("hsocket_init failed (%s)", herror_message(status)); return status; } - return hsocket_bind (&_httpd_socket, _httpd_port); + return hsocket_bind(&_httpd_socket, _httpd_port); } /* @@ -224,7 +227,6 @@ httpd_init (int argc, char *argv[]) * FUNCTION: httpd_register * ----------------------------------------------------- */ - int httpd_register_secure(const char *ctx, httpd_service func, httpd_auth auth) { @@ -268,7 +270,7 @@ httpd_register_default_secure(const char *ctx, httpd_service service, httpd_auth ret = httpd_register_secure(ctx, service, auth); - /* this is broken, but working */ + /* XXX: this is broken, but working */ _httpd_services_default = _httpd_services_tail; return ret; @@ -292,7 +294,7 @@ httpd_get_port(void) * ----------------------------------------------------- */ hservice_t * -httpd_services () +httpd_services(void) { return _httpd_services_head; } @@ -303,9 +305,11 @@ httpd_services () * ----------------------------------------------------- */ static void -hservice_free (hservice_t * service) +hservice_free(hservice_t * service) { free (service); + + return; } /* @@ -340,6 +344,8 @@ void httpd_response_set_content_type (httpd_conn_t * res, const char *content_type) { strncpy (res->content_type, content_type, 25); + + return; } @@ -414,7 +420,7 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg) httpd_set_header (conn, HEADER_CONTENT_LENGTH, buflen); httpd_send_header (conn, 500, "INTERNAL"); - return hsocket_nsend (conn->sock, buffer, strlen (buffer)); + return http_output_stream_write_string(conn->out, buffer); } /* @@ -449,7 +455,7 @@ httpd_request_print (hrequest_t * req) httpd_conn_t * -httpd_new (hsocket_t sock) +httpd_new (hsocket_t *sock) { httpd_conn_t *conn; @@ -512,17 +518,17 @@ static int _httpd_decode_authorization(const char *value, char **user, char **pa len = strlen(value) * 2; if (!(tmp = (char *)calloc(1, len))) { - log_error2("malloc failed (%s)", strerror(errno)); + log_error2("calloc failed (%s)", strerror(errno)); return -1; } value = strstr(value, " ") + 1; - log_error2("Authorization (base64) = \"%s\"", value); + log_verbose2("Authorization (base64) = \"%s\"", value); base64_decode(value, tmp); - log_error2("Authorization (ascii) = \"%s\"", tmp); + log_verbose2("Authorization (ascii) = \"%s\"", tmp); if ((tmp2 = strstr(tmp, ":"))) { @@ -584,81 +590,63 @@ static void * httpd_session_main (void *data) #endif { - 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 */ + hrequest_t *req; /* only for test */ conndata_t *conn; - httpd_conn_t *rconn = NULL; - hservice_t *service = NULL; + httpd_conn_t *rconn; + hservice_t *service; herror_t status; + int done; - header[0] = '\0'; - len = 0; conn = (conndata_t *) data; - log_verbose1 ("starting httpd_session_main()"); -#ifdef HAVE_SSL - if (!_httpd_socket.sslCtx) - { - log_verbose1 ("Using HTTP"); - } - else - { - log_verbose1 ("Using HTTPS"); - conn->sock.ssl = init_ssl (_httpd_socket.sslCtx, conn->sock.sock, SSL_SERVER); - hsocket_block (conn->sock, 0); - if (conn->sock.ssl == NULL) - { - done = 1; - } - } -#endif - conn->atime = time ((time_t) 0); - /* call the service */ -/* req = hrequest_new_from_buffer (header);*/ + log_verbose2("starting new httpd session on socket %d", conn->sock); - rconn = httpd_new (conn->sock); + rconn = httpd_new(&(conn->sock)); + done = 0; while (!done) { - log_verbose1 ("starting HTTP request"); + log_verbose2("starting HTTP request on socket %d", conn->sock); /* XXX: only used in WSAreaper */ conn->atime = time(NULL); - if ((status = hrequest_new_from_socket (conn->sock, &req)) != H_OK) + if ((status = hrequest_new_from_socket (&(conn->sock), &req)) != H_OK) { - /* "Request parse error!" */ - /* XXX: may be "socket read error" */ - if (herror_code (status) != HSOCKET_ERROR_SSLCLOSE) + int code; + + switch((code = herror_code(status))) { - httpd_send_internal_error (rconn, herror_message (status)); - herror_release (status); + case HSOCKET_ERROR_SSLCLOSE: + case HSOCKET_ERROR_RECEIVE: + log_error2("hrequest_new_from_socket failed (%s)", herror_message(status)); + break; + default: + httpd_send_internal_error(rconn, herror_message(status)); + break; } + herror_release(status); done = 1; } else { - char *conn_str = hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); + char *conn_str; + + httpd_request_print (req); + + conn_str = hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); if (conn_str && strncasecmp (conn_str, "close", 6) == 0) - { done = 1; - } + if (!done) - { done = req->version == HTTP_1_0 ? 1 : 0; - } - httpd_request_print (req); if ((service = httpd_find_service (req->path))) { log_verbose3 ("service '%s' for '%s' found", service->ctx, req->path); - if (_httpd_authenticate_request(req, service->auth)) { - + if (_httpd_authenticate_request(req, service->auth)) + { if (service->func != NULL) { service->func (rconn, req); @@ -669,20 +657,34 @@ httpd_session_main (void *data) } else { + char buffer[256]; + sprintf (buffer, "service '%s' not registered properly (func == NULL)", req->path); log_verbose1 (buffer); httpd_send_internal_error (rconn, buffer); } } - else { - - httpd_set_header(rconn, HEADER_WWW_AUTHENTICATE, "Basic realm=\"nanoHTTP\""); - httpd_send_header(rconn, 401, "Unauthorized"); - hsocket_send(conn->sock, "<html><head><title>Unauthorized</title></header><body><h1>Unauthorized request logged</h1></body></html>"); - } + else + { + char *template = + "<html>" + "<head>" + "<title>Unauthorized</title>" + "</head>" + "<body>" + "<h1>Unauthorized request logged</h1>" + "</body>" + "</html>"; + + httpd_set_header(rconn, HEADER_WWW_AUTHENTICATE, "Basic realm=\"nanoHTTP\""); + httpd_send_header(rconn, 401, "Unauthorized"); + http_output_stream_write_string(rconn->out, template); + done = 1; + } } else { + char buffer[256]; sprintf (buffer, "no service for '%s' found", req->path); log_verbose1 (buffer); httpd_send_internal_error (rconn, buffer); @@ -693,7 +695,7 @@ httpd_session_main (void *data) httpd_free(rconn); - hsocket_close (&(conn->sock)); + hsocket_close(&(conn->sock)); #ifdef WIN32 CloseHandle ((HANDLE) conn->tid); @@ -701,7 +703,7 @@ httpd_session_main (void *data) pthread_attr_destroy(&(conn->attr)); #endif - hsocket_init(&(conn->sock)); + conn->flag = CONNECTION_FREE; #ifdef WIN32 _endthread (); @@ -722,23 +724,19 @@ httpd_set_header (httpd_conn_t * conn, const char *key, const char *value) log_warn1 ("Connection object is NULL"); return 0; } - p = conn->header; - while (p != NULL) + + for (p=conn->header; p; p=p->next) { - if (p->key != NULL) + if (p->key && !strcmp(p->key, key)) { - if (!strcmp (p->key, key)) - { - free (p->value); - p->value = (char *) malloc (strlen (value) + 1); - strcpy (p->value, value); - return 1; - } + free (p->value); + p->value = strdup(value); + return 1; } - p = p->next; } conn->header = hpairnode_new (key, value, conn->header); + return 0; } @@ -795,19 +793,20 @@ httpd_term (DWORD sig) // log_debug2 ("Got signal %d", sig); if (sig == _httpd_terminate_signal) _httpd_run = 0; + return TRUE; } - #else - void httpd_term (int sig) { log_debug2 ("Got signal %d", sig); + if (sig == _httpd_terminate_signal) _httpd_run = 0; -} + return; +} #endif /* @@ -840,21 +839,28 @@ static conndata_t * _httpd_wait_for_empty_conn (void) { int i; + + pthread_mutex_lock(&_httpd_connection_lock); for (i = 0; ; i++) { - if (!_httpd_run) + if (!_httpd_run) { + + pthread_mutex_unlock(&_httpd_connection_lock); return NULL; + } if (i >= _httpd_max_connections) { system_sleep (1); i = -1; } - else if (_httpd_connection[i].sock.sock == HSOCKET_FREE) + else if (_httpd_connection[i].flag == CONNECTION_FREE) { + _httpd_connection[i].flag = CONNECTION_IN_USE; break; } } + pthread_mutex_unlock(&_httpd_connection_lock); return &_httpd_connection[i]; } @@ -879,10 +885,11 @@ _httpd_start_thread (conndata_t * conn) #endif pthread_sigmask (SIG_BLOCK, &thrsigset, NULL); - err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main, conn); - if (err) - log_error2 ("Error creating thread: ('%d')", err); + if ((err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main, conn))) + log_error2 ("pthread_create failed (%s)", strerror(err)); #endif + + return; } @@ -895,47 +902,32 @@ _httpd_start_thread (conndata_t * conn) herror_t httpd_run (void) { - herror_t err; + struct timeval timeout; conndata_t *conn; + herror_t err; fd_set fds; - struct timeval timeout; log_verbose1 ("starting run routine"); - timeout.tv_sec = 1; - timeout.tv_usec = 0; - #ifndef WIN32 sigemptyset (&thrsigset); sigaddset (&thrsigset, SIGALRM); #endif - /* listen to port */ - if ((err = hsocket_listen (_httpd_socket)) != H_OK) - { - log_error2 ("httpd_run(): '%d'", herror_message (err)); - return err; - } - log_verbose2 ("listening to port '%d'", _httpd_port); - - /* register signal handler */ _httpd_register_signal_handler (); - /* make the socket non blocking */ - if ((err = hsocket_block (_httpd_socket, 0)) != H_OK) + if ((err = hsocket_listen(&_httpd_socket)) != H_OK) { - log_error2 ("httpd_run(): '%s'", herror_message (err)); + log_error2 ("hsocket_listen failed (%s)", herror_message (err)); return err; } while (_httpd_run) { - /* Get an empty connection struct */ conn = _httpd_wait_for_empty_conn (); if (!_httpd_run) break; - /* Wait for a socket to accept */ while (_httpd_run) { @@ -971,30 +963,18 @@ httpd_run (void) if (!_httpd_run) break; - /* Accept a socket */ - err = hsocket_accept (_httpd_socket, &(conn->sock)); - if (err != H_OK - /* TODO (#1#) is this check neccessary? - && herror_code (err) == SSL_ERROR_INIT*/ - ) + if ((err = hsocket_accept(&_httpd_socket, &(conn->sock))) != H_OK) { - hsocket_close(&(conn->sock)); + log_error2("hsocket_accept failed (%s)", herror_message (err)); - hsocket_init(&(conn->sock)); + hsocket_close(&(conn->sock)); - 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! */ - } - /* Now start a thread */ _httpd_start_thread (conn); } - free (_httpd_connection); + return 0; } @@ -1012,6 +992,8 @@ httpd_destroy (void) hsocket_module_destroy (); + free (_httpd_connection); + return; } @@ -1239,8 +1221,7 @@ httpd_mime_send_file (httpd_conn_t * conn, const char *content_id, const char *c return herror_new ("httpd_mime_send_file", FILE_ERROR_READ, "Can not read from file '%d'", filename); } - status = http_output_stream_write (conn->out, buffer, size); - if (status != H_OK) + if ((status = http_output_stream_write (conn->out, buffer, size)) != H_OK) { fclose (fd); return status; diff --git a/nanohttp/nanohttp-server.h b/nanohttp/nanohttp-server.h index 1768edd..20d7834 100644 --- a/nanohttp/nanohttp-server.h +++ b/nanohttp/nanohttp-server.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-server.h,v 1.15 2006/02/27 22:26:02 snowdrop Exp $ + * $Id: nanohttp-server.h,v 1.16 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -34,7 +34,7 @@ typedef struct httpd_conn { - hsocket_t sock; + hsocket_t *sock; char content_type[25]; http_output_stream_t *out; hpair_t *header; @@ -68,6 +68,9 @@ extern "C" { Begin httpd_* function set */ herror_t httpd_init(int argc, char *argv[]); +void httpd_destroy(void); + +herror_t httpd_run(void); int httpd_register(const char *ctx, httpd_service service); int httpd_register_secure(const char *ctx, httpd_service service, httpd_auth auth); @@ -75,12 +78,9 @@ int httpd_register_secure(const char *ctx, httpd_service service, httpd_auth aut int httpd_register_default(const char *ctx, httpd_service service); int httpd_register_secure_default(const char *ctx, httpd_service service, httpd_auth auth); -herror_t httpd_run(); -void httpd_destroy(); - int httpd_get_port(void); -hservice_t *httpd_services(); +hservice_t *httpd_services(void); herror_t httpd_send_header(httpd_conn_t * res, int code, const char *text); diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c index 77d4d9c..e1ee807 100644 --- a/nanohttp/nanohttp-socket.c +++ b/nanohttp/nanohttp-socket.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-socket.c,v 1.53 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-socket.c,v 1.54 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -87,12 +87,26 @@ typedef int ssize_t; #include "nanohttp-common.h" #include "nanohttp-ssl.h" -#ifdef HAVE_SSL -/*SSL_CTX *SSLctx = NULL; -char *SSLCert = NULL; -char *SSLPass = NULL; -char *SSLCA = NULL; -int SSLCertLess = 0;*/ +#ifdef WIN32 +static inline void +_hsocket_module_sys_init(int argc, char **argv) +{ + struct WSAData info; + WSAStartup(MAKEWORD(2, 2), &info); + + return; +} + +static inline void +_hsocket_module_sys_destroy(void) +{ + WSACleanup(); + + return; +} +#else +static inline void _hsocket_module_sys_init(int argc, char **argv) { return; } +static inline void _hsocket_module_sys_destroy(void) { return; } #endif /*-------------------------------------------------- @@ -101,29 +115,20 @@ NOTE: This will be called from httpd_init() for server and from httpc_init() for client ----------------------------------------------------*/ herror_t -hsocket_module_init() +hsocket_module_init(int argc, char **argv) { -#ifdef WIN32 - struct WSAData info; - WSAStartup(MAKEWORD(2, 2), &info); -#endif + _hsocket_module_sys_init(argc, argv); -#ifdef HAVE_SSL - start_ssl(); -#endif - - return H_OK; + return hssl_module_init(argc, argv); } /*-------------------------------------------------- FUNCTION: hsocket_module_destroy ----------------------------------------------------*/ void -hsocket_module_destroy() +hsocket_module_destroy(void) { -#ifdef WIN32 - WSACleanup(); -#endif + _hsocket_module_sys_destroy(); return; } @@ -132,9 +137,8 @@ hsocket_module_destroy() FUNCTION: hsocket_init ----------------------------------------------------*/ herror_t -hsocket_init(hsocket_t * sock) +hsocket_init(hsocket_t *sock) { - log_verbose1("Starting hsocket init"); memset(sock, 0, sizeof(hsocket_t)); sock->sock = HSOCKET_FREE; @@ -143,38 +147,13 @@ hsocket_init(hsocket_t * sock) } /*-------------------------------------------------- -FUNCTION: hsocket_init_ssl -----------------------------------------------------*/ -#ifdef HAVE_SSL -herror_t -hsocket_init_ssl(hsocket_t * sock, - const char* sslCert, - const char* sslPass, - const char* sslCA) -{ - hsocket_init(sock); - - log_verbose1("calling initialize_ctx()"); - sock->sslCtx = initialize_ctx(sslCert, sslPass, sslCA); - if (sock->sslCtx == NULL) - { - return herror_new("hsocket_init_ctx", HSOCKET_ERROR_SSLCTX, - "Unable to initialize SSL CTX"); - } - - return H_OK; -} - -#endif - - -/*-------------------------------------------------- FUNCTION: hsocket_free ----------------------------------------------------*/ void -hsocket_free(hsocket_t sock) +hsocket_free(hsocket_t *sock) { - /* nothing to free for unix sockets */ + /* nop */ + return; } @@ -182,21 +161,20 @@ hsocket_free(hsocket_t sock) FUNCTION: hsocket_open ----------------------------------------------------*/ herror_t -hsocket_open(hsocket_t * dsock, const char *hostname, int port) +hsocket_open(hsocket_t * dsock, const char *hostname, int port, int ssl) { - hsocket_t sock; - char *ip; struct sockaddr_in address; struct hostent *host; + char *ip; - if ((sock.sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) + if ((dsock->sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) return herror_new("hsocket_open", HSOCKET_ERROR_CREATE, - "Socket error: %d", errno); + "Socket error (%s)", strerror(errno)); /* Get host data */ if (!(host = gethostbyname(hostname))) return herror_new("hsocket_open", HSOCKET_ERROR_GET_HOSTNAME, - "Socket error: %d", errno); + "Socket error (%s)", strerror(errno)); ip = inet_ntoa(*(struct in_addr *) *host->h_addr_list); address.sin_addr.s_addr = inet_addr(ip); @@ -205,31 +183,23 @@ hsocket_open(hsocket_t * dsock, const char *hostname, int port) address.sin_family = host->h_addrtype; address.sin_port = htons((unsigned short) port); + log_debug4("Opening %s://%s:%i", ssl ? "https" : "http", hostname, port); + /* connect to the server */ - if (connect(sock.sock, (struct sockaddr *) &address, sizeof(address)) != 0) + if (connect(dsock->sock, (struct sockaddr *) &address, sizeof(address)) != 0) return herror_new("hsocket_open", HSOCKET_ERROR_CONNECT, - "Socket error: %d", errno); + "Socket error (%s)", strerror(errno)); -#ifdef HAVE_SSL - if (!dsock->sslCtx) - { -#endif - log_verbose1("Using HTTP"); - dsock->sock = sock.sock; -#ifdef HAVE_SSL - } - else + if (ssl) { herror_t status; - log_verbose1("Using HTTPS"); - dsock->ssl = init_ssl(dsock->sslCtx, sock.sock, SSL_CLIENT); - if ((status = hsocket_block(*dsock, dsock->block)) != H_OK) + + if ((status = hssl_client_ssl(dsock)) != H_OK) { - log_error1("Cannot make socket non-blocking"); + log_error2("hssl_client_ssl failed (%s)", herror_message(status)); return status; } } -#endif return H_OK; } @@ -247,9 +217,9 @@ hsocket_bind(hsocket_t * dsock, int port) /* create socket */ if ((sock.sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - log_error3("Can not create socket: '%s'", "Socket error: %d", errno); + log_error2("Cannot create socket (%s)", strerror(errno)); return herror_new("hsocket_bind", HSOCKET_ERROR_CREATE, - "Socket error: %d", errno); + "Socket error (%s)", strerror(errno)); } setsockopt(sock.sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); @@ -262,59 +232,83 @@ hsocket_bind(hsocket_t * dsock, int port) 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); + log_error2("Cannot bind socket (%s)", strerror(errno)); + return herror_new("hsocket_bind", HSOCKET_ERROR_BIND, "Socket error (%s)", + strerror(errno)); } dsock->sock = sock.sock; return H_OK; } -/*---------------------------------------------------------- -FUNCTION: hsocket_accept -----------------------------------------------------------*/ -herror_t -hsocket_accept(hsocket_t sock, hsocket_t * dest) +#ifdef WIN32 +static herror_t +_hsocket_sys_accept(hsocket_t *sock, hsocket_t *dest) { socklen_t asize; hsocket_t sockfd; - struct sockaddr_in addr; - - if (sock.sock <= 0) - return herror_new("hsocket_accept", HSOCKET_ERROR_NOT_INITIALIZED, - "Called hsocket_listen() before initializing!"); asize = sizeof(struct sockaddr_in); -#ifdef WIN32 while (1) { - sockfd.sock = accept(sock.sock, (struct sockaddr *) &addr, &asize); + sockfd.sock = accept(sock->sock, (struct sockaddr *) &(dest->addr), &asize); if (sockfd.sock == INVALID_SOCKET) { if (WSAGetLastError() != WSAEWOULDBLOCK) return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, - "Socket error: %d", errno); + "Socket error (%s)", strerror(errno)); } else { break; } } + + dest->sock = sockfd.sock; + + return H_OK; +} #else -/* TODO (#1#): why not a loop like in win32? */ - sockfd.sock = accept(sock.sock, (struct sockaddr *) &addr, &asize); - if (sockfd.sock == -1) +static herror_t +_hsocket_sys_accept(hsocket_t *sock, hsocket_t *dest) +{ + socklen_t len; + + len = sizeof(struct sockaddr_in); + + if ((dest->sock = accept(sock->sock, (struct sockaddr *) &(dest->addr), &len)) == -1) { - return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, - "Socket error: %d", errno); + log_warn2("accept failed (%s)", strerror(errno)); + return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, "Cannot accept network connection (%s)", strerror(errno)); } + + return H_OK; +} #endif -/* TODO (#1#): Write to access.log file */ - log_verbose3("accept new socket (%d) from '%s'", sockfd.sock, - SAVE_STR(((char *) inet_ntoa(addr.sin_addr)))); +/*---------------------------------------------------------- +FUNCTION: hsocket_accept +----------------------------------------------------------*/ +herror_t +hsocket_accept(hsocket_t *sock, hsocket_t *dest) +{ + herror_t status; + + if (sock->sock < 0) + return herror_new("hsocket_accept", HSOCKET_ERROR_NOT_INITIALIZED, + "hsocket_t not initialized"); + + if ((status = _hsocket_sys_accept(sock, dest)) != H_OK) + return status; + + if ((status = hssl_server_ssl(dest)) != H_OK) + { + log_warn("hsocket_accept", "SSL startup failed (%s)", herror_message(status)); + return status; + } + + log_debug3("accepting connection from '%s' socket=%d", + SAVE_STR(((char *) inet_ntoa(dest->addr.sin_addr))), dest->sock); - dest->sock = sockfd.sock; return H_OK; } @@ -322,17 +316,17 @@ hsocket_accept(hsocket_t sock, hsocket_t * dest) FUNCTION: hsocket_listen ----------------------------------------------------*/ herror_t -hsocket_listen(hsocket_t sock) +hsocket_listen(hsocket_t *sock) { - if (sock.sock <= 0) + if (sock->sock < 0) return herror_new("hsocket_listen", HSOCKET_ERROR_NOT_INITIALIZED, - "Called hsocket_listen() before initializing!"); + "Called hsocket_listen before initializing!"); - if (listen(sock.sock, 15) == -1) + if (listen(sock->sock, 15) == -1) { - log_error3("Can not listen: '%s'", "Socket error: %d", errno); + log_error2("listen failed (%s)", strerror(errno)); return herror_new("hsocket_listen", HSOCKET_ERROR_LISTEN, - "Socket error: %d", errno); + "Cannot listen on this socket (%s)", strerror(errno)); } return H_OK; @@ -360,6 +354,8 @@ _hsocket_sys_close(hsocket_t *sock) shutdown(sock->sock, SHUT_RDWR); + close(sock->sock); + return; } #endif @@ -372,14 +368,7 @@ hsocket_close(hsocket_t *sock) { log_verbose3("closing socket %p (%d)...", sock, sock->sock); -#ifdef HAVE_SSL - if (sock->ssl) - { - log_verbose1("Closing SSL"); - ssl_cleanup(sock->ssl); - sock->ssl = NULL; - } -#endif + hssl_cleanup(sock); _hsocket_sys_close(sock); @@ -392,68 +381,34 @@ hsocket_close(hsocket_t *sock) FUNCTION: hsocket_send ----------------------------------------------------*/ herror_t -hsocket_nsend(hsocket_t sock, const byte_t * bytes, int n) +hsocket_nsend(hsocket_t *sock, const byte_t * bytes, int n) { - int size; - int total = 0; + herror_t status; + size_t total = 0; + size_t size; log_verbose2("Starting to send on sock=%p", &sock); - if (sock.sock <= 0) + if (sock->sock < 0) return herror_new("hsocket_nsend", HSOCKET_ERROR_NOT_INITIALIZED, - "Called hsocket_listen() before initializing!"); + "hsocket not initialized"); /* log_verbose2( "SENDING %s", bytes );*/ - /* TODO (#1#): check return value and send again until n bytes sent */ while (1) { -#ifdef HAVE_SSL - log_verbose2("ssl = %p", sock.ssl); - if (sock.ssl) - { - size = SSL_write(sock.ssl, bytes + total, n); - } - else - { -#endif - size = send((int) sock.sock, bytes + total, n, 0); -#ifdef HAVE_SSL - } -#endif - log_verbose2("Sent %d", size); - /* size = _test_send_to_file(filename, bytes, n); */ -#ifdef WIN32 - if (size == INVALID_SOCKET) - { - if (WSAGetLastError() == WSAEWOULDBLOCK) - { - continue; - } - else - { - return herror_new("hsocket_nsend", HSOCKET_ERROR_SEND, - "Socket error: %d", errno); - } - } -#else - if (size == -1) + + if ((status = hssl_write(sock, bytes + total, n, &size)) != H_OK) { -#ifdef HAVE_SSL - if (sock.ssl) - { - log_error1("Send error"); - log_ssl_error(sock.ssl, size); - } -#endif - return herror_new("hsocket_nsend", HSOCKET_ERROR_SEND, - "Socket error: %d", errno); + log_warn("hssl_write failed (%s)", herror_message(status)); + return status; } -#endif + n -= size; total += size; if (n <= 0) break; } + return H_OK; } @@ -461,125 +416,39 @@ hsocket_nsend(hsocket_t sock, const byte_t * bytes, int n) FUNCTION: hsocket_send ----------------------------------------------------*/ herror_t -hsocket_send(hsocket_t sock, const char *str) +hsocket_send(hsocket_t *sock, const char *str) { return hsocket_nsend(sock, str, strlen(str)); } -/* - return: -1 is error. read bytes otherwise -*/ herror_t -hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, - int *received) +hsocket_read(hsocket_t *sock, byte_t * buffer, int total, int force, int *received) { - int status; - int totalRead; -#ifdef WIN32 - int wsa_error = 0; -#endif + herror_t status; + size_t totalRead; + size_t count; + +// log_verbose3("Entering hsocket_read(total=%d,force=%d)", total, force); + totalRead = 0; -/* - log_verbose3("Entering hsocket_read(total=%d,force=%d)", total, force); -*/ do { -#ifdef HAVE_SSL - 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; -#ifndef WIN32 - fcntl(sock.sock, F_SETFL, O_NONBLOCK); -#endif - status = SSL_read(sock.ssl, &buffer[totalRead], total - totalRead); - - if(ssl_checkFatal( sock.ssl, status )){ - log_verbose1("SSL Error"); - return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL Error"); - } - if (SSL_get_shutdown(sock.ssl) == SSL_RECEIVED_SHUTDOWN) { - log_verbose1("SSL shutdown error"); - return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL shutdown error"); - } - - if (status < 1) - { - int ret = select(sock.sock + 1, &fds, NULL, NULL, &timeout); -#ifdef WIN32 - if (ret == 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_ERROR_SSLCLOSE, "Timeout"); - } - else - { - status = SSL_read(sock.ssl, &buffer[totalRead], total - totalRead); - if(ssl_checkFatal( sock.ssl, status )){ - log_verbose1("SSL Error"); - return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL Error"); - } - } - } -#ifndef WIN32 - fcntl(sock.sock, F_SETFL, 0); -#endif - } - else - { -#else /* HAVE_SSL */ - { -#endif /* HAVE_SSL */ - status = recv(sock.sock, &buffer[totalRead], total - totalRead, 0); -#ifdef WIN32 - if (status == INVALID_SOCKET) - { - wsa_error = WSAGetLastError(); - switch (wsa_error) - { - case WSAEWOULDBLOCK: - /* case WSAEALREADY: case WSAEINPROGRESS: */ - continue; - default: - log_error2("WSAGetLastError()=%d", wsa_error); - return herror_new("hsocket_read", HSOCKET_ERROR_RECEIVE, - "Socket error: %d", errno); - } - } - } -#else + if ((status = hssl_read(sock, &buffer[totalRead], (size_t)total - totalRead, &count)) != H_OK) + { + log_warn("hssl_read failed (%s)", herror_message(status)); + return status; } - if (status == -1) - return herror_new("hsocket_read", HSOCKET_ERROR_RECEIVE, - "Socket error: %d", errno); -#endif - if (!force) { - *received = status; - /* - log_verbose3("Leaving !force (received=%d)(status=%d)", *received, - status); */ + /* log_verbose3("Leaving !force (received=%d)(status=%d)", *received, status); + */ + *received = count; return H_OK; } - totalRead += status; + totalRead += count; if (totalRead == total) { @@ -595,34 +464,32 @@ hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, } -herror_t -hsocket_block(hsocket_t sock, int block) -{ -#ifdef WIN32 - unsigned long iMode; -#endif - - if (sock.sock <= 0) - return herror_new("hsocket_block", HSOCKET_ERROR_NOT_INITIALIZED, - "Called hsocket_listen() before initializing!"); - -#ifdef WIN32 -/*#define HSOCKET_BLOCKMODE 0 -#define HSOCKET_NONBLOCKMODE 1 -*/ - - iMode = (block == 0) ? 1 : 0; /* Non block mode */ - if (ioctlsocket(sock.sock, FIONBIO, (u_long FAR *) & iMode) == - INVALID_SOCKET) - { - 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 */ - -#endif - return H_OK; -} +// #ifdef WIN32 +// herror_t +// hsocket_block(hsocket_t *sock, int block) +// { +// unsigned long iMode; +// +// if (sock->sock < 0) +// return herror_new("hsocket_block", HSOCKET_ERROR_NOT_INITIALIZED, +// "Called hsocket_listen() before initializing!"); +// +// iMode = (block == 0) ? 1 : 0; /* Non block mode */ +// if (ioctlsocket(sock.sock, FIONBIO, (u_long FAR *) & iMode) == +// INVALID_SOCKET) +// { +// int err = WSAGetLastError(); +// log_error2("ioctlsocket error %d", err); +// return herror_new("hsocket_block", HSOCKET_ERROR_IOCTL, +// "Socket error %d", err); +// } +// +// return H_OK; +// } +// #else +// herror_t +// hsocket_block(hsocket_t *sock, int block) +// { +// return H_OK; +// } +// #endif diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h index 63d55dd..bbe5692 100644 --- a/nanohttp/nanohttp-socket.h +++ b/nanohttp/nanohttp-socket.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-socket.h,v 1.24 2006/02/27 22:26:02 snowdrop Exp $ + * $Id: nanohttp-socket.h,v 1.25 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -24,9 +24,11 @@ #ifndef NANO_HTTP_SOCKET_H #define NANO_HTTP_SOCKET_H -#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> -#include <nanohttp/nanohttp-common.h> +#include <time.h> #ifdef HAVE_SSL #include <openssl/ssl.h> @@ -36,6 +38,8 @@ #include <winsock2.h> #endif +#include <nanohttp/nanohttp-common.h> + #define HSOCKET_FREE -1 /* @@ -43,44 +47,33 @@ */ typedef struct hsocket_t { - -#ifdef HAVE_SSL - SSL *ssl; - SSL_CTX *sslCtx; -#endif - #ifdef WIN32 SOCKET sock; #else - volatile int sock; + int sock; #endif - int block; - + struct sockaddr_in addr; + void *ssl; } hsocket_t; /* end of socket definition */ -#ifdef WIN32 -typedef int socklen_t; -#endif - #ifdef __cplusplus extern "C" { #endif - /** Initializes the socket modul. This should be called only once for an application. @returns This function should always return H_OK. */ -herror_t hsocket_module_init(); +herror_t hsocket_module_init(int argc, char **argv); /** Destroys the socket modul. This should be called after finishing an application. */ -void hsocket_module_destroy(); +void hsocket_module_destroy(void); /** @@ -93,34 +86,14 @@ void hsocket_module_destroy(); @see hsocket_init_ssl @returns This function should always return H_OK. */ -herror_t hsocket_init(hsocket_t * sock); - - -/** - Initializes a given socket object with ssl context. - To initialize the socket without ssl, you should use - hsocket_init() - - @param sock the destination socket to initialize. - @param sslCert keyfile - @param sslPass passwort - @param sslCA calist - - @see hsocket_init - @returns HSOCKET_ERROR_SSLCTX if failed. H_OK otherwise - */ -herror_t -hsocket_init_ssl(hsocket_t * sock, - const char* sslCert, - const char* sslPass, - const char* sslCA); +herror_t hsocket_init(hsocket_t *sock); /** Destroys and releases a given socket. @param sock the socket to destroy */ -void hsocket_free(hsocket_t sock); +void hsocket_free(hsocket_t *sock); /** @@ -130,13 +103,14 @@ void hsocket_free(hsocket_t sock); @param sock the destonation socket object to use @param host hostname @param port port number to connect to + @param ssl whether to open a SSL connection @returns H_OK if success. One of the followings if fails:<P> <BR>HSOCKET_ERROR_CREATE <BR>HSOCKET_ERROR_GET_HOSTNAME <BR>HSOCKET_ERROR_CONNECT */ -herror_t hsocket_open(hsocket_t * sock, const char *host, int port); +herror_t hsocket_open(hsocket_t *sock, const char *host, int port, int ssl); /** @@ -160,7 +134,7 @@ void hsocket_close(hsocket_t *sock); @see hsocket_listen */ -herror_t hsocket_bind(hsocket_t * sock, int port); +herror_t hsocket_bind(hsocket_t *sock, int port); /** @@ -174,7 +148,7 @@ herror_t hsocket_bind(hsocket_t * sock, int port); <BR>HSOCKET_ERROR_NOT_INITIALIZED <BR>HSOCKET_ERROR_LISTEN */ -herror_t hsocket_listen(hsocket_t sock); +herror_t hsocket_listen(hsocket_t *sock); /** @@ -188,7 +162,7 @@ herror_t hsocket_listen(hsocket_t sock); <BR>HSOCKET_ERROR_NOT_INITIALIZED <BR>HSOCKET_ERROR_ACCEPT */ -herror_t hsocket_accept(hsocket_t sock, hsocket_t * dest); +herror_t hsocket_accept(hsocket_t *sock, hsocket_t * dest); /** @@ -202,7 +176,7 @@ herror_t hsocket_accept(hsocket_t sock, hsocket_t * dest); <BR>HSOCKET_ERROR_NOT_INITIALIZED <BR>HSOCKET_ERROR_SEND */ -herror_t hsocket_nsend(hsocket_t sock, const byte_t * bytes, int size); +herror_t hsocket_nsend(hsocket_t *sock, const byte_t * bytes, int size); /** @@ -215,7 +189,7 @@ herror_t hsocket_nsend(hsocket_t sock, const byte_t * bytes, int size); <BR>HSOCKET_ERROR_NOT_INITIALIZED <BR>HSOCKET_ERROR_SEND */ -herror_t hsocket_send(hsocket_t sock, const char *str); +herror_t hsocket_send(hsocket_t *sock, const char *str); /** @@ -234,7 +208,7 @@ herror_t hsocket_send(hsocket_t sock, const char *str); the socket. */ -herror_t hsocket_read(hsocket_t sock, byte_t * buffer, int size, int force, +herror_t hsocket_read(hsocket_t *sock, byte_t * buffer, int size, int force, int *readed); /** @@ -246,7 +220,7 @@ herror_t hsocket_read(hsocket_t sock, byte_t * buffer, int size, int force, <BR>HSOCKET_ERROR_NOT_INITIALIZED <BR>HSOCKET_ERROR_IOCTL */ -herror_t hsocket_block(hsocket_t sock, int block); +// herror_t hsocket_block(hsocket_t *sock, int block); #ifdef __cplusplus } diff --git a/nanohttp/nanohttp-ssl.c b/nanohttp/nanohttp-ssl.c index 63bf0f7..a365e64 100644 --- a/nanohttp/nanohttp-ssl.c +++ b/nanohttp/nanohttp-ssl.c @@ -1,4 +1,7 @@ -/* +/************************************************************************* + * $Id: nanohttp-ssl.c,v 1.18 2006/03/06 13:37:38 m0gg Exp $ + * + * CSOAP Project: A http client/server library in C * Copyright (C) 2001-2005 Rochester Institute of Technology * * This program is free software; you can redistribute it and/or modify @@ -21,9 +24,6 @@ * Descrip: SSL connection routines */ -/* Enter only if --with-ssl was specified to the configure script */ -#ifdef HAVE_SSL - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -36,16 +36,6 @@ #include <netinet/in.h> #endif -#if HAVE_INTTYPES_H -#include <inttypes.h> -#else -# if HAVE_STDINT_H -# include <stdint.h> -# else -typedef unsigned int uint32_t; -# endif -#endif - #ifdef HAVE_STRING_H #include <string.h> #endif @@ -54,6 +44,10 @@ typedef unsigned int uint32_t; #include <stdlib.h> #endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + #ifdef HAVE_TIME_H #include <time.h> #endif @@ -66,12 +60,11 @@ typedef unsigned int uint32_t; #include <unistd.h> #endif -#ifdef WIN32 +#ifdef HAVE_IO_H #include <io.h> -typedef unsigned int uint32_t; -#else #endif +#ifdef HAVE_SSL #ifdef HAVE_OPENSSL_RAND_H #include <openssl/rand.h> #endif @@ -79,24 +72,25 @@ typedef unsigned int uint32_t; #ifdef HAVE_OPENSSL_ERR_H #include <openssl/err.h> #endif +#endif #include "nanohttp-common.h" #include "nanohttp-socket.h" #include "nanohttp-ssl.h" -#define MAXCHUNK 1024 -#define HEADER_LEN 5 -char HEADER[HEADER_LEN] = { 186, 84, 202, 86, 224 }; -static char *pass; +#ifdef HAVE_SSL -/* - * superseed - * Creates a 1k random seed and uses it to seed - * the SSL random number generator - */ +static char *certificate = NULL; +static char *certpass = NULL; +static char *ca_list = NULL; +static SSL_CTX *context = NULL; -void -superseed () +static int enabled = 0; +static int initialized = 0; + + +static void +_hssl_superseed (void) { int buf[256], i; @@ -107,18 +101,47 @@ superseed () buf[i] = rand (); } RAND_seed ((unsigned char *) buf, sizeof (buf)); + + return; } + +static char * +_hssl_get_error(SSL *ssl, int ret) +{ + switch(SSL_get_error(ssl, ret)) + { + case SSL_ERROR_NONE: + return "None"; + case SSL_ERROR_ZERO_RETURN: + return "Zero return"; + case SSL_ERROR_WANT_READ: + return "Want read"; + case SSL_ERROR_WANT_WRITE: + return "Want write"; + case SSL_ERROR_WANT_X509_LOOKUP: + return "Want x509 lookup"; + case SSL_ERROR_SYSCALL: + return "Syscall failed"; + case SSL_ERROR_SSL: + return "SSL error"; + default: + return "Unkown"; + } +} + + static int pw_cb (char *buf, int num, int rwflag, void *userdata) { - if (num < (int) strlen (pass) + 1) + if (num < (int) strlen (certpass) + 1) return (0); - strcpy (buf, pass); - return strlen (pass); + strcpy(buf, certpass); + return strlen(certpass); } + int verify_sn (X509 * cert, int who, int nid, char *str) { @@ -152,6 +175,7 @@ verify_sn (X509 * cert, int who, int nid, char *str) } } + #ifdef NOUSER_VERIFY static int user_verify (X509 * cert) @@ -190,262 +214,331 @@ verify_cb (int prev_ok, X509_STORE_CTX * ctx) #endif } -void -start_ssl( void ) + +static void +_hssl_parse_arguments(int argc, char **argv) +{ + + int i; + + for (i=1; i<argc; i++) + { + if (!strcmp(argv[i-1], NHTTP_ARG_CERT)) + { + certificate = argv[i]; + } + else if (!strcmp(argv[i-1], NHTTP_ARG_CERTPASS)) + { + certpass = argv[i]; + } + else if (!strcmp(argv[i-1], NHTTP_ARG_CA)) + { + ca_list = argv[i]; + } + else if (!strcmp(argv[i-1], NHTTP_ARG_HTTPS)) + { + enabled = 1; + } + } + + return; +} + + +static void +_hssl_library_init(void) { /* Global system initialization */ log_verbose1 ("Initializing library"); - SSL_library_init (); - SSL_load_error_strings (); - ERR_load_crypto_strings (); - OpenSSL_add_ssl_algorithms (); + + SSL_library_init(); + + SSL_load_error_strings(); + ERR_load_crypto_strings(); + + OpenSSL_add_ssl_algorithms(); + + initialized = 1; return; } -SSL_CTX * -initialize_ctx (const char *keyfile, const char *password, const char *calist) + +static herror_t +hssl_context_init(void) { - SSL_CTX *ctx = NULL; + log_verbose3("enabled=%i, certificate=%p", enabled, certificate); + + if (!enabled || !certificate) + return H_OK; - if (password == NULL) - password = ""; + if (certpass == NULL) + certpass = ""; /* Create our context */ - ctx = SSL_CTX_new (SSLv23_method ()); - - if (ctx == NULL) + if (!(context = SSL_CTX_new(SSLv23_method()))) { log_error1 ("Cannot create SSL context"); - return NULL; + return herror_new("hssl_context_init", HSSL_ERROR_CONTEXT, "Unable to create SSL context"); } - log_verbose1 ("SSL context created ok"); - /* Load our keys and certificates */ - if (keyfile != NULL && password != NULL) + if (!(SSL_CTX_use_certificate_file (context, certificate, SSL_FILETYPE_PEM))) { + SSL_CTX_free(context); + log_error2 ("Cannot read certificate file: \"%s\"", certificate); + return herror_new("hssl_context_init", HSSL_ERROR_CERTIFICATE, "Unable to use SSL certificate \"%s\"", certificate); + } - if (!(SSL_CTX_use_certificate_file (ctx, keyfile, SSL_FILETYPE_PEM))) - { - log_error2 ("Couldn't read certificate file: %s", keyfile); - SSL_CTX_free (ctx); - return ctx = NULL; - } - - log_verbose1 ("Certificate file read ok"); + SSL_CTX_set_default_passwd_cb(context, pw_cb); - pass = strdup(password); - SSL_CTX_set_default_passwd_cb (ctx, pw_cb); + if (!(SSL_CTX_use_PrivateKey_file(context, certificate, SSL_FILETYPE_PEM))) + { + SSL_CTX_free(context); + log_error2 ("Cannot read key file: \"%s\"", certificate); + return herror_new("hssl_context_init", HSSL_ERROR_PEM, "Unable to use private key"); + } - if (!(SSL_CTX_use_PrivateKey_file (ctx, keyfile, SSL_FILETYPE_PEM))) + if (ca_list != NULL && *ca_list != '\0') + { + if (!(SSL_CTX_load_verify_locations(context, ca_list, NULL))) { - log_error2 ("Couldn't read key file: %s", keyfile); - SSL_CTX_free (ctx); - return ctx = NULL; + SSL_CTX_free(context); + log_error2 ("Cannot read CA list: \"%s\"", ca_list); + return herror_new("hssl_context_init", HSSL_ERROR_CA_LIST, "Unable to read certification authorities \"%s\""); } - log_verbose1 ("Keyfile read ok"); + SSL_CTX_set_client_CA_list (context, SSL_load_client_CA_file (ca_list)); + log_verbose1 ("Certification authority contacted"); } - if (calist != NULL && *calist != '\0') - { + SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_cb); - /* Load the CAs we trust */ - if (!(SSL_CTX_load_verify_locations (ctx, calist, NULL))) - { - log_error2 ("Couldn't read CA list: %s", calist); - SSL_CTX_free (ctx); - return ctx = NULL; - } + log_verbose1("Verify callback registered"); + + SSL_CTX_set_mode(context, SSL_MODE_AUTO_RETRY); + + SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF); + + _hssl_superseed(); + + return H_OK; +} - SSL_CTX_set_client_CA_list (ctx, SSL_load_client_CA_file (calist)); - log_verbose1 ("Certificate Authority contacted"); +static void +_hssl_context_destroy(void) +{ + if (context) + { + SSL_CTX_free(context); + context = NULL; } - SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, - verify_cb); - log_verbose1 ("Verify callback registered"); + return; +} - SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_OFF); +herror_t +hssl_module_init(int argc, char **argv) +{ + _hssl_parse_arguments(argc, argv); - /* Load randomness */ - superseed (); + if (!initialized) + { + if (enabled) + { + _hssl_library_init(); + log_verbose1("SSL enabled"); + } + else + { + log_verbose1("SSL _not_ enabled"); + } + } - return ctx; + return hssl_context_init(); } + void -log_ssl_error (SSL * ssl, int ret) +hssl_module_destroy(void) { - int errqueue; - char errorbuf[256] = "Error: "; + _hssl_context_destroy(); - if (ret == 0) + return; +} + + +herror_t +hssl_client_ssl(hsocket_t *sock) +{ + SSL *ssl; + int ret; + + log_verbose1 ("Starting SSL client initialization"); + + if (!(ssl = SSL_new(context))) { - log_error1 ("SSL handshake was not successful, contolled shutdown"); + log_error1("Cannot create new SSL object"); + return herror_new("hssl_client_ssl", HSSL_ERROR_CLIENT, "SSL_new failed"); } - else if (ret == -1) + + SSL_set_fd (ssl, sock->sock); + + if ((ret = SSL_connect(ssl)) <= 0) { - log_error1 ("SSL handshake was not successful, fatal error at protocol"); - } + herror_t err; - errqueue = SSL_get_error (ssl, ret); + log_error2 ("SSL connect error (%s)", _hssl_get_error(ssl, -1)); + err = herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free (ssl); + return err; + } - switch (errqueue) + /* SSL_connect should take care of this for us. + if (SSL_get_peer_certificate(ssl) == NULL) { - case SSL_ERROR_NONE: - strcat (errorbuf, "None"); - break; - case SSL_ERROR_ZERO_RETURN: - strcat (errorbuf, "Zero return"); - break; - case SSL_ERROR_WANT_READ: - strcat (errorbuf, "Want read"); - break; - case SSL_ERROR_WANT_WRITE: - strcat (errorbuf, "Want write"); - break; - case SSL_ERROR_WANT_X509_LOOKUP: - strcat (errorbuf, "Want x509 lookup"); - break; - case SSL_ERROR_SYSCALL: - strcat (errorbuf, "Syscall:"); - if (ret == 0) - { - strcat (errorbuf, "Protocol violation"); - } - else if (ret == -1) - { - strcat (errorbuf, "BIO reported an I/O error"); - } - else - { - strcat (errorbuf, "Unknown syscall error"); - } /* if */ + log_error1("No certificate provided"); + SSL_free(ssl); + return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "No certificate provided"); + } - break; - case SSL_ERROR_SSL: - strcat (errorbuf, "SSL library"); - while ((errqueue = ERR_get_error())) - { - log_error2 ("SSL %s", ERR_error_string (errqueue, NULL)); - } - break; - } /* switch code */ + if (SSL_get_verify_result(ssl) != X509_V_OK) + { + log_error1("Certificate did not verify"); + SSL_free(ssl); + return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); + } */ - log_error1 (errorbuf); + log_verbose1 ("SSL client initialization completed"); + + /* XXX: why??? + if ((status = hsocket_block(sock, sock->block)) != H_OK) + { + log_error2("Cannot make socket non-blocking (%s)", herror_message(status)); + SSL_free(ssl); + return status; + } */ + + sock->ssl = ssl; + + return H_OK; } -SSL * -init_ssl (SSL_CTX * ctx, int sock, int type) + +herror_t +hssl_server_ssl(hsocket_t *sock) { - int ret; SSL *ssl; -#if 0 -#ifdef WIN32 - BIO *rbio; - BIO *wbio; -#else - BIO *sbio; -#endif -#endif + int ret; - log_verbose1 ("Starting SSL Initialization"); + if (!enabled) + return H_OK; - ssl = SSL_new (ctx); + log_verbose2("Starting SSL initialization for socket %d", sock->sock); - if (ssl == NULL) + if (!(ssl = SSL_new(context))) { - log_error1 ("Cannot create new ssl object"); - return NULL; + log_warn1("SSL_new failed"); + return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "Cannot create SSL object"); } + SSL_set_fd(ssl, sock->sock); -#if 0 -#ifdef WIN32 - log_error1 ("Setting up BIO with socket"); - rbio = BIO_new_socket (sock, BIO_NOCLOSE); - if (rbio == NULL) + if ((ret = SSL_accept(ssl)) <= 0) { - log_error1 ("BIO_new_socket failed"); - return NULL; + herror_t err; + + log_error2 ("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + + err = herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free (ssl); + + return err; } - SSL_set_bio (ssl, rbio, rbio); -#else - sbio = BIO_new_socket (sock, BIO_NOCLOSE); + sock->ssl = ssl; - if (sbio == NULL) + return H_OK; +} + + +void +hssl_cleanup(hsocket_t *sock) +{ + + if (sock->ssl) { - log_error1 ("BIO_new_socket failed"); - return NULL; + SSL_shutdown (sock->ssl); + SSL_free (sock->ssl); + sock->ssl = NULL; } - SSL_set_bio (ssl, sbio, sbio); -#endif -#endif - SSL_set_fd (ssl, sock); - if (type == SSL_SERVER) + return; +} + + +herror_t hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +{ + int count; + + log_verbose4("sock->sock=%d sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); + + if (sock->ssl) { - hsocket_t sock_t; - sock_t.sock = sock; - hsocket_block (sock_t, 1); - ret = SSL_accept (ssl); - hsocket_block (sock_t, 0); - if (ret <= 0) - { - log_error1 ("SSL accept error"); - log_ssl_error (ssl, ret); - SSL_free (ssl); - return NULL; - } /* if error */ + if ((count = SSL_read(sock->ssl, buf, len)) == -1) + return herror_new("SSL_read", HSOCKET_ERROR_RECEIVE, "SSL_read failed (%s)", _hssl_get_error(sock->ssl, count)); } else - { /* client */ - ret = SSL_connect (ssl); - if (ret <= 0) - { - log_error1 ("SSL connect error"); - log_ssl_error (ssl, ret); - SSL_free (ssl); - return NULL; - } /* if error */ - /* SSL_connect should take care of this for us. - if(SSL_get_peer_certificate(ssl) == NULL) { log_error1( "No - certificate provided"); SSL_free(ssl); return ssl = NULL; } - if(SSL_get_verify_result(ssl) != X509_V_OK) { log_error1( "Certificate - did not verify"); SSL_free(ssl); return ssl = NULL; } */ + { + if ((count = recv(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); } + *received = count; - log_verbose1 ("Completed SSL Initialization"); - return ssl; + return H_OK; } -void -ssl_cleanup (SSL * ssl) + +herror_t hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) { - /* does nothing to context */ + int count; - if (ssl != NULL) - { + log_verbose4("sock->sock=%d, sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); - SSL_shutdown (ssl); -// SSL_clear(ssl); - SSL_free (ssl); - ssl = NULL; + if (sock->ssl) + { + if ((count = SSL_write(sock->ssl, buf, len)) == -1) + return herror_new("SSL_write", HSOCKET_ERROR_SEND, "SSL_write failed (%s)", _hssl_get_error(sock->ssl, count)); + } + else + { + if ((count = send(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); } + *sent = count; + + return H_OK; } -int -ssl_checkFatal( SSL *ssl, int status ){ - switch (SSL_get_error(ssl, status)) { - case SSL_ERROR_ZERO_RETURN: - case SSL_ERROR_SSL: - case SSL_ERROR_SYSCALL: - return 1; - break; - default: - return 0; - } +#else + +herror_t hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +{ + int count; + + if ((count = recv(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); + *received = count; + return H_OK; +} + + +herror_t hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) +{ + int count; + + if ((count = send(sock->sock, buf, len, 0)) == -1) + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); + *sent = count; + return H_OK; } -#endif /* end of ifdef HAVE_SSL */ +#endif diff --git a/nanohttp/nanohttp-ssl.h b/nanohttp/nanohttp-ssl.h index 1cdafb2..82a7db7 100644 --- a/nanohttp/nanohttp-ssl.h +++ b/nanohttp/nanohttp-ssl.h @@ -18,68 +18,53 @@ /* * Author: Matt Campbell - * Contrib: - * Descrip: Common ssl routines */ - -/* Do enter only if --with-ssl was specified by the configure script */ -#ifdef HAVE_SSL - -#ifdef TRU64 -#include <arpa/inet.h> -typedef unsigned int uint32_t; -#endif - #ifndef __NANOHTTP_SSL_H_ #define __NANOHTTP_SSL_H_ -#include <openssl/ssl.h> - -#ifdef WIN32 -typedef unsigned int uint32_t; -#else -#include <unistd.h> +#ifdef HAVE_CONFIG_H +#include <config.h> #endif -#define SSL_SERVER 0 -#define SSL_CLIENT 1 - -#define CERT_SUBJECT 0 -#define CERT_ISSUER 1 - -typedef struct Con -{ - SSL *ssl; - int sock; -} Con; +#ifdef HAVE_SSL -/* - * Callback for password checker - */ +#ifdef HAVE_OPENSSL_SSL_H +#include <openssl/ssl.h> +#endif #ifdef __cplusplus extern "C" { #endif -//static int pw_cb(char* buf, int num, int rwflag, void *userdata); +/** + * + * Initialization and shutdown of the SSL module + * + */ +herror_t hssl_module_init(int argc, char **argv); +void hssl_module_destroy(void); -/* - * Start the ssl library +/** + * + * Socket initialization and shutdown + * */ -void start_ssl( void ); +herror_t hssl_client_ssl(hsocket_t *sock); +herror_t hssl_server_ssl(hsocket_t *sock); + +void hssl_cleanup(hsocket_t *sock); + /* - * Initialize the context + * Callback for password checker */ - -SSL_CTX *initialize_ctx(const char *keyfile, - const char *password, - const char *calist); +//static int pw_cb(char* buf, int num, int rwflag, void *userdata); /* * Quick function for verifying a portion of the cert * nid is any NID_ defined in <openssl/objects.h> * returns non-zero if everything went ok */ +#define CERT_SUBJECT 1 int verify_sn(X509 * cert, int who, int nid, char *str); @@ -95,33 +80,31 @@ int verify_sn(X509 * cert, int who, int nid, char *str); int user_verify(X509 * cert); -/* - * Create the ssl socket and return it - * pass in the context and an open socket - */ +#ifdef __cplusplus +} +#endif -SSL *init_ssl(SSL_CTX * ctx, int sock, int type); +#else /* HAVE_SSL */ -/* - * Close the ssl connection (socket is still left open) - */ +static inline herror_t hssl_module_init(int argc, char **argv) { return H_OK; } +static inline void hssl_module_destroy(void) { return; } -void ssl_cleanup(); +static inline herror_t hssl_client_ssl(hsocket_t *sock) { return H_OK; } +static inline herror_t hssl_server_ssl(hsocket_t *sock) { return H_OK; } -/** - Log funtion to report ssl failures - @param ssl - @param ret - */ -void -log_ssl_error (SSL * ssl, int ret); +static inline void hssl_cleanup(hsocket_t *sock) { return; } -int ssl_checkFatal( SSL *ssl, int status ); +#endif /* HAVE_SSL */ +#ifdef __cplusplus +extern "C" { #endif +herror_t hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received); +herror_t hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent); + #ifdef __cplusplus } #endif -#endif /* HAVE_SSL */ +#endif diff --git a/nanohttp/nanohttp-stream.c b/nanohttp/nanohttp-stream.c index 0d8188a..ba36725 100755 --- a/nanohttp/nanohttp-stream.c +++ b/nanohttp/nanohttp-stream.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-stream.c,v 1.11 2006/02/27 22:26:02 snowdrop Exp $ +* $Id: nanohttp-stream.c,v 1.12 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -43,17 +43,6 @@ #include "nanohttp-stream.h" -void -_log_str(char *fn, char *str, int size) -{ -/* FILE *f = fopen(fn, "ab"); - if (!f) f=fopen(fn,"wb"); - fwrite(str, size, 1, f); - fflush(f); - fclose(f); -*/ -} - /* ------------------------------------------------------------------- @@ -88,7 +77,7 @@ _http_stream_is_chunked(hpair_t * header) Creates a new input stream. */ http_input_stream_t * -http_input_stream_new(hsocket_t sock, hpair_t * header) +http_input_stream_new(hsocket_t *sock, hpair_t * header) { http_input_stream_t *result; char *content_length; @@ -195,7 +184,6 @@ static int _http_input_stream_is_chunked_ready(http_input_stream_t * stream) { return stream->chunk_size != 0; - } static int @@ -312,9 +300,7 @@ _http_input_stream_chunked_read(http_input_stream_t * stream, byte_t * dest, counter = 100; /* maximum for stop infinity */ while (1) { - err = hsocket_read(stream->sock, &ch, 1, 1, &status); - - if (err != H_OK) + if ((err = hsocket_read(stream->sock, &ch, 1, 1, &status)) != H_OK) { stream->err = err; return -1; @@ -356,8 +342,7 @@ _http_input_stream_chunked_read(http_input_stream_t * stream, byte_t * dest, if (remain < size) { /* read from socket */ - err = hsocket_read(stream->sock, &(dest[read]), remain, 1, &status); - if (err != H_OK) + if ((err = hsocket_read(stream->sock, &(dest[read]), remain, 1, &status)) != H_OK) { stream->err = err; return -1; @@ -407,8 +392,7 @@ _http_input_stream_connection_closed_read(http_input_stream_t * stream, herror_t err; /* read from socket */ - err = hsocket_read(stream->sock, dest, size, 0, &status); - if (err != H_OK) + if ((err = hsocket_read(stream->sock, dest, size, 0, &status)) != H_OK) { stream->err = err; return -1; @@ -418,7 +402,6 @@ _http_input_stream_connection_closed_read(http_input_stream_t * stream, stream->connection_closed = 1; stream->received += status; - _log_str("stream.in", dest, size); return status; } @@ -481,7 +464,7 @@ http_input_stream_read(http_input_stream_t * stream, byte_t * dest, int size) return -1; } - /* reset error flag */ + /* XXX: possible memleak! reset error flag */ stream->err = H_OK; switch (stream->type) @@ -523,7 +506,7 @@ HTTP OUTPUT STREAM Creates a new output stream. Transfer code will be found from header. */ http_output_stream_t * -http_output_stream_new(hsocket_t sock, hpair_t * header) +http_output_stream_new(hsocket_t *sock, hpair_t * header) { http_output_stream_t *result; char *content_length; @@ -599,7 +582,6 @@ http_output_stream_write(http_output_stream_t * stream, if (size > 0) { - _log_str("stream.out", (char *) bytes, size); if ((status = hsocket_nsend(stream->sock, bytes, size)) != H_OK) return status; } diff --git a/nanohttp/nanohttp-stream.h b/nanohttp/nanohttp-stream.h index ac78603..88e5f97 100755 --- a/nanohttp/nanohttp-stream.h +++ b/nanohttp/nanohttp-stream.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-stream.h,v 1.9 2006/02/27 22:26:02 snowdrop Exp $ + * $Id: nanohttp-stream.h,v 1.10 2006/03/06 13:37:38 m0gg Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -29,12 +29,6 @@ #include <nanohttp/nanohttp-socket.h> #include <nanohttp/nanohttp-common.h> -#ifdef __cplusplus -extern "C" { -#endif - -void _log_str(char *fn, char *str, int size); - /* HTTP Stream modul: @@ -88,7 +82,7 @@ typedef enum http_transfer_type */ typedef struct http_input_stream { - hsocket_t sock; + hsocket_t *sock; herror_t err; http_transfer_type_t type; int received; @@ -109,13 +103,17 @@ typedef struct http_input_stream */ typedef struct http_output_stream { - hsocket_t sock; + hsocket_t *sock; http_transfer_type_t type; int content_length; int sent; } http_output_stream_t; +#ifdef __cplusplus +extern "C" { +#endif + /* -------------------------------------------------------------- HTTP INPUT STREAM @@ -136,7 +134,7 @@ typedef struct http_output_stream @see http_input_stream_free */ -http_input_stream_t *http_input_stream_new(hsocket_t sock, hpair_t * header); +http_input_stream_t *http_input_stream_new(hsocket_t *sock, hpair_t *header); /** @@ -218,7 +216,7 @@ int http_input_stream_read(http_input_stream_t * stream, @see http_output_stream_free */ -http_output_stream_t *http_output_stream_new(hsocket_t sock, +http_output_stream_t *http_output_stream_new(hsocket_t *sock, hpair_t * header); |