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

Reply via email to