client: fix redirects and allow ssl / non-ssl redirects
authorAndy Green <andy@warmcat.com>
Thu, 9 Feb 2017 07:25:01 +0000 (15:25 +0800)
committerAndy Green <andy@warmcat.com>
Thu, 9 Feb 2017 07:25:01 +0000 (15:25 +0800)
lib/client-handshake.c
lib/client.c
lib/parsers.c
lib/private-libwebsockets.h
test-server/test-client.c

index a407d9c..306c392 100644 (file)
@@ -63,7 +63,7 @@ lws_client_connect_2(struct lws *wsi)
        /*
         * prepare the actual connection (to the proxy, if any)
         */
-       lwsl_client("%s: address %s\n", __func__, ads);
+       lwsl_notice("%s: address %s\n", __func__, ads);
 
 #ifdef LWS_USE_IPV6
        if (LWS_IPV6_ENABLED(wsi->vhost)) {
@@ -374,6 +374,7 @@ failed1:
 LWS_VISIBLE struct lws *
 lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const char *path, const char *host)
 {
+       char origin[300] = "", protocol[300] = "", method[32] = "", *p;
        if (wsi->u.hdr.redirects == 3) {
                lwsl_err("%s: Too many redirects\n", __func__);
                return NULL;
@@ -389,24 +390,54 @@ lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const
        }
 #endif
 
-       lwsl_notice("redirect ads='%s', port=%d, path='%s'\n", address, port, path);
+       p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
+       if (p)
+               strncpy(origin, p, sizeof(origin) - 1);
 
-       if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
-               return NULL;
+       p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
+       if (p)
+               strncpy(protocol, p, sizeof(protocol) - 1);
 
-       if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
-               return NULL;
+       p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
+       if (p)
+               strncpy(method, p, sizeof(method) - 1);
 
-       if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
-               return NULL;
+       lwsl_notice("redirect ads='%s', port=%d, path='%s', ssl = %d\n", address, port, path, ssl);
+
+       /* close the connection by hand */
 
        compatible_close(wsi->sock);
        remove_wsi_socket_from_fds(wsi);
+
        wsi->sock = LWS_SOCK_INVALID;
        wsi->state = LWSS_CLIENT_UNCONNECTED;
        wsi->protocol = NULL;
        wsi->pending_timeout = NO_PENDING_TIMEOUT;
        wsi->u.hdr.c_port = port;
+       wsi->hdr_parsing_completed = 0;
+       _lws_header_table_reset(wsi->u.hdr.ah);
+
+       if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
+               return NULL;
+
+       if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
+               return NULL;
+
+       if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
+               return NULL;
+
+       if (origin[0])
+               if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
+                                         origin))
+                       return NULL;
+       if (protocol[0])
+               if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
+                                         protocol))
+                       return NULL;
+       if (method[0])
+               if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
+                                         method))
+                       return NULL;
 
        return lws_client_connect_2(wsi);
 }
index c819fe7..4ffb1fa 100755 (executable)
@@ -480,10 +480,12 @@ lws_client_interpret_server_handshake(struct lws *wsi)
                        goto bail3;
                }
 
-               if (!strcmp(prot, "wss://") || !strcmp(prot, "https://"))
+               if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
                        ssl = 1;
 
-               if (lws_client_reset(wsi, ssl, ads, port, path, ads)) {
+               lwsl_notice("ssl %d %s\n", ssl, prot);
+
+               if (!lws_client_reset(wsi, ssl, ads, port, path, ads)) {
                        lwsl_err("Redirect failed\n");
                        cce = "HS: Redirect failed";
                        goto bail3;
index 72e35dd..14cbbd9 100644 (file)
@@ -60,6 +60,16 @@ lextable_decode(int pos, char c)
        }
 }
 
+void
+_lws_header_table_reset(struct allocated_headers *ah)
+{
+       /* init the ah to reflect no headers or data have appeared yet */
+       memset(ah->frag_index, 0, sizeof(ah->frag_index));
+       ah->nfrag = 0;
+       ah->pos = 0;
+       ah->http_response = 0;
+}
+
 // doesn't scrub the ah rxbuffer by default, parent must do if needed
 
 void
@@ -74,11 +84,7 @@ lws_header_table_reset(struct lws *wsi, int autoservice)
        /* ah also concurs with ownership */
        assert(ah->wsi == wsi);
 
-       /* init the ah to reflect no headers or data have appeared yet */
-       memset(ah->frag_index, 0, sizeof(ah->frag_index));
-       ah->nfrag = 0;
-       ah->pos = 0;
-       ah->http_response = 0;
+       _lws_header_table_reset(ah);
 
        /* since we will restart the ah, our new headers are not completed */
        // wsi->hdr_parsing_completed = 0;
index ec33639..0041557 100644 (file)
@@ -1718,6 +1718,8 @@ lws_header_table_detach(struct lws *wsi, int autoservice);
 
 LWS_EXTERN void
 lws_header_table_reset(struct lws *wsi, int autoservice);
+void
+_lws_header_table_reset(struct allocated_headers *ah);
 
 LWS_EXTERN char * LWS_WARN_UNUSED_RESULT
 lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h);
index cfea0f8..b90a388 100644 (file)
@@ -558,9 +558,11 @@ int main(int argc, char **argv)
        info.ws_ping_pong_interval = pp_secs;
        info.extensions = exts;
 
-       if (use_ssl) {
-               info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+#if defined(LWS_OPENSSL_SUPPORT)
+       info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+#endif
 
+       if (use_ssl) {
                /*
                 * If the server wants us to present a valid SSL client certificate
                 * then we can set it up here.