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