aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2008-05-12 21:43:24 +0000
committerDaniel Stenberg <daniel@haxx.se>2008-05-12 21:43:24 +0000
commit514592b89207e83d13b5a4e79bc247aa6f74c4b7 (patch)
tree9c9df12cf0f9b8f5e2aa835c4379ae7be9e3805d /lib
parentd72efff878a352e24d3a7cc8cf7c2f8b0b65f409 (diff)
- 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.
Diffstat (limited to 'lib')
-rw-r--r--lib/connect.c44
-rw-r--r--lib/connect.h9
-rw-r--r--lib/easy.c96
-rw-r--r--lib/getinfo.c30
-rw-r--r--lib/strerror.c3
5 files changed, 154 insertions, 28 deletions
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 <curl/mprintf.h>
@@ -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 <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 @@ 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: