summaryrefslogtreecommitdiffstats
path: root/Source/CTest/Curl/sendf.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest/Curl/sendf.c')
-rw-r--r--Source/CTest/Curl/sendf.c239
1 files changed, 155 insertions, 84 deletions
diff --git a/Source/CTest/Curl/sendf.c b/Source/CTest/Curl/sendf.c
index 01cfb23..7d0f71d 100644
--- a/Source/CTest/Curl/sendf.c
+++ b/Source/CTest/Curl/sendf.c
@@ -1,16 +1,16 @@
/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
- *
+ *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
@@ -39,25 +39,22 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
-#include <winsock.h>
-#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
+#include "connect.h" /* for the Curl_ourerrno() proto */
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
-#ifdef KRB4
+#ifdef HAVE_KRB4
#include "security.h"
#endif
#include <string.h>
+#include "memory.h"
/* The last #include file should be: */
-#ifdef MALLOCDEBUG
#include "memdebug.h"
-#endif
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
@@ -76,11 +73,13 @@ static struct curl_slist *slist_get_last(struct curl_slist *list)
return item;
}
-/* append a struct to the linked list. It always retunrs the address of the
- * first record, so that you can sure this function as an initialization
- * function as well as an append function. If you find this bothersome,
- * then simply create a separate _init function and call it appropriately from
- * within the proram. */
+/*
+ * curl_slist_append() appends a string to the linked list. It always retunrs
+ * the address of the first record, so that you can sure this function as an
+ * initialization function as well as an append function. If you find this
+ * bothersome, then simply create a separate _init function and call it
+ * appropriately from within the proram.
+ */
struct curl_slist *curl_slist_append(struct curl_slist *list,
const char *data)
{
@@ -89,13 +88,18 @@ struct curl_slist *curl_slist_append(struct curl_slist *list,
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
- new_item->next = NULL;
- new_item->data = strdup(data);
+ char *dup = strdup(data);
+ if(dup) {
+ new_item->next = NULL;
+ new_item->data = dup;
+ }
+ else {
+ free(new_item);
+ return NULL;
+ }
}
- if (new_item == NULL || new_item->data == NULL) {
- fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
+ else
return NULL;
- }
if (list) {
last = slist_get_last(list);
@@ -119,7 +123,7 @@ void curl_slist_free_all(struct curl_slist *list)
item = list;
do {
next = item->next;
-
+
if (item->data) {
free(item->data);
}
@@ -132,13 +136,13 @@ void curl_slist_free_all(struct curl_slist *list)
void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
{
- va_list ap;
- if(data->set.verbose) {
+ if(data && data->set.verbose) {
+ va_list ap;
char print_buffer[1024 + 1];
va_start(ap, fmt);
vsnprintf(print_buffer, 1024, fmt, ap);
va_end(ap);
- Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer));
+ Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer), NULL);
}
}
@@ -155,14 +159,14 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
data->state.errorbuf = TRUE; /* wrote error string */
if(data->set.verbose) {
- int len = (int)strlen(data->set.errorbuffer);
+ size_t len = strlen(data->set.errorbuffer);
bool doneit=FALSE;
- if(len < CURL_ERROR_SIZE) {
+ if(len < CURL_ERROR_SIZE - 1) {
doneit = TRUE;
data->set.errorbuffer[len] = '\n';
data->set.errorbuffer[++len] = '\0';
}
- Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len);
+ Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len, NULL);
if(doneit)
/* cut off the newline again */
data->set.errorbuffer[--len]=0;
@@ -172,12 +176,12 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
}
/* Curl_sendf() sends formated data to the server */
-CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
+CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
const char *fmt, ...)
{
struct SessionHandle *data = conn->data;
ssize_t bytes_written;
- ssize_t write_len;
+ size_t write_len;
CURLcode res;
char *s;
char *sptr;
@@ -189,10 +193,10 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
return CURLE_OUT_OF_MEMORY; /* failure */
bytes_written=0;
- write_len = (int)strlen(s);
+ write_len = strlen(s);
sptr = s;
- do {
+ while (1) {
/* Write the buffer to the socket */
res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
@@ -200,9 +204,10 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
break;
if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written);
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written,
+ conn->host.dispname);
- if(bytes_written != write_len) {
+ if((size_t)bytes_written != write_len) {
/* if not all was written at once, we must advance the pointer, decrease
the size left and try again! */
write_len -= bytes_written;
@@ -210,8 +215,7 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
}
else
break;
-
- } while(1);
+ }
free(s); /* free the output string */
@@ -221,33 +225,51 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
/*
* Curl_write() is an internal write function that sends plain (binary) data
* to the server. Works with plain sockets, SSL or kerberos.
- *
*/
-CURLcode Curl_write(struct connectdata *conn, int sockfd,
- void *mem, size_t len,
+CURLcode Curl_write(struct connectdata *conn,
+ curl_socket_t sockfd,
+ void *mem,
+ size_t len,
ssize_t *written)
{
ssize_t bytes_written;
- (void)conn;
+ CURLcode retcode;
#ifdef USE_SSLEAY
+ /* 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]);
/* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */
- if (conn->ssl.use) {
+ if (conn->ssl[num].use) {
int err;
- int rc = SSL_write(conn->ssl.handle, mem, len);
+ char error_buffer[120]; /* OpenSSL documents that this must be at least
+ 120 bytes long. */
+ unsigned long sslerror;
+ int rc = SSL_write(conn->ssl[num].handle, mem, (int)len);
if(rc < 0) {
- err = SSL_get_error(conn->ssl.handle, rc);
-
+ err = SSL_get_error(conn->ssl[num].handle, rc);
+
switch(err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
- /* this is basicly the EWOULDBLOCK equivalent */
+ /* The operation did not complete; the same TLS/SSL I/O function
+ should be called again later. This is basicly an EWOULDBLOCK
+ equivalent. */
*written = 0;
return CURLE_OK;
case SSL_ERROR_SYSCALL:
- failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n", errno);
+ failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
+ Curl_ourerrno());
+ return CURLE_SEND_ERROR;
+ case SSL_ERROR_SSL:
+ /* A failure in the SSL library occurred, usually a protocol error.
+ The OpenSSL error queue contains more information on the error. */
+ sslerror = ERR_get_error();
+ failf(conn->data, "SSL_write() error: %s\n",
+ ERR_error_string(sslerror, error_buffer));
return CURLE_SEND_ERROR;
}
/* a true error */
@@ -257,34 +279,44 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
bytes_written = rc;
}
else {
+#else
+ (void)conn;
#endif
-#ifdef KRB4
+#ifdef HAVE_KRB4
if(conn->sec_complete) {
bytes_written = Curl_sec_write(conn, sockfd, mem, len);
}
else
-#endif /* KRB4 */
+#endif /* HAVE_KRB4 */
{
- bytes_written = (int)swrite(sockfd, mem, (int)len);
+ bytes_written = (ssize_t)swrite(sockfd, mem, len);
}
if(-1 == bytes_written) {
-#ifdef WIN32
- if(WSAEWOULDBLOCK == GetLastError())
+ int err = Curl_ourerrno();
+
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == err)
#else
- if(EWOULDBLOCK == errno)
+ /* As pointed out by Christophe Demory on March 11 2003, errno
+ may be EWOULDBLOCK or on some systems EAGAIN when it returned
+ due to its inability to send off data without blocking. We
+ therefor treat both error codes the same here */
+ (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
- {
+ )
/* this is just a case of EWOULDBLOCK */
- *written=0;
- return CURLE_OK;
- }
+ bytes_written=0;
}
#ifdef USE_SSLEAY
}
#endif
*written = bytes_written;
- return (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
+ retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
+
+ return retcode;
}
/* client_write() sends data to the write callback(s)
@@ -324,7 +356,7 @@ CURLcode Curl_client_write(struct SessionHandle *data,
return CURLE_WRITE_ERROR;
}
}
-
+
return CURLE_OK;
}
@@ -335,23 +367,27 @@ CURLcode Curl_client_write(struct SessionHandle *data,
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
*/
-int Curl_read(struct connectdata *conn,
- int sockfd,
- char *buf,
- size_t buffersize,
- ssize_t *n)
+int Curl_read(struct connectdata *conn, /* connection data */
+ curl_socket_t sockfd, /* read from this socket */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ ssize_t *n) /* amount bytes read */
{
ssize_t nread;
+#ifdef USE_SSLEAY
+ /* 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 */
- (void)conn;
-#ifdef USE_SSLEAY
- if (conn->ssl.use) {
- nread = SSL_read(conn->ssl.handle, buf, buffersize);
+ if (conn->ssl[num].use) {
+ nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, (int)buffersize);
if(nread < 0) {
/* failed SSL_read */
- int err = SSL_get_error(conn->ssl.handle, nread);
+ int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
@@ -362,25 +398,37 @@ int Curl_read(struct connectdata *conn,
/* there's data pending, re-invoke SSL_read() */
return -1; /* basicly EWOULDBLOCK */
default:
- failf(conn->data, "SSL read error: %d", err);
+ /* openssl/ssl.h says "look at error stack/return value/errno" */
+ {
+ char error_buffer[120]; /* OpenSSL documents that this must be at
+ least 120 bytes long. */
+ unsigned long sslerror = ERR_get_error();
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(sslerror, error_buffer),
+ Curl_ourerrno() );
+ }
return CURLE_RECV_ERROR;
}
}
}
else {
+#else
+ (void)conn;
#endif
-#ifdef KRB4
+ *n=0; /* reset amount to zero */
+#ifdef HAVE_KRB4
if(conn->sec_complete)
nread = Curl_sec_read(conn, sockfd, buf, buffersize);
else
#endif
- nread = sread (sockfd, buf, (int)buffersize);
+ nread = sread(sockfd, buf, buffersize);
if(-1 == nread) {
+ int err = Curl_ourerrno();
#ifdef WIN32
- if(WSAEWOULDBLOCK == GetLastError())
+ if(WSAEWOULDBLOCK == err)
#else
- if(EWOULDBLOCK == errno)
+ if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
#endif
return -1;
}
@@ -393,11 +441,11 @@ int Curl_read(struct connectdata *conn,
}
/* return 0 on success */
-int Curl_debug(struct SessionHandle *data, curl_infotype type,
- char *ptr, size_t size)
+static int showit(struct SessionHandle *data, curl_infotype type,
+ char *ptr, size_t size)
{
static const char * const s_infotype[CURLINFO_END] = {
- "* ", "< ", "> ", "{ ", "} " };
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug)
return (*data->set.fdebug)(data, type, ptr, size,
@@ -406,6 +454,7 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
fwrite(s_infotype[type], 2, 1, data->set.err);
fwrite(ptr, size, 1, data->set.err);
break;
@@ -415,11 +464,33 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
return 0;
}
+int Curl_debug(struct SessionHandle *data, curl_infotype type,
+ char *ptr, size_t size, char *host)
+{
+ int rc;
+ if(data->set.printhost && host) {
+ char buffer[160];
+ const char *t=NULL;
+ switch (type) {
+ case CURLINFO_HEADER_IN:
+ case CURLINFO_DATA_IN:
+ t = "from";
+ break;
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_DATA_OUT:
+ t = "to";
+ break;
+ default:
+ break;
+ }
-/*
- * local variables:
- * eval: (load-file "../curl-mode.el")
- * end:
- * vim600: fdm=marker
- * vim: et sw=2 ts=2 sts=2 tw=78
- */
+ if(t) {
+ snprintf(buffer, sizeof(buffer), "[Data %s %s]", t, host);
+ rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
+ if(rc)
+ return rc;
+ }
+ }
+ rc = showit(data, type, ptr, size);
+ return rc;
+}