From 75018531e6aedb37c7c76c7fd2ff16eec0cc9dee Mon Sep 17 00:00:00 2001 From: rans Date: Tue, 31 Aug 2004 16:34:08 +0000 Subject: Reaper added and rearranged code --- nanohttp/nanohttp-client.c | 46 ++------------ nanohttp/nanohttp-client.h | 17 +----- nanohttp/nanohttp-server.c | 145 ++++++++------------------------------------ nanohttp/nanohttp-socket.c | 101 +++++++++++++++++++++++++++++- nanohttp/nanohttp-socket.h | 36 ++++++++++- nanohttp/nanohttp-windows.h | 63 +++++++++++++++++++ 6 files changed, 227 insertions(+), 181 deletions(-) create mode 100644 nanohttp/nanohttp-windows.h diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c index 22571c6..20a04a1 100644 --- a/nanohttp/nanohttp-client.c +++ b/nanohttp/nanohttp-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-client.c,v 1.16 2004/08/30 15:26:53 snowdrop Exp $ +* $Id: nanohttp-client.c,v 1.17 2004/08/31 16:34:08 rans Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -23,12 +23,6 @@ ******************************************************************/ #include -#ifdef WIN32 -#include "wsockcompat.h" -#include -#define close(s) closesocket(s) -#endif - #ifdef HAVE_CONFIG_H #include #endif @@ -38,23 +32,6 @@ #include -#ifdef WIN32 - -#include - -static struct tm *localtime_r(const time_t *const timep, struct tm *p_tm) -{ - static struct tm* tmp; - tmp = localtime(timep); - if (tmp) { - memcpy(p_tm, tmp, sizeof(struct tm)); - tmp = p_tm; - } - return tmp; -} - -#endif - /*-------------------------------------------------- FUNCTION: httpc_init DESC: Initialize http client connection @@ -589,11 +566,6 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, char buffer[4096]; int status; -#ifdef WIN32 - unsigned long iMode = HSOCKET_NONBLOCKMODE; -#endif - - if (conn == NULL) { log_error1("Connection object is NULL"); return 1; @@ -620,21 +592,13 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, return 3; } -#ifndef WIN32 - /* Try always non block mode - #if HSOCKET_BLOCKMODE!=0*/ - fcntl(conn->sock, F_SETFL, O_NONBLOCK); - /*#endif*/ -#else - iMode = HSOCKET_NONBLOCKMODE; - if(ioctlsocket(conn->sock, FIONBIO, (u_long FAR*) &iMode) == INVALID_SOCKET) + status=hsocket_makenonblock(conn->sock); + if(status!=HSOCKET_OK) { - log_error1("ioctlsocket error"); - return -1; + log_error1("Cannot make socket non-blocking"); + return status; } -#endif - /* check method */ if (method == HTTP_REQUEST_GET) { diff --git a/nanohttp/nanohttp-client.h b/nanohttp/nanohttp-client.h index 9c5cd64..f937f00 100644 --- a/nanohttp/nanohttp-client.h +++ b/nanohttp/nanohttp-client.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-client.h,v 1.6 2004/08/30 15:26:53 snowdrop Exp $ + * $Id: nanohttp-client.h,v 1.7 2004/08/31 16:34:08 rans Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -90,18 +90,3 @@ int httpc_post_finish_cb(httpc_conn_t *conn, #endif - - - - - - - - - - - - - - - diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c index 7823cc5..807ab58 100644 --- a/nanohttp/nanohttp-server.c +++ b/nanohttp/nanohttp-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-server.c,v 1.13 2004/08/31 13:57:27 rans Exp $ +* $Id: nanohttp-server.c,v 1.14 2004/08/31 16:34:08 rans Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -23,38 +23,15 @@ ******************************************************************/ #include -#include #include #include -#include #include -#ifdef WIN32 -#include "wsockcompat.h" -#include -#include -#define close(s) closesocket(s) - -static struct tm *localtime_r(const time_t *const timep, struct tm *p_tm) -{ - static struct tm* tmp; - tmp = localtime(timep); - if (tmp) { - memcpy(p_tm, tmp, sizeof(struct tm)); - tmp = p_tm; - } - return tmp; -} - -typedef int socklen_t; -#endif - #ifdef HAVE_CONFIG_H #include #endif #ifndef WIN32 -#include /* According to POSIX 1003.1-2001 */ #include @@ -63,25 +40,14 @@ typedef int socklen_t; #include #include -#include #endif -typedef struct tag_conndata -{ - hsocket_t sock; -#ifdef WIN32 - HANDLE tid; -#else - pthread_t tid; - pthread_attr_t attr; -#endif -}conndata_t; - /* ----------------------------------------------------- nano httpd internally globals ----------------------------------------------------- */ static int _httpd_port = 10000; static int _httpd_max_connections = 20; +static int _httpd_max_idle = 120; static hsocket_t _httpd_socket; static hservice_t *_httpd_services_head = NULL; static hservice_t *_httpd_services_tail = NULL; @@ -89,6 +55,10 @@ static int _httpd_run = 1; static int _httpd_terminate_signal = SIGTERM; static conndata_t *_httpd_connection; +#ifdef WIN32 +#include +#endif + /* ----------------------------------------------------- FUNCTION: httpd_init NOTE: This will be called from soap_server_init_args() @@ -96,12 +66,9 @@ NOTE: This will be called from soap_server_init_args() int httpd_init(int argc, char *argv[]) { int i, status; - _httpd_connection=calloc(_httpd_max_connections, sizeof(conndata_t)); for(i=0; i<_httpd_max_connections; i++) { _httpd_connection[i].sock=0; - } - status = hsocket_module_init(); + status = hsocket_module_init(); if (status != 0) return status; - /* write argument information */ log_verbose1("Arguments:"); @@ -123,6 +90,15 @@ int httpd_init(int argc, char *argv[]) /* httpd_register("/httpd/list", service_list); */ + _httpd_connection=calloc(_httpd_max_connections, sizeof(conndata_t)); for(i=0; i<_httpd_max_connections; i++) { memset((char *)&_httpd_connection[i], 0, sizeof(_httpd_connection[i])); + } + +#ifdef WIN32 + if (_beginthread(WSAReaper, 0, NULL)==-1) { + log_error1("Winsock reaper thread failed to start"); + return(-1); + } +#endif /* create socket */ hsocket_init(&_httpd_socket); @@ -312,7 +288,7 @@ static void* httpd_session_main(void *data) log_verbose1("starting httpd_session_main()"); - + conn->atime=time((time_t)0); while (len < 4064) { /*printf("receiving ...\n");*/ total = recv(conn->sock, ch, 1, 0); @@ -361,6 +337,7 @@ static void* httpd_session_main(void *data) hrequest_free(req); #ifdef WIN32 + CloseHandle((HANDLE)conn->tid); _endthread(); return 0; #else @@ -379,65 +356,6 @@ void httpd_term(int sig) _httpd_run = 0; } -static int httpd_accept(hsocket_t sock) -{ - int i; - int err; - socklen_t asize; - struct sockaddr_in addr; - - asize = sizeof(struct sockaddr_in); - while(1) - { - for (i=0;;i++) { - if (i>=_httpd_max_connections) { - Sleep(1000); - i=0; - continue; - } - if (_httpd_connection[i].sock==0) break; - } - _httpd_connection[i].sock = accept(sock, (struct sockaddr *)&addr, &asize); -#ifndef WIN32 - if (_httpd_connection[i].sock == -1) { - _httpd_connection[i].sock=0; - continue; - } -#else - if (_httpd_connection[i].sock == INVALID_SOCKET) - { - if(WSAGetLastError()!=WSAEWOULDBLOCK) - { - log_error1("accept() died... restarting..."); - closesocket(sock); - WSACleanup(); - return INVALID_SOCKET; - } - else - { - _httpd_connection[i].sock=0; - continue; - } - } -#endif - else - { - log_verbose3("accept new socket (%d) from '%s'", _httpd_connection[i].sock, - SAVE_STR(((char*)inet_ntoa(addr.sin_addr))) ); - -#ifdef WIN32 - _httpd_connection[i].tid=(HANDLE)_beginthreadex(NULL, 65535, httpd_session_main, &_httpd_connection[i], 0, &err); -#else - err = pthread_create(&(_httpd_connection[i].tid), &(_httpd_connection[i].attr), httpd_session_main, &_httpd_connection[i]); -#endif - if (err) { - log_error2("Error creating thread: ('%d')", err); - } - } - } - return 0; -} - /* ----------------------------------------------------- FUNCTION: httpd_run ----------------------------------------------------- */ @@ -449,9 +367,7 @@ int httpd_run() struct timeval timeout; -#ifdef WIN32 - unsigned long iMode=HSOCKET_NONBLOCKMODE; -#else +#ifndef WIN32 pthread_attr_init(&attr); #ifdef PTHREAD_CREATE_DETACHED pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); @@ -474,19 +390,11 @@ pthread_attr_init(&attr); log_verbose2("listening to port '%d'", _httpd_port); -#ifndef WIN32 -/* Try always non block mode -#if HSOCKET_BLOCKMODE!=0*/ - fcntl(_httpd_socket, F_SETFL, O_NONBLOCK); -/*#endif*/ -#else - iMode = HSOCKET_NONBLOCKMODE; - if(ioctlsocket(_httpd_socket, FIONBIO, (u_long FAR*) &iMode) == INVALID_SOCKET) - { - log_error1("ioctlsocket error"); - return -1; + err=hsocket_makenonblock(_httpd_socket); + if (err != HSOCKET_OK) { + log_error2("httpd_run(): '%d'", err); + return err; } -#endif timeout.tv_sec = 1; timeout.tv_usec = 0; @@ -512,7 +420,8 @@ pthread_attr_init(&attr); if (!_httpd_run) break; - if (httpd_accept(_httpd_socket) != 0) + if (hsocket_accept(_httpd_socket, httpd_session_main, _httpd_connection, + _httpd_max_connections) != 0) { continue; } @@ -521,9 +430,6 @@ pthread_attr_init(&attr); return 0; } - - - char *httpd_get_postdata(httpd_conn_t *conn, hrequest_t *req, long *received, long max) { char *content_length_str; @@ -570,5 +476,4 @@ char *httpd_get_postdata(httpd_conn_t *conn, hrequest_t *req, long *received, lo free (postdata); return NULL; - } diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c index 12aee6f..844a5ef 100644 --- a/nanohttp/nanohttp-socket.c +++ b/nanohttp/nanohttp-socket.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-socket.c,v 1.12 2004/08/31 13:56:24 rans Exp $ +* $Id: nanohttp-socket.c,v 1.13 2004/08/31 16:34:08 rans Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -27,8 +27,11 @@ #ifdef WIN32 #include "wsockcompat.h" #include +#include #define close(s) closesocket(s) typedef int ssize_t; +#else +#include #endif #ifdef HAVE_CONFIG_H @@ -141,7 +144,7 @@ int hsocket_open(hsocket_t *dsock, const char* hostname, int port) /*-------------------------------------------------- -FUNCTION: hsocket_close +FUNCTION: hsocket_bind ----------------------------------------------------*/ int hsocket_bind(hsocket_t *dsock, int port) { @@ -175,6 +178,70 @@ int hsocket_bind(hsocket_t *dsock, int port) return HSOCKET_OK; } +#ifdef WIN32 +int hsocket_accept(hsocket_t sock, unsigned ( __stdcall *func )( void * ), conndata_t *conns, + int max_conn) +#else +int hsocket_accept(hsocket_t sock, void(*func) (void *), conndata_t *conns, int max_conn) +#endif +{ + int i; + int err; + socklen_t asize; + struct sockaddr_in addr; + + asize = sizeof(struct sockaddr_in); + while(1) + { + for (i=0;;i++) { + if (i>=max_conn) { + Sleep(1000); + i=0; + continue; + } + if (conns[i].sock==0) break; + } + conns[i].sock = accept(sock, (struct sockaddr *)&addr, &asize); +#ifndef WIN32 + if (conns[i].sock == -1) { + conns[i].sock=0; + continue; + } +#else + if (conns[i].sock == INVALID_SOCKET) + { + if(WSAGetLastError()!=WSAEWOULDBLOCK) + { + log_error1("accept() died... restarting..."); + closesocket(sock); + WSACleanup(); + return INVALID_SOCKET; + } + else + { + conns[i].sock=0; + continue; + } + } +#endif + else + { + log_verbose3("accept new socket (%d) from '%s'", conns[i].sock, + SAVE_STR(((char*)inet_ntoa(addr.sin_addr))) ); + +#ifdef WIN32 + conns[i].tid=(HANDLE)_beginthreadex(NULL, 65535, func, &conns[i], 0, &err); +#else + err = pthread_create(&(conns[i].tid), &(conns[i].attr), func, &conns[i]); +#endif + if (err) { + log_error2("Error creating thread: ('%d')", err); + } + } + } + return 0; +} + /*-------------------------------------------------- FUNCTION: hsocket_listen ----------------------------------------------------*/ @@ -394,3 +461,33 @@ int hbufsocket_read(hbufsocket_t *bufsock, char *buffer, int size) return HSOCKET_OK; } } + +int hsocket_makenonblock(hsocket_t sock) +{ +#ifdef WIN32 + unsigned long iMode; + iMode = HSOCKET_NONBLOCKMODE; + if(ioctlsocket(sock, FIONBIO, (u_long FAR*) &iMode) == INVALID_SOCKET) + { + log_error1("ioctlsocket error"); + return -1; + } +#else fcntl(sock, F_SETFL, O_NONBLOCK); +#endif + return HSOCKET_OK; +} + +#ifdef WIN32 + +struct tm *localtime_r(const time_t *const timep, struct tm *p_tm) +{ + static struct tm* tmp; + tmp = localtime(timep); + if (tmp) { + memcpy(p_tm, tmp, sizeof(struct tm)); + tmp = p_tm; + } + return tmp; +} + +#endif diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h index 085ae0c..da3f62c 100644 --- a/nanohttp/nanohttp-socket.h +++ b/nanohttp/nanohttp-socket.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-socket.h,v 1.7 2004/08/30 15:26:53 snowdrop Exp $ + * $Id: nanohttp-socket.h,v 1.8 2004/08/31 16:34:08 rans Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -39,10 +39,16 @@ #define HSOCKET_BLOCKMODE 0 #define HSOCKET_NONBLOCKMODE 1 +#include #ifdef WIN32 #include +#include +#include typedef SOCKET hsocket_t; +typedef int socklen_t; +#define close(s) closesocket(s) #else +#include typedef int hsocket_t; #endif /* @@ -91,7 +97,24 @@ int hsocket_bind(hsocket_t *sock, int port); */ int hsocket_listen(hsocket_t sock, int n); -int hsocket_accept(hsocket_t sock, hsocket_t *dest); +typedef struct tag_conndata +{ + hsocket_t sock; +#ifdef WIN32 + HANDLE tid; +#else + pthread_t tid; + pthread_attr_t attr; +#endif + time_t atime; +}conndata_t; + +#ifdef WIN32 +int hsocket_accept(hsocket_t sock, unsigned ( __stdcall *func )( void * ), conndata_t *conns, + int max_conn); +#else +int hsocket_accept(hsocket_t sock, void(*func) (void *), conndata_t *conns, int max_conn); +#endif /* @@ -172,6 +195,15 @@ typedef struct _bufsocket int hbufsocket_read(hbufsocket_t *bufsock, char *buffer, int size); +/*-------------------------------------------------- +FUNCTION: hsocket_makenonblock +----------------------------------------------------*/ +int hsocket_makenonblock(hsocket_t sock); + +#ifdef WIN32 + +struct tm *localtime_r(const time_t *const timep, struct tm *p_tm); + #endif #endif diff --git a/nanohttp/nanohttp-windows.h b/nanohttp/nanohttp-windows.h new file mode 100644 index 0000000..9e15fbb --- /dev/null +++ b/nanohttp/nanohttp-windows.h @@ -0,0 +1,63 @@ +/****************************************************************** + * $Id: nanohttp-windows.h,v 1.1 2004/08/31 16:34:57 rans Exp $ + * + * CSOAP Project: A http client/server library in C + * Copyright (C) 2003 Ferhat Ayaz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Email: ayaz@jprogrammer.net + ******************************************************************/ +#ifndef NANO_HTTP_WINDOWS_H +#define NANO_HTTP_WINDOWS_H + +#ifdef WIN32 + +static void WSAReaper(void *x) +{ + short int connections; + short int i; + char junk[10]; + int rc; + time_t ctime; + + for (;;) { + connections=0; + ctime=time((time_t)0); + for (i=0;i<_httpd_max_connections;i++) { + if (_httpd_connection[i].tid==0) continue; + GetExitCodeThread((HANDLE)_httpd_connection[i].tid, &rc); + if (rc!=STILL_ACTIVE) continue; + connections++; + if ((ctime-_httpd_connection[i].atime<_httpd_max_idle)|| + (_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); + TerminateThread(_httpd_connection[i].tid, (DWORD)&rc); + CloseHandle(_httpd_connection[i].tid); + memset((char *)&_httpd_connection[i], 0, sizeof(_httpd_connection[i])); + } + Sleep(100); + } + return; +} + +#endif + +#endif -- cgit v1.1-32-gdbae