Hi
After some reading, the approach to use websockets with libcurl seems to
be to let libcurl only establish the connection with
CURLOPT_CONNECT_ONLY and then use curl_easy_send() and curl_easy_recv()
on the easy_handle. This means to send and receive the HTTP headers also
with this functions.
(I read http://curl.haxx.se/mail/lib-2015-03/0142.html)
My understanding is that there is no way to let libcurl handle the HTTP
Upgrade itself, and then takeover the connection. At least not with the
multi-interface.
I tried to let the HTTP request and response be handled "normally" by
setting up the request parameters (url, headers, ...) on the easy_handle
and use curl_multi_perform() to work it's magic. And when the
response-headers were received (and the upgrade conditions were met)
pause (CURLPAUSE_ALL) and set CURLOPT_CONNECT_ONLY on the easy_handle
and then use curl_easy_send() and _recv(). But this fails with
"Unsupported protocol" Error. The reason is, that Curl_getconnectinfo()
will not retrieve the current socket, since "data->state.lastconnect" is
not set yet.
Am I right with this analysis, or did I just do something wrong?
If Curl_getconnectinfo() would not not just care about "lastconnect"
socket, but also would retrieve the connection that is actually being
used, my approach would work. This was suggested in
https://github.com/bagder/curl/pull/86, but was never merged.
But all in all this approach seems to be a bit crude anyway. So I came
up with the Idea to handle the upgrade of the connection inside libcurl,
and then use the READ and WRITEFUNCTION callbacks to handle the
websocket communication.
I came up with quite a small "prove of concept" (patch attached) to show
were I'm heading. If you think this is the right way to go, I would be
able to write a more conclusive patch.
cheers, Frank
diff --git a/lib/http.c b/lib/http.c
index b9e8047..09ab570 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -3056,8 +3056,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
break;
case 101:
/* Switching Protocols */
+ infof(data, "Received 101\n");
if(k->upgr101 == UPGR101_REQUESTED) {
- infof(data, "Received 101\n");
k->upgr101 = UPGR101_RECEIVED;
/* switch to http2 now. The bytes after response headers
@@ -3067,6 +3067,14 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
return result;
*nread = 0;
}
+ else {
+ const char* ptr = Curl_checkheaders(conn, "Upgrade");
+ if(ptr && Curl_compareheader(ptr, "Upgrade:", "websocket")) {
+ infof(data, "Upgrade: Websocket\n");
+ k->keepon |= KEEP_SEND;
+ conn->writesockfd = conn->sockfd;
+ }
+ }
break;
default:
break;
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html