mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
introduce-ietf-05-framing-and-commandline-options.patch
This adds 05 support, and -v switches on test-client and test-ping to allow setting their ietf protocol version to 4 or 5. It also optimizes the masking to us a function pointer, which takes some conditionals out of the fast path. Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
f3d3b40364
commit
bfb051f3a3
9 changed files with 152 additions and 45 deletions
|
@ -87,6 +87,8 @@ libwebsocket_client_close(struct libwebsocket *wsi)
|
|||
* @protocol: Comma-separated list of protocols being asked for from
|
||||
* the server, or just one. The server will pick the one it
|
||||
* likes best.
|
||||
* @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
|
||||
* protocol supported, or the specific protocol ordinal
|
||||
*
|
||||
* This function creates a connection to a remote server
|
||||
*/
|
||||
|
@ -99,7 +101,8 @@ libwebsocket_client_connect(struct libwebsocket_context *this,
|
|||
const char *path,
|
||||
const char *host,
|
||||
const char *origin,
|
||||
const char *protocol)
|
||||
const char *protocol,
|
||||
int ietf_version_or_minus_one)
|
||||
{
|
||||
struct hostent *server_hostent;
|
||||
struct sockaddr_in server_addr;
|
||||
|
@ -137,13 +140,41 @@ libwebsocket_client_connect(struct libwebsocket_context *this,
|
|||
|
||||
this->wsi[this->fds_count] = wsi;
|
||||
|
||||
wsi->ietf_spec_revision = 4;
|
||||
/* -1 means just use latest supported */
|
||||
|
||||
if (ietf_version_or_minus_one == -1)
|
||||
ietf_version_or_minus_one = 5;
|
||||
|
||||
wsi->ietf_spec_revision = ietf_version_or_minus_one;
|
||||
wsi->name_buffer_pos = 0;
|
||||
wsi->user_space = NULL;
|
||||
wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
|
||||
wsi->pings_vs_pongs = 0;
|
||||
wsi->protocol = NULL;
|
||||
|
||||
/* set up appropriate masking */
|
||||
|
||||
wsi->xor_mask = xor_no_mask;
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 4:
|
||||
wsi->xor_mask = xor_mask_04;
|
||||
break;
|
||||
case 5:
|
||||
wsi->xor_mask = xor_mask_05;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"Client ietf version %d not supported\n",
|
||||
wsi->ietf_spec_revision);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* force no mask if he asks for that though */
|
||||
|
||||
if (this->options & LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK)
|
||||
wsi->xor_mask = xor_no_mask;
|
||||
|
||||
for (n = 0; n < WSI_TOKEN_COUNT; n++) {
|
||||
wsi->utf8_token[n].token = NULL;
|
||||
wsi->utf8_token[n].token_len = 0;
|
||||
|
@ -309,7 +340,8 @@ libwebsocket_client_connect(struct libwebsocket_context *this,
|
|||
p += sprintf(p, "\x0d\x0aSec-WebSocket-Origin: %s\x0d\x0a", origin);
|
||||
if (protocol != NULL)
|
||||
p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a", protocol);
|
||||
p += sprintf(p, "Sec-WebSocket-Version: 4\x0d\x0a\x0d\x0a");
|
||||
p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a\x0d\x0a",
|
||||
wsi->ietf_spec_revision);
|
||||
|
||||
|
||||
/* prepare the expected server accept response */
|
||||
|
|
|
@ -222,7 +222,7 @@ bail:
|
|||
*/
|
||||
|
||||
static int
|
||||
handshake_04(struct libwebsocket *wsi)
|
||||
handshake_0405(struct libwebsocket *wsi)
|
||||
{
|
||||
static const char *websocket_magic_guid_04 =
|
||||
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
|
@ -537,7 +537,6 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
|||
wsi->ietf_spec_revision =
|
||||
atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token);
|
||||
|
||||
|
||||
/*
|
||||
* Perform the handshake according to the protocol version the
|
||||
* client announced
|
||||
|
@ -545,20 +544,32 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
|||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 0: /* applies to 76 and 00 */
|
||||
wsi->xor_mask = xor_no_mask;
|
||||
if (handshake_00(wsi))
|
||||
goto bail;
|
||||
break;
|
||||
case 4: /* 04 */
|
||||
wsi->xor_mask = xor_mask_04;
|
||||
debug("libwebsocket_parse calling handshake_04\n");
|
||||
if (handshake_04(wsi))
|
||||
if (handshake_0405(wsi))
|
||||
goto bail;
|
||||
break;
|
||||
case 5: /* 05 */
|
||||
wsi->xor_mask = xor_mask_05;
|
||||
debug("libwebsocket_parse calling handshake_04\n");
|
||||
if (handshake_0405(wsi))
|
||||
goto bail;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown client spec version %d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
fprintf(stderr, "accepted v%02d connection\n",
|
||||
wsi->ietf_spec_revision);
|
||||
|
||||
break;
|
||||
|
||||
case WSI_STATE_ESTABLISHED:
|
||||
|
|
|
@ -607,6 +607,7 @@ static void sigpipe_handler(int x)
|
|||
* else ignored
|
||||
* @gid: group id to change to after setting listen socket, or -1.
|
||||
* @uid: user id to change to after setting listen socket, or -1.
|
||||
* @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
|
||||
*
|
||||
* This function creates the listening socket and takes care
|
||||
* of all initialization in one step.
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
|
||||
#define CONTEXT_PORT_NO_LISTEN 0
|
||||
|
||||
#define LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK 1
|
||||
|
||||
enum libwebsocket_context_options {
|
||||
LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK = 1,
|
||||
};
|
||||
|
||||
enum libwebsocket_callback_reasons {
|
||||
LWS_CALLBACK_ESTABLISHED,
|
||||
|
@ -258,7 +261,8 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
|
|||
const char *path,
|
||||
const char *host,
|
||||
const char *origin,
|
||||
const char *protocol);
|
||||
const char *protocol,
|
||||
int ietf_version_or_minus_one);
|
||||
|
||||
extern const char *
|
||||
libwebsocket_canonical_hostname(struct libwebsocket_context *this);
|
||||
|
|
|
@ -220,13 +220,15 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned char
|
||||
xor_mask(struct libwebsocket *wsi, unsigned char c)
|
||||
unsigned char
|
||||
xor_no_mask(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
xor_mask_04(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
if (wsi->protocol->owning_server->options &
|
||||
LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK)
|
||||
return c;
|
||||
|
||||
c ^= wsi->masking_key_04[wsi->frame_mask_index++];
|
||||
if (wsi->frame_mask_index == 20)
|
||||
wsi->frame_mask_index = 0;
|
||||
|
@ -234,6 +236,13 @@ xor_mask(struct libwebsocket *wsi, unsigned char c)
|
|||
return c;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
xor_mask_05(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
return c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
|
@ -255,9 +264,14 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
}
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
wsi->frame_masking_nonce_04[0] = c;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "libwebsocket_rx_sm doesn't know "
|
||||
"about spec version %d\n", wsi->ietf_spec_revision);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LWS_RXPS_04_MASK_NONCE_1:
|
||||
|
@ -275,6 +289,9 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK)
|
||||
goto post_mask;
|
||||
|
||||
if (wsi->ietf_spec_revision > 4)
|
||||
goto post_sha1;
|
||||
|
||||
/*
|
||||
* we are able to compute the frame key now
|
||||
* it's a SHA1 of ( frame nonce we were just sent, concatenated
|
||||
|
@ -297,6 +314,8 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
|
||||
SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
|
||||
|
||||
post_sha1:
|
||||
|
||||
/*
|
||||
* start from the zero'th byte in the XOR key buffer since
|
||||
* this is the start of a frame with a new key
|
||||
|
@ -356,7 +375,7 @@ post_mask:
|
|||
* FIN (b7)
|
||||
*/
|
||||
|
||||
c = xor_mask(wsi, c);
|
||||
c = wsi->xor_mask(wsi, c);
|
||||
|
||||
if (c & 0x70) {
|
||||
fprintf(stderr,
|
||||
|
@ -381,7 +400,7 @@ post_mask:
|
|||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN:
|
||||
c = xor_mask(wsi, c);
|
||||
c = wsi->xor_mask(wsi, c);
|
||||
|
||||
if (c & 0x80) {
|
||||
fprintf(stderr, "Frame has extensions "
|
||||
|
@ -430,14 +449,14 @@ post_mask:
|
|||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN16_2:
|
||||
c = xor_mask(wsi, c);
|
||||
c = wsi->xor_mask(wsi, c);
|
||||
|
||||
wsi->rx_packet_length = c << 8;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN16_1:
|
||||
c = xor_mask(wsi, c);
|
||||
c = wsi->xor_mask(wsi, c);
|
||||
|
||||
wsi->rx_packet_length |= c;
|
||||
wsi->lws_rx_parse_state =
|
||||
|
@ -445,7 +464,7 @@ post_mask:
|
|||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_8:
|
||||
c = xor_mask(wsi, c);
|
||||
c = wsi->xor_mask(wsi, c);
|
||||
if (c & 0x80) {
|
||||
fprintf(stderr, "b63 of length must be zero\n");
|
||||
/* kill the connection */
|
||||
|
@ -461,42 +480,42 @@ post_mask:
|
|||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_7:
|
||||
#if defined __LP64__
|
||||
wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 48;
|
||||
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 48;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_6:
|
||||
#if defined __LP64__
|
||||
wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 40;
|
||||
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 40;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_5:
|
||||
#if defined __LP64__
|
||||
wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 32;
|
||||
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 32;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_4:
|
||||
wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 24;
|
||||
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 24;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_3:
|
||||
wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 16;
|
||||
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 16;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_2:
|
||||
wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 8;
|
||||
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 8;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_1:
|
||||
wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c));
|
||||
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c));
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
break;
|
||||
|
@ -541,7 +560,8 @@ issue:
|
|||
|
||||
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
|
||||
wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->rx_user_buffer_head++)] = xor_mask(wsi, c);
|
||||
(wsi->rx_user_buffer_head++)] =
|
||||
wsi->xor_mask(wsi, c);
|
||||
|
||||
if (--wsi->rx_packet_length == 0) {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
|
@ -627,6 +647,7 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
}
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
/*
|
||||
* 04 logical framing from the spec (all this is masked when
|
||||
* incoming and has to be unmasked)
|
||||
|
@ -695,6 +716,11 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "client_rx_sm doesn't know how "
|
||||
"to handle spec version %02d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -943,7 +969,7 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
|||
|
||||
|
||||
static int
|
||||
libwebsocket_04_frame_mask_generate(struct libwebsocket *wsi)
|
||||
libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
|
||||
{
|
||||
int fd;
|
||||
char buf[4 + 20];
|
||||
|
@ -965,21 +991,27 @@ libwebsocket_04_frame_mask_generate(struct libwebsocket *wsi)
|
|||
}
|
||||
close(fd);
|
||||
|
||||
/* start masking from first byte of masking key buffer */
|
||||
wsi->frame_mask_index = 0;
|
||||
|
||||
if (wsi->ietf_spec_revision != 4)
|
||||
return 0;
|
||||
|
||||
/* 04 only does SHA-1 more complex key */
|
||||
|
||||
/*
|
||||
* the frame key is the frame nonce (4 bytes) followed by the
|
||||
* connection masking key, hashed by SHA1
|
||||
*/
|
||||
|
||||
memcpy(buf, wsi->frame_masking_nonce_04, 4);
|
||||
|
||||
memcpy(buf + 4, wsi->masking_key_04, 20);
|
||||
|
||||
/* concatenate the nonce with the connection key then hash it */
|
||||
|
||||
SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
|
||||
|
||||
/* start masking from first byte of masking key buffer */
|
||||
wsi->frame_mask_index = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1065,7 +1097,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
break;
|
||||
|
||||
case 4:
|
||||
|
||||
case 5:
|
||||
switch (protocol & 0xf) {
|
||||
case LWS_WRITE_TEXT:
|
||||
n = LWS_WS_OPCODE_04__TEXT_FRAME;
|
||||
|
@ -1135,11 +1167,12 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Deal with masking if appropriate
|
||||
* Deal with masking if we are in client -> server direction and
|
||||
* the protocol demands it
|
||||
*/
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT &&
|
||||
wsi->ietf_spec_revision == 4) {
|
||||
wsi->ietf_spec_revision >= 4) {
|
||||
|
||||
/*
|
||||
* this is only useful for security tests where it's required
|
||||
|
@ -1148,7 +1181,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
|
||||
if (!(protocol & LWS_WRITE_CLIENT_IGNORE_XOR_MASK)) {
|
||||
|
||||
if (libwebsocket_04_frame_mask_generate(wsi)) {
|
||||
if (libwebsocket_0405_frame_mask_generate(wsi)) {
|
||||
fprintf(stderr, "libwebsocket_write: "
|
||||
"frame mask generation failed\n");
|
||||
return 1;
|
||||
|
@ -1160,7 +1193,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
*/
|
||||
|
||||
for (n = 0; n < (len + pre + post); n++)
|
||||
buf[n - pre] = xor_mask(wsi, buf[n - pre]);
|
||||
buf[n - pre] = wsi->xor_mask(wsi, buf[n - pre]);
|
||||
}
|
||||
|
||||
/* make space for the frame nonce in clear */
|
||||
|
@ -1168,6 +1201,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
|
||||
/* copy the frame nonce into place */
|
||||
memcpy(&buf[0 - pre], wsi->frame_masking_nonce_04, 4);
|
||||
|
||||
}
|
||||
|
||||
send_raw:
|
||||
|
|
|
@ -224,6 +224,7 @@ struct libwebsocket {
|
|||
unsigned char final;
|
||||
|
||||
int pings_vs_pongs;
|
||||
unsigned char (*xor_mask)(struct libwebsocket *, unsigned char);
|
||||
|
||||
/* client support */
|
||||
char initial_handshake_hash_base64[30];
|
||||
|
@ -261,3 +262,12 @@ lws_b64_decode_string(const char *in, char *out, int out_size);
|
|||
|
||||
extern int
|
||||
lws_b64_selftest(void);
|
||||
|
||||
extern unsigned char
|
||||
xor_no_mask(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
extern unsigned char
|
||||
xor_mask_04(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
extern unsigned char
|
||||
xor_mask_05(struct libwebsocket *wsi, unsigned char c);
|
||||
|
|
|
@ -161,6 +161,8 @@ else ignored
|
|||
<dd>group id to change to after setting listen socket, or -1.
|
||||
<dt><b>uid</b>
|
||||
<dd>user id to change to after setting listen socket, or -1.
|
||||
<dt><b>options</b>
|
||||
<dd>0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
|
||||
</dl>
|
||||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
|
@ -340,7 +342,8 @@ Many protocols won't care becuse their packets are always small.
|
|||
<i>const char *</i> <b>path</b>,
|
||||
<i>const char *</i> <b>host</b>,
|
||||
<i>const char *</i> <b>origin</b>,
|
||||
<i>const char *</i> <b>protocol</b>)
|
||||
<i>const char *</i> <b>protocol</b>,
|
||||
<i>int</i> <b>ietf_version_or_minus_one</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>this</b>
|
||||
|
@ -362,6 +365,9 @@ signed certs
|
|||
<dd>Comma-separated list of protocols being asked for from
|
||||
the server, or just one. The server will pick the one it
|
||||
likes best.
|
||||
<dt><b>ietf_version_or_minus_one</b>
|
||||
<dd>-1 to ask to connect using the default, latest
|
||||
protocol supported, or the specific protocol ordinal
|
||||
</dl>
|
||||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
|
|
|
@ -158,6 +158,7 @@ static struct option options[] = {
|
|||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "ssl", no_argument, NULL, 's' },
|
||||
{ "killmask", no_argument, NULL, 'k' },
|
||||
{ "version", required_argument, NULL, 'v' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -171,6 +172,7 @@ int main(int argc, char **argv)
|
|||
const char *address;
|
||||
struct libwebsocket *wsi_dumb;
|
||||
struct libwebsocket *wsi_mirror;
|
||||
int ietf_version = -1; /* latest */
|
||||
|
||||
fprintf(stderr, "libwebsockets test client\n"
|
||||
"(C) Copyright 2010 Andy Green <andy@warmcat.com> "
|
||||
|
@ -179,10 +181,8 @@ int main(int argc, char **argv)
|
|||
if (argc < 2)
|
||||
goto usage;
|
||||
|
||||
optind++;
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "khsp:", options, NULL);
|
||||
n = getopt_long(argc, argv, "v:khsp:", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
|
@ -195,6 +195,9 @@ int main(int argc, char **argv)
|
|||
case 'k':
|
||||
opts = LWS_WRITE_CLIENT_IGNORE_XOR_MASK;
|
||||
break;
|
||||
case 'v':
|
||||
ietf_version = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
}
|
||||
|
@ -225,7 +228,7 @@ int main(int argc, char **argv)
|
|||
|
||||
wsi_dumb = libwebsocket_client_connect(context, address, port, use_ssl,
|
||||
"/", argv[optind], argv[optind],
|
||||
protocols[PROTOCOL_DUMB_INCREMENT].name);
|
||||
protocols[PROTOCOL_DUMB_INCREMENT].name, ietf_version);
|
||||
|
||||
if (wsi_dumb == NULL) {
|
||||
fprintf(stderr, "libwebsocket dumb connect failed\n");
|
||||
|
@ -236,7 +239,7 @@ int main(int argc, char **argv)
|
|||
|
||||
wsi_mirror = libwebsocket_client_connect(context, address, port,
|
||||
use_ssl, "/", argv[optind], argv[optind],
|
||||
protocols[PROTOCOL_LWS_MIRROR].name);
|
||||
protocols[PROTOCOL_LWS_MIRROR].name, ietf_version);
|
||||
|
||||
if (wsi_mirror == NULL) {
|
||||
fprintf(stderr, "libwebsocket dumb connect failed\n");
|
||||
|
|
|
@ -277,6 +277,7 @@ static struct option options[] = {
|
|||
{ "mirror", no_argument, NULL, 'm' },
|
||||
{ "replicate", required_argument, NULL, 'r' },
|
||||
{ "killmask", no_argument, NULL, 'k' },
|
||||
{ "version", required_argument, NULL, 'v' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -310,6 +311,7 @@ int main(int argc, char **argv)
|
|||
struct winsize w;
|
||||
unsigned long oldus = 0;
|
||||
unsigned long l;
|
||||
int ietf_version = -1;
|
||||
|
||||
if (argc < 2)
|
||||
goto usage;
|
||||
|
@ -318,7 +320,7 @@ int main(int argc, char **argv)
|
|||
optind++;
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "kr:hmfts:n:i:p:", options, NULL);
|
||||
n = getopt_long(argc, argv, "v:kr:hmfts:n:i:p:", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
|
@ -356,6 +358,9 @@ int main(int argc, char **argv)
|
|||
case 'k':
|
||||
write_options = LWS_WRITE_CLIENT_IGNORE_XOR_MASK;
|
||||
break;
|
||||
case 'v':
|
||||
ietf_version = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
goto usage;
|
||||
|
@ -393,8 +398,9 @@ int main(int argc, char **argv)
|
|||
|
||||
for (n = 0; n < clients; n++) {
|
||||
wsi[n] = libwebsocket_client_connect(context, address, port,
|
||||
use_ssl, "/", libwebsocket_canonical_hostname(context),
|
||||
"origin", protocols[PROTOCOL_LWS_MIRROR].name);
|
||||
use_ssl, "/", address,
|
||||
"origin", protocols[PROTOCOL_LWS_MIRROR].name,
|
||||
ietf_version);
|
||||
if (wsi[n] == NULL) {
|
||||
fprintf(stderr, "client connnection %d failed to "
|
||||
"connect\n", n);
|
||||
|
|
Loading…
Add table
Reference in a new issue