summaryrefslogtreecommitdiff
path: root/lib/gopher.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2010-08-24 23:14:00 +0200
committerDaniel Stenberg <daniel@haxx.se>2010-08-25 14:21:25 +0200
commitcb64c987a062a9c16ab997415a1440182edb069a (patch)
tree93a2d9084e84e58608d1dfa1cdeb7fb6f994395a /lib/gopher.c
parent67d16160184493c6717e4e572fafed7467af4983 (diff)
downloadcurl-cb64c987a062a9c16ab997415a1440182edb069a.tar.gz
gopher: fix memory leak and busyloop
The fix for the busyloop really only is a temporary work-around. It causes a BLOCKING behavior which is a NO-NO. This function should rather be split up in a do and a doing piece where the pieces that aren't possible to send now will be sent in the doing function repeatedly until the entire request is sent.
Diffstat (limited to 'lib/gopher.c')
-rw-r--r--lib/gopher.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/lib/gopher.c b/lib/gopher.c
index 2fab6dabe..6fe740f75 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -76,6 +76,8 @@
#include "strequal.h"
#include "gopher.h"
#include "rawstr.h"
+#include "select.h"
+#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -122,6 +124,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
curl_off_t *bytecount = &data->req.bytecount;
char *path = data->state.path;
char *sel;
+ char *sel_org = NULL;
ssize_t amount, k;
*done = TRUE; /* unconditionally */
@@ -139,19 +142,21 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
/* ... then turn ? into TAB for search servers, Veronica, etc. ... */
j = strlen(newp);
- if (j)
- for(i=0; i<j; i++)
- newp[i] = ((newp[i] == '?') ? '\x09' : newp[i]);
+ for(i=0; i<j; i++)
+ if(newp[i] == '?')
+ newp[i] = '\x09';
/* ... and finally unescape */
sel = curl_easy_unescape(data, newp, 0, &len);
if (!sel)
return CURLE_OUT_OF_MEMORY;
+ sel_org = sel;
}
- /* We use Curl_write instead of Curl_sendf to make sure the entire buffer
- is sent, which could be sizeable with long selectors. */
+ /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is
+ sent, which could be sizeable with long selectors. */
k = strlen(sel);
+
for(;;) {
result = Curl_write(conn, sockfd, sel, k, &amount);
if (CURLE_OK == result) { /* Which may not have written it all! */
@@ -159,11 +164,26 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
sel += amount;
if (k < 1)
break; /* but it did write it all */
- } else {
+ }
+ else {
failf(data, "Failed sending Gopher request");
+ Curl_safefree(sel_org);
return result;
}
+ /* Don't busyloop. The entire loop thing is a work-around as it causes a
+ BLOCKING behavior which is a NO-NO. This function should rather be
+ split up in a do and a doing piece where the pieces that aren't
+ possible to send now will be sent in the doing function repeatedly
+ until the entire request is sent.
+
+ Wait a while for the socket to be writable. Note that this doesn't
+ acknowledge the timeout.
+ */
+ Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 100);
}
+
+ Curl_safefree(sel_org);
+
/* We can use Curl_sendf to send the terminal \r\n relatively safely and
save allocing another string/doing another _write loop. */
result = Curl_sendf(sockfd, conn, "\r\n");