raw: enable server and client raw sockets
This commit is contained in:
parent
4578036b53
commit
205ccedf6e
13 changed files with 410 additions and 53 deletions
116
README.coding.md
116
README.coding.md
|
@ -440,6 +440,122 @@ on the flags during open.
|
|||
7) There is an optional `mod_time` uint32_t member in the generic fop_fd. If you are able to set it during open, you
|
||||
should indicate it by setting `LWS_FOP_FLAG_MOD_TIME_VALID` on the flags.
|
||||
|
||||
@section rawfd RAW file descriptor polling
|
||||
|
||||
LWS allows you to include generic platform file descriptors in the lws service / poll / event loop.
|
||||
|
||||
Open your fd normally and then
|
||||
|
||||
```
|
||||
lws_sock_file_fd_type u;
|
||||
|
||||
u.filefd = your_open_file_fd;
|
||||
|
||||
if (!lws_adopt_descriptor_vhost(vhost, 0, u,
|
||||
"protocol-name-to-bind-to",
|
||||
optional_wsi_parent_or_NULL)) {
|
||||
// failed
|
||||
}
|
||||
|
||||
// OK
|
||||
```
|
||||
|
||||
A wsi is created for the file fd that acts like other wsi, you will get these
|
||||
callbacks on the named protocol
|
||||
|
||||
```
|
||||
LWS_CALLBACK_RAW_ADOPT_FILE
|
||||
LWS_CALLBACK_RAW_RX_FILE
|
||||
LWS_CALLBACK_RAW_WRITEABLE_FILE
|
||||
LWS_CALLBACK_RAW_CLOSE_FILE
|
||||
```
|
||||
|
||||
starting with LWS_CALLBACK_RAW_ADOPT_FILE.
|
||||
|
||||
`protocol-lws-raw-test` plugin provides a method for testing this with
|
||||
`libwebsockets-test-server-v2.0`:
|
||||
|
||||
The plugin creates a FIFO on your system called "/tmp/lws-test-raw"
|
||||
|
||||
You can feed it data through the FIFO like this
|
||||
|
||||
```
|
||||
$ sudo sh -c "echo hello > /tmp/lws-test-raw"
|
||||
```
|
||||
|
||||
This plugin simply prints the data. But it does it through the lws event
|
||||
loop / service poll.
|
||||
|
||||
@section rawsrvsocket RAW server socket descriptor polling
|
||||
|
||||
You can also enable your vhost to accept RAW socket connections, in addition to
|
||||
HTTP[s] and WS[s]. If the first bytes written on the connection are not a
|
||||
valid HTTP method, then the connection switches to RAW mode.
|
||||
|
||||
This is disabled by default, you enable it by setting the `.options` flag
|
||||
LWS_SERVER_OPTION_FALLBACK_TO_RAW when creating the vhost.
|
||||
|
||||
RAW mode socket connections receive the following callbacks
|
||||
|
||||
```
|
||||
LWS_CALLBACK_RAW_ADOPT
|
||||
LWS_CALLBACK_RAW_RX
|
||||
LWS_CALLBACK_RAW_WRITEABLE
|
||||
LWS_CALLBACK_RAW_CLOSE
|
||||
```
|
||||
|
||||
You can control which protocol on your vhost handles these RAW mode
|
||||
incoming connections by marking the selected protocol with a pvo `raw`, eg
|
||||
|
||||
```
|
||||
"protocol-lws-raw-test": {
|
||||
"status": "ok",
|
||||
"raw": "1"
|
||||
},
|
||||
```
|
||||
|
||||
The "raw" pvo marks this protocol as being used for RAW connections.
|
||||
|
||||
`protocol-lws-raw-test` plugin provides a method for testing this with
|
||||
`libwebsockets-test-server-v2.0`:
|
||||
|
||||
Run libwebsockets-test-server-v2.0 and connect to it by telnet, eg
|
||||
|
||||
```
|
||||
$ telnet 127.0.0.1 7681
|
||||
```
|
||||
|
||||
type something that isn't a valid HTTP method and enter, before the
|
||||
connection times out. The connection will switch to RAW mode using this
|
||||
protocol, and pass the unused rx as a raw RX callback.
|
||||
|
||||
The test protocol echos back what was typed on telnet to telnet.
|
||||
|
||||
@section rawclientsocket RAW client socket descriptor polling
|
||||
|
||||
You can now also open RAW socket connections in client mode.
|
||||
|
||||
Follow the usual method for creating a client connection, but set the
|
||||
`info.method` to "RAW". When the connection is made, the wsi will be
|
||||
converted to RAW mode and operate using the same callbacks as the
|
||||
server RAW sockets described above.
|
||||
|
||||
The libwebsockets-test-client supports this using raw:// URLS. To
|
||||
test, open a netcat listener in one window
|
||||
|
||||
```
|
||||
$ nc -l 9999
|
||||
```
|
||||
|
||||
and in another window, connect to it using the test client
|
||||
|
||||
```
|
||||
$ libwebsockets-test-client raw://127.0.0.1:9999
|
||||
```
|
||||
|
||||
The connection should succeed, and text typed in the netcat window (including a CRLF)
|
||||
will be received in the client.
|
||||
|
||||
@section ecdh ECDH Support
|
||||
|
||||
ECDH Certs are now supported. Enable the CMake option
|
||||
|
|
33
lib/client.c
33
lib/client.c
|
@ -196,6 +196,9 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
case LWSCM_WSCL_ISSUE_HANDSHAKE2:
|
||||
p = lws_generate_client_handshake(wsi, p);
|
||||
if (p == NULL) {
|
||||
if (wsi->mode == LWSCM_RAW)
|
||||
return 0;
|
||||
|
||||
lwsl_err("Failed to generate handshake for client\n");
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
|
@ -1027,6 +1030,36 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt)
|
|||
} else
|
||||
wsi->do_ws = 0;
|
||||
|
||||
if (!strcmp(meth, "RAW")) {
|
||||
const char *pp = lws_hdr_simple_ptr(wsi,
|
||||
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
|
||||
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
lwsl_notice("client transition to raw\n");
|
||||
if (pp) {
|
||||
const struct lws_protocols *pr;
|
||||
|
||||
pr = lws_vhost_name_to_protocol(wsi->vhost, pp);
|
||||
|
||||
if (!pr) {
|
||||
lwsl_err("protocol %s not enabled on vhost\n",
|
||||
pp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lws_bind_protocol(wsi, pr);
|
||||
}
|
||||
if ((wsi->protocol->callback)(wsi,
|
||||
LWS_CALLBACK_RAW_ADOPT,
|
||||
wsi->user_space, NULL, 0))
|
||||
return NULL;
|
||||
|
||||
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
|
||||
lws_union_transition(wsi, LWSCM_RAW);
|
||||
lws_header_table_detach(wsi, 1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (wsi->do_ws) {
|
||||
/*
|
||||
* create the random key
|
||||
|
|
|
@ -175,6 +175,13 @@ lws_protocol_init(struct lws_context *context)
|
|||
vh->protocols[n].name);
|
||||
vh->default_protocol_index = n;
|
||||
}
|
||||
if (!strcmp(pvo->name, "raw")) {
|
||||
lwsl_notice("Setting raw "
|
||||
"protocol for vh %s to %s\n",
|
||||
vh->name,
|
||||
vh->protocols[n].name);
|
||||
vh->raw_protocol_index = n;
|
||||
}
|
||||
pvo = pvo->next;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,11 @@ lws_read(struct lws *wsi, unsigned char *buf, size_t len)
|
|||
/* Handshake indicates this session is done. */
|
||||
goto bail;
|
||||
|
||||
/* we might have transitioned to RAW */
|
||||
if (wsi->mode == LWSCM_RAW)
|
||||
/* we gave the read buffer to RAW handler already */
|
||||
goto read_ok;
|
||||
|
||||
/*
|
||||
* It's possible that we've exhausted our data already, or
|
||||
* rx flow control has stopped us dealing with this early,
|
||||
|
|
|
@ -165,6 +165,32 @@ lws_remove_child_from_any_parent(struct lws *wsi)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
|
||||
{
|
||||
// if (wsi->protocol == p)
|
||||
// return 0;
|
||||
|
||||
if (wsi->protocol)
|
||||
wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
|
||||
wsi->user_space, NULL, 0);
|
||||
if (!wsi->user_space_externally_allocated)
|
||||
lws_free_set_NULL(wsi->user_space);
|
||||
|
||||
wsi->protocol = p;
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
if (lws_ensure_user_space(wsi))
|
||||
return 1;
|
||||
|
||||
if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL,
|
||||
wsi->user_space, NULL, 0))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
||||
{
|
||||
|
|
|
@ -1612,6 +1612,8 @@ enum lws_context_options {
|
|||
* the context, only the string you give in the client connect
|
||||
* info for .origin (if any) will be used directly.
|
||||
*/
|
||||
LWS_SERVER_OPTION_FALLBACK_TO_RAW = (1 << 20),
|
||||
/**< (VH) if invalid http is coming in the first line, */
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
};
|
||||
|
|
|
@ -813,9 +813,16 @@ swallow:
|
|||
}
|
||||
/*
|
||||
* hm it's an unknown http method from a client in fact,
|
||||
* treat as dangerous
|
||||
* it cannot be valid http
|
||||
*/
|
||||
if (m == ARRAY_SIZE(methods)) {
|
||||
/*
|
||||
* are we set up to accept raw in these cases?
|
||||
*/
|
||||
if (lws_check_opt(wsi->vhost->options,
|
||||
LWS_SERVER_OPTION_FALLBACK_TO_RAW))
|
||||
return 2; /* transition to raw */
|
||||
|
||||
lwsl_info("Unknown method - dropping\n");
|
||||
goto forbid;
|
||||
}
|
||||
|
|
|
@ -795,6 +795,7 @@ struct lws_vhost {
|
|||
unsigned int created_vhost_protocols:1;
|
||||
|
||||
unsigned char default_protocol_index;
|
||||
unsigned char raw_protocol_index;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
112
lib/server.c
112
lib/server.c
|
@ -210,7 +210,7 @@ lws_select_vhost(struct lws_context *context, int port, const char *servername)
|
|||
if (p)
|
||||
colon = p - servername;
|
||||
|
||||
/* first try exact matches */
|
||||
/* Priotity 1: first try exact matches */
|
||||
|
||||
while (vhost) {
|
||||
if (port == vhost->listen_port &&
|
||||
|
@ -222,7 +222,7 @@ lws_select_vhost(struct lws_context *context, int port, const char *servername)
|
|||
}
|
||||
|
||||
/*
|
||||
* if no exact matches, try matching *.vhost-name
|
||||
* Priority 2: if no exact matches, try matching *.vhost-name
|
||||
* unintentional matches are possible but resolve to x.com for *.x.com
|
||||
* which is reasonable. If exact match exists we already chose it and
|
||||
* never reach here. SSL will still fail it if the cert doesn't allow
|
||||
|
@ -243,6 +243,20 @@ lws_select_vhost(struct lws_context *context, int port, const char *servername)
|
|||
vhost = vhost->vhost_next;
|
||||
}
|
||||
|
||||
/* Priority 3: match the first vhost on our port */
|
||||
|
||||
vhost = context->vhost_list;
|
||||
while (vhost) {
|
||||
if (port == vhost->listen_port) {
|
||||
lwsl_info("vhost match to %s based on port %d\n",
|
||||
vhost->name, port);
|
||||
return vhost;
|
||||
}
|
||||
vhost = vhost->vhost_next;
|
||||
}
|
||||
|
||||
/* no match */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1137,43 +1151,19 @@ transaction_result_n:
|
|||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
|
||||
{
|
||||
// if (wsi->protocol == p)
|
||||
// return 0;
|
||||
|
||||
if (wsi->protocol)
|
||||
wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
|
||||
wsi->user_space, NULL, 0);
|
||||
if (!wsi->user_space_externally_allocated)
|
||||
lws_free_set_NULL(wsi->user_space);
|
||||
|
||||
wsi->protocol = p;
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
if (lws_ensure_user_space(wsi))
|
||||
return 1;
|
||||
|
||||
if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL,
|
||||
wsi->user_space, NULL, 0))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
||||
{
|
||||
int protocol_len, n = 0, hit, non_space_char_found = 0, m;
|
||||
struct lws_context *context = lws_get_context(wsi);
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
struct _lws_header_related hdr;
|
||||
struct allocated_headers *ah;
|
||||
int protocol_len, n = 0, hit, non_space_char_found = 0;
|
||||
unsigned char *obuf = *buf;
|
||||
char protocol_list[128];
|
||||
char protocol_name[64];
|
||||
size_t olen = len;
|
||||
char *p;
|
||||
|
||||
if (len >= 10000000) {
|
||||
|
@ -1195,7 +1185,38 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (lws_parse(wsi, *(*buf)++)) {
|
||||
m = lws_parse(wsi, *(*buf)++);
|
||||
if (m) {
|
||||
if (m == 2) {
|
||||
/*
|
||||
* we are transitioning from http with
|
||||
* an AH, to raw. Drop the ah and set
|
||||
* the mode.
|
||||
*/
|
||||
raw_transition:
|
||||
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
lws_bind_protocol(wsi, &wsi->vhost->protocols[
|
||||
wsi->vhost->
|
||||
raw_protocol_index]);
|
||||
lwsl_info("transition to raw vh %s prot %d\n",
|
||||
wsi->vhost->name,
|
||||
wsi->vhost->raw_protocol_index);
|
||||
if ((wsi->protocol->callback)(wsi,
|
||||
LWS_CALLBACK_RAW_ADOPT,
|
||||
wsi->user_space, NULL, 0))
|
||||
goto bail_nuke_ah;
|
||||
|
||||
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
|
||||
lws_union_transition(wsi, LWSCM_RAW);
|
||||
lws_header_table_detach(wsi, 1);
|
||||
|
||||
if (m == 2 && (wsi->protocol->callback)(wsi,
|
||||
LWS_CALLBACK_RAW_RX,
|
||||
wsi->user_space, obuf, olen))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
lwsl_info("lws_parse failed\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
@ -1253,13 +1274,8 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECT)) {
|
||||
lwsl_info("Changing to RAW mode\n");
|
||||
lws_union_transition(wsi, LWSCM_RAW);
|
||||
if (!wsi->more_rx_waiting) {
|
||||
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
|
||||
|
||||
//lwsl_notice("%p: dropping ah EST\n", wsi);
|
||||
lws_header_table_detach(wsi, 1);
|
||||
}
|
||||
m = 0;
|
||||
goto raw_transition;
|
||||
}
|
||||
|
||||
wsi->mode = LWSCM_PRE_WS_SERVING_ACCEPT;
|
||||
|
@ -1991,6 +2007,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
case LWSCM_HTTP_SERVING:
|
||||
case LWSCM_HTTP_SERVING_ACCEPTED:
|
||||
case LWSCM_HTTP2_SERVING:
|
||||
case LWSCM_RAW:
|
||||
|
||||
/* handle http headers coming in */
|
||||
|
||||
|
@ -2033,9 +2050,9 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
|
||||
/* these states imply we MUST have an ah attached */
|
||||
|
||||
if (wsi->state == LWSS_HTTP ||
|
||||
if (wsi->mode != LWSCM_RAW && (wsi->state == LWSS_HTTP ||
|
||||
wsi->state == LWSS_HTTP_ISSUING_FILE ||
|
||||
wsi->state == LWSS_HTTP_HEADERS) {
|
||||
wsi->state == LWSS_HTTP_HEADERS)) {
|
||||
if (!wsi->u.hdr.ah) {
|
||||
|
||||
//lwsl_err("wsi %p: missing ah\n", wsi);
|
||||
|
@ -2105,7 +2122,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
|
||||
len = lws_ssl_capable_read(wsi, pt->serv_buf,
|
||||
context->pt_serv_buf_size);
|
||||
// lwsl_notice("%s: wsi %p read %d\r\n", __func__, wsi, len);
|
||||
lwsl_debug("%s: wsi %p read %d\r\n", __func__, wsi, len);
|
||||
switch (len) {
|
||||
case 0:
|
||||
lwsl_info("%s: read 0 len\n", __func__);
|
||||
|
@ -2124,10 +2141,10 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
wsi, LWS_CALLBACK_RAW_RX,
|
||||
wsi->user_space, pt->serv_buf, len);
|
||||
if (n < 0) {
|
||||
lwsl_info("raw writeable_fail\n");
|
||||
lwsl_info("LWS_CALLBACK_RAW_RX_fail\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
goto try_pollout;
|
||||
}
|
||||
|
||||
/* just ignore incoming if waiting for close */
|
||||
|
@ -2162,6 +2179,17 @@ try_pollout:
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (wsi->mode == LWSCM_RAW) {
|
||||
n = user_callback_handle_rxflow(wsi->protocol->callback,
|
||||
wsi, LWS_CALLBACK_RAW_WRITEABLE,
|
||||
wsi->user_space, NULL, 0);
|
||||
if (n < 0) {
|
||||
lwsl_info("writeable_fail\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!wsi->hdr_parsing_completed)
|
||||
break;
|
||||
|
||||
|
|
|
@ -863,13 +863,15 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
|
|||
goto handled;
|
||||
}
|
||||
#endif
|
||||
/* fallthru */
|
||||
case LWSCM_RAW:
|
||||
n = lws_server_socket_service(context, wsi, pollfd);
|
||||
if (n) /* closed by above */
|
||||
return 1;
|
||||
goto handled;
|
||||
|
||||
case LWSCM_RAW_FILEDESC:
|
||||
case LWSCM_RAW:
|
||||
|
||||
if (pollfd->revents & LWS_POLLOUT) {
|
||||
n = lws_calllback_as_writeable(wsi);
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
|
||||
|
@ -892,6 +894,9 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
|
|||
goto close_and_handled;
|
||||
}
|
||||
}
|
||||
|
||||
if (pollfd->revents & LWS_POLLHUP)
|
||||
goto close_and_handled;
|
||||
n = 0;
|
||||
goto handled;
|
||||
|
||||
|
|
|
@ -17,6 +17,13 @@
|
|||
* may be proprietary. So unlike the library itself, they are licensed
|
||||
* Public Domain.
|
||||
*
|
||||
* This plugin test both raw file descriptors and raw socket descriptors. It
|
||||
* can test both or just one depending on how you configure it. libwebsockets-
|
||||
* test-server-v2.0 is set up to test both.
|
||||
*
|
||||
* RAW File Descriptor Testing
|
||||
* ===========================
|
||||
*
|
||||
* Enable on a vhost like this
|
||||
*
|
||||
* "protocol-lws-raw-test": {
|
||||
|
@ -28,8 +35,33 @@
|
|||
*
|
||||
* $ sudo sh -c "echo hello > /tmp/lws-test-raw"
|
||||
*
|
||||
* This plugin simply prints the data. But it does it through the lws event loop /
|
||||
* service poll.
|
||||
* This plugin simply prints the data. But it does it through the lws event
|
||||
* loop / service poll.
|
||||
*
|
||||
*
|
||||
* RAW Socket Descriptor Testing
|
||||
* =============================
|
||||
*
|
||||
* 1) You must give the vhost the option flag LWS_SERVER_OPTION_FALLBACK_TO_RAW
|
||||
*
|
||||
* 2) Enable on a vhost like this
|
||||
*
|
||||
* "protocol-lws-raw-test": {
|
||||
* "status": "ok",
|
||||
* "raw": "1"
|
||||
* },
|
||||
*
|
||||
* The "raw" pvo marks this protocol as being used for RAW connections.
|
||||
*
|
||||
* 3) Run libwebsockets-test-server-v2.0 and connect to it by telnet, eg
|
||||
*
|
||||
* telnet 127.0.0.1 7681
|
||||
*
|
||||
* type something that isn't a valid HTTP method and enter, before the
|
||||
* connection times out. The connection will switch to RAW mode using this
|
||||
* protocol, and pass the unused rx as a raw RX callback.
|
||||
*
|
||||
* The test protocol echos back what was typed on telnet to telnet.
|
||||
*/
|
||||
|
||||
#if !defined (LWS_PLUGIN_STATIC)
|
||||
|
@ -51,6 +83,8 @@ struct per_vhost_data__raw_test {
|
|||
|
||||
struct per_session_data__raw_test {
|
||||
int number;
|
||||
unsigned char buf[128];
|
||||
int len;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -84,8 +118,8 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
pvo = pvo->next;
|
||||
}
|
||||
if (vhd->fifo_path[0] == '\0') {
|
||||
lwsl_err("Missing pvo \"fifo-path\"\n");
|
||||
return 1;
|
||||
lwsl_err("%s: Missing pvo \"fifo-path\", raw file fd testing disabled\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlink(vhd->fifo_path);
|
||||
|
@ -101,7 +135,9 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
}
|
||||
lwsl_notice("FIFO %s created\n", vhd->fifo_path);
|
||||
u.filefd = vhd->fifo;
|
||||
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u, "protocol-lws-raw-test", NULL)) {
|
||||
if (!lws_adopt_descriptor_vhost(vhd->vhost, 0, u,
|
||||
"protocol-lws-raw-test",
|
||||
NULL)) {
|
||||
lwsl_err("Failed to adopt fifo descriptor\n");
|
||||
close(vhd->fifo);
|
||||
unlink(vhd->fifo_path);
|
||||
|
@ -118,6 +154,11 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
}
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* Callbacks related to Raw file descriptor testing
|
||||
*/
|
||||
|
||||
case LWS_CALLBACK_RAW_ADOPT_FILE:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_ADOPT_FILE\n");
|
||||
break;
|
||||
|
@ -179,6 +220,32 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE_FILE\n");
|
||||
break;
|
||||
|
||||
/*
|
||||
* Callbacks related to Raw socket descriptor testing
|
||||
*/
|
||||
|
||||
case LWS_CALLBACK_RAW_ADOPT:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_ADOPT\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_RX:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_RX %ld\n", (long)len);
|
||||
if (len > sizeof(pss->buf))
|
||||
len = sizeof(pss->buf);
|
||||
memcpy(pss->buf, in, len);
|
||||
pss->len = len;
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_CLOSE:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_CLOSE\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_WRITEABLE:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE\n");
|
||||
lws_write(wsi, pss->buf, pss->len, LWS_WRITE_HTTP);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -334,10 +334,38 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
callback_test_raw_client(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_RAW_ADOPT:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_ADOPT\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_RX:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_RX %ld\n", (long)len);
|
||||
puts(in);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_CLOSE:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_CLOSE\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RAW_WRITEABLE:
|
||||
lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* list of supported protocols and callbacks */
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
|
@ -349,6 +377,11 @@ static struct lws_protocols protocols[] = {
|
|||
callback_lws_mirror,
|
||||
0,
|
||||
128,
|
||||
}, {
|
||||
"lws-test-raw-client",
|
||||
callback_test_raw_client,
|
||||
0,
|
||||
128
|
||||
},
|
||||
{ NULL, NULL, 0, 0 } /* end */
|
||||
};
|
||||
|
@ -597,7 +630,13 @@ int main(int argc, char **argv)
|
|||
i.method = "GET";
|
||||
do_ws = 0;
|
||||
} else
|
||||
lwsl_notice("using %s mode (ws)\n", prot);
|
||||
if (!strcmp(prot, "raw")) {
|
||||
i.method = "RAW";
|
||||
i.protocol = "lws-test-raw-client";
|
||||
lwsl_notice("using RAW mode connection\n");
|
||||
do_ws = 0;
|
||||
} else
|
||||
lwsl_notice("using %s mode (ws)\n", prot);
|
||||
|
||||
/*
|
||||
* sit there servicing the websocket context to handle incoming
|
||||
|
|
|
@ -155,13 +155,34 @@ static const struct lws_protocol_vhost_options pvo_opt = {
|
|||
"1"
|
||||
};
|
||||
|
||||
static const struct lws_protocol_vhost_options pvo_opt4a = {
|
||||
NULL,
|
||||
NULL,
|
||||
"raw", /* indicate we are the protocol that gets raw connections */
|
||||
"1"
|
||||
};
|
||||
|
||||
static const struct lws_protocol_vhost_options pvo_opt4 = {
|
||||
&pvo_opt4a,
|
||||
NULL,
|
||||
"fifo-path", /* tell the raw test plugin to open a raw file here */
|
||||
"/tmp/lws-test-raw"
|
||||
};
|
||||
|
||||
/*
|
||||
* We must enable the plugin protocols we want into our vhost with a
|
||||
* linked-list. We can also give the plugin per-vhost options here.
|
||||
*/
|
||||
|
||||
static const struct lws_protocol_vhost_options pvo_3 = {
|
||||
static const struct lws_protocol_vhost_options pvo_4 = {
|
||||
NULL,
|
||||
&pvo_opt4, /* set us as the protocol who gets raw connections */
|
||||
"protocol-lws-raw-test",
|
||||
"" /* ignored, just matches the protocol name above */
|
||||
};
|
||||
|
||||
static const struct lws_protocol_vhost_options pvo_3 = {
|
||||
&pvo_4,
|
||||
NULL,
|
||||
"protocol-post-demo",
|
||||
"" /* ignored, just matches the protocol name above */
|
||||
|
@ -367,7 +388,7 @@ int main(int argc, char **argv)
|
|||
info.gid = gid;
|
||||
info.uid = uid;
|
||||
info.max_http_header_pool = 16;
|
||||
info.options = opts |
|
||||
info.options = opts | LWS_SERVER_OPTION_FALLBACK_TO_RAW |
|
||||
LWS_SERVER_OPTION_VALIDATE_UTF8 |
|
||||
LWS_SERVER_OPTION_LIBUV; /* plugins require this */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue