summaryrefslogtreecommitdiffstats
path: root/nanohttp/nanohttp-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'nanohttp/nanohttp-server.c')
-rw-r--r--nanohttp/nanohttp-server.c143
1 files changed, 68 insertions, 75 deletions
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index d5d77dd..c75eacf 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-server.c,v 1.62 2006/07/09 16:24:19 snowdrop Exp $
+* $Id: nanohttp-server.c,v 1.63 2006/11/19 09:40:14 m0gg Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -41,6 +41,10 @@
#include <sys/types.h>
#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
@@ -73,14 +77,15 @@
#include <process.h>
#endif
-#ifdef MEM_DEBUG
-#include <utils/alloc.h>
-#endif
-
#include "nanohttp-logging.h"
+#include "nanohttp-common.h"
+#include "nanohttp-socket.h"
+#include "nanohttp-stream.h"
+#include "nanohttp-request.h"
#include "nanohttp-server.h"
#include "nanohttp-base64.h"
#include "nanohttp-ssl.h"
+#include "nanohttp-admin.h"
typedef struct _conndata
{
@@ -118,9 +123,6 @@ static hservice_t *_httpd_services_tail = NULL;
static conndata_t *_httpd_connection;
-static int _httpd_enable_service_list = 0;
-static int _httpd_enable_statistics = 0;
-
#ifdef WIN32
static DWORD _httpd_terminate_signal = CTRL_C_EVENT;
static int _httpd_max_idle = 120;
@@ -176,6 +178,7 @@ _httpd_connection_slots_init(void)
#else
pthread_mutex_init(&_httpd_connection_lock, NULL);
#endif
+
_httpd_connection = calloc(_httpd_max_connections, sizeof(conndata_t));
for (i = 0; i < _httpd_max_connections; i++)
hsocket_init(&(_httpd_connection[i].sock));
@@ -183,17 +186,13 @@ _httpd_connection_slots_init(void)
return;
}
-static void
-_httpd_register_builtin_services(void)
+static void
+_httpd_register_builtin_services(int argc, char **argv)
{
+ herror_t status;
- if (_httpd_enable_service_list)
- ; /* httpd_register("/httpd/services",
- _httpd_list_services); */
-
- if (_httpd_enable_statistics)
- ; /* httpd_register("/httpd/statistics",
- _httpd_statistics); */
+ if ((status = httpd_admin_init_args(argc, argv)) != H_OK)
+ log_error2("httpd_admin_init_args failed (%s)", herror_message(status));
return;
}
@@ -218,15 +217,7 @@ httpd_init(int argc, char *argv[])
_httpd_connection_slots_init();
- _httpd_register_builtin_services();
-
-#ifdef WIN32
- /*
- if (_beginthread (WSAReaper, 0, NULL) == -1) { log_error1 ("Winsock
- reaper thread failed to start"); return herror_new("httpd_init",
- THREAD_BEGIN_ERROR, "_beginthread() failed while starting WSAReaper"); }
- */
-#endif
+ _httpd_register_builtin_services(argc, argv);
if ((status = hsocket_init(&_httpd_socket)) != H_OK)
{
@@ -253,6 +244,16 @@ httpd_register_secure(const char *ctx, httpd_service func, httpd_auth auth)
return -1;
}
+ if (!(service->statistics = (struct service_statistics *)malloc(sizeof(struct service_statistics))))
+ {
+ log_error2("malloc failed (%s)", strerror(errno));
+ return -1;
+ }
+ memset(service->statistics, 0, sizeof(struct service_statistics));
+ service->statistics->time.tv_sec = 0;
+ service->statistics->time.tv_usec = 0;
+ pthread_rwlock_init(&(service->statistics->lock), NULL);
+
service->next = NULL;
service->auth = auth;
service->func = func;
@@ -319,7 +320,7 @@ httpd_set_timeout(int t)
const char *
httpd_get_protocol(void)
{
- return hssl_enabled()? "https" : "http";
+ return hssl_enabled() ? "https" : "http";
}
/*--------------------------------------------------
@@ -328,28 +329,24 @@ FUNCTION: httpd_get_conncount
int
httpd_get_conncount(void)
{
- int i;
- int c=0;
+ int i, ret;
- for (i = 0;i<_httpd_max_connections; i++)
+ for (ret = i = 0; i<_httpd_max_connections; i++)
{
-
if (_httpd_connection[i].flag == CONNECTION_IN_USE)
- {
- c++;
- }
+ ret++;
}
- return c;
+ return ret;
}
/*
* -----------------------------------------------------
- * FUNCTION: httpd_services
+ * FUNCTION: httpd_get_services
* -----------------------------------------------------
*/
hservice_t *
-httpd_services(void)
+httpd_get_services(void)
{
return _httpd_services_head;
}
@@ -372,18 +369,15 @@ hservice_free(hservice_t * service)
* FUNCTION: httpd_find_service
* -----------------------------------------------------
*/
-static hservice_t *
-httpd_find_service(const char *ctx)
+hservice_t *
+httpd_find_service(const char *context)
{
- hservice_t *cur = _httpd_services_head;
+ hservice_t *cur;
- while (cur != NULL)
+ for (cur = _httpd_services_head; cur; cur = cur->next)
{
- if (!strcmp(cur->ctx, ctx))
- {
+ if (!strcmp(cur->ctx, context))
return cur;
- }
- cur = cur->next;
}
return _httpd_services_default;
@@ -546,24 +540,6 @@ httpd_free(httpd_conn_t * conn)
return;
}
-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
-}
static int
_httpd_decode_authorization(const char *value, char **user, char **pass)
@@ -657,8 +633,12 @@ httpd_session_main(void *data)
httpd_conn_t *rconn;
hservice_t *service;
herror_t status;
+ struct timeval start, end, duration;
int done;
+ if (gettimeofday(&start, NULL) == -1)
+ log_error2("gettimeofday failed (%s)", strerror(errno));
+
conn = (conndata_t *) data;
log_verbose2("starting new httpd session on socket %d", conn->sock);
@@ -708,13 +688,27 @@ httpd_session_main(void *data)
{
log_verbose3("service '%s' for '%s' found", service->ctx, req->path);
+ pthread_rwlock_wrlock(&(service->statistics->lock));
+ service->statistics->requests++;
+ pthread_rwlock_unlock(&(service->statistics->lock));
+
if (_httpd_authenticate_request(req, service->auth))
{
if (service->func != NULL)
{
service->func(rconn, req);
- if (rconn->out
- && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE)
+
+ if (gettimeofday(&end, NULL) == -1)
+ log_error2("gettimeofday failed (%s)", strerror(errno));
+ timersub(&end, &start, &duration);
+
+ pthread_rwlock_wrlock(&(service->statistics->lock));
+ service->statistics->bytes_received += rconn->sock->bytes_received;
+ service->statistics->bytes_transmitted += rconn->sock->bytes_transmitted;
+ timeradd(&(service->statistics->time), &duration, &(service->statistics->time));
+ pthread_rwlock_unlock(&(service->statistics->lock));
+
+ if (rconn->out && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE)
{
log_verbose1("Connection close requested");
done = 1;
@@ -735,11 +729,13 @@ httpd_session_main(void *data)
{
char *template =
"<html>"
- "<head>"
- "<title>Unauthorized</title>"
+ "<head>"
+ "<title>Unauthorized</title>"
"</head>"
"<body>"
- "<h1>Unauthorized request logged</h1>" "</body>" "</html>";
+ "<h1>Unauthorized request logged</h1>"
+ "</body>"
+ "</html>";
httpd_set_header(rconn, HEADER_WWW_AUTHENTICATE,
"Basic realm=\"nanoHTTP\"");
@@ -1259,8 +1255,7 @@ httpd_mime_next(httpd_conn_t * conn, const char *content_id,
/* Send boundary */
status =
- http_output_stream_write(conn->out, (const byte_t *) buffer,
- strlen(buffer));
+ http_output_stream_write(conn->out, buffer, strlen(buffer));
if (status != H_OK)
return status;
@@ -1274,8 +1269,7 @@ httpd_mime_next(httpd_conn_t * conn, const char *content_id,
content_id ? content_id : "<content-id-not-set>");
status =
- http_output_stream_write(conn->out, (const byte_t *) buffer,
- strlen(buffer));
+ http_output_stream_write(conn->out, buffer, strlen(buffer));
return status;
}
@@ -1289,7 +1283,7 @@ httpd_mime_send_file(httpd_conn_t * conn, const char *content_id,
const char *content_type, const char *transfer_encoding,
const char *filename)
{
- byte_t buffer[MAX_FILE_BUFFER_SIZE];
+ unsigned char buffer[MAX_FILE_BUFFER_SIZE];
herror_t status;
FILE *fd;
size_t size;
@@ -1343,8 +1337,7 @@ httpd_mime_end(httpd_conn_t * conn)
/* Send boundary */
status =
- http_output_stream_write(conn->out, (const byte_t *) buffer,
- strlen(buffer));
+ http_output_stream_write(conn->out, buffer, strlen(buffer));
if (status != H_OK)
return status;