From cec0d2ad1ed2d07e8075a348e47238f5bcd54fe8 Mon Sep 17 00:00:00 2001
From: snowdrop
Date: Thu, 18 Dec 2003 15:32:09 +0000
Subject: splitted httpc_talk_to_server()

---
 nanohttp/nanohttp-client.c | 495 ++++++++++++++++++++++++++-------------------
 nanohttp/nanohttp-client.h |  12 +-
 nanohttp/nanohttp-common.c |   4 +-
 3 files changed, 302 insertions(+), 209 deletions(-)

(limited to 'nanohttp')

diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c
index f670c71..f7d17a6 100644
--- a/nanohttp/nanohttp-client.c
+++ b/nanohttp/nanohttp-client.c
@@ -1,5 +1,5 @@
 /******************************************************************
- *  $Id: nanohttp-client.c,v 1.6 2003/12/18 12:23:44 snowdrop Exp $
+ *  $Id: nanohttp-client.c,v 1.7 2003/12/18 15:32:09 snowdrop Exp $
  *
  * CSOAP Project:  A http client/server library in C
  * Copyright (C) 2003  Ferhat Ayaz
@@ -151,151 +151,19 @@ int httpc_send_header(httpc_conn_t *conn)
   return status;
 }
 
-
-/*--------------------------------------------------
-  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, 
-			 httpc_response_start_callback start_cb,
-			 httpc_response_callback cb, int content_size, 
-			 char* content, void *userdata)
+hresponse_t *httpc_receive_header(hsocket_t sock)
 {
-  hurl_t *url;
-  char buffer[4096];
+  hresponse_t *res;
+  int done;
+  int i;
   int status;
+  char buffer[HSOCKET_MAX_BUFSIZE];
   char *response;
-  int rsize;
-  hresponse_t *res;
   char *rest;
+  int rsize;
   int restsize;
-  int i, done;
-
-  /* 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;
-  hbufsocket_t bufsock;
-  char chunk_size_str[25];
-  int chunk_size_cur;
-
-  /* connection closed */
-  char *connection_status;
-  
-
-  if (conn == NULL) {
-    log_error1("Connection object is NULL");
-    return 1;
-  }
-
-  /* set response to 0 to allocate 
-     it in hsocket_recv */
-  response = 0;
-
-  /* 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;
-  }
-  
   /* Receive Response incl. header */
   rsize = restsize = 0;
   response = rest = NULL;
@@ -303,11 +171,11 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, const char *url
 
   while (!done) {
     
-    status = hsocket_read(conn->sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
+    status = hsocket_read(sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
   
     if (status <= 0) {
       log_error2("Can not receive response (status:%d)", status); 
-      return 6;
+      return NULL;
     } 
 
 
@@ -337,8 +205,7 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, const char *url
 	  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);
@@ -356,65 +223,92 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, const char *url
 
   if (response == NULL) {
     log_error1("Header too long!");
-    return 13;
+    return NULL;
   }
   
   res = hresponse_new_from_buffer(response);
   if (res == NULL) {
-    log_error2("Can't create response (url:'%s')", urlstr);
-    return 7;
+    log_error1("Can't create response");
+    return NULL;
   }
 
-  /* Invoke callback */
-  start_cb(conn, userdata, res->header, res->spec, res->errcode, res->desc);
+  res->bodysize = restsize;
+  res->body = rest;
 
+  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 content-length                    */ 
+  /*   Retreive with only "Connection: close"          */ 
   /* ================================================= */
+  connection_status = 
+    hpairnode_get(res->header, HEADER_CONNECTION);
 
-  /* Check if server communicates with content-length */
-  content_length_str = 
-    hpairnode_get_ignore_case(res->header, HEADER_CONTENT_LENGTH);
+  if (connection_status != NULL && 
+      !strcmp(connection_status, "close")) { 
 
-  if (content_length_str != NULL) {
+    log_debug1("Server communicates with 'Connection: close' !");
 
-    log_debug1("Server communicates with content-length!");
-    
     /* Invoke callback for rest */
-    if (restsize > 0)
-      cb(0, conn, userdata, restsize, rest);
+    if (res->bodysize > 0)
+      cb(0, conn, userdata, res->bodysize, res->body);
 
-    /* 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;
-      }
+    while (1) {
+      
+      status = hsocket_read(conn->sock, buffer, HSOCKET_MAX_BUFSIZE, 0);
 
-      if (hsocket_read(conn->sock, readBuf, recvSize,1)) {
-	log_error1("Can not read from socket!");
-	return 9;
-      } else {
-	cb(counter++, conn, userdata, recvSize, readBuf);
+      if (status == 0) { /* connection closed */
+	return 0; 
+      }
+    
+      if (status < 0) { /* error */
+	log_error2("Can nor read from socket (status: %d)", status);
+	return 11;
       }
 
-      remain_length -= HSOCKET_MAX_BUFSIZE;
-
-    } /* while */
-
-    /* rest and response are no longer required */
+      /* Invoke callback */ 
+      cb(counter++, conn, userdata, status, buffer);
+    }
 
     return 0;
+  }
 
-  } /* if content length */
-
+  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                  */ 
   /* ================================================= */
@@ -422,6 +316,7 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, const char *url
   /* Check if server communicates with chunked encoding */
   transfer_encoding = 
     hpairnode_get(res->header, HEADER_TRANSFER_ENCODING);
+
   if (transfer_encoding != NULL && 
       !strcmp(transfer_encoding, "chunked")) { 
 
@@ -430,8 +325,8 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, const char *url
     /* initialize buffered socket */
     bufsock.sock = conn->sock;
     bufsock.cur = 0;
-    bufsock.buffer = rest;
-    bufsock.bufsize = restsize;
+    bufsock.buffer = res->body;
+    bufsock.bufsize = res->bodysize;
     
     chunk_size = 1;
     while (chunk_size > 0) {
@@ -489,45 +384,235 @@ int httpc_talk_to_server(hreq_method method, httpc_conn_t *conn, const char *url
 
   } /* 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 only "Connection: close"          */ 
+  /*   Retreive with content-length                    */ 
   /* ================================================= */
-  connection_status = 
-    hpairnode_get(res->header, HEADER_CONNECTION);
 
-  if (connection_status != NULL && 
-      !strcmp(connection_status, "close")) { 
+  /* Check if server communicates with content-length */
+  content_length_str = 
+    hpairnode_get_ignore_case(res->header, HEADER_CONTENT_LENGTH);
 
-    /* Invoke callback for rest */
-    if (restsize > 0)
-      cb(0, conn, userdata, restsize, rest);
+  if (content_length_str != NULL) {
 
-    log_debug1("Server communicates with 'Connection: close' !");
+    log_debug1("Server communicates with content-length!");
+    
+    /* 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);
+    /* content length */
+    content_length = atol(content_length_str);
 
-      if (status == 0) { /* connection closed */
-	return 0; 
+    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 (status < 0) { /* error */
-	log_error2("Can nor read from socket (status: %d)", status);
-	return 11;
+
+      if (hsocket_read(conn->sock, buffer, recvSize,1)) {
+	log_error1("Can not read from socket!");
+	return 9;
+      } else {
+	cb(counter++, conn, userdata, recvSize, buffer);
       }
 
-      /* Invoke callback */ 
-      cb(counter++, conn, userdata, status, 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;
+
+  /* receive header */
+  res = httpc_receive_header(conn->sock);
+  if (res == NULL) return 1;
+
+  /* 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;
+}
+
+/*--------------------------------------------------
+  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, 
+			 httpc_response_start_callback start_cb,
+			 httpc_response_callback cb, int content_size, 
+			 char* content, void *userdata)
+{
+  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;
+  }
+
+  status = httpc_receive_response(conn, start_cb, cb, userdata);
+  return status;
+  
 }
 	
 	 
diff --git a/nanohttp/nanohttp-client.h b/nanohttp/nanohttp-client.h
index 7fad690..ed249f8 100644
--- a/nanohttp/nanohttp-client.h
+++ b/nanohttp/nanohttp-client.h
@@ -1,5 +1,5 @@
 /******************************************************************
- *  $Id: nanohttp-client.h,v 1.2 2003/12/18 11:14:37 snowdrop Exp $
+ *  $Id: nanohttp-client.h,v 1.3 2003/12/18 15:32:09 snowdrop Exp $
  *
  * CSOAP Project:  A http client/server library in C
  * Copyright (C) 2003  Ferhat Ayaz
@@ -70,7 +70,15 @@ int httpc_post_cb(httpc_conn_t *conn, const char *url,
 		  httpc_response_callback cb, int content_size, 
 		  char *content,  void *userdata);
 
-		 
+
+
+int httpc_post_open(httpc_conn_t *conn);
+int httpc_post_send(httpc_conn_t *conn, const char* buffer);
+hresponse_t *httpc_post_finish(httpc_conn_t *conn);
+int httpc_post_finish_cb(httpc_conn_t *conn, 
+			 httpc_response_start_callback start_cb,
+			 httpc_response_callback cb);
+
 
 #endif
 
diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c
index d7396d6..29c237a 100644
--- a/nanohttp/nanohttp-common.c
+++ b/nanohttp/nanohttp-common.c
@@ -1,5 +1,5 @@
 /******************************************************************
- *  $Id: nanohttp-common.c,v 1.5 2003/12/18 12:23:44 snowdrop Exp $
+ *  $Id: nanohttp-common.c,v 1.6 2003/12/18 15:32:09 snowdrop Exp $
  *
  * CSOAP Project:  A http client/server library in C
  * Copyright (C) 2003  Ferhat Ayaz
@@ -119,7 +119,7 @@ int strcmpigcase(const char *s1, const char *s2)
   l1 = strlen(s1);
   l2 = strlen(s2);
 
-  if (l1 != l2) return;
+  if (l1 != l2) return 0;
   
   for (i=0;i<l1;i++) 
     if (toupper(s1[i]) != toupper(s2[i]))
-- 
cgit v1.1-32-gdbae