]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
pingpong: use a dynbuf for the *_pp_sendf() function
authorDaniel Stenberg <daniel@haxx.se>
Wed, 23 Sep 2020 07:22:02 +0000 (09:22 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 23 Sep 2020 13:14:09 +0000 (15:14 +0200)
... reuses the same dynamic buffer instead of doing repeated malloc/free
cycles.

Test case 100 (FTP dir list PASV) does 7 fewer memory allocation calls
after this change in my test setup (132 => 125), curl 7.72.0 needed 140
calls for this.

Test case 103 makes 9 less allocations now (130). Down from 149 in
7.72.0.

Closes #6004

lib/ftp.c
lib/imap.c
lib/pingpong.c
lib/pingpong.h
lib/pop3.c
lib/smtp.c

index a672875d36674f986b147581056049e762cb1232..a5083be04dd67635fdd16de835d7003e40a8c06f 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -3112,6 +3112,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
       return result;
   }
 
+  Curl_pp_setup(pp); /* once per transfer */
   Curl_pp_init(pp); /* init the generic pingpong data */
 
   /* When we connect, we start in the state where we await the 220
index b9b14d10e14ad99f682409ec4becfa5cf90d1c3b..02fc796e474367c0f0a7cee706b991157fea7503 100644 (file)
@@ -1430,6 +1430,7 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
   Curl_sasl_init(&imapc->sasl, &saslimap);
 
   /* Initialise the pingpong layer */
+  Curl_pp_setup(pp);
   Curl_pp_init(pp);
 
   /* Parse the URL options */
index 1cfd0286e6644443772f32c8a48253c6d9305aec..5a06674ad102002ffa5bf8a7eb4d1ed2effe7893 100644 (file)
@@ -146,7 +146,11 @@ void Curl_pp_init(struct pingpong *pp)
   pp->response = Curl_now(); /* start response time-out now! */
 }
 
-
+/* setup for the coming transfer */
+void Curl_pp_setup(struct pingpong *pp)
+{
+  Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
+}
 
 /***********************************************************************
  *
@@ -164,8 +168,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
 {
   ssize_t bytes_written = 0;
   size_t write_len;
-  char fmt_crlf[128];
-  size_t fmtlen;
   char *s;
   CURLcode result;
   struct connectdata *conn = pp->conn;
@@ -182,49 +184,42 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
   if(!conn)
     /* can't send without a connection! */
     return CURLE_SEND_ERROR;
-
   data = conn->data;
 
-  fmtlen = strlen(fmt);
-  DEBUGASSERT(fmtlen < sizeof(fmt_crlf)-3);
-  if(fmtlen >= sizeof(fmt_crlf)-3)
-    return CURLE_BAD_FUNCTION_ARGUMENT;
-  memcpy(fmt_crlf, fmt, fmtlen);
-  /* append a trailing CRLF+null to the format string */
-  memcpy(&fmt_crlf[fmtlen], "\r\n", 3);
-  s = vaprintf(fmt_crlf, args);
-  if(!s)
-    return CURLE_OUT_OF_MEMORY;
+  Curl_dyn_reset(&pp->sendbuf);
+  result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args);
+  if(result)
+    return result;
 
-  write_len = strlen(s);
+  /* append CRLF */
+  result = Curl_dyn_addn(&pp->sendbuf, "\r\n", 2);
+  if(result)
+    return result;
 
+  write_len = Curl_dyn_len(&pp->sendbuf);
+  s = Curl_dyn_ptr(&pp->sendbuf);
   Curl_pp_init(pp);
 
   result = Curl_convert_to_network(data, s, write_len);
   /* Curl_convert_to_network calls failf if unsuccessful */
-  if(result) {
-    free(s);
+  if(result)
     return result;
-  }
 
 #ifdef HAVE_GSSAPI
   conn->data_prot = PROT_CMD;
 #endif
   result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
-                     &bytes_written);
+                      &bytes_written);
+  if(result)
+    return result;
 #ifdef HAVE_GSSAPI
   data_sec = conn->data_prot;
   DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
   conn->data_prot = data_sec;
 #endif
 
-  if(result) {
-    free(s);
-    return result;
-  }
-
-  if(conn->data->set.verbose)
-    Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
+  if(data->set.verbose)
+    Curl_debug(data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
 
   if(bytes_written != (ssize_t)write_len) {
     /* the whole chunk was not sent, keep it around and adjust sizes */
@@ -233,7 +228,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
     pp->sendleft = write_len - bytes_written;
   }
   else {
-    free(s);
     pp->sendthis = NULL;
     pp->sendleft = pp->sendsize = 0;
     pp->response = Curl_now();
@@ -495,7 +489,6 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
     pp->sendleft -= written;
   }
   else {
-    free(pp->sendthis);
     pp->sendthis = NULL;
     pp->sendleft = pp->sendsize = 0;
     pp->response = Curl_now();
@@ -505,15 +498,15 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
 
 CURLcode Curl_pp_disconnect(struct pingpong *pp)
 {
-  free(pp->cache);
-  pp->cache = NULL;
+  Curl_dyn_free(&pp->sendbuf);
+  Curl_safefree(pp->cache);
   return CURLE_OK;
 }
 
 bool Curl_pp_moredata(struct pingpong *pp)
 {
   return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
-         TRUE : FALSE;
+    TRUE : FALSE;
 }
 
 #endif
index e874799d44101ad1dd6b234c47835fedbe1c121c..855815afd5510437044093370a7524819ba79aec 100644 (file)
@@ -64,6 +64,7 @@ struct pingpong {
                                milliseconds we await for a server response. */
   struct connectdata *conn; /* points to the connectdata struct that this
                                belongs to */
+  struct dynbuf sendbuf;
 
   /* Function pointers the protocols MUST implement and provide for the
      pingpong layer to function */
@@ -86,6 +87,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
 /* initialize stuff to prepare for reading a fresh new response */
 void Curl_pp_init(struct pingpong *pp);
 
+/* setup for the transfer */
+void Curl_pp_setup(struct pingpong *pp);
+
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
 timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
index be27484723ad99b3d83a7da4ac67b8a264f5bb89..5a73545823f9ff1a56fb9ed939185c2bdfc1eb8a 100644 (file)
@@ -1093,6 +1093,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
   Curl_sasl_init(&pop3c->sasl, &saslpop3);
 
   /* Initialise the pingpong layer */
+  Curl_pp_setup(pp);
   Curl_pp_init(pp);
 
   /* Parse the URL options */
index c2d63232297c4d479213d0d3b3c2bdcce2f892e4..49743c03699a56b39d93382090e6d445d52dcfe8 100644 (file)
@@ -1324,6 +1324,7 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
   Curl_sasl_init(&smtpc->sasl, &saslsmtp);
 
   /* Initialise the pingpong layer */
+  Curl_pp_setup(pp);
   Curl_pp_init(pp);
 
   /* Parse the URL options */