Esempio n. 1
0
/* return 0 on success, non-zero on failure */
static int get_request(curl_socket_t sock, struct httprequest *req)
{
  int error;
  int fail = 0;
  int done_processing = 0;
  char *reqbuf = req->reqbuf;
  ssize_t got = 0;

  char *pipereq = NULL;
  size_t pipereq_length = 0;

  if(req->pipelining) {
    pipereq = reqbuf + req->checkindex;
    pipereq_length = req->offset - req->checkindex;
  }

  /*** Init the httprequest structure properly for the upcoming request ***/

  req->checkindex = 0;
  req->offset = 0;
  req->testno = DOCNUMBER_NOTHING;
  req->partno = 0;
  req->open = TRUE;
  req->auth_req = FALSE;
  req->auth = FALSE;
  req->cl = 0;
  req->digest = FALSE;
  req->ntlm = FALSE;
  req->pipe = 0;
  req->skip = 0;
  req->rcmd = RCMD_NORMALREQ;
  req->protocol = RPROT_NONE;
  req->prot_version = 0;
  req->pipelining = FALSE;
  req->rtp_buffer = NULL;
  req->rtp_buffersize = 0;

  /*** end of httprequest init ***/

  while(!done_processing && (req->offset < REQBUFSIZ-1)) {
    if(pipereq_length && pipereq) {
      memmove(reqbuf, pipereq, pipereq_length);
      got = curlx_uztosz(pipereq_length);
      pipereq_length = 0;
    }
    else {
      if(req->skip)
        /* we are instructed to not read the entire thing, so we make sure to only
           read what we're supposed to and NOT read the enire thing the client
           wants to send! */
        got = sread(sock, reqbuf + req->offset, req->cl);
      else
        got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
    }
    if(got_exit_signal)
      return 1;
    if(got == 0) {
      logmsg("Connection closed by client");
      fail = 1;
    }
    else if(got < 0) {
      error = SOCKERRNO;
      logmsg("recv() returned error: (%d) %s", error, strerror(error));
      fail = 1;
    }
    if(fail) {
      /* dump the request received so far to the external file */
      reqbuf[req->offset] = '\0';
      storerequest(reqbuf, req->offset);
      return 1;
    }

    logmsg("Read %zd bytes", got);

    req->offset += (size_t)got;
    reqbuf[req->offset] = '\0';

    done_processing = ProcessRequest(req);
    if(got_exit_signal)
      return 1;
    if(done_processing && req->pipe) {
      logmsg("Waiting for another piped request");
      done_processing = 0;
      req->pipe--;
    }
  }

  if((req->offset == REQBUFSIZ-1) && (got > 0)) {
    logmsg("Request would overflow buffer, closing connection");
    /* dump request received so far to external file anyway */
    reqbuf[REQBUFSIZ-1] = '\0';
    fail = 1;
  }
  else if(req->offset > REQBUFSIZ-1) {
    logmsg("Request buffer overflow, closing connection");
    /* dump request received so far to external file anyway */
    reqbuf[REQBUFSIZ-1] = '\0';
    fail = 1;
  }
  else
    reqbuf[req->offset] = '\0';

  /* dump the request to an external file */
  storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
  if(got_exit_signal)
    return 1;

  return fail; /* return 0 on success */
}
Esempio n. 2
0
static CURLcode gopher_do(struct connectdata *conn, bool *done)
{
  CURLcode result=CURLE_OK;
  struct SessionHandle *data=conn->data;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];

  curl_off_t *bytecount = &data->req.bytecount;
  char *path = data->state.path;
  char *sel;
  char *sel_org = NULL;
  ssize_t amount, k;
  int len;

  *done = TRUE; /* unconditionally */

  /* Create selector. Degenerate cases: / and /1 => convert to "" */
  if(strlen(path) <= 2) {
    sel = (char *)"";
    len = (int)strlen(sel);
  }
  else {
    char *newp;
    size_t j, i;

    /* Otherwise, drop / and the first character (i.e., item type) ... */
    newp = path;
    newp+=2;

    /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
    j = strlen(newp);
    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. */
  k = curlx_uztosz(len);

  for(;;) {
    result = Curl_write(conn, sockfd, sel, k, &amount);
    if(!result) { /* Which may not have written it all! */
      result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
      if(result) {
        free(sel_org);
        return result;
      }
      k -= amount;
      sel += amount;
      if(k < 1)
        break; /* but it did write it all */
    }
    else {
      failf(data, "Failed sending Gopher request");
      free(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);
  }

  free(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");
  if(result) {
    failf(data, "Failed sending Gopher request");
    return result;
  }
  result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
  if(result)
    return result;

  Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
                      -1, NULL); /* no upload */
  return CURLE_OK;
}