From 514592b89207e83d13b5a4e79bc247aa6f74c4b7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 12 May 2008 21:43:24 +0000 Subject: - Introducing curl_easy_send() and curl_easy_recv(). They can be used to send and receive data over a connection previously setup with curl_easy_perform() and its CURLOPT_CONNECT_ONLY option. The sendrecv.c example was added to show how they can be used. --- CHANGES | 6 +++ RELEASE-NOTES | 5 +- docs/examples/Makefile.inc | 3 +- docs/examples/sendrecv.c | 117 ++++++++++++++++++++++++++++++++++++++++++ docs/libcurl/Makefile.am | 8 +-- docs/libcurl/curl_easy_recv.3 | 70 +++++++++++++++++++++++++ docs/libcurl/curl_easy_send.3 | 65 +++++++++++++++++++++++ docs/libcurl/index.html | 2 + docs/libcurl/libcurl-errors.3 | 6 ++- include/curl/curl.h | 2 + include/curl/easy.h | 24 ++++++++- lib/connect.c | 44 ++++++++++++++++ lib/connect.h | 9 ++++ lib/easy.c | 96 ++++++++++++++++++++++++++++++++++ lib/getinfo.c | 30 +---------- lib/strerror.c | 3 ++ 16 files changed, 454 insertions(+), 36 deletions(-) create mode 100644 docs/examples/sendrecv.c create mode 100644 docs/libcurl/curl_easy_recv.3 create mode 100644 docs/libcurl/curl_easy_send.3 diff --git a/CHANGES b/CHANGES index 8372bd37b..b5bde4e40 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,12 @@ Changelog +Daniel Stenberg (9 May 2008) +- Introducing curl_easy_send() and curl_easy_recv(). They can be used to send + and receive data over a connection previously setup with curl_easy_perform() + and its CURLOPT_CONNECT_ONLY option. The sendrecv.c example was added to + show how they can be used. + Yang Tse (9 May 2008) - Internal time differences now use monotonic time source if available. This also implies the removal of the winmm.lib dependency for WIN32. diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 15781b3ea..cb6496930 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -3,8 +3,8 @@ Curl and libcurl 7.18.2 Public curl releases: 105 Command line options: 126 curl_easy_setopt() options: 150 - Public functions in libcurl: 56 - Public web site mirrors: 39 + Public functions in libcurl: 58 + Public web site mirrors: 37 Known libcurl bindings: 36 Contributors: 636 @@ -14,6 +14,7 @@ This release includes the following changes: o CURLOPT_NOBODY is now supported over SFTP o curl can now run on Symbian OS o curl -w redirect_url and CURLINFO_REDIRECT_URL + o added curl_easy_send() and curl_easy_recv() This release includes the following bugfixes: diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc index 5d0c162a5..840c9bf6c 100644 --- a/docs/examples/Makefile.inc +++ b/docs/examples/Makefile.inc @@ -4,7 +4,8 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface \ getinfo getinmemory http-post httpput \ https multi-app multi-debugcallback multi-double \ multi-post multi-single persistant post-callback \ - postit2 sepheaders simple simplepost simplessl + postit2 sepheaders simple simplepost simplessl \ + sendrecv # These examples require external dependencies that may not be commonly # available on POSIX systems, so don't bother attempting to compile them here. diff --git a/docs/examples/sendrecv.c b/docs/examples/sendrecv.c new file mode 100644 index 000000000..1a37d2862 --- /dev/null +++ b/docs/examples/sendrecv.c @@ -0,0 +1,117 @@ +/***************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * An example of curl_easy_send() and curl_easy_recv() usage. + * + * $Id$ + */ + +#include +#include +#include + +/* Auxiliary function that waits on the socket. */ +static int wait_on_socket(int sockfd, int for_recv, long timeout_ms) +{ + struct timeval tv; + long seconds, usecs; + fd_set infd, outfd, errfd; + int res; + + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec= (timeout_ms % 1000) * 1000; + + FD_ZERO(&infd); + FD_ZERO(&outfd); + FD_ZERO(&errfd); + + FD_SET(sockfd, &errfd); /* always check for error */ + + if(for_recv) + { + FD_SET(sockfd, &infd); + } + else + { + FD_SET(sockfd, &outfd); + } + + /* select() returns the number of signalled sockets or -1 */ + res = select(sockfd + 1, &infd, &outfd, &errfd, &tv); + return res; +} + +int main(void) +{ + CURL *curl; + CURLcode res; + /* Minimalistic http request */ + const char *request = "GET / HTTP/1.0\r\nHost: curl.haxx.se\r\n\r\n"; + int sockfd; /* socket */ + size_t iolen; + + curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se"); + /* Do not do the transfer - only connect to host */ + curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L); + res = curl_easy_perform(curl); + + if(CURLE_OK != res) + { + printf("Error: %s\n", strerror(res)); + return 1; + } + + /* Extract the socket from the curl handle - we'll need it + * for waiting */ + res = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockfd); + + if(CURLE_OK != res) + { + printf("Error: %s\n", strerror(res)); + return 1; + } + + /* wait for the socket to become ready for sending */ + if(!wait_on_socket(sockfd, 0, 60000L)) + { + printf("Error: timeout.\n"); + return 1; + } + + puts("Sending request."); + /* Send the request. Real applications should check the iolen + * to see if all the request has been sent */ + res = curl_easy_send(curl, request, strlen(request), &iolen); + + if(CURLE_OK != res) + { + printf("Error: %s\n", strerror(res)); + return 1; + } + puts("Reading response."); + + /* read the response */ + for(;;) + { + char buf[1024]; + + wait_on_socket(sockfd, 1, 60000L); + res = curl_easy_recv(curl, buf, 1024, &iolen); + + if(CURLE_OK != res) + break; + + printf("Received %u bytes.\n", iolen); + } + + /* always cleanup */ + curl_easy_cleanup(curl); + } + return 0; +} diff --git a/docs/libcurl/Makefile.am b/docs/libcurl/Makefile.am index 9bf8e99c7..9e562c21e 100644 --- a/docs/libcurl/Makefile.am +++ b/docs/libcurl/Makefile.am @@ -19,7 +19,7 @@ man_MANS = curl_easy_cleanup.3 curl_easy_getinfo.3 curl_easy_init.3 \ libcurl-tutorial.3 curl_easy_reset.3 curl_easy_escape.3 \ curl_easy_unescape.3 curl_multi_setopt.3 curl_multi_socket.3 \ curl_multi_timeout.3 curl_formget.3 curl_multi_assign.3 \ - curl_easy_pause.3 + curl_easy_pause.3 curl_easy_recv.3 curl_easy_send.3 HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \ curl_easy_init.html curl_easy_perform.html curl_easy_setopt.html \ @@ -37,7 +37,8 @@ HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \ curl_share_strerror.html curl_global_init_mem.html libcurl-tutorial.html \ curl_easy_reset.html curl_easy_escape.html curl_easy_unescape.html \ curl_multi_setopt.html curl_multi_socket.html curl_multi_timeout.html \ - curl_formget.html curl_multi_assign.html curl_easy_pause.html + curl_formget.html curl_multi_assign.html curl_easy_pause.html \ + curl_easy_recv.html curl_easy_send.html PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \ curl_easy_perform.pdf curl_easy_setopt.pdf curl_easy_duphandle.pdf \ @@ -54,7 +55,8 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \ curl_share_strerror.pdf curl_global_init_mem.pdf libcurl-tutorial.pdf \ curl_easy_reset.pdf curl_easy_escape.pdf curl_easy_unescape.pdf \ curl_multi_setopt.pdf curl_multi_socket.pdf curl_multi_timeout.pdf \ - curl_formget.pdf curl_multi_assign.pdf curl_easy_pause.pdf + curl_formget.pdf curl_multi_assign.pdf curl_easy_pause.pdf \ + curl_easy_recv.pdf curl_easy_send.pdf CLEANFILES = $(HTMLPAGES) $(PDFPAGES) diff --git a/docs/libcurl/curl_easy_recv.3 b/docs/libcurl/curl_easy_recv.3 new file mode 100644 index 000000000..ea806ff66 --- /dev/null +++ b/docs/libcurl/curl_easy_recv.3 @@ -0,0 +1,70 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, , 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. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" * $Id$ +.\" ************************************************************************** +.\" +.TH curl_easy_recv 3 "29 April 2008" "libcurl 7.18.2" "libcurl Manual" +.SH NAME +curl_easy_recv - receives raw data on an "easy" connection +.SH SYNOPSIS +.B #include +.sp +.BI "CURLcode curl_easy_recv( CURL *" curl ", void *" buffer "," +.BI "size_t " buflen ", size_t *" n ");" +.ad +.SH DESCRIPTION +This function receives raw data from the established connection. You may use +it together with \fIcurl_easy_send(3)\fP to implement custom protocols using +libcurl. This functionality can be particularly useful if you use proxies +and/or SSL encryption: libcurl will take care of proxy negotiation and +connection set-up. + +\fBbuffer\fP is a pointer to your buffer that will get the received +data. \fBbuflen\fP is the maximum amount of data you can get in that +buffer. The variable \fBn\fP points to will receive the number of received +bytes. + +To establish the connection, set \fBCURLOPT_CONNECT_ONLY\fP option before +calling \fIcurl_easy_perform(3)\fP. Note that \fIcurl_easy_recv(3)\fP does not +work on connections that were created without this option. + +You must ensure that the socket has data to read before calling +\fIcurl_easy_recv(3)\fP, otherwise the call will return \fBCURLE_AGAIN\fP - +the socket is used in non-blocking mode internally. Use +\fIcurl_easy_getinfo(3)\fP with \fBCURLINFO_LASTSOCKET\fP to obtain the +socket; use your operating system facilities like \fIselect(2)\fP to check if +it has any data you can read. +.SH AVAILABILITY +Added in 7.18.2. +.SH RETURN VALUE +On success, returns \fBCURLE_OK\fP, stores the received data into +\fBbuffer\fP, and the number of bytes it actually read into \fB*n\fP. + +On failure, returns the appropriate error code. + +If there is no data to read, the function returns \fBCURLE_AGAIN\fP. Use +your operating system facilities to wait until the data is ready, and retry. +.SH EXAMPLE +See \fBsendrecv.c\fP in \fBdocs/examples\fP directory for usage example. +.SH "SEE ALSO" +.BR curl_easy_setopt "(3), " curl_easy_perform "(3), " +.BR curl_easy_getinfo "(3), " +.BR curl_easy_send "(3) " diff --git a/docs/libcurl/curl_easy_send.3 b/docs/libcurl/curl_easy_send.3 new file mode 100644 index 000000000..60a97b29d --- /dev/null +++ b/docs/libcurl/curl_easy_send.3 @@ -0,0 +1,65 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, , 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. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" * $Id$ +.\" ************************************************************************** +.\" +.TH curl_easy_send 3 "29 April 2008" "libcurl 7.18.2" "libcurl Manual" +.SH NAME +curl_easy_send - sends raw data over an "easy" connection +.SH SYNOPSIS +.B #include +.sp +.BI "CURLcode curl_easy_send( CURL *" curl ", const void *" buffer "," +.BI " size_t " buflen ", size_t *" n ");" +.ad +.SH DESCRIPTION +This function sends arbitrary data over the established connection. You may +use it together with \fIcurl_easy_recv(3)\fP to implement custom protocols +using libcurl. This functionality can be particularly useful if you use +proxies and/or SSL encryption: libcurl will take care of proxy negotiation and +connection set-up. + +\fBbuffer\fP is a pointer to the data of length \fBbuflen\fP that you want sent. +The variable \fBn\fP points to will receive the number of sent bytes. + +To establish the connection, set \fBCURLOPT_CONNECT_ONLY\fP option before +calling \fIcurl_easy_perform(3)\fP. Note that \fIcurl_easy_send(3)\fP will not +work on connections that were created without this option. + +You must ensure that the socket is writable before calling +\fIcurl_easy_send(3)\fP, otherwise the call will return \fBCURLE_AGAIN\fP - +the socket is used in non-blocking mode internally. Use +\fIcurl_easy_getinfo(3)\fP with \fBCURLINFO_LASTSOCKET\fP to obtain the +socket; use your operating system facilities like \fIselect(2)\fP to check if +it can be written to. +.SH AVAILABILITY +Added in 7.18.2. +.SH RETURN VALUE +On success, returns \fBCURLE_OK\fP and stores the number of bytes actually +sent into \fB*n\fP. Note that this may very well be less than the amount you +wanted to send. + +On failure, returns the appropriate error code. +.SH EXAMPLE +See \fBsendrecv.c\fP in \fBdocs/examples\fP directory for usage example. +.SH "SEE ALSO" +.BR curl_easy_setopt "(3), " curl_easy_perform "(3), " curl_easy_getinfo "(3), " +.BR curl_easy_recv "(3) " diff --git a/docs/libcurl/index.html b/docs/libcurl/index.html index 6b4f10550..287a2dd69 100644 --- a/docs/libcurl/index.html +++ b/docs/libcurl/index.html @@ -24,7 +24,9 @@
curl_easy_getinfo
curl_easy_init
curl_easy_perform +
curl_easy_recv
curl_easy_reset +
curl_easy_send
curl_easy_setopt
curl_easy_strerror
curl_escape diff --git a/docs/libcurl/libcurl-errors.3 b/docs/libcurl/libcurl-errors.3 index a686793f7..28e6f82c9 100644 --- a/docs/libcurl/libcurl-errors.3 +++ b/docs/libcurl/libcurl-errors.3 @@ -5,7 +5,7 @@ .\" * | (__| |_| | _ <| |___ .\" * \___|\___/|_| \_\_____| .\" * -.\" * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. +.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. .\" * .\" * This software is licensed as described in the file COPYING, which .\" * you should have received as part of this distribution. The terms @@ -208,6 +208,10 @@ The resource referenced in the URL does not exist An unspecified error occurred during the SSH session .IP "CURLE_SSL_SHUTDOWN_FAILED (80)" Failed to shut down the SSL connection +.IP "CURLE_AGAIN (81)" +Socket is not ready for send/recv wait till it's ready and try again. This +return code is only returned from \fIcurl_easy_recv(3)\fP and +\fIcurl_easy_send(3)\fP (Added in 7.18.2) .IP "CURLE_OBSOLETE*" These error codes will never be returned. They used to be used in an old libcurl version and are currently unused. diff --git a/include/curl/curl.h b/include/curl/curl.h index 6fcc34faf..042367466 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -447,6 +447,8 @@ typedef enum { CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again */ CURL_LAST /* never use! */ } CURLcode; diff --git a/include/curl/easy.h b/include/curl/easy.h index 17de21070..88aa0e655 100644 --- a/include/curl/easy.h +++ b/include/curl/easy.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -74,6 +74,28 @@ CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); */ CURL_EXTERN void curl_easy_reset(CURL *curl); +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + #ifdef __cplusplus } #endif diff --git a/lib/connect.c b/lib/connect.c index 33e4e0777..74380da1e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -92,6 +92,7 @@ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "inet_ntop.h" #include "inet_pton.h" +#include "sslgen.h" /* for Curl_ssl_check_cxn() */ /* The last #include file should be: */ #include "memdebug.h" @@ -977,3 +978,46 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_OK; } + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given SessionHandle. + * + * The socket 'long' will be -1 in case of failure! + */ +CURLcode Curl_getconnectinfo(struct SessionHandle *data, + long *param_longp, + struct connectdata **connp) +{ + if((data->state.lastconnect != -1) && + (data->state.connc->connects[data->state.lastconnect] != NULL)) { + struct connectdata *c = + data->state.connc->connects[data->state.lastconnect]; + if(connp) + /* only store this if the caller cares for it */ + *connp = c; + *param_longp = c->sock[FIRSTSOCKET]; + /* we have a socket connected, let's determine if the server shut down */ + /* determine if ssl */ + if(c->ssl[FIRSTSOCKET].use) { + /* use the SSL context */ + if(!Curl_ssl_check_cxn(c)) + *param_longp = -1; /* FIN received */ + } +/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ +#ifdef MSG_PEEK + else { + /* use the socket */ + char buf; + if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { + *param_longp = -1; /* FIN received */ + } + } +#endif + } + else + *param_longp = -1; + + return CURLE_OK; +} diff --git a/lib/connect.h b/lib/connect.h index 78c0191ba..8e55cc941 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -47,4 +47,13 @@ long Curl_timeleft(struct connectdata *conn, #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given SessionHandle. + * + * The socket 'long' will be -1 in case of failure! + */ +CURLcode Curl_getconnectinfo(struct SessionHandle *data, + long *param_longp, + struct connectdata **connp); #endif diff --git a/lib/easy.c b/lib/easy.c index 1af575416..216dfe7bf 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -83,6 +83,7 @@ #include "easyif.h" #include "select.h" #include "sendf.h" /* for failf function prototype */ +#include "connect.h" /* for Curl_getconnectinfo */ #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1056,3 +1057,98 @@ CURLcode Curl_convert_from_utf8(struct SessionHandle *data, } #endif /* CURL_DOES_CONVERSIONS */ + +static CURLcode easy_connection(struct SessionHandle *data, + curl_socket_t *sfd, + struct connectdata **connp) +{ + CURLcode ret; + long sockfd; + + if(data == NULL) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ + if(!data->set.connect_only) { + failf(data, "CONNECT_ONLY is required!"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + ret = Curl_getconnectinfo(data, &sockfd, connp); + if(ret != CURLE_OK) + return ret; + + if(sockfd == -1) { + failf(data, "Failed to get recent socket"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + *sfd = (curl_socket_t)sockfd; /* we know that this is actually a socket + descriptor so the typecast is fine here */ + + return CURLE_OK; +} + +/* + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + * Returns CURLE_OK on success, error code on error. + */ +CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n) +{ + curl_socket_t sfd; + CURLcode ret; + int ret1; + ssize_t n1; + struct connectdata *c; + struct SessionHandle *data = (struct SessionHandle *)curl; + + ret = easy_connection(data, &sfd, &c); + if(ret) + return ret; + + *n = 0; + ret1 = Curl_read(c, sfd, buffer, buflen, &n1); + + if(ret1 == -1) + return CURLE_AGAIN; + + if(n1 == -1) + return CURLE_RECV_ERROR; + + *n = (size_t)n1; + + return CURLE_OK; +} + +/* + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen, + size_t *n) +{ + curl_socket_t sfd; + CURLcode ret; + ssize_t n1; + struct connectdata *c = NULL; + struct SessionHandle *data = (struct SessionHandle *)curl; + + ret = easy_connection(data, &sfd, &c); + if(ret) + return ret; + + *n = 0; + ret = Curl_write(c, sfd, buffer, buflen, &n1); + + if(n1 == -1) + return CURLE_SEND_ERROR; + + /* detect EAGAIN */ + if((CURLE_OK == ret) && (0 == n1)) + return CURLE_AGAIN; + + *n = (size_t)n1; + + return ret; +} diff --git a/lib/getinfo.c b/lib/getinfo.c index 145a71b22..078154246 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -34,6 +34,7 @@ #include #include "memory.h" #include "sslgen.h" +#include "connect.h" /* Curl_getconnectinfo() */ /* Make this the last #include */ #include "memdebug.h" @@ -75,9 +76,6 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) double *param_doublep=NULL; char **param_charp=NULL; struct curl_slist **param_slistp=NULL; -#ifdef MSG_PEEK - char buf; -#endif int type; if(!data) @@ -205,31 +203,7 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) *param_charp = data->state.most_recent_ftp_entrypath; break; case CURLINFO_LASTSOCKET: - if((data->state.lastconnect != -1) && - (data->state.connc->connects[data->state.lastconnect] != NULL)) { - struct connectdata *c = data->state.connc->connects - [data->state.lastconnect]; - *param_longp = c->sock[FIRSTSOCKET]; - /* we have a socket connected, let's determine if the server shut down */ - /* determine if ssl */ - if(c->ssl[FIRSTSOCKET].use) { - /* use the SSL context */ - if(!Curl_ssl_check_cxn(c)) - *param_longp = -1; /* FIN received */ - } -/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ -#ifdef MSG_PEEK - else { - /* use the socket */ - if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, - (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { - *param_longp = -1; /* FIN received */ - } - } -#endif - } - else - *param_longp = -1; + (void)Curl_getconnectinfo(data, param_longp, NULL); break; case CURLINFO_REDIRECT_URL: /* Return the URL this request would have been redirected to if that diff --git a/lib/strerror.c b/lib/strerror.c index d2d46a308..fe5a76df5 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -261,6 +261,9 @@ curl_easy_strerror(CURLcode error) case CURLE_SSH: return "Error in the SSH layer"; + case CURLE_AGAIN: + return "Socket not ready for send/recv"; + /* error codes not used by current libcurl */ case CURLE_OBSOLETE4: case CURLE_OBSOLETE10: -- cgit v1.2.3