diff --git a/include/libwebsockets/lws-adopt.h b/include/libwebsockets/lws-adopt.h index 1ffccad0f..1a4842e77 100644 --- a/include/libwebsockets/lws-adopt.h +++ b/include/libwebsockets/lws-adopt.h @@ -113,6 +113,40 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type, lws_sock_file_fd_type fd, const char *vh_prot_name, struct lws *parent); +typedef struct lws_adopt_desc { + struct lws_vhost *vh; /**< vhost the wsi should belong to */ + lws_adoption_type type; /**< OR-ed combinations of lws_adoption_type flags */ + lws_sock_file_fd_type fd; /**< union with either .sockfd or .filefd set */ + const char *vh_prot_name; /**< NULL or vh protocol name to bind raw connection to */ + struct lws *parent; /**< NULL or struct lws to attach new_wsi to as a child */ + void *opaque; /**< opaque pointer to set on created wsi */ +} lws_adopt_desc_t; + +/** +* lws_adopt_descriptor_vhost_via_info() - adopt foreign socket or file descriptor +* if socket descriptor, should already have been accepted from listen socket +* +* \param info: the struct containing the parameters +* +* - vh: lws vhost +* - type: OR-ed combinations of lws_adoption_type flags +* - fd: union with either .sockfd or .filefd set +* - vh_prot_name: NULL or vh protocol name to bind raw connection to +* - parent: NULL or struct lws to attach new_wsi to as a child +* - opaque: opaque pointer to set on created wsi +* +* Either returns new wsi bound to accept_fd, or closes accept_fd and +* returns NULL, having cleaned up any new wsi pieces. +* +* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's +* ready to accept an upgrade to ws or just serve http. +* +* parent may be NULL, if given it should be an existing wsi that will become the +* parent of the new wsi created by this call. +*/ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info); + /** * lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it * for the default vhost of context. @@ -181,6 +215,7 @@ lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, * \param protocol_name: Name of protocol on vhost to bind wsi to * \param ifname: NULL, for network interface name to bind socket to * \param parent_wsi: NULL or parent wsi new wsi will be a child of + * \param opaque: set created wsi opaque ptr to this * \param retry_policy: NULL for vhost default policy else wsi specific policy * * Either returns new wsi bound to accept_fd, or closes accept_fd and @@ -189,6 +224,10 @@ lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, LWS_VISIBLE LWS_EXTERN struct lws * lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, int flags, const char *protocol_name, const char *ifname, - struct lws *parent_wsi, const lws_retry_bo_t *retry_policy); + struct lws *parent_wsi, void *opaque, + const lws_retry_bo_t *retry_policy); #endif + + + ///@} diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 38bb86915..8421a50be 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -117,7 +117,8 @@ lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi) static struct lws * lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, - const char *vh_prot_name, struct lws *parent) + const char *vh_prot_name, struct lws *parent, + void *opaque) { struct lws_context *context = vh->context; struct lws_context_per_thread *pt; @@ -137,6 +138,8 @@ lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, if (!new_wsi) return NULL; + new_wsi->opaque_user_data = opaque; + pt = &context->pt[(int)new_wsi->tsi]; lws_stats_bump(pt, LWSSTATS_C_CONNECTIONS, 1); @@ -307,23 +310,39 @@ fail: /* if not a socket, it's a raw, non-ssl file descriptor */ -LWS_VISIBLE struct lws * +struct lws * lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type, lws_sock_file_fd_type fd, const char *vh_prot_name, struct lws *parent) +{ + lws_adopt_desc_t info; + + memset(&info, 0, sizeof(info)); + + info.vh = vh; + info.type = type; + info.fd = fd; + info.vh_prot_name = vh_prot_name; + info.parent = parent; + + return lws_adopt_descriptor_vhost_via_info(&info); +} + +struct lws * +lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info) { struct lws *new_wsi; #if defined(LWS_WITH_PEER_LIMITS) struct lws_peer *peer = NULL; - if (type & LWS_ADOPT_SOCKET) { - peer = lws_get_or_create_peer(vh, fd.sockfd); + if (info->type & LWS_ADOPT_SOCKET) { + peer = lws_get_or_create_peer(info->vh, info->fd.sockfd); - if (peer && vh->context->ip_limit_wsi && - peer->count_wsi >= vh->context->ip_limit_wsi) { + if (peer && info->vh->context->ip_limit_wsi && + peer->count_wsi >= info->vh->context->ip_limit_wsi) { lwsl_notice("Peer reached wsi limit %d\n", - vh->context->ip_limit_wsi); - lws_stats_bump(&vh->context->pt[0], + info->vh->context->ip_limit_wsi); + lws_stats_bump(&info->vh->context->pt[0], LWSSTATS_C_PEER_LIMIT_WSI_DENIED, 1); return NULL; @@ -331,27 +350,29 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type, } #endif - new_wsi = lws_adopt_descriptor_vhost1(vh, type, vh_prot_name, parent); + new_wsi = lws_adopt_descriptor_vhost1(info->vh, info->type, + info->vh_prot_name, info->parent, + info->opaque); if (!new_wsi) { - if (type & LWS_ADOPT_SOCKET) - compatible_close(fd.sockfd); + if (info->type & LWS_ADOPT_SOCKET) + compatible_close(info->fd.sockfd); return NULL; } #if defined(LWS_WITH_ACCESS_LOG) - lws_get_peer_simple_fd(fd.sockfd, new_wsi->simple_ip, + lws_get_peer_simple_fd(info->fd.sockfd, new_wsi->simple_ip, sizeof(new_wsi->simple_ip)); #endif #if defined(LWS_WITH_PEER_LIMITS) if (peer) - lws_peer_add_wsi(vh->context, peer, new_wsi); + lws_peer_add_wsi(info->vh->context, peer, new_wsi); #endif - return lws_adopt_descriptor_vhost2(new_wsi, type, fd); + return lws_adopt_descriptor_vhost2(new_wsi, info->type, info->fd); } -LWS_VISIBLE struct lws * +struct lws * lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd) { lws_sock_file_fd_type fd; @@ -561,7 +582,8 @@ bail: struct lws * lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, int flags, const char *protocol_name, const char *ifname, - struct lws *parent_wsi, const lws_retry_bo_t *retry_policy) + struct lws *parent_wsi, void *opaque, + const lws_retry_bo_t *retry_policy) { #if !defined(LWS_PLAT_OPTEE) struct lws *wsi; @@ -572,7 +594,7 @@ lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, /* create the logical wsi without any valid fd */ wsi = lws_adopt_descriptor_vhost1(vhost, LWS_ADOPT_RAW_SOCKET_UDP, - protocol_name, parent_wsi); + protocol_name, parent_wsi, opaque); if (!wsi) { lwsl_err("%s: udp wsi creation failed\n", __func__); goto bail; diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index 33c8f3985..7e3db09b1 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -320,7 +320,7 @@ ok: context->async_dns.wsi = lws_create_adopt_udp(context->vhost_list, ads, 53, 0, lws_async_dns_protocol.name, NULL, - NULL, &retry_policy); + NULL, NULL, &retry_policy); if (!dns->wsi) { lwsl_err("%s: foreign socket adoption failed\n", __func__); return 1; diff --git a/lib/system/dhcpclient/dhcpclient.c b/lib/system/dhcpclient/dhcpclient.c index 38dceffb2..3c2031d21 100644 --- a/lib/system/dhcpclient/dhcpclient.c +++ b/lib/system/dhcpclient/dhcpclient.c @@ -199,7 +199,7 @@ lws_dhcpc_retry_conn(struct lws_sorted_usec_list *sul) 68, LWS_CAUDP_PF_PACKET | LWS_CAUDP_BROADCAST, "lws-dhcpclient", (const char *)&r[1], - NULL, &bo2); + NULL, NULL, &bo2); lwsl_debug("%s: created wsi_raw: %p\n", __func__, r->wsi_raw); if (!r->wsi_raw) { lwsl_err("%s: unable to create udp skt\n", __func__); diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index 46236acf1..c5849d9b9 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -82,7 +82,8 @@ lws_ntpc_retry_conn(struct lws_sorted_usec_list *sul) v->retry_count_write = 0; v->wsi_udp = lws_create_adopt_udp(v->vhost, v->ntp_server_ads, 123, 0, - v->protocol->name, NULL, NULL, &bo2); + v->protocol->name, NULL, NULL, NULL, + &bo2); lwsl_debug("%s: created wsi_udp: %p\n", __func__, v->wsi_udp); if (!v->wsi_udp) { lwsl_err("%s: unable to create udp skt\n", __func__); diff --git a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c index 36419e89a..e85bb7d52 100644 --- a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c +++ b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c @@ -170,7 +170,7 @@ int main(int argc, const char **argv) * Create our own "foreign" UDP socket bound to 7681/udp */ if (!lws_create_adopt_udp(vhost, NULL, 7681, LWS_CAUDP_BIND, - protocols[0].name, NULL, NULL, NULL)) { + protocols[0].name, NULL, NULL, NULL, NULL)) { lwsl_err("%s: foreign socket adoption failed\n", __func__); goto bail; }