From b0691bfc7943532575dba0cee285838d45072535 Mon Sep 17 00:00:00 2001 From: snowdrop Date: Fri, 15 Oct 2004 13:29:36 +0000 Subject: added mime support and https stream object --- nanohttp/nanohttp-client.c | 959 ++++++++++----------------------------------- 1 file changed, 210 insertions(+), 749 deletions(-) (limited to 'nanohttp/nanohttp-client.c') 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 + #ifdef HAVE_CONFIG_H #include #endif @@ -31,6 +32,15 @@ #include #include +#ifdef MEM_DEBUG +#include +#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); + } @@ -122,6 +142,23 @@ httpc_set_header(httpc_conn_t * conn, const char *key, const char *value) } +/*-------------------------------------------------- +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. @@ -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; @@ -170,443 +207,6 @@ httpc_send_header(httpc_conn_t * conn) return status; } -/*-------------------------------------------------- -FUNCTION: httpc_set_transfer_encoding -DESC: -----------------------------------------------------*/ -void httpc_set_transfer_encoding(httpc_conn_t *conn, const char* encoding) -{ - httpc_set_header(conn, HEADER_TRANSFER_ENCODING, encoding); - - if (!strcmp(encoding, TRANSFER_ENCODING_CHUNKED)) - conn->_is_chunked = 1; -} - -/*-------------------------------------------------- -FUNCTION: httpc_set_transfer_encoding -DESC: -----------------------------------------------------*/ -int httpc_send_data(httpc_conn_t *conn, const unsigned char* bytes, size_t size) -{ - int status; - char chunked[15]; - - if (conn->_is_chunked) - { - sprintf(chunked,"%x\r\n",size); - status = hsocket_send(conn->sock, chunked); - if (status != HSOCKET_OK) - return status; - } - - status = hsocket_nsend(conn->sock, bytes, size); - - if (conn->_is_chunked) - { - status = hsocket_send(conn->sock, "\r\n"); - if (status != HSOCKET_OK) - return status; - } - - return status; -} - - - -static -hresponse_t * -httpc_receive_header(hsocket_t sock) -{ - 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 @@ -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; -} -- cgit v1.1-32-gdbae