Index: CHANGES
===================================================================
RCS file: /cvsroot/curl/curl/CHANGES,v
retrieving revision 1.1325
diff -u -r1.1325 CHANGES
--- CHANGES	9 May 2008 16:31:51 -0000	1.1325
+++ CHANGES	11 May 2008 21:56:26 -0000
@@ -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.
Index: RELEASE-NOTES
===================================================================
RCS file: /cvsroot/curl/curl/RELEASE-NOTES,v
retrieving revision 1.795
diff -u -r1.795 RELEASE-NOTES
--- RELEASE-NOTES	9 May 2008 16:31:51 -0000	1.795
+++ RELEASE-NOTES	11 May 2008 21:56:26 -0000
@@ -3,7 +3,7 @@
  Public curl releases:         105
  Command line options:         126
  curl_easy_setopt() options:   150
- Public functions in libcurl:  56
+ Public functions in libcurl:  58
  Public web site mirrors:      39
  Known libcurl bindings:       36
  Contributors:                 636
@@ -14,6 +14,7 @@
  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:
 
Index: docs/examples/Makefile.inc
===================================================================
RCS file: /cvsroot/curl/curl/docs/examples/Makefile.inc,v
retrieving revision 1.2
diff -u -r1.2 Makefile.inc
--- docs/examples/Makefile.inc	31 Mar 2008 03:01:13 -0000	1.2
+++ docs/examples/Makefile.inc	11 May 2008 21:56:26 -0000
@@ -4,7 +4,8 @@
   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.
Index: docs/examples/sendrecv.c
===================================================================
RCS file: docs/examples/sendrecv.c
diff -N docs/examples/sendrecv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/examples/sendrecv.c	11 May 2008 21:56:26 -0000
@@ -0,0 +1,117 @@
+/*****************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * An example of curl_easy_send() and curl_easy_recv() usage.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <curl/curl.h>
+
+/* 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;
+}
Index: docs/libcurl/Makefile.am
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/Makefile.am,v
retrieving revision 1.27
diff -u -r1.27 Makefile.am
--- docs/libcurl/Makefile.am	8 Jan 2008 14:52:07 -0000	1.27
+++ docs/libcurl/Makefile.am	11 May 2008 21:56:27 -0000
@@ -19,7 +19,7 @@
  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 @@
  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 @@
  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)
 
Index: docs/libcurl/curl_easy_recv.3
===================================================================
RCS file: docs/libcurl/curl_easy_recv.3
diff -N docs/libcurl/curl_easy_recv.3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/libcurl/curl_easy_recv.3	11 May 2008 21:56:27 -0000
@@ -0,0 +1,70 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2008, 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.
+.\" *
+.\" * 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 <curl/easy.h>
+.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) "
Index: docs/libcurl/curl_easy_send.3
===================================================================
RCS file: docs/libcurl/curl_easy_send.3
diff -N docs/libcurl/curl_easy_send.3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ docs/libcurl/curl_easy_send.3	11 May 2008 21:56:27 -0000
@@ -0,0 +1,65 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2008, 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.
+.\" *
+.\" * 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 <curl/easy.h>
+.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) "
Index: docs/libcurl/index.html
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/index.html,v
retrieving revision 1.12
diff -u -r1.12 index.html
--- docs/libcurl/index.html	31 Jul 2004 19:46:25 -0000	1.12
+++ docs/libcurl/index.html	11 May 2008 21:56:27 -0000
@@ -24,7 +24,9 @@
 <br><a href="curl_easy_getinfo.html">curl_easy_getinfo</A>
 <br><a href="curl_easy_init.html">curl_easy_init</A>
 <br><a href="curl_easy_perform.html">curl_easy_perform</A>
+<br><a href="curl_easy_recv.html">curl_easy_recv</A>
 <br><a href="curl_easy_reset.html">curl_easy_reset</A>
+<br><a href="curl_easy_send.html">curl_easy_send</A>
 <br><a href="curl_easy_setopt.html">curl_easy_setopt</A>
 <br><a href="curl_easy_strerror.html">curl_easy_strerror</A>
 <br><a href="curl_escape.html">curl_escape</A>
Index: docs/libcurl/libcurl-errors.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/libcurl-errors.3,v
retrieving revision 1.30
diff -u -r1.30 libcurl-errors.3
--- docs/libcurl/libcurl-errors.3	3 Oct 2007 08:07:50 -0000	1.30
+++ docs/libcurl/libcurl-errors.3	11 May 2008 21:56:27 -0000
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2008, 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
@@ -208,6 +208,10 @@
 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.
Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.349
diff -u -r1.349 curl.h
--- include/curl/curl.h	30 Apr 2008 21:20:09 -0000	1.349
+++ include/curl/curl.h	11 May 2008 21:56:28 -0000
@@ -447,6 +447,8 @@
 
   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;
 
Index: include/curl/easy.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/easy.h,v
retrieving revision 1.13
diff -u -r1.13 easy.h
--- include/curl/easy.h	9 Nov 2004 14:02:58 -0000	1.13
+++ include/curl/easy.h	11 May 2008 21:56:28 -0000
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, 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
@@ -74,6 +74,28 @@
  */
 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
Index: lib/connect.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/connect.c,v
retrieving revision 1.190
diff -u -r1.190 connect.c
--- lib/connect.c	3 May 2008 13:43:35 -0000	1.190
+++ lib/connect.c	11 May 2008 21:56:28 -0000
@@ -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 @@
 
   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;
+}
Index: lib/connect.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/connect.h,v
retrieving revision 1.24
diff -u -r1.24 connect.h
--- lib/connect.h	7 Feb 2008 22:25:04 -0000	1.24
+++ lib/connect.h	11 May 2008 21:56:28 -0000
@@ -47,4 +47,13 @@
 
 #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
Index: lib/easy.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/easy.c,v
retrieving revision 1.119
diff -u -r1.119 easy.c
--- lib/easy.c	22 Apr 2008 22:53:54 -0000	1.119
+++ lib/easy.c	11 May 2008 21:56:28 -0000
@@ -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 <curl/mprintf.h>
@@ -1056,3 +1057,98 @@
 }
 
 #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;
+}
Index: lib/getinfo.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/getinfo.c,v
retrieving revision 1.60
diff -u -r1.60 getinfo.c
--- lib/getinfo.c	30 Apr 2008 21:20:09 -0000	1.60
+++ lib/getinfo.c	11 May 2008 21:56:28 -0000
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include "memory.h"
 #include "sslgen.h"
+#include "connect.h" /* Curl_getconnectinfo() */
 
 /* Make this the last #include */
 #include "memdebug.h"
@@ -75,9 +76,6 @@
   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 @@
     *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
Index: lib/strerror.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/strerror.c,v
retrieving revision 1.49
diff -u -r1.49 strerror.c
--- lib/strerror.c	7 Nov 2007 09:21:36 -0000	1.49
+++ lib/strerror.c	11 May 2008 21:56:29 -0000
@@ -261,6 +261,9 @@
   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:
