summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar snowdrop2003-12-16 13:16:11 +0000
committerGravatar snowdrop2003-12-16 13:16:11 +0000
commit15c050ac3a39c9022268aa72770dc94956088615 (patch)
tree7c77d7bbebba8a84cab4f56827f5d9e64d908c4d
parent39ad0f75f24d87e0e76d58b0f2da0b07b9a21ca7 (diff)
downloadcsoap-15c050ac3a39c9022268aa72770dc94956088615.tar.gz
csoap-15c050ac3a39c9022268aa72770dc94956088615.tar.bz2
added chunked transfer encoding
-rw-r--r--nanohttp/nanohttp-client.c188
-rw-r--r--nanohttp/nanohttp-common.c31
-rw-r--r--nanohttp/nanohttp-common.h5
-rw-r--r--nanohttp/nanohttp-socket.c78
-rw-r--r--nanohttp/nanohttp-socket.h19
5 files changed, 292 insertions, 29 deletions
diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c
index 72af32e..8f3f37b 100644
--- a/nanohttp/nanohttp-client.c
+++ b/nanohttp/nanohttp-client.c
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-client.c,v 1.1 2003/12/11 14:51:04 snowdrop Exp $
+ * $Id: nanohttp-client.c,v 1.2 2003/12/16 13:16:11 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -374,7 +374,6 @@ int httpc_recv_cb_callback(hsocket_t sock, char *buffer,
return 1;
}
-
/*--------------------------------------------------
FUNCTION: httpc_get_cb
----------------------------------------------------*/
@@ -392,6 +391,24 @@ int httpc_get_cb(httpc_conn_t *conn, const char *urlstr,
int restsize;
httpc_cb_userdata_t cbdata;
+ /* content-length */
+ char *content_length_str;
+ long content_length;
+ long remain_length;
+ int counter;
+ int recvSize;
+ char readBuf[HSOCKET_MAX_BUFSIZE];
+
+ /* chunked encoding */
+ char *transfer_encoding;
+ char *chunk_buffer;
+ int chunk_size, cs;
+ hbufsocket_t bufsock;
+ char tmpch;
+ char chunk_size_str[25];
+ int chunk_size_cur;
+ char chunk_ch[2];
+
if (conn == NULL) {
log_error1("Connection object is NULL");
return 1;
@@ -440,40 +457,175 @@ int httpc_get_cb(httpc_conn_t *conn, const char *urlstr,
return 5;
}
- /* Receive Response */
+ /* Receive Response incl. header */
status = hsocket_recv_limit(conn->sock, &response,
"\r\n\r\n", &rest, &rsize, &restsize);
if (status != HSOCKET_OK) {
log_error2("Can not receive response (status:%d)", status);
- return NULL;
+ return 6;
}
res = hresponse_new(response);
if (res == NULL) {
log_error2("Can't create response (url:'%s')", urlstr);
- return 6;
+ return 7;
}
/* Invoke callback */
start_cb(conn, userdata, res->header, res->spec, res->errcode, res->desc);
- /* Invoke callback for rest */
- cb(0, conn, userdata, restsize, rest);
-
- /* rest and response are no longer required */
- free(rest);
- free(response);
- /* Invoke with callback */
- cbdata.conn = conn;
- cbdata.userdata = userdata;
- cbdata.callback = cb;
- cbdata.counter = 1;
+ /* ================================================= */
+ /* Retreive with content-length */
+ /* ================================================= */
- hsocket_recv_cb(conn->sock, httpc_recv_cb_callback, &cbdata);
+ /* Check if server communicates with content-length */
+ content_length_str =
+ hpairnode_get(res->header, HEADER_CONTENT_LENGTH);
- return 0;
+ if (content_length_str != NULL) {
+
+ log_debug1("Server communicates with content-length!");
+
+ /* Invoke callback for rest */
+ if (restsize > 0)
+ cb(0, conn, userdata, restsize, rest);
+
+ /* content length */
+ content_length = atol(content_length_str);
+
+ counter = 1;
+ remain_length = content_length - restsize;
+ while (remain_length > 0) {
+ if (remain_length >= HSOCKET_MAX_BUFSIZE) {
+ recvSize = HSOCKET_MAX_BUFSIZE;
+ } else {
+ recvSize = remain_length;
+ }
+
+ if (hsocket_read(conn->sock, readBuf, recvSize)) {
+ log_error1("Can not read from socket!");
+ return 9;
+ } else {
+ cb(counter++, conn, userdata, recvSize, readBuf);
+ }
+
+ remain_length -= HSOCKET_MAX_BUFSIZE;
+
+ } /* while */
+
+ /* rest and response are no longer required */
+ free(rest);
+ free(response);
+
+ return 0;
+
+ } /* if content length */
+
+
+ /* ================================================= */
+ /* 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 !");
+
+ /* read chunk size */
+ /*
+ strncpy(chunk_size_str, rest, 15);
+ chunk_size_cur = 0;
+ cs = 0;
+ while (1) {
+
+ chunk_size_str[chunk_size_cur] = rest[cs++];
+
+ 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++;
+ }
+
+ if (chunk_size_cur > 15) {
+ log_error1("Can not parse chunk size!");
+ return 10;
+ }
+
+ }
+
+ chunk_size = strtol(chunk_size_str,(char**)NULL, 16);
+
+ log_debug3("chunk_size: '%s' as dec: '%d'",
+ chunk_size_str, chunk_size);
+ */
+
+ /* initialize buffered socket */
+ bufsock.sock = conn->sock;
+ bufsock.cur = 0;
+ bufsock.buffer = rest;
+ bufsock.bufsize = restsize;
+
+ 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;
+ }
+
+ 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);
+ 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);
+
+ } /* while (chunk_size > 0)
+
+ /* rest and response are no longer required */
+ free(rest);
+ free(response);
+
+ return 0;
+
+ } /* if transfer_encodig */
+
+
+ log_error1("Unknown server response retreive type!");
+
+ return 1;
}
diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c
index 9efe0ac..bb4cde9 100644
--- a/nanohttp/nanohttp-common.c
+++ b/nanohttp/nanohttp-common.c
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-common.c,v 1.1 2003/12/11 14:51:04 snowdrop Exp $
+ * $Id: nanohttp-common.c,v 1.2 2003/12/16 13:16:13 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -116,7 +116,8 @@ hpair_t *hpairnode_parse(const char *str, const char *delim, hpair_t *next)
{
hpair_t *pair;
char *key, *value;
-
+ int c;
+
pair = (hpair_t*)malloc(sizeof(hpair_t));
pair->key = "";
pair->value = "";
@@ -130,8 +131,9 @@ hpair_t *hpairnode_parse(const char *str, const char *delim, hpair_t *next)
}
if (value != NULL) {
- pair->value = (char*)malloc(strlen(value)+1);
- strcpy(pair->value, value);
+ for (c=0;value[c]==' ';c++); /* skip white space */
+ pair->value = (char*)malloc(strlen(&value[c])+1);
+ strcpy(pair->value, &value[c]);
}
return pair;
@@ -148,6 +150,25 @@ void hpairnode_free(hpair_t *pair)
}
+char *hpairnode_get(hpair_t *pair, const char* key)
+{
+ if (key == NULL) {
+ log_error1("key is NULL");
+ return NULL;
+ }
+
+ while (pair != NULL) {
+ if (pair->key != NULL) {
+ if (!strcmp(pair->key, key)) {
+ return pair->value;
+ }
+ }
+ pair = pair->next;
+ }
+
+ return NULL;
+}
+
static
void hurl_dump(const hurl_t *url)
{
@@ -338,7 +359,7 @@ hresponse_t *hresponse_new(const char* buffer)
}
str[strlen(str)-1] = '\0';
- res->header = hpairnode_parse(str, ": ", res->header);
+ res->header = hpairnode_parse(str, ":", res->header);
}
/* *** Save body *** */
diff --git a/nanohttp/nanohttp-common.h b/nanohttp/nanohttp-common.h
index d3bb702..65e8167 100644
--- a/nanohttp/nanohttp-common.h
+++ b/nanohttp/nanohttp-common.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-common.h,v 1.1 2003/12/11 14:51:04 snowdrop Exp $
+ * $Id: nanohttp-common.h,v 1.2 2003/12/16 13:16:14 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -27,6 +27,7 @@
#define HEADER_CONTENT_LENGTH "Content-Length"
#define HEADER_CONTENT_TYPE "Content-Type"
+#define HEADER_TRANSFER_ENCODING "Transfer-Encoding"
#define HEADER_HOST "Host"
#define HEADER_DATE "Date"
@@ -50,7 +51,7 @@ struct hpair
hpair_t *hpairnode_new(const char* key, const char* value, hpair_t* next);
void hpairnode_free(hpair_t *pair);
-
+char *hpairnode_get(hpair_t *pair, const char* key);
typedef enum hreq_method
diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c
index 1a9742b..d465b8e 100644
--- a/nanohttp/nanohttp-socket.c
+++ b/nanohttp/nanohttp-socket.c
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-socket.c,v 1.1 2003/12/11 14:51:04 snowdrop Exp $
+ * $Id: nanohttp-socket.c,v 1.2 2003/12/16 13:16:14 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -234,6 +234,25 @@ int hsocket_recv_limit(hsocket_t sock, char** buffer,
return HSOCKET_OK;
}
+int hsocket_read(hsocket_t sock, char* buffer, int total)
+{
+ int status;
+ int totalRead;
+
+ totalRead = 0;
+
+ do {
+ status = recv(sock, &buffer[totalRead], total - totalRead, 0);
+ if (status > 0) {
+ totalRead += status;
+ } else {
+ return status;
+ }
+ if (totalRead >= total)
+ return 0;
+ } while (1);
+}
+
/*--------------------------------------------------
FUNCTION: hsocket_recv
----------------------------------------------------*/
@@ -243,6 +262,13 @@ int hsocket_recv(hsocket_t sock, char** buffer, int *totalSize)
int chunk=1;
char tmp[HSOCKET_MAX_BUFSIZE+1];
int fsize;
+ int bufSize;
+
+ if (*totalSize > 0) {
+ bufSize = *totalSize;
+ } else {
+ bufSize = HSOCKET_MAX_BUFSIZE;
+ }
*totalSize = 0;
@@ -255,7 +281,8 @@ int hsocket_recv(hsocket_t sock, char** buffer, int *totalSize)
do {
- size = recv(sock, tmp, HSOCKET_MAX_BUFSIZE, 0);
+ size = recv(sock, tmp, bufSize, 0);
+ bufSize = HSOCKET_MAX_BUFSIZE;
if (size == -1) {
log_error1("Error reading from socket\n");
@@ -269,7 +296,8 @@ int hsocket_recv(hsocket_t sock, char** buffer, int *totalSize)
*totalSize += size;
if (*buffer) {
log_debug2("reallocation %d bytes",*totalSize+fsize+1);
- *buffer = (char*)realloc((char*)*buffer, (*totalSize)+fsize+HSOCKET_MAX_BUFSIZE);
+ *buffer = (char*)realloc((char*)*buffer,
+ (*totalSize)+fsize+HSOCKET_MAX_BUFSIZE);
strcat(*buffer, tmp);
} else {
log_debug1("Allocating");
@@ -322,3 +350,47 @@ int hsocket_recv_cb(hsocket_t sock,
+/*--------------------------------------------------
+ FUNCTION: hbufsocket_read
+----------------------------------------------------*/
+int hbufsocket_read(hbufsocket_t *bufsock, char *buffer, int size)
+{
+ int status;
+ int tmpsize;
+
+ if (bufsock->bufsize - bufsock->cur >= size) {
+
+ log_debug1("no need to read from socket");
+ strncpy(buffer, &(bufsock->buffer[bufsock->cur]), size);
+ bufsock->cur += size;
+ return HSOCKET_OK;
+
+ } else {
+
+ tmpsize = bufsock->bufsize - bufsock->cur;
+ log_debug2("tmpsize = %d", tmpsize);
+
+ if (tmpsize > 0)
+ strncpy(buffer, &(bufsock->buffer[bufsock->cur]), tmpsize);
+
+ size -= tmpsize;
+
+ free(bufsock->buffer);
+ status = recv(bufsock->sock, bufsock->buffer, size, 0);
+ if (status > 0) {
+ bufsock->bufsize = size;
+ bufsock->cur = size;
+ strncpy(&buffer[tmpsize], bufsock->buffer, size);
+ }
+
+ return HSOCKET_OK;
+ }
+}
+
+
+
+
+
+
+
+
diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h
index 92e92e2..901876f 100644
--- a/nanohttp/nanohttp-socket.h
+++ b/nanohttp/nanohttp-socket.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-socket.h,v 1.1 2003/12/11 14:51:04 snowdrop Exp $
+ * $Id: nanohttp-socket.h,v 1.2 2003/12/16 13:16:14 snowdrop Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -124,6 +124,23 @@ int hsocket_recv_limit(hsocket_t sock, char** buffer,
int hsocket_recv_cb(hsocket_t sock,
hsocket_recv_callback cb, void *userdata);
+int hsocket_read(hsocket_t sock, char* buffer, int total);
+
+
+/* ======================================== */
+/* Buffered socket */
+/* ======================================== */
+typedef struct _bufsocket
+{
+ hsocket_t sock;
+ char *buffer;
+ int bufsize;
+ int cur;
+}hbufsocket_t;
+
+
+int hbufsocket_read(hbufsocket_t *bufsock, char *buffer, int size);
+
#endif