summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar snowdrop2004-10-15 13:29:36 +0000
committerGravatar snowdrop2004-10-15 13:29:36 +0000
commitb0691bfc7943532575dba0cee285838d45072535 (patch)
tree8690810748ac8ddb5d9cbda961f7d5ef7e711faa
parentd2c445f5d7cf21606c9878bff3e4046c283944df (diff)
downloadcsoap-b0691bfc7943532575dba0cee285838d45072535.tar.gz
csoap-b0691bfc7943532575dba0cee285838d45072535.tar.bz2
added mime support and https stream object
-rw-r--r--nanohttp/nanohttp-client.c959
-rw-r--r--nanohttp/nanohttp-client.h131
-rw-r--r--nanohttp/nanohttp-common.c617
-rw-r--r--nanohttp/nanohttp-common.h368
-rw-r--r--nanohttp/nanohttp-server.c587
-rw-r--r--nanohttp/nanohttp-server.h57
-rw-r--r--nanohttp/nanohttp-socket.c355
-rw-r--r--nanohttp/nanohttp-socket.h282
8 files changed, 1608 insertions, 1748 deletions
diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c
index 13972a1..3c3ce7f 100644
--- a/nanohttp/nanohttp-client.c
+++ b/nanohttp/nanohttp-client.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-client.c,v 1.19 2004/09/19 07:05:03 snowdrop Exp $
+* $Id: nanohttp-client.c,v 1.20 2004/10/15 13:29:36 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -19,10 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
-* Email: ayaz@jprogrammer.net
+* Email: ferhatayaz@yahoo.com
******************************************************************/
#include <nanohttp/nanohttp-client.h>
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -31,6 +32,15 @@
#include <stdio.h>
#include <stdlib.h>
+#ifdef MEM_DEBUG
+#include <utils/alloc.h>
+#endif
+
+static
+int httpc_send_data(httpc_conn_t *conn, const unsigned char* data, size_t size)
+{
+ return -1;
+}
/*--------------------------------------------------
FUNCTION: httpc_init
@@ -53,15 +63,16 @@ to communicate via http.
httpc_conn_t *
httpc_new()
{
+ static int counter = 10000;
httpc_conn_t *res = (httpc_conn_t *) malloc(sizeof(httpc_conn_t));
hsocket_init(&res->sock);
res->header = NULL;
- res->url = NULL;
res->version = HTTP_1_1;
+ res->out = NULL;
res->_dime_package_nr = 0;
res->_dime_sent_bytes = 0;
- res->_is_chunked = 0;
+ res->id = counter++;
return res;
}
@@ -75,17 +86,26 @@ httpc_free(httpc_conn_t * conn)
{
hpair_t *tmp;
- if (conn != NULL) {
- hsocket_free(conn->sock);
+ if (conn == NULL)
+ return;
- while (conn->header != NULL) {
- tmp = conn->header;
- conn->header = conn->header->next;
- hpairnode_free(tmp);
- }
- free(conn);
+ while (conn->header != NULL)
+ {
+ tmp = conn->header;
+ conn->header = conn->header->next;
+ hpairnode_free(tmp);
+ }
+
+ if (conn->out != NULL)
+ {
+ http_output_stream_free(conn->out);
+ conn->out = NULL;
}
+
+ hsocket_free(conn->sock);
+ free(conn);
+
}
@@ -127,6 +147,23 @@ FUNCTION: httpc_header_add_date
DESC: Adds the current date to the header.
----------------------------------------------------*/
static
+void _httpc_set_error(httpc_conn_t *conn, int errcode,
+ const char *format, ...)
+{
+ va_list ap;
+
+ conn->errcode = errcode;
+
+ va_start(ap, format);
+ vsnprintf(conn->errmsg, 149, format, ap);
+ va_end(ap);
+}
+
+/*--------------------------------------------------
+FUNCTION: httpc_header_add_date
+DESC: Adds the current date to the header.
+----------------------------------------------------*/
+static
void
httpc_header_add_date(httpc_conn_t * conn)
{
@@ -160,7 +197,7 @@ httpc_send_header(httpc_conn_t * conn)
if (p->key && p->value) {
sprintf(buffer, "%s: %s\r\n", p->key, p->value);
status = hsocket_send(conn->sock, buffer);
- if (status != HSOCKET_OK)
+ if (status != H_OK)
return status;
}
p = p->next;
@@ -171,443 +208,6 @@ httpc_send_header(httpc_conn_t * conn)
}
/*--------------------------------------------------
-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)
-{
- hresponse_t *res;
- int done;
- int i;
- int status;
- char buffer[HSOCKET_MAX_BUFSIZE];
- char *response;
- char *rest;
- int rsize;
- int restsize;
-
- /* Receive Response incl. header */
- rsize = restsize = 0;
- response = rest = NULL;
- done = 0;
-
- while (!done) {
-
- status = hsocket_read(sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
-
- if (status <= 0) {
- log_error2("Can not receive response (status:%d)", status);
- return NULL;
- }
- for (i = 0; i < status - 2; i++) {
-
- if (buffer[i] == '\n') {
- if (buffer[i + 1] == '\n') {
-
- response = (char *) realloc(response, rsize + i + 1);
- strncpy(&response[rsize], buffer, i);
- response[rsize + i] = '\0';
- rsize += i;
-
- restsize = status - i - 2;
- rest = (char *) malloc(restsize + 1);
- strncpy(rest, &buffer[i + 2], restsize);
- rest[restsize] = '\0';
- done = 1;
- break;
-
- } else if (buffer[i + 1] == '\r' && buffer[i + 2] == '\n') {
-
- response = (char *) realloc(response, rsize + i + 1);
- strncpy(&response[rsize], buffer, i);
- response[rsize + i] = '\0';
- rsize += i;
-
- restsize = status - i - 3;
- rest = (char *) malloc(restsize + 1);
- strncpy(rest, &buffer[i + 3], restsize);
- rest[restsize] = '\0';
- done = 1;
- break;
- }
- }
- }
-
- if (!done)
- rsize += status;
- }
-
-
- if (response == NULL) {
- log_error1("Header too long!");
- return NULL;
- }
- res = hresponse_new_from_buffer(response);
- if (res == NULL) {
- log_error1("Can't create response");
- return NULL;
- }
- res->bodysize = restsize;
- res->body = rest;
-
- if (res->errcode == 100) { /* continue */
- hresponse_free(res);
- res = httpc_receive_header(sock);
- }
- return res;
-}
-
-
-static
-int
-httpc_receive_with_connection_closed(httpc_conn_t * conn,
- hresponse_t * res,
- httpc_response_callback cb,
- void *userdata)
-{
- /* connection closed */
- char *connection_status;
- int status;
- char buffer[HSOCKET_MAX_BUFSIZE];
- int counter;
-
- counter = 0;
-
- /* ================================================= */
- /* Retreive with only "Connection: close" */
- /* ================================================= */
- connection_status =
- hpairnode_get(res->header, HEADER_CONNECTION);
-
- if (connection_status != NULL &&
- !strcmp(connection_status, "close")) {
-
- log_debug1("Server communicates with 'Connection: close' !");
-
- /* Invoke callback for rest */
- if (res->bodysize > 0)
- cb(0, conn, userdata, res->bodysize, res->body);
-
-
- while (1) {
-
- status = hsocket_read(conn->sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
-
- if (status == 0) { /* close connection */
- close(conn->sock);
- return 0;
- }
- if (status < 0) { /* error */
- log_error2("Can nor read from socket (status: %d)", status);
- return 11;
- }
- /* Invoke callback */
- cb(counter++, conn, userdata, status, buffer);
- }
-
- return 0;
- }
- return -1;
-}
-
-static
-int
-httpc_receive_with_chunked_encoding(httpc_conn_t * conn,
- hresponse_t * res,
- httpc_response_callback cb,
- void *userdata)
-{
- /* chunked encoding */
- char *transfer_encoding;
- char *chunk_buffer;
- int chunk_size;
- hbufsocket_t bufsock;
- char chunk_size_str[25];
- int chunk_size_cur;
- int counter;
- char buffer[2];
-
- counter = 0;
- /* ================================================= */
- /* Retreive with chunked encoding */
- /* ================================================= */
-
- /* Check if server communicates with chunked encoding */
- transfer_encoding =
- hpairnode_get(res->header, HEADER_TRANSFER_ENCODING);
-
- if (transfer_encoding != NULL &&
- !strcmp(transfer_encoding, "chunked")) {
-
- log_debug1("Server communicates with chunked encoding !");
-
- /* initialize buffered socket */
- bufsock.sock = conn->sock;
- bufsock.cur = 0;
- bufsock.buffer = (char *) res->body;
- bufsock.bufsize = res->bodysize;
-
- chunk_size = 1;
- while (chunk_size > 0) {
-
- /* read chunk size */
- chunk_size_cur = 0;
- while (1) {
-
- if (hbufsocket_read(&bufsock, &chunk_size_str[chunk_size_cur], 1)) {
- log_error1("Can not read from socket");
- return 9;
- }
-
- log_debug2("chunk_size_str[chunk_size_cur] = '%c'",
- chunk_size_str[chunk_size_cur]);
-
- if (chunk_size_str[chunk_size_cur] == '\n') {
- chunk_size_str[chunk_size_cur] = '\0';
- break;
- }
- if (chunk_size_str[chunk_size_cur] != '\r'
- && chunk_size_str[chunk_size_cur] != ';') {
- chunk_size_cur++;
- }
- /* TODO (#1#): check for chunk_size_cur >= 25 */
-
- } /* while (1) */
-
- chunk_size = strtol(chunk_size_str, (char **) NULL, 16); /* hex to dec */
- log_debug3("chunk_size: '%s' as dec: '%d'",
- chunk_size_str, chunk_size);
-
- if (chunk_size <= 0)
- break;
-
- chunk_buffer = (char *) malloc(chunk_size + 1);
- if (hbufsocket_read(&bufsock, chunk_buffer, chunk_size)) {
- log_error1("Can not read from socket");
- return 9;
- }
- cb(counter++, conn, userdata, chunk_size, chunk_buffer);
- free(chunk_buffer);
-
- /* skip new line */
- buffer[0] = 0; /* reset buffer[0] */
- while (buffer[0] != '\n') {
- hbufsocket_read(&bufsock, &buffer[0], 1);
- }
-
- } /* while (chunk_size > 0) */
-
- /* rest and response are no longer required */
-
- return 0;
-
- } /* if transfer_encodig */
- return -1;
-}
-
-/*
- * returns -1 if server does not communicate with content-length;
- */
-static
-int
-httpc_receive_with_content_length(httpc_conn_t * conn,
- hresponse_t * res,
- httpc_response_callback cb,
- void *userdata)
-{
- int counter;
- int content_length;
- int remain_length;
- int recvSize;
- char *content_length_str;
- char buffer[HSOCKET_MAX_BUFSIZE];
-
- /* ================================================= */
- /* Retreive with content-length */
- /* ================================================= */
-
- /* Check if server communicates with content-length */
- content_length_str =
- hpairnode_get_ignore_case(res->header, HEADER_CONTENT_LENGTH);
-
- if (content_length_str != NULL) {
-
- log_debug1("Server communicates with content-length!");
-
- /* Invoke callback for rest */
- if (res->bodysize > 0)
- cb(0, conn, userdata, res->bodysize, (char *) res->body);
-
- /* content length */
- content_length = atol(content_length_str);
-
- counter = 1;
- remain_length = content_length - res->bodysize;
- while (remain_length > 0) {
- if (remain_length >= HSOCKET_MAX_BUFSIZE) {
- recvSize = HSOCKET_MAX_BUFSIZE;
- } else {
- recvSize = remain_length;
- }
-
- if (hsocket_read(conn->sock, buffer, recvSize, 1)) {
- log_error1("Can not read from socket!");
- return 9;
- } else {
- cb(counter++, conn, userdata, recvSize, buffer);
- }
-
- remain_length -= HSOCKET_MAX_BUFSIZE;
-
- } /* while */
-
- /* rest and response are no longer required */
-
- return 0;
-
- } /* if content length */
- return -1;
-}
-
-static
-int
-httpc_receive_response(httpc_conn_t * conn,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, void *userdata)
-{
- 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);
- if (res == NULL)
- return 1;
- log_verbose1("header ok");
-
- /* Invoke callback */
- start_cb(conn, userdata, res->header, res->spec,
- res->errcode, res->desc);
-
- /* try to receive with content length */
- status = httpc_receive_with_content_length(conn, res,
- cb, userdata);
- if (status != -1) {
- hresponse_free(res);
- return status;
- }
- status = httpc_receive_with_chunked_encoding(conn, res,
- cb, userdata);
-
- if (status != -1) {
- hresponse_free(res);
- return status;
- }
- status = httpc_receive_with_connection_closed(conn, res,
- cb, userdata);
- if (status != -1) {
- hresponse_free(res);
- return status;
- }
- log_error1("Unknown server response retreive type!");
- 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
module. It will send the request and process the
@@ -654,10 +254,10 @@ If success, this function will return 0.
----------------------------------------------------*/
static
int
-httpc_talk_to_server(hreq_method method, httpc_conn_t * conn,
+httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn,
const char *urlstr)
{
- hurl_t *url;
+ hurl_t url;
char buffer[4096];
int status;
@@ -669,23 +269,25 @@ httpc_talk_to_server(hreq_method method, httpc_conn_t * conn,
httpc_header_add_date(conn);
/* Create url */
- url = hurl_new(urlstr);
- if (url == NULL) {
+ status = hurl_parse(&url, urlstr);
+ if (status != H_OK) {
log_error2("Can not parse URL '%s'", SAVE_STR(urlstr));
- return 2;
+ return status;
}
+/* TODO (#1#): Check for HTTP protocol in URL */
+
/* Set hostname */
- httpc_set_header(conn, HEADER_HOST, url->host);
+ httpc_set_header(conn, HEADER_HOST, url.host);
/* Open connection */
- status = hsocket_open(&conn->sock, url->host, url->port);
- if (status != HSOCKET_OK) {
+ status = hsocket_open(&conn->sock, url.host, url.port);
+ if (status != H_OK) {
log_error3("Can not open connection to '%s' (status:%d)",
- SAVE_STR(url->host), status);
+ SAVE_STR(url.host), status);
return 3;
}
- status = hsocket_makenonblock(conn->sock);
- if (status != HSOCKET_OK) {
+ status = hsocket_block(conn->sock, 0);
+ if (status != H_OK) {
log_error1("Cannot make socket non-blocking");
return status;
}
@@ -694,14 +296,14 @@ httpc_talk_to_server(hreq_method method, httpc_conn_t * conn,
/* Set GET Header */
sprintf(buffer, "GET %s HTTP/%s\r\n",
- (url->context) ? url->context : ("/"),
+ (url.context[0] != '\0') ? 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/%s\r\n",
- (url->context) ? url->context : ("/"),
+ (url.context[0] != '\0') ? url.context : ("/"),
(conn->version == HTTP_1_0)?"1.0":"1.1");
} else {
@@ -710,14 +312,14 @@ httpc_talk_to_server(hreq_method method, httpc_conn_t * conn,
}
status = hsocket_send(conn->sock, buffer);
- if (status != HSOCKET_OK) {
+ if (status != H_OK) {
log_error2("Can not send request (status:%d)", status);
hsocket_close(conn->sock);
return 4;
}
/* Send Header */
status = httpc_send_header(conn);
- if (status != HSOCKET_OK) {
+ if (status != H_OK) {
log_error2("Can not send header (status:%d)", status);
hsocket_close(conn->sock);
return 5;
@@ -726,178 +328,100 @@ httpc_talk_to_server(hreq_method method, httpc_conn_t * conn,
}
-
/*--------------------------------------------------
-FUNCTION: httpc_get_cb
-DESC: Wraps the httpc_talk_to_server() function
-to communicate with GET method.
-
-See the documentation of httpc_talk_to_server()
-for more information.
+FUNCTION: httpc_get
+DESC:
----------------------------------------------------*/
-int
-httpc_get_cb(httpc_conn_t * conn, const char *urlstr,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, void *userdata)
+hresponse_t *
+httpc_get(httpc_conn_t *conn, const char *urlstr)
{
int status;
+ hresponse_t *res;
status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr);
- if (status != HSOCKET_OK)
- return status;
+ if (status != H_OK)
+ {
+ _httpc_set_error(conn, status, "Can not comunicate: %s", urlstr);
+ return NULL;
+ }
- status = _httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
+ res = hresponse_new_from_socket(conn->sock);
+ if (res == NULL)
+ {
+ _httpc_set_error(conn, -1, "Can not get response from '%s'", urlstr);
+ return NULL;
+ }
+
+ return res;
}
-
/*--------------------------------------------------
-FUNCTION: httpc_post_cb
-DESC: Wraps the httpc_talk_to_server() function
-to communicate with POST method.
-
-See the documentation of httpc_talk_to_server()
-for more information.
-
-TODO: Add post content rutine
+FUNCTION: httpc_post_begin
+DESC: Returns H_OK if success
----------------------------------------------------*/
-int
-httpc_post_cb(httpc_conn_t * conn, const char *urlstr,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, int content_size,
- const char *content, void *userdata)
+int httpc_post_begin(httpc_conn_t *conn, const char *url)
{
+
int status;
- char buffer[255];
-
- sprintf(buffer, "%d", content_size);
- httpc_set_header(conn, HEADER_CONTENT_LENGTH, buffer);
-
- status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
- if (status != HSOCKET_OK)
- return status;
- status = hsocket_nsend(conn->sock, content, content_size);
- if (status != HSOCKET_OK)
+ status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url);
+ if (status != H_OK)
return status;
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
-}
-
-
-/* ======================================================
- The following
- functions are used internally to wrap the httpc_x_cb
-(x = get|post) functions.
-======================================================*/
-static
-void
-httpc_custom_res_callback(int counter, httpc_conn_t * conn,
- void *userdata, int size, char *buffer)
-{
- hresponse_t *res;
-
- /* get response object */
- res = (hresponse_t *) userdata;
-
- /* allocate buffersize */
+ conn->out = http_output_stream_new(conn->sock, conn->header);
- res->bodysize += size;
- res->body = (char *) realloc(res->body, res->bodysize + 1);
-
- memcpy(&(res->body[res->bodysize - size]), buffer, size);
- res->body[res->bodysize] = '\0';
-}
-
-
-static
-void
-httpc_custom_start_callback(httpc_conn_t * conn, void *userdata,
- hpair_t * header, const char *spec,
- int errcode, const char *desc)
-{
- hresponse_t *res;
-
- /* get response object */
- res = (hresponse_t *) userdata;
-
- /* set spec */
- if (spec != NULL) {
- strcpy(res->spec, spec);
- }
- /* set errcode */
- res->errcode = errcode;
-
- /* set desc */
- if (desc != NULL) {
- res->desc = (char *) malloc(strlen(desc) + 1);
- strcpy(res->desc, desc);
- }
- /* set header */
- if (header == NULL) {
- log_warn1("header is NULL!");
- }
- res->header = hpairnode_copy_deep(header);
+ return H_OK;
}
/*--------------------------------------------------
-FUNCTION: httpc_get
+FUNCTION: httpc_post_begin
+DESC: End a "POST" method and receive the response.
+ You MUST call httpc_post_end() before!
----------------------------------------------------*/
-hresponse_t *
-httpc_get(httpc_conn_t * conn, const char *url)
+hresponse_t *httpc_post_end(httpc_conn_t *conn)
{
- int status;
- hresponse_t *res;
-
- res = hresponse_new();
- status = httpc_get_cb(conn, url, httpc_custom_start_callback,
- httpc_custom_res_callback, res);
-
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
- return res;
-}
-
+ int status;
+ hresponse_t *res;
-/*--------------------------------------------------
-FUNCTION: httpc_post
-----------------------------------------------------*/
-hresponse_t *
-httpc_post(httpc_conn_t * conn, const char *url,
- int content_size, const char *content)
-{
- int status;
- hresponse_t *res;
+ status = http_output_stream_flush(conn->out);
- res = hresponse_new();
- status = httpc_post_cb(conn, url, httpc_custom_start_callback,
- httpc_custom_res_callback, content_size,
- (char *) content, res);
+ if (status != H_OK)
+ {
+ _httpc_set_error(conn, status, "Can not flush output stream");
+ return NULL;
+ }
- if (status != 0) {
- hresponse_free(res);
- return NULL;
+ res = hresponse_new_from_socket(conn->sock);
+ if (res == NULL)
+ {
+ _httpc_set_error(conn, -1, "Can not get response ");
+ return NULL;
}
+
return res;
}
+
/* ---------------------------------------------------
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;
+ if (status != H_OK)
+ return status;
+
+ conn->out = http_output_stream_new(conn->sock, conn->header);
+
+ return H_OK;
}
static _print_binary_ascii(int n)
@@ -946,7 +470,7 @@ int httpc_dime_next(httpc_conn_t* conn, long content_length,
const char *dime_options, int last)
{
int status, tmp;
- unsigned char header[12];
+ byte_t header[12];
for (tmp=0;tmp<12;tmp++)
header[tmp]=0;
@@ -983,55 +507,47 @@ int httpc_dime_next(httpc_conn_t* conn, long content_length,
_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)
+ status = http_output_stream_write(conn->out, header, 12);
+ if (status != H_OK)
return status;
- status = httpc_send_data(conn, (const unsigned char*)dime_options, strlen(dime_options));
- if (status != HSOCKET_OK)
+ status = http_output_stream_write(conn->out, (const byte_t*)dime_options, strlen(dime_options));
+ if (status != H_OK)
return status;
- status = httpc_send_data(conn, (const unsigned char*)id, strlen(id));
- if (status != HSOCKET_OK)
+ status = http_output_stream_write(conn->out, (const byte_t*)id, strlen(id));
+ if (status != H_OK)
return status;
- status = httpc_send_data(conn, (const unsigned char*)content_type, strlen(content_type));
- if (status != HSOCKET_OK)
+ status = http_output_stream_write(conn->out, (const byte_t*)content_type, strlen(content_type));
+ if (status != H_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)
+hresponse_t* httpc_dime_end(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);
+ /* Flush put stream */
+ status = http_output_stream_flush(conn->out);
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
+ if (status != H_OK)
+ {
+ _httpc_set_error(conn, status, "Can not flush output stream");
+ return NULL;
+ }
+ res = hresponse_new_from_socket(conn->sock);
+ if (res == NULL)
+ {
+ _httpc_set_error(conn, -1, "Can not get response ");
+ return NULL;
+ }
+
return res;
}
@@ -1043,11 +559,11 @@ hresponse_t* httpc_dime_get_response(httpc_conn_t *conn)
static
void _httpc_mime_get_boundary(httpc_conn_t *conn, char *dest)
{
- sprintf(dest, "---=_NH_%p", conn);
+ sprintf(dest, "---=.Part_NH_%d", conn->id);
log_verbose2("boundary= \"%s\"", dest);
}
-int httpc_mime_post_begin(httpc_conn_t *conn, const char *url,
+int httpc_mime_begin(httpc_conn_t *conn, const char *url,
const char* related_start,
const char* related_start_info,
const char* related_type)
@@ -1086,12 +602,12 @@ int httpc_mime_post_begin(httpc_conn_t *conn, const char *url,
httpc_set_header(conn, HEADER_CONTENT_TYPE, buffer);
- status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url);
+ status = httpc_post_begin(conn, url);
return status;
}
-int httpc_mime_post_next(httpc_conn_t *conn,
+int httpc_mime_next(httpc_conn_t *conn,
const char* content_id,
const char* content_type,
const char* transfer_encoding)
@@ -1105,9 +621,10 @@ int httpc_mime_post_next(httpc_conn_t *conn,
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)
+ status = http_output_stream_write(conn->out,
+ (const byte_t*)buffer, strlen(buffer));
+
+ if (status != H_OK)
return status;
/* Send Content header */
@@ -1116,152 +633,96 @@ int httpc_mime_post_next(httpc_conn_t *conn,
HEADER_CONTENT_TRANSFER_ENCODING, transfer_encoding,
HEADER_CONTENT_ID, content_id);
- status = httpc_send_data(conn, (const unsigned char*)buffer, strlen(buffer));
+ status = http_output_stream_write(conn->out,
+ (const byte_t*)buffer, strlen(buffer));
return status;
}
-int httpc_mime_post_send(httpc_conn_t *conn, size_t size, const unsigned char* data)
+hresponse_t *httpc_mime_end(httpc_conn_t *conn)
{
- 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)
-{
-
+ hresponse_t *res;
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;
-}
+ status = http_output_stream_write(conn->out,
+ (const byte_t*)buffer, strlen(buffer));
+ if (status != H_OK)
+ return NULL;
-hresponse_t *httpc_mime_post_end(httpc_conn_t *conn)
-{
- int status;
- hresponse_t *res;
+ /* Flush put stream */
+ status = http_output_stream_flush(conn->out);
- res = hresponse_new();
- status = httpc_mime_post_end_cb(conn, httpc_custom_start_callback,
- httpc_custom_res_callback, res);
+ if (status != H_OK)
+ {
+ _httpc_set_error(conn, status, "Can not flush output stream");
+ return NULL;
+ }
- if (status != 0) {
- hresponse_free(res);
- return NULL;
+ res = hresponse_new_from_socket(conn->sock);
+ if (res == NULL)
+ {
+ _httpc_set_error(conn, -1, "Can not get response ");
+ return NULL;
}
-
+
return res;
-}
-
-
-/*
- * POST Module
- */
-
-
-/*--------------------------------------------------
-FUNCTION: httpc_post_open
-----------------------------------------------------*/
-int
-httpc_post_open(httpc_conn_t * conn, const char *urlstr)
-{
- int status;
-
- httpc_set_header(conn, HEADER_TRANSFER_ENCODING, "chunked");
-
- status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
- return status;
}
-/*--------------------------------------------------
-FUNCTION: httpc_post_send
-----------------------------------------------------*/
-int
-httpc_post_send(httpc_conn_t * conn,
- const char *buffer,
- int bufsize)
+/**
+ Send boundary and part header and continue
+ with next part
+*/
+int
+httpc_mime_send_file (httpc_conn_t * conn,
+ const char *content_id,
+ const char *content_type,
+ const char *transfer_encoding, const char *filename)
{
- char hexsize[100]; /* chunk size in hex */
- int status;
-
- sprintf(hexsize, "%x\r\n", bufsize);
-
- status = hsocket_send(conn->sock, hexsize);
- if (status != HSOCKET_OK)
- return status;
-
- status = hsocket_nsend(conn->sock, buffer, bufsize);
- if (status != HSOCKET_OK)
- return status;
+ int status;
+ FILE *fd = fopen (filename, "rb");
+ byte_t buffer[MAX_FILE_BUFFER_SIZE];
+ size_t size;
- status = hsocket_send(conn->sock, "\r\n");
+ if (fd == NULL)
+ return FILE_ERROR_OPEN;
- return status;
-}
+ status =
+ httpc_mime_next(conn, content_id, content_type, transfer_encoding);
+ if (status != H_OK)
+ {
+ fclose (fd);
+ return status;
+ }
-/*--------------------------------------------------
-FUNCTION: httpc_post_finish_cb
-----------------------------------------------------*/
-int
-httpc_post_finish_cb(httpc_conn_t * conn,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb,
- void *userdata)
-{
- int status;
+ while (!feof (fd))
+ {
+ size = fread (buffer, 1, MAX_FILE_BUFFER_SIZE, fd);
+ if (size == -1)
+ {
+ fclose (fd);
+ return FILE_ERROR_READ;
+ }
- status = hsocket_send(conn->sock, "0\r\n\r\n");
- if (status != HSOCKET_OK)
- return status;
+ status = http_output_stream_write (conn->out, buffer, size);
+ if (status != H_OK) {
+ fclose (fd);
+ return status;
+ }
+ }
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
+ fclose (fd);
+ return H_OK;
}
-/*--------------------------------------------------
-FUNCTION: httpc_post_finish
-----------------------------------------------------*/
-hresponse_t *
-httpc_post_finish(httpc_conn_t * conn)
-{
- int status;
- hresponse_t *res;
-
- res = hresponse_new();
- status = httpc_post_finish_cb(conn, httpc_custom_start_callback,
- httpc_custom_res_callback, res);
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
- return res;
-}
diff --git a/nanohttp/nanohttp-client.h b/nanohttp/nanohttp-client.h
index 6a53f9d..8bd8579 100644
--- a/nanohttp/nanohttp-client.h
+++ b/nanohttp/nanohttp-client.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-client.h,v 1.8 2004/09/19 07:05:03 snowdrop Exp $
+ * $Id: nanohttp-client.h,v 1.9 2004/10/15 13:29:36 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -19,7 +19,7 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Email: ayaz@jprogrammer.net
+ * Email: ferhatayaz@yahoo.com
******************************************************************/
#ifndef NANO_HTTP_CLIENT_H
#define NANO_HTTP_CLIENT_H
@@ -27,13 +27,13 @@
#include <nanohttp/nanohttp-common.h>
#include <nanohttp/nanohttp-socket.h>
-#include <nanohttp/nanohttp-reqres.h>
+#include <nanohttp/nanohttp-response.h>
typedef struct httpc_conn
{
hsocket_t sock;
hpair_t *header;
- hurl_t *url;
+ hurl_t url;
http_version_t version;
/*
-1 : last dime package
@@ -42,44 +42,58 @@ typedef struct httpc_conn
*/
int _dime_package_nr;
long _dime_sent_bytes;
- int _is_chunked;
+ int errcode;
+ char errmsg[150];
+ http_output_stream_t *out;
+ int id; /* uniq id */
}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[]);
+/* --------------------------------------------------------------
+ HTTP CLIENT MODULE RELATED FUNCTIONS
+ ---------------------------------------------------------------*/
+
+/**
+ initialize the httpc_* module
+*/
+hstatus_t httpc_init(int argc, char *argv[]);
+
+/**
+ Creates a new connection
+*/
httpc_conn_t* httpc_new();
+
+/**
+ Release a connections
+*/
void httpc_free(httpc_conn_t* conn);
+/**
+ Set header element (key,value) pair.
+*/
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);
+/**
+ Invoke a "GET" method request and receive the response
+*/
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);
-
+/**
+ Start a "POST" method request
+ Returns: HSOCKET_OK or error flag
+*/
+int httpc_post_begin(httpc_conn_t *conn, const char *url);
+
+/**
+ End a "POST" method and receive the response.
+ You MUST call httpc_post_end() before!
+*/
+hresponse_t *httpc_post_end(httpc_conn_t *conn);
+
-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 RELATED FUNCTIONS
+ ---------------------------------------------------------------*/
/*
DIME support httpc_dime_* function set
@@ -88,47 +102,50 @@ 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);
+hresponse_t* httpc_dime_end(httpc_conn_t *conn);
+
+/* --------------------------------------------------------------
+ MIME RELATED FUNCTIONS
+ ---------------------------------------------------------------*/
/*
MIME support httpc_mime_* function set
*/
-int httpc_mime_post_begin(httpc_conn_t *conn, const char *url,
+/**
+ Begin MIME multipart/related POST request
+ Returns: HSOCKET_OK or error flag
+*/
+int httpc_mime_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,
+/**
+ Send boundary and part header and continue
+ with next part
+*/
+int httpc_mime_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);
-
+/**
+ Finish MIME request and get the response
+*/
+hresponse_t *httpc_mime_end(httpc_conn_t *conn);
-/*
- 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);
+/**
+ Send boundary and part header and continue
+ with next part
*/
+int
+httpc_mime_send_file (httpc_conn_t * conn,
+ const char *content_id,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *filename);
#endif
+
diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c
index fb67595..e31c20f 100644
--- a/nanohttp/nanohttp-common.c
+++ b/nanohttp/nanohttp-common.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-common.c,v 1.12 2004/09/19 07:05:03 snowdrop Exp $
+* $Id: nanohttp-common.c,v 1.13 2004/10/15 13:29:36 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -23,40 +23,15 @@
******************************************************************/
#include <nanohttp/nanohttp-common.h>
-#include <nanohttp/nanohttp-reqres.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-
-#ifdef WIN32
#include <string.h>
-static char *
-strtok_r(char *s, const char *delim, char **save_ptr)
-{
- char *token;
-
- if (s == NULL)
- s = *save_ptr;
- /* Scan leading delimiters. */
- s += strspn(s, delim);
- if (*s == '\0')
- return NULL;
-
- /* Find the end of the token. */
- token = s;
- s = strpbrk(token, delim);
- if (s == NULL)
- /* This token finishes the string. */
- *save_ptr = strchr(token, '\0');
- else {
- /* Terminate the token and make *SAVE_PTR point past it. */
- *s = '\0';
- *save_ptr = s + 1;
- }
- return token;
-}
+#ifdef MEM_DEBUG
+#include <utils/alloc.h>
#endif
static log_level_t loglevel = HLOG_DEBUG;
@@ -144,10 +119,9 @@ log_error(const char *FUNC, const char *format,...)
}
-/*
- * ----------------------------------------- FUNCTION: strcmpigcase
- * ------------------------------------------
- */
+/* -----------------------------------------
+ FUNCTION: strcmpigcase
+ ------------------------------------------*/
int
strcmpigcase(const char *s1, const char *s2)
{
@@ -364,23 +338,22 @@ hurl_dump(const hurl_t * url)
log_error1("url is NULL!");
return;
}
- log_verbose2("PROTOCOL : %s", SAVE_STR(url->protocol));
- log_verbose2(" HOST : %s", SAVE_STR(url->host));
+ log_verbose2("PROTOCOL : %d", url->protocol);
+ log_verbose2(" HOST : %s", url->host);
log_verbose2(" PORT : %d", url->port);
- log_verbose2(" CONTEXT : %s", SAVE_STR(url->context));
+ log_verbose2(" CONTEXT : %s", url->context);
}
-hurl_t *
-hurl_new(const char *urlstr)
+int hurl_parse(hurl_t* url, const char *urlstr)
{
int iprotocol;
int ihost;
int iport;
int len;
int size;
- hurl_t *url;
char tmp[8];
+ char protocol[1024];
iprotocol = 0;
len = strlen(urlstr);
@@ -392,17 +365,17 @@ hurl_new(const char *urlstr)
if (iprotocol == 0) {
log_error1("no protocol");
- return NULL;
+ return URL_ERROR_NO_PROTOCOL;
}
if (iprotocol + 3 >= len) {
log_error1("no host");
- return NULL;
+ return URL_ERROR_NO_HOST;
}
if (urlstr[iprotocol] != ':'
&& urlstr[iprotocol + 1] != '/'
&& urlstr[iprotocol + 2] != '/') {
log_error1("no protocol");
- return NULL;
+ return URL_ERROR_NO_PROTOCOL;
}
/* find host */
ihost = iprotocol + 3;
@@ -414,7 +387,7 @@ hurl_new(const char *urlstr)
if (ihost == iprotocol + 1) {
log_error1("no host");
- return NULL;
+ return URL_ERROR_NO_HOST;
}
/* find port */
iport = ihost;
@@ -425,14 +398,20 @@ hurl_new(const char *urlstr)
}
}
}
- url = (hurl_t *) malloc(sizeof(hurl_t));
-
- url->protocol = (char *) malloc(sizeof(char) * iprotocol + 1);
- strncpy(url->protocol, urlstr, iprotocol);
- url->protocol[iprotocol] = '\0';
- size = ihost - iprotocol - 3;
- url->host = (char *) malloc(sizeof(char) * size + 1);
+ /* find protocol */
+ strncpy(protocol, urlstr, iprotocol);
+ protocol[iprotocol] = '\0';
+ if (strcmpigcase(protocol, "http"))
+ url->protocol = PROTOCOL_HTTP;
+ else if (strcmpigcase(protocol, "https"))
+ url->protocol = PROTOCOL_HTTPS;
+ else if (strcmpigcase(protocol, "ftp"))
+ url->protocol = PROTOCOL_FTP;
+ else return URL_ERROR_UNKNOWN_PROTOCOL;
+
+ /* TODO (#1#): add max of size and URL_MAX_HOST_SIZE */
+ size = ihost - iprotocol - 3;
strncpy(url->host, &urlstr[iprotocol + 3], size);
url->host[size] = '\0';
@@ -441,402 +420,250 @@ hurl_new(const char *urlstr)
strncpy(tmp, &urlstr[ihost + 1], size);
url->port = atoi(tmp);
} else {
- url->port = 80;
+ switch (url->protocol) {
+ case PROTOCOL_HTTP:
+ url->port = URL_DEFAULT_PORT_HTTP;
+ break;
+ case PROTOCOL_HTTPS:
+ url->port = URL_DEFAULT_PORT_HTTPS;
+ break;
+ case PROTOCOL_FTP:
+ url->port = URL_DEFAULT_PORT_FTP;
+ break;
+ }
}
len = strlen(urlstr);
if (len > iport) {
- size = len - iport;
- url->context = (char *) malloc(sizeof(char) * size + 1);
+ /* TODO (#1#): find max of size and URL_MAX_CONTEXT_SIZE */
+ size = len - iport;
strncpy(url->context, &urlstr[iport], size);
url->context[size] = '\0';
} else {
- url->context = NULL;
+ url->context[0] = '\0';
}
hurl_dump(url);
- return url;
-}
-
-
-void
-hurl_free(hurl_t * url)
-{
- if (url == NULL)
- return;
-
- free(url->protocol);
- free(url->host);
- free(url->context);
-
- free(url);
+ return H_OK;
}
-/* request stuff */
+/* Content-type stuff */
-/*
- * ----------------------------------------------------- FUNCTION:
- * hrequest_new_from_buffer
- * -----------------------------------------------------
- */
-hrequest_t *
-hrequest_new_from_buffer(char *data)
+content_type_t *content_type_new(const char* content_type_str)
{
- hrequest_t *req;
- hpair_t *hpair = NULL, *qpair = NULL, *tmppair = NULL;
-
- char *tmp;
- char *tmp2;
- char *saveptr;
- char *saveptr2;
- char *saveptr3;
- char *result;
- char *key;
- char *value;
- char *opt_key;
- char *opt_value;
- int firstline = 1;
-
- req = (hrequest_t *) malloc(sizeof(hrequest_t));
-
- req->method = NULL;
- req->spec = NULL;
- req->path = NULL;
- req->query = NULL;
- req->header = NULL;
-
- tmp = data;
-
- for (;;) {
- result = (char *) strtok_r(tmp, "\n", &saveptr);
- tmp = saveptr;
-
- if (result == NULL)
- break;
-
- if (firstline) {
- firstline = 0;
- tmp2 = result;
-
- /* parse [GET|POST] [PATH] [SPEC] */
- key = (char *) strtok_r(tmp2, " ", &saveptr2);
-
- /* save method (get or post) */
- tmp2 = saveptr2;
- if (key != NULL) {
- req->method = (char *) malloc(strlen(key) + 1);
- strcpy(req->method, key);
- }
- /* below is key the path and tmp2 the spec */
- key = (char *) strtok_r(tmp2, " ", &saveptr2);
-
- /* save spec */
- tmp2 = saveptr2;
- if (tmp2 != NULL) {
- req->spec = (char *) malloc(strlen(tmp2) + 1);
- strcpy(req->spec, tmp2);
- }
- /*
- * parse and save path+query parse:
- * /path/of/target?key1=value1&key2=value2...
- */
-
- if (key != NULL) {
- tmp2 = key;
- key = (char *) strtok_r(tmp2, "?", &saveptr2);
- tmp2 = saveptr2;
-
- /* save path */
- req->path = (char *) malloc(strlen(key) + 1);
- strcpy(req->path, key);
-
- /* parse options */
- for (;;) {
- key = (char *) strtok_r(tmp2, "&", &saveptr2);
- tmp2 = saveptr2;
-
- if (key == NULL)
- break;
-
- opt_key = (char *) strtok_r(key, "=", &saveptr3);
- opt_value = saveptr3;
-
- if (opt_value == NULL)
- opt_value = "";
-
- /* create option pair */
- if (opt_key != NULL) {
- tmppair = (hpair_t *) malloc(sizeof(hpair_t));
-
- if (req->query == NULL) {
- req->query = qpair = tmppair;
- } else {
- qpair->next = tmppair;
- qpair = tmppair;
- }
-
- /* fill hpairnode_t struct */
- qpair->next = NULL;
- qpair->key = (char *) malloc(strlen(opt_key) + 1);
- qpair->value = (char *) malloc(strlen(opt_value) + 1);
-
- strcpy(qpair->key, opt_key);
- strcpy(qpair->value, opt_value);
-
- }
- }
- }
- } else {
+ hpair_t *pair = NULL, *last = NULL;
+ content_type_t * ct;
+ char ch, key[256], value[256];
+ int inQuote = 0, i=0, c=0, begin=0, len;
+ int mode = 0;
+ /* 0: searching ';'
+ 1: process key
+ 2: process value
+ */
+
+
+ /* Create object */
+ ct = (content_type_t*)malloc(sizeof(content_type_t));
+ ct->params = NULL;
+
+ len = strlen(content_type_str);
+ while (i <= len)
+ {
+ if (i != len)
+ ch = content_type_str[i++];
+ else
+ {
+ ch = ' '; i++;
+ }
- /* parse "key: value" */
- tmp2 = result;
- key = (char *) strtok_r(tmp2, ": ", &saveptr2);
- value = saveptr2;
+ switch (mode)
+ {
+ case 0:
+
+ if (ch == ';')
+ {
+ ct->type[c] = '\0';
+ c = 0;
+ mode = 1;
+ }
+ else if (ch != ' ' && ch != '\t' && ch != '\r')
+ ct->type[c++] = ch;
+ break;
+
+ case 1:
+
+ if (ch == '=')
+ {
+ key[c] = '\0';
+ c = 0;
+ mode = 2;
+ }
+ else if (ch != ' ' && ch != '\t' && ch != '\r')
+ key[c++] = ch;
+ break;
+
+ case 2:
+
+ if (ch != ' ') begin = 1;
+
+ if ((ch == ' ' || ch == ';') && !inQuote && begin)
+ {
+ value[c] = '\0';
+
+ pair = hpairnode_new(key, value, NULL);
+ if (ct->params == NULL)
+ ct->params = pair;
+ else
+ last->next = pair;
+ last = pair;
+
+ c = 0;
+ begin = 0;
+ mode = 1;
+ }
+ else if (ch == '"')
+ inQuote = !inQuote;
+ else if (begin && ch != '\r')
+ value[c++] = ch;
+
+ break;
- /* create pair */
- tmppair = (hpair_t *) malloc(sizeof(hpair_t));
+ }
+ }
- if (req->header == NULL) {
- req->header = hpair = tmppair;
- } else {
- hpair->next = tmppair;
- hpair = tmppair;
- }
+ return ct;
+}
- /* fill pairnode_t struct */
- hpair->next = NULL;
- hpair->key = (char *) malloc(strlen(key) + 1);
- hpair->value = (char *) malloc(strlen(value) + 1);
- strcpy(hpair->key, key);
- strcpy(hpair->value, value);
- }
- }
+void content_type_free(content_type_t *ct)
+{
+ if (!ct) return;
- return req;
+ hpairnode_free_deep(ct->params);
+ free(ct);
}
-void
-hrequest_free(hrequest_t * req)
+part_t *part_new(const char *id, const char* filename,
+ const char* content_type, const char* transfer_encoding, part_t *next)
{
- if (req == NULL)
- return;
-
- free(req->method);
- free(req->path);
- free(req->spec);
-
- hpairnode_free_deep(req->header);
- hpairnode_free_deep(req->query);
+ part_t *part = (part_t*)malloc(sizeof(part_t));
+ part->header = NULL;
+ part->next = next;
+ strcpy(part->id, id);
+ strcpy(part->filename, filename);
+ if (content_type)
+ strcpy(part->content_type, content_type);
+ else
+ part->content_type[0] = '\0';
+
+ part->header = hpairnode_new(HEADER_CONTENT_ID, id, part->header);
+ /* TODO (#1#): encoding is always binary. implement also others! */
+/* part->header = hpairnode_new(HEADER_CONTENT_TRANSFER_ENCODING, "binary", part->header);*/
+
+ strcpy(part->transfer_encoding, transfer_encoding?transfer_encoding:"binary");
+
+ if (content_type) {
+ part->header = hpairnode_new(HEADER_CONTENT_TYPE, content_type, part->header);
+ } else {
+ /* TODO (#1#): get content-type from mime type list */
+ }
+ return part;
}
-/* response stuff */
-
-/*
- * ------------------------------------------- FUNCTION: hresponse_new
- * ---------------------------------------------
- */
-hresponse_t *
-hresponse_new()
+attachments_t *attachments_new() /* should be used internally */
{
- hresponse_t *res;
-
- /* create response object */
- res = (hresponse_t *) malloc(sizeof(hresponse_t));
- res->spec[0] = '\0';
- res->errcode = -1;
- res->desc = NULL;
- res->header = NULL;
- res->body = NULL;
- res->bodysize = 0;
-
- return res;
+ attachments_t *attachments= (attachments_t*)malloc(sizeof(attachments_t));
+ attachments->parts = NULL;
+ attachments->last = NULL;
+ attachments->root_part = NULL;
+
+ return attachments;
}
-static
-hresponse_t *
-_hresponse_parse_header(const char *buffer)
+void attachments_add_part(attachments_t *attachments, part_t *part)
{
- 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;
+ /* paranoya check */
+ if (!attachments)
+ return;
+
+ if (attachments->last)
+ attachments->last->next = part;
+ else
+ attachments->parts = part;
+
+ attachments->last = part;
}
-hresponse_t *
-hresponse_new_from_socket(hsocket_t sock)
+/*
+ Free a mime message
+*/
+void attachments_free(attachments_t *message)
{
- int i=0, status;
- hresponse_t *res;
- char buffer[MAX_HEADER_SIZE+1];
+ part_t *tmp, *part;
- /* 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++;
- }
+ if (message == NULL)
+ return;
- /* Create response */
- res = _hresponse_parse_header(buffer);
- if (res == NULL)
- {
- log_error1("Header parse error");
- return NULL;
+ part = message->parts;
+ while (part) {
+ tmp = part->next;
+ mime_part_free(part);
+ part= tmp;
}
- /* Create input stream */
- res->in = http_input_stream_new(sock, res->header);
-
- return res;
+/* TODO (#1#): HERE IS A BUG!!!! */
+/* free(message);*/
}
-/*
- * ------------------------------------------- FUNCTION:
- * hresponse_new_from_buffer ---------------------------------------------
- */
-hresponse_t *
-hresponse_new_from_buffer(const char *buffer)
-{
- hresponse_t *res;
- char *s1, *s2, *str;
- /* create response object */
- res = hresponse_new();
+#ifdef WIN32
- /* *** parse spec *** */
- /* [HTTP/1.1 | 1.2] [CODE] [DESC] */
+/* strtok_r() */
+char *
+strtok_r(char *s, const char *delim, char **save_ptr)
+{
+ char *token;
- /* 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);
+ if (s == NULL)
+ s = *save_ptr;
- /* stage 2: http code */
- str = (char *) strtok_r(s1, " ", &s2);
- s1 = s2;
- if (str == NULL) {
- log_error1("Parse error");
+ /* Scan leading delimiters. */
+ s += strspn(s, delim);
+ if (*s == '\0')
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);
+ /* Find the end of the token. */
+ token = s;
+ s = strpbrk(token, delim);
+ if (s == NULL)
+ /* This token finishes the string. */
+ *save_ptr = strchr(token, '\0');
+ else {
+ /* Terminate the token and make *SAVE_PTR point past it. */
+ *s = '\0';
+ *save_ptr = s + 1;
}
-
- /* *** Save body *** */
- res->body = s1;
-
- /* return response object */
- return res;
+ return token;
}
-
-void
-hresponse_free(hresponse_t * res)
+/* localtime_r() */
+struct tm *
+localtime_r (const time_t * const timep, struct tm *p_tm)
{
- /* not implemented yet! */
+ 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-common.h b/nanohttp/nanohttp-common.h
index 0d765d8..d37c43a 100644
--- a/nanohttp/nanohttp-common.h
+++ b/nanohttp/nanohttp-common.h
@@ -1,8 +1,8 @@
/******************************************************************
- * $Id: nanohttp-common.h,v 1.11 2004/09/19 07:05:03 snowdrop Exp $
- *
+ * $Id: nanohttp-common.h,v 1.12 2004/10/15 13:29:36 snowdrop Exp $
+ *
* CSOAP Project: A http client/server library in C
- * Copyright (C) 2003 Ferhat Ayaz
+ * 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
@@ -19,11 +19,13 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Email: ayaz@jprogrammer.net
+ * Email: ferhatayaz@yahoo.com
******************************************************************/
#ifndef NANO_HTTP_COMMON_H
#define NANO_HTTP_COMMON_H
+#include <stdlib.h>
+#include <time.h>
#define HEADER_CONTENT_LENGTH "Content-Length"
#define HEADER_CONTENT_TYPE "Content-Type"
@@ -42,8 +44,75 @@
#define TRANSFER_ENCODING_CHUNKED "chunked"
+#define BOUNDARY_LENGTH 18
+
#define MAX_HEADER_SIZE 4256
#define MAX_SOCKET_BUFFER_SIZE 4256
+#define MAX_FILE_BUFFER_SIZE 4256
+
+#define URL_MAX_HOST_SIZE 120
+#define URL_MAX_CONTEXT_SIZE 1024
+
+#define HSOCKET_MAX_BUFSIZE 1024
+
+#define REQUEST_MAX_PATH_SIZE 1024
+#define RESPONSE_MAX_DESC_SIZE 1024
+
+/*
+ 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
+
+
+
+/* TODO (#1#): find proper ports */
+#define URL_DEFAULT_PORT_HTTP 80
+#define URL_DEFAULT_PORT_HTTPS 81
+#define URL_DEFAULT_PORT_FTP 120
+
+/* Success flag */
+#define H_OK 0
+
+/* File errors */
+#define FILE_ERROR_OPEN 8000
+#define FILE_ERROR_READ 8001
+
+/* Socket errors */
+#define HSOCKET_ERROR_CREATE 1001
+#define HSOCKET_ERROR_GET_HOSTNAME 1002
+#define HSOCKET_ERROR_CONNECT 1003
+#define HSOCKET_ERROR_SEND 1004
+#define HSOCKET_ERROR_RECEIVE 1005
+#define HSOCKET_ERROR_BIND 1006
+#define HSOCKET_ERROR_LISTEN 1007
+#define HSOCKET_ERROR_ACCEPT 1008
+#define HSOCKET_ERROR_NOT_INITIALIZED 1009
+#define HSOCKET_ERROR_IOCTL 1010
+
+/* URL errors */
+#define URL_ERROR_UNKNOWN_PROTOCOL 1101
+#define URL_ERROR_NO_PROTOCOL 1102
+#define URL_ERROR_NO_HOST 1103
+
+/* Stream errors */
+#define STREAM_ERROR_INVALID_TYPE 1201
+#define STREAM_ERROR_SOCKET_ERROR 1202
+#define STREAM_ERROR_NO_CHUNK_SIZE 1203
+#define STREAM_ERROR_WRONG_CHUNK_SIZE 1204
+
+
+/* MIME errors */
+#define MIME_ERROR_NO_BOUNDARY_PARAM 1301
+#define MIME_ERROR_NO_START_PARAM 1302
+#define MIME_ERROR_PARSE_ERROR 1303
+#define MIME_ERROR_NO_ROOT_PART 1304
+#define MIME_ERROR_NOT_MIME_MESSAGE 1305
+
+
/*
Set Sleep function platform depended
@@ -54,7 +123,36 @@ Set Sleep function platform depended
#define system_sleep(seconds) sleep(seconds);
#endif
+#ifdef WIN32
+#include <string.h>
+char* strtok_r(char *s, const char *delim, char **save_ptr);
+struct tm *localtime_r(const time_t *const timep, struct tm *p_tm);
+#endif
+
typedef unsigned char byte_t;
+typedef int hstatus_t;
+
+
+/**
+ Indicates the version of the
+ used HTTP protocol.
+*/
+typedef enum _http_version {
+ HTTP_1_0,
+ HTTP_1_1 /* default */
+}http_version_t;
+
+
+/**
+ Indicates the used method
+*/
+typedef enum _hreq_method
+{
+ HTTP_REQUEST_POST,
+ HTTP_REQUEST_GET
+}hreq_method_t ;
+
+
/*
string function to compare strings ignoring case
@@ -77,68 +175,255 @@ struct hpair
};
+/**
+ Creates a new pair with the given parameters. Both strings
+ key and value will be cloned while creating the pair.
+
+ @param key the key of the (key,value) pair
+ @param value the value of the (key,value) pair
+ @param next next pair node in the linked list
+
+ @returns A newly crated hpair_t object. Use hpair_free()
+ or hpair_free_deep() to free the pair.
+*/
hpair_t *hpairnode_new(const char* key, const char* value, hpair_t* next);
+
+
+/**
+ Creates a new pair from a given string. This function
+ will split 'str' with the found first delimiter 'delim'.
+ The 'value' field of the newly created pair will have
+ the value "", if no delimiter was found/
+ Whitespaces (' ') will be removed from the beginnig of
+ the parsed value.
+
+ @param str A string to parse
+ @param delim a delimiter to use while splitting into key,value
+ @param next next pair node in the linked list
+
+ @returns A newly crated hpair_t object. Use hpair_free()
+ or hpair_free_deep() to free the pair.
+*/
+hpair_t *hpairnode_parse(const char *str, const char *delim, hpair_t * next);
+
+
+/**
+ Frees a given pair.
+
+ @param pair the pair to free
+*/
void hpairnode_free(hpair_t *pair);
+
+
+/**
+ Makes a deep free operation. All pairnodes,
+ beginning with the given pari, in the
+ linked list will be destroyed.
+
+ @param pair the pair to start to free the linked list
+*/
+void hpairnode_free_deep(hpair_t * pair);
+
+
+/**
+ Returns the (key,value) pair, which key is the
+ given 'key'.
+
+ @param pair the first pair to start to search from.
+ @param key key to find the in the pair.
+ @returns if a value will be found, this function will
+ return the value (do not free this string) or NULL
+ if no pair was found with the key 'key'.
+*/
char *hpairnode_get(hpair_t *pair, const char* key);
+
+
+/**
+ Returns the (key,value) pair, which key is the
+ given 'key'. The case will be ignored while
+ comparing the key strings.
+
+ @param pair the first pair to start to search from.
+ @param key key to find the in the pair.
+ @returns if a value will be found, this function will
+ return the value (do not free this string) or NULL
+ if no pair was found with the key 'key'.
+*/
char *hpairnode_get_ignore_case(hpair_t *pair, const char* key);
+
+
+/**
+ This function will create a new pair and fills the
+ (key,value) fields of a given pair. Note that the 'next'
+ field will not be copied.
+
+ @param src the source pair object to copy.
+
+ @returns a newly created pair with the same (key,value)
+ pairs as in 'src'. This fields will be cloned. The'next'
+ field will be set to NULL.
+
+ @see hpairnode_copy_deep
+*/
hpair_t* hpairnode_copy(const hpair_t *src);
+
+
+/**
+ Clones the hole linked list.
+
+ @param src the source pair object to copy from
+
+ @returns the first object in the linked list.
+
+ @see hpairnode_copy
+*/
hpair_t* hpairnode_copy_deep(const hpair_t *src);
+
+/* Debug functions */
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;
+/**
+ The protocol types in enumeration
+ format. Used in some other nanohttp objects
+ like hurl_t.
-typedef enum hreq_method
+ @see hurl_t
+*/
+typedef enum _hprotocol
{
- HTTP_REQUEST_POST,
- HTTP_REQUEST_GET
-}hreq_method ;
+ PROTOCOL_HTTP,
+ PROTOCOL_HTTPS,
+ PROTOCOL_FTP
+}hprotocol_t;
-typedef struct hurl
+
+/**
+ The URL object. A representation
+ of an URL like:<P>
+
+ [protocol]://[host]:[port]/[context]
+
+*/
+typedef struct _hurl
{
- char *protocol;
- char *host;
+ /**
+ The transfer protocol.
+ Note that only PROTOCOL_HTTP is supported by nanohttp.
+ */
+ hprotocol_t protocol;
+
+ /**
+ The port number. If no port number was given in the URL,
+ one of the default port numbers will be selected.
+ URL_HTTP_DEFAULT_PORT
+ URL_HTTPS_DEFAULT_PORT
+ URL_FTP_DEFAULT_PORT
+ */
int port;
- char *context;
+
+ /** The hostname */
+ char host[URL_MAX_HOST_SIZE];
+
+ /** The string after the hostname. */
+ char context[URL_MAX_CONTEXT_SIZE];
}hurl_t;
-hurl_t* hurl_new(const char* urlstr);
-void hurl_free(hurl_t *url);
+/**
+ Parses the given 'urlstr' and fills the given hurl_t object.
+
+ @param obj the destination URL object to fill
+ @param url the URL in string format
+ @returns H_OK on success or one of the following otherwise
+ URL_ERROR_UNKNOWN_PROTOCOL
+ URL_ERROR_NO_PROTOCOL
+ URL_ERROR_NO_HOST
+*/
+hstatus_t hurl_parse(hurl_t *obj, const char* url);
/*
- DIME common stuff
+ Object representation of the content-type field
+ in a HTTP header:
+ <P>
+ Example:<P>
+
+ text/xml; key="value" key2="value2' ...
*/
-#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 _content_type
+{
+ char type[128];
+ hpair_t *params;
+}content_type_t;
+
+
+/**
+ Parses the given string and creates a new ccontent_type_t
+ object.
+
+ @param content_type_str the string representation of the
+ content-type field in a HTTP header.
+
+ @returns A newly created content_type_t object. Free this
+ object with content_type_free();
+
+ @see content_type_free
+*/
+content_type_t *content_type_new(const char* content_type_str);
+
+
+/**
+ Frees the given content_type_t object
+*/
+void content_type_free(content_type_t *ct);
+
+
+
+/*
+ part. Attachment
+*/
+typedef struct _part
+{
+ char id[250];
+ hpair_t *header;
+ char content_type[128];
+ char transfer_encoding[128];
+ char filename[250];
+ struct _part *next;
+}part_t;
+
+
+part_t *part_new(const char *id, const char* filename,
+ const char* content_type, const char* transfer_encoding, part_t *next);
+
-typedef struct _DIME_PACKAGE
+/*
+ Attachments
+*/
+typedef struct _attachments
{
- 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;
-
-
-/* logging stuff*/
+ part_t *parts;
+ part_t *last;
+ part_t *root_part;
+}attachments_t;
+
+attachments_t *attachments_new(); /* should be used internally */
+
+/*
+ Free a attachment. Create attachments with MIME
+ and DIME (DIME is not supported yet).
+
+ @see mime_get_attachments
+*/
+void attachments_free(attachments_t *message);
+
+
+
+
+/* logging stuff */
typedef enum log_level
{
HLOG_VERBOSE,
@@ -199,7 +484,6 @@ void log_error(const char* FUNC, const char *format, ...);
-
#endif
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index 9fecc1a..ad4f02c 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-server.c,v 1.25 2004/09/19 07:05:03 snowdrop Exp $
+* $Id: nanohttp-server.c,v 1.26 2004/10/15 13:29:36 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -42,6 +42,22 @@
#endif
+#ifdef MEM_DEBUG
+#include <utils/alloc.h>
+#endif
+
+typedef struct _conndata
+{
+ hsocket_t sock;
+#ifdef WIN32
+ HANDLE tid;
+#else
+ pthread_t tid;
+ pthread_attr_t attr;
+#endif
+ time_t atime;
+}conndata_t;
+
/*
* -----------------------------------------------------
* nano httpd
@@ -62,8 +78,9 @@ static int _httpd_terminate_signal = SIGTERM;
#endif
static conndata_t *_httpd_connection;
+
#ifdef WIN32
-#include <nanohttp/nanohttp-windows.h>
+static void WSAReaper(void *x);
#endif
/*
@@ -106,7 +123,7 @@ httpd_init (int argc, char *argv[])
/* init built-in services */
- /* httpd_register("/httpd/list", service_list);*/
+ /* httpd_register("/httpd/list", service_list); */
_httpd_connection = calloc (_httpd_max_connections, sizeof (conndata_t));
for (i = 0; i < _httpd_max_connections; i++)
@@ -171,6 +188,16 @@ httpd_services ()
return _httpd_services_head;
}
+/*
+ * -----------------------------------------------------
+ * FUNCTION: httpd_services
+ * -----------------------------------------------------
+ */
+static
+void hservice_free(hservice_t *service)
+{
+ free(service);
+}
/*
* -----------------------------------------------------
@@ -213,8 +240,7 @@ httpd_response_set_content_type (httpd_conn_t * res, const char *content_type)
* -----------------------------------------------------
*/
int
-httpd_send_header (httpd_conn_t * res,
- int code, const char *text, hpair_t * pair)
+httpd_send_header (httpd_conn_t * res, int code, const char *text)
{
struct tm stm;
time_t nw;
@@ -247,7 +273,7 @@ httpd_send_header (httpd_conn_t * res,
strcat (header, "Connection: close\r\n");
/* add pairs */
- cur = pair;
+ cur = res->header;
while (cur != NULL)
{
sprintf (buffer, "%s: %s\r\n", cur->key, cur->value);
@@ -261,6 +287,7 @@ httpd_send_header (httpd_conn_t * res,
/* send header */
status = hsocket_nsend (res->sock, header, strlen (header));
+ res->out = http_output_stream_new (res->sock, res->header);
return status;
}
@@ -273,7 +300,7 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg)
char buffer[4064];
sprintf (buffer, template1, errmsg);
- httpd_send_header (conn, 500, "INTERNAL", NULL);
+ httpd_send_header (conn, 500, "INTERNAL");
return send (conn->sock, buffer, strlen (buffer), 0);
}
@@ -288,9 +315,9 @@ httpd_request_print (hrequest_t * req)
hpair_t *pair;
log_verbose1 ("++++++ Request +++++++++");
- log_verbose2 (" Method : '%s'", req->method);
+ log_verbose2 (" Method : '%s'", (req->method == HTTP_REQUEST_POST)?"POST":"GET");
log_verbose2 (" Path : '%s'", req->path);
- log_verbose2 (" Spec : '%s'", req->spec);
+ log_verbose2 (" Spec : '%s'", (req->version==HTTP_1_0)?"HTTP/1.0":"HTTP/1.1");
log_verbose1 (" Parsed query string :");
pair = req->query;
@@ -303,6 +330,30 @@ httpd_request_print (hrequest_t * req)
}
+
+httpd_conn_t *httpd_new(hsocket_t sock)
+{
+ httpd_conn_t *conn = (httpd_conn_t *) malloc (sizeof (httpd_conn_t));
+ conn->sock = sock;
+ conn->out = NULL;
+ conn->content_type[0] = '\0';
+ conn->header = NULL;
+
+ return conn;
+}
+
+
+void httpd_free(httpd_conn_t *conn)
+{
+ if (conn->out != NULL)
+ http_output_stream_free(conn->out);
+
+ if (conn->header != NULL)
+ hpairnode_free_deep(conn->header);
+
+ free(conn);
+}
+
/*
* -----------------------------------------------------
* FUNCTION: httpd_session_main
@@ -335,64 +386,52 @@ httpd_session_main (void *data)
log_verbose1 ("starting httpd_session_main()");
conn->atime = time ((time_t) 0);
- while (len < 4064)
- {
- /* printf("receiving ...\n"); */
- total = recv (conn->sock, ch, 1, 0);
- if (total == 0)
- break;
- header[len] = ch[0];
- len++;
- if (len > 3)
- {
- if (!strncmp (&header[len - 4], "\r\n\r\n", 4))
- {
- header[len] = '\0';
- break;
- }
- }
- }
-
- /* log_verbose2("=== HEADER ===\n%s\n============\n", header); */
/* call the service */
- req = hrequest_new_from_buffer (header);
- httpd_request_print (req);
+/* req = hrequest_new_from_buffer (header);*/
+ rconn = httpd_new(conn->sock);
+ req = hrequest_new_from_socket (conn->sock);
+ if (req == NULL)
+ {
+ httpd_send_internal_error (rconn, "Request parse error!");
+ }
+ else
+ {
+ httpd_request_print (req);
- rconn = (httpd_conn_t *) malloc (sizeof (httpd_conn_t));
- rconn->sock = conn->sock;
- rconn->content_type[0] = '\0';
- service = httpd_find_service (req->path);
- if (service != NULL)
- {
- log_verbose2 ("service '%s' found", req->path);
- if (service->func != NULL)
+ service = httpd_find_service (req->path);
+ if (service != NULL)
{
- service->func (rconn, req);
+ log_verbose2 ("service '%s' found", req->path);
+ if (service->func != NULL)
+ {
+ service->func (rconn, req);
+ }
+ else
+ {
+ sprintf (buffer,
+ "service '%s' not registered properly (func == NULL)",
+ req->path);
+ log_verbose1 (buffer);
+ httpd_send_internal_error (rconn, buffer);
+ }
}
else
{
- sprintf (buffer,
- "service '%s' not registered properly (func == NULL)",
- req->path);
+ sprintf (buffer, "service '%s' not found", req->path);
log_verbose1 (buffer);
httpd_send_internal_error (rconn, buffer);
}
- }
- else
- {
- sprintf (buffer, "service '%s' not found", req->path);
- log_verbose1 (buffer);
- httpd_send_internal_error (rconn, buffer);
+
+ /* httpd_response_free(res); */
+ /*hrequest_free (req);*/
}
- close (conn->sock);
+ hsocket_close(conn->sock);
conn->sock = 0;
-
- /* httpd_response_free(res); */
- hrequest_free (req);
-
+ hrequest_free(req);
+ httpd_free(rconn);
#ifdef WIN32
CloseHandle ((HANDLE) conn->tid);
_endthread ();
@@ -403,6 +442,44 @@ httpd_session_main (void *data)
#endif
}
+int
+httpd_set_header (httpd_conn_t * conn, const char *key, const char *value)
+{
+ hpair_t *p;
+
+ if (conn == NULL)
+ {
+ log_warn1 ("Connection object is NULL");
+ return 0;
+ }
+ p = conn->header;
+ while (p != NULL)
+ {
+ if (p->key != NULL)
+ {
+ if (!strcmp (p->key, key))
+ {
+ free (p->value);
+ p->value = (char *) malloc (strlen (value) + 1);
+ strcpy (p->value, value);
+ return 1;
+ }
+ }
+ p = p->next;
+ }
+
+ conn->header = hpairnode_new (key, value, conn->header);
+ return 0;
+}
+
+
+void httpd_set_headers(httpd_conn_t *conn, hpair_t *header)
+{
+ while (header) {
+ httpd_set_header(conn, header->key, header->value);
+ header = header->next;
+ }
+}
/*
* -----------------------------------------------------
@@ -410,19 +487,21 @@ httpd_session_main (void *data)
* -----------------------------------------------------
*/
#ifdef WIN32
-BOOL WINAPI httpd_term(DWORD sig)
+BOOL WINAPI
+httpd_term (DWORD sig)
{
- log_debug2("Got signal %d", sig);
+ log_debug2 ("Got signal %d", sig);
if (sig == _httpd_terminate_signal)
- _httpd_run = 0;
+ _httpd_run = 0;
return TRUE;
}
-
+
#else
void
-httpd_term (int sig) {
- log_debug2("Got signal %d", sig);
+httpd_term (int sig)
+{
+ log_debug2 ("Got signal %d", sig);
if (sig == _httpd_terminate_signal)
_httpd_run = 0;
}
@@ -435,20 +514,21 @@ httpd_term (int sig) {
* FUNCTION: _httpd_register_signal_handler
* -----------------------------------------------------
*/
-static
-void _httpd_register_signal_handler()
+static void
+_httpd_register_signal_handler ()
{
log_verbose2 ("registering termination signal handler (SIGNAL:%d)",
_httpd_terminate_signal);
#ifdef WIN32
- if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)httpd_term, TRUE) == FALSE){
- log_error1 ("Unable to install console event handler!");
+ if (SetConsoleCtrlHandler ((PHANDLER_ROUTINE) httpd_term, TRUE) == FALSE)
+ {
+ log_error1 ("Unable to install console event handler!");
}
#else
signal (_httpd_terminate_signal, httpd_term);
#endif
-}
+}
@@ -456,56 +536,55 @@ void _httpd_register_signal_handler()
/*--------------------------------------------------
FUNCTION: _httpd_wait_for_empty_conn
----------------------------------------------------*/
-static
-conndata_t *_httpd_wait_for_empty_conn()
+static conndata_t *
+_httpd_wait_for_empty_conn ()
{
- int i;
+ int i;
for (i = 0;; i++)
{
if (!_httpd_run)
- return NULL;
-
- if (i >= _httpd_max_connections)
+ return NULL;
+
+ if (i >= _httpd_max_connections)
{
- system_sleep(1);
+ system_sleep (1);
i = 0;
}
else if (_httpd_connection[i].sock == 0)
{
break;
- }
- }
-
- return &_httpd_connection[i];
-}
+ }
+ }
+
+ return &_httpd_connection[i];
+}
/*
* -----------------------------------------------------
* FUNCTION: _httpd_start_thread
* -----------------------------------------------------
*/
-static
-void _httpd_start_thread(conndata_t* conn)
+static void
+_httpd_start_thread (conndata_t * conn)
{
int err;
-
+
#ifdef WIN32
- conn->tid =
- (HANDLE) _beginthreadex (NULL, 65535, httpd_session_main, conn, 0, &err);
+ conn->tid =
+ (HANDLE) _beginthreadex (NULL, 65535, httpd_session_main, conn, 0, &err);
#else
- pthread_attr_init (&(conn-> attr));
- #ifdef PTHREAD_CREATE_DETACHED
- pthread_attr_setdetachstate (&(conn->attr),
- PTHREAD_CREATE_DETACHED);
- #endif
- err = pthread_create (&(conn->tid), &(conn->attr),httpd_session_main,
- conn);
+ pthread_attr_init (&(conn->attr));
+#ifdef PTHREAD_CREATE_DETACHED
+ pthread_attr_setdetachstate (&(conn->attr), PTHREAD_CREATE_DETACHED);
+#endif
+ err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main,
+ conn);
if (err)
- {
- log_error2 ("Error creating thread: ('%d')", err);
- }
+ {
+ log_error2 ("Error creating thread: ('%d')", err);
+ }
#endif
-}
+}
@@ -529,8 +608,8 @@ httpd_run ()
timeout.tv_usec = 0;
/* listen to port */
- err = hsocket_listen (_httpd_socket, 15);
- if (err != HSOCKET_OK)
+ err = hsocket_listen (_httpd_socket);
+ if (err != H_OK)
{
log_error2 ("httpd_run(): '%d'", err);
return err;
@@ -538,69 +617,120 @@ httpd_run ()
log_verbose2 ("listening to port '%d'", _httpd_port);
/* register signal handler */
- _httpd_register_signal_handler();
-
+ _httpd_register_signal_handler ();
+
/* make the socket non blocking */
- err = hsocket_makenonblock (_httpd_socket);
- if (err != HSOCKET_OK)
+ err = hsocket_block (_httpd_socket, 0);
+ if (err != H_OK)
{
log_error2 ("httpd_run(): '%d'", err);
return err;
}
-
+
while (_httpd_run)
{
/* Get an empty connection struct */
- conn = _httpd_wait_for_empty_conn();
- if (!_httpd_run) break;
-
+ conn = _httpd_wait_for_empty_conn ();
+ if (!_httpd_run)
+ break;
+
/* 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))
+ 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;
- }
+ break;
+ }
}
-
- /* check signal status*/
+
+ /* check signal status */
if (!_httpd_run)
- break;
-
+ break;
+
/* Accept a socket */
- err = hsocket_accept(_httpd_socket, &(conn->sock));
- if (err != HSOCKET_OK)
+ err = hsocket_accept (_httpd_socket, &(conn->sock));
+ if (err != H_OK)
{
- log_error2("Can not accept socket: %d", err);
- return -1; /* this is hard core! */
- }
-
+ log_error2 ("Can not accept socket: %d", err);
+ return -1; /* this is hard core! */
+ }
+
/* Now start a thread */
- _httpd_start_thread(conn);
+ _httpd_start_thread (conn);
}
free (_httpd_connection);
return 0;
}
+void httpd_destroy()
+{
+ hservice_t *tmp, *cur = _httpd_services_head;
+
+ while (cur != NULL)
+ {
+ tmp = cur->next;
+ hservice_free(cur);
+ cur = tmp;
+ }
+
+}
+
+#ifdef WIN32
+
+static
+void WSAReaper(void *x)
+{
+ short int connections;
+ short int i;
+ char junk[10];
+ int rc;
+ time_t ctime;
+
+ for (;;) {
+ connections=0;
+ ctime=time((time_t)0);
+ for (i=0;i<_httpd_max_connections;i++) {
+ if (_httpd_connection[i].tid==0) continue;
+ GetExitCodeThread((HANDLE)_httpd_connection[i].tid,(PDWORD) &rc);
+ if (rc!=STILL_ACTIVE) continue;
+ connections++;
+ if ((ctime-_httpd_connection[i].atime<_httpd_max_idle)||
+ (_httpd_connection[i].atime==0)) continue;
+ log_verbose3("Reaping socket %u from (runtime ~= %d seconds)",
+ _httpd_connection[i].sock, ctime-_httpd_connection[i].atime);
+ shutdown(_httpd_connection[i].sock, 2);
+ while (recv(_httpd_connection[i].sock, junk, sizeof(junk), 0)>0) { };
+ closesocket(_httpd_connection[i].sock);
+ _httpd_connection[i].sock = 0;
+ TerminateThread(_httpd_connection[i].tid, (DWORD)&rc);
+ CloseHandle(_httpd_connection[i].tid);
+ memset((char *)&_httpd_connection[i], 0, sizeof(_httpd_connection[i]));
+ }
+ Sleep(100);
+ }
+ return;
+}
+
+#endif
unsigned char *
httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received,
@@ -611,7 +741,7 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received,
long total = 0;
unsigned char *postdata = NULL;
- if (!strcmp (req->method, "POST"))
+ if (req->method == HTTP_REQUEST_POST)
{
content_length_str =
@@ -643,8 +773,7 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received,
log_error1 ("Not enough memory");
return NULL;
}
- if (hsocket_read (conn->sock, postdata,
- (int)content_length, 1)>0)
+ if (http_input_stream_read(req->in, postdata, (int) content_length) > 0)
{
*received = content_length;
postdata[content_length] = '\0';
@@ -653,3 +782,185 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received,
free (postdata);
return NULL;
}
+
+
+
+
+/*
+ MIME support httpd_mime_* function set
+*/
+
+static void
+_httpd_mime_get_boundary (httpd_conn_t * conn, char *dest)
+{
+ sprintf (dest, "---=.Part_NH_%p", conn);
+ log_verbose2 ("boundary= \"%s\"", dest);
+}
+
+
+/**
+ Begin MIME multipart/related POST
+ Returns: H_OK or error flag
+*/
+int
+httpd_mime_send_header (httpd_conn_t * conn,
+ const char *related_start,
+ const char *related_start_info,
+ const char *related_type, int code, const char *text)
+{
+ int status;
+ char buffer[300];
+ char temp[250];
+ char boundary[250];
+ hpair_t *header;
+
+ /*
+ 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, 250, " start=\"%s\";", related_start);
+ strcat (buffer, temp);
+ }
+
+ if (related_start_info)
+ {
+ snprintf (temp, 250, " start-info=\"%s\";", related_start_info);
+ strcat (buffer, temp);
+ }
+
+ _httpd_mime_get_boundary (conn, boundary);
+ snprintf (temp, 250, " boundary=\"%s\"", boundary);
+ strcat (buffer, temp);
+
+ httpd_set_header (conn, HEADER_CONTENT_TYPE, buffer);
+
+ return httpd_send_header (conn, code, text);
+}
+
+
+/**
+ Send boundary and part header and continue
+ with next part
+*/
+int
+httpd_mime_next (httpd_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 */
+ _httpd_mime_get_boundary (conn, boundary);
+ sprintf (buffer, "\r\n--%s\r\n", boundary);
+
+ /* Send boundary */
+ status = http_output_stream_write (conn->out,
+ (const byte_t *) buffer,
+ strlen (buffer));
+
+ if (status != H_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 ? content_type : "text/plain",
+ HEADER_CONTENT_TRANSFER_ENCODING,
+ transfer_encoding ? transfer_encoding : "binary",
+ HEADER_CONTENT_ID,
+ content_id ? content_id : "<content-id-not-set>");
+
+ status = http_output_stream_write (conn->out,
+ (const byte_t *) buffer,
+ strlen (buffer));
+
+ return status;
+}
+
+/**
+ Send boundary and part header and continue
+ with next part
+*/
+int
+httpd_mime_send_file (httpd_conn_t * conn,
+ const char *content_id,
+ const char *content_type,
+ const char *transfer_encoding, const char *filename)
+{
+ int status;
+ FILE *fd = fopen (filename, "rb");
+ byte_t buffer[MAX_FILE_BUFFER_SIZE];
+ size_t size;
+
+ if (fd == NULL)
+ return FILE_ERROR_OPEN;
+
+ status =
+ httpd_mime_next (conn, content_id, content_type, transfer_encoding);
+ if (status != H_OK)
+ {
+ fclose (fd);
+ return status;
+ }
+
+ while (!feof (fd))
+ {
+ size = fread (buffer, 1, MAX_FILE_BUFFER_SIZE, fd);
+ if (size == -1)
+ {
+ fclose (fd);
+ return FILE_ERROR_READ;
+ }
+
+ status = http_output_stream_write (conn->out, buffer, size);
+ if (status != H_OK) {
+ fclose (fd);
+ return status;
+ }
+ }
+
+ fclose (fd);
+ return H_OK;
+}
+
+/**
+ Finish MIME request
+ Returns: H_OK or error flag
+*/
+int
+httpd_mime_end (httpd_conn_t * conn)
+{
+ int status;
+ char buffer[512];
+ char boundary[75];
+
+ /* Get the boundary string */
+ _httpd_mime_get_boundary (conn, boundary);
+ sprintf (buffer, "\r\n--%s--\r\n\r\n", boundary);
+
+ /* Send boundary */
+ status = http_output_stream_write (conn->out,
+ (const byte_t *) buffer,
+ strlen (buffer));
+
+ if (status != H_OK)
+ return status;
+
+ /* Flush put stream */
+ status = http_output_stream_flush (conn->out);
+
+ return status;
+}
diff --git a/nanohttp/nanohttp-server.h b/nanohttp/nanohttp-server.h
index 3170c3d..7e5263e 100644
--- a/nanohttp/nanohttp-server.h
+++ b/nanohttp/nanohttp-server.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-server.h,v 1.5 2004/09/19 07:05:03 snowdrop Exp $
+ * $Id: nanohttp-server.h,v 1.6 2004/10/15 13:29:37 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -19,7 +19,7 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Email: ayaz@jprogrammer.net
+ * Email: ferhatayaz@yahoo.com
******************************************************************/
#ifndef NANO_HTTP_SERVER_H
#define NANO_HTTP_SERVER_H
@@ -27,16 +27,20 @@
#include <nanohttp/nanohttp-common.h>
#include <nanohttp/nanohttp-socket.h>
-#include <nanohttp/nanohttp-reqres.h>
+#include <nanohttp/nanohttp-request.h>
+#include <nanohttp/nanohttp-stream.h>
#define NHTTPD_ARG_PORT "-NHTTPport"
#define NHTTPD_ARG_TERMSIG "-NHTTPtsig"
#define NHTTPD_ARG_MAXCONN "-NHTTPmaxconn"
+
typedef struct httpd_conn
{
hsocket_t sock;
char content_type[25];
+ http_output_stream_t *out;
+ hpair_t *header;
}httpd_conn_t;
@@ -69,12 +73,55 @@ void httpd_destroy();
hservice_t *httpd_services();
int httpd_send_header(httpd_conn_t *res,
- int code, const char* text,
- hpair_t *pair);
+ int code, const char* text);
+int httpd_set_header(httpd_conn_t *conn, const char *key, const char* value);
+void httpd_set_headers(httpd_conn_t *conn, hpair_t *header);
unsigned char *httpd_get_postdata(httpd_conn_t *conn,
hrequest_t *req, long *received, long max);
+/* --------------------------------------------------------------
+ MIME RELATED FUNCTIONS
+ ---------------------------------------------------------------*/
+/*
+ MIME support httpd_mime_* function set
+*/
+
+/**
+ Begin MIME multipart/related POST
+ Returns: HSOCKET_OK or error flag
+*/
+int httpd_mime_send_header(httpd_conn_t *conn,
+ const char* related_start,
+ const char* related_start_info,
+ const char* related_type, int code, const char* text);
+
+/**
+ Send boundary and part header and continue
+ with next part
+*/
+int httpd_mime_next(httpd_conn_t *conn,
+ const char* content_id,
+ const char* content_type,
+ const char* transfer_encoding);
+
+/**
+ Send boundary and part header and continue
+ with next part
+*/
+int httpd_mime_send_file(httpd_conn_t *conn,
+ const char* content_id,
+ const char* content_type,
+ const char* transfer_encoding,
+ const char* filename);
+
+/**
+ Finish MIME request
+ Returns: HSOCKET_OK or error flag
+*/
+int httpd_mime_end(httpd_conn_t *conn);
+
+
#endif
diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c
index 718b96f..82d7280 100644
--- a/nanohttp/nanohttp-socket.c
+++ b/nanohttp/nanohttp-socket.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-socket.c,v 1.22 2004/09/19 07:05:03 snowdrop Exp $
+* $Id: nanohttp-socket.c,v 1.23 2004/10/15 13:29:37 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -25,16 +25,16 @@
#include <nanohttp/nanohttp-common.h>
#ifdef WIN32
-#include "wsockcompat.h"
-#include <winsock2.h>
-#include <process.h>
-
-#ifndef __MINGW32__
-typedef int ssize_t;
-#endif
-
+ #include "wsockcompat.h"
+ #include <winsock2.h>
+ #include <process.h>
+
+ #ifndef __MINGW32__
+ typedef int ssize_t;
+ #endif
+
#else
-#include <fcntl.h>
+ #include <fcntl.h>
#endif
#ifdef HAVE_CONFIG_H
@@ -64,12 +64,16 @@ typedef int ssize_t;
#include <stdio.h>
#include <errno.h>
+#ifdef MEM_DEBUG
+#include <utils/alloc.h>
+#endif
+
/*--------------------------------------------------
FUNCTION: hsocket_module_init
NOTE: This will be called from httpd_init()
for server and from httpc_init() for client
----------------------------------------------------*/
-int
+hstatus_t
hsocket_module_init ()
{
#ifdef WIN32
@@ -79,7 +83,7 @@ hsocket_module_init ()
#else /* */
/* nothing to init for unix sockets */
#endif /* */
- return 0;
+ return H_OK;
}
/*--------------------------------------------------
@@ -99,12 +103,12 @@ hsocket_module_destroy ()
/*--------------------------------------------------
FUNCTION: hsocket_init
----------------------------------------------------*/
-int
+hstatus_t
hsocket_init (hsocket_t * sock)
{
/* just set the descriptor to -1 */
*sock = -1;
- return 0;
+ return H_OK;
}
/*--------------------------------------------------
@@ -119,7 +123,7 @@ hsocket_free (hsocket_t sock)
/*--------------------------------------------------
FUNCTION: hsocket_open
----------------------------------------------------*/
-int
+hstatus_t
hsocket_open (hsocket_t * dsock, const char *hostname, int port)
{
hsocket_t sock;
@@ -129,12 +133,12 @@ hsocket_open (hsocket_t * dsock, const char *hostname, int port)
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock <= 0)
- return HSOCKET_CAN_NOT_CREATE;
+ return HSOCKET_ERROR_CREATE;
/* Get host data */
host = gethostbyname (hostname);
if (host == NULL)
- return HSOCKET_CAN_NOT_GET_HOSTNAME;
+ return HSOCKET_ERROR_GET_HOSTNAME;
ip = inet_ntoa (*(struct in_addr *) *host->h_addr_list);
address.sin_addr.s_addr = inet_addr (ip);
@@ -145,16 +149,16 @@ hsocket_open (hsocket_t * dsock, const char *hostname, int port)
/* connect to the server */
if (connect (sock, (struct sockaddr *) &address, sizeof (address)) != 0)
- return HSOCKET_CAN_NOT_CONNECT;
+ return HSOCKET_ERROR_CONNECT;
*dsock = sock;
- return HSOCKET_OK;
+ return H_OK;
}
/*--------------------------------------------------
FUNCTION: hsocket_bind
----------------------------------------------------*/
-int
+hstatus_t
hsocket_bind (hsocket_t * dsock, int port)
{
hsocket_t sock;
@@ -165,7 +169,7 @@ hsocket_bind (hsocket_t * dsock, int port)
if (sock == -1)
{
log_error2 ("Can not create socket: '%s'", strerror (errno));
- return HSOCKET_CAN_NOT_CREATE;
+ return HSOCKET_ERROR_CREATE;
}
/* bind socket */
addr.sin_family = AF_INET;
@@ -177,63 +181,69 @@ hsocket_bind (hsocket_t * dsock, int port)
if (bind (sock, (struct sockaddr *) &addr, sizeof (struct sockaddr)) == -1)
{
log_error2 ("Can not bind: '%s'", strerror (errno));
- return HSOCKET_CAN_NOT_BIND;
+ return HSOCKET_ERROR_BIND;
}
*dsock = sock;
- return HSOCKET_OK;
+ return H_OK;
}
/*----------------------------------------------------------
FUNCTION: hsocket_accept
----------------------------------------------------------*/
-int
+hstatus_t
hsocket_accept (hsocket_t sock, hsocket_t * dest)
{
socklen_t asize;
hsocket_t sockfd;
struct sockaddr_in addr;
+ if (sock <= 0)
+ return HSOCKET_ERROR_NOT_INITIALIZED;
+
asize = sizeof (struct sockaddr_in);
#ifdef WIN32
while (1)
{
sockfd = accept (sock, (struct sockaddr *) &addr, &asize);
- if (sockfd == INVALID_SOCKET)
- {
+ if (sockfd == INVALID_SOCKET) {
if (WSAGetLastError () != WSAEWOULDBLOCK)
- return HSOCKET_CAN_NOT_ACCEPT;
- }
- else
- {
+ return HSOCKET_ERROR_ACCEPT;
+ } else {
break;
}
}
-#else
+#else
+/* TODO (#1#): why not a loop like in win32? */
sockfd = accept (sock, (struct sockaddr *) &addr, &asize);
- if (sockfd == -1)
- {
- return HSOCKET_CAN_NOT_ACCEPT;
+ if (sockfd == -1) {
+ return HSOCKET_ERROR_ACCEPT;
}
-#endif
+#endif
+/* TODO (#1#): Write to access.log file */
+
log_verbose3 ("accept new socket (%d) from '%s'", sockfd,
SAVE_STR (((char *) inet_ntoa (addr.sin_addr))));
*dest = sockfd;
- return HSOCKET_OK;
+ return H_OK;
}
/*--------------------------------------------------
FUNCTION: hsocket_listen
----------------------------------------------------*/
-int
-hsocket_listen (hsocket_t sock, int n)
+hstatus_t
+hsocket_listen (hsocket_t sock)
{
- if (listen (sock, n) == -1)
+ if (sock <= 0)
+ return HSOCKET_ERROR_NOT_INITIALIZED;
+
+ if (listen (sock, 15) == -1)
{
log_error2 ("Can not listen: '%s'", strerror (errno));
- return HSOCKET_CAN_NOT_LISTEN;
+ return HSOCKET_ERROR_LISTEN;
}
- return HSOCKET_OK;
+
+ return H_OK;
}
/*--------------------------------------------------
@@ -243,7 +253,18 @@ void
hsocket_close (hsocket_t sock)
{
#ifdef WIN32
+ /*shutdown(sock,SD_RECEIVE);*/
+
+/* struct linger _linger;
+
+ hsocket_block(sock,1);
+ _linger.l_onoff =1;
+ _linger.l_linger = 30000;
+ setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&_linger, sizeof(struct linger));
+
+
closesocket (sock);
+*/
#else
close (sock);
#endif
@@ -252,22 +273,39 @@ hsocket_close (hsocket_t sock)
/*--------------------------------------------------
FUNCTION: hsocket_send
----------------------------------------------------*/
-int
-hsocket_nsend (hsocket_t sock, const unsigned char *bytes, int n)
+hstatus_t
+hsocket_nsend (hsocket_t sock, const byte_t *bytes, int n)
{
int size;
- size = send ((int) sock, bytes, n, 0);
- if (size == -1)
- return HSOCKET_CAN_NOT_SEND;
+ if (sock <= 0)
+ return HSOCKET_ERROR_NOT_INITIALIZED;
- return HSOCKET_OK;
+ /* TODO (#1#): check return value and send again until n bytes sent */
+
+ while (1)
+ {
+ size = send((int) sock, bytes, n, 0);
+#ifdef WIN32
+ if (size == INVALID_SOCKET)
+ if (WSAGetLastError () == WSAEWOULDBLOCK)
+ continue;
+ else
+ return HSOCKET_ERROR_SEND;
+#else
+ if (size == -1)
+ return HSOCKET_ERROR_SEND;
+#endif
+ n -= size;
+ if (n<=0) break;
+ }
+ return H_OK;
}
/*--------------------------------------------------
FUNCTION: hsocket_send
----------------------------------------------------*/
-int
+hstatus_t
hsocket_send (hsocket_t sock, const char *str)
{
return hsocket_nsend (sock, str, strlen (str));
@@ -277,214 +315,87 @@ hsocket_send (hsocket_t sock, const char *str)
return: -1 is error. read bytes otherwise
*/
int
-hsocket_read (hsocket_t sock, unsigned char *buffer, int total, int force)
+hsocket_read (hsocket_t sock, byte_t *buffer, int total, int force)
{
int status;
int totalRead;
-
+ int wsa_error;
totalRead = 0;
do
{
- status = recv (sock, &buffer[totalRead], total - totalRead, 0);
+ status = recv(sock, &buffer[totalRead], total - totalRead, 0);
#ifdef WIN32
- if (status == INVALID_SOCKET)
- if (WSAGetLastError () == WSAEWOULDBLOCK)
- continue;
- else
- return -1;
+ if (status == INVALID_SOCKET)
+ {
+ wsa_error = WSAGetLastError();
+ switch (wsa_error)
+ {
+ case WSAEWOULDBLOCK:
+ case WSAEALREADY:
+ case WSAEINPROGRESS:
+ continue;
+ default:
+ log_error2("WSAGetLastError()=%d", wsa_error);
+ return -1;
+ }
+ }
+
#else
+/*
+ switch (errno) {
+ case EWOULDBLOCK:
+ case EALREADY:
+ case EINPROGRESS:
+ return true;
+ }
+*/
if (status == -1)
return -1;
#endif
- if (!force)
+ if (!force) {
+ _log_str("socket.recv", buffer, status);
return status;
+ }
totalRead += status;
- if (totalRead == total)
+ if (totalRead == total) {
+ _log_str("socket.recv", buffer, totalRead);
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)
+hstatus_t
+hsocket_block(hsocket_t sock, int block)
{
- 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;
- }
+#ifdef WIN32
+ unsigned long iMode;
+#endif
- return HSOCKET_OK;
- }
-}
+ if (sock <= 0)
+ return HSOCKET_ERROR_NOT_INITIALIZED;
-int
-hsocket_makenonblock (hsocket_t sock)
-{
#ifdef WIN32
- unsigned long iMode;
- iMode = HSOCKET_NONBLOCKMODE;
+/*#define HSOCKET_BLOCKMODE 0
+#define HSOCKET_NONBLOCKMODE 1
+*/
+ iMode = (block==0)?1:0; /* Non block mode */
if (ioctlsocket (sock, FIONBIO, (u_long FAR *) & iMode) == INVALID_SOCKET)
{
log_error1 ("ioctlsocket error");
- return -1;
+ return HSOCKET_ERROR_IOCTL;
}
#else /* fcntl(sock, F_SETFL, O_NONBLOCK); */
+/* TODO (#1#): check for *nix the non blocking sockets */
+
#endif
- return HSOCKET_OK;
+ return H_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 48d2a0b..8deb273 100644
--- a/nanohttp/nanohttp-socket.h
+++ b/nanohttp/nanohttp-socket.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-socket.h,v 1.12 2004/09/19 07:05:03 snowdrop Exp $
+ * $Id: nanohttp-socket.h,v 1.13 2004/10/15 13:29:37 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -24,182 +24,184 @@
#ifndef NANO_HTTP_SOCKET_H
#define NANO_HTTP_SOCKET_H
-#define HSOCKET_OK 0
-#define HSOCKET_CAN_NOT_CREATE 1001
-#define HSOCKET_CAN_NOT_GET_HOSTNAME 1002
-#define HSOCKET_CAN_NOT_CONNECT 1003
-#define HSOCKET_CAN_NOT_SEND 1004
-#define HSOCKET_CAN_NOT_RECEIVE 1005
-#define HSOCKET_CAN_NOT_BIND 1006
-#define HSOCKET_CAN_NOT_LISTEN 1007
-#define HSOCKET_CAN_NOT_ACCEPT 1008
+#include <nanohttp/nanohttp-common.h>
-#define HSOCKET_MAX_BUFSIZE 1024
+#include <time.h>
+
+#ifdef WIN32
+ #include <winsock2.h>
+#endif
-#define HSOCKET_BLOCKMODE 0
-#define HSOCKET_NONBLOCKMODE 1
-#include <time.h>
#ifdef WIN32
-#include <winsock2.h>
-#include <process.h>
-#include <string.h>
-typedef SOCKET hsocket_t;
-typedef int socklen_t;
-#define close(s) closesocket(s)
+ typedef SOCKET hsocket_t;
+ typedef int socklen_t;
#else
-#include <pthread.h>
-typedef int hsocket_t;
+ typedef int hsocket_t;
#endif
-/*
- PROTOTYPE:
- int my_recv_cb(hsocket_t sock, char *buffer, int size, void *userdata);
- returns 1 to continue 0 to stop receiving.
- */
-typedef int (*hsocket_recv_callback)(hsocket_t, char *, int, void*);
-/*
- hsocket_module_init
- Returns 0 if success.
- >0 if fail.
+
+/**
+ Initializes the socket modul. This should be called only
+ once for an application.
+
+ @returns This function should always return H_OK.
*/
-int hsocket_module_init();
+hstatus_t hsocket_module_init();
+
+
+/**
+ Destroys the socket modul. This should be called after
+ finishing an application.
+*/
void hsocket_module_destroy();
-/*
- hsocket_init
- Returns 0 if success.
- >0 if fail.
+/**
+ Initializes a given socket object. This function should
+ be called for every socket before using it.
+
+ @param sock the destination socket to initialize.
+
+ @returns This function should always return H_OK.
*/
-int hsocket_init(hsocket_t *sock);
+hstatus_t hsocket_init(hsocket_t *sock);
+
+
+/**
+ Destroys and releases a given socket.
+
+ @param sock the socket to destroy
+*/
void hsocket_free(hsocket_t sock);
-/*
- hsocket_open: create and connect a socket
- Returns 0 if success
- >0 if fail.
+/**
+ Connects to a given host. The hostname can be an IP number
+ or a humen readable hostname.
+
+ @param sock the destonation socket object to use
+ @param host hostname
+ @param port port number to connect to
+
+ @returns H_OK if success. One of the followings if fails:<P>
+ <BR>HSOCKET_ERROR_CREATE
+ <BR>HSOCKET_ERROR_GET_HOSTNAME
+ <BR>HSOCKET_ERROR_CONNECT
*/
-int hsocket_open(hsocket_t *sock, const char* host, int port);
+hstatus_t hsocket_open(hsocket_t *sock, const char* host, int port);
+
+
+/**
+ Close a socket connection.
+
+ @param sock the socket to close
+*/
void hsocket_close(hsocket_t sock);
-/*
- hsocket_bind: create and bind a socket
- Returns 0 if success
- >0 if fail.
- */
-int hsocket_bind(hsocket_t *sock, int port);
-/*
- Listen to socket. Must be called after bind
+/**
+ Binds a socket to a given port number. After bind you
+ can call hsocket_listen() to listen to the port.
+
+ @param sock socket to use.
+ @param port port number to bind to
+
+ @returns H_OK if success. One of the followings if fails:<P>
+ <BR>HSOCKET_ERROR_CREATE
+ <BR>HSOCKET_ERROR_BIND
+
+ @see hsocket_listen
*/
-int hsocket_listen(hsocket_t sock, int n);
+hstatus_t hsocket_bind(hsocket_t *sock, int port);
-typedef struct tag_conndata
-{
- hsocket_t sock;
-#ifdef WIN32
- HANDLE tid;
-#else
- pthread_t tid;
- pthread_attr_t attr;
-#endif
- time_t atime;
-}conndata_t;
-int hsocket_accept(hsocket_t sock, hsocket_t *dest);
+/**
+ Set the socket to the listen mode. You must bind
+ the socket to a port with hsocket_bind() before
+ you can listen to the port.
+ @param sock the socket to use
-/*
- hsocket_nsend
- sends n bytes of data
- Returns 0 if success
- >0 if fail
- */
-int hsocket_nsend(hsocket_t sock, const unsigned char* buffer, int n);
+ @returns H_OK if success. One of the followings if fails:<P>
+ <BR>HSOCKET_ERROR_NOT_INITIALIZED
+ <BR>HSOCKET_ERROR_LISTEN
+*/
+hstatus_t hsocket_listen(hsocket_t sock);
-/*
- hsocket_send
- sends strlen(buffer) bytes of data
- Returns 0 if success
- >0 if fail
- */
-int hsocket_send(hsocket_t sock, const char* str);
-
-
-/*
- hsocket_recv
- receives everything quequed on the socket.
- Sets *buffer to the received buffer.
- Sets size to the received size.
- You must free the buffer manually with free().
- If buffer is non zero, this functions assumes that
- buffer is valid and just reallocates the given buffer.
- If buffer is zero (like in the following example),
- the buffer will be allocated first.
-
- Example:
-
- int size;
- char *buffer;
- hsocket_t sock;
-
- buffer = 0;
- sock = ...
-
- if (!hsocket_recv(sock, &buffer, &size)) {
- printf("Received total: %d\n", size);
- printf("Received: '%s'\n", buffer);
-
- free(buffer);
- } else {
- printf("Error receiving data\n");
- }
-
- Returns 0 if success
- >0 if fail
- */
-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,
- int *totalBuffer, int *totalRest);
+/**
+ Accepts an incoming socket request. Note that this function
+ will not return until a socket connection is ready.
-/*
- returns 1 to continue, 0 to break;
- */
-int hsocket_recv_cb(hsocket_t sock,
- hsocket_recv_callback cb, void *userdata);
+ @param sock the socket which listents to a port
+ @param dest the destination socket which will be created
+
+ @returns H_OK if success. One of the followings if fails:<P>
+ <BR>HSOCKET_ERROR_NOT_INITIALIZED
+ <BR>HSOCKET_ERROR_ACCEPT
+*/
+hstatus_t hsocket_accept(hsocket_t sock, hsocket_t *dest);
-int hsocket_read(hsocket_t sock, unsigned char* buffer, int total, int force);
+/**
+ Sends data throught the socket.
-/* ======================================== */
-/* Buffered socket */
-/* ======================================== */
-typedef struct _bufsocket
-{
- hsocket_t sock;
- char *buffer;
- int bufsize;
- int cur;
-}hbufsocket_t;
+ @param sock the socket to use to send the data
+ @param bytes bytes to send
+ @param size size of memory to sent pointed by bytes.
+ @returns H_OK if success. One of the followings if fails:<P>
+ <BR>HSOCKET_ERROR_NOT_INITIALIZED
+ <BR>HSOCKET_ERROR_SEND
+*/
+hstatus_t hsocket_nsend(hsocket_t sock, const byte_t* bytes, int size);
-int hbufsocket_read(hbufsocket_t *bufsock, char *buffer, int size);
-/*--------------------------------------------------
-FUNCTION: hsocket_makenonblock
-----------------------------------------------------*/
-int hsocket_makenonblock(hsocket_t sock);
+/**
+ Sends a string throught the socket
-#ifdef WIN32
+ @param sock the socket to use to send the data
+ @param str the null terminated string to sent
+
+ @returns H_OK if success. One of the followings if fails:<P>
+ <BR>HSOCKET_ERROR_NOT_INITIALIZED
+ <BR>HSOCKET_ERROR_SEND
+*/
+hstatus_t hsocket_send(hsocket_t sock, const char* str);
+
+
+/**
+ Reads data from the socket.
+
+ @param sock the socket to read data from
+ @param buffer the buffer to use to save the readed bytes
+ @param size the maximum size of bytes to read
+ @param force if force is 1 then hsocket_read() will wait until
+ maximum size of bytes (size parameter) was readed. Otherwise
+ this function will not wait and will return with the bytes
+ quequed on the socket.
+
+ @returns This function will return -1 if an read error was occured.
+ Otherwise the return value is the size of bytes readed from
+ the socket.
+
+*/
+int hsocket_read(hsocket_t sock, byte_t* buffer, int size, int force);
+
+/**
+ Sets the goven socket to non-blocking socket mode.
+
+ @param sock the socket to set into the non-blocking mode
+
+ @returns H_OK if success. One of the followings if fails:<P>
+ <BR>HSOCKET_ERROR_NOT_INITIALIZED
+ <BR>HSOCKET_ERROR_IOCTL
+*/
+hstatus_t hsocket_block(hsocket_t sock, int block);
-struct tm *localtime_r(const time_t *const timep, struct tm *p_tm);
-#endif
#endif