• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
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 #if !defined(_GNU_SOURCE)
26 #define _GNU_SOURCE
27 #endif
28 #include "private-lib-core.h"
29 
30 struct lws *
wsi_from_fd(const struct lws_context * context,int fd)31 wsi_from_fd(const struct lws_context *context, int fd)
32 {
33 	struct lws **p, **done;
34 
35 	if (!context->max_fds_unrelated_to_ulimit)
36 		return context->lws_lookup[fd - lws_plat_socket_offset()];
37 
38 	/* slow fds handling */
39 
40 	p = context->lws_lookup;
41 	done = &p[context->max_fds];
42 
43 	while (p != done) {
44 		if (*p && (*p)->desc.sockfd == fd)
45 			return *p;
46 		p++;
47 	}
48 
49 	return NULL;
50 }
51 
52 #if defined(_DEBUG)
53 int
sanity_assert_no_wsi_traces(const struct lws_context * context,struct lws * wsi)54 sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi)
55 {
56 	struct lws **p, **done;
57 
58 	if (!context->max_fds_unrelated_to_ulimit)
59 		/* can't tell */
60 		return 0;
61 
62 	/* slow fds handling */
63 
64 	p = context->lws_lookup;
65 	done = &p[context->max_fds];
66 
67 	/* confirm the wsi doesn't already exist */
68 
69 	while (p != done && *p != wsi)
70 		p++;
71 
72 	if (p == done)
73 		return 0;
74 
75 	assert(0); /* this wsi is still mentioned inside lws */
76 
77 	return 1;
78 }
79 
80 int
sanity_assert_no_sockfd_traces(const struct lws_context * context,lws_sockfd_type sfd)81 sanity_assert_no_sockfd_traces(const struct lws_context *context,
82 			       lws_sockfd_type sfd)
83 {
84 #if LWS_MAX_SMP > 1
85 	/*
86 	 * We can't really do this test... another thread can accept and
87 	 * reuse the closed fd
88 	 */
89 	return 0;
90 #else
91 	struct lws **p, **done;
92 
93 	if (sfd == LWS_SOCK_INVALID || !context->lws_lookup)
94 		return 0;
95 
96 	if (!context->max_fds_unrelated_to_ulimit &&
97 	    context->lws_lookup[sfd - lws_plat_socket_offset()]) {
98 		assert(0); /* the fd is still in use */
99 		return 1;
100 	}
101 
102 	/* slow fds handling */
103 
104 	p = context->lws_lookup;
105 	done = &p[context->max_fds];
106 
107 	/* confirm the sfd not already in use */
108 
109 	while (p != done && (!*p || (*p)->desc.sockfd != sfd))
110 		p++;
111 
112 	if (p == done)
113 		return 0;
114 
115 	assert(0); /* this fd is still in the tables */
116 
117 	return 1;
118 #endif
119 }
120 #endif
121 
122 
123 int
insert_wsi(const struct lws_context * context,struct lws * wsi)124 insert_wsi(const struct lws_context *context, struct lws *wsi)
125 {
126 	struct lws **p, **done;
127 
128 	if (sanity_assert_no_wsi_traces(context, wsi))
129 		return 0;
130 
131 	if (!context->max_fds_unrelated_to_ulimit) {
132 		assert(context->lws_lookup[wsi->desc.sockfd -
133 		                           lws_plat_socket_offset()] == 0);
134 
135 		context->lws_lookup[wsi->desc.sockfd - \
136 				  lws_plat_socket_offset()] = wsi;
137 
138 		return 0;
139 	}
140 
141 	/* slow fds handling */
142 
143 	p = context->lws_lookup;
144 	done = &p[context->max_fds];
145 
146 	/* confirm fd isn't already in use by a wsi */
147 
148 	if (sanity_assert_no_sockfd_traces(context, wsi->desc.sockfd))
149 		return 0;
150 
151 	p = context->lws_lookup;
152 
153 	/* find an empty slot */
154 
155 	while (p != done && *p)
156 		p++;
157 
158 	if (p == done) {
159 		lwsl_err("%s: reached max fds\n", __func__);
160 		return 1;
161 	}
162 
163 	*p = wsi;
164 
165 	return 0;
166 }
167 
168 
169 
170 void
delete_from_fd(const struct lws_context * context,int fd)171 delete_from_fd(const struct lws_context *context, int fd)
172 {
173 
174 	struct lws **p, **done;
175 
176 	if (!context->max_fds_unrelated_to_ulimit) {
177 		if (context->lws_lookup)
178 			context->lws_lookup[fd - lws_plat_socket_offset()] = NULL;
179 
180 		return;
181 	}
182 
183 	/* slow fds handling */
184 
185 	p = context->lws_lookup;
186 	assert(p);
187 
188 	done = &p[context->max_fds];
189 
190 	/* find the match */
191 
192 	while (p != done && (!*p || (*p)->desc.sockfd != fd))
193 		p++;
194 
195 	if (p != done)
196 		*p = NULL;
197 
198 #if defined(_DEBUG)
199 	p = context->lws_lookup;
200 	while (p != done && (!*p || (*p)->desc.sockfd != fd))
201 		p++;
202 
203 	if (p != done) {
204 		lwsl_err("%s: fd %d in lws_lookup again at %d\n", __func__,
205 				fd, (int)(p - context->lws_lookup));
206 		assert(0);
207 	}
208 #endif
209 }
210 
211 void
delete_from_fdwsi(const struct lws_context * context,struct lws * wsi)212 delete_from_fdwsi(const struct lws_context *context, struct lws *wsi)
213 {
214 
215 	struct lws **p, **done;
216 
217 	if (!context->max_fds_unrelated_to_ulimit)
218 		return;
219 
220 
221 	/* slow fds handling */
222 
223 	p = context->lws_lookup;
224 	done = &p[context->max_fds];
225 
226 	/* find the match */
227 
228 	while (p != done && (!*p || (*p) != wsi))
229 		p++;
230 
231 	if (p != done)
232 		*p = NULL;
233 }
234 
235 void
lws_plat_insert_socket_into_fds(struct lws_context * context,struct lws * wsi)236 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
237 {
238 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
239 
240 	if (context->event_loop_ops->io)
241 		context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ);
242 
243 	pt->fds[pt->fds_count++].revents = 0;
244 }
245 
246 void
lws_plat_delete_socket_from_fds(struct lws_context * context,struct lws * wsi,int m)247 lws_plat_delete_socket_from_fds(struct lws_context *context,
248 						struct lws *wsi, int m)
249 {
250 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
251 
252 	if (context->event_loop_ops->io)
253 		context->event_loop_ops->io(wsi,
254 				LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
255 
256 	pt->fds_count--;
257 }
258 
259 int
lws_plat_change_pollfd(struct lws_context * context,struct lws * wsi,struct lws_pollfd * pfd)260 lws_plat_change_pollfd(struct lws_context *context,
261 		      struct lws *wsi, struct lws_pollfd *pfd)
262 {
263 	return 0;
264 }
265