mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
refactor: change event lib minimal examples to serve as the test apps
This commit is contained in:
parent
0b52d92d12
commit
f497562a62
36 changed files with 1204 additions and 750 deletions
|
@ -1608,7 +1608,10 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if (LWS_WITH_LIBEV)
|
||||
# libev generates a big mess of warnings with gcc, maintainer claims gcc to blame
|
||||
set_source_files_properties( lib/event-libs/libev/libev.c PROPERTIES COMPILE_FLAGS "-Wno-error" )
|
||||
endif()
|
||||
|
||||
|
||||
if (NOT LWS_WITHOUT_SERVER)
|
||||
|
@ -1651,9 +1654,8 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)
|
|||
""
|
||||
""
|
||||
"")
|
||||
# libev generates a big mess of warnings with gcc, maintainers blame gcc
|
||||
# libev generates a big mess of warnings with gcc, maintainer claims gcc to blame
|
||||
set_source_files_properties( test-apps/test-server-libev.c PROPERTIES COMPILE_FLAGS "-Wno-error" )
|
||||
set_source_files_properties( lib/event-libs/libev.c PROPERTIES COMPILE_FLAGS "-Wno-error" )
|
||||
|
||||
endif()
|
||||
if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
|
@ -1671,7 +1673,7 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)
|
|||
#
|
||||
# test-server-extpoll
|
||||
#
|
||||
if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL)
|
||||
if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL AND NOT WIN32)
|
||||
create_test_app(test-server-extpoll
|
||||
"test-apps/test-server.c"
|
||||
""
|
||||
|
@ -1889,7 +1891,7 @@ endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS)
|
|||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
endif(NOT LWS_WITHOUT_TESTAPPS)
|
||||
endif((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)
|
||||
|
||||
if (LWS_WITH_LWSWS)
|
||||
list(APPEND LWSWS_SRCS
|
||||
|
|
|
@ -1794,10 +1794,8 @@ lws_context_destroy(struct lws_context *context)
|
|||
struct lws wsi;
|
||||
int n, m;
|
||||
|
||||
if (!context) {
|
||||
lwsl_notice("%s: ctx %p\n", __func__, context);
|
||||
if (!context)
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->finalize_destroy_after_internal_loops_stopped) {
|
||||
if (context->event_loop_ops->destroy_context2)
|
||||
|
@ -1809,8 +1807,11 @@ lws_context_destroy(struct lws_context *context)
|
|||
}
|
||||
|
||||
if (context->being_destroyed1) {
|
||||
if (!context->being_destroyed2)
|
||||
return lws_context_destroy2(context);
|
||||
if (!context->being_destroyed2) {
|
||||
lws_context_destroy2(context);
|
||||
|
||||
return;
|
||||
}
|
||||
lwsl_info("%s: ctx %p: already being destroyed\n",
|
||||
__func__, context);
|
||||
return;
|
||||
|
|
|
@ -43,8 +43,6 @@ event libs, eg,
|
|||
```
|
||||
#if defined(LWS_WITH_LIBUV)
|
||||
#include "event-libs/libuv/private.h"
|
||||
#else
|
||||
#define LWS_LIBUV_ENABLED(context) (0)
|
||||
#endif
|
||||
```
|
||||
|
||||
|
|
|
@ -177,9 +177,6 @@ elops_init_context_ev(struct lws_context *context,
|
|||
static void
|
||||
elops_accept_ev(struct lws *wsi)
|
||||
{
|
||||
struct lws_context *context = lws_get_context(wsi);
|
||||
struct ev_io *r = &wsi->w_read.ev.watcher;
|
||||
struct ev_io *w = &wsi->w_write.ev.watcher;
|
||||
int fd;
|
||||
|
||||
if (wsi->role_ops->file_handle)
|
||||
|
@ -187,10 +184,11 @@ elops_accept_ev(struct lws *wsi)
|
|||
else
|
||||
fd = wsi->desc.sockfd;
|
||||
|
||||
wsi->w_read.context = context;
|
||||
wsi->w_write.context = context;
|
||||
ev_io_init(r, lws_accept_cb, fd, EV_READ);
|
||||
ev_io_init(w, lws_accept_cb, fd, EV_WRITE);
|
||||
wsi->w_read.context = wsi->context;
|
||||
wsi->w_write.context = wsi->context;
|
||||
|
||||
ev_io_init(&wsi->w_read.ev.watcher, lws_accept_cb, fd, EV_READ);
|
||||
ev_io_init(&wsi->w_write.ev.watcher, lws_accept_cb, fd, EV_WRITE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
struct lws_pt_eventlibs_libev {
|
||||
struct ev_loop *io_loop;
|
||||
struct ev_timer hrtimer;
|
||||
};
|
||||
|
||||
struct lws_io_watcher_libev {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
struct lws_pt_eventlibs_libevent {
|
||||
struct event_base *io_loop;
|
||||
struct event *hrtimer;
|
||||
};
|
||||
|
||||
struct lws_io_watcher_libevent {
|
||||
|
|
|
@ -62,3 +62,5 @@ struct lws_signal_watcher_libuv {
|
|||
|
||||
extern struct lws_event_loop_ops event_loop_ops_uv;
|
||||
|
||||
LWS_VISIBLE uv_loop_t *
|
||||
lws_uv_getloop(struct lws_context *context, int tsi);
|
||||
|
|
74
lib/event-libs/private.h
Normal file
74
lib/event-libs/private.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*
|
||||
* This is included from private-libwebsockets.h
|
||||
*/
|
||||
|
||||
struct lws_event_loop_ops {
|
||||
const char *name;
|
||||
/* event loop-specific context init during context creation */
|
||||
int (*init_context)(struct lws_context *context,
|
||||
const struct lws_context_creation_info *info);
|
||||
/* called during lws_destroy_context */
|
||||
int (*destroy_context1)(struct lws_context *context);
|
||||
/* called during lws_destroy_context2 */
|
||||
int (*destroy_context2)(struct lws_context *context);
|
||||
/* init vhost listening wsi */
|
||||
int (*init_vhost_listen_wsi)(struct lws *wsi);
|
||||
/* init the event loop for a pt */
|
||||
int (*init_pt)(struct lws_context *context, void *_loop, int tsi);
|
||||
/* called at end of first phase of close_free_wsi() */
|
||||
int (*wsi_logical_close)(struct lws *wsi);
|
||||
/* return nonzero if client connect not allowed */
|
||||
int (*check_client_connect_ok)(struct lws *wsi);
|
||||
/* close handle manually */
|
||||
void (*close_handle_manually)(struct lws *wsi);
|
||||
/* event loop accept processing */
|
||||
void (*accept)(struct lws *wsi);
|
||||
/* control wsi active events */
|
||||
void (*io)(struct lws *wsi, int flags);
|
||||
/* run the event loop for a pt */
|
||||
void (*run_pt)(struct lws_context *context, int tsi);
|
||||
/* called before pt is destroyed */
|
||||
void (*destroy_pt)(struct lws_context *context, int tsi);
|
||||
/* called just before wsi is freed */
|
||||
void (*destroy_wsi)(struct lws *wsi);
|
||||
|
||||
unsigned int periodic_events_available:1;
|
||||
};
|
||||
|
||||
/* bring in event libs private declarations */
|
||||
|
||||
#if defined(LWS_WITH_POLL)
|
||||
#include "event-libs/poll/private.h"
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBUV)
|
||||
#include "event-libs/libuv/private.h"
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEVENT)
|
||||
#include "event-libs/libevent/private.h"
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
#include "event-libs/libev/private.h"
|
||||
#endif
|
||||
|
|
@ -574,13 +574,14 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *
|
|||
* must go through and close all those first
|
||||
*/
|
||||
if (wsi->vhost) {
|
||||
lws_vhost_lock(wsi->vhost);
|
||||
if ((int)reason != -1)
|
||||
lws_vhost_lock(wsi->vhost);
|
||||
lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
|
||||
wsi->dll_client_transaction_queue_head.next) {
|
||||
struct lws *w = lws_container_of(d, struct lws,
|
||||
dll_client_transaction_queue);
|
||||
|
||||
__lws_close_free_wsi(w, reason, "trans q leader closing");
|
||||
__lws_close_free_wsi(w, -1, "trans q leader closing");
|
||||
} lws_end_foreach_dll_safe(d, d1);
|
||||
|
||||
/*
|
||||
|
@ -592,7 +593,8 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *
|
|||
* queue leader is closing.
|
||||
*/
|
||||
lws_dll_lws_remove(&wsi->dll_client_transaction_queue);
|
||||
lws_vhost_unlock(wsi->vhost);
|
||||
if ((int)reason !=-1)
|
||||
lws_vhost_unlock(wsi->vhost);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1030,6 +1032,7 @@ lws_buflist_use_segment(struct lws_buflist **head, size_t len)
|
|||
void
|
||||
lws_buflist_describe(struct lws_buflist **head, void *id)
|
||||
{
|
||||
struct lws_buflist *old;
|
||||
int n = 0;
|
||||
|
||||
if (*head == NULL)
|
||||
|
@ -1040,7 +1043,12 @@ lws_buflist_describe(struct lws_buflist **head, void *id)
|
|||
(unsigned long long)(*head)->pos,
|
||||
(unsigned long long)(*head)->len,
|
||||
(unsigned long long)(*head)->len - (*head)->pos);
|
||||
old = *head;
|
||||
head = &((*head)->next);
|
||||
if (*head == old) {
|
||||
lwsl_err("%s: next points to self\n", __func__);
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -4606,7 +4606,7 @@ lws_plat_recommended_rsa_bits(void);
|
|||
* cleanly and at the moment all of its libuv objects have completed close.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE uv_loop_t *
|
||||
LWS_VISIBLE LWS_EXTERN uv_loop_t *
|
||||
lws_uv_getloop(struct lws_context *context, int tsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
|
|
|
@ -57,8 +57,6 @@ lws_plat_pipe_signal(struct lws *wsi)
|
|||
|
||||
n = write(pt->dummy_pipe_fds[1], &buf, 1);
|
||||
|
||||
lwsl_debug("%s: fd %d %d\n", __func__, pt->dummy_pipe_fds[1], n);
|
||||
|
||||
return n != 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -374,210 +374,11 @@ enum lws_ssl_capable_status {
|
|||
|
||||
/*
|
||||
*
|
||||
* ------ role ------
|
||||
* ------ roles ------
|
||||
*
|
||||
*/
|
||||
|
||||
typedef uint32_t lws_wsi_state_t;
|
||||
|
||||
/*
|
||||
* The wsi->role_ops pointer decides almost everything about what role the wsi
|
||||
* will play, h2, raw, ws, etc.
|
||||
*
|
||||
* However there are a few additional flags needed that vary, such as if the
|
||||
* role is a client or server side, if it has that concept. And the connection
|
||||
* fulfilling the role, has a separate dynamic state.
|
||||
*
|
||||
* 31 16 15 0
|
||||
* [ role flags ] [ state ]
|
||||
*
|
||||
* The role flags part is generally invariant for the lifetime of the wsi,
|
||||
* although it can change if the connection role itself does, eg, if the
|
||||
* connection upgrades from H1 -> WS1 the role flags may be changed at that
|
||||
* point.
|
||||
*
|
||||
* The state part reflects the dynamic connection state, and the states are
|
||||
* reused between roles.
|
||||
*
|
||||
* None of the internal role or state representations are made available outside
|
||||
* of lws internals. Even for lws internals, if you add stuff here, please keep
|
||||
* the constants inside this header only by adding necessary helpers here and
|
||||
* use the helpers in the actual code. This is to ease any future refactors.
|
||||
*
|
||||
* Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our
|
||||
* data as a stream inside a different protocol.
|
||||
*/
|
||||
|
||||
#define _RS 16
|
||||
|
||||
#define LWSIFR_CLIENT (0x1000 << _RS) /* client side */
|
||||
#define LWSIFR_SERVER (0x2000 << _RS) /* server side */
|
||||
|
||||
#define LWSIFR_P_ENCAP_H2 (0x0100 << _RS) /* we are encapsulated by h2 */
|
||||
|
||||
enum lwsi_role {
|
||||
LWSI_ROLE_MASK = (0xffff << _RS),
|
||||
LWSI_ROLE_ENCAP_MASK = (0x0f00 << _RS),
|
||||
};
|
||||
|
||||
#define lwsi_role(wsi) (wsi->wsistate & LWSI_ROLE_MASK)
|
||||
#if !defined (_DEBUG)
|
||||
#define lwsi_set_role(wsi, role) wsi->wsistate = \
|
||||
(wsi->wsistate & (~LWSI_ROLE_MASK)) | role
|
||||
#else
|
||||
void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);
|
||||
#endif
|
||||
|
||||
#define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT))
|
||||
#define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER))
|
||||
#define lwsi_role_h2_ENCAPSULATION(wsi) \
|
||||
((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2)
|
||||
|
||||
/* Pollout wants a callback in this state */
|
||||
#define LWSIFS_POCB (0x100)
|
||||
/* Before any protocol connection was established */
|
||||
#define LWSIFS_NOT_EST (0x200)
|
||||
|
||||
enum lwsi_state {
|
||||
|
||||
/* Phase 1: pre-transport */
|
||||
|
||||
LRS_UNCONNECTED = LWSIFS_NOT_EST | 0,
|
||||
LRS_WAITING_CONNECT = LWSIFS_NOT_EST | 1,
|
||||
|
||||
/* Phase 2: establishing intermediaries on top of transport */
|
||||
|
||||
LRS_WAITING_PROXY_REPLY = LWSIFS_NOT_EST | 2,
|
||||
LRS_WAITING_SSL = LWSIFS_NOT_EST | 3,
|
||||
LRS_WAITING_SOCKS_GREETING_REPLY = LWSIFS_NOT_EST | 4,
|
||||
LRS_WAITING_SOCKS_CONNECT_REPLY = LWSIFS_NOT_EST | 5,
|
||||
LRS_WAITING_SOCKS_AUTH_REPLY = LWSIFS_NOT_EST | 6,
|
||||
|
||||
/* Phase 3: establishing tls tunnel */
|
||||
|
||||
LRS_SSL_INIT = LWSIFS_NOT_EST | 7,
|
||||
LRS_SSL_ACK_PENDING = LWSIFS_NOT_EST | 8,
|
||||
LRS_PRE_WS_SERVING_ACCEPT = LWSIFS_NOT_EST | 9,
|
||||
|
||||
/* Phase 4: connected */
|
||||
|
||||
LRS_WAITING_SERVER_REPLY = LWSIFS_NOT_EST | 10,
|
||||
LRS_H2_AWAIT_PREFACE = LWSIFS_NOT_EST | 11,
|
||||
LRS_H2_AWAIT_SETTINGS = LWSIFS_NOT_EST |
|
||||
LWSIFS_POCB | 12,
|
||||
|
||||
/* Phase 5: protocol logically established */
|
||||
|
||||
LRS_H2_CLIENT_SEND_SETTINGS = LWSIFS_POCB | 13,
|
||||
LRS_H2_WAITING_TO_SEND_HEADERS = LWSIFS_POCB | 14,
|
||||
LRS_DEFERRING_ACTION = LWSIFS_POCB | 15,
|
||||
LRS_IDLING = 16,
|
||||
LRS_H1C_ISSUE_HANDSHAKE = 17,
|
||||
LRS_H1C_ISSUE_HANDSHAKE2 = 18,
|
||||
LRS_ISSUE_HTTP_BODY = 19,
|
||||
LRS_ISSUING_FILE = 20,
|
||||
LRS_HEADERS = 21,
|
||||
LRS_BODY = 22,
|
||||
LRS_ESTABLISHED = LWSIFS_POCB | 23,
|
||||
|
||||
/* Phase 6: finishing */
|
||||
|
||||
LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 24,
|
||||
LRS_RETURNED_CLOSE = LWSIFS_POCB | 25,
|
||||
LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 26,
|
||||
LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 27,
|
||||
LRS_SHUTDOWN = 28,
|
||||
|
||||
/* Phase 7: dead */
|
||||
|
||||
LRS_DEAD_SOCKET = 29,
|
||||
|
||||
LRS_MASK = 0xffff
|
||||
};
|
||||
|
||||
#define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK))
|
||||
#define lwsi_state_PRE_CLOSE(wsi) ((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK))
|
||||
#define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST))
|
||||
#define lwsi_state_est_PRE_CLOSE(wsi) (!(wsi->wsistate_pre_close & LWSIFS_NOT_EST))
|
||||
#define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB)
|
||||
#if !defined (_DEBUG)
|
||||
#define lwsi_set_state(wsi, lrs) wsi->wsistate = \
|
||||
(wsi->wsistate & (~LRS_MASK)) | lrs
|
||||
#else
|
||||
void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* internal role-specific ops
|
||||
*/
|
||||
struct lws_context_per_thread;
|
||||
struct lws_role_ops {
|
||||
const char *name;
|
||||
const char *alpn;
|
||||
/*
|
||||
* After http headers have parsed, this is the last chance for a role
|
||||
* to upgrade the connection to something else using the headers.
|
||||
* ws-over-h2 is upgraded from h2 like this.
|
||||
*/
|
||||
int (*check_upgrades)(struct lws *wsi);
|
||||
/* role-specific context init during context creation */
|
||||
int (*init_context)(struct lws_context *context,
|
||||
const struct lws_context_creation_info *info);
|
||||
/* role-specific per-vhost init during vhost creation */
|
||||
int (*init_vhost)(struct lws_vhost *vh,
|
||||
const struct lws_context_creation_info *info);
|
||||
/* role-specific per-vhost destructor during vhost destroy */
|
||||
int (*destroy_vhost)(struct lws_vhost *vh);
|
||||
/* generic 1Hz callback for the role itself */
|
||||
int (*periodic_checks)(struct lws_context *context, int tsi,
|
||||
time_t now);
|
||||
/* chance for the role to force POLLIN without network activity */
|
||||
int (*service_flag_pending)(struct lws_context *context, int tsi);
|
||||
/* an fd using this role has POLLIN signalled */
|
||||
int (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,
|
||||
struct lws_pollfd *pollfd);
|
||||
/* an fd using the role wanted a POLLOUT callback and now has it */
|
||||
int (*handle_POLLOUT)(struct lws *wsi);
|
||||
/* perform user pollout */
|
||||
int (*perform_user_POLLOUT)(struct lws *wsi);
|
||||
/* do effective callback on writeable */
|
||||
int (*callback_on_writable)(struct lws *wsi);
|
||||
/* connection-specific tx credit in bytes */
|
||||
lws_fileofs_t (*tx_credit)(struct lws *wsi);
|
||||
/* role-specific write formatting */
|
||||
int (*write_role_protocol)(struct lws *wsi, unsigned char *buf,
|
||||
size_t len, enum lws_write_protocol *wp);
|
||||
|
||||
/* get encapsulation parent */
|
||||
struct lws * (*encapsulation_parent)(struct lws *wsi);
|
||||
|
||||
/* role-specific destructor */
|
||||
int (*alpn_negotiated)(struct lws *wsi, const char *alpn);
|
||||
|
||||
/* chance for the role to handle close in the protocol */
|
||||
int (*close_via_role_protocol)(struct lws *wsi,
|
||||
enum lws_close_status reason);
|
||||
/* role-specific close processing */
|
||||
int (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);
|
||||
/* role-specific connection close processing */
|
||||
int (*close_kill_connection)(struct lws *wsi,
|
||||
enum lws_close_status reason);
|
||||
/* role-specific destructor */
|
||||
int (*destroy_role)(struct lws *wsi);
|
||||
|
||||
/*
|
||||
* the callback reasons for WRITEABLE for client, server
|
||||
* (just client applies if no concept of client or server)
|
||||
*/
|
||||
uint16_t writeable_cb[2];
|
||||
/*
|
||||
* the callback reasons for CLOSE for client, server
|
||||
* (just client applies if no concept of client or server)
|
||||
*/
|
||||
uint16_t close_cb[2];
|
||||
|
||||
unsigned int file_handle:1; /* role operates on files not sockets */
|
||||
};
|
||||
#include "roles/private.h"
|
||||
|
||||
/* null-terminated array of pointers to roles lws built with */
|
||||
extern const struct lws_role_ops *available_roles[];
|
||||
|
@ -589,113 +390,13 @@ extern const struct lws_role_ops *available_roles[];
|
|||
|
||||
#define LWS_FOR_EVERY_AVAILABLE_ROLE_END }}
|
||||
|
||||
/* core roles */
|
||||
extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,
|
||||
role_ops_pipe;
|
||||
|
||||
/* bring in role private declarations */
|
||||
|
||||
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||||
#include "roles/http/private.h"
|
||||
#else
|
||||
#define lwsi_role_http(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_H1)
|
||||
#include "roles/h1/private.h"
|
||||
#else
|
||||
#define lwsi_role_h1(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_H2)
|
||||
#include "roles/h2/private.h"
|
||||
#else
|
||||
#define lwsi_role_h2(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_WS)
|
||||
#include "roles/ws/private.h"
|
||||
#else
|
||||
#define lwsi_role_ws(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_CGI)
|
||||
#include "roles/cgi/private.h"
|
||||
#else
|
||||
#define lwsi_role_cgi(wsi) (0)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
LWS_HP_RET_BAIL_OK,
|
||||
LWS_HP_RET_BAIL_DIE,
|
||||
LWS_HP_RET_USER_SERVICE,
|
||||
|
||||
LWS_HPI_RET_WSI_ALREADY_DIED, /* we closed it */
|
||||
LWS_HPI_RET_HANDLED, /* no probs */
|
||||
LWS_HPI_RET_PLEASE_CLOSE_ME, /* close it for us */
|
||||
|
||||
LWS_UPG_RET_DONE,
|
||||
LWS_UPG_RET_CONTINUE,
|
||||
LWS_UPG_RET_BAIL
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* ------ event_loop ops ------
|
||||
*
|
||||
*/
|
||||
|
||||
struct lws_event_loop_ops {
|
||||
const char *name;
|
||||
/* event loop-specific context init during context creation */
|
||||
int (*init_context)(struct lws_context *context,
|
||||
const struct lws_context_creation_info *info);
|
||||
/* called during lws_destroy_context */
|
||||
int (*destroy_context1)(struct lws_context *context);
|
||||
/* called during lws_destroy_context2 */
|
||||
int (*destroy_context2)(struct lws_context *context);
|
||||
/* init vhost listening wsi */
|
||||
int (*init_vhost_listen_wsi)(struct lws *wsi);
|
||||
/* init the event loop for a pt */
|
||||
int (*init_pt)(struct lws_context *context, void *_loop, int tsi);
|
||||
/* called at end of first phase of close_free_wsi() */
|
||||
int (*wsi_logical_close)(struct lws *wsi);
|
||||
/* return nonzero if client connect not allowed */
|
||||
int (*check_client_connect_ok)(struct lws *wsi);
|
||||
/* close handle manually */
|
||||
void (*close_handle_manually)(struct lws *wsi);
|
||||
/* event loop accept processing */
|
||||
void (*accept)(struct lws *wsi);
|
||||
/* control wsi active events */
|
||||
void (*io)(struct lws *wsi, int flags);
|
||||
/* run the event loop for a pt */
|
||||
void (*run_pt)(struct lws_context *context, int tsi);
|
||||
/* called before pt is destroyed */
|
||||
void (*destroy_pt)(struct lws_context *context, int tsi);
|
||||
/* called just before wsi is freed */
|
||||
void (*destroy_wsi)(struct lws *wsi);
|
||||
|
||||
unsigned int periodic_events_available:1;
|
||||
};
|
||||
|
||||
/* bring in event libs private declarations */
|
||||
|
||||
#if defined(LWS_WITH_POLL)
|
||||
#include "event-libs/poll/private.h"
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBUV)
|
||||
#include "event-libs/libuv/private.h"
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEVENT)
|
||||
#include "event-libs/libevent/private.h"
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
#include "event-libs/libev/private.h"
|
||||
#endif
|
||||
|
||||
#include "event-libs/private.h"
|
||||
|
||||
/* enums of socks version */
|
||||
enum socks_version {
|
||||
|
@ -774,8 +475,6 @@ struct lws_ring {
|
|||
struct lws_protocols;
|
||||
struct lws;
|
||||
|
||||
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || defined(LWS_WITH_LIBEVENT)
|
||||
|
||||
struct lws_io_watcher {
|
||||
#ifdef LWS_WITH_LIBEV
|
||||
struct lws_io_watcher_libev ev;
|
||||
|
@ -803,7 +502,6 @@ struct lws_signal_watcher {
|
|||
#endif
|
||||
struct lws_context *context;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define LWS_FD_HASH(fd) ((fd ^ (fd >> 8) ^ (fd >> 16)) % FD_HASHTABLE_MODULUS)
|
||||
|
|
|
@ -66,7 +66,7 @@ However when the declarations must be accessible to other things in lws build, e
|
|||
the role adds members to `struct lws` when enabled, they should be in the role
|
||||
directory in a file `private.h`.
|
||||
|
||||
Search for "bring in role private declarations" in `./lib/private-libwebsockets.h
|
||||
Search for "bring in role private declarations" in `./lib/roles/private.h
|
||||
and add your private role file there following the style used for the other roles,
|
||||
eg,
|
||||
|
||||
|
|
|
@ -314,11 +314,17 @@ lws_h1_server_socket_service(struct lws *wsi, struct lws_pollfd *pollfd)
|
|||
goto try_pollout;
|
||||
}
|
||||
|
||||
/*
|
||||
* We got here because there was specifically POLLIN...
|
||||
* regardless of our buflist state, we need to get it,
|
||||
* and either use it, or append to the buflist and use
|
||||
* buflist head material.
|
||||
*/
|
||||
|
||||
buffered = lws_buflist_aware_read(pt, wsi, &ebuf);
|
||||
switch (ebuf.len) {
|
||||
case 0:
|
||||
lwsl_info("%s: read 0 len a\n",
|
||||
__func__);
|
||||
lwsl_info("%s: read 0 len a\n", __func__);
|
||||
wsi->seen_zero_length_recv = 1;
|
||||
lws_change_pollfd(wsi, LWS_POLLIN, 0);
|
||||
goto try_pollout;
|
||||
|
|
|
@ -279,11 +279,19 @@ drain:
|
|||
lws_dll_lws_remove(&wsi->dll_buflist);
|
||||
}
|
||||
} else
|
||||
if (n != ebuf.len &&
|
||||
lws_buflist_append_segment(&wsi->buflist,
|
||||
if (n != ebuf.len) {
|
||||
m = lws_buflist_append_segment(&wsi->buflist,
|
||||
(uint8_t *)ebuf.token + n,
|
||||
ebuf.len - n) < 0)
|
||||
return LWS_HPI_RET_PLEASE_CLOSE_ME;
|
||||
ebuf.len - n);
|
||||
if (m < 0)
|
||||
return LWS_HPI_RET_PLEASE_CLOSE_ME;
|
||||
if (m) {
|
||||
lwsl_debug("%s: added %p to rxflow list\n",
|
||||
__func__, wsi);
|
||||
lws_dll_lws_add_front(&wsi->dll_buflist,
|
||||
&pt->dll_head_buflist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// lws_buflist_describe(&wsi->buflist, wsi);
|
||||
|
|
|
@ -123,10 +123,11 @@ lws_client_connect_2(struct lws *wsi)
|
|||
}
|
||||
#endif
|
||||
|
||||
lwsl_info("applying %p to txn queue on %p (wsistate 0x%x)\n", wsi, w,
|
||||
w->wsistate);
|
||||
lwsl_info("applying %p to txn queue on %p (wsistate 0x%x)\n",
|
||||
wsi, w, w->wsistate);
|
||||
/*
|
||||
* ...let's add ourselves to his transaction queue...
|
||||
* we are adding ourselves at the HEAD
|
||||
*/
|
||||
lws_dll_lws_add_front(&wsi->dll_client_transaction_queue,
|
||||
&w->dll_client_transaction_queue_head);
|
||||
|
@ -522,12 +523,15 @@ send_hs:
|
|||
* LRS_H1C_ISSUE_HANDSHAKE2, and let them write.
|
||||
*
|
||||
* If we are trying to do this too early, before the master
|
||||
* connection has written his own headers,
|
||||
* connection has written his own headers, then it will just
|
||||
* wait in the queue until it's possible to send them.
|
||||
*/
|
||||
lws_callback_on_writable(wsi_piggyback);
|
||||
lwsl_info("wsi %p: waiting to send headers\n", wsi);
|
||||
lwsl_info("%s: wsi %p: waiting to send headers (parent state %x)\n",
|
||||
__func__, wsi, lwsi_state(wsi_piggyback));
|
||||
} else {
|
||||
lwsl_info("wsi %p: client creating own connection\n", wsi);
|
||||
lwsl_info("%s: wsi %p: client creating own connection\n",
|
||||
__func__, wsi);
|
||||
|
||||
/* we are making our own connection */
|
||||
lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);
|
||||
|
|
|
@ -29,24 +29,26 @@ lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
|
|||
|
||||
/*
|
||||
* return self, or queued client wsi we are acting on behalf of
|
||||
*
|
||||
* That is the TAIL of the queue (new queue elements are added at the HEAD)
|
||||
*/
|
||||
|
||||
struct lws *
|
||||
lws_client_wsi_effective(struct lws *wsi)
|
||||
{
|
||||
struct lws *wsi_eff = wsi;
|
||||
struct lws_dll_lws *d;
|
||||
struct lws_dll_lws *tail = NULL;
|
||||
|
||||
if (!wsi->transaction_from_pipeline_queue ||
|
||||
!wsi->dll_client_transaction_queue_head.next)
|
||||
return wsi;
|
||||
|
||||
d = wsi->dll_client_transaction_queue_head.next;
|
||||
if (d)
|
||||
wsi_eff = lws_container_of(d, struct lws,
|
||||
dll_client_transaction_queue);
|
||||
lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
|
||||
wsi->dll_client_transaction_queue_head.next) {
|
||||
tail = d;
|
||||
} lws_end_foreach_dll_safe(d, d1);
|
||||
|
||||
return wsi_eff;
|
||||
return lws_container_of(tail, struct lws,
|
||||
dll_client_transaction_queue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -97,34 +99,40 @@ lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
|
|||
if ((pollfd->revents & LWS_POLLOUT) &&
|
||||
wsi->keepalive_active &&
|
||||
wsi->dll_client_transaction_queue_head.next) {
|
||||
int found = 0;
|
||||
struct lws *wfound = NULL;
|
||||
|
||||
lwsl_debug("%s: pollout HANDSHAKE2\n", __func__);
|
||||
|
||||
/* we have a transaction queue that wants to pipeline */
|
||||
/*
|
||||
* We have a transaction queued that wants to pipeline.
|
||||
*
|
||||
* We have to allow it to send headers strictly in the order
|
||||
* that it was queued, ie, tail-first.
|
||||
*/
|
||||
lws_vhost_lock(wsi->vhost);
|
||||
lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
|
||||
wsi->dll_client_transaction_queue_head.next) {
|
||||
struct lws *w = lws_container_of(d, struct lws,
|
||||
dll_client_transaction_queue);
|
||||
|
||||
lwsl_notice("%s: %p states 0x%x\n", __func__, w, w->wsistate);
|
||||
if (lwsi_state(w) == LRS_H1C_ISSUE_HANDSHAKE2) {
|
||||
/*
|
||||
* pollfd has the master sockfd in it... we
|
||||
* need to use that in HANDSHAKE2 to understand
|
||||
* which wsi to actually write on
|
||||
*/
|
||||
lws_client_socket_service(w, pollfd, wsi);
|
||||
lws_callback_on_writable(wsi);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
lwsl_debug("%s: %p states 0x%x\n", __func__, w, w->wsistate);
|
||||
if (lwsi_state(w) == LRS_H1C_ISSUE_HANDSHAKE2)
|
||||
wfound = w;
|
||||
} lws_end_foreach_dll_safe(d, d1);
|
||||
lws_vhost_unlock(wsi->vhost);
|
||||
|
||||
if (!found)
|
||||
lwsl_err("%s: didn't find anything in HS2\n", __func__);
|
||||
if (wfound) {
|
||||
/*
|
||||
* pollfd has the master sockfd in it... we
|
||||
* need to use that in HANDSHAKE2 to understand
|
||||
* which wsi to actually write on
|
||||
*/
|
||||
lws_client_socket_service(wfound, pollfd, wsi);
|
||||
lws_callback_on_writable(wsi);
|
||||
} else
|
||||
lwsl_debug("%s: didn't find anything in txn q in HS2\n",
|
||||
__func__);
|
||||
|
||||
lws_vhost_unlock(wsi->vhost);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1342,7 +1342,7 @@ deal_body:
|
|||
*/
|
||||
|
||||
while (1) {
|
||||
ebuf.len = lws_buflist_next_segment_len(
|
||||
ebuf.len = (int)lws_buflist_next_segment_len(
|
||||
&wsi->buflist, (uint8_t **)&ebuf.token);
|
||||
if (!ebuf.len)
|
||||
break;
|
||||
|
@ -1789,7 +1789,8 @@ lws_http_transaction_completed(struct lws *wsi)
|
|||
}
|
||||
#endif
|
||||
} else {
|
||||
lwsl_debug("%s: resetting and keeping ah as more pipeline stuff available\n", __func__);
|
||||
lwsl_debug("%s: resetting and keeping ah as pipeline\n",
|
||||
__func__);
|
||||
lws_header_table_reset(wsi, 0);
|
||||
/*
|
||||
* If we kept the ah, we should restrict the amount
|
||||
|
@ -1804,13 +1805,12 @@ lws_http_transaction_completed(struct lws *wsi)
|
|||
if (wsi->http.ah)
|
||||
wsi->http.ah->ues = URIES_IDLE;
|
||||
|
||||
lwsi_set_state(wsi, LRS_ESTABLISHED);
|
||||
//lwsi_set_state(wsi, LRS_ESTABLISHED);
|
||||
} else
|
||||
if (lws_buflist_next_segment_len(&wsi->buflist, NULL))
|
||||
if (lws_header_table_attach(wsi, 0))
|
||||
lwsl_debug("acquired ah\n");
|
||||
|
||||
|
||||
lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);
|
||||
lws_callback_on_writable(wsi);
|
||||
|
||||
|
@ -2063,6 +2063,7 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)
|
|||
{
|
||||
struct lws_context_per_thread *pt;
|
||||
struct lws_pollfd *pfd;
|
||||
int n;
|
||||
|
||||
if (!wsi)
|
||||
return NULL;
|
||||
|
@ -2070,8 +2071,13 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)
|
|||
if (!readbuf || len == 0)
|
||||
return wsi;
|
||||
|
||||
if (lws_buflist_append_segment(&wsi->buflist, (const uint8_t *)readbuf, len) < 0)
|
||||
pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
|
||||
n = lws_buflist_append_segment(&wsi->buflist, (const uint8_t *)readbuf, len);
|
||||
if (n < 0)
|
||||
goto bail;
|
||||
if (n)
|
||||
lws_dll_lws_add_front(&wsi->dll_buflist, &pt->dll_head_buflist);
|
||||
|
||||
/*
|
||||
* we can't process the initial read data until we can attach an ah.
|
||||
|
@ -2086,7 +2092,6 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)
|
|||
if (wsi->http.ah || !lws_header_table_attach(wsi, 0)) {
|
||||
|
||||
lwsl_notice("%s: calling service on readbuf ah\n", __func__);
|
||||
pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
|
||||
/* unlike a normal connect, we have the headers already
|
||||
* (or the first part of them anyway).
|
||||
|
|
273
lib/roles/private.h
Normal file
273
lib/roles/private.h
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*
|
||||
* This is included from private-libwebsockets.h
|
||||
*/
|
||||
|
||||
typedef uint32_t lws_wsi_state_t;
|
||||
|
||||
/*
|
||||
* The wsi->role_ops pointer decides almost everything about what role the wsi
|
||||
* will play, h2, raw, ws, etc.
|
||||
*
|
||||
* However there are a few additional flags needed that vary, such as if the
|
||||
* role is a client or server side, if it has that concept. And the connection
|
||||
* fulfilling the role, has a separate dynamic state.
|
||||
*
|
||||
* 31 16 15 0
|
||||
* [ role flags ] [ state ]
|
||||
*
|
||||
* The role flags part is generally invariant for the lifetime of the wsi,
|
||||
* although it can change if the connection role itself does, eg, if the
|
||||
* connection upgrades from H1 -> WS1 the role flags may be changed at that
|
||||
* point.
|
||||
*
|
||||
* The state part reflects the dynamic connection state, and the states are
|
||||
* reused between roles.
|
||||
*
|
||||
* None of the internal role or state representations are made available outside
|
||||
* of lws internals. Even for lws internals, if you add stuff here, please keep
|
||||
* the constants inside this header only by adding necessary helpers here and
|
||||
* use the helpers in the actual code. This is to ease any future refactors.
|
||||
*
|
||||
* Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our
|
||||
* data as a stream inside a different protocol.
|
||||
*/
|
||||
|
||||
#define _RS 16
|
||||
|
||||
#define LWSIFR_CLIENT (0x1000 << _RS) /* client side */
|
||||
#define LWSIFR_SERVER (0x2000 << _RS) /* server side */
|
||||
|
||||
#define LWSIFR_P_ENCAP_H2 (0x0100 << _RS) /* we are encapsulated by h2 */
|
||||
|
||||
enum lwsi_role {
|
||||
LWSI_ROLE_MASK = (0xffff << _RS),
|
||||
LWSI_ROLE_ENCAP_MASK = (0x0f00 << _RS),
|
||||
};
|
||||
|
||||
#define lwsi_role(wsi) (wsi->wsistate & LWSI_ROLE_MASK)
|
||||
#if !defined (_DEBUG)
|
||||
#define lwsi_set_role(wsi, role) wsi->wsistate = \
|
||||
(wsi->wsistate & (~LWSI_ROLE_MASK)) | role
|
||||
#else
|
||||
void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);
|
||||
#endif
|
||||
|
||||
#define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT))
|
||||
#define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER))
|
||||
#define lwsi_role_h2_ENCAPSULATION(wsi) \
|
||||
((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2)
|
||||
|
||||
/* Pollout wants a callback in this state */
|
||||
#define LWSIFS_POCB (0x100)
|
||||
/* Before any protocol connection was established */
|
||||
#define LWSIFS_NOT_EST (0x200)
|
||||
|
||||
enum lwsi_state {
|
||||
|
||||
/* Phase 1: pre-transport */
|
||||
|
||||
LRS_UNCONNECTED = LWSIFS_NOT_EST | 0,
|
||||
LRS_WAITING_CONNECT = LWSIFS_NOT_EST | 1,
|
||||
|
||||
/* Phase 2: establishing intermediaries on top of transport */
|
||||
|
||||
LRS_WAITING_PROXY_REPLY = LWSIFS_NOT_EST | 2,
|
||||
LRS_WAITING_SSL = LWSIFS_NOT_EST | 3,
|
||||
LRS_WAITING_SOCKS_GREETING_REPLY = LWSIFS_NOT_EST | 4,
|
||||
LRS_WAITING_SOCKS_CONNECT_REPLY = LWSIFS_NOT_EST | 5,
|
||||
LRS_WAITING_SOCKS_AUTH_REPLY = LWSIFS_NOT_EST | 6,
|
||||
|
||||
/* Phase 3: establishing tls tunnel */
|
||||
|
||||
LRS_SSL_INIT = LWSIFS_NOT_EST | 7,
|
||||
LRS_SSL_ACK_PENDING = LWSIFS_NOT_EST | 8,
|
||||
LRS_PRE_WS_SERVING_ACCEPT = LWSIFS_NOT_EST | 9,
|
||||
|
||||
/* Phase 4: connected */
|
||||
|
||||
LRS_WAITING_SERVER_REPLY = LWSIFS_NOT_EST | 10,
|
||||
LRS_H2_AWAIT_PREFACE = LWSIFS_NOT_EST | 11,
|
||||
LRS_H2_AWAIT_SETTINGS = LWSIFS_NOT_EST |
|
||||
LWSIFS_POCB | 12,
|
||||
|
||||
/* Phase 5: protocol logically established */
|
||||
|
||||
LRS_H2_CLIENT_SEND_SETTINGS = LWSIFS_POCB | 13,
|
||||
LRS_H2_WAITING_TO_SEND_HEADERS = LWSIFS_POCB | 14,
|
||||
LRS_DEFERRING_ACTION = LWSIFS_POCB | 15,
|
||||
LRS_IDLING = 16,
|
||||
LRS_H1C_ISSUE_HANDSHAKE = 17,
|
||||
LRS_H1C_ISSUE_HANDSHAKE2 = 18,
|
||||
LRS_ISSUE_HTTP_BODY = 19,
|
||||
LRS_ISSUING_FILE = 20,
|
||||
LRS_HEADERS = 21,
|
||||
LRS_BODY = 22,
|
||||
LRS_ESTABLISHED = LWSIFS_POCB | 23,
|
||||
|
||||
/* Phase 6: finishing */
|
||||
|
||||
LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 24,
|
||||
LRS_RETURNED_CLOSE = LWSIFS_POCB | 25,
|
||||
LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 26,
|
||||
LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 27,
|
||||
LRS_SHUTDOWN = 28,
|
||||
|
||||
/* Phase 7: dead */
|
||||
|
||||
LRS_DEAD_SOCKET = 29,
|
||||
|
||||
LRS_MASK = 0xffff
|
||||
};
|
||||
|
||||
#define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK))
|
||||
#define lwsi_state_PRE_CLOSE(wsi) ((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK))
|
||||
#define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST))
|
||||
#define lwsi_state_est_PRE_CLOSE(wsi) (!(wsi->wsistate_pre_close & LWSIFS_NOT_EST))
|
||||
#define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB)
|
||||
#if !defined (_DEBUG)
|
||||
#define lwsi_set_state(wsi, lrs) wsi->wsistate = \
|
||||
(wsi->wsistate & (~LRS_MASK)) | lrs
|
||||
#else
|
||||
void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* internal role-specific ops
|
||||
*/
|
||||
struct lws_context_per_thread;
|
||||
struct lws_role_ops {
|
||||
const char *name;
|
||||
const char *alpn;
|
||||
/*
|
||||
* After http headers have parsed, this is the last chance for a role
|
||||
* to upgrade the connection to something else using the headers.
|
||||
* ws-over-h2 is upgraded from h2 like this.
|
||||
*/
|
||||
int (*check_upgrades)(struct lws *wsi);
|
||||
/* role-specific context init during context creation */
|
||||
int (*init_context)(struct lws_context *context,
|
||||
const struct lws_context_creation_info *info);
|
||||
/* role-specific per-vhost init during vhost creation */
|
||||
int (*init_vhost)(struct lws_vhost *vh,
|
||||
const struct lws_context_creation_info *info);
|
||||
/* role-specific per-vhost destructor during vhost destroy */
|
||||
int (*destroy_vhost)(struct lws_vhost *vh);
|
||||
/* generic 1Hz callback for the role itself */
|
||||
int (*periodic_checks)(struct lws_context *context, int tsi,
|
||||
time_t now);
|
||||
/* chance for the role to force POLLIN without network activity */
|
||||
int (*service_flag_pending)(struct lws_context *context, int tsi);
|
||||
/* an fd using this role has POLLIN signalled */
|
||||
int (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,
|
||||
struct lws_pollfd *pollfd);
|
||||
/* an fd using the role wanted a POLLOUT callback and now has it */
|
||||
int (*handle_POLLOUT)(struct lws *wsi);
|
||||
/* perform user pollout */
|
||||
int (*perform_user_POLLOUT)(struct lws *wsi);
|
||||
/* do effective callback on writeable */
|
||||
int (*callback_on_writable)(struct lws *wsi);
|
||||
/* connection-specific tx credit in bytes */
|
||||
lws_fileofs_t (*tx_credit)(struct lws *wsi);
|
||||
/* role-specific write formatting */
|
||||
int (*write_role_protocol)(struct lws *wsi, unsigned char *buf,
|
||||
size_t len, enum lws_write_protocol *wp);
|
||||
|
||||
/* get encapsulation parent */
|
||||
struct lws * (*encapsulation_parent)(struct lws *wsi);
|
||||
|
||||
/* role-specific destructor */
|
||||
int (*alpn_negotiated)(struct lws *wsi, const char *alpn);
|
||||
|
||||
/* chance for the role to handle close in the protocol */
|
||||
int (*close_via_role_protocol)(struct lws *wsi,
|
||||
enum lws_close_status reason);
|
||||
/* role-specific close processing */
|
||||
int (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);
|
||||
/* role-specific connection close processing */
|
||||
int (*close_kill_connection)(struct lws *wsi,
|
||||
enum lws_close_status reason);
|
||||
/* role-specific destructor */
|
||||
int (*destroy_role)(struct lws *wsi);
|
||||
|
||||
/*
|
||||
* the callback reasons for WRITEABLE for client, server
|
||||
* (just client applies if no concept of client or server)
|
||||
*/
|
||||
uint16_t writeable_cb[2];
|
||||
/*
|
||||
* the callback reasons for CLOSE for client, server
|
||||
* (just client applies if no concept of client or server)
|
||||
*/
|
||||
uint16_t close_cb[2];
|
||||
|
||||
unsigned int file_handle:1; /* role operates on files not sockets */
|
||||
};
|
||||
|
||||
/* core roles */
|
||||
extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,
|
||||
role_ops_pipe;
|
||||
|
||||
/* bring in role private declarations */
|
||||
|
||||
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||||
#include "roles/http/private.h"
|
||||
#else
|
||||
#define lwsi_role_http(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_H1)
|
||||
#include "roles/h1/private.h"
|
||||
#else
|
||||
#define lwsi_role_h1(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_H2)
|
||||
#include "roles/h2/private.h"
|
||||
#else
|
||||
#define lwsi_role_h2(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_WS)
|
||||
#include "roles/ws/private.h"
|
||||
#else
|
||||
#define lwsi_role_ws(wsi) (0)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_CGI)
|
||||
#include "roles/cgi/private.h"
|
||||
#else
|
||||
#define lwsi_role_cgi(wsi) (0)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
LWS_HP_RET_BAIL_OK,
|
||||
LWS_HP_RET_BAIL_DIE,
|
||||
LWS_HP_RET_USER_SERVICE,
|
||||
|
||||
LWS_HPI_RET_WSI_ALREADY_DIED, /* we closed it */
|
||||
LWS_HPI_RET_HANDLED, /* no probs */
|
||||
LWS_HPI_RET_PLEASE_CLOSE_ME, /* close it for us */
|
||||
|
||||
LWS_UPG_RET_DONE,
|
||||
LWS_UPG_RET_CONTINUE,
|
||||
LWS_UPG_RET_BAIL
|
||||
};
|
|
@ -568,7 +568,7 @@ lws_ws_frame_rest_is_payload(struct lws *wsi, uint8_t **buf, size_t len)
|
|||
{
|
||||
uint8_t *buffer = *buf, mask[4];
|
||||
struct lws_tokens ebuf;
|
||||
unsigned int avail = len;
|
||||
unsigned int avail = (unsigned int)len;
|
||||
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
||||
unsigned int old_packet_length = (int)wsi->ws->rx_packet_length;
|
||||
#endif
|
||||
|
|
|
@ -351,33 +351,64 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi)
|
|||
return timeout_ms;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* POLLIN said there is something... we must read it, and either use it; or
|
||||
* if other material already in the buflist append it and return the buflist
|
||||
* head material.
|
||||
*/
|
||||
int
|
||||
lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi,
|
||||
struct lws_tokens *ebuf)
|
||||
{
|
||||
ebuf->len = (int)lws_buflist_next_segment_len(&wsi->buflist,
|
||||
(uint8_t **)&ebuf->token);
|
||||
if (!ebuf->len) {
|
||||
ebuf->token = (char *)pt->serv_buf;
|
||||
ebuf->len = lws_ssl_capable_read(wsi, pt->serv_buf,
|
||||
wsi->context->pt_serv_buf_size);
|
||||
int n, prior = (int)lws_buflist_next_segment_len(&wsi->buflist, NULL);
|
||||
|
||||
// if (ebuf->len > 0)
|
||||
// lwsl_hexdump_notice(ebuf->token, ebuf->len);
|
||||
ebuf->token = (char *)pt->serv_buf;
|
||||
ebuf->len = lws_ssl_capable_read(wsi, pt->serv_buf,
|
||||
wsi->context->pt_serv_buf_size);
|
||||
|
||||
return 0; /* fresh */
|
||||
if (ebuf->len == LWS_SSL_CAPABLE_MORE_SERVICE && prior)
|
||||
goto get_from_buflist;
|
||||
|
||||
if (ebuf->len <= 0)
|
||||
return 0;
|
||||
|
||||
/* nothing in buflist already? Then just use what we read */
|
||||
|
||||
if (!prior)
|
||||
return 0;
|
||||
|
||||
/* stash what we read */
|
||||
|
||||
n = lws_buflist_append_segment(&wsi->buflist, (uint8_t *)ebuf->token,
|
||||
ebuf->len);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
if (n) {
|
||||
lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi);
|
||||
lws_dll_lws_add_front(&wsi->dll_buflist, &pt->dll_head_buflist);
|
||||
}
|
||||
|
||||
return 1; /* buffered */
|
||||
/* get the first buflist guy in line */
|
||||
|
||||
get_from_buflist:
|
||||
|
||||
ebuf->len = (int)lws_buflist_next_segment_len(&wsi->buflist,
|
||||
(uint8_t **)&ebuf->token);
|
||||
|
||||
return 1; /* came from buflist */
|
||||
}
|
||||
|
||||
int
|
||||
lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,
|
||||
int buffered)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
int m;
|
||||
|
||||
/* it's in the buflist; we didn't use any */
|
||||
|
||||
if (!used && buffered)
|
||||
return 0;
|
||||
|
||||
if (used && buffered) {
|
||||
m = lws_buflist_use_segment(&wsi->buflist, used);
|
||||
|
@ -394,10 +425,17 @@ lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,
|
|||
|
||||
/* any remainder goes on the buflist */
|
||||
|
||||
if (used != ebuf->len &&
|
||||
lws_buflist_append_segment(&wsi->buflist, (uint8_t *)ebuf->token +
|
||||
used, ebuf->len - used) < 0)
|
||||
return 1; /* OOM */
|
||||
if (used != ebuf->len) {
|
||||
m = lws_buflist_append_segment(&wsi->buflist,
|
||||
(uint8_t *)ebuf->token + used,
|
||||
ebuf->len - used);
|
||||
if (m < 0)
|
||||
return 1; /* OOM */
|
||||
if (m) {
|
||||
lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi);
|
||||
lws_dll_lws_add_front(&wsi->dll_buflist, &pt->dll_head_buflist);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -316,9 +316,11 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
(void)budget;
|
||||
#if (UV_VERSION_MAJOR > 0) // Travis...
|
||||
while ((n = uv_loop_close(&loop)) && --budget)
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "lwsws exited cleanly: %d\n", n);
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ wait $SPID 2>/dev/null
|
|||
|
||||
if [ -z "$TRAVIS_OS_NAME" ] ; then
|
||||
SPID=""
|
||||
spawn "" $5/http-server/minimal-http-server-libuv $1/lws-minimal-http-server-libuv -s
|
||||
spawn "" $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s
|
||||
dotest $1 $2 localhost-suv -l
|
||||
spawn $SPID $5/http-server/minimal-http-server-libuv $1/lws-minimal-http-server-libuv -s
|
||||
spawn $SPID $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s
|
||||
dotest $1 $2 localhost-suv-h1 -l --h1
|
||||
|
||||
kill $SPID 2>/dev/null
|
||||
|
|
|
@ -94,7 +94,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP %d\n", u->index);
|
||||
lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP %p: idx %d\n",
|
||||
wsi, u->index);
|
||||
client_wsi[u->index] = NULL;
|
||||
if (++completed == COUNT) {
|
||||
if (!failed)
|
||||
|
@ -166,7 +167,7 @@ lws_try_client_connection(struct lws_client_connect_info *i, int m)
|
|||
interrupted = 1;
|
||||
}
|
||||
} else
|
||||
lwsl_user("started connection %d\n", m);
|
||||
lwsl_user("started connection %p: idx %d\n", client_wsi[m], m);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
|
@ -201,7 +202,6 @@ int main(int argc, const char **argv)
|
|||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
||||
info.protocols = protocols;
|
||||
info.max_http_header_pool = 20;
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
/*
|
||||
|
@ -237,6 +237,9 @@ int main(int argc, const char **argv)
|
|||
i.address = "warmcat.com";
|
||||
}
|
||||
|
||||
if ((p = lws_cmdline_option(argc, argv, "--port")))
|
||||
i.port = atoi(p);
|
||||
|
||||
i.host = i.address;
|
||||
i.origin = i.address;
|
||||
i.method = "GET";
|
||||
|
@ -267,7 +270,7 @@ int main(int argc, const char **argv)
|
|||
if (m == (int)LWS_ARRAY_SIZE(client_wsi) - 1)
|
||||
next = us() + 1000000;
|
||||
else
|
||||
next = us() + 100000;
|
||||
next = us() + 300000;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
set(SAMP lws-minimal-http-server-libuv-foreign)
|
||||
set(SRCS minimal-http-server-libuv-foreign.c)
|
||||
set(SAMP lws-minimal-http-server-eventlib-foreign)
|
||||
set(SRCS minimal-http-server-eventlib-foreign.c)
|
||||
|
||||
# If we are being built as part of lws, confirm current build config supports
|
||||
# reqconfig, else skip building ourselves.
|
||||
|
@ -63,16 +63,25 @@ ENDMACRO()
|
|||
|
||||
set(requirements 1)
|
||||
require_lws_config(LWS_ROLE_H1 1 requirements)
|
||||
require_lws_config(LWS_WITH_LIBUV 1 requirements)
|
||||
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\n#include <uv.h>\nint main(void) {\n#if (UV_VERSION_MAJOR > 0)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_RECENT_LIBUV)
|
||||
if (NOT HAS_RECENT_LIBUV)
|
||||
if (LWS_WITH_MINIMAL_EXAMPLES)
|
||||
message("libuv is too old (pre- 1.0)")
|
||||
else()
|
||||
message(FATAL_ERROR "libuv is too old (pre- 1.0)")
|
||||
endif()
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBUV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBUV)
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBEVENT)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEVENT)
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBEV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEV)
|
||||
|
||||
if (LWS_WITH_LIBUV)
|
||||
set(extralibs ${extralibs} uv)
|
||||
endif()
|
||||
if (LWS_WITH_LIBEVENT)
|
||||
set(extralibs ${extralibs} event)
|
||||
endif()
|
||||
if (LWS_WITH_LIBEV)
|
||||
set(extralibs ${extralibs} ev)
|
||||
endif()
|
||||
|
||||
message("Extra libs: ${extralibs}")
|
||||
|
||||
if (NOT LWS_WITH_LIBUV AND NOT LWS_WITH_LIBEVENT AND NOT LWS_WITH_LIBEV)
|
||||
set(requirements 0)
|
||||
endif()
|
||||
|
||||
|
@ -80,9 +89,9 @@ if (requirements)
|
|||
add_executable(${SAMP} ${SRCS})
|
||||
|
||||
if (websockets_shared)
|
||||
target_link_libraries(${SAMP} websockets_shared uv)
|
||||
target_link_libraries(${SAMP} websockets_shared ${extralibs})
|
||||
add_dependencies(${SAMP} websockets_shared)
|
||||
else()
|
||||
target_link_libraries(${SAMP} websockets uv)
|
||||
target_link_libraries(${SAMP} websockets ${extralibs})
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -1,4 +1,19 @@
|
|||
# lws minimal http server libuv foreign
|
||||
# lws minimal http server eventlib foreign
|
||||
|
||||
Commandline option|Meaning
|
||||
---|---
|
||||
-d <loglevel>|Debug verbosity in decimal, eg, -d15
|
||||
--uv|Use the libuv event library (lws must have been configured with `-DLWS_WITH_LIBUV=1`)
|
||||
--event|Use the libevent library (lws must have been configured with `-DLWS_WITH_LIBEVENT=1`)
|
||||
--ev|Use the libev event library (lws must have been configured with `-DLWS_WITH_LIBEV=1`)
|
||||
|
||||
Notice libevent and libev cannot coexist in the one library. But all the other combinations are OK.
|
||||
|
||||
x|libuv|libevent|libev
|
||||
---|---|---|---
|
||||
libuv|-|OK|OK
|
||||
libevent|OK|-|no
|
||||
libev|OK|no|-
|
||||
|
||||
This demonstrates having lws take part in a libuv loop owned by
|
||||
something else, with its own objects running in the loop.
|
||||
|
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* lws-minimal-http-server-eventlib-foreign
|
||||
*
|
||||
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates the most minimal http server you can make with lws that
|
||||
* uses a libuv event loop created outside lws. It shows how lws can
|
||||
* participate in someone else's event loop and clean up after itself.
|
||||
*
|
||||
* You choose the event loop to work with at runtime, by giving the
|
||||
* --uv, --event or --ev switch. Lws has to have been configured to build the
|
||||
* selected event lib support.
|
||||
*
|
||||
* To keep it simple, it serves stuff from the subdirectory
|
||||
* "./mount-origin" of the directory it was started in.
|
||||
* You can change that by changing mount.origin below.
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
struct lws_context_creation_info info;
|
||||
static struct lws_context *context;
|
||||
static int lifetime = 5, reported;
|
||||
|
||||
static void foreign_timer_service(void *foreign_loop);
|
||||
|
||||
enum {
|
||||
TEST_STATE_CREATE_LWS_CONTEXT,
|
||||
TEST_STATE_DESTROY_LWS_CONTEXT,
|
||||
TEST_STATE_EXIT
|
||||
};
|
||||
|
||||
static int sequence = TEST_STATE_CREATE_LWS_CONTEXT;
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ NULL, /* linked-list "next" */
|
||||
/* .mountpoint */ "/", /* mountpoint URL */
|
||||
/* .origin */ "./mount-origin", /* serve from dir */
|
||||
/* .def */ "index.html", /* default filename */
|
||||
/* .protocol */ NULL,
|
||||
/* .cgienv */ NULL,
|
||||
/* .extra_mimetypes */ NULL,
|
||||
/* .interpret */ NULL,
|
||||
/* .cgi_timeout */ 0,
|
||||
/* .cache_max_age */ 0,
|
||||
/* .auth_mask */ 0,
|
||||
/* .cache_reusable */ 0,
|
||||
/* .cache_revalidate */ 0,
|
||||
/* .cache_intermediaries */ 0,
|
||||
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
|
||||
/* .mountpoint_len */ 1, /* char count */
|
||||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
static void
|
||||
signal_cb(int signum)
|
||||
{
|
||||
lwsl_notice("Signal %d caught, exiting...\n", signum);
|
||||
|
||||
switch (signum) {
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lws_context_destroy(context);
|
||||
}
|
||||
|
||||
/*
|
||||
* The event-loop specific foreign loop code, one set for each event loop lib
|
||||
*
|
||||
* Only the code in this section is specific to the event library used.
|
||||
*/
|
||||
|
||||
#if defined(LWS_WITH_LIBUV)
|
||||
|
||||
static uv_loop_t loop_uv;
|
||||
static uv_timer_t timer_outer_uv;
|
||||
static uv_signal_t sighandler_uv;
|
||||
|
||||
static void
|
||||
timer_cb_uv(uv_timer_t *t)
|
||||
{
|
||||
foreign_timer_service(&loop_uv);
|
||||
}
|
||||
|
||||
static void
|
||||
signal_cb_uv(uv_signal_t *watcher, int signum)
|
||||
{
|
||||
signal_cb(signum);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_init_and_run_libuv(void)
|
||||
{
|
||||
/* we create and start our "foreign loop" */
|
||||
|
||||
#if (UV_VERSION_MAJOR > 0) // Travis...
|
||||
uv_loop_init(&loop_uv);
|
||||
#endif
|
||||
uv_signal_init(&loop_uv, &sighandler_uv);
|
||||
uv_signal_start(&sighandler_uv, signal_cb_uv, SIGINT);
|
||||
|
||||
uv_timer_init(&loop_uv, &timer_outer_uv);
|
||||
#if (UV_VERSION_MAJOR > 0) // Travis...
|
||||
uv_timer_start(&timer_outer_uv, timer_cb_uv, 0, 1000);
|
||||
#else
|
||||
(void)timer_cb_uv;
|
||||
#endif
|
||||
|
||||
uv_run(&loop_uv, UV_RUN_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_stop_libuv(void)
|
||||
{
|
||||
uv_stop(&loop_uv);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_cleanup_libuv(void)
|
||||
{
|
||||
/* cleanup the foreign loop assets */
|
||||
|
||||
uv_timer_stop(&timer_outer_uv);
|
||||
uv_close((uv_handle_t*)&timer_outer_uv, NULL);
|
||||
uv_signal_stop(&sighandler_uv);
|
||||
uv_close((uv_handle_t *)&sighandler_uv, NULL);
|
||||
|
||||
uv_run(&loop_uv, UV_RUN_DEFAULT);
|
||||
#if (UV_VERSION_MAJOR > 0) // Travis...
|
||||
uv_loop_close(&loop_uv);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEVENT)
|
||||
|
||||
static struct event_base *loop_event;
|
||||
static struct event *timer_outer_event;
|
||||
static struct event *sighandler_event;
|
||||
|
||||
static void
|
||||
timer_cb_event(int fd, short event, void *arg)
|
||||
{
|
||||
foreign_timer_service(loop_event);
|
||||
}
|
||||
|
||||
static void
|
||||
signal_cb_event(int fd, short event, void *arg)
|
||||
{
|
||||
signal_cb((int)(lws_intptr_t)arg);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_init_and_run_libevent(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
/* we create and start our "foreign loop" */
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
loop_event = event_base_new();
|
||||
|
||||
sighandler_event = evsignal_new(loop_event, SIGINT, signal_cb_event,
|
||||
(void*)SIGINT);
|
||||
|
||||
timer_outer_event = event_new(loop_event, -1, EV_PERSIST,
|
||||
timer_cb_event, NULL);
|
||||
//evtimer_new(loop_event, timer_cb_event, NULL);
|
||||
evtimer_add(timer_outer_event, &tv);
|
||||
|
||||
event_base_loop(loop_event, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_stop_libevent(void)
|
||||
{
|
||||
event_base_loopexit(loop_event, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_cleanup_libevent(void)
|
||||
{
|
||||
/* cleanup the foreign loop assets */
|
||||
|
||||
evtimer_del(timer_outer_event);
|
||||
event_free(timer_outer_event);
|
||||
evsignal_del(sighandler_event);
|
||||
event_free(sighandler_event);
|
||||
|
||||
event_base_loop(loop_event, 0);
|
||||
event_base_free(loop_event);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
|
||||
static struct ev_loop *loop_ev;
|
||||
static struct ev_timer timer_outer_ev;
|
||||
static struct ev_signal sighandler_ev;
|
||||
|
||||
static void
|
||||
timer_cb_ev(struct ev_loop *loop, struct ev_timer *watcher, int revents)
|
||||
{
|
||||
foreign_timer_service(loop_ev);
|
||||
}
|
||||
|
||||
static void
|
||||
signal_cb_ev(struct ev_loop *loop, struct ev_signal *watcher, int revents)
|
||||
{
|
||||
signal_cb(watcher->signum);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_init_and_run_libev(void)
|
||||
{
|
||||
/* we create and start our "foreign loop" */
|
||||
|
||||
loop_ev = ev_loop_new(0);
|
||||
|
||||
ev_signal_init(&sighandler_ev, signal_cb_ev, SIGINT);
|
||||
ev_signal_start(loop_ev, &sighandler_ev);
|
||||
|
||||
ev_timer_init(&timer_outer_ev, timer_cb_ev, 0, 1);
|
||||
ev_timer_start(loop_ev, &timer_outer_ev);
|
||||
|
||||
ev_run(loop_ev, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_stop_libev(void)
|
||||
{
|
||||
ev_break(loop_ev, EVBREAK_ALL);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_cleanup_libev(void)
|
||||
{
|
||||
/* cleanup the foreign loop assets */
|
||||
|
||||
ev_timer_stop(loop_ev, &timer_outer_ev);
|
||||
ev_signal_stop(loop_ev, &sighandler_ev);
|
||||
|
||||
ev_run(loop_ev, UV_RUN_DEFAULT);
|
||||
ev_loop_destroy(loop_ev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* this is called at 1Hz using a foreign loop timer */
|
||||
|
||||
static void
|
||||
foreign_timer_service(void *foreign_loop)
|
||||
{
|
||||
void *foreign_loops[1];
|
||||
|
||||
lwsl_user("Foreign 1Hz timer\n");
|
||||
|
||||
if (sequence == TEST_STATE_EXIT && !context && !reported) {
|
||||
/*
|
||||
* at this point the lws_context_destroy() we did earlier
|
||||
* has completed and the entire context is wholly destroyed
|
||||
*/
|
||||
lwsl_user("lws_destroy_context() done, continuing for 5s\n");
|
||||
reported = 1;
|
||||
}
|
||||
|
||||
if (--lifetime)
|
||||
return;
|
||||
|
||||
switch (sequence++) {
|
||||
case TEST_STATE_CREATE_LWS_CONTEXT:
|
||||
/* this only has to exist for the duration of create context */
|
||||
foreign_loops[0] = foreign_loop;
|
||||
info.foreign_loops = foreign_loops;
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
lwsl_err("lws init failed\n");
|
||||
return;
|
||||
}
|
||||
lwsl_user("LWS Context created and will be active for 10s\n");
|
||||
lifetime = 11;
|
||||
break;
|
||||
|
||||
case TEST_STATE_DESTROY_LWS_CONTEXT:
|
||||
/* cleanup the lws part */
|
||||
lwsl_user("Destroying lws context and continuing loop for 5s\n");
|
||||
lws_context_destroy(context);
|
||||
lifetime = 6;
|
||||
break;
|
||||
|
||||
case TEST_STATE_EXIT:
|
||||
lwsl_user("Deciding to exit foreign loop too\n");
|
||||
#if defined(LWS_WITH_LIBUV)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBUV)
|
||||
foreign_event_loop_stop_libuv();
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEVENT)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBEVENT)
|
||||
foreign_event_loop_stop_libevent();
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBEV)
|
||||
foreign_event_loop_stop_libev();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const char *p;
|
||||
int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
|
||||
/* for LLL_ verbosity above NOTICE to be built into lws,
|
||||
* lws must have been configured and built with
|
||||
* -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
|
||||
/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
|
||||
/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
|
||||
/* | LLL_DEBUG */;
|
||||
|
||||
if ((p = lws_cmdline_option(argc, argv, "-d")))
|
||||
logs = atoi(p);
|
||||
|
||||
lws_set_log_level(logs, NULL);
|
||||
lwsl_user("LWS minimal http server libuv + foreign loop |"
|
||||
" visit http://localhost:7681\n");
|
||||
|
||||
/*
|
||||
* We prepare the info here, but don't use it until later in the
|
||||
* timer callback, to demonstrate the independence of the foreign loop
|
||||
* and lws.
|
||||
*/
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.error_document_404 = "/404.html";
|
||||
info.pcontext = &context;
|
||||
|
||||
if (lws_cmdline_option(argc, argv, "-s")) {
|
||||
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.ssl_cert_filepath = "localhost-100y.cert";
|
||||
info.ssl_private_key_filepath = "localhost-100y.key";
|
||||
}
|
||||
|
||||
if (lws_cmdline_option(argc, argv, "--uv"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBUV;
|
||||
else
|
||||
if (lws_cmdline_option(argc, argv, "--event"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEVENT;
|
||||
else
|
||||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else {
|
||||
lwsl_err("This app only makes sense when used\n");
|
||||
lwsl_err(" with a foreign loop, --uv, --event, or --ev\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_user(" This app creates a foreign event loop with a timer +\n");
|
||||
lwsl_user(" signalhandler, and performs a test in three phases:\n");
|
||||
lwsl_user("\n");
|
||||
lwsl_user(" 1) 5s: Runs the loop with just the timer\n");
|
||||
lwsl_user(" 2) 10s: create an lws context serving on localhost:7681\n");
|
||||
lwsl_user(" using the same foreign loop. Destroy it after 10s.\n");
|
||||
lwsl_user(" 3) 5s: Run the loop again with just the timer\n");
|
||||
lwsl_user("\n");
|
||||
lwsl_user(" Finally close only the timer and signalhandler and\n");
|
||||
lwsl_user(" exit the loop cleanly\n");
|
||||
|
||||
lwsl_notice("%s\n", info.ssl_cert_filepath);
|
||||
|
||||
/* foreign loop specific startup and run */
|
||||
|
||||
#if defined(LWS_WITH_LIBUV)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBUV)
|
||||
foreign_event_loop_init_and_run_libuv();
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEVENT)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBEVENT)
|
||||
foreign_event_loop_init_and_run_libevent();
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBEV)
|
||||
foreign_event_loop_init_and_run_libev();
|
||||
#endif
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
/* foreign loop specific cleanup and exit */
|
||||
|
||||
#if defined(LWS_WITH_LIBUV)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBUV)
|
||||
foreign_event_loop_cleanup_libuv();
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEVENT)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBEVENT)
|
||||
foreign_event_loop_cleanup_libevent();
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
if (info.options & LWS_SERVER_OPTION_LIBEV)
|
||||
foreign_event_loop_cleanup_libev();
|
||||
#endif
|
||||
|
||||
lwsl_user("%s: exiting...\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
/*
|
||||
* lws-minimal-http-server-libuv-foreign
|
||||
*
|
||||
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates the most minimal http server you can make with lws that
|
||||
* uses a libuv event loop created outside lws. It shows how lws can
|
||||
* participate in someone else's event loop and clean up after itself.
|
||||
*
|
||||
* To keep it simple, it serves stuff from the subdirectory
|
||||
* "./mount-origin" of the directory it was started in.
|
||||
* You can change that by changing mount.origin below.
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
static struct lws_context *context;
|
||||
static uv_loop_t loop;
|
||||
static int lifetime = 5, reported;
|
||||
struct lws_context_creation_info info;
|
||||
|
||||
enum {
|
||||
TEST_STATE_CREATE_LWS_CONTEXT,
|
||||
TEST_STATE_DESTROY_LWS_CONTEXT,
|
||||
TEST_STATE_EXIT
|
||||
};
|
||||
|
||||
static int sequence = TEST_STATE_CREATE_LWS_CONTEXT;
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ NULL, /* linked-list "next" */
|
||||
/* .mountpoint */ "/", /* mountpoint URL */
|
||||
/* .origin */ "./mount-origin", /* serve from dir */
|
||||
/* .def */ "index.html", /* default filename */
|
||||
/* .protocol */ NULL,
|
||||
/* .cgienv */ NULL,
|
||||
/* .extra_mimetypes */ NULL,
|
||||
/* .interpret */ NULL,
|
||||
/* .cgi_timeout */ 0,
|
||||
/* .cache_max_age */ 0,
|
||||
/* .auth_mask */ 0,
|
||||
/* .cache_reusable */ 0,
|
||||
/* .cache_revalidate */ 0,
|
||||
/* .cache_intermediaries */ 0,
|
||||
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
|
||||
/* .mountpoint_len */ 1, /* char count */
|
||||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
void signal_cb(uv_signal_t *watcher, int signum)
|
||||
{
|
||||
lwsl_notice("Signal %d caught, exiting...\n", watcher->signum);
|
||||
|
||||
switch (watcher->signum) {
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
break;
|
||||
default:
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
if (context)
|
||||
lws_context_destroy(context);
|
||||
}
|
||||
|
||||
/* this logs once a second to show that the foreign loop assets are working */
|
||||
|
||||
static void
|
||||
timer_cb(uv_timer_t *t)
|
||||
{
|
||||
void *foreign_loops[1];
|
||||
|
||||
foreign_loops[0] = &loop;
|
||||
info.foreign_loops = foreign_loops;
|
||||
|
||||
lwsl_user("Foreign 1Hz timer\n");
|
||||
|
||||
if (sequence == TEST_STATE_EXIT && !context && !reported) {
|
||||
/*
|
||||
* at this point the lws_context_destroy() we did earlier
|
||||
* has completed and the entire context is wholly destroyed
|
||||
*/
|
||||
lwsl_user("lws_destroy_context() completed, continuing for 5s\n");
|
||||
reported = 1;
|
||||
}
|
||||
|
||||
if (--lifetime)
|
||||
return;
|
||||
|
||||
switch (sequence++) {
|
||||
case TEST_STATE_CREATE_LWS_CONTEXT:
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
lwsl_err("lws init failed\n");
|
||||
return;
|
||||
}
|
||||
lwsl_user("LWS Context created and active for 10s\n");
|
||||
lifetime = 11;
|
||||
break;
|
||||
case TEST_STATE_DESTROY_LWS_CONTEXT:
|
||||
/* cleanup the lws part */
|
||||
lwsl_user("Destroying lws context and continuing loop for 5s\n");
|
||||
lws_context_destroy(context);
|
||||
lifetime = 6;
|
||||
break;
|
||||
|
||||
case TEST_STATE_EXIT:
|
||||
lwsl_user("Deciding to exit foreign loop too\n");
|
||||
uv_stop(&loop);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
uv_timer_t timer_outer;
|
||||
uv_signal_t sighandler;
|
||||
const char *p;
|
||||
int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
|
||||
/* for LLL_ verbosity above NOTICE to be built into lws,
|
||||
* lws must have been configured and built with
|
||||
* -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
|
||||
/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
|
||||
/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
|
||||
/* | LLL_DEBUG */;
|
||||
|
||||
if ((p = lws_cmdline_option(argc, argv, "-d")))
|
||||
logs = atoi(p);
|
||||
|
||||
lws_set_log_level(logs, NULL);
|
||||
lwsl_user("LWS minimal http server libuv + foreign loop |"
|
||||
" visit http://localhost:7681\n");
|
||||
|
||||
/*
|
||||
* We prepare the info here, but don't use it until later in the
|
||||
* timer callback, to demonstrate the independence of the foreign loop
|
||||
* and lws.
|
||||
*/
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.error_document_404 = "/404.html";
|
||||
info.options = LWS_SERVER_OPTION_LIBUV;
|
||||
info.pcontext = &context;
|
||||
if (lws_cmdline_option(argc, argv, "-s")) {
|
||||
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.ssl_cert_filepath = "localhost-100y.cert";
|
||||
info.ssl_private_key_filepath = "localhost-100y.key";
|
||||
}
|
||||
info.pcontext = &context;
|
||||
|
||||
lwsl_user(" This app creates a uv loop with a timer + signalhandler, and\n");
|
||||
lwsl_user(" performs a test in three phases:\n");
|
||||
lwsl_user("\n");
|
||||
lwsl_user(" 1) 5s: Runs the loop with just the timer\n");
|
||||
lwsl_user(" 2) 10s: create an lws context serving on localhost:7681\n");
|
||||
lwsl_user(" using the same uv loop. Destroy it after 10s.\n");
|
||||
lwsl_user(" 3) 5s: Run the loop again with just the timer\n");
|
||||
lwsl_user("\n");
|
||||
lwsl_user(" Finally close only the timer and signalhandler and\n");
|
||||
lwsl_user(" exit the loop cleanly\n");
|
||||
|
||||
/* we create and start our "foreign loop" */
|
||||
|
||||
uv_loop_init(&loop);
|
||||
uv_signal_init(&loop, &sighandler);
|
||||
uv_signal_start(&sighandler, signal_cb, SIGINT);
|
||||
|
||||
uv_timer_init(&loop, &timer_outer);
|
||||
uv_timer_start(&timer_outer, timer_cb, 0, 1000);
|
||||
|
||||
uv_run(&loop, UV_RUN_DEFAULT);
|
||||
|
||||
/* in the case we hit ^C while lws still exists */
|
||||
lws_context_destroy(context);
|
||||
|
||||
/* cleanup the foreign loop assets */
|
||||
|
||||
uv_timer_stop(&timer_outer);
|
||||
uv_close((uv_handle_t*)&timer_outer, NULL);
|
||||
uv_signal_stop(&sighandler);
|
||||
uv_close((uv_handle_t *)&sighandler, NULL);
|
||||
|
||||
uv_run(&loop, UV_RUN_DEFAULT);
|
||||
uv_loop_close(&loop);
|
||||
|
||||
lwsl_user("%s: exiting...\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -3,10 +3,10 @@
|
|||
<body>
|
||||
<img src="libwebsockets.org-logo.png"><br>
|
||||
|
||||
Hello from the <b>minimal http server libuv foreign loop example</b>.
|
||||
Hello from the <b>minimal http server eventlib foreign loop example</b>.
|
||||
<br>
|
||||
The timer messages in the console are coming from<br>
|
||||
a timer on the libuv loop set up before the lws context<br>
|
||||
a timer on the event library lib loop set up before the lws context<br>
|
||||
started using it.
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
* lws-minimal-http-server-libuv
|
||||
* lws-minimal-http-server-eventlib
|
||||
*
|
||||
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates the most minimal http server you can make with lws using
|
||||
* the libuv event loop.
|
||||
* This demonstrates a minimal http[s] server that can work with any of the
|
||||
* supported event loop backends, or the default poll() one.
|
||||
*
|
||||
* To keep it simple, it serves stuff from the subdirectory
|
||||
* "./mount-origin" of the directory it was started in.
|
||||
|
@ -42,22 +42,22 @@ static const struct lws_http_mount mount = {
|
|||
|
||||
void signal_cb(void *handle, int signum)
|
||||
{
|
||||
uv_signal_t *watcher = (uv_signal_t *)handle;
|
||||
|
||||
lwsl_notice("Signal %d caught, exiting...\n", watcher->signum);
|
||||
|
||||
switch (watcher->signum) {
|
||||
switch (signum) {
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
break;
|
||||
default:
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
abort();
|
||||
lwsl_err("%s: signal %d\n", __func__, signum);
|
||||
break;
|
||||
}
|
||||
lws_context_destroy(context);
|
||||
}
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
signal_cb(NULL, sig);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
|
@ -74,19 +74,32 @@ int main(int argc, const char **argv)
|
|||
logs = atoi(p);
|
||||
|
||||
lws_set_log_level(logs, NULL);
|
||||
lwsl_user("LWS minimal http server libuv [-s (ssl)] | visit http://localhost:7681\n");
|
||||
lwsl_user("LWS minimal http server eventlib | visit http://localhost:7681\n");
|
||||
lwsl_user(" [-s (ssl)] [--uv (libuv)] [--ev (libev)] [--event (libevent)]\n");
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.error_document_404 = "/404.html";
|
||||
info.pcontext = &context;
|
||||
info.signal_cb = signal_cb;
|
||||
|
||||
if (lws_cmdline_option(argc, argv, "-s")) {
|
||||
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.ssl_cert_filepath = "localhost-100y.cert";
|
||||
info.ssl_private_key_filepath = "localhost-100y.key";
|
||||
}
|
||||
info.options |= LWS_SERVER_OPTION_LIBUV;
|
||||
info.signal_cb = signal_cb;
|
||||
|
||||
if (lws_cmdline_option(argc, argv, "--uv"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBUV;
|
||||
else
|
||||
if (lws_cmdline_option(argc, argv, "--event"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEVENT;
|
||||
else
|
||||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
|
@ -94,8 +107,10 @@ int main(int argc, const char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
lws_service(context, 0);
|
||||
while (!lws_service(context, 0))
|
||||
;
|
||||
|
||||
lwsl_info("calling external context destroy\n");
|
||||
lws_context_destroy(context);
|
||||
|
||||
return 0;
|
|
@ -79,6 +79,11 @@ dotest() {
|
|||
if [ -e $2/$MYTEST/$T.result ] ; then
|
||||
R=`cat $2/$MYTEST/$T.result`
|
||||
cat $2/$MYTEST/$T.log | tail -n 3 > $2/$MYTEST/$T.time
|
||||
if [ $R -ne 0 ] ; then
|
||||
echo
|
||||
cat $2/$MYTEST/$T.log
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
feedback $MYTEST $R $T
|
||||
|
|
|
@ -68,6 +68,8 @@ file_upload_cb(void *data, const char *name, const char *filename,
|
|||
(struct per_session_data__post_demo *)data;
|
||||
#if !defined(LWS_WITH_ESP32)
|
||||
int n;
|
||||
|
||||
(void)n;
|
||||
#endif
|
||||
|
||||
switch (state) {
|
||||
|
@ -92,7 +94,7 @@ file_upload_cb(void *data, const char *name, const char *filename,
|
|||
|
||||
#if !defined(LWS_WITH_ESP32)
|
||||
n = write((int)(long long)pss->fd, buf, len);
|
||||
lwsl_notice("%s: write %d says %d\n", __func__, len, n);
|
||||
lwsl_info("%s: write %d says %d\n", __func__, len, n);
|
||||
#else
|
||||
lwsl_notice("%s: Received chunk size %d\n", __func__, len);
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,10 @@ LOG=/tmp/lwslog
|
|||
A=`which libwebsockets-test-server`
|
||||
INSTALLED=`dirname $A`
|
||||
|
||||
SHAREDIR=$INSTALLED/../share/libwebsockets-test-server
|
||||
CORPUS=$SHAREDIR/test.html
|
||||
|
||||
|
||||
CPID=
|
||||
LEN=0
|
||||
|
||||
|
@ -28,24 +32,26 @@ function check {
|
|||
#dd if=$LOG bs=1 skip=$LEN 2>/dev/null
|
||||
|
||||
if [ "$1" = "default" ] ; then
|
||||
diff /tmp/lwscap $INSTALLED/../share/libwebsockets-test-server/test.html > /dev/null
|
||||
diff /tmp/lwscap $CORPUS > /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "FAIL: got something other than test.html back"
|
||||
echo "FAIL: got something other than $CORPUS back"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ "$1" = "defaultplusforbidden" ] ; then
|
||||
cat $INSTALLED/../share/libwebsockets-test-server/test.html > /tmp/plusforb
|
||||
cat $CORPUS > /tmp/plusforb
|
||||
echo -e -n "HTTP/1.0 403 Forbidden\x0d\x0acontent-type: text/html\x0d\x0acontent-length: 38\x0d\x0a\x0d\x0a<html><body><h1>403</h1></body></html>" >> /tmp/plusforb
|
||||
diff /tmp/lwscap /tmp/plusforb > /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
cat $INSTALLED/../share/libwebsockets-test-server/test.html > /tmp/plusforb
|
||||
cat $CORPUS > /tmp/plusforb
|
||||
|
||||
echo -e -n "HTTP/1.1 403 Forbidden\x0d\x0acontent-type: text/html\x0d\x0acontent-length: 38\x0d\x0a\x0d\x0a<html><body><h1>403</h1></body></html>" >> /tmp/plusforb
|
||||
diff /tmp/lwscap /tmp/plusforb > /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
|
||||
echo "FAIL: got something other than test.html + forbidden back"
|
||||
echo "FAIL: got something other than $CORPUS + forbidden back"
|
||||
tail -n 10 /tmp/lwscap
|
||||
tail -n 100 $LOG
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
@ -58,8 +64,16 @@ function check {
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" = "notfound" ] ; then
|
||||
if [ -z "`grep '<h1>404</h1>' /tmp/lwscap`" ] ; then
|
||||
echo "FAIL: should have told not found"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ "$1" = "rejected" ] ; then
|
||||
if [ -z "`grep '<h1>406</h1>' /tmp/lwscap`" ] ; then
|
||||
if [ -z "`grep '<h1>404</h1>' /tmp/lwscap`" ] ; then
|
||||
echo "FAIL: should have told forbidden (test server has no dirs)"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -67,7 +81,7 @@ function check {
|
|||
|
||||
|
||||
if [ "$1" = "media" ] ; then
|
||||
if [ -z "`grep '<h1>415</h1>' /tmp/lwscap`" ] ; then
|
||||
if [ -z "`grep '<h1>404</h1>' /tmp/lwscap`" ] ; then
|
||||
echo "FAIL: should have told unknown media type"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -126,6 +140,7 @@ echo
|
|||
echo "---- /cgi-bin/settingsjs?UPDATE_SETTINGS=1&Root_Channels_1_Channel_name_http_post=%3F&Root_Channels_1_Channel_location_http_post=%3F"
|
||||
rm -f /tmp/lwscap
|
||||
echo -n -e "GET /cgi-bin/settingsjs?UPDATE_SETTINGS=1&Root_Channels_1_Channel_name_http_post=%3F&Root_Channels_1_Channel_location_http_post=%3F HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
cat /tmp/lwscap
|
||||
check 1 "UPDATE_SETTINGS=1"
|
||||
check 2 "Root_Channels_1_Channel_name_http_post=?"
|
||||
check 3 "Root_Channels_1_Channel_location_http_post=?"
|
||||
|
@ -147,16 +162,16 @@ check 1 "key1_2=value1"
|
|||
check
|
||||
|
||||
echo
|
||||
echo "---- ? processing (%2f%2e%2e%2f%2e./test.html?arg=1)"
|
||||
echo "---- ? processing (%2f%2e%2e%2f%2e./xxtest.html?arg=1)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -n -e "GET %2f%2e%2e%2f%2e./test.html?arg=1 HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
echo -n -e "GET %2f%2e%2e%2f%2e./xxtest.html?arg=1 HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check 1 "arg=1"
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- ? processing (%2f%2e%2e%2f%2e./test.html?arg=/../.)"
|
||||
echo "---- ? processing (%2f%2e%2e%2f%2e./xxtest.html?arg=/../.)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -n -e "GET %2f%2e%2e%2f%2e./test.html?arg=/../. HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
echo -n -e "GET %2f%2e%2e%2f%2e./xxtest.html?arg=/../. HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check 1 "arg=/../."
|
||||
check
|
||||
|
||||
|
@ -167,23 +182,23 @@ check
|
|||
|
||||
echo
|
||||
echo "---- spam more than the name buffer of crap"
|
||||
dd if=/dev/urandom bs=1 count=80 2>/dev/null | nc -i1s $SERVER $PORT
|
||||
dd if=/dev/urandom bs=1 count=80 2>/dev/null | nc -i1 $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- spam 10MB of crap"
|
||||
dd if=/dev/urandom bs=1 count=655360 | nc -i1s $SERVER $PORT
|
||||
dd if=/dev/urandom bs=1 count=655360 | nc -i1 $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- malformed URI"
|
||||
echo "GET nonsense................................................................................................................" \
|
||||
| nc -i1s $SERVER $PORT
|
||||
| nc -i1 $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- missing URI"
|
||||
echo -n -e "GET HTTP/1.0\x0d\x0a\x0d\x0a" | nc -i1s $SERVER $PORT >/tmp/lwscap
|
||||
echo -n -e "GET HTTP/1.0\x0d\x0a\x0d\x0a" | nc -i1 $SERVER $PORT >/tmp/lwscap
|
||||
check
|
||||
|
||||
echo
|
||||
|
@ -210,7 +225,7 @@ echo -n -e "GET blah HTTP/1.0\x0d\x0a...........................................
|
|||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
| nc -i1s $SERVER $PORT
|
||||
| nc -i1 $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
|
@ -232,28 +247,13 @@ echo -n -e "GET ................................................................
|
|||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
| nc -i1s $SERVER $PORT
|
||||
| nc -i1 $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- good request but http payload coming too (test.html served then forbidden)"
|
||||
echo -n -e "GET /test.html HTTP/1.1\x0d\x0a\x0d\x0aILLEGAL-PAYLOAD........................................" \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
| nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
| cat - /dev/zero | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check defaultplusforbidden
|
||||
check
|
||||
|
||||
|
@ -261,7 +261,8 @@ echo
|
|||
echo "---- nonexistent file"
|
||||
rm -f /tmp/lwscap
|
||||
echo -n -e "GET /nope HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check media
|
||||
cat /tmp/lwscap
|
||||
check notfound
|
||||
check
|
||||
|
||||
echo
|
||||
|
@ -275,7 +276,7 @@ echo
|
|||
echo "---- directory attack 1 (/../../../../etc/passwd should be /etc/passswd)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -n -e "GET /../../../../etc/passwd HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check rejected
|
||||
check notfound
|
||||
check
|
||||
|
||||
echo
|
||||
|
@ -317,21 +318,21 @@ echo
|
|||
echo "---- directory attack 7 (/%2e%2e%2f../../../etc/passwd should be /etc/passswd)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e -n "GET /%2e%2e%2f../../../etc/passwd HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check rejected
|
||||
check notfound
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- directory attack 8 (%2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd should be /etc/passswd)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e -n "GET %2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd HTTP/1.0\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check rejected
|
||||
check notfound
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- http/1.1 pipelining"
|
||||
rm -f /tmp/lwscap
|
||||
wget -O/tmp/lwsdump http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html 2>&1 | grep "Downloaded: 8 files" > /tmp/lwscap
|
||||
good=`cat $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html | md5sum | cut -d' ' -f1`
|
||||
good=`cat $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS | md5sum | cut -d' ' -f1`
|
||||
if [ "$good" != "`md5sum /tmp/lwsdump | cut -d' ' -f 1`" ] ; then
|
||||
echo "FAIL: mismatched content good=$good received=`md5sum /tmp/lwsdump`"
|
||||
exit 1
|
||||
|
@ -551,13 +552,11 @@ for i in \
|
|||
|
||||
R=`rm -f /tmp/lwscap ; echo -n -e "GET $i HTTP/1.0\r\n\r\n" | nc localhost 7681 2>/dev/null >/tmp/lwscap; head -n1 /tmp/lwscap| cut -d' ' -f2`
|
||||
|
||||
#cat /tmp/lwscap | head -n1
|
||||
#echo ==== $R
|
||||
|
||||
|
||||
if [ "$R" != "403" ]; then
|
||||
U=`cat $LOG | grep lws_http_serve | tail -n 1 | cut -d':' -f6 | cut -d' ' -f2`
|
||||
# echo $U
|
||||
U=`cat $LOG | grep Method: | tail -n 1 | cut -d"'" -f4 | sed "s|\\'||g"`
|
||||
echo "- \"$i\" -> $R \"$U\"" >>/tmp/results
|
||||
else
|
||||
echo "- \"$i\" -> $R" >>/tmp/results
|
||||
|
@ -565,36 +564,36 @@ fi
|
|||
done
|
||||
|
||||
cat <<EOF >/tmp/lwsresult1
|
||||
- "/..../" -> 406 "/..../"
|
||||
- "/.../." -> 406 "/.../"
|
||||
- "/...//" -> 406 "/.../"
|
||||
- "/.../a" -> 406 "/.../a"
|
||||
- "/.../w" -> 406 "/.../w"
|
||||
- "/.../?" -> 406 "/.../"
|
||||
- "/..../" -> 404 "/..../"
|
||||
- "/.../." -> 404 "/.../"
|
||||
- "/...//" -> 404 "/.../"
|
||||
- "/.../a" -> 404 "/.../a"
|
||||
- "/.../w" -> 404 "/.../w"
|
||||
- "/.../?" -> 404 "/.../"
|
||||
- "/.../%" -> 403
|
||||
- "/../.." -> 200 "/"
|
||||
- "/.././" -> 200 "/"
|
||||
- "/../.a" -> 415 "/.a"
|
||||
- "/../.w" -> 415 "/.w"
|
||||
- "/../.a" -> 404 "/.a"
|
||||
- "/../.w" -> 404 "/.w"
|
||||
- "/../.." -> 200 "/"
|
||||
- "/../.%" -> 403
|
||||
- "/..//." -> 200 "/"
|
||||
- "/..///" -> 200 "/"
|
||||
- "/..//a" -> 415 "/a"
|
||||
- "/..//w" -> 415 "/w"
|
||||
- "/..//a" -> 404 "/a"
|
||||
- "/..//w" -> 404 "/w"
|
||||
- "/..//?" -> 200 "/"
|
||||
- "/..//%" -> 403
|
||||
- "/../a." -> 415 "/a."
|
||||
- "/../a/" -> 406 "/a/"
|
||||
- "/../aa" -> 415 "/aa"
|
||||
- "/../aw" -> 415 "/aw"
|
||||
- "/../a?" -> 415 "/a"
|
||||
- "/../a." -> 404 "/a."
|
||||
- "/../a/" -> 404 "/a/"
|
||||
- "/../aa" -> 404 "/aa"
|
||||
- "/../aw" -> 404 "/aw"
|
||||
- "/../a?" -> 404 "/a"
|
||||
- "/../a%" -> 403
|
||||
- "/../w." -> 415 "/w."
|
||||
- "/../w/" -> 406 "/w/"
|
||||
- "/../wa" -> 415 "/wa"
|
||||
- "/../ww" -> 415 "/ww"
|
||||
- "/../w?" -> 415 "/w"
|
||||
- "/../w." -> 404 "/w."
|
||||
- "/../w/" -> 404 "/w/"
|
||||
- "/../wa" -> 404 "/wa"
|
||||
- "/../ww" -> 404 "/ww"
|
||||
- "/../w?" -> 404 "/w"
|
||||
- "/../w%" -> 403
|
||||
- "/../?." -> 200 "/"
|
||||
- "/../?/" -> 200 "/"
|
||||
|
@ -608,49 +607,49 @@ cat <<EOF >/tmp/lwsresult1
|
|||
- "/../%w" -> 403
|
||||
- "/../%?" -> 403
|
||||
- "/../%%" -> 403
|
||||
- "/./..." -> 415 "/..."
|
||||
- "/./..." -> 404 "/..."
|
||||
- "/./../" -> 200 "/"
|
||||
- "/./..a" -> 415 "/..a"
|
||||
- "/./..w" -> 415 "/..w"
|
||||
- "/./..a" -> 404 "/..a"
|
||||
- "/./..w" -> 404 "/..w"
|
||||
- "/./..?" -> 200 "/"
|
||||
- "/./..%" -> 403
|
||||
- "/.//.." -> 200 "/"
|
||||
- "/.a../" -> 406 "/.a../"
|
||||
- "/.a../" -> 404 "/.a../"
|
||||
- "/.a/.." -> 200 "/"
|
||||
- "/.w../" -> 406 "/.w../"
|
||||
- "/.w../" -> 404 "/.w../"
|
||||
- "/.w/.." -> 200 "/"
|
||||
- "/.?../" -> 415 "/."
|
||||
- "/.?../" -> 404 "/."
|
||||
- "/../.." -> 200 "/"
|
||||
- "/.%../" -> 403
|
||||
- "/.%/.." -> 403
|
||||
- "//...." -> 415 "/...."
|
||||
- "//.../" -> 406 "/.../"
|
||||
- "//...a" -> 415 "/...a"
|
||||
- "//...w" -> 415 "/...w"
|
||||
- "//...?" -> 415 "/..."
|
||||
- "//...." -> 404 "/...."
|
||||
- "//.../" -> 404 "/.../"
|
||||
- "//...a" -> 404 "/...a"
|
||||
- "//...w" -> 404 "/...w"
|
||||
- "//...?" -> 404 "/..."
|
||||
- "//...%" -> 403
|
||||
- "//../." -> 200 "/"
|
||||
- "//..//" -> 200 "/"
|
||||
- "//../a" -> 415 "/a"
|
||||
- "//../w" -> 415 "/w"
|
||||
- "//../a" -> 404 "/a"
|
||||
- "//../w" -> 404 "/w"
|
||||
- "//../?" -> 200 "/"
|
||||
- "//../%" -> 403
|
||||
- "//..a." -> 415 "/..a."
|
||||
- "//..a/" -> 406 "/..a/"
|
||||
- "//..aa" -> 415 "/..aa"
|
||||
- "//..aw" -> 415 "/..aw"
|
||||
- "//..a?" -> 415 "/..a"
|
||||
- "//..a." -> 404 "/..a."
|
||||
- "//..a/" -> 404 "/..a/"
|
||||
- "//..aa" -> 404 "/..aa"
|
||||
- "//..aw" -> 404 "/..aw"
|
||||
- "//..a?" -> 404 "/..a"
|
||||
- "//..a%" -> 403
|
||||
- "//..w." -> 415 "/..w."
|
||||
- "//..w/" -> 406 "/..w/"
|
||||
- "//..wa" -> 415 "/..wa"
|
||||
- "//..ww" -> 415 "/..ww"
|
||||
- "//..w?" -> 415 "/..w"
|
||||
- "//..w." -> 404 "/..w."
|
||||
- "//..w/" -> 404 "/..w/"
|
||||
- "//..wa" -> 404 "/..wa"
|
||||
- "//..ww" -> 404 "/..ww"
|
||||
- "//..w?" -> 404 "/..w"
|
||||
- "//..w%" -> 403
|
||||
- "//..?." -> 200 "/"
|
||||
- "//..?/" -> 200 "/"
|
||||
- "//..?a" -> 415 "/a"
|
||||
- "//..?w" -> 415 "/w"
|
||||
- "//..?a" -> 404 "/a"
|
||||
- "//..?w" -> 404 "/w"
|
||||
- "//..??" -> 200 "/"
|
||||
- "//..?%" -> 403
|
||||
- "//..%." -> 403
|
||||
|
@ -660,65 +659,65 @@ cat <<EOF >/tmp/lwsresult1
|
|||
- "//..%?" -> 403
|
||||
- "//..%%" -> 403
|
||||
- "//./.." -> 200 "/"
|
||||
- "///..." -> 415 "/..."
|
||||
- "///..." -> 404 "/..."
|
||||
- "///../" -> 200 "/"
|
||||
- "///..a" -> 415 "/..a"
|
||||
- "///..w" -> 415 "/..w"
|
||||
- "///..a" -> 404 "/..a"
|
||||
- "///..w" -> 404 "/..w"
|
||||
- "///..?" -> 200 "/"
|
||||
- "///..%" -> 403
|
||||
- "////.." -> 200 "/"
|
||||
- "//a../" -> 406 "/a../"
|
||||
- "//a../" -> 404 "/a../"
|
||||
- "//a/.." -> 200 "/"
|
||||
- "//w../" -> 406 "/w../"
|
||||
- "//w../" -> 404 "/w../"
|
||||
- "//w/.." -> 200 "/"
|
||||
- "//?../" -> 200 "/"
|
||||
- "//?/.." -> 200 "/"
|
||||
- "//%../" -> 403
|
||||
- "//%/.." -> 403
|
||||
- "/a.../" -> 406 "/a.../"
|
||||
- "/a../." -> 406 "/a../"
|
||||
- "/a..//" -> 406 "/a../"
|
||||
- "/a../a" -> 406 "/a../a"
|
||||
- "/a../w" -> 406 "/a../w"
|
||||
- "/a../?" -> 406 "/a../"
|
||||
- "/a.../" -> 404 "/a.../"
|
||||
- "/a../." -> 404 "/a../"
|
||||
- "/a..//" -> 404 "/a../"
|
||||
- "/a../a" -> 404 "/a../a"
|
||||
- "/a../w" -> 404 "/a../w"
|
||||
- "/a../?" -> 404 "/a../"
|
||||
- "/a../%" -> 403
|
||||
- "/a./.." -> 200 "/"
|
||||
- "/a/..." -> 406 "/a/..."
|
||||
- "/a/..." -> 404 "/a/..."
|
||||
- "/a/../" -> 200 "/"
|
||||
- "/a/..a" -> 406 "/a/..a"
|
||||
- "/a/..w" -> 406 "/a/..w"
|
||||
- "/a/..a" -> 404 "/a/..a"
|
||||
- "/a/..w" -> 404 "/a/..w"
|
||||
- "/a/..?" -> 200 "/"
|
||||
- "/a/..%" -> 403
|
||||
- "/a//.." -> 200 "/"
|
||||
- "/aa../" -> 406 "/aa../"
|
||||
- "/aa../" -> 404 "/aa../"
|
||||
- "/aa/.." -> 200 "/"
|
||||
- "/aw../" -> 406 "/aw../"
|
||||
- "/aw../" -> 404 "/aw../"
|
||||
- "/aw/.." -> 200 "/"
|
||||
- "/a?../" -> 415 "/a"
|
||||
- "/a?/.." -> 415 "/a"
|
||||
- "/a?../" -> 404 "/a"
|
||||
- "/a?/.." -> 404 "/a"
|
||||
- "/a%../" -> 403
|
||||
- "/a%/.." -> 403
|
||||
- "/w.../" -> 406 "/w.../"
|
||||
- "/w../." -> 406 "/w../"
|
||||
- "/w..//" -> 406 "/w../"
|
||||
- "/w../a" -> 406 "/w../a"
|
||||
- "/w../w" -> 406 "/w../w"
|
||||
- "/w../?" -> 406 "/w../"
|
||||
- "/w.../" -> 404 "/w.../"
|
||||
- "/w../." -> 404 "/w../"
|
||||
- "/w..//" -> 404 "/w../"
|
||||
- "/w../a" -> 404 "/w../a"
|
||||
- "/w../w" -> 404 "/w../w"
|
||||
- "/w../?" -> 404 "/w../"
|
||||
- "/w../%" -> 403
|
||||
- "/w./.." -> 200 "/"
|
||||
- "/w/..." -> 406 "/w/..."
|
||||
- "/w/..." -> 404 "/w/..."
|
||||
- "/w/../" -> 200 "/"
|
||||
- "/w/..a" -> 406 "/w/..a"
|
||||
- "/w/..w" -> 406 "/w/..w"
|
||||
- "/w/..a" -> 404 "/w/..a"
|
||||
- "/w/..w" -> 404 "/w/..w"
|
||||
- "/w/..?" -> 200 "/"
|
||||
- "/w/..%" -> 403
|
||||
- "/w//.." -> 200 "/"
|
||||
- "/wa../" -> 406 "/wa../"
|
||||
- "/wa../" -> 404 "/wa../"
|
||||
- "/wa/.." -> 200 "/"
|
||||
- "/ww../" -> 406 "/ww../"
|
||||
- "/ww../" -> 404 "/ww../"
|
||||
- "/ww/.." -> 200 "/"
|
||||
- "/w?../" -> 415 "/w"
|
||||
- "/w?/.." -> 415 "/w"
|
||||
- "/w?../" -> 404 "/w"
|
||||
- "/w?/.." -> 404 "/w"
|
||||
- "/w%../" -> 403
|
||||
- "/w%/.." -> 403
|
||||
- "/?.../" -> 200 "/"
|
||||
|
@ -767,13 +766,13 @@ cat <<EOF >/tmp/lwsresult1
|
|||
- "/%?/.." -> 403
|
||||
- "/%%../" -> 403
|
||||
- "/%%/.." -> 403
|
||||
- "/a/w/../a" -> 406 "/a/a"
|
||||
- "/path/to/dir/../other/dir" -> 406 "/path/to/other/dir"
|
||||
- "/a/w/../a" -> 404 "/a/a"
|
||||
- "/path/to/dir/../other/dir" -> 404 "/path/to/other/dir"
|
||||
EOF
|
||||
|
||||
if [ "`md5sum /tmp/results | cut -d' ' -f 1`" != "`md5sum /tmp/lwsresult1 | cut -d' ' -f1`" ] ; then
|
||||
echo "Differences..."
|
||||
diff -urN /tmp/results /tmp/lwsresult1
|
||||
diff -urN /tmp/lwsresult1 /tmp/results
|
||||
exit 1
|
||||
else
|
||||
echo "OK"
|
|
@ -14,7 +14,7 @@ else
|
|||
sudo make install &&
|
||||
../minimal-examples/selftests.sh &&
|
||||
../scripts/h2spec.sh &&
|
||||
../test-apps/attack.sh &&
|
||||
../scripts/attack.sh &&
|
||||
../scripts/h2load.sh &&
|
||||
../scripts/autobahn-test.sh
|
||||
else
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
|
||||
int close_testing;
|
||||
int max_poll_elements;
|
||||
|
@ -77,12 +78,69 @@ char crl_path[1024] = "";
|
|||
#include "../plugins/protocol_post_demo.c"
|
||||
#endif
|
||||
|
||||
static int
|
||||
lws_callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
{
|
||||
const unsigned char *c;
|
||||
char buf[1024];
|
||||
int n = 0, hlen;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_HTTP:
|
||||
|
||||
/* non-mount-handled accesses will turn up here */
|
||||
|
||||
/* dump the headers */
|
||||
|
||||
do {
|
||||
c = lws_token_to_string(n);
|
||||
if (!c) {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
|
||||
hlen = lws_hdr_total_length(wsi, n);
|
||||
if (!hlen || hlen > (int)sizeof(buf) - 1) {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
|
||||
lws_hdr_copy(wsi, buf, sizeof buf, n);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
fprintf(stderr, " %s = %s\n", (char *)c, buf);
|
||||
n++;
|
||||
} while (c);
|
||||
|
||||
/* dump the individual URI Arg parameters */
|
||||
|
||||
n = 0;
|
||||
while (lws_hdr_copy_fragment(wsi, buf, sizeof(buf),
|
||||
WSI_TOKEN_HTTP_URI_ARGS, n) > 0) {
|
||||
lwsl_notice("URI Arg %d: %s\n", ++n, buf);
|
||||
}
|
||||
|
||||
if (lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL))
|
||||
return -1;
|
||||
|
||||
if (lws_http_transaction_completed(wsi))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
/* list of supported protocols and callbacks */
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
/* first protocol must always be HTTP handler */
|
||||
|
||||
{ "http-only", lws_callback_http_dummy, 0, 0, },
|
||||
{ "http-only", lws_callback_http, 0, 0, },
|
||||
#if defined(LWS_ROLE_WS)
|
||||
LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT,
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
|
|
Loading…
Add table
Reference in a new issue