introduced the new add_buffer() concept that makes the HTTP request to get
authorDaniel Stenberg <daniel@haxx.se>
Tue, 3 Oct 2000 11:01:32 +0000 (11:01 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 3 Oct 2000 11:01:32 +0000 (11:01 +0000)
sent in only one shot

lib/http.c
lib/sendf.c
lib/sendf.h

index 4e3471b..7e20894 100644 (file)
@@ -340,35 +340,41 @@ CURLcode http(struct connectdata *conn)
     http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n";
 
   do {
+    send_buffer *req_buffer;
     struct curl_slist *headers=data->headers;
-    sendf(data->firstsocket, data,
-          "%s " /* GET/HEAD/POST/PUT */
-          "%s HTTP/1.0\r\n" /* path */
-          "%s" /* proxyuserpwd */
-          "%s" /* userpwd */
-          "%s" /* range */
-          "%s" /* user agent */
-          "%s" /* cookie */
-          "%s" /* host */
-          "%s" /* pragma */
-          "%s" /* accept */
-          "%s", /* referer */
-
-          data->customrequest?data->customrequest:
-          (data->bits.no_body?"HEAD":
-           (data->bits.http_post || data->bits.http_formpost)?"POST":
-           (data->bits.http_put)?"PUT":"GET"),
-          ppath,
-          (data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
-          (data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
-          (data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
-          (data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
-          (data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
-          (data->ptr_host?data->ptr_host:""), /* Host: host */
-          http->p_pragma?http->p_pragma:"",
-          http->p_accept?http->p_accept:"",
-          (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
-          );
+
+    /* initialize a dynamic send-buffer */
+    req_buffer = add_buffer_init();
+
+    /* add the main request stuff */
+    add_bufferf(req_buffer,
+                "%s " /* GET/HEAD/POST/PUT */
+                "%s HTTP/1.0\r\n" /* path */
+                "%s" /* proxyuserpwd */
+                "%s" /* userpwd */
+                "%s" /* range */
+                "%s" /* user agent */
+                "%s" /* cookie */
+                "%s" /* host */
+                "%s" /* pragma */
+                "%s" /* accept */
+                "%s", /* referer */
+
+                data->customrequest?data->customrequest:
+                (data->bits.no_body?"HEAD":
+                 (data->bits.http_post || data->bits.http_formpost)?"POST":
+                 (data->bits.http_put)?"PUT":"GET"),
+                ppath,
+                (data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
+                (data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
+                (data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
+                (data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
+                (data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
+                (data->ptr_host?data->ptr_host:""), /* Host: host */
+                http->p_pragma?http->p_pragma:"",
+                http->p_accept?http->p_accept:"",
+                (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
+                );
 
     if(co) {
       int count=0;
@@ -376,19 +382,16 @@ CURLcode http(struct connectdata *conn)
       while(co) {
         if(co->value && strlen(co->value)) {
           if(0 == count) {
-            sendf(data->firstsocket, data,
-                  "Cookie:");
+            add_bufferf(req_buffer, "Cookie:");
           }
-          sendf(data->firstsocket, data,
-                "%s%s=%s", count?"; ":"", co->name,
-                co->value);
+          add_bufferf(req_buffer,
+                      "%s%s=%s", count?"; ":"", co->name, co->value);
           count++;
         }
         co = co->next; /* next cookie please */
       }
       if(count) {
-        sendf(data->firstsocket, data,
-              "\r\n");
+        add_buffer(req_buffer, "\r\n", 2);
       }
       cookie_freelist(co); /* free the cookie list */
       co=NULL;
@@ -419,16 +422,16 @@ CURLcode http(struct connectdata *conn)
       switch(data->timecondition) {
       case TIMECOND_IFMODSINCE:
       default:
-        sendf(data->firstsocket, data,
-              "If-Modified-Since: %s\r\n", buf);
+        add_bufferf(req_buffer,
+                    "If-Modified-Since: %s\r\n", buf);
         break;
       case TIMECOND_IFUNMODSINCE:
-        sendf(data->firstsocket, data,
-              "If-Unmodified-Since: %s\r\n", buf);
+        add_bufferf(req_buffer,
+                    "If-Unmodified-Since: %s\r\n", buf);
         break;
       case TIMECOND_LASTMOD:
-        sendf(data->firstsocket, data,
-              "Last-Modified: %s\r\n", buf);
+        add_bufferf(req_buffer,
+                    "Last-Modified: %s\r\n", buf);
         break;
       }
     }
@@ -445,9 +448,7 @@ CURLcode http(struct connectdata *conn)
         if(*ptr) {
           /* only send this if the contents was non-blank */
 
-          sendf(data->firstsocket, data,
-                "%s\015\012",
-                headers->data);
+          add_bufferf(req_buffer, "%s\r\n", headers->data);
         }
       }
       headers = headers->next;
@@ -468,12 +469,13 @@ CURLcode http(struct connectdata *conn)
                        generated form data */
       data->in = (FILE *)&http->form;
 
-      sendf(data->firstsocket, data,
-            "Content-Length: %d\r\n",
-            http->postsize-2);
+      add_bufferf(req_buffer,
+                  "Content-Length: %d\r\n", http->postsize-2);
 
+      /* set upload size to the progress meter */
       pgrsSetUploadSize(data, http->postsize);
 
+      add_buffer_send(data->firstsocket, conn, req_buffer);
       result = Transfer(conn, data->firstsocket, -1, TRUE,
                         &http->readbytecount,
                           data->firstsocket,
@@ -487,16 +489,20 @@ CURLcode http(struct connectdata *conn)
       /* Let's PUT the data to the server! */
 
       if(data->infilesize>0) {
-        sendf(data->firstsocket, data,
-              "Content-Length: %d\r\n\r\n", /* file size */
-              data->infilesize );
+        add_bufferf(req_buffer,
+                    "Content-Length: %d\r\n\r\n", /* file size */
+                    data->infilesize );
       }
       else
-        sendf(data->firstsocket, data,
-              "\015\012");
+        add_bufferf(req_buffer, "\015\012");
 
+      /* set the upload size to the progress meter */
       pgrsSetUploadSize(data, data->infilesize);
 
+      /* this sends the buffer and frees all the buffer resources */
+      add_buffer_send(data->firstsocket, conn, req_buffer);
+
+      /* prepare for transfer */
       result = Transfer(conn, data->firstsocket, -1, TRUE,
                         &http->readbytecount,
                         data->firstsocket,
@@ -512,30 +518,34 @@ CURLcode http(struct connectdata *conn)
         if(!checkheaders(data, "Content-Length:"))
           /* we allow replacing this header, although it isn't very wise to
              actually set your own */
-          sendf(data->firstsocket, data,
-                "Content-Length: %d\r\n",
-                (data->postfieldsize?data->postfieldsize:
-                 strlen(data->postfields)) );
+          add_bufferf(req_buffer,
+                      "Content-Length: %d\r\n",
+                      (data->postfieldsize?data->postfieldsize:
+                       strlen(data->postfields)) );
 
         if(!checkheaders(data, "Content-Type:"))
-          sendf(data->firstsocket, data,
-                "Content-Type: application/x-www-form-urlencoded\r\n");
+          add_bufferf(req_buffer,
+                      "Content-Type: application/x-www-form-urlencoded\r\n");
 
         /* and here comes the actual data */
         if(data->postfieldsize) {
-          ssend(data->firstsocket, conn, "\r\n", 2);
-          ssend(data->firstsocket, conn, data->postfields, data->postfieldsize);
-          ssend(data->firstsocket, conn, "\r\n", 2);
+          add_buffer(req_buffer, "\r\n", 2);
+          add_buffer(req_buffer, data->postfields,
+                     data->postfieldsize);
+          add_buffer(req_buffer, "\r\n", 2);
+        }
+        else {
+          add_bufferf(req_buffer,
+                      "\r\n"
+                      "%s\r\n",
+                      data->postfields );
         }
-        sendf(data->firstsocket, data,
-              "\r\n"
-              "%s\r\n",
-              data->postfields );
       }
       else
-        sendf(data->firstsocket, data, "\r\n");
+        add_buffer(req_buffer, "\r\n", 2);
 
       /* HTTP GET/HEAD download: */
+      add_buffer_send(data->firstsocket, conn, req_buffer);
       result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount,
                         -1, NULL); /* nothing to upload */
     }
index 77f403d..8042ac8 100644 (file)
@@ -53,6 +53,7 @@
 
 #include <curl/curl.h>
 #include "urldata.h"
+#include "sendf.h"
 
 #include <curl/mprintf.h>
 
@@ -89,7 +90,7 @@ void failf(struct UrlData *data, char *fmt, ...)
 }
 
 /* sendf() sends the formated data to the server */
-int sendf(int fd, struct UrlData *data, char *fmt, ...)
+size_t sendf(int fd, struct UrlData *data, char *fmt, ...)
 {
   size_t bytes_written;
   char *s;
@@ -118,7 +119,7 @@ int sendf(int fd, struct UrlData *data, char *fmt, ...)
 /*
  * ftpsendf() sends the formated string as a ftp command to a ftp server
  */
-int ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
+size_t ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
 {
   size_t bytes_written;
   char *s;
@@ -154,9 +155,6 @@ size_t ssend(int fd, struct connectdata *conn, void *mem, size_t len)
   size_t bytes_written;
   struct UrlData *data=conn->data; /* conn knows data, not vice versa */
 
-  if(data->bits.verbose)
-    fprintf(data->err, "> [binary output]\n");
-
 #ifdef USE_SSLEAY
   if (data->use_ssl) {
     bytes_written = SSL_write(data->ssl, mem, len);
@@ -177,6 +175,88 @@ size_t ssend(int fd, struct connectdata *conn, void *mem, size_t len)
   return bytes_written;
 }
 
+/*
+ * add_buffer_init() returns a fine buffer struct
+ */
+send_buffer *add_buffer_init(void)
+{
+  send_buffer *blonk;
+  blonk=(send_buffer *)malloc(sizeof(send_buffer));
+  if(blonk) {
+    memset(blonk, 0, sizeof(send_buffer));
+    return blonk;
+  }
+  return NULL; /* failed, go home */
+}
+
+/*
+ * add_buffer_send() sends a buffer and frees all associated memory.
+ */
+size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in)
+{
+  if(in->buffer)
+    free(in->buffer);
+  free(in);
+
+  if(conn->data->bits.verbose) {
+    fputs("> ", conn->data->err);
+    /* this data _may_ contain binary stuff */
+    fwrite(in->buffer, in->size_used, 1, conn->data->err);
+  }
 
+  return ssend(sockfd, conn, in->buffer, in->size_used);
+}
 
 
+/* 
+ * add_bufferf() builds a buffer from the formatted input
+ */
+CURLcode add_bufferf(send_buffer *in, char *fmt, ...)
+{
+  CURLcode result = CURLE_OUT_OF_MEMORY;
+  char *s;
+  va_list ap;
+  va_start(ap, fmt);
+  s = mvaprintf(fmt, ap); /* this allocs a new string to append */
+  va_end(ap);
+
+  if(s) {
+    result = add_buffer(in, s, strlen(s));
+    free(s);
+  }
+  return result;
+}
+
+/*
+ * add_buffer() appends a memory chunk to the existing one
+ */
+CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
+{
+  char *new_rb;
+  int new_size;
+
+  if(size > 0) {
+    if(!in->buffer ||
+       ((in->size_used + size) > (in->size_max - 1))) {
+      new_size = (in->size_used+size)*2;
+      if(in->buffer)
+        /* we have a buffer, enlarge the existing one */
+        new_rb = (char *)realloc(in->buffer, new_size);
+      else
+        /* create a new buffer */
+        new_rb = (char *)malloc(new_size);
+
+      if(!new_rb)
+        return CURLE_OUT_OF_MEMORY;
+
+      in->buffer = new_rb;
+      in->size_max = new_size;
+    }
+    memcpy(&in->buffer[in->size_used], inptr, size);
+      
+    in->size_used += size;
+  }
+
+  return CURLE_OK;
+}
+
index 91af88f..0ff305e 100644 (file)
@@ -46,4 +46,18 @@ size_t ssend(int fd, struct connectdata *, void *fmt, size_t len);
 void infof(struct UrlData *, char *fmt, ...);
 void failf(struct UrlData *, char *fmt, ...);
 
+struct send_buffer {
+  char *buffer;
+  long size_max;
+  long size_used;
+};
+typedef struct send_buffer send_buffer;
+
+
+send_buffer *add_buffer_init(void);
+CURLcode add_buffer(send_buffer *in, void *inptr, size_t size);
+CURLcode add_bufferf(send_buffer *in, char *fmt, ...);
+size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in);
+
+
 #endif