summaryrefslogtreecommitdiffstats
path: root/nanohttp
diff options
context:
space:
mode:
authorGravatar snowdrop2004-09-19 07:05:01 +0000
committerGravatar snowdrop2004-09-19 07:05:01 +0000
commitd2c445f5d7cf21606c9878bff3e4046c283944df (patch)
treec562922b592bc3359a9dd12a671eff2974829592 /nanohttp
parent6ea7f7e0961d05c5f0d995eecc785d1fd1e96b6f (diff)
downloadcsoap-d2c445f5d7cf21606c9878bff3e4046c283944df.tar.gz
csoap-d2c445f5d7cf21606c9878bff3e4046c283944df.tar.bz2
Added http stream feature (only input stream yet)
Added DIME "client" support (very experimental)
Diffstat (limited to 'nanohttp')
-rw-r--r--nanohttp/Makefile.am7
-rw-r--r--nanohttp/nanohttp-client.c426
-rw-r--r--nanohttp/nanohttp-client.h222
-rw-r--r--nanohttp/nanohttp-common.c108
-rw-r--r--nanohttp/nanohttp-common.h70
-rwxr-xr-xnanohttp/nanohttp-reqres.h73
-rw-r--r--nanohttp/nanohttp-server.c51
-rw-r--r--nanohttp/nanohttp-server.h6
-rw-r--r--nanohttp/nanohttp-socket.c1003
-rw-r--r--nanohttp/nanohttp-socket.h10
-rwxr-xr-xnanohttp/nanohttp-stream.c292
-rwxr-xr-xnanohttp/nanohttp-stream.h80
12 files changed, 1660 insertions, 688 deletions
diff --git a/nanohttp/Makefile.am b/nanohttp/Makefile.am
index c8ba204..ba3cf78 100644
--- a/nanohttp/Makefile.am
+++ b/nanohttp/Makefile.am
@@ -4,12 +4,15 @@
h_sources = nanohttp-common.h\
nanohttp-socket.h\
nanohttp-client.h\
-nanohttp-server.h
+nanohttp-server.h\
+nanohttp-reqres.h\
+nanohttp-stream.h
cc_sources = nanohttp-common.c\
nanohttp-socket.c\
nanohttp-client.c\
-nanohttp-server.c
+nanohttp-server.c\
+nanohttp-stream.c
library_includedir=$(includedir)/$(NANOHTTP_LIBRARY_NAME)-$(NANOHTTP_API_VERSION)/$(NANOHTTP_LIBRARY_NAME)
library_include_HEADERS = $(h_sources)
diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c
index ee02c59..13972a1 100644
--- a/nanohttp/nanohttp-client.c
+++ b/nanohttp/nanohttp-client.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-client.c,v 1.18 2004/09/01 07:58:00 snowdrop Exp $
+* $Id: nanohttp-client.c,v 1.19 2004/09/19 07:05:03 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -58,7 +58,10 @@ httpc_new()
hsocket_init(&res->sock);
res->header = NULL;
res->url = NULL;
-
+ res->version = HTTP_1_1;
+ res->_dime_package_nr = 0;
+ res->_dime_sent_bytes = 0;
+ res->_is_chunked = 0;
return res;
}
@@ -167,6 +170,49 @@ httpc_send_header(httpc_conn_t * conn)
return status;
}
+/*--------------------------------------------------
+FUNCTION: httpc_set_transfer_encoding
+DESC:
+----------------------------------------------------*/
+void httpc_set_transfer_encoding(httpc_conn_t *conn, const char* encoding)
+{
+ httpc_set_header(conn, HEADER_TRANSFER_ENCODING, encoding);
+
+ if (!strcmp(encoding, TRANSFER_ENCODING_CHUNKED))
+ conn->_is_chunked = 1;
+}
+
+/*--------------------------------------------------
+FUNCTION: httpc_set_transfer_encoding
+DESC:
+----------------------------------------------------*/
+int httpc_send_data(httpc_conn_t *conn, const unsigned char* bytes, size_t size)
+{
+ int status;
+ char chunked[15];
+
+ if (conn->_is_chunked)
+ {
+ sprintf(chunked,"%x\r\n",size);
+ status = hsocket_send(conn->sock, chunked);
+ if (status != HSOCKET_OK)
+ return status;
+ }
+
+ status = hsocket_nsend(conn->sock, bytes, size);
+
+ if (conn->_is_chunked)
+ {
+ status = hsocket_send(conn->sock, "\r\n");
+ if (status != HSOCKET_OK)
+ return status;
+ }
+
+ return status;
+}
+
+
+
static
hresponse_t *
httpc_receive_header(hsocket_t sock)
@@ -196,10 +242,6 @@ httpc_receive_header(hsocket_t sock)
}
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') {
@@ -353,11 +395,11 @@ httpc_receive_with_chunked_encoding(httpc_conn_t * conn,
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]);
@@ -369,6 +411,8 @@ httpc_receive_with_chunked_encoding(httpc_conn_t * conn,
&& chunk_size_str[chunk_size_cur] != ';') {
chunk_size_cur++;
}
+ /* TODO (#1#): check for chunk_size_cur >= 25 */
+
} /* while (1) */
chunk_size = strtol(chunk_size_str, (char **) NULL, 16); /* hex to dec */
@@ -475,6 +519,14 @@ httpc_receive_response(httpc_conn_t * conn,
hresponse_t *res;
int status;
+ /* check if chunked */
+ if (conn->_is_chunked)
+ {
+ status = hsocket_send(conn->sock, "0\r\n\r\n");
+ if (status != HSOCKET_OK)
+ return status;
+ }
+
/* receive header */
log_verbose1("receiving header");
res = httpc_receive_header(conn->sock);
@@ -510,6 +562,51 @@ httpc_receive_response(httpc_conn_t * conn,
return -1;
}
+static
+int
+_httpc_receive_response(httpc_conn_t * conn,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata)
+{
+ hresponse_t *res;
+ int status, counter=1;
+ byte_t buffer[MAX_SOCKET_BUFFER_SIZE+1];
+
+ /* check if chunked */
+ if (conn->_is_chunked)
+ {
+ status = hsocket_send(conn->sock, "0\r\n\r\n");
+ if (status != HSOCKET_OK)
+ return status;
+ }
+
+ /* Create response object */
+ res = hresponse_new_from_socket(conn->sock);
+ if (res == NULL)
+ {
+ log_error1("hresponse_new_from_socket() failed!");
+ return -1;
+ }
+
+ /* Invoke callback */
+ start_cb(conn, userdata, res->header, res->spec,
+ res->errcode, res->desc);
+
+ while (http_input_stream_is_ready(res->in))
+ {
+ status = http_input_stream_read(res->in, buffer, MAX_SOCKET_BUFFER_SIZE);
+ if (status < 0)
+ {
+ log_error2("Stream read error: %d", status);
+ return -1;
+ }
+
+ cb(counter++, conn, userdata, status, buffer);
+ }
+
+ return HSOCKET_OK;
+}
+
/*--------------------------------------------------
FUNCTION: httpc_talk_to_server
DESC: This function is the heart of the httpc
@@ -596,14 +693,16 @@ httpc_talk_to_server(hreq_method method, httpc_conn_t * conn,
if (method == HTTP_REQUEST_GET) {
/* Set GET Header */
- sprintf(buffer, "GET %s HTTP/1.1\r\n",
- (url->context) ? url->context : ("/"));
+ sprintf(buffer, "GET %s HTTP/%s\r\n",
+ (url->context) ? url->context : ("/"),
+ (conn->version == HTTP_1_0)?"1.0":"1.1");
} else if (method == HTTP_REQUEST_POST) {
/* Set POST Header */
- sprintf(buffer, "POST %s HTTP/1.1\r\n",
- (url->context) ? url->context : ("/"));
+ sprintf(buffer, "POST %s HTTP/%s\r\n",
+ (url->context) ? url->context : ("/"),
+ (conn->version == HTTP_1_0)?"1.0":"1.1");
} else {
log_error1("Unknown method type!");
@@ -648,7 +747,7 @@ httpc_get_cb(httpc_conn_t * conn, const char *urlstr,
if (status != HSOCKET_OK)
return status;
- status = httpc_receive_response(conn, start_cb, cb, userdata);
+ status = _httpc_receive_response(conn, start_cb, cb, userdata);
return status;
}
@@ -668,7 +767,7 @@ 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)
+ const char *content, void *userdata)
{
int status;
char buffer[255];
@@ -689,11 +788,11 @@ httpc_post_cb(httpc_conn_t * conn, const char *urlstr,
}
-/*
- * ====================================================== 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,
@@ -789,6 +888,297 @@ httpc_post(httpc_conn_t * conn, const char *url,
}
+/* ---------------------------------------------------
+ DIME support functions httpc_dime_* function set
+-----------------------------------------------------*/
+int httpc_dime_begin(httpc_conn_t *conn, const char *url)
+{
+ int status;
+ httpc_set_header(conn, HEADER_CONTENT_TYPE, "application/dime");
+
+ status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url);
+ return status;
+}
+
+static _print_binary_ascii(int n)
+{
+ int i,c=0;
+ char ascii[36];
+
+ for (i=0;i<32;i++) {
+ ascii[34-i-c] = (n & (1<<i))?'1':'0';
+ if ((i+1)%8 == 0) {
+ c++;
+ ascii[i+c] = ' ';
+ }
+ }
+
+ ascii[35]='\0';
+
+ log_verbose2("%s", ascii);
+}
+
+static
+void _get_binary_ascii8(unsigned char n, char* ascii)
+{
+ int i;
+ for (i=0;i<8;i++)
+ ascii[7-i] = (n & (1<<i))?'1':'0';
+
+ ascii[8]='\0';
+}
+
+static
+void _print_binary_ascii32(unsigned char b1, unsigned char b2,
+ unsigned char b3, unsigned char b4)
+{
+ char ascii[4][9];
+ _get_binary_ascii8(b1, ascii[0]);
+ _get_binary_ascii8(b2, ascii[1]);
+ _get_binary_ascii8(b3, ascii[2]);
+ _get_binary_ascii8(b4, ascii[3]);
+
+ log_verbose5("%s %s %s %s", ascii[0], ascii[1], ascii[2], ascii[3]);
+}
+
+int httpc_dime_next(httpc_conn_t* conn, long content_length,
+ const char *content_type, const char *id,
+ const char *dime_options, int last)
+{
+ int status, tmp;
+ unsigned char header[12];
+
+ for (tmp=0;tmp<12;tmp++)
+ header[tmp]=0;
+
+ header[0] |= DIME_VERSION_1;
+
+ if (conn->_dime_package_nr == 0)
+ header[0] |= DIME_FIRST_PACKAGE;
+
+ if (last)
+ header[0] |= DIME_LAST_PACKAGE;
+
+ header[1] = DIME_TYPE_URI;
+
+ tmp = strlen(dime_options);
+ header[2] = tmp >> 8;
+ header[3] = tmp;
+
+ tmp = strlen(id);
+ header[4] = tmp >> 8;
+ header[5] = tmp;
+
+ tmp = strlen(content_type);
+ header[6] = tmp >> 8;
+ header[7] = tmp;
+
+ header[8] = content_length >> 24;
+ header[9] = content_length >> 16;
+ header[10] = content_length >> 8;
+ header[11] = content_length;
+
+
+ _print_binary_ascii32(header[0], header[1], header[2], header[3]);
+ _print_binary_ascii32(header[4], header[5], header[6], header[7]);
+ _print_binary_ascii32(header[8], header[9], header[10], header[11]);
+
+ status = httpc_send_data(conn, header, 12);
+ if (status != HSOCKET_OK)
+ return status;
+
+ status = httpc_send_data(conn, (const unsigned char*)dime_options, strlen(dime_options));
+ if (status != HSOCKET_OK)
+ return status;
+
+ status = httpc_send_data(conn, (const unsigned char*)id, strlen(id));
+ if (status != HSOCKET_OK)
+ return status;
+
+ status = httpc_send_data(conn, (const unsigned char*)content_type, strlen(content_type));
+ if (status != HSOCKET_OK)
+ return status;
+
+ return status;
+}
+
+int httpc_dime_send_data(httpc_conn_t* conn, int size, unsigned char* data)
+{
+ return httpc_send_data(conn, data, size);
+}
+
+int httpc_dime_get_response_cb(httpc_conn_t *conn,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata)
+{
+ int status;
+
+ status = httpc_receive_response(conn, start_cb, cb, userdata);
+ return status;
+}
+
+
+hresponse_t* httpc_dime_get_response(httpc_conn_t *conn)
+{
+ int status;
+ hresponse_t *res;
+
+ res = hresponse_new();
+ status = httpc_dime_get_response_cb(conn, httpc_custom_start_callback,
+ httpc_custom_res_callback, res);
+
+ if (status != 0) {
+ hresponse_free(res);
+ return NULL;
+ }
+
+ return res;
+}
+
+
+/* ---------------------------------------------------
+ MIME support functions httpc_mime_* function set
+-----------------------------------------------------*/
+
+static
+void _httpc_mime_get_boundary(httpc_conn_t *conn, char *dest)
+{
+ sprintf(dest, "---=_NH_%p", conn);
+ log_verbose2("boundary= \"%s\"", dest);
+}
+
+int httpc_mime_post_begin(httpc_conn_t *conn, const char *url,
+ const char* related_start,
+ const char* related_start_info,
+ const char* related_type)
+{
+ int status;
+ char buffer[300];
+ char temp[75];
+ char boundary[75];
+
+ /*
+ Set Content-type
+ Set multipart/related parameter
+ type=..; start=.. ; start-info= ..; boundary=...
+
+ */
+ sprintf(buffer, "multipart/related;");
+
+ if (related_type) {
+ snprintf(temp, 75, " type=\"%s\";", related_type);
+ strcat(buffer, temp);
+ }
+
+ if (related_start) {
+ snprintf(temp, 75, " start=\"%s\";", related_start);
+ strcat(buffer, temp);
+ }
+
+ if (related_start_info) {
+ snprintf(temp, 75, " start-info=\"%s\";", related_start_info);
+ strcat(buffer, temp);
+ }
+
+ _httpc_mime_get_boundary(conn, boundary);
+ snprintf(temp, 75, " boundary=\"%s\"", boundary);
+ strcat(buffer, temp);
+
+ httpc_set_header(conn, HEADER_CONTENT_TYPE, buffer);
+
+ status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url);
+ return status;
+}
+
+
+int httpc_mime_post_next(httpc_conn_t *conn,
+ const char* content_id,
+ const char* content_type,
+ const char* transfer_encoding)
+{
+ int status;
+ char buffer[512];
+ char boundary[75];
+
+ /* Get the boundary string */
+ _httpc_mime_get_boundary(conn, boundary);
+ sprintf(buffer, "\r\n--%s\r\n", boundary);
+
+ /* Send boundary */
+ status = httpc_send_data(conn, (const unsigned char*)buffer, strlen(buffer));
+ /* status = hsocket_send(conn->sock, buffer);*/
+ if (status != HSOCKET_OK)
+ return status;
+
+ /* Send Content header */
+ sprintf(buffer, "%s: %s\r\n%s: %s\r\n%s: %s\r\n\r\n",
+ HEADER_CONTENT_TYPE, content_type,
+ HEADER_CONTENT_TRANSFER_ENCODING, transfer_encoding,
+ HEADER_CONTENT_ID, content_id);
+
+ status = httpc_send_data(conn, (const unsigned char*)buffer, strlen(buffer));
+
+ return status;
+}
+
+
+int httpc_mime_post_send(httpc_conn_t *conn, size_t size, const unsigned char* data)
+{
+ int status;
+ char buffer[15];
+
+ status = httpc_send_data(conn, (const unsigned char*)data, size);
+ if (status != HSOCKET_OK)
+ return status;
+
+
+ return status;
+}
+
+
+int httpc_mime_post_end_cb(httpc_conn_t *conn,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata)
+{
+
+ int status;
+ char buffer[512];
+ char boundary[75];
+ char chunked[15];
+
+ /* Get the boundary string */
+ _httpc_mime_get_boundary(conn, boundary);
+ sprintf(buffer, "\r\n--%s--\r\n\r\n", boundary);
+
+ /* Send boundary */
+ status = httpc_send_data(conn, (unsigned char*)buffer, strlen(buffer));
+ if (status != HSOCKET_OK)
+ return status;
+
+ /*status = hsocket_send(conn->sock, buffer);*/
+
+ status = httpc_receive_response(conn, start_cb, cb, userdata);
+ return status;
+}
+
+
+hresponse_t *httpc_mime_post_end(httpc_conn_t *conn)
+{
+ int status;
+ hresponse_t *res;
+
+ res = hresponse_new();
+ status = httpc_mime_post_end_cb(conn, httpc_custom_start_callback,
+ httpc_custom_res_callback, res);
+
+ if (status != 0) {
+ hresponse_free(res);
+ return NULL;
+ }
+
+ return res;
+}
+
/*
* POST Module
diff --git a/nanohttp/nanohttp-client.h b/nanohttp/nanohttp-client.h
index f937f00..6a53f9d 100644
--- a/nanohttp/nanohttp-client.h
+++ b/nanohttp/nanohttp-client.h
@@ -1,92 +1,134 @@
-/******************************************************************
- * $Id: nanohttp-client.h,v 1.7 2004/08/31 16:34:08 rans Exp $
- *
- * CSOAP Project: A http client/server library in C
- * Copyright (C) 2003 Ferhat Ayaz
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Email: ayaz@jprogrammer.net
- ******************************************************************/
-#ifndef NANO_HTTP_CLIENT_H
-#define NANO_HTTP_CLIENT_H
-
-
-#include <nanohttp/nanohttp-common.h>
-#include <nanohttp/nanohttp-socket.h>
-
-
-typedef struct httpc_conn
-{
- hsocket_t sock;
- hpair_t *header;
- hurl_t *url;
-}httpc_conn_t;
-
-/*
- PROTOTYPE:
- void my_callback(int counter, httpc_conn_t* conn,
- void *userdata, int size, char *buffer)
- */
-typedef void (*httpc_response_callback)(int, httpc_conn_t*, void*,int,char*);
-
-/*
- void my_start_callback(httpc_conn_t *conn, void *userdata,
- hpair_t *header, const char *spec,
- int errcode, const char *desc)
- */
-typedef void (*httpc_response_start_callback)(httpc_conn_t*, void*, hpair_t*,
- const char*, int, const char*);
+/******************************************************************
+ * $Id: nanohttp-client.h,v 1.8 2004/09/19 07:05:03 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
+ ******************************************************************/
+#ifndef NANO_HTTP_CLIENT_H
+#define NANO_HTTP_CLIENT_H
+
+
+#include <nanohttp/nanohttp-common.h>
+#include <nanohttp/nanohttp-socket.h>
+#include <nanohttp/nanohttp-reqres.h>
+
+typedef struct httpc_conn
+{
+ hsocket_t sock;
+ hpair_t *header;
+ hurl_t *url;
+ http_version_t version;
+ /*
+ -1 : last dime package
+ 0 : no dime connection
+ >0 : dime package number
+ */
+ int _dime_package_nr;
+ long _dime_sent_bytes;
+ int _is_chunked;
+}httpc_conn_t;
+
+/*
+ PROTOTYPE:
+ void my_callback(int counter, httpc_conn_t* conn,
+ void *userdata, int size, char *buffer)
+ */
+typedef void (*httpc_response_callback)(int, httpc_conn_t*, void*,int,char*);
+
+/*
+ void my_start_callback(httpc_conn_t *conn, void *userdata,
+ hpair_t *header, const char *spec,
+ int errcode, const char *desc)
+ */
+typedef void (*httpc_response_start_callback)(httpc_conn_t*, void*, hpair_t*,
+ const char*, int, const char*);
int httpc_init(int argc, char *argv[]);
-httpc_conn_t* httpc_new();
-void httpc_free(httpc_conn_t* conn);
-
-int httpc_set_header(httpc_conn_t *conn, const char* key, const char* value);
-
-hresponse_t *httpc_get(httpc_conn_t *conn, const char *url);
-hresponse_t *httpc_post(httpc_conn_t *conn, const char *url,
- int conten_size, const char *content);
-
-int httpc_get_cb(httpc_conn_t *conn, const char *url,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, void *userdata);
-
-
-int httpc_post_cb(httpc_conn_t *conn, const char *url,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, int content_size,
- char *content, void *userdata);
-
-
-
-/*
- Chunked POST Module
- */
-
-/* Returns 0 if success, >0 otherwise */
-/* do not use this
-int httpc_post_open(httpc_conn_t *conn, const char *url);
-
-int httpc_post_send(httpc_conn_t *conn, const char* buffer, int bufsize);
-hresponse_t *httpc_post_finish(httpc_conn_t *conn);
-int httpc_post_finish_cb(httpc_conn_t *conn,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, void *userdata);
-*/
-
-#endif
-
+httpc_conn_t* httpc_new();
+void httpc_free(httpc_conn_t* conn);
+
+int httpc_set_header(httpc_conn_t *conn, const char* key, const char* value);
+void httpc_set_transfer_encoding(httpc_conn_t *conn, const char* encoding);
+
+hresponse_t *httpc_get(httpc_conn_t *conn, const char *url);
+hresponse_t *httpc_post(httpc_conn_t *conn, const char *url,
+ int conten_size, const char *content);
+
+int httpc_get_cb(httpc_conn_t *conn, const char *url,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata);
+
+
+int httpc_post_cb(httpc_conn_t *conn, const char *url,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, int content_size,
+ const char *content, void *userdata);
+
+/*
+ DIME support httpc_dime_* function set
+*/
+int httpc_dime_begin(httpc_conn_t *conn, const char *url);
+int httpc_dime_next(httpc_conn_t* conn, long content_length,
+ const char *content_type, const char *id,
+ const char *dime_options, int last);
+int httpc_dime_send_data(httpc_conn_t* conn, int size, unsigned char* data);
+hresponse_t* httpc_dime_get_response(httpc_conn_t *conn);
+int httpc_dime_get_response_cb(httpc_conn_t *conn,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata);
+
+/*
+ MIME support httpc_mime_* function set
+*/
+
+int httpc_mime_post_begin(httpc_conn_t *conn, const char *url,
+ const char* related_start,
+ const char* related_start_info,
+ const char* related_type);
+
+int httpc_mime_post_next(httpc_conn_t *conn,
+ const char* content_id,
+ const char* content_type,
+ const char* transfer_encoding);
+
+int httpc_mime_post_send(httpc_conn_t *conn, size_t size, const unsigned char* data);
+hresponse_t *httpc_mime_post_end(httpc_conn_t *conn);
+int httpc_mime_post_end_cb(httpc_conn_t *conn,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata);
+
+
+/*
+ Chunked POST Module
+ */
+
+/* Returns 0 if success, >0 otherwise */
+/* do not use this
+int httpc_post_open(httpc_conn_t *conn, const char *url);
+
+int httpc_post_send(httpc_conn_t *conn, const char* buffer, int bufsize);
+hresponse_t *httpc_post_finish(httpc_conn_t *conn);
+int httpc_post_finish_cb(httpc_conn_t *conn,
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata);
+*/
+
+#endif
+
diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c
index b96c0bc..fb67595 100644
--- a/nanohttp/nanohttp-common.c
+++ b/nanohttp/nanohttp-common.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-common.c,v 1.11 2004/09/01 07:58:08 snowdrop Exp $
+* $Id: nanohttp-common.c,v 1.12 2004/09/19 07:05:03 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -23,6 +23,7 @@
******************************************************************/
#include <nanohttp/nanohttp-common.h>
+#include <nanohttp/nanohttp-reqres.h>
#include <stdio.h>
#include <stdlib.h>
@@ -657,6 +658,111 @@ hresponse_new()
return res;
}
+static
+hresponse_t *
+_hresponse_parse_header(const char *buffer)
+{
+ hresponse_t *res;
+ char *s1, *s2, *str;
+
+ /* create response object */
+ res = hresponse_new();
+
+ /* *** 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);
+ }
+
+ /* return response object */
+ return res;
+}
+
+hresponse_t *
+hresponse_new_from_socket(hsocket_t sock)
+{
+ int i=0, status;
+ hresponse_t *res;
+ char buffer[MAX_HEADER_SIZE+1];
+
+ /* Read header */
+ while (i<MAX_HEADER_SIZE)
+ {
+ status = hsocket_read(sock, &(buffer[i]), 1, 1);
+ if (status == -1)
+ {
+ log_error1("Socket read error");
+ return NULL;
+ }
+
+ buffer[i+1] = '\0'; /* for strmp */
+
+ if (i > 3)
+ {
+ if (!strcmp(&(buffer[i-1]), "\n\n") ||
+ !strcmp(&(buffer[i-2]), "\n\r\n"))
+ break;
+ }
+ i++;
+ }
+
+ /* Create response */
+ res = _hresponse_parse_header(buffer);
+ if (res == NULL)
+ {
+ log_error1("Header parse error");
+ return NULL;
+ }
+
+ /* Create input stream */
+ res->in = http_input_stream_new(sock, res->header);
+
+ return res;
+}
/*
* ------------------------------------------- FUNCTION:
diff --git a/nanohttp/nanohttp-common.h b/nanohttp/nanohttp-common.h
index 455e9ed..0d765d8 100644
--- a/nanohttp/nanohttp-common.h
+++ b/nanohttp/nanohttp-common.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-common.h,v 1.10 2004/09/14 15:31:24 snowdrop Exp $
+ * $Id: nanohttp-common.h,v 1.11 2004/09/19 07:05:03 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -27,17 +27,24 @@
#define HEADER_CONTENT_LENGTH "Content-Length"
#define HEADER_CONTENT_TYPE "Content-Type"
+#define HEADER_CONTENT_ID "Content-Id"
+#define HEADER_CONTENT_TRANSFER_ENCODING "Content-Transfer-Encoding"
#define HEADER_TRANSFER_ENCODING "Transfer-Encoding"
#define HEADER_CONNECTION "Connection"
#define HEADER_HOST "Host"
#define HEADER_DATE "Date"
-
+#define HEADER_ACCEPT "Accept"
#ifndef SAVE_STR
#define SAVE_STR(str) ((str==0)?("(null)"):(str))
#endif
+#define TRANSFER_ENCODING_CHUNKED "chunked"
+
+#define MAX_HEADER_SIZE 4256
+#define MAX_SOCKET_BUFFER_SIZE 4256
+
/*
Set Sleep function platform depended
*/
@@ -47,6 +54,8 @@ Set Sleep function platform depended
#define system_sleep(seconds) sleep(seconds);
#endif
+typedef unsigned char byte_t;
+
/*
string function to compare strings ignoring case
Returns 1 if s1 equals s2 and 0 otherwise.
@@ -54,6 +63,7 @@ Set Sleep function platform depended
int strcmpigcase(const char *s1, const char *s2);
+
/*
hpairnode_t represents a pair (key, value) pair.
This is also a linked list.
@@ -76,6 +86,11 @@ hpair_t* hpairnode_copy_deep(const hpair_t *src);
void hpairnode_dump_deep(hpair_t *pair);
void hpairnode_dump(hpair_t *pair);
+typedef enum http_version {
+ HTTP_1_0,
+ HTTP_1_1 /* default */
+}http_version_t;
+
typedef enum hreq_method
{
HTTP_REQUEST_POST,
@@ -95,40 +110,33 @@ typedef struct hurl
hurl_t* hurl_new(const char* urlstr);
void hurl_free(hurl_t *url);
-/*
- request object
- */
-typedef struct hrequest
-{
- char *method;
- char *path;
- char *spec;
- hpair_t *query;
- hpair_t *header;
-}hrequest_t;
-hrequest_t *hrequest_new_from_buffer(char *data);
-void hrequest_free(hrequest_t *req);
-/* response object */
+/*
+ DIME common stuff
+*/
+#define DIME_VERSION_1 0x08
+#define DIME_FIRST_PACKAGE 0x04
+#define DIME_LAST_PACKAGE 0x02
+#define DIME_CHUNKED 0x01
+#define DIME_TYPE_URI 0x2
-typedef struct hresponse
+typedef struct _DIME_PACKAGE
{
- char spec[10];
- int errcode;
- char *desc;
- hpair_t *header;
- char *body;
- long bodysize;
-}hresponse_t;
+ char version; /* Specifies the version of the DIME message */
+ char first_record; /* Specifies that this record is the first record of the message */
+ char last_recored; /* Specifies that this record is the last record of the message */
+ char chunked; /* Specifies that the contents of the message have been chunked */
+ char type_t; /* Specifies the structure and format of the TYPE field */
+ char *options; /* Contains any optional information used by a DIME parser */
+ char *id; /* Contains a URI for uniquely identifying a DIME payload with any
+ additional padding; */
+ char *type; /* Specifies the encoding for the record based on a type reference URI or a MIME media-type */
+ int data_size; /* Specifies the length (in bytes) of the DATA */
+ unsigned char* data; /* Contains the actual data payload for the record;
+ format of the data depends on the type specified for the record */
+}DIME_PACKAGE;
-/*
- PARAMS
- buffer: The hole received data from socket.
- */
-hresponse_t *hresponse_new_from_buffer(const char* buffer);
-hresponse_t *hresponse_new();
-void hresponse_free(hresponse_t *res);
/* logging stuff*/
typedef enum log_level
diff --git a/nanohttp/nanohttp-reqres.h b/nanohttp/nanohttp-reqres.h
new file mode 100755
index 0000000..0aaef72
--- /dev/null
+++ b/nanohttp/nanohttp-reqres.h
@@ -0,0 +1,73 @@
+/******************************************************************
+ * $Id: nanohttp-reqres.h,v 1.1 2004/09/19 07:05:03 snowdrop Exp $
+ *
+ * CSOAP Project: A http client/server library in C
+ * Copyright (C) 2003-2004 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: ferhatayaz@yahoo.com
+ ******************************************************************/
+#ifndef NANO_HTTP_REQRES_H
+#define NANO_HTTP_REQRES_H
+
+#include <nanohttp/nanohttp-stream.h>
+
+/*
+ request object
+ */
+typedef struct hrequest
+{
+ char *method;
+ char *path;
+ char *spec;
+ hpair_t *query;
+ hpair_t *header;
+}hrequest_t;
+
+hrequest_t *hrequest_new_from_buffer(char *data);
+void hrequest_free(hrequest_t *req);
+
+/* response object */
+typedef struct hresponse
+{
+ char spec[10];
+ int errcode;
+ char *desc;
+ hpair_t *header;
+ char *body;
+ long bodysize;
+ http_input_stream_t *in;
+}hresponse_t;
+
+/*
+ PARAMS
+ buffer: The hole received data from socket.
+ */
+hresponse_t *hresponse_new_from_buffer(const char* buffer);
+hresponse_t *hresponse_new_from_socket(hsocket_t sock);
+hresponse_t *hresponse_new();
+void hresponse_free(hresponse_t *res);
+
+
+
+#endif
+
+
+
+
+
+
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index f6f2288..9fecc1a 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-server.c,v 1.24 2004/09/14 17:34:36 snowdrop Exp $
+* $Id: nanohttp-server.c,v 1.25 2004/09/19 07:05:03 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -559,26 +559,27 @@ httpd_run ()
/* Wait for a socket to accept */
while (_httpd_run)
{
- /* zero and set file descriptior */
- FD_ZERO (&fds);
- FD_SET (_httpd_socket, &fds);
-
- /* select socket descriptor */
- switch (select(_httpd_socket+1, &fds, NULL, NULL, &timeout))
- {
- case 0:
- /* descriptor is not ready */
- continue;
- case -1:
- /* got a signal? */
- continue;
- default:
- /* no nothing */
- break;
- }
- if (FD_ISSET (_httpd_socket, &fds)) {
- break;
- }
+ /* zero and set file descriptior */
+ FD_ZERO (&fds);
+ FD_SET (_httpd_socket, &fds);
+
+ /* select socket descriptor */
+ switch (select(_httpd_socket+1, &fds, NULL, NULL, &timeout))
+ {
+ case 0:
+ /* descriptor is not ready */
+ continue;
+ case -1:
+ /* got a signal? */
+ continue;
+ default:
+ /* no nothing */
+ break;
+ }
+ if (FD_ISSET (_httpd_socket, &fds))
+ {
+ break;
+ }
}
/* check signal status*/
@@ -601,14 +602,14 @@ httpd_run ()
}
-char *
+unsigned 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;
+ unsigned char *postdata = NULL;
if (!strcmp (req->method, "POST"))
{
@@ -636,14 +637,14 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received,
postdata[0] = '\0';
return postdata;
}
- postdata = (char *) malloc (content_length + 1);
+ postdata = (unsigned 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)
+ (int)content_length, 1)>0)
{
*received = content_length;
postdata[content_length] = '\0';
diff --git a/nanohttp/nanohttp-server.h b/nanohttp/nanohttp-server.h
index d7ff39e..3170c3d 100644
--- a/nanohttp/nanohttp-server.h
+++ b/nanohttp/nanohttp-server.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-server.h,v 1.4 2004/09/01 14:09:44 snowdrop Exp $
+ * $Id: nanohttp-server.h,v 1.5 2004/09/19 07:05:03 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -27,7 +27,7 @@
#include <nanohttp/nanohttp-common.h>
#include <nanohttp/nanohttp-socket.h>
-
+#include <nanohttp/nanohttp-reqres.h>
#define NHTTPD_ARG_PORT "-NHTTPport"
#define NHTTPD_ARG_TERMSIG "-NHTTPtsig"
@@ -73,7 +73,7 @@ int httpd_send_header(httpd_conn_t *res,
hpair_t *pair);
-char *httpd_get_postdata(httpd_conn_t *conn,
+unsigned char *httpd_get_postdata(httpd_conn_t *conn,
hrequest_t *req, long *received, long max);
#endif
diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c
index c1699e8..718b96f 100644
--- a/nanohttp/nanohttp-socket.c
+++ b/nanohttp/nanohttp-socket.c
@@ -1,513 +1,490 @@
-/******************************************************************
-* $Id: nanohttp-socket.c,v 1.21 2004/09/14 15:50:54 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
-******************************************************************/
-#include <nanohttp/nanohttp-socket.h>
-#include <nanohttp/nanohttp-common.h>
-
-
-
-
-#ifdef WIN32
- #include "wsockcompat.h"
- #include <winsock2.h>
- #include <process.h>
-
-#ifndef __MINGW32__
- typedef int ssize_t;
-#endif
-
-#else
- #include <fcntl.h>
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-
-/*--------------------------------------------------
-FUNCTION: hsocket_module_init
-NOTE: This will be called from httpd_init()
- for server and from httpc_init() for client
-----------------------------------------------------*/
-int
-hsocket_module_init ()
-{
-#ifdef WIN32
- struct WSAData info;
- WSAStartup (MAKEWORD (2, 2), &info);
-
-#else /* */
- /* nothing to init for unix sockets */
-#endif /* */
- return 0;
-}
-
-/*--------------------------------------------------
-FUNCTION: hsocket_module_destroy
-----------------------------------------------------*/
-void
-hsocket_module_destroy ()
-{
-#ifdef WIN32
- WSACleanup ();
-
-#else /* */
- /* nothing to destroy for unix sockets */
-#endif /* */
-}
-
-
-/*--------------------------------------------------
-FUNCTION: hsocket_init
-----------------------------------------------------*/
-int
-hsocket_init (hsocket_t * sock)
-{
- /* just set the descriptor to -1 */
- *sock = -1;
- return 0;
-}
-
-
-/*--------------------------------------------------
-FUNCTION: hsocket_free
-----------------------------------------------------*/
-void
-hsocket_free (hsocket_t sock)
-{
- /* nothing to free for unix sockets */
-}
-
-
-/*--------------------------------------------------
-FUNCTION: hsocket_open
-----------------------------------------------------*/
-int
-hsocket_open (hsocket_t * dsock, const char *hostname, int port)
-{
- hsocket_t sock;
- char *ip;
- struct sockaddr_in address;
- struct hostent *host;
-
- 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;
-
- ip = inet_ntoa (*(struct in_addr *) *host->h_addr_list);
- address.sin_addr.s_addr = inet_addr (ip);
-
- /* 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;
-}
-
-
-/*--------------------------------------------------
-FUNCTION: hsocket_bind
-----------------------------------------------------*/
-int
-hsocket_bind (hsocket_t * dsock, int port)
-{
- hsocket_t 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;
-}
-
-
-/*----------------------------------------------------------
-FUNCTION: hsocket_accept
-----------------------------------------------------------*/
-int hsocket_accept(hsocket_t sock, hsocket_t *dest)
-{
- socklen_t asize;
- hsocket_t sockfd;
- struct sockaddr_in addr;
-
- asize = sizeof(struct sockaddr_in);
-#ifdef WIN32
- while(1)
- {
- sockfd = accept(sock, (struct sockaddr *)&addr, &asize);
- if (sockfd == INVALID_SOCKET)
- {
- if(WSAGetLastError()!=WSAEWOULDBLOCK)
- return HSOCKET_CAN_NOT_ACCEPT;
- }
- else
- {
- break;
- }
- }
-#else
- sockfd = accept(sock, (struct sockaddr *)&addr, &asize);
- if (sockfd == -1) {
- 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_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;
-}
-
-/*--------------------------------------------------
-FUNCTION: hsocket_close
-----------------------------------------------------*/
-void
-hsocket_close (hsocket_t sock)
-{
-#ifdef WIN32
- closesocket (sock);
-#else
- close (sock);
-#endif
-}
-
-
-/*--------------------------------------------------
-FUNCTION: hsocket_send
-----------------------------------------------------*/
-int
-hsocket_nsend (hsocket_t sock, const char *buffer, int n)
-{
- int size;
-
- size = send ((int) sock, buffer, n, 0);
- if (size == -1)
- return HSOCKET_CAN_NOT_SEND;
-
- return HSOCKET_OK;
-}
-
-/*--------------------------------------------------
-FUNCTION: hsocket_send
-----------------------------------------------------*/
-int
-hsocket_send (hsocket_t sock, const char *buffer)
-{
- return hsocket_nsend(sock, buffer, strlen(buffer));
-}
-
-
-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)
- {
-#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
-----------------------------------------------------*/
-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;
-}
-
-
-
-/*--------------------------------------------------
-FUNCTION: hsocket_recv
-----------------------------------------------------*/
-int
-hsocket_recv_cb (hsocket_t sock, 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;
-}
-
-
-
-/*--------------------------------------------------
-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
-hsocket_makenonblock (hsocket_t sock)
-{
-#ifdef WIN32
- unsigned long iMode;
- iMode = HSOCKET_NONBLOCKMODE;
- if (ioctlsocket (sock, FIONBIO, (u_long FAR *) & iMode) == INVALID_SOCKET)
- {
- log_error1 ("ioctlsocket error");
- return -1;
- }
-#else /* fcntl(sock, F_SETFL, O_NONBLOCK); */
-#endif
- return HSOCKET_OK;
-}
-
-#ifdef WIN32
-
-struct tm *
-localtime_r (const time_t * const timep, struct tm *p_tm)
-{
- static struct tm *tmp;
- tmp = localtime (timep);
- if (tmp)
- {
- memcpy (p_tm, tmp, sizeof (struct tm));
- tmp = p_tm;
- }
- return tmp;
-}
-
-#endif /* */
+/******************************************************************
+* $Id: nanohttp-socket.c,v 1.22 2004/09/19 07:05:03 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
+******************************************************************/
+#include <nanohttp/nanohttp-socket.h>
+#include <nanohttp/nanohttp-common.h>
+
+#ifdef WIN32
+#include "wsockcompat.h"
+#include <winsock2.h>
+#include <process.h>
+
+#ifndef __MINGW32__
+typedef int ssize_t;
+#endif
+
+#else
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+/*--------------------------------------------------
+FUNCTION: hsocket_module_init
+NOTE: This will be called from httpd_init()
+ for server and from httpc_init() for client
+----------------------------------------------------*/
+int
+hsocket_module_init ()
+{
+#ifdef WIN32
+ struct WSAData info;
+ WSAStartup (MAKEWORD (2, 2), &info);
+
+#else /* */
+ /* nothing to init for unix sockets */
+#endif /* */
+ return 0;
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_module_destroy
+----------------------------------------------------*/
+void
+hsocket_module_destroy ()
+{
+#ifdef WIN32
+ WSACleanup ();
+
+#else /* */
+ /* nothing to destroy for unix sockets */
+#endif /* */
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_init
+----------------------------------------------------*/
+int
+hsocket_init (hsocket_t * sock)
+{
+ /* just set the descriptor to -1 */
+ *sock = -1;
+ return 0;
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_free
+----------------------------------------------------*/
+void
+hsocket_free (hsocket_t sock)
+{
+ /* nothing to free for unix sockets */
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_open
+----------------------------------------------------*/
+int
+hsocket_open (hsocket_t * dsock, const char *hostname, int port)
+{
+ hsocket_t sock;
+ char *ip;
+ struct sockaddr_in address;
+ struct hostent *host;
+
+ 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;
+
+ ip = inet_ntoa (*(struct in_addr *) *host->h_addr_list);
+ address.sin_addr.s_addr = inet_addr (ip);
+
+ /* 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;
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_bind
+----------------------------------------------------*/
+int
+hsocket_bind (hsocket_t * dsock, int port)
+{
+ hsocket_t 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;
+}
+
+/*----------------------------------------------------------
+FUNCTION: hsocket_accept
+----------------------------------------------------------*/
+int
+hsocket_accept (hsocket_t sock, hsocket_t * dest)
+{
+ socklen_t asize;
+ hsocket_t sockfd;
+ struct sockaddr_in addr;
+
+ asize = sizeof (struct sockaddr_in);
+#ifdef WIN32
+ while (1)
+ {
+ sockfd = accept (sock, (struct sockaddr *) &addr, &asize);
+ if (sockfd == INVALID_SOCKET)
+ {
+ if (WSAGetLastError () != WSAEWOULDBLOCK)
+ return HSOCKET_CAN_NOT_ACCEPT;
+ }
+ else
+ {
+ break;
+ }
+ }
+#else
+ sockfd = accept (sock, (struct sockaddr *) &addr, &asize);
+ if (sockfd == -1)
+ {
+ 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_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;
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_close
+----------------------------------------------------*/
+void
+hsocket_close (hsocket_t sock)
+{
+#ifdef WIN32
+ closesocket (sock);
+#else
+ close (sock);
+#endif
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_send
+----------------------------------------------------*/
+int
+hsocket_nsend (hsocket_t sock, const unsigned char *bytes, int n)
+{
+ int size;
+
+ size = send ((int) sock, bytes, n, 0);
+ if (size == -1)
+ return HSOCKET_CAN_NOT_SEND;
+
+ return HSOCKET_OK;
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_send
+----------------------------------------------------*/
+int
+hsocket_send (hsocket_t sock, const char *str)
+{
+ return hsocket_nsend (sock, str, strlen (str));
+}
+
+/*
+ return: -1 is error. read bytes otherwise
+*/
+int
+hsocket_read (hsocket_t sock, unsigned char *buffer, int total, int force)
+{
+ int status;
+ int totalRead;
+
+ totalRead = 0;
+
+ do
+ {
+ status = recv (sock, &buffer[totalRead], total - totalRead, 0);
+
+#ifdef WIN32
+ if (status == INVALID_SOCKET)
+ if (WSAGetLastError () == WSAEWOULDBLOCK)
+ continue;
+ else
+ return -1;
+#else
+ if (status == -1)
+ return -1;
+#endif
+
+ if (!force)
+ return status;
+
+ totalRead += status;
+
+ if (totalRead == total)
+ return totalRead;
+ }
+ while (1);
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_recv
+----------------------------------------------------*/
+int
+hsocket_recv (hsocket_t sock, unsigned 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;
+}
+
+/*--------------------------------------------------
+FUNCTION: hsocket_recv
+----------------------------------------------------*/
+int
+hsocket_recv_cb (hsocket_t sock, 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;
+}
+
+/*--------------------------------------------------
+FUNCTION: hbufsocket_read
+----------------------------------------------------*/
+int
+hbufsocket_read (hbufsocket_t * bufsock, char *buffer, int size)
+{
+ int status;
+ int tmpsize;
+
+ if (bufsock->bufsize - bufsock->cur >= size)
+ {
+
+ /* 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_verbose5 ("tmpsize=%d, bufsock->bufsize=%d, bufsock->cur=%d, size=%d",
+ tmpsize, bufsock->bufsize, bufsock->cur, size);
+
+ if (tmpsize > 0)
+ strncpy (buffer, &(bufsock->buffer[bufsock->cur]), tmpsize);
+
+ size -= tmpsize;
+
+ free (bufsock->buffer);
+
+ status = hsocket_read (bufsock->sock, &buffer[tmpsize], size, 1);
+ log_verbose3("hsocket_read(): size=%d,status=%d", size, status);
+ if (status == size)
+ {
+ bufsock->buffer = (char *) malloc (size + 1);
+ strncpy (bufsock->buffer, &buffer[tmpsize], size);
+ bufsock->cur = size;
+ bufsock->bufsize = size;
+ }
+ else
+ {
+ return status;
+ }
+
+ return HSOCKET_OK;
+ }
+}
+
+int
+hsocket_makenonblock (hsocket_t sock)
+{
+#ifdef WIN32
+ unsigned long iMode;
+ iMode = HSOCKET_NONBLOCKMODE;
+ if (ioctlsocket (sock, FIONBIO, (u_long FAR *) & iMode) == INVALID_SOCKET)
+ {
+ log_error1 ("ioctlsocket error");
+ return -1;
+ }
+#else /* fcntl(sock, F_SETFL, O_NONBLOCK); */
+#endif
+ return HSOCKET_OK;
+}
+
+#ifdef WIN32
+
+struct tm *
+localtime_r (const time_t * const timep, struct tm *p_tm)
+{
+ static struct tm *tmp;
+ tmp = localtime (timep);
+ if (tmp)
+ {
+ memcpy (p_tm, tmp, sizeof (struct tm));
+ tmp = p_tm;
+ }
+ return tmp;
+}
+
+#endif /* */
diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h
index 117a5b2..48d2a0b 100644
--- a/nanohttp/nanohttp-socket.h
+++ b/nanohttp/nanohttp-socket.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-socket.h,v 1.11 2004/09/14 13:23:10 snowdrop Exp $
+ * $Id: nanohttp-socket.h,v 1.12 2004/09/19 07:05:03 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -118,7 +118,7 @@ int hsocket_accept(hsocket_t sock, hsocket_t *dest);
Returns 0 if success
>0 if fail
*/
-int hsocket_nsend(hsocket_t sock, const char* buffer, int n);
+int hsocket_nsend(hsocket_t sock, const unsigned char* buffer, int n);
/*
hsocket_send
@@ -126,7 +126,7 @@ int hsocket_nsend(hsocket_t sock, const char* buffer, int n);
Returns 0 if success
>0 if fail
*/
-int hsocket_send(hsocket_t sock, const char* buffer);
+int hsocket_send(hsocket_t sock, const char* str);
/*
@@ -161,7 +161,7 @@ int hsocket_send(hsocket_t sock, const char* buffer);
Returns 0 if success
>0 if fail
*/
-int hsocket_recv(hsocket_t sock, char** buffer, int *size);
+int hsocket_recv(hsocket_t sock, unsigned char** buffer, int *size);
int hsocket_recv_limit(hsocket_t sock, char** buffer,
const char* delim, char **rest,
@@ -173,7 +173,7 @@ int hsocket_recv_limit(hsocket_t sock, char** buffer,
int hsocket_recv_cb(hsocket_t sock,
hsocket_recv_callback cb, void *userdata);
-int hsocket_read(hsocket_t sock, char* buffer, int total, int force);
+int hsocket_read(hsocket_t sock, unsigned char* buffer, int total, int force);
/* ======================================== */
diff --git a/nanohttp/nanohttp-stream.c b/nanohttp/nanohttp-stream.c
new file mode 100755
index 0000000..8eb31d6
--- /dev/null
+++ b/nanohttp/nanohttp-stream.c
@@ -0,0 +1,292 @@
+/******************************************************************
+* $Id: nanohttp-stream.c,v 1.1 2004/09/19 07:05:03 snowdrop Exp $
+*
+* CSOAP Project: A http client/server library in C
+* Copyright (C) 2003-2004 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: ferhatayaz@yahoo.com
+******************************************************************/
+
+#define STREAM_INVALID -1
+#define STREAM_INVALID_TYPE -2
+#define STREAM_SOCKET_ERROR -3
+#define STREAM_NO_CHUNK_SIZE -4
+
+#include <nanohttp/nanohttp-stream.h>
+
+static
+int _http_stream_is_content_length(hpair_t *header)
+{
+ return
+ hpairnode_get_ignore_case(header, HEADER_CONTENT_LENGTH) != NULL;
+}
+
+static
+int _http_stream_is_chunked(hpair_t *header)
+{
+ char *chunked;
+ chunked = hpairnode_get_ignore_case(header, HEADER_TRANSFER_ENCODING);
+ if (chunked != NULL)
+ {
+ if (!strcmp(chunked, TRANSFER_ENCODING_CHUNKED))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ Creates a new input stream.
+*/
+http_input_stream_t *http_input_stream_new(hsocket_t sock, hpair_t *header)
+{
+ http_input_stream_t *result;
+ char *content_length;
+ char *chunked;
+
+ /* Paranoya check */
+ if (header == NULL)
+ return NULL;
+
+ /* Create object */
+ result = (http_input_stream_t*)malloc(sizeof(http_input_stream_t));
+ result->sock = sock;
+
+ /* Find connection type */
+
+ /* Check if Content-type */
+ if (_http_stream_is_content_length(header))
+ {
+ log_verbose1("Stream transfer with 'Content-length'");
+ content_length = hpairnode_get_ignore_case(header, HEADER_CONTENT_LENGTH);
+ result->content_length = atoi(content_length);
+ result->received = 0;
+ result->type = HTTP_TRANSFER_CONTENT_LENGTH;
+ }
+ /* Check if Chunked */
+ else if (_http_stream_is_chunked(header))
+ {
+ log_verbose1("Stream transfer with 'chunked'");
+ result->type = HTTP_TRANSFER_CONTENT_CHUNKED;
+ result->chunk_size = -1;
+ result->received = -1;
+ }
+ /* Assume connection close */
+ else
+ {
+ log_verbose1("Stream transfer with 'Connection: close'");
+ result->type = HTTP_TRANSFER_CONNECTION_CLOSE;
+ }
+
+ return result;
+}
+
+
+/**
+ Free input stream
+*/
+void http_input_stream_free(http_input_stream_t *stream)
+{
+ free(stream);
+}
+
+static
+int _http_input_stream_is_content_length_ready(
+ http_input_stream_t *stream)
+{
+ return (stream->content_length > stream->received);
+}
+
+static
+int _http_input_stream_is_chunked_ready(
+ http_input_stream_t *stream)
+{
+ return stream->chunk_size != 0;
+
+}
+
+static
+int _http_input_stream_is_connection_closed_ready(
+ http_input_stream_t *stream)
+{
+/* TODO (#1#): implement */
+}
+
+static
+int _http_input_stream_content_length_read(
+ http_input_stream_t *stream, byte_t *dest, size_t size)
+{
+ int status;
+
+ /* check limit */
+ if (stream->content_length - stream->received < size)
+ size = stream->content_length - stream->received;
+
+ /* read from socket */
+ status = hsocket_read(stream->sock, dest, size, 1);
+ if (status == -1)
+ return STREAM_SOCKET_ERROR;
+
+ stream->received += status;
+ return status;
+}
+
+static
+int _http_input_stream_chunked_read_chunk_size(
+ http_input_stream_t *stream)
+{
+ char chunk[25];
+ int chunk_size, status, i = 0;
+
+ while (1)
+ {
+ status = hsocket_read(stream->sock, &(chunk[i]), 1, 1);
+
+ if (status == -1)
+ return STREAM_SOCKET_ERROR;
+
+ if (chunk[i] == '\r' || chunk[i] == ';')
+ {
+ chunk[i] = '\0';
+ }
+ else if (chunk[i] == '\n')
+ {
+ chunk[i] = '\0'; /* double check*/
+ chunk_size = strtol(chunk, (char **) NULL, 16); /* hex to dec */
+ log_debug3("chunk_size: '%s' as dec: '%d'", chunk, chunk_size);
+ return chunk_size;
+ }
+
+ if (i == 24)
+ return STREAM_NO_CHUNK_SIZE;
+ else
+ i++;
+ }
+
+ /* this should never happens */
+ return STREAM_NO_CHUNK_SIZE;
+}
+
+static
+int _http_input_stream_chunked_read(
+ http_input_stream_t *stream, byte_t *dest, size_t size)
+{
+ int status;
+ int remain, read=0;
+
+ while (size > 0)
+ {
+ remain = stream->chunk_size - stream->received ;
+
+ if (remain == 0)
+ {
+ /* receive new chunk size */
+ stream->chunk_size =
+ _http_input_stream_chunked_read_chunk_size(stream);
+
+ if (stream->chunk_size < 0)
+ {
+ /* TODO (#1#): set error flag */
+ return stream->chunk_size;
+ }
+ else if (stream->chunk_size == 0)
+ {
+ return read;
+ }
+ remain = stream->chunk_size;
+ }
+
+ /* show remaining chunk size in socket */
+ if (remain < size)
+ {
+ /* read from socket */
+ status = hsocket_read(stream->sock, &(dest[read]), remain, 1);
+ if (status == -1)
+ return STREAM_SOCKET_ERROR;
+
+ }
+ else
+ {
+ /* read from socket */
+ status = hsocket_read(stream->sock, &(dest[read]), size, 1);
+ if (status == -1)
+ return STREAM_SOCKET_ERROR;
+ }
+
+ read += status;
+ size -= status;
+ stream->received += status;
+ }
+}
+
+static
+int _http_input_stream_connection_closed_read(
+ http_input_stream_t *stream, byte_t *dest, size_t size)
+{
+/* TODO (#1#): implement */
+ return 0;
+}
+
+/**
+ Returns the actual status of the stream.
+*/
+int http_input_stream_is_ready(http_input_stream_t *stream)
+{
+ /* paranoya check */
+ if (stream == NULL)
+ return 0;
+
+ switch (stream->type)
+ {
+ case HTTP_TRANSFER_CONTENT_LENGTH:
+ return _http_input_stream_is_content_length_ready(stream);
+ case HTTP_TRANSFER_CONTENT_CHUNKED:
+ return _http_input_stream_is_chunked_ready(stream);
+ case HTTP_TRANSFER_CONNECTION_CLOSE:
+ return _http_input_stream_is_connection_closed_ready(stream);
+ default:
+ return 0;
+ }
+}
+
+/**
+ Returns the actual read bytes
+ <0 on error
+*/
+int http_input_stream_read(http_input_stream_t *stream,
+ byte_t *dest, size_t size)
+{
+ /* paranoya check */
+ if (stream == NULL)
+ return STREAM_INVALID;
+
+ switch (stream->type)
+ {
+ case HTTP_TRANSFER_CONTENT_LENGTH:
+ return _http_input_stream_content_length_read(stream, dest, size);
+ case HTTP_TRANSFER_CONTENT_CHUNKED:
+ return _http_input_stream_chunked_read(stream, dest, size);
+ case HTTP_TRANSFER_CONNECTION_CLOSE:
+ return _http_input_stream_connection_closed_read(stream, dest, size);
+ default:
+ return STREAM_INVALID_TYPE;
+ }
+}
+
diff --git a/nanohttp/nanohttp-stream.h b/nanohttp/nanohttp-stream.h
new file mode 100755
index 0000000..edbf371
--- /dev/null
+++ b/nanohttp/nanohttp-stream.h
@@ -0,0 +1,80 @@
+/******************************************************************
+ * $Id: nanohttp-stream.h,v 1.1 2004/09/19 07:05:03 snowdrop Exp $
+ *
+ * CSOAP Project: A http client/server library in C
+ * Copyright (C) 2003-2004 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: ferhatayaz@yahoo.com
+ ******************************************************************/
+#ifndef NANO_HTTP_STREAM_H
+#define NANO_HTTP_STREAM_H
+
+#include <nanohttp/nanohttp-socket.h>
+#include <nanohttp/nanohttp-common.h>
+
+/**
+ Supported transfer types
+*/
+typedef enum http_transfer_type
+{
+ HTTP_TRANSFER_CONTENT_LENGTH,
+ HTTP_TRANSFER_CONTENT_CHUNKED,
+ HTTP_TRANSFER_CONNECTION_CLOSE
+}http_transfer_type_t;
+
+/**
+ HTTP INPUT STREAM
+*/
+typedef struct http_input_stream
+{
+ hsocket_t sock;
+ http_transfer_type_t type;
+ size_t received;
+ size_t content_length;
+ size_t chunk_size;
+}http_input_stream_t;
+
+
+/**
+ Creates a new input stream.
+*/
+http_input_stream_t *http_input_stream_new(hsocket_t sock, hpair_t *header);
+
+/**
+ Free input stream
+*/
+void http_input_stream_free(http_input_stream_t *stream);
+
+/**
+ Returns the actual status of the stream.
+*/
+int http_input_stream_is_ready(http_input_stream_t *stream);
+
+/**
+ Returns the actual read bytes
+*/
+int http_input_stream_read(http_input_stream_t *stream,
+ byte_t *dest, size_t size);
+
+#endif
+
+
+
+
+
+