summaryrefslogtreecommitdiffstats
path: root/nanohttp
diff options
context:
space:
mode:
authorGravatar rans2004-08-26 17:07:47 +0000
committerGravatar rans2004-08-26 17:07:47 +0000
commit8fa610c18388161569d68034243af9c923dbbee9 (patch)
tree7a6734c77bed901fe21a0b1b4b5dc848a3b153af /nanohttp
parent3ad9ad0547145e25657660e3c1c92ffb6905d3dc (diff)
downloadcsoap-8fa610c18388161569d68034243af9c923dbbee9.tar.gz
csoap-8fa610c18388161569d68034243af9c923dbbee9.tar.bz2
http stuff
Diffstat (limited to 'nanohttp')
-rw-r--r--nanohttp/nanohttp-client.c1357
-rw-r--r--nanohttp/nanohttp-common.c1050
-rw-r--r--nanohttp/nanohttp-common.h4
-rw-r--r--nanohttp/nanohttp-server.c680
-rw-r--r--nanohttp/nanohttp-socket.c543
-rw-r--r--nanohttp/nanohttp-socket.h10
-rw-r--r--nanohttp/nanohttp.vcproj173
-rw-r--r--nanohttp/pthread.h1345
-rw-r--r--nanohttp/sched.h174
-rw-r--r--nanohttp/semaphore.h163
-rw-r--r--nanohttp/wsockcompat.h61
11 files changed, 3794 insertions, 1766 deletions
diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c
index 4f62afc..8f49048 100644
--- a/nanohttp/nanohttp-client.c
+++ b/nanohttp/nanohttp-client.c
@@ -1,28 +1,34 @@
/******************************************************************
- * $Id: nanohttp-client.c,v 1.12 2004/06/04 08:55:07 snowdrop 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
- ******************************************************************/
+* $Id: nanohttp-client.c,v 1.13 2004/08/26 17:07:47 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
+******************************************************************/
#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
@@ -30,858 +36,859 @@
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
-
-
+#ifdef WIN32
+#include <string.h>
+static struct tm *localtime_r(const time_t *const timep, struct tm *p_tm)
+{
+ static tm* tmp;
+ tmp = localtime(timep);
+ if (tmp) {
+ memcpy(p_tm, tmp, sizeof(struct tm));
+ tmp = p_tm;
+ }
+ return tmp;
+}
+#endif
/*--------------------------------------------------
- FUNCTION: httpc_new
- DESC: Creates a new http client connection object
- You need to create at least 1 http client connection
- to communicate via http.
+FUNCTION: httpc_new
+DESC: Creates a new http client connection object
+You need to create at least 1 http client connection
+to communicate via http.
----------------------------------------------------*/
httpc_conn_t* httpc_new()
{
- httpc_conn_t* res = (httpc_conn_t*)malloc(sizeof(httpc_conn_t));
+ httpc_conn_t* res = (httpc_conn_t*)malloc(sizeof(httpc_conn_t));
- hsocket_init(&res->sock);
- res->header = NULL;
- res->url = NULL;
+ hsocket_init(&res->sock);
+ res->header = NULL;
+ res->url = NULL;
- return res;
+ return res;
}
/*--------------------------------------------------
- FUNCTION: httpc_free
- DESC: Free the given http client object.
+FUNCTION: httpc_free
+DESC: Free the given http client object.
----------------------------------------------------*/
void httpc_free(httpc_conn_t* conn)
{
- hpair_t *tmp;
-
- if (conn != NULL) {
- hsocket_free(conn->sock);
-
- while (conn->header != NULL) {
- tmp = conn->header;
- conn->header = conn->header->next;
- hpairnode_free(tmp);
- }
-
- free(conn);
- }
+ hpair_t *tmp;
+
+ if (conn != NULL) {
+ hsocket_free(conn->sock);
+
+ while (conn->header != NULL) {
+ tmp = conn->header;
+ conn->header = conn->header->next;
+ hpairnode_free(tmp);
+ }
+
+ free(conn);
+ }
}
/*--------------------------------------------------
- FUNCTION: httpc_set_header
- DESC: Adds a new (key, value) pair to the header
- or modifies the old pair if this function will
- finds another pair with the same 'key' value.
+FUNCTION: httpc_set_header
+DESC: Adds a new (key, value) pair to the header
+or modifies the old pair if this function will
+finds another pair with the same 'key' value.
----------------------------------------------------*/
int httpc_set_header(httpc_conn_t *conn, const char* key, const char* value)
{
- hpair_t *p;
-
- if (conn == NULL) {
- log_warn1("Connection object is NULL");
- return 0;
- }
-
- p = conn->header;
- while (p != NULL) {
- if (p->key != NULL) {
- if (!strcmp(p->key, key)) {
- free(p->value);
- p->value = (char*)malloc(strlen(value)+1);
- strcpy(p->value, value);
- return 1;
- }
- }
- p = p->next;
- }
-
- conn->header = hpairnode_new(key, value, conn->header);
- return 0;
+ hpair_t *p;
+
+ if (conn == NULL) {
+ log_warn1("Connection object is NULL");
+ return 0;
+ }
+
+ p = conn->header;
+ while (p != NULL) {
+ if (p->key != NULL) {
+ if (!strcmp(p->key, key)) {
+ free(p->value);
+ p->value = (char*)malloc(strlen(value)+1);
+ strcpy(p->value, value);
+ return 1;
+ }
+ }
+ p = p->next;
+ }
+
+ conn->header = hpairnode_new(key, value, conn->header);
+ return 0;
}
/*--------------------------------------------------
- FUNCTION: httpc_header_add_date
- DESC: Adds the current date to the header.
+FUNCTION: httpc_header_add_date
+DESC: Adds the current date to the header.
----------------------------------------------------*/
static
void httpc_header_add_date(httpc_conn_t *conn)
{
- char buffer[255];
- time_t nw;
- struct tm stm;
-
- /* Set date */
- nw = time(NULL);
- localtime_r(&nw, &stm);
- strftime(buffer, 255, "%a, %d %b %y %T GMT", &stm);
- httpc_set_header(conn, HEADER_DATE, buffer);
+ char buffer[255];
+ time_t nw;
+ struct tm stm;
+
+ /* Set date */
+ nw = time(NULL);
+ localtime_r(&nw, &stm);
+ strftime(buffer, 255, "%a, %d %b %y %T GMT", &stm);
+ httpc_set_header(conn, HEADER_DATE, buffer);
}
/*--------------------------------------------------
- FUNCTION: httpc_send_header
- DESC: Sends the current header information stored
- in conn through conn->sock.
+FUNCTION: httpc_send_header
+DESC: Sends the current header information stored
+in conn through conn->sock.
----------------------------------------------------*/
int httpc_send_header(httpc_conn_t *conn)
{
- hpair_t *p;
- int status;
- char buffer[1024];
-
- p = conn->header;
- while (p != NULL) {
- if (p->key && p->value) {
- sprintf(buffer, "%s: %s\r\n", p->key, p->value);
- status = hsocket_send(conn->sock, buffer);
- if (status != HSOCKET_OK)
- return status;
- }
- p = p->next;
- }
+ hpair_t *p;
+ int status;
+ char buffer[1024];
+
+ p = conn->header;
+ while (p != NULL) {
+ if (p->key && p->value) {
+ sprintf(buffer, "%s: %s\r\n", p->key, p->value);
+ status = hsocket_send(conn->sock, buffer);
+ if (status != HSOCKET_OK)
+ return status;
+ }
+ p = p->next;
+ }
- status = hsocket_send(conn->sock, "\r\n");
- return status;
+ status = hsocket_send(conn->sock, "\r\n");
+ return status;
}
static
hresponse_t *httpc_receive_header(hsocket_t sock)
{
- hresponse_t *res;
- int done;
- int i;
- int status;
- char buffer[HSOCKET_MAX_BUFSIZE];
- char *response;
- char *rest;
- int rsize;
- int restsize;
-
- /* Receive Response incl. header */
- rsize = restsize = 0;
- response = rest = NULL;
- done = 0;
-
- while (!done) {
-
- status = hsocket_read(sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
-
- if (status <= 0) {
- log_error2("Can not receive response (status:%d)", status);
- return NULL;
- }
-
-
- for (i=0;i<status-2;i++) {
-
- /* log_debug5("%d -> '%c' (%d, %d)", buffer[i], buffer[i],
- buffer[i+1], buffer[i+2]);
- */
- if (buffer[i] == '\n') {
- if (buffer[i+1] == '\n') {
-
- response = (char*)realloc(response, rsize+i+1);
- strncpy(&response[rsize], buffer, i);
- response[rsize+i] = '\0';
- rsize += i;
-
- restsize = status - i - 2;
- rest = (char*)malloc(restsize+1);
- strncpy(rest, &buffer[i+2], restsize);
- rest[restsize] = '\0';
- done = 1;
- break;
-
- } else if (buffer[i+1] == '\r' && buffer[i+2] == '\n') {
-
- response = (char*)realloc(response, rsize+i+1);
- strncpy(&response[rsize], buffer, i);
- response[rsize+i] = '\0';
- rsize += i;
-
- restsize = status - i - 3;
- rest = (char*)malloc(restsize+1);
- strncpy(rest, &buffer[i+3], restsize);
- rest[restsize] = '\0';
- done = 1;
- break;
+ hresponse_t *res;
+ int done;
+ int i;
+ int status;
+ char buffer[HSOCKET_MAX_BUFSIZE];
+ char *response;
+ char *rest;
+ int rsize;
+ int restsize;
+
+ /* Receive Response incl. header */
+ rsize = restsize = 0;
+ response = rest = NULL;
+ done = 0;
+
+ while (!done) {
+
+ status = hsocket_read(sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
+
+ if (status <= 0) {
+ log_error2("Can not receive response (status:%d)", status);
+ return NULL;
+ }
+
+
+ for (i=0;i<status-2;i++) {
+
+ /* log_debug5("%d -> '%c' (%d, %d)", buffer[i], buffer[i],
+ buffer[i+1], buffer[i+2]);
+ */
+ if (buffer[i] == '\n') {
+ if (buffer[i+1] == '\n') {
+
+ response = (char*)realloc(response, rsize+i+1);
+ strncpy(&response[rsize], buffer, i);
+ response[rsize+i] = '\0';
+ rsize += i;
+
+ restsize = status - i - 2;
+ rest = (char*)malloc(restsize+1);
+ strncpy(rest, &buffer[i+2], restsize);
+ rest[restsize] = '\0';
+ done = 1;
+ break;
+
+ } else if (buffer[i+1] == '\r' && buffer[i+2] == '\n') {
+
+ response = (char*)realloc(response, rsize+i+1);
+ strncpy(&response[rsize], buffer, i);
+ response[rsize+i] = '\0';
+ rsize += i;
+
+ restsize = status - i - 3;
+ rest = (char*)malloc(restsize+1);
+ strncpy(rest, &buffer[i+3], restsize);
+ rest[restsize] = '\0';
+ done = 1;
+ break;
+ }
+ }
+ }
+
+ if (!done)
+ rsize += status;
+ }
+
+
+ if (response == NULL) {
+ log_error1("Header too long!");
+ return NULL;
+ }
+
+ res = hresponse_new_from_buffer(response);
+ if (res == NULL) {
+ log_error1("Can't create response");
+ return NULL;
+ }
+
+ res->bodysize = restsize;
+ res->body = rest;
+
+ if (res->errcode == 100) { /* continue */
+ hresponse_free(res);
+ res = httpc_receive_header(sock);
}
- }
- }
-
- if (!done)
- rsize += status;
- }
-
-
- if (response == NULL) {
- log_error1("Header too long!");
- return NULL;
- }
-
- res = hresponse_new_from_buffer(response);
- if (res == NULL) {
- log_error1("Can't create response");
- return NULL;
- }
-
- res->bodysize = restsize;
- res->body = rest;
-
- if (res->errcode == 100) { /* continue */
- hresponse_free(res);
- res = httpc_receive_header(sock);
- }
- return res;
+ return res;
}
static
int httpc_receive_with_connection_closed(httpc_conn_t *conn,
- hresponse_t *res,
- httpc_response_callback cb,
- void *userdata)
+ hresponse_t *res,
+ httpc_response_callback cb,
+ void *userdata)
{
- /* connection closed */
- char *connection_status;
- int status;
- char buffer[HSOCKET_MAX_BUFSIZE];
- int counter;
+ /* connection closed */
+ char *connection_status;
+ int status;
+ char buffer[HSOCKET_MAX_BUFSIZE];
+ int counter;
+
+ counter = 0;
+
+ /* ================================================= */
+ /* Retreive with only "Connection: close" */
+ /* ================================================= */
+ connection_status =
+ hpairnode_get(res->header, HEADER_CONNECTION);
- counter = 0;
+ if (connection_status != NULL &&
+ !strcmp(connection_status, "close")) {
- /* ================================================= */
- /* Retreive with only "Connection: close" */
- /* ================================================= */
- connection_status =
- hpairnode_get(res->header, HEADER_CONNECTION);
+ log_debug1("Server communicates with 'Connection: close' !");
- if (connection_status != NULL &&
- !strcmp(connection_status, "close")) {
+ /* Invoke callback for rest */
+ if (res->bodysize > 0)
+ cb(0, conn, userdata, res->bodysize, res->body);
- log_debug1("Server communicates with 'Connection: close' !");
- /* Invoke callback for rest */
- if (res->bodysize > 0)
- cb(0, conn, userdata, res->bodysize, res->body);
+ while (1) {
+ status = hsocket_read(conn->sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
- while (1) {
-
- status = hsocket_read(conn->sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
+ if (status == 0) { /* close connection */
+ close(conn->sock);
+ return 0;
+ }
- if (status == 0) { /* close connection */
- close(conn->sock);
- return 0;
- }
-
- if (status < 0) { /* error */
- log_error2("Can nor read from socket (status: %d)", status);
- return 11;
- }
+ if (status < 0) { /* error */
+ log_error2("Can nor read from socket (status: %d)", status);
+ return 11;
+ }
- /* Invoke callback */
- cb(counter++, conn, userdata, status, buffer);
- }
+ /* Invoke callback */
+ cb(counter++, conn, userdata, status, buffer);
+ }
- return 0;
- }
+ return 0;
+ }
- return -1;
+ return -1;
}
static
int httpc_receive_with_chunked_encoding(httpc_conn_t *conn,
- hresponse_t *res,
- httpc_response_callback cb,
- void *userdata)
+ hresponse_t *res,
+ httpc_response_callback cb,
+ void *userdata)
{
- /* chunked encoding */
- char *transfer_encoding;
- char *chunk_buffer;
- int chunk_size;
- hbufsocket_t bufsock;
- char chunk_size_str[25];
- int chunk_size_cur;
- int counter;
- char buffer[2];
-
- counter = 0;
- /* ================================================= */
- /* Retreive with chunked encoding */
- /* ================================================= */
-
- /* Check if server communicates with chunked encoding */
- transfer_encoding =
- hpairnode_get(res->header, HEADER_TRANSFER_ENCODING);
-
- if (transfer_encoding != NULL &&
- !strcmp(transfer_encoding, "chunked")) {
-
- log_debug1("Server communicates with chunked encoding !");
-
- /* initialize buffered socket */
- bufsock.sock = conn->sock;
- bufsock.cur = 0;
- bufsock.buffer = res->body;
- bufsock.bufsize = res->bodysize;
-
- chunk_size = 1;
- while (chunk_size > 0) {
-
- /* read chunk size */
- chunk_size_cur = 0;
- while (1) {
-
-
- if (hbufsocket_read(&bufsock, &chunk_size_str[chunk_size_cur], 1)) {
- log_error1("Can not read from socket");
- return 9;
- }
-
- log_debug2("chunk_size_str[chunk_size_cur] = '%c'",
- chunk_size_str[chunk_size_cur]);
+ /* chunked encoding */
+ char *transfer_encoding;
+ char *chunk_buffer;
+ int chunk_size;
+ hbufsocket_t bufsock;
+ char chunk_size_str[25];
+ int chunk_size_cur;
+ int counter;
+ char buffer[2];
- if (chunk_size_str[chunk_size_cur] == '\n') {
- chunk_size_str[chunk_size_cur] = '\0';
- break;
- }
+ counter = 0;
+ /* ================================================= */
+ /* Retreive with chunked encoding */
+ /* ================================================= */
- if (chunk_size_str[chunk_size_cur] != '\r'
- && chunk_size_str[chunk_size_cur] != ';') {
- chunk_size_cur++;
- }
+ /* Check if server communicates with chunked encoding */
+ transfer_encoding =
+ hpairnode_get(res->header, HEADER_TRANSFER_ENCODING);
+
+ if (transfer_encoding != NULL &&
+ !strcmp(transfer_encoding, "chunked")) {
+
+ log_debug1("Server communicates with chunked encoding !");
+
+ /* initialize buffered socket */
+ bufsock.sock = conn->sock;
+ bufsock.cur = 0;
+ bufsock.buffer = (char *)res->body;
+ bufsock.bufsize = res->bodysize;
- } /* while (1) */
-
- chunk_size = strtol(chunk_size_str,(char**)NULL, 16); /* hex to dec */
- log_debug3("chunk_size: '%s' as dec: '%d'",
- chunk_size_str, chunk_size);
-
- if (chunk_size <= 0) break;
-
- chunk_buffer = (char*)malloc(chunk_size+1);
- if (hbufsocket_read(&bufsock, chunk_buffer, chunk_size)) {
- log_error1("Can not read from socket");
- return 9;
- }
- cb(counter++, conn, userdata, chunk_size, chunk_buffer);
- free(chunk_buffer);
-
- /* skip new line */
- buffer[0] = 0; /* reset buffer[0] */
- while (buffer[0] != '\n') {
- hbufsocket_read(&bufsock, &buffer[0], 1);
- }
-
- } /* while (chunk_size > 0) */
-
- /* rest and response are no longer required */
-
- return 0;
-
- } /* if transfer_encodig */
-
- return -1;
+ chunk_size = 1;
+ while (chunk_size > 0) {
+
+ /* read chunk size */
+ chunk_size_cur = 0;
+ while (1) {
+
+
+ if (hbufsocket_read(&bufsock, &chunk_size_str[chunk_size_cur], 1)) {
+ log_error1("Can not read from socket");
+ return 9;
+ }
+
+ log_debug2("chunk_size_str[chunk_size_cur] = '%c'",
+ chunk_size_str[chunk_size_cur]);
+
+ if (chunk_size_str[chunk_size_cur] == '\n') {
+ chunk_size_str[chunk_size_cur] = '\0';
+ break;
+ }
+
+ if (chunk_size_str[chunk_size_cur] != '\r'
+ && chunk_size_str[chunk_size_cur] != ';') {
+ chunk_size_cur++;
+ }
+
+ } /* while (1) */
+
+ chunk_size = strtol(chunk_size_str,(char**)NULL, 16); /* hex to dec */
+ log_debug3("chunk_size: '%s' as dec: '%d'",
+ chunk_size_str, chunk_size);
+
+ if (chunk_size <= 0) break;
+
+ chunk_buffer = (char*)malloc(chunk_size+1);
+ if (hbufsocket_read(&bufsock, chunk_buffer, chunk_size)) {
+ log_error1("Can not read from socket");
+ return 9;
+ }
+ cb(counter++, conn, userdata, chunk_size, chunk_buffer);
+ free(chunk_buffer);
+
+ /* skip new line */
+ buffer[0] = 0; /* reset buffer[0] */
+ while (buffer[0] != '\n') {
+ hbufsocket_read(&bufsock, &buffer[0], 1);
+ }
+
+ } /* while (chunk_size > 0) */
+
+ /* rest and response are no longer required */
+
+ return 0;
+
+ } /* if transfer_encodig */
+
+ return -1;
}
/*
- returns -1 if server does not communicate with
- content-length;
- */
+returns -1 if server does not communicate with
+content-length;
+*/
static
int httpc_receive_with_content_length(httpc_conn_t *conn,
- hresponse_t *res,
- httpc_response_callback cb,
- void *userdata)
+ hresponse_t *res,
+ httpc_response_callback cb,
+ void *userdata)
{
- int counter;
- int content_length;
- int remain_length;
- int recvSize;
- char *content_length_str;
- char buffer[HSOCKET_MAX_BUFSIZE];
+ int counter;
+ int content_length;
+ int remain_length;
+ int recvSize;
+ char *content_length_str;
+ char buffer[HSOCKET_MAX_BUFSIZE];
- /* ================================================= */
- /* Retreive with content-length */
- /* ================================================= */
+ /* ================================================= */
+ /* Retreive with content-length */
+ /* ================================================= */
- /* Check if server communicates with content-length */
- content_length_str =
- hpairnode_get_ignore_case(res->header, HEADER_CONTENT_LENGTH);
+ /* Check if server communicates with content-length */
+ content_length_str =
+ hpairnode_get_ignore_case(res->header, HEADER_CONTENT_LENGTH);
- if (content_length_str != NULL) {
+ if (content_length_str != NULL) {
- log_debug1("Server communicates with content-length!");
-
- /* Invoke callback for rest */
- if (res->bodysize > 0)
- cb(0, conn, userdata, res->bodysize, res->body);
+ log_debug1("Server communicates with content-length!");
- /* content length */
- content_length = atol(content_length_str);
+ /* Invoke callback for rest */
+ if (res->bodysize > 0)
+ cb(0, conn, userdata, res->bodysize, (char *)res->body);
- counter = 1;
- remain_length = content_length - res->bodysize;
- while (remain_length > 0) {
- if (remain_length >= HSOCKET_MAX_BUFSIZE) {
- recvSize = HSOCKET_MAX_BUFSIZE;
- } else {
- recvSize = remain_length;
- }
+ /* content length */
+ content_length = atol(content_length_str);
- if (hsocket_read(conn->sock, buffer, recvSize,1)) {
- log_error1("Can not read from socket!");
- return 9;
- } else {
- cb(counter++, conn, userdata, recvSize, buffer);
- }
+ counter = 1;
+ remain_length = content_length - res->bodysize;
+ while (remain_length > 0) {
+ if (remain_length >= HSOCKET_MAX_BUFSIZE) {
+ recvSize = HSOCKET_MAX_BUFSIZE;
+ } else {
+ recvSize = remain_length;
+ }
- remain_length -= HSOCKET_MAX_BUFSIZE;
+ if (hsocket_read(conn->sock, buffer, recvSize,1)) {
+ log_error1("Can not read from socket!");
+ return 9;
+ } else {
+ cb(counter++, conn, userdata, recvSize, buffer);
+ }
- } /* while */
+ remain_length -= HSOCKET_MAX_BUFSIZE;
- /* rest and response are no longer required */
+ } /* while */
- return 0;
+ /* rest and response are no longer required */
- } /* if content length */
+ return 0;
- return -1;
+ } /* if content length */
+
+ return -1;
}
static
int httpc_receive_response(httpc_conn_t *conn,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, void *userdata)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata)
{
- hresponse_t *res;
- int status;
-
- /* receive header */
- log_verbose1("receiving header");
- res = httpc_receive_header(conn->sock);
- if (res == NULL) return 1;
- log_verbose1("header ok");
-
- /* Invoke callback */
- start_cb(conn, userdata, res->header, res->spec,
- res->errcode, res->desc);
-
- /* try to receive with content length */
- status = httpc_receive_with_content_length(conn, res,
- cb, userdata);
- if (status != -1) {
- hresponse_free(res);
- return status;
- }
-
- status = httpc_receive_with_chunked_encoding(conn, res,
- cb, userdata);
-
- if (status != -1) {
- hresponse_free(res);
- return status;
- }
-
- status = httpc_receive_with_connection_closed(conn, res,
- cb, userdata);
- if (status != -1) {
- hresponse_free(res);
- return status;
- }
-
- log_error1("Unknown server response retreive type!");
+ hresponse_t *res;
+ int status;
+
+ /* receive header */
+ log_verbose1("receiving header");
+ res = httpc_receive_header(conn->sock);
+ if (res == NULL) return 1;
+ log_verbose1("header ok");
+
+ /* Invoke callback */
+ start_cb(conn, userdata, res->header, res->spec,
+ res->errcode, res->desc);
+
+ /* try to receive with content length */
+ status = httpc_receive_with_content_length(conn, res,
+ cb, userdata);
+ if (status != -1) {
+ hresponse_free(res);
+ return status;
+ }
+
+ status = httpc_receive_with_chunked_encoding(conn, res,
+ cb, userdata);
+
+ if (status != -1) {
+ hresponse_free(res);
+ return status;
+ }
+
+ status = httpc_receive_with_connection_closed(conn, res,
+ cb, userdata);
+ if (status != -1) {
+ hresponse_free(res);
+ return status;
+ }
+
+ log_error1("Unknown server response retreive type!");
}
/*--------------------------------------------------
- FUNCTION: httpc_talk_to_server
- DESC: This function is the heart of the httpc
- module. It will send the request and process the
- response.
-
- Here the parameters:
-
- method:
- the request method. This can be HTTP_REQUEST_POST and
- HTTP_REQUEST_GET.
-
- conn:
- the connection object (created with httpc_new())
-
- urlstr:
- the complete url in string format.
- http://<host>:<port>/<context>
- where <port> is not mendatory.
-
- start_cb:
- a callback function, which will be called when
- the response header is completely arrives.
-
- cb:
- a callback function, which will be called everytime
- when data arrives.
-
- content_size:
- size of content to send.
- (only if method is HTTP_REQUEST_POST)
-
- content:
- the content data to send.
- (only if method is HTTP_REQUEST_POST)
-
- userdata:
- a user define data, which will be passed to the
- start_cb and cb callbacks as a parameter. This
- can also be NULL.
-
-
- If success, this function will return 0.
- >0 otherwise.
+FUNCTION: httpc_talk_to_server
+DESC: This function is the heart of the httpc
+module. It will send the request and process the
+response.
+
+Here the parameters:
+
+method:
+the request method. This can be HTTP_REQUEST_POST and
+HTTP_REQUEST_GET.
+
+conn:
+the connection object (created with httpc_new())
+
+urlstr:
+the complete url in string format.
+http://<host>:<port>/<context>
+where <port> is not mendatory.
+
+start_cb:
+a callback function, which will be called when
+the response header is completely arrives.
+
+cb:
+a callback function, which will be called everytime
+when data arrives.
+
+content_size:
+size of content to send.
+(only if method is HTTP_REQUEST_POST)
+
+content:
+the content data to send.
+(only if method is HTTP_REQUEST_POST)
+
+userdata:
+a user define data, which will be passed to the
+start_cb and cb callbacks as a parameter. This
+can also be NULL.
+
+
+If success, this function will return 0.
+>0 otherwise.
----------------------------------------------------*/
static
int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn,
- const char *urlstr)
+ const char *urlstr)
{
- hurl_t *url;
- char buffer[4096];
- int status;
-
-
- if (conn == NULL) {
- log_error1("Connection object is NULL");
- return 1;
- }
-
- /* Build request header */
- httpc_header_add_date(conn);
-
- /* Create url */
- url = hurl_new(urlstr);
- if (url == NULL) {
- log_error2("Can not parse URL '%s'", SAVE_STR(urlstr));
- return 2;
- }
-
- /* Set hostname */
- httpc_set_header(conn, HEADER_HOST, url->host);
-
- /* Open connection */
- status = hsocket_open(&conn->sock, url->host, url->port);
- if (status != HSOCKET_OK) {
- log_error3("Can not open connection to '%s' (status:%d)",
- SAVE_STR(url->host), status);
- return 3;
- }
-
- /* check method */
- if (method == HTTP_REQUEST_GET) {
-
- /* Set GET Header */
- sprintf(buffer, "GET %s HTTP/1.1\r\n",
- (url->context)?url->context:("/"));
-
- } else if (method == HTTP_REQUEST_POST) {
-
- /* Set POST Header */
- sprintf(buffer, "POST %s HTTP/1.1\r\n",
- (url->context)?url->context:("/"));
- } else {
-
- log_error1("Unknown method type!");
- return 15;
- }
-
- status = hsocket_send(conn->sock, buffer);
- if (status != HSOCKET_OK) {
- log_error2("Can not send request (status:%d)", status);
- hsocket_close(conn->sock);
- return 4;
- }
-
- /* Send Header */
- status = httpc_send_header(conn);
- if (status != HSOCKET_OK) {
- log_error2("Can not send header (status:%d)", status);
- hsocket_close(conn->sock);
- return 5;
- }
-
- return status;
-
+ hurl_t *url;
+ char buffer[4096];
+ int status;
+
+
+ if (conn == NULL) {
+ log_error1("Connection object is NULL");
+ return 1;
+ }
+
+ /* Build request header */
+ httpc_header_add_date(conn);
+
+ /* Create url */
+ url = hurl_new(urlstr);
+ if (url == NULL) {
+ log_error2("Can not parse URL '%s'", SAVE_STR(urlstr));
+ return 2;
+ }
+
+ /* Set hostname */
+ httpc_set_header(conn, HEADER_HOST, url->host);
+
+ /* Open connection */
+ status = hsocket_open(&conn->sock, url->host, url->port);
+ if (status != HSOCKET_OK) {
+ log_error3("Can not open connection to '%s' (status:%d)",
+ SAVE_STR(url->host), status);
+ return 3;
+ }
+
+#ifndef WIN32
+#if HSOCKET_BLOCKMODE!=0
+ fcntl(conn->sock, F_SETFL, O_NONBLOCK);
+#endif
+#else
+ unsigned long iMode = HSOCKET_BLOCKMODE;
+ if(ioctlsocket(conn->sock, FIONBIO, (u_long FAR*) &iMode) == INVALID_SOCKET)
+ {
+ log_error1("ioctlsocket error");
+ return -1;
+ }
+
+#endif
+
+ /* check method */
+ if (method == HTTP_REQUEST_GET) {
+
+ /* Set GET Header */
+ sprintf(buffer, "GET %s HTTP/1.1\r\n",
+ (url->context)?url->context:("/"));
+
+ } else if (method == HTTP_REQUEST_POST) {
+
+ /* Set POST Header */
+ sprintf(buffer, "POST %s HTTP/1.1\r\n",
+ (url->context)?url->context:("/"));
+ } else {
+
+ log_error1("Unknown method type!");
+ return 15;
+ }
+
+ status = hsocket_send(conn->sock, buffer);
+ if (status != HSOCKET_OK) {
+ log_error2("Can not send request (status:%d)", status);
+ hsocket_close(conn->sock);
+ return 4;
+ }
+
+ /* Send Header */
+ status = httpc_send_header(conn);
+ if (status != HSOCKET_OK) {
+ log_error2("Can not send header (status:%d)", status);
+ hsocket_close(conn->sock);
+ return 5;
+ }
+
+ return status;
+
}
-
-
+
+
/*--------------------------------------------------
- FUNCTION: httpc_get_cb
- DESC: Wraps the httpc_talk_to_server() function
- to communicate with GET method.
+FUNCTION: httpc_get_cb
+DESC: Wraps the httpc_talk_to_server() function
+to communicate with GET method.
- See the documentation of httpc_talk_to_server()
- for more information.
+See the documentation of httpc_talk_to_server()
+for more information.
----------------------------------------------------*/
int httpc_get_cb(httpc_conn_t *conn, const char *urlstr,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, void *userdata)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata)
{
- int status;
+ int status;
- status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr);
+ status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr);
- if (status != HSOCKET_OK)
- return status;
+ if (status != HSOCKET_OK)
+ return status;
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
+ status = httpc_receive_response(conn, start_cb, cb, userdata);
+ return status;
}
/*--------------------------------------------------
- FUNCTION: httpc_post_cb
- DESC: Wraps the httpc_talk_to_server() function
- to communicate with POST method.
+FUNCTION: httpc_post_cb
+DESC: Wraps the httpc_talk_to_server() function
+to communicate with POST method.
- See the documentation of httpc_talk_to_server()
- for more information.
+See the documentation of httpc_talk_to_server()
+for more information.
- TODO: Add post content rutine
+TODO: Add post content rutine
----------------------------------------------------*/
int httpc_post_cb(httpc_conn_t *conn, const char *urlstr,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, int content_size,
- char *content, void *userdata)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, int content_size,
+ char *content, void *userdata)
{
- int status;
- char buffer[255];
+ int status;
+ char buffer[255];
- sprintf(buffer, "%d", content_size);
- httpc_set_header(conn, HEADER_CONTENT_LENGTH, buffer);
+ sprintf(buffer, "%d", content_size);
+ httpc_set_header(conn, HEADER_CONTENT_LENGTH, buffer);
- status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
- if (status != HSOCKET_OK)
- return status;
+ status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
+ if (status != HSOCKET_OK)
+ return status;
- status = hsocket_nsend(conn->sock, content, content_size);
- if (status != HSOCKET_OK)
- return status;
+ status = hsocket_nsend(conn->sock, content, content_size);
+ if (status != HSOCKET_OK)
+ return status;
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
+ status = httpc_receive_response(conn, start_cb, cb, userdata);
+ return status;
}
-
+
/*======================================================
- The following functions are used internally to wrap
- the httpc_x_cb (x = get|post) functions.
- ======================================================*/
+The following functions are used internally to wrap
+the httpc_x_cb (x = get|post) functions.
+======================================================*/
static
void httpc_custom_res_callback(int counter, httpc_conn_t* conn,
- void *userdata, int size, char *buffer)
+ void *userdata, int size, char *buffer)
{
- hresponse_t *res;
+ hresponse_t *res;
- /* get response object */
- res = (hresponse_t*)userdata;
+ /* get response object */
+ res = (hresponse_t*)userdata;
- /* allocate buffersize */
+ /* allocate buffersize */
- res->bodysize += size;
- res->body = (unsigned char*)realloc(res->body, res->bodysize + 1);
+ res->bodysize += size;
+ res->body = (char *)realloc(res->body, res->bodysize + 1);
- memcpy(&(res->body[res->bodysize-size]), buffer, size);
- res->body[res->bodysize]='\0';
+ memcpy(&(res->body[res->bodysize-size]), buffer, size);
+ res->body[res->bodysize]='\0';
}
static
void httpc_custom_start_callback(httpc_conn_t *conn, void *userdata,
- hpair_t *header, const char *spec,
- int errcode, const char *desc)
+ hpair_t *header, const char *spec,
+ int errcode, const char *desc)
{
- hresponse_t *res;
+ hresponse_t *res;
- /* get response object */
- res = (hresponse_t*)userdata;
+ /* get response object */
+ res = (hresponse_t*)userdata;
- /* set spec */
- if (spec != NULL) {
- strcpy(res->spec, spec);
- }
+ /* set spec */
+ if (spec != NULL) {
+ strcpy(res->spec, spec);
+ }
- /* set errcode */
- res->errcode = errcode;
+ /* set errcode */
+ res->errcode = errcode;
- /* set desc */
- if (desc != NULL) {
- res->desc = (char*)malloc(strlen(desc)+1);
- strcpy(res->desc, desc);
- }
+ /* set desc */
+ if (desc != NULL) {
+ res->desc = (char*)malloc(strlen(desc)+1);
+ strcpy(res->desc, desc);
+ }
- /* set header */
- if (header == NULL) {
- log_warn1("header is NULL!");
- }
+ /* set header */
+ if (header == NULL) {
+ log_warn1("header is NULL!");
+ }
- res->header = hpairnode_copy_deep(header);
+ res->header = hpairnode_copy_deep(header);
}
-
+
/*--------------------------------------------------
- FUNCTION: httpc_get
+FUNCTION: httpc_get
----------------------------------------------------*/
hresponse_t *httpc_get(httpc_conn_t *conn, const char *url)
{
- int status;
- hresponse_t *res;
+ int status;
+ hresponse_t *res;
- res = hresponse_new();
- status = httpc_get_cb(conn, url, httpc_custom_start_callback,
- httpc_custom_res_callback, res);
+ res = hresponse_new();
+ status = httpc_get_cb(conn, url, httpc_custom_start_callback,
+ httpc_custom_res_callback, res);
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
+ if (status != 0) {
+ hresponse_free(res);
+ return NULL;
+ }
- return res;
+ return res;
}
/*--------------------------------------------------
- FUNCTION: httpc_post
+FUNCTION: httpc_post
----------------------------------------------------*/
hresponse_t *httpc_post(httpc_conn_t *conn, const char *url,
- int content_size, const char *content)
+ int content_size, const char *content)
{
- int status;
- hresponse_t *res;
+ int status;
+ hresponse_t *res;
- res = hresponse_new();
- status = httpc_post_cb(conn, url, httpc_custom_start_callback,
- httpc_custom_res_callback, content_size,
- content, res);
+ res = hresponse_new();
+ status = httpc_post_cb(conn, url, httpc_custom_start_callback,
+ httpc_custom_res_callback, content_size,
+ (char *)content, res);
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
+ if (status != 0) {
+ hresponse_free(res);
+ return NULL;
+ }
- return res;
+ return res;
}
/*
- POST Module
- */
+POST Module
+*/
/*--------------------------------------------------
- FUNCTION: httpc_post_open
+FUNCTION: httpc_post_open
----------------------------------------------------*/
int httpc_post_open(httpc_conn_t *conn, const char *urlstr)
{
- int status;
+ int status;
- httpc_set_header(conn, HEADER_TRANSFER_ENCODING, "chunked");
+ httpc_set_header(conn, HEADER_TRANSFER_ENCODING, "chunked");
- status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
- return status;
+ status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
+ return status;
}
/*--------------------------------------------------
- FUNCTION: httpc_post_send
+FUNCTION: httpc_post_send
----------------------------------------------------*/
int httpc_post_send(httpc_conn_t *conn,
- const char* buffer,
- int bufsize)
+ const char* buffer,
+ int bufsize)
{
- char hexsize[100]; /* chunk size in hex */
- int status;
-
- sprintf(hexsize, "%x\r\n", bufsize);
-
- status = hsocket_send(conn->sock, hexsize);
- if (status != HSOCKET_OK)
- return status;
-
- status = hsocket_nsend(conn->sock, buffer, bufsize);
- if (status != HSOCKET_OK)
- return status;
-
- status = hsocket_send(conn->sock, "\r\n");
-
- return status;
-}
+ char hexsize[100]; /* chunk size in hex */
+ int status;
+ sprintf(hexsize, "%x\r\n", bufsize);
-/*--------------------------------------------------
- FUNCTION: httpc_post_finish
-----------------------------------------------------*/
-hresponse_t *httpc_post_finish(httpc_conn_t *conn)
-{
- int status;
- hresponse_t *res;
+ status = hsocket_send(conn->sock, hexsize);
+ if (status != HSOCKET_OK)
+ return status;
- res = hresponse_new();
- status = httpc_post_finish_cb(conn, httpc_custom_start_callback,
- httpc_custom_res_callback, res);
+ status = hsocket_nsend(conn->sock, buffer, bufsize);
+ if (status != HSOCKET_OK)
+ return status;
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
+ status = hsocket_send(conn->sock, "\r\n");
- return res;
+ return status;
}
-
/*--------------------------------------------------
- FUNCTION: httpc_post_finish_cb
+FUNCTION: httpc_post_finish_cb
----------------------------------------------------*/
int httpc_post_finish_cb(httpc_conn_t *conn,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb,
- void *userdata)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb,
+ void *userdata)
{
- int status;
-
- status = hsocket_send(conn->sock, "0\r\n\r\n");
- if (status != HSOCKET_OK) return status;
-
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ int status;
+ status = hsocket_send(conn->sock, "0\r\n\r\n");
+ if (status != HSOCKET_OK) return status;
+ status = httpc_receive_response(conn, start_cb, cb, userdata);
+ return status;
+}
+/*--------------------------------------------------
+FUNCTION: httpc_post_finish
+----------------------------------------------------*/
+hresponse_t *httpc_post_finish(httpc_conn_t *conn)
+{
+ int status;
+ hresponse_t *res;
+ res = hresponse_new();
+ status = httpc_post_finish_cb(conn, httpc_custom_start_callback,
+ httpc_custom_res_callback, res);
+ if (status != 0) {
+ hresponse_free(res);
+ return NULL;
+ }
+ return res;
+}
diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c
index 1d00d42..6fac5ba 100644
--- a/nanohttp/nanohttp-common.c
+++ b/nanohttp/nanohttp-common.c
@@ -1,26 +1,26 @@
/******************************************************************
- * $Id: nanohttp-common.c,v 1.8 2004/02/03 08:59:23 snowdrop 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
- ******************************************************************/
+* $Id: nanohttp-common.c,v 1.9 2004/08/26 17:07:47 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
+******************************************************************/
#include <nanohttp/nanohttp-common.h>
@@ -28,663 +28,683 @@
#include <stdlib.h>
#include <stdarg.h>
+#ifdef WIN32
+#include <string.h>
+static char *strtok_r (char *s, const char *delim, char **save_ptr)
+{
+ char *token;
+
+ if (s == NULL)
+ s = *save_ptr;
+
+ /* Scan leading delimiters. */
+ s += strspn (s, delim);
+ if (*s == '\0')
+ return NULL;
+
+ /* Find the end of the token. */
+ token = s;
+ s = strpbrk (token, delim);
+ if (s == NULL)
+ /* This token finishes the string. */
+ *save_ptr = strchr (token, '\0');
+ else
+ {
+ /* Terminate the token and make *SAVE_PTR point past it. */
+ *s = '\0';
+ *save_ptr = s + 1;
+ }
+ return token;
+}
+#endif
static log_level_t loglevel = HLOG_DEBUG;
log_level_t log_set_level(log_level_t level)
{
- log_level_t old = loglevel;
- loglevel = level;
- return old;
+ log_level_t old = loglevel;
+ loglevel = level;
+ return old;
}
log_level_t log_get_level()
{
- return loglevel;
+ return loglevel;
}
-
static
void log_write(log_level_t level, const char *prefix,
- const char* func, const char *format, va_list ap)
+ const char* func, const char *format, va_list ap)
{
- char buffer[1054];
- char buffer2[1054];
-
- if (level < loglevel) return;
-
- sprintf(buffer, "*%s*: [%s] %s\n", prefix, func, format);
- vsprintf(buffer2, buffer, ap);
- printf(buffer2);
- fflush(stdout);
+ char buffer[1054];
+ char buffer2[1054];
+
+ if (level < loglevel) return;
+
+ sprintf(buffer, "*%s*: [%s] %s\n", prefix, func, format);
+ vsprintf(buffer2, buffer, ap);
+ printf(buffer2);
+ fflush(stdout);
}
void log_verbose(const char* FUNC, const char *format, ...)
{
- va_list ap;
-
- va_start(ap, format);
- log_write(HLOG_VERBOSE, "VERBOSE", FUNC, format, ap);
- va_end(ap);
+ va_list ap;
+
+ va_start(ap, format);
+ log_write(HLOG_VERBOSE, "VERBOSE", FUNC, format, ap);
+ va_end(ap);
}
void log_debug(const char* FUNC, const char *format, ...)
{
- va_list ap;
-
- va_start(ap, format);
- log_write(HLOG_DEBUG, "DEBUG", FUNC, format, ap);
- va_end(ap);
+ va_list ap;
+
+ va_start(ap, format);
+ log_write(HLOG_DEBUG, "DEBUG", FUNC, format, ap);
+ va_end(ap);
}
void log_info(const char* FUNC, const char *format, ...)
{
- va_list ap;
-
- va_start(ap, format);
- log_write(HLOG_INFO, "INFO", FUNC, format, ap);
- va_end(ap);
+ va_list ap;
+
+ va_start(ap, format);
+ log_write(HLOG_INFO, "INFO", FUNC, format, ap);
+ va_end(ap);
}
void log_warn(const char* FUNC, const char *format, ...)
{
- va_list ap;
-
- va_start(ap, format);
- log_write(HLOG_WARN, "WARN", FUNC, format, ap);
- va_end(ap);
+ va_list ap;
+
+ va_start(ap, format);
+ log_write(HLOG_WARN, "WARN", FUNC, format, ap);
+ va_end(ap);
}
void log_error(const char* FUNC, const char *format, ...)
{
- va_list ap;
-
- va_start(ap, format);
- log_write(HLOG_ERROR, "ERROR", FUNC, format, ap);
- va_end(ap);
+ va_list ap;
+
+ va_start(ap, format);
+ log_write(HLOG_ERROR, "ERROR", FUNC, format, ap);
+ va_end(ap);
}
/* -----------------------------------------
- FUNCTION: strcmpigcase
- ------------------------------------------ */
+FUNCTION: strcmpigcase
+------------------------------------------ */
int strcmpigcase(const char *s1, const char *s2)
{
- int l1, l2, i;
+ int l1, l2, i;
+
+ if (s1 == NULL && s2 == NULL) return 1;
+ if (s1 == NULL || s2 == NULL) return 0;
- if (s1 == NULL && s2 == NULL) return 1;
- if (s1 == NULL || s2 == NULL) return 0;
+ l1 = strlen(s1);
+ l2 = strlen(s2);
- l1 = strlen(s1);
- l2 = strlen(s2);
+ if (l1 != l2) return 0;
- if (l1 != l2) return 0;
-
- for (i=0;i<l1;i++)
- if (toupper(s1[i]) != toupper(s2[i]))
- return 0;
+ for (i=0;i<l1;i++)
+ if (toupper(s1[i]) != toupper(s2[i]))
+ return 0;
- return 1;
+ return 1;
}
hpair_t *hpairnode_new(const char* key, const char* value, hpair_t *next)
{
- hpair_t *pair;
+ hpair_t *pair;
- log_verbose3("new pair ('%s','%s')", SAVE_STR(key), SAVE_STR(value));
- pair = (hpair_t*)malloc(sizeof(hpair_t));
+ log_verbose3("new pair ('%s','%s')", SAVE_STR(key), SAVE_STR(value));
+ pair = (hpair_t*)malloc(sizeof(hpair_t));
- if (key != NULL) {
- pair->key = (char*)malloc(strlen(key)+1);
- strcpy(pair->key, key);
- } else {
- pair->key = NULL;
- }
+ if (key != NULL) {
+ pair->key = (char*)malloc(strlen(key)+1);
+ strcpy(pair->key, key);
+ } else {
+ pair->key = NULL;
+ }
- if (value != NULL) {
- pair->value = (char*)malloc(strlen(value)+1);
- strcpy(pair->value, value);
- } else {
- pair->value = NULL;
- }
+ if (value != NULL) {
+ pair->value = (char*)malloc(strlen(value)+1);
+ strcpy(pair->value, value);
+ } else {
+ pair->value = NULL;
+ }
- pair->next = next;
+ pair->next = next;
- return pair;
+ return pair;
}
hpair_t *hpairnode_parse(const char *str, const char *delim, hpair_t *next)
{
- hpair_t *pair;
- char *key, *value;
- int c;
-
- pair = (hpair_t*)malloc(sizeof(hpair_t));
- pair->key = "";
- pair->value = "";
- pair->next = next;
-
- key = strtok_r(str, delim, &value);
-
- if (key != NULL) {
- pair->key = (char*)malloc(strlen(key)+1);
- strcpy(pair->key, key);
- }
-
- if (value != NULL) {
- for (c=0;value[c]==' ';c++); /* skip white space */
- pair->value = (char*)malloc(strlen(&value[c])+1);
- strcpy(pair->value, &value[c]);
- }
-
- return pair;
+ hpair_t *pair;
+ char *key, *value;
+ int c;
+
+ pair = (hpair_t*)malloc(sizeof(hpair_t));
+ pair->key = "";
+ pair->value = "";
+ pair->next = next;
+
+ key = strtok_r((char *)str, delim, &value);
+
+ if (key != NULL) {
+ pair->key = (char*)malloc(strlen(key)+1);
+ strcpy(pair->key, key);
+ }
+
+ if (value != NULL) {
+ for (c=0;value[c]==' ';c++); /* skip white space */
+ pair->value = (char*)malloc(strlen(&value[c])+1);
+ strcpy(pair->value, &value[c]);
+ }
+
+ return pair;
}
hpair_t* hpairnode_copy(const hpair_t *src)
{
- hpair_t *pair;
+ hpair_t *pair;
- if (src == NULL) return NULL;
+ if (src == NULL) return NULL;
- pair = hpairnode_new(src->key, src->value, NULL);
- return pair;
+ pair = hpairnode_new(src->key, src->value, NULL);
+ return pair;
}
hpair_t* hpairnode_copy_deep(const hpair_t *src)
{
- hpair_t *pair, *result, *next;
+ hpair_t *pair, *result, *next;
+
+ if (src == NULL) return NULL;
- if (src == NULL) return NULL;
+ result = hpairnode_copy(src);
- result = hpairnode_copy(src);
+ next = src->next;
+ pair = result;
- next = src->next;
- pair = result;
+ while (next != NULL) {
+ pair->next = hpairnode_copy(next);
+ pair = pair->next;
+ next = next->next;
+ }
- while (next != NULL) {
- pair->next = hpairnode_copy(next);
- pair = pair->next;
- next = next->next;
- }
-
- return result;
+ return result;
}
void hpairnode_dump(hpair_t *pair)
{
- if (pair == NULL) {
- log_verbose1("(NULL)[]");
- return;
- }
-
- log_verbose5("(%p)['%s','%s','%p']", pair,
- SAVE_STR(pair->key), SAVE_STR(pair->value),
- pair->next);
+ if (pair == NULL) {
+ log_verbose1("(NULL)[]");
+ return;
+ }
+
+ log_verbose5("(%p)['%s','%s','%p']", pair,
+ SAVE_STR(pair->key), SAVE_STR(pair->value),
+ pair->next);
}
void hpairnode_dump_deep(hpair_t *pair)
{
- hpair_t *p;
- p = pair;
+ hpair_t *p;
+ p = pair;
- log_verbose1("-- BEGIN dump hpairnode_t --");
+ log_verbose1("-- BEGIN dump hpairnode_t --");
- while (p != NULL) {
- hpairnode_dump(p);
- p = p->next;
- }
+ while (p != NULL) {
+ hpairnode_dump(p);
+ p = p->next;
+ }
- log_verbose1("-- END dump hpairnode_t --\n");
+ log_verbose1("-- END dump hpairnode_t --\n");
}
void hpairnode_free(hpair_t *pair)
{
- if (pair == NULL) return;
-
- free(pair->key);
- free(pair->value);
-
- free(pair);
+ if (pair == NULL) return;
+
+ free(pair->key);
+ free(pair->value);
+
+ free(pair);
}
void hpairnode_free_deep(hpair_t *pair)
{
- hpair_t *tmp;
+ hpair_t *tmp;
- while (pair != NULL) {
- tmp = pair->next;
- hpairnode_free(pair);
- pair=tmp;
- }
+ while (pair != NULL) {
+ tmp = pair->next;
+ hpairnode_free(pair);
+ pair=tmp;
+ }
}
char *hpairnode_get_ignore_case(hpair_t *pair, const char* key)
{
- if (key == NULL) {
- log_error1("key is NULL");
- return NULL;
- }
-
- while (pair != NULL) {
- if (pair->key != NULL) {
- if (strcmpigcase(pair->key, key)) {
- return pair->value;
- }
- }
- pair = pair->next;
- }
-
- return NULL;
+ if (key == NULL) {
+ log_error1("key is NULL");
+ return NULL;
+ }
+
+ while (pair != NULL) {
+ if (pair->key != NULL) {
+ if (strcmpigcase(pair->key, key)) {
+ return pair->value;
+ }
+ }
+ pair = pair->next;
+ }
+
+ return NULL;
}
char *hpairnode_get(hpair_t *pair, const char* key)
{
- if (key == NULL) {
- log_error1("key is NULL");
- return NULL;
- }
-
- while (pair != NULL) {
- if (pair->key != NULL) {
- if (!strcmp(pair->key, key)) {
- return pair->value;
- }
- }
- pair = pair->next;
- }
-
- return NULL;
+ if (key == NULL) {
+ log_error1("key is NULL");
+ return NULL;
+ }
+
+ while (pair != NULL) {
+ if (pair->key != NULL) {
+ if (!strcmp(pair->key, key)) {
+ return pair->value;
+ }
+ }
+ pair = pair->next;
+ }
+
+ return NULL;
}
static
void hurl_dump(const hurl_t *url)
{
- if (url == NULL) {
- log_error1("url is NULL!");
- return ;
- }
+ if (url == NULL) {
+ log_error1("url is NULL!");
+ return ;
+ }
- log_verbose2("PROTOCOL : %s", SAVE_STR(url->protocol));
- log_verbose2(" HOST : %s", SAVE_STR(url->host));
- log_verbose2(" PORT : %d", url->port);
- log_verbose2(" CONTEXT : %s", SAVE_STR(url->context));
+ log_verbose2("PROTOCOL : %s", SAVE_STR(url->protocol));
+ log_verbose2(" HOST : %s", SAVE_STR(url->host));
+ log_verbose2(" PORT : %d", url->port);
+ log_verbose2(" CONTEXT : %s", SAVE_STR(url->context));
}
hurl_t* hurl_new(const char* urlstr)
{
- int iprotocol;
- int ihost;
- int iport;
- int len;
- int size;
- hurl_t *url;
- char tmp[8];
-
- iprotocol = 0;
- len = strlen(urlstr);
-
- /* find protocol */
- while (urlstr[iprotocol] != ':' && urlstr[iprotocol] != '\0')
- {
- iprotocol++;
- }
-
- if (iprotocol == 0) {
- log_error1("no protocol");
- return NULL;
- }
-
- if (iprotocol + 3 >= len) {
- log_error1("no host");
- return NULL;
- }
-
- if ( urlstr[iprotocol] != ':'
- && urlstr[iprotocol+1] != '/'
- && urlstr[iprotocol+2] != '/')
- {
- log_error1("no protocol");
- return NULL;
- }
-
- /* find host */
- ihost = iprotocol + 3;
- while (urlstr[ihost] != ':'
- && urlstr[ihost] != '/'
- && urlstr[ihost] != '\0')
- {
- ihost++;
- }
-
- if (ihost == iprotocol + 1) {
- log_error1("no host");
- return NULL;
- }
-
- /* find port */
- iport = ihost;
- if (ihost + 1 < len) {
- if (urlstr[ihost] == ':') {
- while (urlstr[iport] != '/' && urlstr[iport] != '\0') {
- iport++;
- }
- }
- }
-
- url = (hurl_t*)malloc(sizeof(hurl_t));
-
- url->protocol = (char*)malloc(sizeof(char)*iprotocol+1);
- strncpy(url->protocol, urlstr, iprotocol);
- url->protocol[iprotocol] = '\0';
-
- size = ihost - iprotocol - 3;
- url->host = (char*)malloc(sizeof(char)*size + 1);
- strncpy(url->host, &urlstr[iprotocol+3], size);
- url->host[size] = '\0';
-
- if (iport > ihost)
- {
- size = iport - ihost;
- strncpy(tmp, &urlstr[ihost+1], size);
- url->port = atoi(tmp);
- } else {
- url->port = 80;
- }
-
- len = strlen(urlstr);
- if (len > iport )
- {
- size = len - iport;
- url->context = (char*)malloc(sizeof(char)*size+1);
- strncpy(url->context, &urlstr[iport], size);
- url->context[size]='\0';
- } else {
- url->context = NULL;
- }
-
- hurl_dump(url);
-
- return url;
+ int iprotocol;
+ int ihost;
+ int iport;
+ int len;
+ int size;
+ hurl_t *url;
+ char tmp[8];
+
+ iprotocol = 0;
+ len = strlen(urlstr);
+
+ /* find protocol */
+ while (urlstr[iprotocol] != ':' && urlstr[iprotocol] != '\0')
+ {
+ iprotocol++;
+ }
+
+ if (iprotocol == 0) {
+ log_error1("no protocol");
+ return NULL;
+ }
+
+ if (iprotocol + 3 >= len) {
+ log_error1("no host");
+ return NULL;
+ }
+
+ if ( urlstr[iprotocol] != ':'
+ && urlstr[iprotocol+1] != '/'
+ && urlstr[iprotocol+2] != '/')
+ {
+ log_error1("no protocol");
+ return NULL;
+ }
+
+ /* find host */
+ ihost = iprotocol + 3;
+ while (urlstr[ihost] != ':'
+ && urlstr[ihost] != '/'
+ && urlstr[ihost] != '\0')
+ {
+ ihost++;
+ }
+
+ if (ihost == iprotocol + 1) {
+ log_error1("no host");
+ return NULL;
+ }
+
+ /* find port */
+ iport = ihost;
+ if (ihost + 1 < len) {
+ if (urlstr[ihost] == ':') {
+ while (urlstr[iport] != '/' && urlstr[iport] != '\0') {
+ iport++;
+ }
+ }
+ }
+
+ url = (hurl_t*)malloc(sizeof(hurl_t));
+
+ url->protocol = (char*)malloc(sizeof(char)*iprotocol+1);
+ strncpy(url->protocol, urlstr, iprotocol);
+ url->protocol[iprotocol] = '\0';
+
+ size = ihost - iprotocol - 3;
+ url->host = (char*)malloc(sizeof(char)*size + 1);
+ strncpy(url->host, &urlstr[iprotocol+3], size);
+ url->host[size] = '\0';
+
+ if (iport > ihost)
+ {
+ size = iport - ihost;
+ strncpy(tmp, &urlstr[ihost+1], size);
+ url->port = atoi(tmp);
+ } else {
+ url->port = 80;
+ }
+
+ len = strlen(urlstr);
+ if (len > iport )
+ {
+ size = len - iport;
+ url->context = (char*)malloc(sizeof(char)*size+1);
+ strncpy(url->context, &urlstr[iport], size);
+ url->context[size]='\0';
+ } else {
+ url->context = NULL;
+ }
+
+ hurl_dump(url);
+
+ return url;
}
void hurl_free(hurl_t *url)
{
- if (url == NULL) return;
+ if (url == NULL) return;
- free(url->protocol);
- free(url->host);
- free(url->context);
+ free(url->protocol);
+ free(url->host);
+ free(url->context);
- free(url);
+ free(url);
}
/* request stuff */
/* -----------------------------------------------------
- FUNCTION: hrequest_new_from_buffer
+FUNCTION: hrequest_new_from_buffer
----------------------------------------------------- */
hrequest_t *hrequest_new_from_buffer(char *data)
{
- hrequest_t *req;
- hpair_t *hpair = NULL, *qpair = NULL, *tmppair = NULL;
-
- char *tmp;
- char *tmp2;
- char *saveptr;
- char *saveptr2;
- char *saveptr3;
- char *result;
- char *key;
- char *value;
- char *opt_key;
- char *opt_value;
- int firstline = 1;
-
- req = (hrequest_t*)malloc(sizeof(hrequest_t));
-
- req->method = NULL;
- req->spec = NULL;
- req->path = NULL;
- req->query = NULL;
- req->header = NULL;
-
- tmp = data;
-
- for (;;) {
- result = (char*)strtok_r(tmp, "\n", &saveptr);
- tmp=saveptr;
-
- if (result == NULL)
- break;
-
- if (firstline) {
- firstline=0;
- tmp2 = result;
-
- /* parse [GET|POST] [PATH] [SPEC] */
- key = (char*)strtok_r(tmp2," ", &saveptr2);
-
- /* save method (get or post) */
- tmp2 = saveptr2;
- if (key != NULL) {
- req->method = (char*)malloc(strlen(key)+1);
- strcpy(req->method, key);
- }
-
- /* below is key the path and tmp2 the spec */
- key = (char*)strtok_r(tmp2," ", &saveptr2);
-
- /* save spec */
- tmp2 = saveptr2;
- if (tmp2 != NULL) {
- req->spec = (char*)malloc(strlen(tmp2)+1);
- strcpy(req->spec, tmp2);
- }
-
- /* parse and save path+query
- parse: /path/of/target?key1=value1&key2=value2...
- */
-
- if (key != NULL) {
- tmp2 = key;
- key = (char*)strtok_r(tmp2,"?", &saveptr2);
- tmp2 = saveptr2;
-
- /* save path */
- req->path = (char*)malloc(strlen(key)+1);
- strcpy(req->path, key);
-
- /* parse options */
- for (;;) {
- key = (char*)strtok_r(tmp2,"&",&saveptr2);
- tmp2 = saveptr2;
-
- if (key == NULL)
- break;
-
- opt_key = (char*)strtok_r(key,"=", &saveptr3);
- opt_value = saveptr3;
-
- if (opt_value == NULL)
- opt_value = "";
-
- /* create option pair */
- if (opt_key != NULL) {
- tmppair = (hpair_t*)malloc(sizeof(hpair_t));
-
- if (req->query == NULL) {
- req->query = qpair = tmppair;
- } else {
- qpair->next = tmppair;
- qpair = tmppair;
- }
-
- /* fill hpairnode_t struct */
- qpair->next = NULL;
- qpair->key = (char*)malloc(strlen(opt_key)+1);
- qpair->value = (char*)malloc(strlen(opt_value)+1);
-
- strcpy(qpair->key, opt_key);
- strcpy(qpair->value, opt_value);
-
- }
+ hrequest_t *req;
+ hpair_t *hpair = NULL, *qpair = NULL, *tmppair = NULL;
+
+ char *tmp;
+ char *tmp2;
+ char *saveptr;
+ char *saveptr2;
+ char *saveptr3;
+ char *result;
+ char *key;
+ char *value;
+ char *opt_key;
+ char *opt_value;
+ int firstline = 1;
+
+ req = (hrequest_t*)malloc(sizeof(hrequest_t));
+
+ req->method = NULL;
+ req->spec = NULL;
+ req->path = NULL;
+ req->query = NULL;
+ req->header = NULL;
+
+ tmp = data;
+
+ for (;;) {
+ result = (char*)strtok_r(tmp, "\n", &saveptr);
+ tmp=saveptr;
+
+ if (result == NULL)
+ break;
+
+ if (firstline) {
+ firstline=0;
+ tmp2 = result;
+
+ /* parse [GET|POST] [PATH] [SPEC] */
+ key = (char*)strtok_r(tmp2," ", &saveptr2);
+
+ /* save method (get or post) */
+ tmp2 = saveptr2;
+ if (key != NULL) {
+ req->method = (char*)malloc(strlen(key)+1);
+ strcpy(req->method, key);
+ }
+
+ /* below is key the path and tmp2 the spec */
+ key = (char*)strtok_r(tmp2," ", &saveptr2);
+
+ /* save spec */
+ tmp2 = saveptr2;
+ if (tmp2 != NULL) {
+ req->spec = (char*)malloc(strlen(tmp2)+1);
+ strcpy(req->spec, tmp2);
+ }
+
+ /* parse and save path+query
+ parse: /path/of/target?key1=value1&key2=value2...
+ */
+
+ if (key != NULL) {
+ tmp2 = key;
+ key = (char*)strtok_r(tmp2,"?", &saveptr2);
+ tmp2 = saveptr2;
+
+ /* save path */
+ req->path = (char*)malloc(strlen(key)+1);
+ strcpy(req->path, key);
+
+ /* parse options */
+ for (;;) {
+ key = (char*)strtok_r(tmp2,"&",&saveptr2);
+ tmp2 = saveptr2;
+
+ if (key == NULL)
+ break;
+
+ opt_key = (char*)strtok_r(key,"=", &saveptr3);
+ opt_value = saveptr3;
+
+ if (opt_value == NULL)
+ opt_value = "";
+
+ /* create option pair */
+ if (opt_key != NULL) {
+ tmppair = (hpair_t*)malloc(sizeof(hpair_t));
+
+ if (req->query == NULL) {
+ req->query = qpair = tmppair;
+ } else {
+ qpair->next = tmppair;
+ qpair = tmppair;
+ }
+
+ /* fill hpairnode_t struct */
+ qpair->next = NULL;
+ qpair->key = (char*)malloc(strlen(opt_key)+1);
+ qpair->value = (char*)malloc(strlen(opt_value)+1);
+
+ strcpy(qpair->key, opt_key);
+ strcpy(qpair->value, opt_value);
+
+ }
+ }
+ }
+
+ } else {
+
+ /* parse "key: value" */
+ tmp2 = result;
+ key = (char*)strtok_r(tmp2, ": ", &saveptr2);
+ value = saveptr2;
+
+ /* create pair */
+ tmppair = (hpair_t*)malloc(sizeof(hpair_t));
+
+ if (req->header == NULL) {
+ req->header = hpair = tmppair;
+ } else {
+ hpair->next = tmppair;
+ hpair = tmppair;
+ }
+
+ /* fill pairnode_t struct */
+ hpair->next = NULL;
+ hpair->key = (char*)malloc(strlen(key)+1);
+ hpair->value = (char*)malloc(strlen(value)+1);
+
+ strcpy(hpair->key, key);
+ strcpy(hpair->value, value);
+ }
}
- }
-
- } else {
-
- /* parse "key: value" */
- tmp2 = result;
- key = (char*)strtok_r(tmp2, ": ", &saveptr2);
- value = saveptr2;
-
- /* create pair */
- tmppair = (hpair_t*)malloc(sizeof(hpair_t));
-
- if (req->header == NULL) {
- req->header = hpair = tmppair;
- } else {
- hpair->next = tmppair;
- hpair = tmppair;
- }
-
- /* fill pairnode_t struct */
- hpair->next = NULL;
- hpair->key = (char*)malloc(strlen(key)+1);
- hpair->value = (char*)malloc(strlen(value)+1);
-
- strcpy(hpair->key, key);
- strcpy(hpair->value, value);
- }
- }
-
- return req;
+
+ return req;
}
void hrequest_free(hrequest_t *req)
{
- if (req == NULL) return;
+ if (req == NULL) return;
- free(req->method);
- free(req->path);
- free(req->spec);
+ free(req->method);
+ free(req->path);
+ free(req->spec);
+
+ hpairnode_free_deep(req->header);
+ hpairnode_free_deep(req->query);
- hpairnode_free_deep(req->header);
- hpairnode_free_deep(req->query);
-
}
/* response stuff */
/* -------------------------------------------
- FUNCTION: hresponse_new
- ---------------------------------------------*/
+FUNCTION: hresponse_new
+---------------------------------------------*/
hresponse_t *hresponse_new()
{
- hresponse_t *res;
-
- /* create response object */
- res = (hresponse_t*)malloc(sizeof(hresponse_t));
- res->spec[0] = '\0';
- res->errcode = -1;
- res->desc = NULL;
- res->header = NULL;
- res->body = NULL;
- res->bodysize = 0;
-
- return res;
+ hresponse_t *res;
+
+ /* create response object */
+ res = (hresponse_t*)malloc(sizeof(hresponse_t));
+ res->spec[0] = '\0';
+ res->errcode = -1;
+ res->desc = NULL;
+ res->header = NULL;
+ res->body = NULL;
+ res->bodysize = 0;
+
+ return res;
}
/* -------------------------------------------
- FUNCTION: hresponse_new_from_buffer
- ---------------------------------------------*/
+FUNCTION: hresponse_new_from_buffer
+---------------------------------------------*/
hresponse_t *hresponse_new_from_buffer(const char* buffer)
{
- hresponse_t *res;
- char *s1, *s2, *str;
- hpair_t *pair;
-
- /* create response object */
- res = hresponse_new();
-
- /* *** parse spec *** */
- /* [HTTP/1.1 | 1.2] [CODE] [DESC] */
-
- /* stage 1: HTTP spec */
- str = (char*)strtok_r(buffer, " ", &s2);
- s1 = s2;
- if (str == NULL) { log_error1("Parse error"); return NULL; }
-
- strncpy(res->spec, str, 10);
-
- /* stage 2: http code */
- str = (char*)strtok_r(s1, " ", &s2);
- s1 = s2;
- if (str == NULL) { log_error1("Parse error"); return NULL; }
-
- res->errcode = atoi(str);
-
- /* stage 3: description text */
- str = (char*)strtok_r(s1, "\r\n", &s2);
- s1 = s2;
- if (str == NULL) { log_error1("Parse error"); return NULL; }
-
- res->desc = (char*)malloc(strlen(str)+1);
- strcpy(res->desc, str);
- res->desc[strlen(str)] = '\0';
-
- /* *** parse header *** */
- /* [key]: [value] */
- for (;;) {
- str = strtok_r(s1, "\n", &s2);
- s1 = s2;
-
- /* check if header ends without body */
- if (str == NULL) {
- return res;
- }
-
- /* check also for end of header */
- if (!strcmp(str, "\r")) {
- break;
- }
-
- str[strlen(str)-1] = '\0';
- res->header = hpairnode_parse(str, ":", res->header);
- }
-
- /* *** Save body *** */
- res->body = s1;
-
- /* return response object */
- return res;
-}
+ hresponse_t *res;
+ char *s1, *s2, *str;
+ hpair_t *pair;
+ /* create response object */
+ res = hresponse_new();
-void hresponse_free(hresponse_t *res)
-{
- /* not implemented yet!*/
-}
+ /* *** parse spec *** */
+ /* [HTTP/1.1 | 1.2] [CODE] [DESC] */
+
+ /* stage 1: HTTP spec */
+ str = (char*)strtok_r((char *)buffer, " ", &s2);
+ s1 = s2;
+ if (str == NULL) { log_error1("Parse error"); return NULL; }
+
+ strncpy(res->spec, str, 10);
+ /* stage 2: http code */
+ str = (char*)strtok_r(s1, " ", &s2);
+ s1 = s2;
+ if (str == NULL) { log_error1("Parse error"); return NULL; }
+ res->errcode = atoi(str);
+ /* stage 3: description text */
+ str = (char*)strtok_r(s1, "\r\n", &s2);
+ s1 = s2;
+ if (str == NULL) { log_error1("Parse error"); return NULL; }
+ res->desc = (char*)malloc(strlen(str)+1);
+ strcpy(res->desc, str);
+ res->desc[strlen(str)] = '\0';
+ /* *** parse header *** */
+ /* [key]: [value] */
+ for (;;) {
+ str = strtok_r(s1, "\n", &s2);
+ s1 = s2;
+ /* check if header ends without body */
+ if (str == NULL) {
+ return res;
+ }
+ /* check also for end of header */
+ if (!strcmp(str, "\r")) {
+ break;
+ }
+ str[strlen(str)-1] = '\0';
+ res->header = hpairnode_parse(str, ":", res->header);
+ }
+
+ /* *** Save body *** */
+ res->body = s1;
+
+ /* return response object */
+ return res;
+}
+
+
+void hresponse_free(hresponse_t *res)
+{
+ /* not implemented yet!*/
+}
diff --git a/nanohttp/nanohttp-common.h b/nanohttp/nanohttp-common.h
index ebde99c..365fdf3 100644
--- a/nanohttp/nanohttp-common.h
+++ b/nanohttp/nanohttp-common.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-common.h,v 1.6 2004/01/21 12:28:20 snowdrop Exp $
+ * $Id: nanohttp-common.h,v 1.7 2004/08/26 17:07:47 rans Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -110,7 +110,7 @@ typedef struct hresponse
int errcode;
char *desc;
hpair_t *header;
- unsigned char *body;
+ char *body;
long bodysize;
}hresponse_t;
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index a752fda..ef7c503 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,28 +1,34 @@
/******************************************************************
- * $Id: nanohttp-server.c,v 1.7 2004/05/18 16:37:21 snowdrop 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
- ******************************************************************/
+* $Id: nanohttp-server.c,v 1.8 2004/08/26 17:07:47 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
+******************************************************************/
#include <nanohttp/nanohttp-server.h>
+#ifdef WIN32
+#include "wsockcompat.h"
+#include <winsock2.h>
+#define close(s) closesocket(s)
+#endif
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -34,24 +40,25 @@
#include <string.h>
#include <signal.h>
+#ifndef WIN32
/* According to POSIX 1003.1-2001 */
#include <sys/select.h>
-
+
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
-
+#endif
typedef struct tag_conndata
{
- hsocket_t sock;
+ hsocket_t sock;
}conndata_t;
/* -----------------------------------------------------
- nano httpd internally globals
+nano httpd internally globals
----------------------------------------------------- */
static int _httpd_port = 10000;
static hsocket_t _httpd_socket;
@@ -61,347 +68,368 @@ static int _httpd_run = 1;
static int _httpd_terminate_signal = SIGTERM;
/* -----------------------------------------------------
- FUNCTION: httpd_init
+FUNCTION: httpd_init
----------------------------------------------------- */
int httpd_init(int argc, char *argv[])
{
- int i, status;
-
- /* write argument information */
- log_verbose1("Arguments:");
- for (i=0;i<argc;i++)
- log_verbose3("argv[%i] = '%s'", i, SAVE_STR(argv[i]));
-
- /* initialize from arguments */
- for (i=0;i<argc;i++) {
- if (!strcmp(argv[i], NHTTPD_ARG_PORT) && i < argc-1) {
- _httpd_port = atoi(argv[i+1]);
- } else if (!strcmp(argv[i], NHTTPD_ARG_TERMSIG) && i < argc-1) {
- _httpd_terminate_signal = atoi(argv[i+1]);
- }
- }
-
- log_verbose2("socket bind to port '%d'", _httpd_port);
-
- /* init built-in services */
- /*
- httpd_register("/httpd/list", service_list);
- */
-
- /* create socket */
- hsocket_init(&_httpd_socket);
- status = hsocket_bind(&_httpd_socket, _httpd_port);
-
- return status;
+ int i, status;
+
+ /* write argument information */
+ log_verbose1("Arguments:");
+ for (i=0;i<argc;i++)
+ log_verbose3("argv[%i] = '%s'", i, SAVE_STR(argv[i]));
+
+ /* initialize from arguments */
+ for (i=0;i<argc;i++) {
+ if (!strcmp(argv[i], NHTTPD_ARG_PORT) && i < argc-1) {
+ _httpd_port = atoi(argv[i+1]);
+ } else if (!strcmp(argv[i], NHTTPD_ARG_TERMSIG) && i < argc-1) {
+ _httpd_terminate_signal = atoi(argv[i+1]);
+ }
+ }
+
+ log_verbose2("socket bind to port '%d'", _httpd_port);
+
+ /* init built-in services */
+ /*
+ httpd_register("/httpd/list", service_list);
+ */
+
+ /* create socket */
+ hsocket_init(&_httpd_socket);
+ status = hsocket_bind(&_httpd_socket, _httpd_port);
+
+ return status;
}
/* -----------------------------------------------------
- FUNCTION: httpd_register
+FUNCTION: httpd_register
----------------------------------------------------- */
int httpd_register(const char* ctx, httpd_service func)
{
- hservice_t* service;
- log_verbose3("register service:t(%p):%s", service, SAVE_STR(ctx));
-
- service = (hservice_t*)malloc(sizeof(hservice_t));
- service->next = NULL;
- service->func = func;
- strcpy(service->ctx, ctx);
-
- if (_httpd_services_head == NULL) {
- _httpd_services_head = _httpd_services_tail = service;
- } else {
- _httpd_services_tail->next = service;
- _httpd_services_tail = service;
- }
-
- return 1;
+ hservice_t* service;
+ log_verbose3("register service:t(%p):%s", service, SAVE_STR(ctx));
+
+ service = (hservice_t*)malloc(sizeof(hservice_t));
+ service->next = NULL;
+ service->func = func;
+ strcpy(service->ctx, ctx);
+
+ if (_httpd_services_head == NULL) {
+ _httpd_services_head = _httpd_services_tail = service;
+ } else {
+ _httpd_services_tail->next = service;
+ _httpd_services_tail = service;
+ }
+
+ return 1;
}
/* -----------------------------------------------------
- FUNCTION: httpd_services
+FUNCTION: httpd_services
----------------------------------------------------- */
hservice_t *httpd_services()
{
- return _httpd_services_head;
+ return _httpd_services_head;
}
/* -----------------------------------------------------
- FUNCTION: httpd_find_service
+FUNCTION: httpd_find_service
----------------------------------------------------- */
static hservice_t *httpd_find_service(const char* ctx)
{
- hservice_t *cur = _httpd_services_head;
+ hservice_t *cur = _httpd_services_head;
- while (cur != NULL) {
- if (!strcmp(cur->ctx, ctx)) {
- return cur;
- }
- cur = cur->next;
- }
+ while (cur != NULL) {
+ if (!strcmp(cur->ctx, ctx)) {
+ return cur;
+ }
+ cur = cur->next;
+ }
- return NULL;
+ return NULL;
}
/* -----------------------------------------------------
- FUNCTION: httpd_response_set_content_type
+FUNCTION: httpd_response_set_content_type
----------------------------------------------------- */
void httpd_response_set_content_type(httpd_conn_t *res,
- const char* content_type)
+ const char* content_type)
{
- strncpy(res->content_type, content_type, 25);
+ strncpy(res->content_type, content_type, 25);
}
/* -----------------------------------------------------
- FUNCTION: httpd_response_send_header
+FUNCTION: httpd_response_send_header
----------------------------------------------------- */
int httpd_send_header(httpd_conn_t *res,
- int code, const char* text,
- hpair_t *pair)
+ int code, const char* text,
+ hpair_t *pair)
{
- struct tm stm;
- time_t nw;
- char buffer[255];
- char header[1024];
- hpair_t *cur;
- int status;
-
- /* set status code */
- sprintf(header, "HTTP/1.1 %d %s\r\n", code, text);
-
- /* set date */
- nw = time(NULL);
- localtime_r(&nw, &stm);
- strftime(buffer, 255, "Date: %a, %d %b %y %T GMT", &stm);
- strcat(header, buffer);
- strcat(header, "\r\n");
-
- /* set content-type */
- /*
- if (res->content_type[0] == '\0') {
- strcat(header, "Content-Type: text/html\r\n");
- } else {
- sprintf(buffer, "Content-Type: %s\r\n", res->content_type);
- strcat(header, buffer);
- }
- */
-
- /* set server name */
- strcat(header, "Server: Nano HTTPD library\r\n");
-
- /* set connection status */
- strcat(header, "Connection: close\r\n");
-
- /* add pairs */
- cur = pair;
- while (cur != NULL) {
- sprintf(buffer, "%s: %s\r\n", cur->key, cur->value);
- strcat(header, buffer);
- cur = cur->next;
- }
-
- /* set end of header */
- strcat(header, "\r\n");
-
- /* send header */
- status = hsocket_nsend(res->sock, header, strlen(header));
-
- return status;
+ struct tm stm;
+ time_t nw;
+ char buffer[255];
+ char header[1024];
+ hpair_t *cur;
+ int status;
+
+ /* set status code */
+ sprintf(header, "HTTP/1.1 %d %s\r\n", code, text);
+
+ /* set date */
+ nw = time(NULL);
+ localtime_r(&nw, &stm);
+ strftime(buffer, 255, "Date: %a, %d %b %y %T GMT", &stm);
+ strcat(header, buffer);
+ strcat(header, "\r\n");
+
+ /* set content-type */
+ /*
+ if (res->content_type[0] == '\0') {
+ strcat(header, "Content-Type: text/html\r\n");
+ } else {
+ sprintf(buffer, "Content-Type: %s\r\n", res->content_type);
+ strcat(header, buffer);
+ }
+ */
+
+ /* set server name */
+ strcat(header, "Server: Nano HTTPD library\r\n");
+
+ /* set connection status */
+ strcat(header, "Connection: close\r\n");
+
+ /* add pairs */
+ cur = pair;
+ while (cur != NULL) {
+ sprintf(buffer, "%s: %s\r\n", cur->key, cur->value);
+ strcat(header, buffer);
+ cur = cur->next;
+ }
+
+ /* set end of header */
+ strcat(header, "\r\n");
+
+ /* send header */
+ status = hsocket_nsend(res->sock, header, strlen(header));
+
+ return status;
}
int httpd_send_internal_error(httpd_conn_t *conn, const char* errmsg)
{
- const char *template =
- "<html><body><h3>Error!</h3><hr> Message: '%s' </body></html>\r\n";
+ const char *template1 =
+ "<html><body><h3>Error!</h3><hr> Message: '%s' </body></html>\r\n";
- char buffer[4064];
- sprintf(buffer, template, errmsg);
- httpd_send_header(conn, 500, "INTERNAL", NULL);
- return send(conn->sock, buffer, strlen(buffer), 0);
+ char buffer[4064];
+ sprintf(buffer, template1, errmsg);
+ httpd_send_header(conn, 500, "INTERNAL", NULL);
+ return send(conn->sock, buffer, strlen(buffer), 0);
}
/* -----------------------------------------------------
- FUNCTION: httpd_request_print
+FUNCTION: httpd_request_print
----------------------------------------------------- */
static void httpd_request_print(hrequest_t *req)
{
- hpair_t *pair;
-
- log_verbose1("++++++ Request +++++++++");
- log_verbose2(" Method : '%s'", req->method);
- log_verbose2(" Path : '%s'", req->path);
- log_verbose2(" Spec : '%s'", req->spec);
- log_verbose1(" Parsed query string :");
-
- pair = req->query;
- while (pair != NULL) {
- log_verbose3(" %s = '%s'", pair->key, pair->value);
- pair = pair->next;
- }
- log_verbose1("++++++++++++++++++++++++");
-
+ hpair_t *pair;
+
+ log_verbose1("++++++ Request +++++++++");
+ log_verbose2(" Method : '%s'", req->method);
+ log_verbose2(" Path : '%s'", req->path);
+ log_verbose2(" Spec : '%s'", req->spec);
+ log_verbose1(" Parsed query string :");
+
+ pair = req->query;
+ while (pair != NULL) {
+ log_verbose3(" %s = '%s'", pair->key, pair->value);
+ pair = pair->next;
+ }
+ log_verbose1("++++++++++++++++++++++++");
+
}
/* -----------------------------------------------------
- FUNCTION: httpd_session_main
+FUNCTION: httpd_session_main
----------------------------------------------------- */
static void* httpd_session_main(void *data)
{
- conndata_t *conn = (conndata_t*)data;
- const char *msg = "SESSION 1.0\n";
- int len = strlen(msg);
- char ch[2];
- char buffer[256]; /* temp buffer for recv() */
- char header[4064]; /* received header */
- int total; /* result from recv() */
- int hindex; /* searching end of header */
- int headerreached =0; /* whether reach header "\n\n" */
- hrequest_t* req = NULL; /* only for test */
- httpd_conn_t *rconn;
- hservice_t* service = NULL;
- char *content_length_str;
- long content_length = 0;
-
- header[0] = '\0';
- len = 0;
-
-
- log_verbose1("starting httpd_session_main()");
-
- while (len < 4064) {
- /*printf("receiving ...\n");*/
- total = recv(conn->sock, ch, 1, 0);
- if (total==0) break;
- header[len] = ch[0];
- len++;
- if (len > 3) {
- if (!strncmp(&header[len-4], "\r\n\r\n", 4)) {
- header[len] = '\0';
- break;
- }
- }
- }
-
- /* log_verbose2("=== HEADER ===\n%s\n============\n", header);*/
- /* call the service */
- req = hrequest_new_from_buffer(header);
- httpd_request_print(req);
-
-
- rconn = (httpd_conn_t*)malloc(sizeof(httpd_conn_t));
- rconn->sock = conn->sock;
- rconn->content_type[0] = '\0';
-
- 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);
- }
-
- close(conn->sock);
-
- /* httpd_response_free(res);*/
- hrequest_free(req);
-
- pthread_exit(NULL);
+ conndata_t *conn = (conndata_t*)data;
+ const char *msg = "SESSION 1.0\n";
+ int len = strlen(msg);
+ char ch[2];
+ char buffer[256]; /* temp buffer for recv() */
+ char header[4064]; /* received header */
+ int total; /* result from recv() */
+ int hindex; /* searching end of header */
+ int headerreached =0; /* whether reach header "\n\n" */
+ hrequest_t* req = NULL; /* only for test */
+ httpd_conn_t *rconn;
+ hservice_t* service = NULL;
+ char *content_length_str;
+ long content_length = 0;
+
+ header[0] = '\0';
+ len = 0;
+
+
+ log_verbose1("starting httpd_session_main()");
+
+ while (len < 4064) {
+ /*printf("receiving ...\n");*/
+ total = recv(conn->sock, ch, 1, 0);
+ if (total==0) break;
+ header[len] = ch[0];
+ len++;
+ if (len > 3) {
+ if (!strncmp(&header[len-4], "\r\n\r\n", 4)) {
+ header[len] = '\0';
+ break;
+ }
+ }
+ }
+
+ /* log_verbose2("=== HEADER ===\n%s\n============\n", header);*/
+ /* call the service */
+ req = hrequest_new_from_buffer(header);
+ httpd_request_print(req);
+
+
+ rconn = (httpd_conn_t*)malloc(sizeof(httpd_conn_t));
+ rconn->sock = conn->sock;
+ rconn->content_type[0] = '\0';
+
+ 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);
+ }
+
+ close(conn->sock);
+
+ /* httpd_response_free(res);*/
+ hrequest_free(req);
+
+ pthread_exit(NULL);
+ return service;
}
/* -----------------------------------------------------
- FUNCTION: httpd_term
+FUNCTION: httpd_term
----------------------------------------------------- */
void httpd_term(int sig)
{
- if (sig == _httpd_terminate_signal)
- _httpd_run = 0;
+ if (sig == _httpd_terminate_signal)
+ _httpd_run = 0;
}
/* -----------------------------------------------------
- FUNCTION: httpd_run
+FUNCTION: httpd_run
----------------------------------------------------- */
int httpd_run()
{
- conndata_t *conn;
- pthread_t tid;
- pthread_attr_t attr;
- hsocket_t sockfd;
- int err;
- fd_set fds;
- struct timeval timeout;
-
- pthread_attr_init(&attr);
+ conndata_t *conn;
+ pthread_t tid;
+ pthread_attr_t attr;
+ hsocket_t sockfd;
+ int err;
+ fd_set fds;
+ struct timeval timeout;
+
+ pthread_attr_init(&attr);
#ifdef PTHREAD_CREATE_DETACHED
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
#endif
-
- log_verbose1("starting run routine");
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- /* listen to port */
- err = hsocket_listen(_httpd_socket,15);
- if (err != HSOCKET_OK) {
- log_error2("httpd_run(): '%d'", err);
- return err;
- }
+ log_verbose1("starting run routine");
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ /* listen to port */
+ err = hsocket_listen(_httpd_socket,15);
+ if (err != HSOCKET_OK) {
+ log_error2("httpd_run(): '%d'", err);
+ return err;
+ }
- log_verbose2("registering termination signal handler (SIGNAL:%d)", _httpd_terminate_signal);
- signal(_httpd_terminate_signal, httpd_term);
+ log_verbose2("registering termination signal handler (SIGNAL:%d)", _httpd_terminate_signal);
+ signal(_httpd_terminate_signal, httpd_term);
+ log_verbose2("listening to port '%d'", _httpd_port);
- log_verbose2("listening to port '%d'", _httpd_port);
-
- fcntl(_httpd_socket, F_SETFL, O_NONBLOCK);
+#ifndef WIN32
+#if HSOCKET_BLOCKMODE!=0
+ fcntl(_httpd_socket, F_SETFL, O_NONBLOCK);
+#endif
+#else
+ unsigned long iMode=HSOCKET_BLOCKMODE;
+ if(ioctlsocket(_httpd_socket, FIONBIO, (u_long FAR*) &iMode) == INVALID_SOCKET)
+ {
+ log_error1("ioctlsocket error");
+ return -1;
+ }
+#endif
- while (_httpd_run) {
-
- FD_ZERO(&fds);
- FD_SET(_httpd_socket, &fds);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
- {
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- select(1, &fds, NULL, NULL, &timeout);
- } while (_httpd_run && (FD_ISSET(_httpd_socket, &fds)))
+ while (_httpd_run) {
+
+ FD_ZERO(&fds);
+ FD_SET(_httpd_socket, &fds);
+
+#ifndef WIN32
+ select(1, &fds, NULL, NULL, &timeout);
+#else
+ if(select(1, &fds, NULL, NULL, &timeout)==SOCKET_ERROR)
+ {
+ err=WSAGetLastError();
+ log_error1("select error");
+ return -1;
+ }
+#endif
- if (!_httpd_run)
- break;
-
- if (hsocket_accept(_httpd_socket, &sockfd) != HSOCKET_OK) {
- continue;
- }
+ while (_httpd_run && (FD_ISSET(_httpd_socket, &fds)))
+ if (!_httpd_run)
+ break;
- conn = (conndata_t*)malloc(sizeof(conndata_t));
- conn->sock = sockfd;
+ if (hsocket_accept(_httpd_socket, &sockfd) != HSOCKET_OK) {
+ continue;
+ }
- err = pthread_create(&tid, &attr, httpd_session_main, conn);
- if (err) {
- log_error2("Error creating thread: ('%d')", err);
- }
- }
- return 0;
+ conn = (conndata_t*)malloc(sizeof(conndata_t));
+ conn->sock = sockfd;
+
+ err = pthread_create(&tid, &attr, httpd_session_main, conn);
+ if (err) {
+ log_error2("Error creating thread: ('%d')", err);
+ }
+ }
+
+ return 0;
}
@@ -409,49 +437,49 @@ int httpd_run()
char *httpd_get_postdata(httpd_conn_t *conn, hrequest_t *req, long *received, long max)
{
- char *content_length_str;
- long content_length = 0;
- long total = 0;
- char *postdata = NULL;
-
- if (!strcmp(req->method, "POST")) {
-
- content_length_str =
- hpairnode_get_ignore_case(req->header, HEADER_CONTENT_LENGTH);
-
- if (content_length_str != NULL)
- content_length = atol(content_length_str);
-
- } else {
- log_warn1("Not a POST method");
- return NULL;
- }
-
- if (content_length > max && max != -1)
- return NULL;
-
- if (content_length == 0) {
- *received = 0;
- postdata = (char*)malloc(1);
- postdata[0] = '\0';
- return postdata;
- }
-
- postdata = (char*)malloc(content_length+1);
- if (postdata == NULL) {
- log_error1("Not enough memory");
- return NULL;
- }
-
-
- if (hsocket_read(conn->sock, postdata,
- (int)content_length, 1) == HSOCKET_OK) {
- *received = content_length;
- postdata[content_length] = '\0';
- return postdata;
- }
-
- free (postdata);
- return NULL;
-
+ char *content_length_str;
+ long content_length = 0;
+ long total = 0;
+ char *postdata = NULL;
+
+ if (!strcmp(req->method, "POST")) {
+
+ content_length_str =
+ hpairnode_get_ignore_case(req->header, HEADER_CONTENT_LENGTH);
+
+ if (content_length_str != NULL)
+ content_length = atol(content_length_str);
+
+ } else {
+ log_warn1("Not a POST method");
+ return NULL;
+ }
+
+ if (content_length > max && max != -1)
+ return NULL;
+
+ if (content_length == 0) {
+ *received = 0;
+ postdata = (char*)malloc(1);
+ postdata[0] = '\0';
+ return postdata;
+ }
+
+ postdata = (char*)malloc(content_length+1);
+ if (postdata == NULL) {
+ log_error1("Not enough memory");
+ return NULL;
+ }
+
+
+ if (hsocket_read(conn->sock, postdata,
+ (int)content_length, 1) == HSOCKET_OK) {
+ *received = content_length;
+ postdata[content_length] = '\0';
+ return postdata;
+ }
+
+ free (postdata);
+ return NULL;
+
}
diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c
index a555a7f..9b0e673 100644
--- a/nanohttp/nanohttp-socket.c
+++ b/nanohttp/nanohttp-socket.c
@@ -1,29 +1,37 @@
/******************************************************************
- * $Id: nanohttp-socket.c,v 1.8 2004/02/03 08:59:23 snowdrop 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
- ******************************************************************/
+* $Id: nanohttp-socket.c,v 1.9 2004/08/26 17:07:47 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
+******************************************************************/
#include <nanohttp/nanohttp-socket.h>
#include <nanohttp/nanohttp-common.h>
+#ifdef WIN32
+#include "wsockcompat.h"
+#include <winsock2.h>
+#define close(s) closesocket(s)
+typedef int ssize_t;
+typedef int socklen_t;
+#endif
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -52,339 +60,384 @@
#include <errno.h>
/*--------------------------------------------------
- FUNCTION: hsocket_module_init
+FUNCTION: hsocket_module_init
----------------------------------------------------*/
int hsocket_module_init()
{
- /* nothing to init for unix sockets */
- return 0;
+ /* nothing to init for unix sockets */
+ return 0;
}
/*--------------------------------------------------
- FUNCTION: hsocket_module_destroy
+FUNCTION: hsocket_module_destroy
----------------------------------------------------*/
void hsocket_module_destroy()
{
- /* nothing to destroy for unix sockets */
+ /* nothing to destroy for unix sockets */
}
/*--------------------------------------------------
- FUNCTION: hsocket_init
+FUNCTION: hsocket_init
----------------------------------------------------*/
int hsocket_init(hsocket_t *sock)
{
- /* nothing to init for unix sockets */
- /* just set the descriptor to -1 */
- *sock = -1;
- return 0;
+ /* nothing to init for unix sockets */
+ /* just set the descriptor to -1 */
+ *sock = -1;
+#ifdef WIN32
+ // WSACleanup();
+ struct WSAData info;
+ WSAStartup(MAKEWORD(2,2), &info);
+#endif
+ return 0;
}
/*--------------------------------------------------
- FUNCTION: hsocket_free
+FUNCTION: hsocket_free
----------------------------------------------------*/
void hsocket_free(hsocket_t sock)
{
- /* nothing to free for unix sockets */
+ /* nothing to free for unix sockets */
}
/*--------------------------------------------------
- FUNCTION: hsocket_open
+FUNCTION: hsocket_open
----------------------------------------------------*/
int hsocket_open(hsocket_t *dsock, const char* hostname, int port)
{
- int sock;
- struct sockaddr_in address;
- struct hostent* host;
+#ifdef WIN32
+ SOCKET sock;
+#else
+ int sock;
+#endif
+ char *ip;
+ struct sockaddr_in address;
+ struct hostent* host;
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock <= 0) return HSOCKET_CAN_NOT_CREATE;
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock <= 0) return HSOCKET_CAN_NOT_CREATE;
- /* Get host data */
- host = gethostbyname(hostname);
- if (host == NULL) return HSOCKET_CAN_NOT_GET_HOSTNAME;
+ /* Get host data */
+ host = gethostbyname(hostname);
+ if (host == NULL) return HSOCKET_CAN_NOT_GET_HOSTNAME;
- /* set server addresss */
- address.sin_family = host->h_addrtype;
- address.sin_port = htons(port);
- memcpy((char*)&address.sin_addr.s_addr,
- host->h_addr_list[0], host->h_length);
+ ip = inet_ntoa (*(struct in_addr *)*host->h_addr_list);
+ address.sin_addr.s_addr = inet_addr(ip);
- /* connect to the server */
- if (connect(sock, (struct sockaddr*) &address, sizeof(address)) != 0)
- return HSOCKET_CAN_NOT_CONNECT;
+ /* set server addresss */
+ address.sin_family = host->h_addrtype;
+ address.sin_port = htons(port);
+ /* connect to the server */
+ if (connect(sock, (struct sockaddr*) &address, sizeof(address)) != 0)
+ return HSOCKET_CAN_NOT_CONNECT;
- *dsock = sock;
- return HSOCKET_OK;
+ *dsock = sock;
+ return HSOCKET_OK;
}
/*--------------------------------------------------
- FUNCTION: hsocket_close
+FUNCTION: hsocket_close
----------------------------------------------------*/
int hsocket_bind(hsocket_t *dsock, int port)
{
- int sock;
- struct sockaddr_in addr;
-
- /* create socket */
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock == -1) {
- log_error2("Can not create socket: '%s'", strerror(errno));
- return HSOCKET_CAN_NOT_CREATE;
- }
-
- /* bind socket */
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port); /* short, network byte order */
- addr.sin_addr.s_addr = INADDR_ANY;
- memset(&(addr.sin_zero), '\0', 8); /* zero the rest of the struct */
-
- if (bind(sock, (struct sockaddr *)&addr,
- sizeof(struct sockaddr)) == -1) {
- log_error2("Can not bind: '%s'", strerror(errno));
- return HSOCKET_CAN_NOT_BIND;
- }
-
- *dsock = sock;
- return HSOCKET_OK;
+#ifdef WIN32
+ SOCKET sock;
+#else
+ int sock;
+#endif
+ struct sockaddr_in addr;
+
+ /* create socket */
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == -1) {
+ log_error2("Can not create socket: '%s'", strerror(errno));
+ return HSOCKET_CAN_NOT_CREATE;
+ }
+
+ /* bind socket */
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port); /* short, network byte order */
+ addr.sin_addr.s_addr = INADDR_ANY;
+ memset(&(addr.sin_zero), '\0', 8); /* zero the rest of the struct */
+
+ if (bind(sock, (struct sockaddr *)&addr,
+ sizeof(struct sockaddr)) == -1) {
+ log_error2("Can not bind: '%s'", strerror(errno));
+ return HSOCKET_CAN_NOT_BIND;
+ }
+
+ *dsock = sock;
+#ifdef WIN32
+ // setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)true, sizeof(BOOL));
+ // setsockopt(sock, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char*)true, sizeof(BOOL));
+#endif
+ return HSOCKET_OK;
}
/*--------------------------------------------------
- FUNCTION: hsocket_listen
+FUNCTION: hsocket_listen
----------------------------------------------------*/
int hsocket_listen(hsocket_t sock, int n)
{
- if (listen(sock, n) == -1) {
- log_error2("Can not listen: '%s'", strerror(errno));
- return HSOCKET_CAN_NOT_LISTEN;
- }
- return HSOCKET_OK;
+ if (listen(sock, n) == -1) {
+ log_error2("Can not listen: '%s'", strerror(errno));
+ return HSOCKET_CAN_NOT_LISTEN;
+ }
+ return HSOCKET_OK;
}
/*--------------------------------------------------
- FUNCTION: hsocket_listen
+FUNCTION: hsocket_listen
----------------------------------------------------*/
int hsocket_accept(hsocket_t sock, hsocket_t *dest)
{
- socklen_t asize;
- int sockfd;
- struct sockaddr_in addr;
-
- asize = sizeof(struct sockaddr_in);
- sockfd = accept(sock, (struct sockaddr *)&addr, &asize);
-
- if (sockfd == -1) {
- //httpd_log("httpd_run(): '%s'\n", strerror(errno));
- return HSOCKET_CAN_NOT_ACCEPT;
- }
-
- log_verbose3("accept new socket (%d) from '%s'", sockfd,
- SAVE_STR(((char*)inet_ntoa(addr.sin_addr))) );
-
- *dest = sockfd;
- return HSOCKET_OK;
+ socklen_t asize;
+ SOCKET sockfd;
+ struct sockaddr_in addr;
+
+ asize = sizeof(struct sockaddr_in);
+#ifdef WIN32
+ while(1)
+ {
+ sockfd = accept(sock, (struct sockaddr *)&addr, &asize);
+ if (sockfd == -1) {
+ if(WSAGetLastError()!=WSAEWOULDBLOCK)
+ {
+ return HSOCKET_CAN_NOT_ACCEPT;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+#else
+ sockfd = accept(sock, (struct sockaddr *)&addr, &asize);
+ if (sockfd == -1) {
+ //httpd_log("httpd_run(): '%s'\n", strerror(errno));
+ return HSOCKET_CAN_NOT_ACCEPT;
+ }
+#endif
+ log_verbose3("accept new socket (%d) from '%s'", sockfd,
+ SAVE_STR(((char*)inet_ntoa(addr.sin_addr))) );
+
+ *dest = sockfd;
+ return HSOCKET_OK;
}
/*--------------------------------------------------
- FUNCTION: hsocket_close
+FUNCTION: hsocket_close
----------------------------------------------------*/
void hsocket_close(hsocket_t sock)
{
- close(sock);
+ close(sock);
+#ifdef WIN32
+ WSACleanup();
+#endif
}
/*--------------------------------------------------
- FUNCTION: hsocket_send
+FUNCTION: hsocket_send
----------------------------------------------------*/
int hsocket_nsend(hsocket_t sock, const char* buffer, int n)
{
- int size;
+ int size;
- size = send((int)sock, buffer, n, 0);
- if (size == -1)
- return HSOCKET_CAN_NOT_SEND;
+ size = send((int)sock, buffer, n, 0);
+ if (size == -1)
+ return HSOCKET_CAN_NOT_SEND;
- return HSOCKET_OK;
+ return HSOCKET_OK;
}
/*--------------------------------------------------
- FUNCTION: hsocket_send
+FUNCTION: hsocket_send
----------------------------------------------------*/
int hsocket_send(hsocket_t sock, const char* buffer)
{
- int size;
- size = send((int)sock, buffer, strlen(buffer), 0);
- if (size == -1)
- return HSOCKET_CAN_NOT_SEND;
+ int size;
+ size = send((int)sock, buffer, strlen(buffer), 0);
+ if (size == -1)
+ return HSOCKET_CAN_NOT_SEND;
- return HSOCKET_OK;
+ return HSOCKET_OK;
}
int hsocket_read(hsocket_t sock, char* buffer, int total, int force)
{
- int status;
- int totalRead;
-
- totalRead = 0;
-
- do {
- status = recv(sock, &buffer[totalRead], total - totalRead, 0);
- if (!force) return status;
- if (status > 0) {
- totalRead += status;
- } else {
- return status;
- }
- if (totalRead >= total)
- return 0;
- } while (1);
+ int status;
+ int totalRead;
+
+ totalRead = 0;
+
+ do {
+ status = recv(sock, &buffer[totalRead], total - totalRead, 0);
+ if (!force)
+ {
+#ifdef WIN32
+ if(WSAGetLastError()!=WSAEWOULDBLOCK)
+ {
+ return status;
+ }
+#else
+ return status;
+#endif
+ }
+ if (status > 0) {
+ totalRead += status;
+ } else {
+#ifdef WIN32
+ if(WSAGetLastError()!=WSAEWOULDBLOCK)
+ {
+ return status;
+ }
+#else
+ return status;
+#endif
+ }
+ if (totalRead >= total)
+ return 0;
+ } while (1);
}
/*--------------------------------------------------
- FUNCTION: hsocket_recv
+FUNCTION: hsocket_recv
----------------------------------------------------*/
int hsocket_recv(hsocket_t sock, char** buffer, int *totalSize)
{
- ssize_t size;
- int chunk=1;
- char tmp[HSOCKET_MAX_BUFSIZE+1];
- int fsize;
- int bufSize;
-
- if (*totalSize > 0) {
- bufSize = *totalSize;
- } else {
- bufSize = HSOCKET_MAX_BUFSIZE;
- }
-
- *totalSize = 0;
-
- /* calculate first size for realloc */
- if (*buffer) {
- fsize = strlen(*buffer);
- } else {
- fsize = 0;
- }
-
- do {
-
- size = recv(sock, tmp, bufSize, 0);
- bufSize = HSOCKET_MAX_BUFSIZE;
-
- if (size == -1) {
- log_error1("Error reading from socket");
- return HSOCKET_CAN_NOT_RECEIVE;
- }
-
- if (size == 0) {
- break;
- }
-
- *totalSize += size;
- if (*buffer) {
- log_verbose2("reallocation %d bytes",*totalSize+fsize+1);
- *buffer = (char*)realloc((char*)*buffer,
- (*totalSize)+fsize+HSOCKET_MAX_BUFSIZE);
- strcat(*buffer, tmp);
- } else {
- *buffer = (char*)realloc(NULL, *totalSize+1);
- strcpy(*buffer, tmp);
- }
-
- (*buffer)[*totalSize+fsize] = '\0';
- chunk++;
- } while (size > 0);
-
- return HSOCKET_OK;
+ ssize_t size;
+ int chunk=1;
+ char tmp[HSOCKET_MAX_BUFSIZE+1];
+ int fsize;
+ int bufSize;
+
+ if (*totalSize > 0) {
+ bufSize = *totalSize;
+ } else {
+ bufSize = HSOCKET_MAX_BUFSIZE;
+ }
+
+ *totalSize = 0;
+
+ /* calculate first size for realloc */
+ if (*buffer) {
+ fsize = strlen(*buffer);
+ } else {
+ fsize = 0;
+ }
+
+ do {
+
+ size = recv(sock, tmp, bufSize, 0);
+ bufSize = HSOCKET_MAX_BUFSIZE;
+
+ if (size == -1) {
+ log_error1("Error reading from socket");
+ return HSOCKET_CAN_NOT_RECEIVE;
+ }
+
+ if (size == 0) {
+ break;
+ }
+
+ *totalSize += size;
+ if (*buffer) {
+ log_verbose2("reallocation %d bytes",*totalSize+fsize+1);
+ *buffer = (char*)realloc((char*)*buffer,
+ (*totalSize)+fsize+HSOCKET_MAX_BUFSIZE);
+ strcat(*buffer, tmp);
+ } else {
+ *buffer = (char*)realloc(NULL, *totalSize+1);
+ strcpy(*buffer, tmp);
+ }
+
+ (*buffer)[*totalSize+fsize] = '\0';
+ chunk++;
+ } while (size > 0);
+
+ return HSOCKET_OK;
}
/*--------------------------------------------------
- FUNCTION: hsocket_recv
+FUNCTION: hsocket_recv
----------------------------------------------------*/
int hsocket_recv_cb(hsocket_t sock,
- hsocket_recv_callback cb, void *userdata)
+ hsocket_recv_callback cb, void *userdata)
{
- ssize_t size;
- char tmp[HSOCKET_MAX_BUFSIZE+1];
-
- do {
-
- size = recv(sock, tmp, HSOCKET_MAX_BUFSIZE, 0);
-
- if (size == -1) {
- log_error1("Error reading from socket");
- return HSOCKET_CAN_NOT_RECEIVE;
- }
-
- if (size == 0) {
- break;
- }
-
- tmp[size]='\0';
- if (!cb(sock, tmp, size, userdata)) {
- break;
- }
-
- } while (size > 0);
-
- return HSOCKET_OK;
+ ssize_t size;
+ char tmp[HSOCKET_MAX_BUFSIZE+1];
+
+ do {
+
+ size = recv(sock, tmp, HSOCKET_MAX_BUFSIZE, 0);
+
+ if (size == -1) {
+ log_error1("Error reading from socket");
+ return HSOCKET_CAN_NOT_RECEIVE;
+ }
+
+ if (size == 0) {
+ break;
+ }
+
+ tmp[size]='\0';
+ if (!cb(sock, tmp, size, userdata)) {
+ break;
+ }
+
+ } while (size > 0);
+
+ return HSOCKET_OK;
}
/*--------------------------------------------------
- FUNCTION: hbufsocket_read
+FUNCTION: hbufsocket_read
----------------------------------------------------*/
int hbufsocket_read(hbufsocket_t *bufsock, char *buffer, int size)
{
- int status;
- int tmpsize;
-
- if (bufsock->bufsize - bufsock->cur >= size) {
-
- log_verbose1("no need to read from socket");
- strncpy(buffer, &(bufsock->buffer[bufsock->cur]), size);
- bufsock->cur += size;
- return HSOCKET_OK;
-
- } else {
-
- tmpsize = bufsock->bufsize - bufsock->cur;
- log_verbose2("tmpsize = %d", tmpsize);
-
- if (tmpsize > 0)
- strncpy(buffer, &(bufsock->buffer[bufsock->cur]), tmpsize);
-
- size -= tmpsize;
-
- free(bufsock->buffer);
-
- status = hsocket_read(bufsock->sock, &buffer[tmpsize], size, 1);
- if (status == size) {
- bufsock->buffer = (char*)malloc(size+1);
- strncpy(bufsock->buffer, &buffer[tmpsize], size);
- bufsock->cur = size;
- } else {
- return status;
- }
-
- return HSOCKET_OK;
- }
-}
+ int status;
+ int tmpsize;
+ if (bufsock->bufsize - bufsock->cur >= size) {
+ log_verbose1("no need to read from socket");
+ strncpy(buffer, &(bufsock->buffer[bufsock->cur]), size);
+ bufsock->cur += size;
+ return HSOCKET_OK;
+ } else {
+ tmpsize = bufsock->bufsize - bufsock->cur;
+ log_verbose2("tmpsize = %d", tmpsize);
+ if (tmpsize > 0)
+ strncpy(buffer, &(bufsock->buffer[bufsock->cur]), tmpsize);
+ size -= tmpsize;
+ free(bufsock->buffer);
+ status = hsocket_read(bufsock->sock, &buffer[tmpsize], size, 1);
+ if (status == size) {
+ bufsock->buffer = (char*)malloc(size+1);
+ strncpy(bufsock->buffer, &buffer[tmpsize], size);
+ bufsock->cur = size;
+ } else {
+ return status;
+ }
+
+ return HSOCKET_OK;
+ }
+}
diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h
index 12dc5d9..f86b149 100644
--- a/nanohttp/nanohttp-socket.h
+++ b/nanohttp/nanohttp-socket.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-socket.h,v 1.5 2004/01/21 12:28:20 snowdrop Exp $
+ * $Id: nanohttp-socket.h,v 1.6 2004/08/26 17:07:47 rans Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -24,7 +24,7 @@
#ifndef NANO_HTTP_SOCKET_H
#define NANO_HTTP_SOCKET_H
-
+#define HSOCKET_BLOCKMODE 0
#define HSOCKET_OK 0
#define HSOCKET_CAN_NOT_CREATE 1001
#define HSOCKET_CAN_NOT_GET_HOSTNAME 1002
@@ -37,8 +37,12 @@
#define HSOCKET_MAX_BUFSIZE 1024
+#ifdef WIN32
+#include <winsock2.h>
+typedef SOCKET hsocket_t;
+#else
typedef int hsocket_t;
-
+#endif
/*
PROTOTYPE:
int my_recv_cb(hsocket_t sock, char *buffer, int size, void *userdata);
diff --git a/nanohttp/nanohttp.vcproj b/nanohttp/nanohttp.vcproj
new file mode 100644
index 0000000..82bb0cb
--- /dev/null
+++ b/nanohttp/nanohttp.vcproj
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="nanohttp"
+ ProjectGUID="{B935F0BE-F513-4F83-8A05-E0C0BE9A08BE}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\,.\"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="2"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies=" Ws2_32.lib"
+ OutputFile="$(OutDir)/nanohttp.lib"
+ AdditionalLibraryDirectories=""
+ IgnoreAllDefaultLibraries="TRUE"
+ IgnoreDefaultLibraryNames=""/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\,.\"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies=" Ws2_32.lib"
+ OutputFile="$(OutDir)/nanohttp.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath=".\nanohttp-client.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\nanohttp-common.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\nanohttp-server.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\nanohttp-socket.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath=".\nanohttp-client.h">
+ </File>
+ <File
+ RelativePath=".\nanohttp-common.h">
+ </File>
+ <File
+ RelativePath=".\nanohttp-server.h">
+ </File>
+ <File
+ RelativePath=".\nanohttp-socket.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ <File
+ RelativePath=".\readme.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/nanohttp/pthread.h b/nanohttp/pthread.h
new file mode 100644
index 0000000..729458c
--- /dev/null
+++ b/nanohttp/pthread.h
@@ -0,0 +1,1345 @@
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2003 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined( PTHREAD_H )
+#define PTHREAD_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#ifdef _UWIN
+# define HAVE_STRUCT_TIMESPEC 1
+# define HAVE_SIGNAL_H 1
+# undef HAVE_CONFIG_H
+# pragma comment(lib, "pthread")
+#endif
+
+/*
+ * -------------------------------------------------------------
+ *
+ *
+ * Module: pthread.h
+ *
+ * Purpose:
+ * Provides an implementation of PThreads based upon the
+ * standard:
+ *
+ * POSIX 1003.1-2001
+ * and
+ * The Single Unix Specification version 3
+ *
+ * (these two are equivalent)
+ *
+ * in order to enhance code portability between Windows,
+ * various commercial Unix implementations, and Linux.
+ *
+ * See the ANNOUNCE file for a full list of conforming
+ * routines and defined constants, and a list of missing
+ * routines and constants not defined in this implementation.
+ *
+ * Authors:
+ * There have been many contributors to this library.
+ * The initial implementation was contributed by
+ * John Bossom, and several others have provided major
+ * sections or revisions of parts of the implementation.
+ * Often significant effort has been contributed to
+ * find and fix important bugs and other problems to
+ * improve the reliability of the library, which sometimes
+ * is not reflected in the amount of code which changed as
+ * result.
+ * As much as possible, the contributors are acknowledged
+ * in the ChangeLog file in the source code distribution
+ * where their changes are noted in detail.
+ *
+ * Contributors are listed in the CONTRIBUTORS file.
+ *
+ * As usual, all bouquets go to the contributors, and all
+ * brickbats go to the project maintainer.
+ *
+ * Maintainer:
+ * The code base for this project is coordinated and
+ * eventually pre-tested, packaged, and made available by
+ *
+ * Ross Johnson <rpj@ise.canberra.edu.au>
+ *
+ * QA Testers:
+ * Ultimately, the library is tested in the real world by
+ * a host of competent and demanding scientists and
+ * engineers who report bugs and/or provide solutions
+ * which are then fixed or incorporated into subsequent
+ * versions of the library. Each time a bug is fixed, a
+ * test case is written to prove the fix and ensure
+ * that later changes to the code don't reintroduce the
+ * same error. The number of test cases is slowly growing
+ * and therefore so is the code reliability.
+ *
+ * Compliance:
+ * See the file ANNOUNCE for the list of implemented
+ * and not-implemented routines and defined options.
+ * Of course, these are all defined is this file as well.
+ *
+ * Web site:
+ * The source code and other information about this library
+ * are available from
+ *
+ * http://sources.redhat.com/pthreads-win32/
+ *
+ * -------------------------------------------------------------
+ */
+
+/* Try to avoid including windows.h */
+#if defined(__MINGW32__) && defined(__cplusplus)
+/*
+ * FIXME: The pthreadGCE.dll build gets linker unresolved errors
+ * on pthread_key_create() unless windows.h is included here.
+ * It appears to have something to do with an argument type mismatch.
+ * Looking at tsd.o with 'nm' shows this line:
+ * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v
+ * instead of
+ * 00000000 T _pthread_key_create
+ */
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#ifdef PTW32_INCLUDE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+/*
+ * VC++6.0 or early compiler's header has no DWORD_PTR type.
+ */
+typedef unsigned long DWORD_PTR;
+#endif
+/*
+ * -----------------
+ * autoconf switches
+ * -----------------
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* Try to avoid including windows.h */
+#if defined(__MINGW32__) && defined(__cplusplus)
+/*
+ * FIXME: The pthreadGCE.dll build gets linker unresolved errors
+ * on pthread_key_create() unless windows.h is included here.
+ * It appears to have something to do with an argument type mismatch.
+ * Looking at tsd.o with 'nm' shows this line:
+ * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v
+ * instead of
+ * 00000000 T _pthread_key_create
+ */
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#ifdef PTW32_INCLUDE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#ifndef NEED_FTIME
+#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#include <setjmp.h>
+#include <limits.h>
+
+/*
+ * Boolean values to make us independent of system includes.
+ */
+enum {
+ PTW32_FALSE = 0,
+ PTW32_TRUE = (! PTW32_FALSE)
+};
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Several systems don't define ENOTSUP. If not, we use
+ * the same value as Solaris.
+ */
+#ifndef ENOTSUP
+# define ENOTSUP 48
+#endif
+
+#ifndef ETIMEDOUT
+# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
+#endif
+
+#include <sched.h>
+
+/*
+ * To avoid including windows.h we define only those things that we
+ * actually need from it. I don't like the potential incompatibility that
+ * this creates with future versions of windows.
+ */
+#ifndef PTW32_INCLUDE_WINDOWS_H
+#ifndef HANDLE
+# define PTW32__HANDLE_DEF
+# define HANDLE void *
+#endif
+#ifndef DWORD
+# define PTW32__DWORD_DEF
+# define DWORD unsigned long
+#endif
+#endif
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#ifndef HAVE_STRUCT_TIMESPEC
+struct timespec {
+ long tv_sec;
+ long tv_nsec;
+};
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#ifndef SIG_BLOCK
+#define SIG_BLOCK 0
+#endif /* SIG_BLOCK */
+
+#ifndef SIG_UNBLOCK
+#define SIG_UNBLOCK 1
+#endif /* SIG_UNBLOCK */
+
+#ifndef SIG_SETMASK
+#define SIG_SETMASK 2
+#endif /* SIG_SETMASK */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * -------------------------------------------------------------
+ *
+ * POSIX 1003.1-2001 Options
+ * =========================
+ *
+ * _POSIX_THREADS (set)
+ * If set, you can use threads
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE (set)
+ * If set, you can control the size of a thread's
+ * stack
+ * pthread_attr_getstacksize
+ * pthread_attr_setstacksize
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR (not set)
+ * If set, you can allocate and control a thread's
+ * stack. If not supported, the following functions
+ * will return ENOSYS, indicating they are not
+ * supported:
+ * pthread_attr_getstackaddr
+ * pthread_attr_setstackaddr
+ *
+ * _POSIX_THREAD_PRIORITY_SCHEDULING (set)
+ * If set, you can use realtime scheduling.
+ * Indicates the availability of:
+ * pthread_attr_getinheritsched
+ * pthread_attr_getschedparam
+ * pthread_attr_getschedpolicy
+ * pthread_attr_getscope
+ * pthread_attr_setinheritsched
+ * pthread_attr_setschedparam
+ * pthread_attr_setschedpolicy
+ * pthread_attr_setscope
+ * pthread_getschedparam
+ * pthread_setschedparam
+ * sched_get_priority_max
+ * sched_get_priority_min
+ * sched_rr_set_interval
+ *
+ * _POSIX_THREAD_PRIO_INHERIT (not set)
+ * If set, you can create priority inheritance
+ * mutexes.
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PRIO_PROTECT (not set)
+ * If set, you can create priority ceiling mutexes
+ * Indicates the availability of:
+ * pthread_mutex_getprioceiling
+ * pthread_mutex_setprioceiling
+ * pthread_mutexattr_getprioceiling
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprioceiling
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PROCESS_SHARED (not set)
+ * If set, you can create mutexes and condition
+ * variables that can be shared with another
+ * process.If set, indicates the availability
+ * of:
+ * pthread_mutexattr_getpshared
+ * pthread_mutexattr_setpshared
+ * pthread_condattr_getpshared
+ * pthread_condattr_setpshared
+ *
+ * _POSIX_THREAD_SAFE_FUNCTIONS (set)
+ * If set you can use the special *_r library
+ * functions that provide thread-safe behaviour
+ *
+ * _POSIX_READER_WRITER_LOCKS (set)
+ * If set, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (set)
+ * If set, you can use spin locks
+ *
+ * _POSIX_BARRIERS (set)
+ * If set, you can use barriers
+ *
+ * + These functions provide both 'inherit' and/or
+ * 'protect' protocol, based upon these macro
+ * settings.
+ *
+ * POSIX 1003.1-2001 Limits
+ * ===========================
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ * Maximum number of attempts to destroy
+ * a thread's thread-specific data on
+ * termination (must be at least 4)
+ *
+ * PTHREAD_KEYS_MAX
+ * Maximum number of thread-specific data keys
+ * available per process (must be at least 128)
+ *
+ * PTHREAD_STACK_MIN
+ * Minimum supported stack size for a thread
+ *
+ * PTHREAD_THREADS_MAX
+ * Maximum number of threads supported per
+ * process (must be at least 64).
+ *
+ * _POSIX_SEM_NSEMS_MAX
+ * The maximum number of semaphores a process can have.
+ * (only defined if not already defined)
+ *
+ * _POSIX_SEM_VALUE_MAX
+ * The maximum value a semaphore can have.
+ * (only defined if not already defined)
+ *
+ * -------------------------------------------------------------
+ */
+
+/*
+ * POSIX Options
+ */
+#ifndef _POSIX_THREADS
+#define _POSIX_THREADS
+#endif
+
+#ifndef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS
+#endif
+
+#ifndef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS
+#endif
+
+#ifndef _POSIX_BARRIERS
+#define _POSIX_BARRIERS
+#endif
+
+#define _POSIX_THREAD_SAFE_FUNCTIONS
+#define _POSIX_THREAD_ATTR_STACKSIZE
+#define _POSIX_THREAD_PRIORITY_SCHEDULING
+
+#if defined( KLUDGE )
+/*
+ * The following are not supported
+ */
+#define _POSIX_THREAD_ATTR_STACKADDR
+#define _POSIX_THREAD_PRIO_INHERIT
+#define _POSIX_THREAD_PRIO_PROTECT
+#define _POSIX_THREAD_PROCESS_SHARED
+
+#endif /* KLUDGE */
+
+/*
+ * POSIX Limits
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ * Standard states this must be at least
+ * 4.
+ *
+ * PTHREAD_KEYS_MAX
+ * WIN32 permits only 64 TLS keys per process.
+ * This limitation could be worked around by
+ * simply simulating keys.
+ *
+ * PTHREADS_STACK_MIN
+ * POSIX specifies 0 which is also the value WIN32
+ * interprets as allowing the system to
+ * set the size to that of the main thread. The
+ * maximum stack size in Win32 is 1Meg. WIN32
+ * allocates more stack as required up to the 1Meg
+ * limit.
+ *
+ * PTHREAD_THREADS_MAX
+ * Not documented by WIN32. Wrote a test program
+ * that kept creating threads until it failed
+ * revealed this approximate number (Windows NT).
+ * This number is somewhat less for Windows 9x
+ * and is effectively less than 64. Perhaps this
+ * constant should be set at DLL load time.
+ *
+ */
+#define PTHREAD_DESTRUCTOR_ITERATIONS 4
+#define PTHREAD_KEYS_MAX 64
+#define PTHREAD_STACK_MIN 0
+#define PTHREAD_THREADS_MAX 2019
+#ifndef _POSIX_SEM_NSEMS_MAX
+/* Not used and only an arbitrary value. */
+# define _POSIX_SEM_NSEMS_MAX 1024
+#endif
+#ifndef _POSIX_SEM_VALUE_MAX
+# define _POSIX_SEM_VALUE_MAX (INT_MAX/2)
+#endif
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifdef _DLL
+# ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#endif
+
+/*
+ * The Open Watcom C/C++ compiler uses a non-standard calling convention
+ * that passes function args in registers unless __cdecl is explicitly specified
+ * in exposed function prototypes.
+ *
+ * We force all calls to cdecl even though this could slow Watcom code down
+ * slightly. If you know that the Watcom compiler will be used to build both
+ * the DLL and application, then you can probably define this as a null string.
+ * Remember that pthread.h (this file) is used for both the DLL and application builds.
+ */
+#define PTW32_CDECL __cdecl
+
+#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
+# include <sys/types.h>
+#else
+typedef struct pthread_t_ *pthread_t;
+typedef struct pthread_attr_t_ *pthread_attr_t;
+typedef struct pthread_once_t_ pthread_once_t;
+typedef struct pthread_key_t_ *pthread_key_t;
+typedef struct pthread_mutex_t_ *pthread_mutex_t;
+typedef struct pthread_mutexattr_t_ *pthread_mutexattr_t;
+typedef struct pthread_cond_t_ *pthread_cond_t;
+typedef struct pthread_condattr_t_ *pthread_condattr_t;
+#endif
+typedef struct pthread_rwlock_t_ *pthread_rwlock_t;
+typedef struct pthread_rwlockattr_t_ *pthread_rwlockattr_t;
+typedef struct pthread_spinlock_t_ *pthread_spinlock_t;
+typedef struct pthread_barrier_t_ *pthread_barrier_t;
+typedef struct pthread_barrierattr_t_ *pthread_barrierattr_t;
+
+/*
+ * ====================
+ * ====================
+ * POSIX Threads
+ * ====================
+ * ====================
+ */
+
+enum {
+/*
+ * pthread_attr_{get,set}detachstate
+ */
+ PTHREAD_CREATE_JOINABLE = 0, /* Default */
+ PTHREAD_CREATE_DETACHED = 1,
+
+/*
+ * pthread_attr_{get,set}inheritsched
+ */
+ PTHREAD_INHERIT_SCHED = 0,
+ PTHREAD_EXPLICIT_SCHED = 1, /* Default */
+
+/*
+ * pthread_{get,set}scope
+ */
+ PTHREAD_SCOPE_PROCESS = 0,
+ PTHREAD_SCOPE_SYSTEM = 1, /* Default */
+
+/*
+ * pthread_setcancelstate paramters
+ */
+ PTHREAD_CANCEL_ENABLE = 0, /* Default */
+ PTHREAD_CANCEL_DISABLE = 1,
+
+/*
+ * pthread_setcanceltype parameters
+ */
+ PTHREAD_CANCEL_ASYNCHRONOUS = 0,
+ PTHREAD_CANCEL_DEFERRED = 1, /* Default */
+
+/*
+ * pthread_mutexattr_{get,set}pshared
+ * pthread_condattr_{get,set}pshared
+ */
+ PTHREAD_PROCESS_PRIVATE = 0,
+ PTHREAD_PROCESS_SHARED = 1,
+
+/*
+ * pthread_barrier_wait
+ */
+ PTHREAD_BARRIER_SERIAL_THREAD = -1
+};
+
+/*
+ * ====================
+ * ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED ((void *) -1)
+
+
+/*
+ * ====================
+ * ====================
+ * Once Key
+ * ====================
+ * ====================
+ */
+#define PTHREAD_ONCE_INIT { PTW32_FALSE, -1 }
+
+struct pthread_once_t_
+{
+ int done; /* indicates if user function executed */
+ long started; /* First thread to increment this value */
+ /* to zero executes the user function */
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Object initialisers
+ * ====================
+ * ====================
+ */
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
+
+/*
+ * Compatibility with LinuxThreads
+ */
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
+
+#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
+
+#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
+
+
+/*
+ * Mutex types.
+ */
+enum
+{
+ /* Compatibility with LinuxThreads */
+ PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
+ /* For compatibility with POSIX */
+ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+/* There are three implementations of cancel cleanup.
+ * Note that pthread.h is included in both application
+ * compilation units and also internally for the library.
+ * The code here and within the library aims to work
+ * for all reasonable combinations of environments.
+ *
+ * The three implementations are:
+ *
+ * WIN32 SEH
+ * C
+ * C++
+ *
+ * Please note that exiting a push/pop block via
+ * "return", "exit", "break", or "continue" will
+ * lead to different behaviour amongst applications
+ * depending upon whether the library was built
+ * using SEH, C++, or C. For example, a library built
+ * with SEH will call the cleanup routine, while both
+ * C++ and C built versions will not.
+ */
+
+/*
+ * Define defaults for cleanup code.
+ * Note: Unless the build explicitly defines one of the following, then
+ * we default to standard C style cleanup. This style uses setjmp/longjmp
+ * in the cancelation and thread exit implementations and therefore won't
+ * do stack unwinding if linked to applications that have it (e.g.
+ * C++ apps). This is currently consistent with most/all commercial Unix
+ * POSIX threads implementations.
+ */
+#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
+# define __CLEANUP_C
+#endif
+
+#if defined( __CLEANUP_SEH ) && defined(__GNUC__)
+#error ERROR [__FILE__, line __LINE__]: GNUC does not support SEH.
+#endif
+
+typedef struct ptw32_cleanup_t ptw32_cleanup_t;
+
+#if defined(_MSC_VER)
+/* Disable MSVC 'anachronism used' warning */
+#pragma warning( disable : 4229 )
+#endif
+
+typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
+
+#if defined(_MSC_VER)
+#pragma warning( default : 4229 )
+#endif
+
+struct ptw32_cleanup_t
+{
+ ptw32_cleanup_callback_t routine;
+ void *arg;
+ struct ptw32_cleanup_t *prev;
+};
+
+#ifdef __CLEANUP_SEH
+ /*
+ * WIN32 SEH version of cancel cleanup.
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
+ _cleanup.arg = (_arg); \
+ __try \
+ { \
+
+#define pthread_cleanup_pop( _execute ) \
+ } \
+ __finally \
+ { \
+ if( _execute || AbnormalTermination()) \
+ { \
+ (*(_cleanup.routine))( _cleanup.arg ); \
+ } \
+ } \
+ }
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+ /*
+ * C implementation of PThreads cancel cleanup
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
+
+#define pthread_cleanup_pop( _execute ) \
+ (void) ptw32_pop_cleanup( _execute ); \
+ }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+ /*
+ * C++ version of cancel cleanup.
+ * - John E. Bossom.
+ */
+
+ class PThreadCleanup {
+ /*
+ * PThreadCleanup
+ *
+ * Purpose
+ * This class is a C++ helper class that is
+ * used to implement pthread_cleanup_push/
+ * pthread_cleanup_pop.
+ * The destructor of this class automatically
+ * pops the pushed cleanup routine regardless
+ * of how the code exits the scope
+ * (i.e. such as by an exception)
+ */
+ ptw32_cleanup_callback_t cleanUpRout;
+ void * obj;
+ int executeIt;
+
+ public:
+ PThreadCleanup() :
+ cleanUpRout( 0 ),
+ obj( 0 ),
+ executeIt( 0 )
+ /*
+ * No cleanup performed
+ */
+ {
+ }
+
+ PThreadCleanup(
+ ptw32_cleanup_callback_t routine,
+ void * arg ) :
+ cleanUpRout( routine ),
+ obj( arg ),
+ executeIt( 1 )
+ /*
+ * Registers a cleanup routine for 'arg'
+ */
+ {
+ }
+
+ ~PThreadCleanup()
+ {
+ if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
+ {
+ (void) (*cleanUpRout)( obj );
+ }
+ }
+
+ void execute( int exec )
+ {
+ executeIt = exec;
+ }
+ };
+
+ /*
+ * C++ implementation of PThreads cancel cleanup;
+ * This implementation takes advantage of a helper
+ * class who's destructor automatically calls the
+ * cleanup routine if we exit our scope weirdly
+ */
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
+ (void *) (_arg) );
+
+#define pthread_cleanup_pop( _execute ) \
+ cleanup.execute( _execute ); \
+ }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * ===============
+ * ===============
+ * Methods
+ * ===============
+ * ===============
+ */
+
+/*
+ * PThread Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
+ int *detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
+ void **stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
+ size_t * stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
+ int detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
+ void *stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
+ size_t stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *,
+ int *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
+ int inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr,
+ int * inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
+ int *);
+
+/*
+ * PThread Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
+ const pthread_attr_t * attr,
+ void *(*start) (void *),
+ void *arg);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
+ pthread_t t2);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
+ void **value_ptr);
+
+PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
+ int *oldstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
+ int *oldtype);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
+ void (*init_routine) (void));
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
+
+PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+ void (*routine) (void *),
+ void *arg);
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread Specific Data Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
+ void (*destructor) (void *));
+
+PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
+ const void *value);
+
+PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
+
+
+/*
+ * Mutex Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+ int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
+
+/*
+ * Barrier Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
+ int pshared);
+
+/*
+ * Mutex Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
+
+/*
+ * Spinlock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
+
+/*
+ * Barrier Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
+ const pthread_barrierattr_t * attr,
+ unsigned int count);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
+
+/*
+ * Condition Variable Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
+ int pshared);
+
+/*
+ * Condition Variable Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
+ const pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
+
+/*
+ * Scheduling
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
+ int policy,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
+ int *policy,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
+
+/*
+ * Read-Write Lock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
+ const pthread_rwlockattr_t *attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+ int pshared);
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
+
+/*
+ * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
+ * already have signal.h that don't define these.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
+
+/*
+ * Non-portable functions
+ */
+
+/*
+ * Compatibility with Linux.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
+ int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
+ int *kind);
+
+/*
+ * Possibly supported by other POSIX threads implementations
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
+PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
+
+/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
+
+/*
+ * Features that are auto-detected at load/run time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
+enum ptw32_features {
+ PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
+ PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
+};
+
+/*
+ * Register a system time change with the library.
+ * Causes the library to perform various functions
+ * in response to the change. Should be called whenever
+ * the application's top level window receives a
+ * WM_TIMECHANGE message. It can be passed directly to
+ * pthread_create() as a new thread if desired.
+ */
+PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
+
+#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/*
+ * Returns the Win32 HANDLE for the POSIX thread.
+ */
+PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
+
+
+/*
+ * Protected Methods
+ *
+ * This function blocks until the given WIN32 handle
+ * is signaled or pthread_cancel had been called.
+ * This function allows the caller to hook into the
+ * PThreads cancel mechanism. It is implemented using
+ *
+ * WaitForMultipleObjects
+ *
+ * on 'waitHandle' and a manually reset WIN32 Event
+ * used to implement pthread_cancel. The 'timeout'
+ * argument to TimedWait is simply passed to
+ * WaitForMultipleObjects.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
+ DWORD timeout);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread-Safe C Runtime Library Mappings.
+ */
+#ifndef _UWIN
+# if defined(NEED_ERRNO)
+ PTW32_DLLPORT int * PTW32_CDECL _errno( void );
+# else
+# ifndef errno
+# if (defined(_MT) || defined(_DLL))
+ __declspec(dllimport) extern int * __cdecl _errno(void);
+# define errno (*_errno())
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * WIN32 C runtime library had been made thread-safe
+ * without affecting the user interface. Provide
+ * mappings from the UNIX thread-safe versions to
+ * the standard C runtime library calls.
+ * Only provide function mappings for functions that
+ * actually exist on WIN32.
+ */
+
+#if !defined(__MINGW32__)
+#define strtok_r( _s, _sep, _lasts ) \
+ ( *(_lasts) = strtok( (_s), (_sep) ) )
+#endif /* !__MINGW32__ */
+
+#define asctime_r( _tm, _buf ) \
+ ( strcpy( (_buf), asctime( (_tm) ) ), \
+ (_buf) )
+
+#define ctime_r( _clock, _buf ) \
+ ( strcpy( (_buf), ctime( (_clock) ) ), \
+ (_buf) )
+
+#define gmtime_r( _clock, _result ) \
+ ( *(_result) = *gmtime( (_clock) ), \
+ (_result) )
+
+#define localtime_r( _clock, _result ) \
+ ( *(_result) = *localtime( (_clock) ), \
+ (_result) )
+
+#define rand_r( _seed ) \
+ ( _seed == _seed? rand() : rand() )
+
+
+#ifdef __cplusplus
+
+/*
+ * Internal exceptions
+ */
+class ptw32_exception {};
+class ptw32_exception_cancel : public ptw32_exception {};
+class ptw32_exception_exit : public ptw32_exception {};
+
+#endif
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* FIXME: This is only required if the library was built using SEH */
+/*
+ * Get internal SEH tag
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#ifndef PTW32_BUILD
+
+#ifdef __CLEANUP_SEH
+
+/*
+ * Redefine the SEH __except keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#define __except( E ) \
+ __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
+ ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
+
+#endif /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_CXX
+
+/*
+ * Redefine the C++ catch keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#ifdef _MSC_VER
+ /*
+ * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
+ * if you want Pthread-Win32 cancelation and pthread_exit to work.
+ */
+
+#ifndef PtW32NoCatchWarn
+
+#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
+#pragma message("------------------------------------------------------------------")
+#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
+#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
+#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
+#pragma message(" cancelation and pthread_exit to work. For example:")
+#pragma message("")
+#pragma message(" #ifdef PtW32CatchAll")
+#pragma message(" PtW32CatchAll")
+#pragma message(" #else")
+#pragma message(" catch(...)")
+#pragma message(" #endif")
+#pragma message(" {")
+#pragma message(" /* Catchall block processing */")
+#pragma message(" }")
+#pragma message("------------------------------------------------------------------")
+
+#endif
+
+#define PtW32CatchAll \
+ catch( ptw32_exception & ) { throw; } \
+ catch( ... )
+
+#else /* _MSC_VER */
+
+#define catch( E ) \
+ catch( ptw32_exception & ) { throw; } \
+ catch( E )
+
+#endif /* _MSC_VER */
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* ! PTW32_BUILD */
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#ifdef PTW32__HANDLE_DEF
+# undef HANDLE
+#endif
+#ifdef PTW32__DWORD_DEF
+# undef DWORD
+#endif
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* PTHREAD_H */
diff --git a/nanohttp/sched.h b/nanohttp/sched.h
new file mode 100644
index 0000000..e6a0ee1
--- /dev/null
+++ b/nanohttp/sched.h
@@ -0,0 +1,174 @@
+/*
+ * Module: sched.h
+ *
+ * Purpose:
+ * Provides an implementation of POSIX realtime extensions
+ * as defined in
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2003 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef _SCHED_H
+#define _SCHED_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+#else
+# define PTW32_DLLPORT __declspec (dllimport)
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#if defined(__MINGW32__) || defined(_UWIN)
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+/* For pid_t */
+# include <sys/types.h>
+/* Required by Unix 98 */
+# include <time.h>
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+#else
+typedef int pid_t;
+#endif
+
+/* Thread scheduling policies */
+
+enum {
+ SCHED_OTHER = 0,
+ SCHED_FIFO,
+ SCHED_RR,
+ SCHED_MIN = SCHED_OTHER,
+ SCHED_MAX = SCHED_RR
+};
+
+struct sched_param {
+ int sched_priority;
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+PTW32_DLLPORT int __cdecl sched_yield (void);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
+
+PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
+
+PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
+
+/*
+ * Note that this macro returns ENOTSUP rather than
+ * ENOSYS as might be expected. However, returning ENOSYS
+ * should mean that sched_get_priority_{min,max} are
+ * not implemented as well as sched_rr_get_interval.
+ * This is not the case, since we just don't support
+ * round-robin scheduling. Therefore I have chosen to
+ * return the same value as sched_setscheduler when
+ * SCHED_RR is passed to it.
+ */
+#define sched_rr_get_interval(_pid, _interval) \
+ ( errno = ENOTSUP, (int) -1 )
+
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* !_SCHED_H */
+
diff --git a/nanohttp/semaphore.h b/nanohttp/semaphore.h
new file mode 100644
index 0000000..f26417e
--- /dev/null
+++ b/nanohttp/semaphore.h
@@ -0,0 +1,163 @@
+/*
+ * Module: semaphore.h
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2003 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#if !defined( SEMAPHORE_H )
+#define SEMAPHORE_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifdef PTW32_BUILD
+# define PTW32_DLLPORT __declspec (dllexport)
+#else
+# define PTW32_DLLPORT __declspec (dllimport)
+#endif
+
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#define _POSIX_SEMAPHORES
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#ifndef HAVE_MODE_T
+typedef unsigned int mode_t;
+#endif
+
+
+typedef struct sem_t_ * sem_t;
+
+PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
+ int pshared,
+ unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
+ const struct timespec * abstime);
+
+PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
+ int count);
+
+PTW32_DLLPORT int __cdecl sem_open (const char * name,
+ int oflag,
+ mode_t mode,
+ unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
+
+PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
+ int * sval);
+
+#ifdef __cplusplus
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* !SEMAPHORE_H */
diff --git a/nanohttp/wsockcompat.h b/nanohttp/wsockcompat.h
new file mode 100644
index 0000000..690048c
--- /dev/null
+++ b/nanohttp/wsockcompat.h
@@ -0,0 +1,61 @@
+/* include/wsockcompat.h
+ * Windows -> Berkeley Sockets compatibility things.
+ */
+
+#if !defined __XML_WSOCKCOMPAT_H__
+#define __XML_WSOCKCOMPAT_H__
+
+#ifdef _WIN32_WCE
+#include <winsock.h>
+#else
+#undef HAVE_ERRNO_H
+#include <winsock2.h>
+#endif
+
+#if !defined SOCKLEN_T
+#define SOCKLEN_T int
+#endif
+
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define EALREADY WSAEALREADY
+#define ENOTSOCK WSAENOTSOCK
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#define EMSGSIZE WSAEMSGSIZE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EADDRINUSE WSAEADDRINUSE
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define ENETDOWN WSAENETDOWN
+#define ENETUNREACH WSAENETUNREACH
+#define ENETRESET WSAENETRESET
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET WSAECONNRESET
+#define ENOBUFS WSAENOBUFS
+#define EISCONN WSAEISCONN
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+#define ELOOP WSAELOOP
+#define EHOSTDOWN WSAEHOSTDOWN
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+/* These cause conflicts with the codes from errno.h. Since they are
+ not used in the relevant code (nanoftp, nanohttp), we can leave
+ them disabled.
+#define ENAMETOOLONG WSAENAMETOOLONG
+#define ENOTEMPTY WSAENOTEMPTY
+*/
+
+#endif /* __XML_WSOCKCOMPAT_H__ */