summaryrefslogtreecommitdiffstats
path: root/nanohttp/nanohttp-client.c
diff options
context:
space:
mode:
authorGravatar snowdrop2004-10-15 13:29:36 +0000
committerGravatar snowdrop2004-10-15 13:29:36 +0000
commitb0691bfc7943532575dba0cee285838d45072535 (patch)
tree8690810748ac8ddb5d9cbda961f7d5ef7e711faa /nanohttp/nanohttp-client.c
parentd2c445f5d7cf21606c9878bff3e4046c283944df (diff)
downloadcsoap-b0691bfc7943532575dba0cee285838d45072535.tar.gz
csoap-b0691bfc7943532575dba0cee285838d45072535.tar.bz2
added mime support and https stream object
Diffstat (limited to 'nanohttp/nanohttp-client.c')
-rw-r--r--nanohttp/nanohttp-client.c959
1 files changed, 210 insertions, 749 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;
-}