summaryrefslogtreecommitdiffstats
path: root/nanohttp/nanohttp-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'nanohttp/nanohttp-client.c')
-rw-r--r--nanohttp/nanohttp-client.c1357
1 files changed, 682 insertions, 675 deletions
diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c
index 4f62afc..8f49048 100644
--- a/nanohttp/nanohttp-client.c
+++ b/nanohttp/nanohttp-client.c
@@ -1,28 +1,34 @@
/******************************************************************
- * $Id: nanohttp-client.c,v 1.12 2004/06/04 08:55:07 snowdrop Exp $
- *
- * CSOAP Project: A http client/server library in C
- * Copyright (C) 2003 Ferhat Ayaz
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Email: ayaz@jprogrammer.net
- ******************************************************************/
+* $Id: nanohttp-client.c,v 1.13 2004/08/26 17:07:47 rans Exp $
+*
+* CSOAP Project: A http client/server library in C
+* Copyright (C) 2003 Ferhat Ayaz
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public
+* License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA.
+*
+* Email: ayaz@jprogrammer.net
+******************************************************************/
#include <nanohttp/nanohttp-client.h>
+#ifdef WIN32
+#include "wsockcompat.h"
+#include <winsock2.h>
+#define close(s) closesocket(s)
+#endif
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -30,858 +36,859 @@
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
-
-
+#ifdef WIN32
+#include <string.h>
+static struct tm *localtime_r(const time_t *const timep, struct tm *p_tm)
+{
+ static tm* tmp;
+ tmp = localtime(timep);
+ if (tmp) {
+ memcpy(p_tm, tmp, sizeof(struct tm));
+ tmp = p_tm;
+ }
+ return tmp;
+}
+#endif
/*--------------------------------------------------
- FUNCTION: httpc_new
- DESC: Creates a new http client connection object
- You need to create at least 1 http client connection
- to communicate via http.
+FUNCTION: httpc_new
+DESC: Creates a new http client connection object
+You need to create at least 1 http client connection
+to communicate via http.
----------------------------------------------------*/
httpc_conn_t* httpc_new()
{
- httpc_conn_t* res = (httpc_conn_t*)malloc(sizeof(httpc_conn_t));
+ httpc_conn_t* res = (httpc_conn_t*)malloc(sizeof(httpc_conn_t));
- hsocket_init(&res->sock);
- res->header = NULL;
- res->url = NULL;
+ hsocket_init(&res->sock);
+ res->header = NULL;
+ res->url = NULL;
- return res;
+ return res;
}
/*--------------------------------------------------
- FUNCTION: httpc_free
- DESC: Free the given http client object.
+FUNCTION: httpc_free
+DESC: Free the given http client object.
----------------------------------------------------*/
void httpc_free(httpc_conn_t* conn)
{
- hpair_t *tmp;
-
- if (conn != NULL) {
- hsocket_free(conn->sock);
-
- while (conn->header != NULL) {
- tmp = conn->header;
- conn->header = conn->header->next;
- hpairnode_free(tmp);
- }
-
- free(conn);
- }
+ hpair_t *tmp;
+
+ if (conn != NULL) {
+ hsocket_free(conn->sock);
+
+ while (conn->header != NULL) {
+ tmp = conn->header;
+ conn->header = conn->header->next;
+ hpairnode_free(tmp);
+ }
+
+ free(conn);
+ }
}
/*--------------------------------------------------
- FUNCTION: httpc_set_header
- DESC: Adds a new (key, value) pair to the header
- or modifies the old pair if this function will
- finds another pair with the same 'key' value.
+FUNCTION: httpc_set_header
+DESC: Adds a new (key, value) pair to the header
+or modifies the old pair if this function will
+finds another pair with the same 'key' value.
----------------------------------------------------*/
int httpc_set_header(httpc_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;
+ 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;
}
/*--------------------------------------------------
- FUNCTION: httpc_header_add_date
- DESC: Adds the current date to the header.
+FUNCTION: httpc_header_add_date
+DESC: Adds the current date to the header.
----------------------------------------------------*/
static
void httpc_header_add_date(httpc_conn_t *conn)
{
- char buffer[255];
- time_t nw;
- struct tm stm;
-
- /* Set date */
- nw = time(NULL);
- localtime_r(&nw, &stm);
- strftime(buffer, 255, "%a, %d %b %y %T GMT", &stm);
- httpc_set_header(conn, HEADER_DATE, buffer);
+ char buffer[255];
+ time_t nw;
+ struct tm stm;
+
+ /* Set date */
+ nw = time(NULL);
+ localtime_r(&nw, &stm);
+ strftime(buffer, 255, "%a, %d %b %y %T GMT", &stm);
+ httpc_set_header(conn, HEADER_DATE, buffer);
}
/*--------------------------------------------------
- FUNCTION: httpc_send_header
- DESC: Sends the current header information stored
- in conn through conn->sock.
+FUNCTION: httpc_send_header
+DESC: Sends the current header information stored
+in conn through conn->sock.
----------------------------------------------------*/
int httpc_send_header(httpc_conn_t *conn)
{
- hpair_t *p;
- int status;
- char buffer[1024];
-
- p = conn->header;
- while (p != NULL) {
- 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)
- return status;
- }
- p = p->next;
- }
+ hpair_t *p;
+ int status;
+ char buffer[1024];
+
+ p = conn->header;
+ while (p != NULL) {
+ 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)
+ return status;
+ }
+ p = p->next;
+ }
- status = hsocket_send(conn->sock, "\r\n");
- return status;
+ status = hsocket_send(conn->sock, "\r\n");
+ 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++) {
-
- /* log_debug5("%d -> '%c' (%d, %d)", buffer[i], buffer[i],
- buffer[i+1], buffer[i+2]);
- */
- if (buffer[i] == '\n') {
- if (buffer[i+1] == '\n') {
-
- 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;
+ 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++) {
+
+ /* log_debug5("%d -> '%c' (%d, %d)", buffer[i], buffer[i],
+ buffer[i+1], buffer[i+2]);
+ */
+ if (buffer[i] == '\n') {
+ if (buffer[i+1] == '\n') {
+
+ 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);
}
- }
- }
-
- 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;
+ return res;
}
static
int httpc_receive_with_connection_closed(httpc_conn_t *conn,
- hresponse_t *res,
- httpc_response_callback cb,
- void *userdata)
+ hresponse_t *res,
+ httpc_response_callback cb,
+ void *userdata)
{
- /* connection closed */
- char *connection_status;
- int status;
- char buffer[HSOCKET_MAX_BUFSIZE];
- int counter;
+ /* 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);
- counter = 0;
+ if (connection_status != NULL &&
+ !strcmp(connection_status, "close")) {
- /* ================================================= */
- /* Retreive with only "Connection: close" */
- /* ================================================= */
- connection_status =
- hpairnode_get(res->header, HEADER_CONNECTION);
+ log_debug1("Server communicates with 'Connection: close' !");
- if (connection_status != NULL &&
- !strcmp(connection_status, "close")) {
+ /* Invoke callback for rest */
+ if (res->bodysize > 0)
+ cb(0, conn, userdata, res->bodysize, res->body);
- 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);
- 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) { /* close connection */
- close(conn->sock);
- return 0;
- }
-
- if (status < 0) { /* error */
- log_error2("Can nor read from socket (status: %d)", status);
- return 11;
- }
+ if (status < 0) { /* error */
+ log_error2("Can nor read from socket (status: %d)", status);
+ return 11;
+ }
- /* Invoke callback */
- cb(counter++, conn, userdata, status, buffer);
- }
+ /* Invoke callback */
+ cb(counter++, conn, userdata, status, buffer);
+ }
- return 0;
- }
+ return 0;
+ }
- return -1;
+ return -1;
}
static
int httpc_receive_with_chunked_encoding(httpc_conn_t *conn,
- hresponse_t *res,
- httpc_response_callback cb,
- void *userdata)
+ 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 = 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]);
+ /* 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];
- if (chunk_size_str[chunk_size_cur] == '\n') {
- chunk_size_str[chunk_size_cur] = '\0';
- break;
- }
+ counter = 0;
+ /* ================================================= */
+ /* Retreive with chunked encoding */
+ /* ================================================= */
- if (chunk_size_str[chunk_size_cur] != '\r'
- && chunk_size_str[chunk_size_cur] != ';') {
- chunk_size_cur++;
- }
+ /* 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;
- } /* 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;
+ 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++;
+ }
+
+ } /* 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;
- */
+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)
+ 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];
+ int counter;
+ int content_length;
+ int remain_length;
+ int recvSize;
+ char *content_length_str;
+ char buffer[HSOCKET_MAX_BUFSIZE];
- /* ================================================= */
- /* Retreive with content-length */
- /* ================================================= */
+ /* ================================================= */
+ /* Retreive with content-length */
+ /* ================================================= */
- /* Check if server communicates with content-length */
- content_length_str =
- hpairnode_get_ignore_case(res->header, HEADER_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) {
+ 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, res->body);
+ log_debug1("Server communicates with content-length!");
- /* content length */
- content_length = atol(content_length_str);
+ /* Invoke callback for rest */
+ if (res->bodysize > 0)
+ cb(0, conn, userdata, res->bodysize, (char *)res->body);
- 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;
- }
+ /* content length */
+ content_length = atol(content_length_str);
- if (hsocket_read(conn->sock, buffer, recvSize,1)) {
- log_error1("Can not read from socket!");
- return 9;
- } else {
- cb(counter++, conn, userdata, recvSize, buffer);
- }
+ 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;
+ }
- remain_length -= HSOCKET_MAX_BUFSIZE;
+ if (hsocket_read(conn->sock, buffer, recvSize,1)) {
+ log_error1("Can not read from socket!");
+ return 9;
+ } else {
+ cb(counter++, conn, userdata, recvSize, buffer);
+ }
- } /* while */
+ remain_length -= HSOCKET_MAX_BUFSIZE;
- /* rest and response are no longer required */
+ } /* while */
- return 0;
+ /* rest and response are no longer required */
- } /* if content length */
+ return 0;
- return -1;
+ } /* 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)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata)
{
- hresponse_t *res;
- int 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!");
+ hresponse_t *res;
+ int 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!");
}
/*--------------------------------------------------
- FUNCTION: httpc_talk_to_server
- DESC: This function is the heart of the httpc
- module. It will send the request and process the
- response.
-
- Here the parameters:
-
- method:
- the request method. This can be HTTP_REQUEST_POST and
- HTTP_REQUEST_GET.
-
- conn:
- the connection object (created with httpc_new())
-
- urlstr:
- the complete url in string format.
- http://<host>:<port>/<context>
- where <port> is not mendatory.
-
- start_cb:
- a callback function, which will be called when
- the response header is completely arrives.
-
- cb:
- a callback function, which will be called everytime
- when data arrives.
-
- content_size:
- size of content to send.
- (only if method is HTTP_REQUEST_POST)
-
- content:
- the content data to send.
- (only if method is HTTP_REQUEST_POST)
-
- userdata:
- a user define data, which will be passed to the
- start_cb and cb callbacks as a parameter. This
- can also be NULL.
-
-
- If success, this function will return 0.
- >0 otherwise.
+FUNCTION: httpc_talk_to_server
+DESC: This function is the heart of the httpc
+module. It will send the request and process the
+response.
+
+Here the parameters:
+
+method:
+the request method. This can be HTTP_REQUEST_POST and
+HTTP_REQUEST_GET.
+
+conn:
+the connection object (created with httpc_new())
+
+urlstr:
+the complete url in string format.
+http://<host>:<port>/<context>
+where <port> is not mendatory.
+
+start_cb:
+a callback function, which will be called when
+the response header is completely arrives.
+
+cb:
+a callback function, which will be called everytime
+when data arrives.
+
+content_size:
+size of content to send.
+(only if method is HTTP_REQUEST_POST)
+
+content:
+the content data to send.
+(only if method is HTTP_REQUEST_POST)
+
+userdata:
+a user define data, which will be passed to the
+start_cb and cb callbacks as a parameter. This
+can also be NULL.
+
+
+If success, this function will return 0.
+>0 otherwise.
----------------------------------------------------*/
static
int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn,
- const char *urlstr)
+ const char *urlstr)
{
- hurl_t *url;
- char buffer[4096];
- int status;
-
-
- if (conn == NULL) {
- log_error1("Connection object is NULL");
- return 1;
- }
-
- /* Build request header */
- httpc_header_add_date(conn);
-
- /* Create url */
- url = hurl_new(urlstr);
- if (url == NULL) {
- log_error2("Can not parse URL '%s'", SAVE_STR(urlstr));
- return 2;
- }
-
- /* Set hostname */
- httpc_set_header(conn, HEADER_HOST, url->host);
-
- /* Open connection */
- status = hsocket_open(&conn->sock, url->host, url->port);
- if (status != HSOCKET_OK) {
- log_error3("Can not open connection to '%s' (status:%d)",
- SAVE_STR(url->host), status);
- return 3;
- }
-
- /* check method */
- if (method == HTTP_REQUEST_GET) {
-
- /* Set GET Header */
- sprintf(buffer, "GET %s HTTP/1.1\r\n",
- (url->context)?url->context:("/"));
-
- } else if (method == HTTP_REQUEST_POST) {
-
- /* Set POST Header */
- sprintf(buffer, "POST %s HTTP/1.1\r\n",
- (url->context)?url->context:("/"));
- } else {
-
- log_error1("Unknown method type!");
- return 15;
- }
-
- status = hsocket_send(conn->sock, buffer);
- if (status != HSOCKET_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) {
- log_error2("Can not send header (status:%d)", status);
- hsocket_close(conn->sock);
- return 5;
- }
-
- return status;
-
+ hurl_t *url;
+ char buffer[4096];
+ int status;
+
+
+ if (conn == NULL) {
+ log_error1("Connection object is NULL");
+ return 1;
+ }
+
+ /* Build request header */
+ httpc_header_add_date(conn);
+
+ /* Create url */
+ url = hurl_new(urlstr);
+ if (url == NULL) {
+ log_error2("Can not parse URL '%s'", SAVE_STR(urlstr));
+ return 2;
+ }
+
+ /* Set hostname */
+ httpc_set_header(conn, HEADER_HOST, url->host);
+
+ /* Open connection */
+ status = hsocket_open(&conn->sock, url->host, url->port);
+ if (status != HSOCKET_OK) {
+ log_error3("Can not open connection to '%s' (status:%d)",
+ SAVE_STR(url->host), status);
+ return 3;
+ }
+
+#ifndef WIN32
+#if HSOCKET_BLOCKMODE!=0
+ fcntl(conn->sock, F_SETFL, O_NONBLOCK);
+#endif
+#else
+ unsigned long iMode = HSOCKET_BLOCKMODE;
+ if(ioctlsocket(conn->sock, FIONBIO, (u_long FAR*) &iMode) == INVALID_SOCKET)
+ {
+ log_error1("ioctlsocket error");
+ return -1;
+ }
+
+#endif
+
+ /* check method */
+ if (method == HTTP_REQUEST_GET) {
+
+ /* Set GET Header */
+ sprintf(buffer, "GET %s HTTP/1.1\r\n",
+ (url->context)?url->context:("/"));
+
+ } else if (method == HTTP_REQUEST_POST) {
+
+ /* Set POST Header */
+ sprintf(buffer, "POST %s HTTP/1.1\r\n",
+ (url->context)?url->context:("/"));
+ } else {
+
+ log_error1("Unknown method type!");
+ return 15;
+ }
+
+ status = hsocket_send(conn->sock, buffer);
+ if (status != HSOCKET_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) {
+ log_error2("Can not send header (status:%d)", status);
+ hsocket_close(conn->sock);
+ return 5;
+ }
+
+ return status;
+
}
-
-
+
+
/*--------------------------------------------------
- FUNCTION: httpc_get_cb
- DESC: Wraps the httpc_talk_to_server() function
- to communicate with GET method.
+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.
+See the documentation of httpc_talk_to_server()
+for more information.
----------------------------------------------------*/
int httpc_get_cb(httpc_conn_t *conn, const char *urlstr,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, void *userdata)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, void *userdata)
{
- int status;
+ int status;
- status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr);
+ status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr);
- if (status != HSOCKET_OK)
- return status;
+ if (status != HSOCKET_OK)
+ return status;
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
+ status = httpc_receive_response(conn, start_cb, cb, userdata);
+ return status;
}
/*--------------------------------------------------
- FUNCTION: httpc_post_cb
- DESC: Wraps the httpc_talk_to_server() function
- to communicate with POST method.
+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.
+See the documentation of httpc_talk_to_server()
+for more information.
- TODO: Add post content rutine
+TODO: Add post content rutine
----------------------------------------------------*/
int httpc_post_cb(httpc_conn_t *conn, const char *urlstr,
- httpc_response_start_callback start_cb,
- httpc_response_callback cb, int content_size,
- char *content, void *userdata)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb, int content_size,
+ char *content, void *userdata)
{
- int status;
- char buffer[255];
+ int status;
+ char buffer[255];
- sprintf(buffer, "%d", content_size);
- httpc_set_header(conn, HEADER_CONTENT_LENGTH, buffer);
+ 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 = 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)
- return status;
+ status = hsocket_nsend(conn->sock, content, content_size);
+ if (status != HSOCKET_OK)
+ return status;
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- 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.
- ======================================================*/
+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)
+ void *userdata, int size, char *buffer)
{
- hresponse_t *res;
+ hresponse_t *res;
- /* get response object */
- res = (hresponse_t*)userdata;
+ /* get response object */
+ res = (hresponse_t*)userdata;
- /* allocate buffersize */
+ /* allocate buffersize */
- res->bodysize += size;
- res->body = (unsigned char*)realloc(res->body, res->bodysize + 1);
+ 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';
+ 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)
+ hpair_t *header, const char *spec,
+ int errcode, const char *desc)
{
- hresponse_t *res;
+ hresponse_t *res;
- /* get response object */
- res = (hresponse_t*)userdata;
+ /* get response object */
+ res = (hresponse_t*)userdata;
- /* set spec */
- if (spec != NULL) {
- strcpy(res->spec, spec);
- }
+ /* set spec */
+ if (spec != NULL) {
+ strcpy(res->spec, spec);
+ }
- /* set errcode */
- res->errcode = errcode;
+ /* set errcode */
+ res->errcode = errcode;
- /* set desc */
- if (desc != NULL) {
- res->desc = (char*)malloc(strlen(desc)+1);
- strcpy(res->desc, desc);
- }
+ /* 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!");
- }
+ /* set header */
+ if (header == NULL) {
+ log_warn1("header is NULL!");
+ }
- res->header = hpairnode_copy_deep(header);
+ res->header = hpairnode_copy_deep(header);
}
-
+
/*--------------------------------------------------
- FUNCTION: httpc_get
+FUNCTION: httpc_get
----------------------------------------------------*/
hresponse_t *httpc_get(httpc_conn_t *conn, const char *url)
{
- int status;
- hresponse_t *res;
+ int status;
+ hresponse_t *res;
- res = hresponse_new();
- status = httpc_get_cb(conn, url, httpc_custom_start_callback,
- httpc_custom_res_callback, 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;
- }
+ if (status != 0) {
+ hresponse_free(res);
+ return NULL;
+ }
- return res;
+ return res;
}
/*--------------------------------------------------
- FUNCTION: httpc_post
+FUNCTION: httpc_post
----------------------------------------------------*/
hresponse_t *httpc_post(httpc_conn_t *conn, const char *url,
- int content_size, const char *content)
+ int content_size, const char *content)
{
- int status;
- hresponse_t *res;
+ int status;
+ hresponse_t *res;
- res = hresponse_new();
- status = httpc_post_cb(conn, url, httpc_custom_start_callback,
- httpc_custom_res_callback, content_size,
- content, res);
+ res = hresponse_new();
+ status = httpc_post_cb(conn, url, httpc_custom_start_callback,
+ httpc_custom_res_callback, content_size,
+ (char *)content, res);
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
+ if (status != 0) {
+ hresponse_free(res);
+ return NULL;
+ }
- return res;
+ return res;
}
/*
- POST Module
- */
+POST Module
+*/
/*--------------------------------------------------
- FUNCTION: httpc_post_open
+FUNCTION: httpc_post_open
----------------------------------------------------*/
int httpc_post_open(httpc_conn_t *conn, const char *urlstr)
{
- int status;
+ int status;
- httpc_set_header(conn, HEADER_TRANSFER_ENCODING, "chunked");
+ httpc_set_header(conn, HEADER_TRANSFER_ENCODING, "chunked");
- status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
- return status;
+ status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, urlstr);
+ return status;
}
/*--------------------------------------------------
- FUNCTION: httpc_post_send
+FUNCTION: httpc_post_send
----------------------------------------------------*/
int httpc_post_send(httpc_conn_t *conn,
- const char* buffer,
- int bufsize)
+ const char* buffer,
+ int bufsize)
{
- 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;
-
- status = hsocket_send(conn->sock, "\r\n");
-
- return status;
-}
+ char hexsize[100]; /* chunk size in hex */
+ int status;
+ sprintf(hexsize, "%x\r\n", bufsize);
-/*--------------------------------------------------
- FUNCTION: httpc_post_finish
-----------------------------------------------------*/
-hresponse_t *httpc_post_finish(httpc_conn_t *conn)
-{
- int status;
- hresponse_t *res;
+ status = hsocket_send(conn->sock, hexsize);
+ if (status != HSOCKET_OK)
+ return status;
- res = hresponse_new();
- status = httpc_post_finish_cb(conn, httpc_custom_start_callback,
- httpc_custom_res_callback, res);
+ status = hsocket_nsend(conn->sock, buffer, bufsize);
+ if (status != HSOCKET_OK)
+ return status;
- if (status != 0) {
- hresponse_free(res);
- return NULL;
- }
+ status = hsocket_send(conn->sock, "\r\n");
- return res;
+ return status;
}
-
/*--------------------------------------------------
- FUNCTION: httpc_post_finish_cb
+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)
+ httpc_response_start_callback start_cb,
+ httpc_response_callback cb,
+ void *userdata)
{
- int status;
-
- status = hsocket_send(conn->sock, "0\r\n\r\n");
- if (status != HSOCKET_OK) return status;
-
- status = httpc_receive_response(conn, start_cb, cb, userdata);
- return status;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ int status;
+ status = hsocket_send(conn->sock, "0\r\n\r\n");
+ if (status != HSOCKET_OK) return status;
+ status = httpc_receive_response(conn, start_cb, cb, userdata);
+ return status;
+}
+/*--------------------------------------------------
+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;
+}