xref: /aosp_15_r20/external/libwebsockets/lib/roles/listen/ops-listen.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include <private-lib-core.h>
26 
27 static int
rops_handle_POLLIN_listen(struct lws_context_per_thread * pt,struct lws * wsi,struct lws_pollfd * pollfd)28 rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi,
29 			  struct lws_pollfd *pollfd)
30 {
31 	struct lws_context *context = wsi->a.context;
32 	struct lws_filter_network_conn_args filt;
33 	lws_sock_file_fd_type fd;
34 
35 	memset(&filt, 0, sizeof(filt));
36 
37 	/* if our vhost is going down, ignore it */
38 
39 	if (wsi->a.vhost->being_destroyed)
40 		return LWS_HPI_RET_HANDLED;
41 
42 	/* pollin means a client has connected to us then
43 	 *
44 	 * pollout is a hack on esp32 for background accepts signalling
45 	 * they completed
46 	 */
47 
48 	do {
49 		struct lws *cwsi;
50 		int opts = LWS_ADOPT_SOCKET | LWS_ADOPT_ALLOW_SSL;
51 
52 		if (!(pollfd->revents & (LWS_POLLIN | LWS_POLLOUT)) ||
53 		    !(pollfd->events & LWS_POLLIN))
54 			break;
55 
56 #if defined(LWS_WITH_TLS)
57 		/*
58 		 * can we really accept it, with regards to SSL limit?
59 		 * another vhost may also have had POLLIN on his
60 		 * listener this round and used it up already
61 		 */
62 		if (wsi->a.vhost->tls.use_ssl &&
63 		    context->simultaneous_ssl_restriction &&
64 		    context->simultaneous_ssl ==
65 				  context->simultaneous_ssl_restriction)
66 			/*
67 			 * no... ignore it, he won't come again until
68 			 * we are below the simultaneous_ssl_restriction
69 			 * limit and POLLIN is enabled on him again
70 			 */
71 			break;
72 #endif
73 		/* listen socket got an unencrypted connection... */
74 
75 		filt.clilen = sizeof(filt.cli_addr);
76 
77 		/*
78 		 * We cannot identify the peer who is in the listen
79 		 * socket connect queue before we accept it; even if
80 		 * we could, not accepting it due to PEER_LIMITS would
81 		 * block the connect queue for other legit peers.
82 		 */
83 
84 		filt.accept_fd = accept((int)pollfd->fd,
85 					(struct sockaddr *)&filt.cli_addr,
86 					&filt.clilen);
87 		if (filt.accept_fd == LWS_SOCK_INVALID) {
88 			if (LWS_ERRNO == LWS_EAGAIN ||
89 			    LWS_ERRNO == LWS_EWOULDBLOCK) {
90 				break;
91 			}
92 			lwsl_err("accept: errno %d\n", LWS_ERRNO);
93 
94 			return LWS_HPI_RET_HANDLED;
95 		}
96 
97 		if (context->being_destroyed) {
98 			compatible_close(filt.accept_fd);
99 
100 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
101 		}
102 
103 		lws_plat_set_socket_options(wsi->a.vhost, filt.accept_fd, 0);
104 
105 #if defined(LWS_WITH_IPV6)
106 		lwsl_debug("accepted new conn port %u on fd=%d\n",
107 			((filt.cli_addr.ss_family == AF_INET6) ?
108 			ntohs(((struct sockaddr_in6 *) &filt.cli_addr)->sin6_port) :
109 			ntohs(((struct sockaddr_in *) &filt.cli_addr)->sin_port)),
110 			filt.accept_fd);
111 #else
112 		{
113 		struct sockaddr_in sain;
114 
115 		memcpy(&sain, &filt.cli_addr, sizeof(sain));
116 		lwsl_debug("accepted new conn port %u on fd=%d\n",
117 			   ntohs(sain.sin_port),
118 			   filt.accept_fd);
119 		}
120 #endif
121 
122 		/*
123 		 * look at who we connected to and give user code a
124 		 * chance to reject based on client IP.  There's no
125 		 * protocol selected yet so we issue this to
126 		 * protocols[0]
127 		 */
128 		if ((wsi->a.vhost->protocols[0].callback)(wsi,
129 				LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
130 				(void *)&filt,
131 				(void *)(lws_intptr_t)filt.accept_fd, 0)) {
132 			lwsl_debug("Callback denied net connection\n");
133 			compatible_close(filt.accept_fd);
134 			return LWS_HPI_RET_HANDLED;
135 		}
136 
137 		if (!(wsi->a.vhost->options &
138 			LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG))
139 			opts |= LWS_ADOPT_HTTP;
140 
141 #if defined(LWS_WITH_TLS)
142 		if (!wsi->a.vhost->tls.use_ssl)
143 #endif
144 			opts &= ~LWS_ADOPT_ALLOW_SSL;
145 
146 		fd.sockfd = filt.accept_fd;
147 		cwsi = lws_adopt_descriptor_vhost(wsi->a.vhost, (lws_adoption_type)opts, fd,
148 				wsi->a.vhost->listen_accept_protocol, NULL);
149 		if (!cwsi) {
150 			lwsl_info("%s: vh %s: adopt failed\n", __func__,
151 					wsi->a.vhost->name);
152 
153 			/* already closed cleanly as necessary */
154 			return LWS_HPI_RET_WSI_ALREADY_DIED;
155 		}
156 /*
157 		if (lws_server_socket_service_ssl(cwsi, accept_fd, 1)) {
158 			lws_close_free_wsi(cwsi, LWS_CLOSE_STATUS_NOSTATUS,
159 					   "listen svc fail");
160 			return LWS_HPI_RET_WSI_ALREADY_DIED;
161 		}
162 
163 		lwsl_info("%s: new %s: wsistate 0x%lx, role_ops %s\n",
164 			    __func__, lws_wsi_tag(cwsi), (unsigned long)cwsi->wsistate,
165 			    cwsi->role_ops->name);
166 */
167 
168 	} while (pt->fds_count < context->fd_limit_per_thread - 1 &&
169 		 wsi->position_in_fds_table != LWS_NO_FDS_POS &&
170 		 lws_poll_listen_fd(&pt->fds[wsi->position_in_fds_table]) > 0);
171 
172 	return LWS_HPI_RET_HANDLED;
173 }
174 
rops_handle_POLLOUT_listen(struct lws * wsi)175 int rops_handle_POLLOUT_listen(struct lws *wsi)
176 {
177 	return LWS_HP_RET_USER_SERVICE;
178 }
179 
180 static const lws_rops_t rops_table_listen[] = {
181 	/*  1 */ { .handle_POLLIN	  = rops_handle_POLLIN_listen },
182 	/*  2 */ { .handle_POLLOUT	  = rops_handle_POLLOUT_listen },
183 };
184 
185 const struct lws_role_ops role_ops_listen = {
186 	/* role name */			"listen",
187 	/* alpn id */			NULL,
188 
189 	/* rops_table */		rops_table_listen,
190 	/* rops_idx */			{
191 	  /* LWS_ROPS_check_upgrades */
192 	  /* LWS_ROPS_pt_init_destroy */		0x00,
193 	  /* LWS_ROPS_init_vhost */
194 	  /* LWS_ROPS_destroy_vhost */			0x00,
195 	  /* LWS_ROPS_service_flag_pending */
196 	  /* LWS_ROPS_handle_POLLIN */			0x01,
197 	  /* LWS_ROPS_handle_POLLOUT */
198 	  /* LWS_ROPS_perform_user_POLLOUT */		0x20,
199 	  /* LWS_ROPS_callback_on_writable */
200 	  /* LWS_ROPS_tx_credit */			0x00,
201 	  /* LWS_ROPS_write_role_protocol */
202 	  /* LWS_ROPS_encapsulation_parent */		0x00,
203 	  /* LWS_ROPS_alpn_negotiated */
204 	  /* LWS_ROPS_close_via_role_protocol */	0x00,
205 	  /* LWS_ROPS_close_role */
206 	  /* LWS_ROPS_close_kill_connection */		0x00,
207 	  /* LWS_ROPS_destroy_role */
208 	  /* LWS_ROPS_adoption_bind */			0x00,
209 	  /* LWS_ROPS_client_bind */
210 	  /* LWS_ROPS_issue_keepalive */		0x00,
211 					},
212 
213 	/* adoption_cb clnt, srv */	{ 0, 0 },
214 	/* rx_cb clnt, srv */		{ 0, 0 },
215 	/* writeable cb clnt, srv */	{ 0, 0 },
216 	/* close cb clnt, srv */	{ 0, 0 },
217 	/* protocol_bind_cb c,s */	{ 0, 0 },
218 	/* protocol_unbind_cb c,s */	{ 0, 0 },
219 	/* file_handle */		0,
220 };
221