X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fclient.c;h=3da932692fdad2d491409a64a84ccbaab5467c6a;hb=a1d2a467f3df805742dc2a5b3f4edbf263222afa;hp=a1146c00c9d2fb128fa06bbf994b2f8760f930e6;hpb=e81a2ad71ae9d48248acb34508cb178b10fc7a48;p=profile%2Fivi%2Flibwebsockets.git diff --git a/lib/client.c b/lib/client.c index a1146c0..3da9326 100644 --- a/lib/client.c +++ b/lib/client.c @@ -35,20 +35,13 @@ #include #endif -#ifdef LWS_OPENSSL_SUPPORT -extern int openssl_websocket_private_data_index; -#endif - -int lws_client_socket_service(struct libwebsocket_context *context, struct libwebsocket *wsi, struct pollfd *pollfd) +int lws_client_socket_service(struct libwebsocket_context *context, + struct libwebsocket *wsi, struct pollfd *pollfd) { int n; - char pkt[1024]; - char *p = &pkt[0]; + char *p = (char *)&context->service_buffer[0]; int len; char c; -#ifdef LWS_OPENSSL_SUPPORT - char ssl_err_buf[512]; -#endif switch (wsi->mode) { @@ -66,7 +59,8 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe return 0; } - n = recv(wsi->sock, pkt, sizeof pkt, 0); + n = recv(wsi->sock, context->service_buffer, + sizeof(context->service_buffer), 0); if (n < 0) { libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); @@ -74,11 +68,11 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe return 0; } - pkt[13] = '\0'; - if (strcmp(pkt, "HTTP/1.0 200 ") != 0) { + context->service_buffer[13] = '\0'; + if (strcmp((char *)context->service_buffer, "HTTP/1.0 200 ")) { libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); - lwsl_err("ERROR from proxy: %s\n", pkt); + lwsl_err("ERROR proxy: %s\n", context->service_buffer); return 0; } @@ -107,24 +101,49 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe /* external POLL support via protocol 0 */ context->protocols[0].callback(context, wsi, LWS_CALLBACK_CLEAR_MODE_POLL_FD, - (void *)(long)wsi->sock, NULL, POLLOUT); + wsi->user_space, (void *)(long)wsi->sock, POLLOUT); - /* we can retry this... so just cook the SSL BIO the first time */ + /* we can retry this... just cook the SSL BIO the first time */ if (wsi->use_ssl && !wsi->ssl) { wsi->ssl = SSL_new(context->ssl_client_ctx); - wsi->client_bio = BIO_new_socket(wsi->sock, - BIO_NOCLOSE); + +#ifdef USE_CYASSL + /* + * CyaSSL does certificate verification differently + * from OpenSSL. + * If we should ignore the certificate, we need to set + * this before SSL_new and SSL_connect is called. + * Otherwise the connect will simply fail with error + * code -155 + */ + if (wsi->use_ssl == 2) + CyaSSL_set_verify(wsi->ssl, + SSL_VERIFY_NONE, NULL); +#endif /* USE_CYASSL */ + + wsi->client_bio = + BIO_new_socket(wsi->sock, BIO_NOCLOSE); SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio); +#ifdef USE_CYASSL + CyaSSL_set_using_nonblock(wsi->ssl, 1); +#else + BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */ +#endif + SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index, context); - } + } if (wsi->use_ssl) { + lws_latency_pre(context, wsi); n = SSL_connect(wsi->ssl); + lws_latency(context, wsi, + "SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE", + n, n > 0); if (n < 0) { n = SSL_get_error(wsi->ssl, n); @@ -132,18 +151,22 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) { /* - * wants us to retry connect due to state of the - * underlying ssl layer... but since it may be - * stalled on blocked write, no incoming data may - * arrive to trigger the retry. Force (possibly - * many if the SSL state persists in returning the - * condition code, but other sockets are getting - * serviced inbetweentimes) us to get called back - * when writable. + * wants us to retry connect due to + * state of the underlying ssl layer... + * but since it may be stalled on + * blocked write, no incoming data may + * arrive to trigger the retry. + * Force (possibly many times if the SSL + * state persists in returning the + * condition code, but other sockets + * are getting serviced inbetweentimes) + * us to get called back when writable. */ - lwsl_info("SSL_connect -> SSL_ERROR_WANT_... retrying\n"); - libwebsocket_callback_on_writable(context, wsi); + lwsl_info( + "SSL_connect WANT_... retrying\n"); + libwebsocket_callback_on_writable( + context, wsi); return 0; /* no error */ } @@ -156,30 +179,41 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe * run into the connection timeout or win */ - lwsl_err("SSL connect error %s\n", + lwsl_err("SSL connect error %lu: %s\n", + ERR_get_error(), ERR_error_string(ERR_get_error(), - ssl_err_buf)); + (char *)context->service_buffer)); return 0; } + #ifndef USE_CYASSL + /* + * See comment above about CyaSSL certificate + * verification + */ + lws_latency_pre(context, wsi); n = SSL_get_verify_result(wsi->ssl); + lws_latency(context, wsi, + "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", + n, n > 0); if ((n != X509_V_OK) && ( n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || wsi->use_ssl != 2)) { - lwsl_err("server's cert didn't " - "look good %d\n", n); + lwsl_err( + "server's cert didn't look good %d\n", n); libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } +#endif /* USE_CYASSL */ } else wsi->ssl = NULL; - #endif +#endif p = libwebsockets_generate_client_handshake(context, wsi, p); if (p == NULL) { - lwsl_err("Failed to generate handshake for client, closing it\n"); + lwsl_err("Failed to generate handshake for client\n"); libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; @@ -187,12 +221,18 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe /* send our request to the server */ - #ifdef LWS_OPENSSL_SUPPORT + lws_latency_pre(context, wsi); +#ifdef LWS_OPENSSL_SUPPORT if (wsi->use_ssl) - n = SSL_write(wsi->ssl, pkt, p - pkt); + n = SSL_write(wsi->ssl, context->service_buffer, + p - (char *)context->service_buffer); else - #endif - n = send(wsi->sock, pkt, p - pkt, 0); +#endif + n = send(wsi->sock, context->service_buffer, + p - (char *)context->service_buffer, 0); + lws_latency(context, wsi, + "send or SSL_write LWS_CONNMODE...HANDSHAKE", + n, n >= 0); if (n < 0) { lwsl_debug("ERROR writing to client socket\n"); @@ -201,12 +241,12 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe return 0; } - wsi->parser_state = WSI_TOKEN_NAME_PART; - wsi->lextable_pos = 0; + wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; + wsi->u.hdr.lextable_pos = 0; wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY; libwebsocket_set_timeout(wsi, - PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT); - + PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, + AWAITING_TIMEOUT); break; case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY: @@ -221,6 +261,10 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe goto bail3; } + if (!(pollfd->revents & POLLIN)) { + lwsl_warn("server reply no POLLIN\n"); + goto bail3; + } /* interpret the server response */ @@ -243,15 +287,30 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe */ len = 1; - while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) { + while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE && + len > 0) { #ifdef LWS_OPENSSL_SUPPORT - if (wsi->use_ssl) + if (wsi->use_ssl) { len = SSL_read(wsi->ssl, &c, 1); - else + if (len < 0) { + n = SSL_get_error(wsi->ssl, len); + if (n == SSL_ERROR_WANT_READ || + n == SSL_ERROR_WANT_WRITE) + return 0; + } + } else #endif len = recv(wsi->sock, &c, 1, 0); - libwebsocket_parse(wsi, c); + if (len < 0) { + lwsl_warn("error on parsing recv\n"); + goto bail3; + } + + if (libwebsocket_parse(wsi, c)) { + lwsl_warn("problems parsing header\n"); + goto bail3; + } } /* @@ -260,7 +319,7 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe * not complete just wait for next packet coming in this state */ - if (wsi->parser_state != WSI_PARSING_COMPLETE) + if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) break; /* @@ -272,8 +331,8 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe return lws_client_interpret_server_handshake(context, wsi); bail3: - if (wsi->c_protocol) - free(wsi->c_protocol); + lwsl_info( + "closing connection at LWS_CONNMODE...SERVER_REPLY\n"); libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; @@ -312,6 +371,8 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context, { const char *pc; int okay = 0; + char *p; + int len; #ifndef LWS_NO_EXTENSIONS char ext_name[128]; struct libwebsocket_extension *ext; @@ -325,80 +386,75 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context, * well, what the server sent looked reasonable for syntax. * Now let's confirm it sent all the necessary headers */ -#if 0 - lwsl_parser("WSI_TOKEN_HTTP: %d\n", - wsi->utf8_token[WSI_TOKEN_HTTP].token_len); - lwsl_parser("WSI_TOKEN_UPGRADE: %d\n", - wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len); - lwsl_parser("WSI_TOKEN_CONNECTION: %d\n", - wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len); - lwsl_parser("WSI_TOKEN_ACCEPT: %d\n", - wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len); - lwsl_parser("WSI_TOKEN_NONCE: %d\n", - wsi->utf8_token[WSI_TOKEN_NONCE].token_len); - lwsl_parser("WSI_TOKEN_PROTOCOL: %d\n", - wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len); -#endif - strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token); - if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) { - lwsl_warn("libwebsocket_client_handshake " - "server sent bad HTTP response '%s'\n", - wsi->utf8_token[WSI_TOKEN_HTTP].token); + if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) { + lwsl_info("no ACCEPT\n"); + goto bail3; + } + + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP); + if (!p) { + lwsl_info("no URI\n"); + goto bail3; + } + if (p && strncmp(p, "101", 3)) { + lwsl_warn( + "lws_client_handshake: got bad HTTP response '%s'\n", p); goto bail3; } - strtolower(wsi->utf8_token[WSI_TOKEN_UPGRADE].token); - if (strcmp(wsi->utf8_token[WSI_TOKEN_UPGRADE].token, - "websocket")) { - lwsl_warn("libwebsocket_client_handshake server " - "sent bad Upgrade header '%s'\n", - wsi->utf8_token[WSI_TOKEN_UPGRADE].token); + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE); + if (!p) { + lwsl_info("no UPGRADE\n"); + goto bail3; + } + strtolower(p); + if (strcmp(p, "websocket")) { + lwsl_warn( + "lws_client_handshake: got bad Upgrade header '%s'\n", p); goto bail3; } - strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token); - if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token, - "upgrade")) { - lwsl_warn("libwebsocket_client_handshake server " - "sent bad Connection hdr '%s'\n", - wsi->utf8_token[WSI_TOKEN_CONNECTION].token); + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION); + if (!p) { + lwsl_info("no Connection hdr\n"); + goto bail3; + } + strtolower(p); + if (strcmp(p, "upgrade")) { + lwsl_warn("lws_client_int_s_hs: bad header %s\n", p); goto bail3; } - pc = wsi->c_protocol; + pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); if (pc == NULL) - lwsl_parser("lws_client_interpret_server_handshake: " - "NULL c_protocol\n"); + lwsl_parser("lws_client_int_s_hs: no protocol list\n"); else - lwsl_parser("lws_client_interpret_server_handshake: " - "cPprotocol='%s'\n", pc); + lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc); /* * confirm the protocol the server wants to talk was in the list * of protocols we offered */ - if (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len) { + len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL); + if (!len) { - lwsl_info("lws_client_interpret_server_handshake " - "WSI_TOKEN_PROTOCOL is null\n"); + lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n"); /* * no protocol name to work from, * default to first protocol */ wsi->protocol = &context->protocols[0]; - wsi->c_callback = wsi->protocol->callback; - free(wsi->c_protocol); - goto check_extensions; } + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL); + len = strlen(p); + while (*pc && !okay) { - if ((!strncmp(pc, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token, - wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len)) && - (pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == ',' || - pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == '\0')) { + if (!strncmp(pc, p, len) && + (pc[len] == ',' || pc[len] == '\0')) { okay = 1; continue; } @@ -408,15 +464,8 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context, pc++; } - /* done with him now */ - - if (wsi->c_protocol) - free(wsi->c_protocol); - if (!okay) { - lwsl_err("libwebsocket_client_handshake server " - "sent bad protocol '%s'\n", - wsi->utf8_token[WSI_TOKEN_PROTOCOL].token); + lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p); goto bail2; } @@ -425,20 +474,16 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context, */ n = 0; wsi->protocol = NULL; - while (context->protocols[n].callback && !wsi->protocol) { /* Stop after finding first one?? */ - if (strcmp(wsi->utf8_token[WSI_TOKEN_PROTOCOL].token, - context->protocols[n].name) == 0) { + while (context->protocols[n].callback && !wsi->protocol) { + if (strcmp(p, context->protocols[n].name) == 0) { wsi->protocol = &context->protocols[n]; - wsi->c_callback = wsi->protocol->callback; + break; } n++; } if (wsi->protocol == NULL) { - lwsl_err("libwebsocket_client_handshake server " - "requested protocol '%s', which we " - "said we supported but we don't!\n", - wsi->utf8_token[WSI_TOKEN_PROTOCOL].token); + lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p); goto bail2; } @@ -447,7 +492,7 @@ check_extensions: #ifndef LWS_NO_EXTENSIONS /* instantiate the accepted extensions */ - if (!wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token_len) { + if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) { lwsl_ext("no client extenstions allowed by server\n"); goto check_accept; } @@ -457,7 +502,13 @@ check_extensions: * and go through matching them or identifying bogons */ - c = wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token; + if (lws_hdr_copy(wsi, (char *)context->service_buffer, + sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0) { + lwsl_warn("ext list from server failed to copy\n"); + goto bail2; + } + + c = (char *)context->service_buffer; n = 0; while (more) { @@ -524,8 +575,7 @@ check_extensions: } if (n == 0) { - lwsl_warn("Server said we should use" - "an unknown extension '%s'!\n", ext_name); + lwsl_warn("Unknown ext '%s'!\n", ext_name); goto bail2; } @@ -539,29 +589,62 @@ check_accept: * Confirm his accept token is the one we precomputed */ - if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token, - wsi->initial_handshake_hash_base64)) { - lwsl_warn("libwebsocket_client_handshake server " - "sent bad ACCEPT '%s' vs computed '%s'\n", - wsi->utf8_token[WSI_TOKEN_ACCEPT].token, - wsi->initial_handshake_hash_base64); + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT); + if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) { + lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p, + wsi->u.hdr.ah->initial_handshake_hash_base64); goto bail2; } /* allocate the per-connection user memory (if any) */ - if (wsi->protocol->per_session_data_size && - !libwebsocket_ensure_user_space(wsi)) + if (libwebsocket_ensure_user_space(wsi)) { + lwsl_err("Problem allocating wsi user mem\n"); goto bail2; + } + + /* + * we seem to be good to go, give client last chance to check + * headers and OK it + */ + + wsi->protocol->callback(context, wsi, + LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, + wsi->user_space, NULL, 0); /* clear his proxy connection timeout */ libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); + /* free up his parsing allocations */ + if (wsi->u.hdr.ah) + free(wsi->u.hdr.ah); + /* mark him as being alive */ wsi->state = WSI_STATE_ESTABLISHED; wsi->mode = LWS_CONNMODE_WS_CLIENT; + /* union transition */ + + memset(&wsi->u, 0, sizeof(wsi->u)); + + /* + * create the frame buffer for this connection according to the + * size mentioned in the protocol definition. If 0 there, then + * use a big default for compatibility + */ + + n = wsi->protocol->rx_buffer_size; + if (!n) + n = LWS_MAX_SOCKET_IO_BUF; + n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING; + wsi->u.ws.rx_user_buffer = malloc(n); + if (!wsi->u.ws.rx_user_buffer) { + lwsl_err("Out of Mem allocating rx buffer %d\n", n); + goto bail3; + } + lwsl_info("Allocating client RX buffer %d\n", n); + lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name); /* call him back to inform him he is up */ @@ -592,16 +675,22 @@ check_accept: return 0; bail3: - if (wsi->c_protocol) - free(wsi->c_protocol); bail2: - if (wsi->c_callback) wsi->c_callback(context, wsi, - LWS_CALLBACK_CLIENT_CONNECTION_ERROR, - wsi->user_space, - NULL, 0); + if (wsi->protocol) + wsi->protocol->callback(context, wsi, + LWS_CALLBACK_CLIENT_CONNECTION_ERROR, + wsi->user_space, NULL, 0); + + lwsl_info("closing connection due to bail2 connection error\n"); + + /* free up his parsing allocations */ + + if (wsi->u.hdr.ah) + free(wsi->u.hdr.ah); + libwebsocket_close_and_free_session(context, wsi, - LWS_CLOSE_STATUS_NOSTATUS); // But this should be LWS_CLOSE_STATUS_PROTOCOL_ERR + LWS_CLOSE_STATUS_PROTOCOL_ERR); return 1; } @@ -611,6 +700,7 @@ char * libwebsockets_generate_client_handshake(struct libwebsocket_context *context, struct libwebsocket *wsi, char *pkt) { + char buf[128]; char hash[20]; char key_b64[40]; char *p = pkt; @@ -620,10 +710,6 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, struct libwebsocket_extension *ext1; int ext_count = 0; #endif - unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 + - MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING]; - static const char magic_websocket_guid[] = - "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; /* * create the random key @@ -633,18 +719,12 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, if (n != 16) { lwsl_err("Unable to read from random dev %s\n", SYSTEM_RANDOM_FILEPATH); - free(wsi->c_path); - free(wsi->c_host); - if (wsi->c_origin) - free(wsi->c_origin); - if (wsi->c_protocol) - free(wsi->c_protocol); libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); return NULL; } - lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64); + lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64)); /* * 00 example client handshake @@ -672,28 +752,26 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, * Sec-WebSocket-Version: 4 */ - p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", wsi->c_path); + p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", + lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI)); - p += sprintf(p, "Pragma: no-cache\x0d\x0a" - "Cache-Control: no-cache\x0d\x0a"); + p += sprintf(p, + "Pragma: no-cache\x0d\x0a""Cache-Control: no-cache\x0d\x0a"); - p += sprintf(p, "Host: %s\x0d\x0a", wsi->c_host); - p += sprintf(p, "Upgrade: websocket\x0d\x0a" - "Connection: Upgrade\x0d\x0a" - "Sec-WebSocket-Key: "); + p += sprintf(p, "Host: %s\x0d\x0a", + lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST)); + p += sprintf(p, +"Upgrade: websocket\x0d\x0a""Connection: Upgrade\x0d\x0a""Sec-WebSocket-Key: "); strcpy(p, key_b64); p += strlen(key_b64); p += sprintf(p, "\x0d\x0a"); - if (wsi->c_origin) { - if (wsi->ietf_spec_revision == 13) - p += sprintf(p, "Origin: %s\x0d\x0a", wsi->c_origin); - else - p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a", - wsi->c_origin); - } - if (wsi->c_protocol) + if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) + p += sprintf(p, "Origin: %s\x0d\x0a", + lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)); + + if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS)) p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a", - wsi->c_protocol); + lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS)); /* tell the server what extensions we could support */ @@ -755,27 +833,20 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, context->protocols[0].callback(context, wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, - NULL, &p, (pkt + sizeof(pkt)) - p - 12); + NULL, &p, (pkt + sizeof(context->service_buffer)) - p - 12); p += sprintf(p, "\x0d\x0a"); /* prepare the expected server accept response */ - strcpy((char *)buf, key_b64); - strcpy((char *)&buf[strlen((char *)buf)], magic_websocket_guid); + key_b64[39] = '\0'; /* enforce composed length below buf sizeof */ + n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key_b64); - SHA1(buf, strlen((char *)buf), (unsigned char *)hash); + SHA1((unsigned char *)buf, n, (unsigned char *)hash); lws_b64_encode_string(hash, 20, - wsi->initial_handshake_hash_base64, - sizeof wsi->initial_handshake_hash_base64); - - /* done with these now */ - - free(wsi->c_path); - free(wsi->c_host); - if (wsi->c_origin) - free(wsi->c_origin); + wsi->u.hdr.ah->initial_handshake_hash_base64, + sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64)); return p; }