summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nanohttp/nanohttp-client.c46
-rw-r--r--nanohttp/nanohttp-client.h17
-rw-r--r--nanohttp/nanohttp-server.c145
-rw-r--r--nanohttp/nanohttp-socket.c101
-rw-r--r--nanohttp/nanohttp-socket.h36
-rw-r--r--nanohttp/nanohttp-windows.h63
6 files changed, 227 insertions, 181 deletions
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 <nanohttp/nanohttp-client.h>
-#ifdef WIN32
-#include "wsockcompat.h"
-#include <winsock2.h>
-#define close(s) closesocket(s)
-#endif
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -38,23 +32,6 @@
#include <stdlib.h>
-#ifdef WIN32
-
-#include <string.h>
-
-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 <nanohttp/nanohttp-server.h>
-#include <time.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <signal.h>
-#ifdef WIN32
-#include "wsockcompat.h"
-#include <winsock2.h>
-#include <process.h>
-#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 <config.h>
#endif
#ifndef WIN32
-#include <pthread.h>
/* According to POSIX 1003.1-2001 */
#include <sys/select.h>
@@ -63,25 +40,14 @@ typedef int socklen_t;
#include <sys/types.h>
#include <unistd.h>
-#include <fcntl.h>
#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 <nanohttp/nanohttp-windows.h>
+#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 <winsock2.h>
+#include <process.h>
#define close(s) closesocket(s)
typedef int ssize_t;
+#else
+#include <fcntl.h>
#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 <time.h>
#ifdef WIN32
#include <winsock2.h>
+#include <process.h>
+#include <string.h>
typedef SOCKET hsocket_t;
+typedef int socklen_t;
+#define close(s) closesocket(s)
#else
+#include <pthread.h>
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