diff options
Diffstat (limited to 'nanohttp/nanohttp-socket.c')
-rw-r--r-- | nanohttp/nanohttp-socket.c | 453 |
1 files changed, 160 insertions, 293 deletions
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 |