Comments (13)
How about this kind of thing?
diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h
index b48a3200..d4f60289 100644
--- a/include/libwebsockets/lws-context-vhost.h
+++ b/include/libwebsockets/lws-context-vhost.h
@@ -959,6 +959,14 @@ struct lws_context_creation_info {
* selected default loglevel can then be cleanly overridden using -d 1039 etc
* commandline switch */
+ lws_sockfd_type vh_listen_sockfd;
+ /**< VHOST: 0 for normal vhost listen socket fd creation, if any.
+ * Nonzero to force the selection of an already-existing fd for the
+ * vhost's listen socket, which is already prepared. This is intended
+ * for an external process having chosen the fd, which cannot then be
+ * zero.
+ */
+
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility
*
diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c
index 44e7c1ef..6a89ba5a 100644
--- a/lib/roles/http/server/server.c
+++ b/lib/roles/http/server/server.c
@@ -72,6 +72,10 @@ check_extant(struct lws_dll2 *d, void *user)
if (wsi->af != a ->af)
return 0;
+ if (a->info && a->info->vh_listen_sockfd &&
+ wsi->desc.sockfd != a->info->vh_listen_sockfd)
+ return 0;
+
lwsl_notice(" using listen skt from vhost %s\n", wsi->a.vhost->name);
return 1;
@@ -107,7 +111,7 @@ deal:
if (!san--)
return -1;
- if (a->vhost->iface) {
+ if (a->vhost->iface && (!a->info || !a->info->vh_listen_sockfd)) {
/*
* let's check before we do anything else about the disposition
@@ -202,7 +206,10 @@ done_list:
for (m = 0; m < limit; m++) {
- sockfd = lws_fi(&a->vhost->fic, "listenskt") ?
+ if (a->info && a->info->vh_listen_sockfd)
+ sockfd = a->info->vh_listen_sockfd;
+ else
+ sockfd = lws_fi(&a->vhost->fic, "listenskt") ?
LWS_SOCK_INVALID :
socket(a->af, SOCK_STREAM, 0);
@@ -274,28 +281,30 @@ done_list:
#endif
lws_plat_set_socket_options(a->vhost, sockfd, 0);
- is = lws_socket_bind(a->vhost, NULL, sockfd,
- a->vhost->listen_port,
- a->vhost->iface, a->af);
+ if (!a->info || !a->info->vh_listen_sockfd) {
+ is = lws_socket_bind(a->vhost, NULL, sockfd,
+ a->vhost->listen_port,
+ a->vhost->iface, a->af);
- if (is == LWS_ITOSA_BUSY) {
- /* treat as fatal */
- compatible_close(sockfd);
+ if (is == LWS_ITOSA_BUSY) {
+ /* treat as fatal */
+ compatible_close(sockfd);
- return -1;
- }
+ return -1;
+ }
- /*
- * There is a race where the network device may come up and then
- * go away and fail here. So correctly handle unexpected failure
- * here despite we earlier confirmed it.
- */
- if (is < 0) {
- lwsl_info("%s: lws_socket_bind says %d\n", __func__, is);
- compatible_close(sockfd);
- if (a->vhost->iface)
- goto deal;
- return -1;
+ /*
+ * There is a race where the network device may come up and then
+ * go away and fail here. So correctly handle unexpected failure
+ * here despite we earlier confirmed it.
+ */
+ if (is < 0) {
+ lwsl_info("%s: lws_socket_bind says %d\n", __func__, is);
+ compatible_close(sockfd);
+ if (a->vhost->iface)
+ goto deal;
+ return -1;
+ }
}
/*
If / when it works it'd be great to have a little patch on a minimal or the test sever (eg, adding --systemd or whatever) and a procedure to test it with systemd.
from libwebsockets.
Thanks for the quick reply!
If / when it works it'd be great to have a little patch on a minimal or the test sever (eg, adding --systemd or whatever) and a procedure to test it with systemd.
Maybe it is better to make a new example to not pull new dependencies to existing cross-platform examples?
Systemd activation example would pull libsystemd dependency (sd_listen_fds) or at least a getenv/getpid/fcntl calls.
What do you recommend as base for new example? minimal-examples-lowlevel/http-server/minimal-http-server
is OK?
I've made a simple POC and it seems everything works as intended: #3038
$ systemctl --user link $PWD/lws-test.service $PWD/lws-test.socket
Created symlink ~/.config/systemd/user/lws-test.service → .../lws-test.service.
Created symlink ~/.config/systemd/user/lws-test.socket → .../lws-test.socket.
$ systemctl --user start lws-test.socket
$ ss -lptn sport 7681
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 *:7681 *:* users:(("systemd",pid=16734,fd=32))
$ curl http://127.0.0.1:7681/
<meta charset="UTF-8">
<html>
<body>
<img src="libwebsockets.org-logo.svg"><br>
<h1>404</h1>
Sorry, that file doesn't exist.
</body>
</html>
$ ss -lptn sport 7681
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 *:7681 *:* users:(("lws-minimal-htt",pid=434298,fd=3),("systemd",pid=16734,fd=32))
from libwebsockets.
- After a few more tests I have found a small cosmetic issue:
lws_get_vhost_listen_port
returns garbage for adopted listening socket. Probably random port auto-detection fromlws_socket_bind
(getsockname
) can be re-used for adopted listening sockets. - Is
lws_plat_set_socket_options
guaranteed to be called on adopted listening fd's? Systemd config have a bunch of socket options (nodelay, noblocking, etc) but it seems lws sets all needed options on adopted fd.
from libwebsockets.
Yes lws will modify the fd according to what's needed (nonblocking, no nagle etc) as part of the normal flow.
It seems systemd can hand it anything, unix socket, fifo or whatever. It looks like it needs more handling in lws to understand what it is and set info flags. For example here, with ipv6 enabled, it chokes on the fd handed to it, even dup()'d trying to set it for ipv6.
I have prepared a minimal example but instead of binding it to systemd there, it seems it has to be done in lws more completely.
from libwebsockets.
It seems systemd can hand it anything, unix socket, fifo or whatever.
Yeah, systemd can hand something completely unusable for lws (e.g. UDP/unix datagram socket). Probably this should be handled by application itself, but not lws. At the end of the day systemd unit files are out of control of lws.
IMHO only ipv4/ipv6 (and maybe unix-stream) adoptation in lws would be more than sufficient.
from libwebsockets.
I pushed a couple of patches on main that work here.
It auto starts the service OK but once it's running, it doesn't stop until you kill it atm.
from libwebsockets.
(btw lws can handle UDP fine; the async DNS uses it).
from libwebsockets.
(btw lws can handle UDP fine; the async DNS uses it).
This is interesting! (I have thought about HTTP/3 after I wrote "UDP completely unusable").
Well, with "completely unusable" I meant that application can't just throw fd's to lws. It is up to app to decide what is systemd unit files setup and what to do with fd's passed by systemd. For example, what to do if systemd passed multiple fd - should app make two lws vhosts or should it use extra fd for something completely different.
It auto starts the service OK but once it's running, it doesn't stop until you kill it atm.
It is OK for my usecase. From my experience with other socket activated services I can say not all of them support auto-stop.
For example, Docker doesn't stop automatically after it started by socket activation.
Redhat's Podman and Cockpit services auto stops after some idle time. After 1 minute without new requests IIRC.
Thanks for the patches! I'll test them later.
from libwebsockets.
@lws-team, current master branch duplicates adopted listening FD (fd=7). Is it really needed?
With your previous patch there was no FD duplication.
$ ss -lptn sport 7681
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 *:7681 *:*
users:(("lws-minimal-htt",pid=64905,fd=7),("lws-minimal-htt",pid=64905,fd=3),("systemd",pid=45678,fd=38))
UPD: Found that dup
: 3207da0#r137002566
from libwebsockets.
With IPV6 enabled, lws deals with ipv4 + ipv6 by binding separate listen sockets to AF_INET and AF_INET6. It can create the sockets itself scratch normally but with this adoption plan, only one socket is handed to it from outside. So dup is used to solve this.
What problem does that actually create?
from libwebsockets.
No actual problem, thanks for explanation.
One small issue - minimal-http-server-systemd-socketact example doesn't work when activated with unix socket.
It seems port=0
should be added into example or into unix-systemd.c
libwebsockets/lib/plat/unix/unix-systemd.c
Lines 46 to 47 in 3207da0
(For unix sockets FD's also duplicated, but well, no actual problem if it is needed)
$ sudo ss -lpn src unix:/run/test.sock
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
u_str LISTEN 0 4096 /run/test.sock 4833896 * 0
users:(("lws-minimal-htt",pid=1783802,fd=7),("lws-minimal-htt",pid=1783802,fd=3),("systemd",pid=1,fd=47))
from libwebsockets.
I added a patch for the unix domain port thing on main.
from libwebsockets.
Thanks, I think issue can be closed now
from libwebsockets.
Related Issues (20)
- mbedTLS TLS v1.3
- Windows bugs HOT 6
- understanding of event loop, not multi-thread HOT 1
- How to disable HTTP/2 dynamically? HOT 1
- How to enable automatic server WebSocket ping-pong? (formerly ws_ping_pong_interval) HOT 1
- host port mismatches vhost port with CONTEXT_PORT_NO_LISTEN / CONTEXT_PORT_NO_LISTEN_SERVER HOT 5
- How to use lws_cancel_service() with libuv? HOT 13
- You have all of these great secure stream client examples but no tagged release to go with them HOT 1
- Cross-compilation conflict with OpenSSL host development files HOT 12
- Specific commit broke Windows build HOT 6
- ‘is’ may be used uninitialized [-Werror=maybe-uninitialized] HOT 4
- ca_filepath validation on client side HOT 7
- what's the difference between unique protocols and protocols with a terminator? HOT 1
- for arm toolchain HOT 3
- libwebsockets.org is down HOT 1
- Website libwebsockets.org is down, so no examples can be gotten. HOT 3
- libwebsockets.org is down HOT 1
- http server with mount, client POST json file, how to read content?
- Libwebsockets.org is down HOT 3
- Problem about integrating libwebsockets with existing application using socket file descriptor adoption HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from libwebsockets.