mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
client convert to new headers scheme eliminating mallocs
This removes all the direct wsi members specific to clients, most of them are moved to being fake headers in the next 3-layer header scheme, c_port moves to being a member of the u.hdr unionized struct. It gets rid of a lot of fiddly mallocs and frees(), despite it adds a small internal API to create the fake headers, actually the patch deletes more than it adds... Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
bebc1bb852
commit
e77fb804dc
6 changed files with 97 additions and 135 deletions
|
@ -9,6 +9,7 @@ struct libwebsocket *__libwebsocket_client_connect_2(
|
|||
struct sockaddr_in server_addr;
|
||||
int n;
|
||||
int plen = 0;
|
||||
const char *ads;
|
||||
|
||||
lwsl_client("__libwebsocket_client_connect_2\n");
|
||||
|
||||
|
@ -21,25 +22,29 @@ struct libwebsocket *__libwebsocket_client_connect_2(
|
|||
"CONNECT %s:%u HTTP/1.0\x0d\x0a"
|
||||
"User-agent: libwebsockets\x0d\x0a"
|
||||
/*Proxy-authorization: basic aGVsbG86d29ybGQ= */
|
||||
"\x0d\x0a", wsi->c_address, wsi->c_port);
|
||||
"\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
|
||||
wsi->u.hdr.c_port);
|
||||
|
||||
/* OK from now on we talk via the proxy */
|
||||
/* OK from now on we talk via the proxy, so connect to that */
|
||||
|
||||
free(wsi->c_address);
|
||||
wsi->c_address = strdup(context->http_proxy_address);
|
||||
wsi->c_port = context->http_proxy_port;
|
||||
/* (will overwrite existing pointer, leaving old string/frag there but unreferenced) */
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, context->http_proxy_address))
|
||||
goto oom4;
|
||||
wsi->u.hdr.c_port = context->http_proxy_port;
|
||||
}
|
||||
|
||||
/*
|
||||
* prepare the actual connection (to the proxy, if any)
|
||||
*/
|
||||
|
||||
lwsl_client("__libwebsocket_client_connect_2: address %s\n",
|
||||
wsi->c_address);
|
||||
ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
|
||||
|
||||
server_hostent = gethostbyname(wsi->c_address);
|
||||
lwsl_client("__libwebsocket_client_connect_2: address %s\n", ads);
|
||||
|
||||
server_hostent = gethostbyname(ads);
|
||||
if (server_hostent == NULL) {
|
||||
lwsl_err("Unable to get host name from %s\n", wsi->c_address);
|
||||
lwsl_err("Unable to get host name from %s\n", ads);
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
|
@ -51,7 +56,7 @@ struct libwebsocket *__libwebsocket_client_connect_2(
|
|||
}
|
||||
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(wsi->c_port);
|
||||
server_addr.sin_port = htons(wsi->u.hdr.c_port);
|
||||
server_addr.sin_addr = *((struct in_addr *)server_hostent->h_addr);
|
||||
bzero(&server_addr.sin_zero, 8);
|
||||
|
||||
|
@ -119,15 +124,7 @@ struct libwebsocket *__libwebsocket_client_connect_2(
|
|||
return wsi;
|
||||
|
||||
oom4:
|
||||
if (wsi->c_protocol)
|
||||
free(wsi->c_protocol);
|
||||
|
||||
if (wsi->c_origin)
|
||||
free(wsi->c_origin);
|
||||
|
||||
free(wsi->c_host);
|
||||
free(wsi->c_path);
|
||||
|
||||
free(wsi->u.hdr.ah);
|
||||
bail1:
|
||||
free(wsi);
|
||||
|
||||
|
@ -203,58 +200,37 @@ libwebsocket_client_connect(struct libwebsocket_context *context,
|
|||
wsi->use_ssl = ssl_connection;
|
||||
#endif
|
||||
|
||||
wsi->c_port = port;
|
||||
wsi->c_address = strdup(address);
|
||||
|
||||
/* copy parameters over so state machine has access */
|
||||
|
||||
wsi->c_path = (char *)malloc(strlen(path) + 1);
|
||||
if (wsi->c_path == NULL)
|
||||
goto bail1;
|
||||
strcpy(wsi->c_path, path);
|
||||
|
||||
wsi->c_host = (char *)malloc(strlen(host) + 1);
|
||||
if (wsi->c_host == NULL)
|
||||
goto oom1;
|
||||
strcpy(wsi->c_host, host);
|
||||
|
||||
if (origin) {
|
||||
wsi->c_origin = (char *)malloc(strlen(origin) + 1);
|
||||
if (wsi->c_origin == NULL)
|
||||
goto oom2;
|
||||
strcpy(wsi->c_origin, origin);
|
||||
} else
|
||||
wsi->c_origin = NULL;
|
||||
|
||||
wsi->c_callback = NULL;
|
||||
if (protocol) {
|
||||
const char *pc;
|
||||
struct libwebsocket_protocols *pp;
|
||||
|
||||
wsi->c_protocol = (char *)malloc(strlen(protocol) + 1);
|
||||
if (wsi->c_protocol == NULL)
|
||||
goto oom3;
|
||||
|
||||
strcpy(wsi->c_protocol, protocol);
|
||||
|
||||
pc = protocol;
|
||||
while (*pc && *pc != ',')
|
||||
pc++;
|
||||
n = pc - protocol;
|
||||
pp = context->protocols;
|
||||
while (pp->name && !wsi->c_callback) {
|
||||
if (!strncmp(protocol, pp->name, n))
|
||||
wsi->c_callback = pp->callback;
|
||||
pp++;
|
||||
}
|
||||
} else
|
||||
wsi->c_protocol = NULL;
|
||||
|
||||
if (!wsi->c_callback)
|
||||
wsi->c_callback = context->protocols[0].callback;
|
||||
|
||||
if (lws_allocate_header_table(wsi))
|
||||
goto oom3;
|
||||
goto bail;
|
||||
|
||||
/*
|
||||
* we're not necessarily in a position to action these right away,
|
||||
* stash them... we only need during connect phase so u.hdr is fine
|
||||
*/
|
||||
wsi->u.hdr.c_port = port;
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
|
||||
goto bail1;
|
||||
|
||||
/* these only need u.hdr lifetime as well */
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
|
||||
goto bail1;
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
|
||||
goto bail1;
|
||||
|
||||
if (origin)
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN, origin))
|
||||
goto bail1;
|
||||
/*
|
||||
* this is a list of protocols we tell the server we're okay with
|
||||
* stash it for later when we compare server response with it
|
||||
*/
|
||||
if (protocol)
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol))
|
||||
goto bail1;
|
||||
|
||||
wsi->protocol = &context->protocols[0];
|
||||
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/*
|
||||
|
@ -293,17 +269,9 @@ libwebsocket_client_connect(struct libwebsocket_context *context,
|
|||
|
||||
return __libwebsocket_client_connect_2(context, wsi);
|
||||
|
||||
oom3:
|
||||
if (wsi->c_origin)
|
||||
free(wsi->c_origin);
|
||||
|
||||
oom2:
|
||||
free(wsi->c_host);
|
||||
|
||||
oom1:
|
||||
free(wsi->c_path);
|
||||
|
||||
bail1:
|
||||
free(wsi->u.hdr.ah);
|
||||
bail:
|
||||
free(wsi);
|
||||
|
||||
return NULL;
|
||||
|
|
50
lib/client.c
50
lib/client.c
|
@ -309,8 +309,6 @@ 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_WS_CLIENT_WAITING_SERVER_REPLY\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
|
@ -398,7 +396,7 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
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");
|
||||
|
@ -421,9 +419,6 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
* default to first protocol
|
||||
*/
|
||||
wsi->protocol = &context->protocols[0];
|
||||
wsi->c_callback = wsi->protocol->callback;
|
||||
free(wsi->c_protocol);
|
||||
|
||||
goto check_extensions;
|
||||
}
|
||||
|
||||
|
@ -441,11 +436,6 @@ 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", p);
|
||||
|
@ -460,7 +450,6 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
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++;
|
||||
|
@ -659,12 +648,10 @@ check_accept:
|
|||
return 0;
|
||||
|
||||
bail3:
|
||||
if (wsi->c_protocol)
|
||||
free(wsi->c_protocol);
|
||||
|
||||
bail2:
|
||||
if (wsi->c_callback)
|
||||
wsi->c_callback(context, wsi,
|
||||
if (wsi->protocol)
|
||||
wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
|
@ -707,12 +694,6 @@ 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;
|
||||
|
@ -746,28 +727,24 @@ 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, "Host: %s\x0d\x0a", wsi->c_host);
|
||||
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 */
|
||||
|
||||
|
@ -843,13 +820,6 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
|||
wsi->u.hdr.initial_handshake_hash_base64,
|
||||
sizeof wsi->u.hdr.initial_handshake_hash_base64);
|
||||
|
||||
/* done with these now */
|
||||
|
||||
free(wsi->c_path);
|
||||
free(wsi->c_host);
|
||||
if (wsi->c_origin)
|
||||
free(wsi->c_origin);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -358,10 +358,6 @@ just_kill_connection:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
if (wsi->c_address)
|
||||
free(wsi->c_address);
|
||||
#endif
|
||||
if (wsi->u.ws.rxflow_buffer)
|
||||
free(wsi->u.ws.rxflow_buffer);
|
||||
|
||||
|
|
|
@ -240,6 +240,14 @@ enum lws_token_indexes {
|
|||
WSI_TOKEN_HTTP,
|
||||
WSI_TOKEN_MUXURL,
|
||||
|
||||
/* use token storage to stash these */
|
||||
|
||||
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
|
||||
_WSI_TOKEN_CLIENT_PEER_ADDRESS,
|
||||
_WSI_TOKEN_CLIENT_URI,
|
||||
_WSI_TOKEN_CLIENT_HOST,
|
||||
_WSI_TOKEN_CLIENT_ORIGIN,
|
||||
|
||||
/* always last real token index*/
|
||||
WSI_TOKEN_COUNT,
|
||||
/* parser state additions */
|
||||
|
|
|
@ -370,6 +370,33 @@ char * lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h)
|
|||
return &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset];
|
||||
}
|
||||
|
||||
int lws_hdr_simple_create(struct libwebsocket *wsi, enum lws_token_indexes h, const char *s)
|
||||
{
|
||||
wsi->u.hdr.ah->next_frag_index++;
|
||||
if (wsi->u.hdr.ah->next_frag_index == sizeof(wsi->u.hdr.ah->frags) / sizeof(wsi->u.hdr.ah->frags[0])) {
|
||||
lwsl_warn("More header fragments than we can deal with, dropping\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->next_frag_index;
|
||||
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset = wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
|
||||
|
||||
do {
|
||||
if (wsi->u.hdr.ah->pos == sizeof wsi->u.hdr.ah->data) {
|
||||
lwsl_err("Ran out of header data space\n");
|
||||
return -1;
|
||||
}
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s;
|
||||
if (*s)
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
|
||||
} while (*s++);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
int n;
|
||||
|
|
|
@ -330,6 +330,7 @@ struct _lws_header_related {
|
|||
int current_alloc_len;
|
||||
#ifndef LWS_NO_CLIENT
|
||||
char initial_handshake_hash_base64[30];
|
||||
unsigned short c_port;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -391,17 +392,6 @@ struct libwebsocket {
|
|||
struct _lws_websocket_related ws;
|
||||
} u;
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
char *c_path;
|
||||
char *c_host;
|
||||
char *c_origin;
|
||||
char *c_protocol;
|
||||
callback_function *c_callback;
|
||||
|
||||
char *c_address;
|
||||
unsigned short c_port;
|
||||
#endif
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
SSL *ssl;
|
||||
BIO *client_bio;
|
||||
|
@ -504,6 +494,9 @@ lws_allocate_header_table(struct libwebsocket *wsi);
|
|||
extern char *
|
||||
lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h);
|
||||
|
||||
extern int
|
||||
lws_hdr_simple_create(struct libwebsocket *wsi, enum lws_token_indexes h, const char *s);
|
||||
|
||||
#ifndef LWS_OPENSSL_SUPPORT
|
||||
|
||||
unsigned char *
|
||||
|
|
Loading…
Add table
Reference in a new issue