diff options
Diffstat (limited to 'nanohttp')
-rw-r--r-- | nanohttp/Makefile.am | 7 | ||||
-rw-r--r-- | nanohttp/nanohttp-client.c | 426 | ||||
-rw-r--r-- | nanohttp/nanohttp-client.h | 222 | ||||
-rw-r--r-- | nanohttp/nanohttp-common.c | 108 | ||||
-rw-r--r-- | nanohttp/nanohttp-common.h | 70 | ||||
-rwxr-xr-x | nanohttp/nanohttp-reqres.h | 73 | ||||
-rw-r--r-- | nanohttp/nanohttp-server.c | 51 | ||||
-rw-r--r-- | nanohttp/nanohttp-server.h | 6 | ||||
-rw-r--r-- | nanohttp/nanohttp-socket.c | 1003 | ||||
-rw-r--r-- | nanohttp/nanohttp-socket.h | 10 | ||||
-rwxr-xr-x | nanohttp/nanohttp-stream.c | 292 | ||||
-rwxr-xr-x | nanohttp/nanohttp-stream.h | 80 |
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 + + + + + + |