Exemple #1
0
/*
 * Curl_write() is an internal write function that sends data to the
 * server. Works with plain sockets, SCP, SSL or kerberos.
 */
CURLcode Curl_write(struct connectdata *conn,
                    curl_socket_t sockfd,
                    const void *mem,
                    size_t len,
                    ssize_t *written)
{
  ssize_t bytes_written;
  CURLcode retcode;
  int num = (sockfd == conn->sock[SECONDARYSOCKET]);

  if(conn->ssl[num].state == ssl_connection_complete)
    bytes_written = Curl_ssl_send(conn, num, mem, len);
  else if(Curl_ssh_enabled(conn, PROT_SCP))
    bytes_written = Curl_scp_send(conn, num, mem, len);
  else if(Curl_ssh_enabled(conn, PROT_SFTP))
    bytes_written = Curl_sftp_send(conn, num, mem, len);
  else if(conn->sec_complete)
    bytes_written = Curl_sec_send(conn, num, mem, len);
  else
    bytes_written = send_plain(conn, num, mem, len);

  *written = bytes_written;
  retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;

  return retcode;
}
Exemple #2
0
/*
 * Curl_write() is an internal write function that sends data to the
 * server. Works with plain sockets, SCP, SSL or kerberos.
 *
 * If the write would block (EWOULDBLOCK), we return CURLE_OK and
 * (*written == 0). Otherwise we return regular CURLcode value.
 */
CURLcode Curl_write(struct connectdata *conn,
                    curl_socket_t sockfd,
                    const void *mem,
                    size_t len,
                    ssize_t *written)
{
  ssize_t bytes_written;
  int curlcode = CURLE_OK;
  int num = (sockfd == conn->sock[SECONDARYSOCKET]);

  if(conn->ssl[num].state == ssl_connection_complete)
    bytes_written = Curl_ssl_send(conn, num, mem, len, &curlcode);
  else if(Curl_ssh_enabled(conn, PROT_SCP))
    bytes_written = Curl_scp_send(conn, num, mem, len);
  else if(Curl_ssh_enabled(conn, PROT_SFTP))
    bytes_written = Curl_sftp_send(conn, num, mem, len);
  else if(conn->sec_complete)
    bytes_written = Curl_sec_send(conn, num, mem, len);
  else
    bytes_written = send_plain(conn, num, mem, len);

  *written = bytes_written;
  if(-1 != bytes_written)
    /* we completely ignore the curlcode value when -1 is not returned */
    return CURLE_OK;

  /* handle EWOULDBLOCK or a send failure */
  switch(curlcode) {
  case /* EWOULDBLOCK */ -1:
    *written = /* EWOULDBLOCK */ 0;
    return CURLE_OK;

  case CURLE_OK:
    /* general send failure */
    return CURLE_SEND_ERROR;

  default:
    /* we got a specific curlcode, forward it */
    return (CURLcode)curlcode;
  }
}
Exemple #3
0
/*
 * Internal read-from-socket function. This is meant to deal with plain
 * sockets, SSL sockets and kerberos sockets.
 *
 * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
 * a regular CURLcode value.
 */
int Curl_read(struct connectdata *conn, /* connection data */
              curl_socket_t sockfd,     /* read from this socket */
              char *buf,                /* store read data here */
              size_t sizerequested,     /* max amount to read */
              ssize_t *n)               /* amount bytes read */
{
  ssize_t nread = 0;
  size_t bytesfromsocket = 0;
  char *buffertofill = NULL;
  bool pipelining = (bool)(conn->data->multi &&
                     Curl_multi_canPipeline(conn->data->multi));

  /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
     If it is the second socket, we set num to 1. Otherwise to 0. This lets
     us use the correct ssl handle. */
  int num = (sockfd == conn->sock[SECONDARYSOCKET]);

  *n=0; /* reset amount to zero */

  /* If session can pipeline, check connection buffer  */
  if(pipelining) {
    size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);

    /* Copy from our master buffer first if we have some unread data there*/
    if(bytestocopy > 0) {
      memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
      conn->read_pos += bytestocopy;
      conn->bits.stream_was_rewound = FALSE;

      *n = (ssize_t)bytestocopy;
      return CURLE_OK;
    }
    /* If we come here, it means that there is no data to read from the buffer,
     * so we read from the socket */
    bytesfromsocket = MIN(sizerequested, BUFSIZE * sizeof (char));
    buffertofill = conn->master_buffer;
  }
  else {
    bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
                          conn->data->set.buffer_size : BUFSIZE);
    buffertofill = buf;
  }

  if(conn->ssl[num].state == ssl_connection_complete) {
    nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);

    if(nread == -1) {
      return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
    }
  }
  else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
    if(conn->protocol & PROT_SCP)
      nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
    else if(conn->protocol & PROT_SFTP)
      nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
#ifdef LIBSSH2CHANNEL_EAGAIN
    if((nread == LIBSSH2CHANNEL_EAGAIN) || (nread == 0))
      /* EWOULDBLOCK */
      return -1;
#endif
    if(nread < 0)
      /* since it is negative and not EAGAIN, it was a protocol-layer error */
      return CURLE_RECV_ERROR;
  }
  else {
    if(conn->sec_complete)
      nread = Curl_sec_read(conn, sockfd, buffertofill,
                            bytesfromsocket);
    /* TODO: Need to handle EAGAIN here somehow, similar to how it
     * is done in Curl_read_plain, either right here or in Curl_sec_read
     * itself. */
    else {
      int ret = Curl_read_plain(sockfd, buffertofill, bytesfromsocket,
                                     &nread);
      if(ret)
        return ret;
    }
  }
  if(nread >= 0) {
    if(pipelining) {
      memcpy(buf, conn->master_buffer, nread);
      conn->buf_len = nread;
      conn->read_pos = nread;
    }

    *n += nread;
  }

  return CURLE_OK;
}