Merge lp:~roger.light/ubuntu/vivid/libwebsockets/fix-for-1422623 into lp:ubuntu/vivid/libwebsockets

Proposed by Roger Light
Status: Needs review
Proposed branch: lp:~roger.light/ubuntu/vivid/libwebsockets/fix-for-1422623
Merge into: lp:ubuntu/vivid/libwebsockets
Diff against target: 34926 lines (+9057/-22437)
103 files modified
.gitignore (+0/-1)
.pc/0001-getnameinfo.patch/lib/libwebsockets.c (+0/-2283)
.pc/0002-keepalive.patch/lib/libwebsockets.c (+0/-2251)
.pc/01-visibility.patch/lib/Makefile.am (+0/-89)
.pc/01-visibility.patch/lib/base64-decode.c (+0/-189)
.pc/01-visibility.patch/lib/client-handshake.c (+0/-329)
.pc/01-visibility.patch/lib/daemonize.c (+0/-220)
.pc/01-visibility.patch/lib/extension.c (+0/-33)
.pc/01-visibility.patch/lib/handshake.c (+0/-286)
.pc/01-visibility.patch/lib/libwebsockets.c (+0/-2251)
.pc/01-visibility.patch/lib/libwebsockets.h (+0/-972)
.pc/01-visibility.patch/lib/output.c (+0/-580)
.pc/01-visibility.patch/lib/parsers.c (+0/-1162)
.pc/01-visibility.patch/scripts/kernel-doc (+0/-2238)
.pc/applied-patches (+0/-3)
Android.mk (+29/-0)
CMakeLists.txt (+606/-236)
COPYING (+0/-503)
INSTALL (+0/-365)
Makefile.am (+0/-13)
README.build (+103/-313)
README.coding (+77/-0)
autogen.sh (+0/-1578)
changelog (+258/-0)
cmake/FindGit.cmake (+163/-0)
cmake/FindOpenSSLbins.cmake (+12/-3)
cmake/LibwebsocketsConfig.cmake.in (+17/-0)
cmake/LibwebsocketsConfigVersion.cmake.in (+11/-0)
cmake/UseRPMTools.cmake (+176/-0)
config.h.cmake (+22/-21)
configure.ac (+0/-226)
cross-arm-linux-gnueabihf.cmake (+28/-0)
cross-ming.cmake (+31/-0)
cross-openwrt-makefile (+91/-0)
debian/changelog (+11/-0)
debian/control (+21/-8)
debian/copyright (+0/-29)
debian/libwebsockets-dev.doc-base (+0/-3)
debian/libwebsockets-dev.docs (+0/-1)
debian/libwebsockets-test-server-data.install (+1/-0)
debian/libwebsockets-test-server.install (+0/-1)
debian/libwebsockets4.lintian-overrides (+1/-1)
debian/libwebsockets4.symbols (+71/-37)
debian/patches/0001-getnameinfo.patch (+0/-57)
debian/patches/0002-keepalive.patch (+0/-33)
debian/patches/01-visibility.patch (+0/-610)
debian/patches/cmake.patch (+22/-0)
debian/patches/series (+2/-3)
debian/patches/soversion.patch (+14/-0)
debian/rules (+4/-2)
lib/Makefile.am (+0/-89)
lib/base64-decode.c (+0/-96)
lib/client-handshake.c (+213/-99)
lib/client-parser.c (+32/-45)
lib/client.c (+199/-94)
lib/context.c (+341/-0)
lib/extension-deflate-frame.c (+1/-1)
lib/extension.c (+178/-0)
lib/getifaddrs.h (+2/-2)
lib/handshake.c (+76/-191)
lib/lextable.h (+338/-0)
lib/libev.c (+175/-0)
lib/libwebsockets.c (+309/-1799)
lib/libwebsockets.h (+277/-51)
lib/lws-plat-unix.c (+404/-0)
lib/lws-plat-win.c (+358/-0)
lib/minilex.c (+206/-330)
lib/output.c (+254/-263)
lib/parsers.c (+298/-452)
lib/pollfd.c (+239/-0)
lib/private-libwebsockets.h (+473/-96)
lib/server-handshake.c (+144/-139)
lib/server.c (+718/-219)
lib/service.c (+517/-0)
lib/sha-1.c (+8/-34)
lib/ssl-http2.c (+78/-0)
lib/ssl.c (+571/-0)
libwebsockets-api-doc.html (+145/-104)
libwebsockets.pc.in (+0/-11)
libwebsockets.spec (+7/-7)
m4/ignore-me (+0/-2)
scripts/FindLibWebSockets.cmake (+33/-0)
test-server/Makefile.am (+0/-131)
test-server/attack.sh (+90/-21)
test-server/test-client.c (+60/-27)
test-server/test-echo.c (+36/-10)
test-server/test-fraggle.c (+20/-5)
test-server/test-ping.c (+17/-8)
test-server/test-server.c (+389/-124)
test-server/test.html (+6/-3)
win32port/client/client.vcxproj (+0/-259)
win32port/client/client.vcxproj.filters (+0/-39)
win32port/libwebsocketswin32/libwebsocketswin32.vcxproj.filters (+0/-93)
win32port/server/server.vcxproj (+0/-276)
win32port/server/server.vcxproj.filters (+0/-51)
win32port/win32helpers/gettimeofday.c (+41/-37)
win32port/win32helpers/gettimeofday.h (+31/-28)
win32port/win32helpers/netdb.h (+0/-1)
win32port/win32helpers/sys/time.h (+0/-1)
win32port/win32helpers/websock-w32.c (+0/-104)
win32port/win32helpers/websock-w32.h (+0/-64)
win32port/win32port.sln (+0/-100)
win32port/zlib/gzio.c (+2/-1)
To merge this branch: bzr merge lp:~roger.light/ubuntu/vivid/libwebsockets/fix-for-1422623
Reviewer Review Type Date Requested Status
Daniel Holbach (community) Needs Fixing
Review via email: mp+249969@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Daniel Holbach (dholbach) wrote :

Contents conflict in lib/Makefile.am
Text conflict in lib/base64-decode.c
Text conflict in lib/extension.c
Text conflict in lib/libwebsockets.c
Text conflict in lib/libwebsockets.h
Text conflict in lib/output.c

review: Needs Fixing
3. By Roger Light

New upstream release 1.3.

4. By Roger Light

* New upstream release, including SO version bump. (LP: #1422623)
* Build changed to cmake.
* New binary package libwebsockets-test-server-data to hold large
  architecture independent data for libwebsockets-test-server.
* Bump standards version to 3.9.5, no changes needed.

Revision history for this message
Roger Light (roger.light) wrote :

Sorry, I must have made a commit without unapplying the quilt patches. I have redone the upstream merge, and overwritten the branch.

Revision history for this message
Daniel Holbach (dholbach) wrote :
Download full text (3.8 KiB)

I'm still seeing this issue. Maybe you can try to run these steps locally as well?

daniel@daydream:~$ bzr branch lp:ubuntu/libwebsockets
Most recent Ubuntu version: 1.2.2-1
Packaging branch status: CURRENT
Branched 2 revisions.
daniel@daydream:~$ cd libwebsockets/
daniel@daydream:~/libwebsockets$ bzr merge lp:~roger.light/ubuntu/vivid/libwebsockets/fix-for-1422623
Unapplying quilt patches to prevent spurious conflicts
+N Android.mk
+N cmake/FindGit.cmake
+N cmake/LibwebsocketsConfig.cmake.in
+N cmake/LibwebsocketsConfigVersion.cmake.in
+N cmake/UseRPMTools.cmake
+N cross-arm-linux-gnueabihf.cmake
+N cross-ming.cmake
+N cross-openwrt-makefile
+N debian/libwebsockets-test-server-data.install
+N debian/patches/cmake.patch
+N debian/patches/soversion.patch
+N lib/context.c
+N lib/lextable.h
+N lib/libev.c
+N lib/lws-plat-unix.c
+N lib/lws-plat-win.c
+N lib/pollfd.c
+N lib/service.c
+N lib/ssl-http2.c
+N lib/ssl.c
+N scripts/FindLibWebSockets.cmake
+N test-server/leaf.jpg
 M .gitignore
 M CMakeLists.txt
-D COPYING
-D INSTALL
-D Makefile.am
 M README.build
 M README.coding
-D autogen.sh
 M changelog
 M cmake/FindOpenSSLbins.cmake
 M config.h.cmake
-D configure.ac
 M debian/changelog
 M debian/control
 M debian/copyright
 M debian/libwebsockets-dev.doc-base
 M debian/libwebsockets-dev.docs
 M debian/libwebsockets-test-server.install
R debian/libwebsockets3.install => debian/libwebsockets4.install
RM debian/libwebsockets3.lintian-overrides => debian/libwebsockets4.lintian-overrides
RM debian/libwebsockets3.symbols => debian/libwebsockets4.symbols
-D debian/patches/0001-getnameinfo.patch
-D debian/patches/0002-keepalive.patch
-D debian/patches/01-visibility.patch
 M debian/patches/series
 M debian/rules
RM lib/Makefile.am => lib/Makefile.am.THIS
 M lib/base64-decode.c
 M lib/client-handshake.c
 M lib/client-parser.c
 M* lib/client.c
 M lib/extension-deflate-frame.c
 M lib/extension.c
 M lib/getifaddrs.h
 M lib/handshake.c
 M lib/libwebsockets.c
 M lib/libwebsockets.h
 M lib/minilex.c
 M lib/output.c
 M lib/parsers.c
 M* lib/private-libwebsockets.h
 M lib/server-handshake.c
 M lib/server.c
 M lib/sha-1.c
 M libwebsockets-api-doc.html
-D libwebsockets.pc.in
 M libwebsockets.spec
-D m4/
-D m4/ignore-me
-D test-server/Makefile.am
 M test-server/attack.sh
 M test-server/test-client.c
 M test-server/test-echo.c
 M test-server/test-fraggle.c
 M test-server/test-ping.c
 M test-server/test-server.c
 M test-server/test.html
-D win32port/client/
-D win32port/client/client.vcxproj
-D win32port/client/client.vcxproj.filters
-D win32port/libwebsocketswin32/
-D win32port/libwebsocketswin32/libwebsocketswin32.vcxproj.filters
-D win32port/server/
-D win32port/server/server.vcxproj
-D win32port/server/server.vcxproj.filters
 M win32port/win32helpers/gettimeofday.c
 M win32port/win32helpers/gettime...

Read more...

review: Needs Fixing
Revision history for this message
Roger Light (roger.light) wrote :

> I'm still seeing this issue. Maybe you can try to run these steps locally as
> well?

Will do, thanks for the pointer on what I need to do.

Revision history for this message
Roger Light (roger.light) wrote :

> I'm still seeing this issue. Maybe you can try to run these steps locally as
> well?

I see the same thing, but nothing I've tried has been able to remove the conflicts. The file conflicts are only those files that have quilt patches. The patches are applied in the bzr repo. I have tried removing the patches, committing and then carrying out merge-upstream. That doesn't work. I've tried merge-upstream with the patches applied, that doesn't work. I've tried removing the contents of the .pc directory, so quilt doesn't think the patches are applied. This means when I run merge-upstream I need to resolve conflicts immediately. Having done that, I still get text conflicts when I try to merge back to the clean branch (no surprise really). I've tried to manually apply the updated upstream source, which works ok but then when I try to merge back bzr tells me the tree transform is malformed.

I think it's out of time now, thanks for looking anyway.

Unmerged revisions

4. By Roger Light

* New upstream release, including SO version bump. (LP: #1422623)
* Build changed to cmake.
* New binary package libwebsockets-test-server-data to hold large
  architecture independent data for libwebsockets-test-server.
* Bump standards version to 3.9.5, no changes needed.

3. By Roger Light

New upstream release 1.3.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.gitignore'
--- .gitignore 2013-03-28 19:10:28 +0000
+++ .gitignore 2015-02-19 16:44:02 +0000
@@ -29,7 +29,6 @@
29configure29configure
30compile30compile
31config.guess31config.guess
32*.in
33*~32*~
34*.orig33*.orig
35autom4te.cache/34autom4te.cache/
3635
=== removed directory '.pc/0001-getnameinfo.patch'
=== removed directory '.pc/0001-getnameinfo.patch/lib'
=== removed file '.pc/0001-getnameinfo.patch/lib/libwebsockets.c'
--- .pc/0001-getnameinfo.patch/lib/libwebsockets.c 2013-03-28 19:10:28 +0000
+++ .pc/0001-getnameinfo.patch/lib/libwebsockets.c 1970-01-01 00:00:00 +0000
@@ -1,2283 +0,0 @@
1/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 Andy Green <andy@warmcat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22#include "private-libwebsockets.h"
23
24#ifdef WIN32
25#include <tchar.h>
26#include <io.h>
27#include <mstcpip.h>
28#else
29#ifdef LWS_BUILTIN_GETIFADDRS
30#include <getifaddrs.h>
31#else
32#include <ifaddrs.h>
33#endif
34#include <syslog.h>
35#include <sys/un.h>
36#include <sys/socket.h>
37#include <netdb.h>
38#endif
39
40#ifdef LWS_OPENSSL_SUPPORT
41int openssl_websocket_private_data_index;
42#endif
43
44#ifdef __MINGW32__
45#include "../win32port/win32helpers/websock-w32.c"
46#else
47#ifdef __MINGW64__
48#include "../win32port/win32helpers/websock-w32.c"
49#endif
50#endif
51
52#ifndef LWS_BUILD_HASH
53#define LWS_BUILD_HASH "unknown-build-hash"
54#endif
55
56static int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
57static void lwsl_emit_stderr(int level, const char *line);
58static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
59
60static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
61
62static const char * const log_level_names[] = {
63 "ERR",
64 "WARN",
65 "NOTICE",
66 "INFO",
67 "DEBUG",
68 "PARSER",
69 "HEADER",
70 "EXTENSION",
71 "CLIENT",
72 "LATENCY",
73};
74
75#ifndef LWS_NO_CLIENT
76 extern int lws_client_socket_service(
77 struct libwebsocket_context *context,
78 struct libwebsocket *wsi, struct pollfd *pollfd);
79#endif
80#ifndef LWS_NO_SERVER
81 extern int lws_server_socket_service(
82 struct libwebsocket_context *context,
83 struct libwebsocket *wsi, struct pollfd *pollfd);
84#endif
85
86/**
87 * lws_get_library_version: get version and git hash library built from
88 *
89 * returns a const char * to a string like "1.1 178d78c"
90 * representing the library version followed by the git head hash it
91 * was built from
92 */
93
94const char *
95lws_get_library_version(void)
96{
97 return library_version;
98}
99
100int
101insert_wsi_socket_into_fds(struct libwebsocket_context *context,
102 struct libwebsocket *wsi)
103{
104 if (context->fds_count >= context->max_fds) {
105 lwsl_err("Too many fds (%d)\n", context->max_fds);
106 return 1;
107 }
108
109 if (wsi->sock > context->max_fds) {
110 lwsl_err("Socket fd %d is too high (%d)\n",
111 wsi->sock, context->max_fds);
112 return 1;
113 }
114
115 assert(wsi);
116 assert(wsi->sock);
117
118 lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
119 wsi, wsi->sock, context->fds_count);
120
121 context->lws_lookup[wsi->sock] = wsi;
122 wsi->position_in_fds_table = context->fds_count;
123 context->fds[context->fds_count].fd = wsi->sock;
124 context->fds[context->fds_count].events = POLLIN;
125 context->fds[context->fds_count++].revents = 0;
126
127 /* external POLL support via protocol 0 */
128 context->protocols[0].callback(context, wsi,
129 LWS_CALLBACK_ADD_POLL_FD,
130 (void *)(long)wsi->sock, NULL, POLLIN);
131
132 return 0;
133}
134
135static int
136remove_wsi_socket_from_fds(struct libwebsocket_context *context,
137 struct libwebsocket *wsi)
138{
139 int m;
140
141 if (!--context->fds_count)
142 goto do_ext;
143
144 if (wsi->sock > context->max_fds) {
145 lwsl_err("Socket fd %d too high (%d)\n",
146 wsi->sock, context->max_fds);
147 return 1;
148 }
149
150 lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n",
151 wsi, wsi->sock, wsi->position_in_fds_table);
152
153 m = wsi->position_in_fds_table; /* replace the contents for this */
154
155 /* have the last guy take up the vacant slot */
156 context->fds[m] = context->fds[context->fds_count];
157 /*
158 * end guy's fds_lookup entry remains unchanged
159 * (still same fd pointing to same wsi)
160 */
161 /* end guy's "position in fds table" changed */
162 context->lws_lookup[context->fds[context->fds_count].fd]->
163 position_in_fds_table = m;
164 /* deletion guy's lws_lookup entry needs nuking */
165 context->lws_lookup[wsi->sock] = NULL;
166 /* removed wsi has no position any more */
167 wsi->position_in_fds_table = -1;
168
169do_ext:
170 /* remove also from external POLL support via protocol 0 */
171 if (wsi->sock)
172 context->protocols[0].callback(context, wsi,
173 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
174
175 return 0;
176}
177
178
179void
180libwebsocket_close_and_free_session(struct libwebsocket_context *context,
181 struct libwebsocket *wsi, enum lws_close_status reason)
182{
183 int n;
184 int old_state;
185 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
186 LWS_SEND_BUFFER_POST_PADDING];
187#ifndef LWS_NO_EXTENSIONS
188 int ret;
189 int m;
190 struct lws_tokens eff_buf;
191 struct libwebsocket_extension *ext;
192#endif
193
194 if (!wsi)
195 return;
196
197 old_state = wsi->state;
198
199 if (old_state == WSI_STATE_DEAD_SOCKET)
200 return;
201
202 wsi->u.ws.close_reason = reason;
203
204 if (wsi->mode == LWS_CONNMODE_HTTP_SERVING && wsi->u.http.fd) {
205 close(wsi->u.http.fd);
206 wsi->u.http.fd = 0;
207 }
208
209#ifndef LWS_NO_EXTENSIONS
210 /*
211 * are his extensions okay with him closing? Eg he might be a mux
212 * parent and just his ch1 aspect is closing?
213 */
214
215 for (n = 0; n < wsi->count_active_extensions; n++) {
216 if (!wsi->active_extensions[n]->callback)
217 continue;
218
219 m = wsi->active_extensions[n]->callback(context,
220 wsi->active_extensions[n], wsi,
221 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
222 wsi->active_extensions_user[n], NULL, 0);
223
224 /*
225 * if somebody vetoed actually closing him at this time....
226 * up to the extension to track the attempted close, let's
227 * just bail
228 */
229
230 if (m) {
231 lwsl_ext("extension vetoed close\n");
232 return;
233 }
234 }
235
236 /*
237 * flush any tx pending from extensions, since we may send close packet
238 * if there are problems with send, just nuke the connection
239 */
240
241 ret = 1;
242 while (ret == 1) {
243
244 /* default to nobody has more to spill */
245
246 ret = 0;
247 eff_buf.token = NULL;
248 eff_buf.token_len = 0;
249
250 /* show every extension the new incoming data */
251
252 for (n = 0; n < wsi->count_active_extensions; n++) {
253 m = wsi->active_extensions[n]->callback(
254 wsi->protocol->owning_server,
255 wsi->active_extensions[n], wsi,
256 LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
257 wsi->active_extensions_user[n], &eff_buf, 0);
258 if (m < 0) {
259 lwsl_ext("Extension reports fatal error\n");
260 goto just_kill_connection;
261 }
262 if (m)
263 /*
264 * at least one extension told us he has more
265 * to spill, so we will go around again after
266 */
267 ret = 1;
268 }
269
270 /* assuming they left us something to send, send it */
271
272 if (eff_buf.token_len)
273 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
274 eff_buf.token_len)) {
275 lwsl_debug("close: ext spill failed\n");
276 goto just_kill_connection;
277 }
278 }
279#endif
280
281 /*
282 * signal we are closing, libsocket_write will
283 * add any necessary version-specific stuff. If the write fails,
284 * no worries we are closing anyway. If we didn't initiate this
285 * close, then our state has been changed to
286 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
287 *
288 * Likewise if it's a second call to close this connection after we
289 * sent the close indication to the peer already, we are in state
290 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
291 */
292
293 if (old_state == WSI_STATE_ESTABLISHED &&
294 reason != LWS_CLOSE_STATUS_NOSTATUS) {
295
296 lwsl_debug("sending close indication...\n");
297
298 /* make valgrind happy */
299 memset(buf, 0, sizeof(buf));
300 n = libwebsocket_write(wsi,
301 &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
302 0, LWS_WRITE_CLOSE);
303 if (!n) {
304 /*
305 * we have sent a nice protocol level indication we
306 * now wish to close, we should not send anything more
307 */
308
309 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
310
311 /*
312 * ...and we should wait for a reply for a bit
313 * out of politeness
314 */
315
316 libwebsocket_set_timeout(wsi,
317 PENDING_TIMEOUT_CLOSE_ACK, 1);
318
319 lwsl_debug("sent close indication, awaiting ack\n");
320
321 return;
322 }
323
324 lwsl_info("close: sending close packet failed, hanging up\n");
325
326 /* else, the send failed and we should just hang up */
327 }
328
329#ifndef LWS_NO_EXTENSIONS
330just_kill_connection:
331#endif
332
333 lwsl_debug("close: just_kill_connection\n");
334
335 /*
336 * we won't be servicing or receiving anything further from this guy
337 * delete socket from the internal poll list if still present
338 */
339
340 remove_wsi_socket_from_fds(context, wsi);
341
342 wsi->state = WSI_STATE_DEAD_SOCKET;
343
344 if ((old_state == WSI_STATE_ESTABLISHED ||
345 wsi->mode == LWS_CONNMODE_WS_SERVING ||
346 wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
347
348 if (wsi->u.ws.rx_user_buffer) {
349 free(wsi->u.ws.rx_user_buffer);
350 wsi->u.ws.rx_user_buffer = NULL;
351 }
352 if (wsi->u.ws.rxflow_buffer) {
353 free(wsi->u.ws.rxflow_buffer);
354 wsi->u.ws.rxflow_buffer = NULL;
355 }
356 }
357
358 /* tell the user it's all over for this guy */
359
360 if (wsi->protocol && wsi->protocol->callback &&
361 ((old_state == WSI_STATE_ESTABLISHED) ||
362 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
363 (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
364 lwsl_debug("calling back CLOSED\n");
365 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
366 wsi->user_space, NULL, 0);
367 } else
368 lwsl_debug("not calling back closed\n");
369
370#ifndef LWS_NO_EXTENSIONS
371 /* deallocate any active extension contexts */
372
373 for (n = 0; n < wsi->count_active_extensions; n++) {
374 if (!wsi->active_extensions[n]->callback)
375 continue;
376
377 wsi->active_extensions[n]->callback(context,
378 wsi->active_extensions[n], wsi,
379 LWS_EXT_CALLBACK_DESTROY,
380 wsi->active_extensions_user[n], NULL, 0);
381
382 free(wsi->active_extensions_user[n]);
383 }
384
385 /*
386 * inform all extensions in case they tracked this guy out of band
387 * even though not active on him specifically
388 */
389
390 ext = context->extensions;
391 while (ext && ext->callback) {
392 ext->callback(context, ext, wsi,
393 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
394 NULL, NULL, 0);
395 ext++;
396 }
397#endif
398
399/* lwsl_info("closing fd=%d\n", wsi->sock); */
400
401#ifdef LWS_OPENSSL_SUPPORT
402 if (wsi->ssl) {
403 n = SSL_get_fd(wsi->ssl);
404 SSL_shutdown(wsi->ssl);
405 compatible_close(n);
406 SSL_free(wsi->ssl);
407 } else {
408#endif
409 if (wsi->sock) {
410 n = shutdown(wsi->sock, SHUT_RDWR);
411 if (n)
412 lwsl_debug("closing: shutdown returned %d\n",
413 errno);
414
415 n = compatible_close(wsi->sock);
416 if (n)
417 lwsl_debug("closing: close returned %d\n",
418 errno);
419 }
420#ifdef LWS_OPENSSL_SUPPORT
421 }
422#endif
423 if (wsi->protocol && wsi->protocol->per_session_data_size &&
424 wsi->user_space) /* user code may own */
425 free(wsi->user_space);
426
427 free(wsi);
428}
429
430/**
431 * libwebsockets_get_peer_addresses() - Get client address information
432 * @context: Libwebsockets context
433 * @wsi: Local struct libwebsocket associated with
434 * @fd: Connection socket descriptor
435 * @name: Buffer to take client address name
436 * @name_len: Length of client address name buffer
437 * @rip: Buffer to take client address IP qotted quad
438 * @rip_len: Length of client address IP buffer
439 *
440 * This function fills in @name and @rip with the name and IP of
441 * the client connected with socket descriptor @fd. Names may be
442 * truncated if there is not enough room. If either cannot be
443 * determined, they will be returned as valid zero-length strings.
444 */
445
446void
447libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
448 struct libwebsocket *wsi, int fd, char *name, int name_len,
449 char *rip, int rip_len)
450{
451 unsigned int len;
452 struct sockaddr_in sin;
453 struct hostent *host;
454 struct hostent *host1;
455 char ip[128];
456 unsigned char *p;
457 int n;
458 int ret = -1;
459#ifdef AF_LOCAL
460 struct sockaddr_un *un;
461#endif
462
463 rip[0] = '\0';
464 name[0] = '\0';
465
466 lws_latency_pre(context, wsi);
467
468 len = sizeof(sin);
469 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
470 perror("getpeername");
471 goto bail;
472 }
473
474 host = gethostbyaddr((char *) &sin.sin_addr, sizeof(sin.sin_addr),
475 AF_INET);
476 if (host == NULL) {
477 perror("gethostbyaddr");
478 goto bail;
479 }
480
481 strncpy(name, host->h_name, name_len);
482 name[name_len - 1] = '\0';
483
484 host1 = gethostbyname(host->h_name);
485 if (host1 == NULL)
486 goto bail;
487 p = (unsigned char *)host1;
488 n = 0;
489 while (p != NULL) {
490 p = (unsigned char *)host1->h_addr_list[n++];
491 if (p == NULL)
492 continue;
493 if ((host1->h_addrtype != AF_INET)
494#ifdef AF_LOCAL
495 && (host1->h_addrtype != AF_LOCAL)
496#endif
497 )
498 continue;
499
500 if (host1->h_addrtype == AF_INET)
501 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
502#ifdef AF_LOCAL
503 else {
504 un = (struct sockaddr_un *)p;
505 strncpy(ip, un->sun_path, sizeof(ip) - 1);
506 ip[sizeof(ip) - 1] = '\0';
507 }
508#endif
509 p = NULL;
510 strncpy(rip, ip, rip_len);
511 rip[rip_len - 1] = '\0';
512 }
513
514 ret = 0;
515bail:
516 lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
517}
518
519int libwebsockets_get_random(struct libwebsocket_context *context,
520 void *buf, int len)
521{
522 int n;
523 char *p = (char *)buf;
524
525#ifdef WIN32
526 for (n = 0; n < len; n++)
527 p[n] = (unsigned char)rand();
528#else
529 n = read(context->fd_random, p, len);
530#endif
531
532 return n;
533}
534
535int lws_set_socket_options(struct libwebsocket_context *context, int fd)
536{
537 int optval = 1;
538 socklen_t optlen = sizeof(optval);
539#ifdef WIN32
540 unsigned long optl = 0;
541#endif
542#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
543 struct protoent *tcp_proto;
544#endif
545
546 if (context->ka_time) {
547 /* enable keepalive on this socket */
548 optval = 1;
549 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
550 (const void *)&optval, optlen) < 0)
551 return 1;
552
553#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
554
555 /*
556 * didn't find a way to set these per-socket, need to
557 * tune kernel systemwide values
558 */
559#elif WIN32
560 {
561 DWORD dwBytesRet;
562 struct tcp_keepalive alive;
563 alive.onoff = TRUE;
564 alive.keepalivetime = context->ka_time;
565 alive.keepaliveinterval = context->ka_interval;
566
567 if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
568 NULL, 0, &dwBytesRet, NULL, NULL))
569 return 1;
570 }
571#else
572 /* set the keepalive conditions we want on it too */
573 optval = context->ka_time;
574 if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE,
575 (const void *)&optval, optlen) < 0)
576 return 1;
577
578 optval = context->ka_probes;
579 if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL,
580 (const void *)&optval, optlen) < 0)
581 return 1;
582
583 optval = context->ka_interval;
584 if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT,
585 (const void *)&optval, optlen) < 0)
586 return 1;
587#endif
588 }
589
590 /* Disable Nagle */
591 optval = 1;
592#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
593 setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
594#else
595 tcp_proto = getprotobyname("TCP");
596 setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen);
597#endif
598
599 /* We are nonblocking... */
600#ifdef WIN32
601 ioctlsocket(fd, FIONBIO, &optl);
602#else
603 fcntl(fd, F_SETFL, O_NONBLOCK);
604#endif
605
606 return 0;
607}
608
609int lws_send_pipe_choked(struct libwebsocket *wsi)
610{
611 struct pollfd fds;
612
613 fds.fd = wsi->sock;
614 fds.events = POLLOUT;
615 fds.revents = 0;
616
617 if (poll(&fds, 1, 0) != 1)
618 return 1;
619
620 if ((fds.revents & POLLOUT) == 0)
621 return 1;
622
623 /* okay to send another packet without blocking */
624
625 return 0;
626}
627
628int
629lws_handle_POLLOUT_event(struct libwebsocket_context *context,
630 struct libwebsocket *wsi, struct pollfd *pollfd)
631{
632 int n;
633
634#ifndef LWS_NO_EXTENSIONS
635 struct lws_tokens eff_buf;
636 int ret;
637 int m;
638 int handled = 0;
639
640 for (n = 0; n < wsi->count_active_extensions; n++) {
641 if (!wsi->active_extensions[n]->callback)
642 continue;
643
644 m = wsi->active_extensions[n]->callback(context,
645 wsi->active_extensions[n], wsi,
646 LWS_EXT_CALLBACK_IS_WRITEABLE,
647 wsi->active_extensions_user[n], NULL, 0);
648 if (m > handled)
649 handled = m;
650 }
651
652 if (handled == 1)
653 goto notify_action;
654
655 if (!wsi->extension_data_pending || handled == 2)
656 goto user_service;
657
658 /*
659 * check in on the active extensions, see if they
660 * had pending stuff to spill... they need to get the
661 * first look-in otherwise sequence will be disordered
662 *
663 * NULL, zero-length eff_buf means just spill pending
664 */
665
666 ret = 1;
667 while (ret == 1) {
668
669 /* default to nobody has more to spill */
670
671 ret = 0;
672 eff_buf.token = NULL;
673 eff_buf.token_len = 0;
674
675 /* give every extension a chance to spill */
676
677 for (n = 0; n < wsi->count_active_extensions; n++) {
678 m = wsi->active_extensions[n]->callback(
679 wsi->protocol->owning_server,
680 wsi->active_extensions[n], wsi,
681 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
682 wsi->active_extensions_user[n], &eff_buf, 0);
683 if (m < 0) {
684 lwsl_err("ext reports fatal error\n");
685 return -1;
686 }
687 if (m)
688 /*
689 * at least one extension told us he has more
690 * to spill, so we will go around again after
691 */
692 ret = 1;
693 }
694
695 /* assuming they gave us something to send, send it */
696
697 if (eff_buf.token_len) {
698 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
699 eff_buf.token_len))
700 return -1;
701 } else
702 continue;
703
704 /* no extension has more to spill */
705
706 if (!ret)
707 continue;
708
709 /*
710 * There's more to spill from an extension, but we just sent
711 * something... did that leave the pipe choked?
712 */
713
714 if (!lws_send_pipe_choked(wsi))
715 /* no we could add more */
716 continue;
717
718 lwsl_info("choked in POLLOUT service\n");
719
720 /*
721 * Yes, he's choked. Leave the POLLOUT masked on so we will
722 * come back here when he is unchoked. Don't call the user
723 * callback to enforce ordering of spilling, he'll get called
724 * when we come back here and there's nothing more to spill.
725 */
726
727 return 0;
728 }
729
730 wsi->extension_data_pending = 0;
731
732user_service:
733#endif
734 /* one shot */
735
736 if (pollfd) {
737 pollfd->events &= ~POLLOUT;
738
739 /* external POLL support via protocol 0 */
740 context->protocols[0].callback(context, wsi,
741 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
742 (void *)(long)wsi->sock, NULL, POLLOUT);
743 }
744#ifndef LWS_NO_EXTENSIONS
745notify_action:
746#endif
747
748 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
749 n = LWS_CALLBACK_CLIENT_WRITEABLE;
750 else
751 n = LWS_CALLBACK_SERVER_WRITEABLE;
752
753 return user_callback_handle_rxflow(wsi->protocol->callback, context,
754 wsi, (enum libwebsocket_callback_reasons) n,
755 wsi->user_space, NULL, 0);
756}
757
758
759
760void
761libwebsocket_service_timeout_check(struct libwebsocket_context *context,
762 struct libwebsocket *wsi, unsigned int sec)
763{
764#ifndef LWS_NO_EXTENSIONS
765 int n;
766
767 /*
768 * if extensions want in on it (eg, we are a mux parent)
769 * give them a chance to service child timeouts
770 */
771
772 for (n = 0; n < wsi->count_active_extensions; n++)
773 wsi->active_extensions[n]->callback(
774 context, wsi->active_extensions[n],
775 wsi, LWS_EXT_CALLBACK_1HZ,
776 wsi->active_extensions_user[n], NULL, sec);
777
778#endif
779 if (!wsi->pending_timeout)
780 return;
781
782 /*
783 * if we went beyond the allowed time, kill the
784 * connection
785 */
786
787 if (sec > wsi->pending_timeout_limit) {
788 lwsl_info("TIMEDOUT WAITING\n");
789 libwebsocket_close_and_free_session(context,
790 wsi, LWS_CLOSE_STATUS_NOSTATUS);
791 }
792}
793
794/**
795 * libwebsocket_service_fd() - Service polled socket with something waiting
796 * @context: Websocket context
797 * @pollfd: The pollfd entry describing the socket fd and which events
798 * happened.
799 *
800 * This function takes a pollfd that has POLLIN or POLLOUT activity and
801 * services it according to the state of the associated
802 * struct libwebsocket.
803 *
804 * The one call deals with all "service" that might happen on a socket
805 * including listen accepts, http files as well as websocket protocol.
806 */
807
808int
809libwebsocket_service_fd(struct libwebsocket_context *context,
810 struct pollfd *pollfd)
811{
812 struct libwebsocket *wsi;
813 int n;
814 int m;
815 int listen_socket_fds_index = 0;
816 struct timeval tv;
817
818#ifndef LWS_NO_EXTENSIONS
819 int more = 1;
820#endif
821 struct lws_tokens eff_buf;
822
823 if (context->listen_service_fd)
824 listen_socket_fds_index = context->lws_lookup[
825 context->listen_service_fd]->position_in_fds_table;
826
827 /*
828 * you can call us with pollfd = NULL to just allow the once-per-second
829 * global timeout checks; if less than a second since the last check
830 * it returns immediately then.
831 */
832
833 gettimeofday(&tv, NULL);
834
835 if (context->last_timeout_check_s != tv.tv_sec) {
836 context->last_timeout_check_s = tv.tv_sec;
837
838 #ifndef WIN32
839 /* if our parent went down, don't linger around */
840 if (context->started_with_parent &&
841 kill(context->started_with_parent, 0) < 0)
842 kill(getpid(), SIGTERM);
843 #endif
844
845 /* global timeout check once per second */
846
847 for (n = 0; n < context->fds_count; n++) {
848 struct libwebsocket *new_wsi =
849 context->lws_lookup[context->fds[n].fd];
850 if (!new_wsi)
851 continue;
852 libwebsocket_service_timeout_check(context,
853 new_wsi, tv.tv_sec);
854 }
855 }
856
857 /* just here for timeout management? */
858
859 if (pollfd == NULL)
860 return 0;
861
862 /* no, here to service a socket descriptor */
863
864 /*
865 * deal with listen service piggybacking
866 * every listen_service_modulo services of other fds, we
867 * sneak one in to service the listen socket if there's anything waiting
868 *
869 * To handle connection storms, as found in ab, if we previously saw a
870 * pending connection here, it causes us to check again next time.
871 */
872
873 if (context->listen_service_fd && pollfd !=
874 &context->fds[listen_socket_fds_index]) {
875 context->listen_service_count++;
876 if (context->listen_service_extraseen ||
877 context->listen_service_count ==
878 context->listen_service_modulo) {
879 context->listen_service_count = 0;
880 m = 1;
881 if (context->listen_service_extraseen > 5)
882 m = 2;
883 while (m--) {
884 /*
885 * even with extpoll, we prepared this
886 * internal fds for listen
887 */
888 n = poll(&context->fds[listen_socket_fds_index],
889 1, 0);
890 if (n > 0) { /* there's a conn waiting for us */
891 libwebsocket_service_fd(context,
892 &context->
893 fds[listen_socket_fds_index]);
894 context->listen_service_extraseen++;
895 } else {
896 if (context->listen_service_extraseen)
897 context->
898 listen_service_extraseen--;
899 break;
900 }
901 }
902 }
903
904 }
905
906 /* okay, what we came here to do... */
907
908 wsi = context->lws_lookup[pollfd->fd];
909 if (wsi == NULL) {
910 if (pollfd->fd > 11)
911 lwsl_err("unexpected NULL wsi fd=%d fds_count=%d\n",
912 pollfd->fd, context->fds_count);
913 return 0;
914 }
915
916 switch (wsi->mode) {
917
918#ifndef LWS_NO_SERVER
919 case LWS_CONNMODE_HTTP_SERVING:
920 case LWS_CONNMODE_SERVER_LISTENER:
921 case LWS_CONNMODE_SSL_ACK_PENDING:
922 return lws_server_socket_service(context, wsi, pollfd);
923#endif
924
925 case LWS_CONNMODE_WS_SERVING:
926 case LWS_CONNMODE_WS_CLIENT:
927
928 /* handle session socket closed */
929
930 if (pollfd->revents & (POLLERR | POLLHUP)) {
931
932 lwsl_debug("Session Socket %p (fd=%d) dead\n",
933 (void *)wsi, pollfd->fd);
934
935 libwebsocket_close_and_free_session(context, wsi,
936 LWS_CLOSE_STATUS_NOSTATUS);
937 return 0;
938 }
939
940 /* the guy requested a callback when it was OK to write */
941
942 if ((pollfd->revents & POLLOUT) &&
943 wsi->state == WSI_STATE_ESTABLISHED)
944 if (lws_handle_POLLOUT_event(context, wsi,
945 pollfd) < 0) {
946 lwsl_info("libwebsocket_service_fd: closing\n");
947 libwebsocket_close_and_free_session(
948 context, wsi, LWS_CLOSE_STATUS_NORMAL);
949 return 0;
950 }
951
952
953 /* any incoming data ready? */
954
955 if (!(pollfd->revents & POLLIN))
956 break;
957
958#ifdef LWS_OPENSSL_SUPPORT
959read_pending:
960 if (wsi->ssl) {
961 eff_buf.token_len = SSL_read(wsi->ssl,
962 context->service_buffer,
963 sizeof(context->service_buffer));
964 if (!eff_buf.token_len) {
965 n = SSL_get_error(wsi->ssl, eff_buf.token_len);
966 lwsl_err("SSL_read returned 0 with reason %s\n",
967 ERR_error_string(n,
968 (char *)context->service_buffer));
969 }
970 } else
971#endif
972 eff_buf.token_len = recv(pollfd->fd,
973 context->service_buffer,
974 sizeof(context->service_buffer), 0);
975
976 if (eff_buf.token_len < 0) {
977 lwsl_debug("Socket read returned %d\n",
978 eff_buf.token_len);
979 if (errno != EINTR && errno != EAGAIN)
980 libwebsocket_close_and_free_session(context,
981 wsi, LWS_CLOSE_STATUS_NOSTATUS);
982 return 0;
983 }
984 if (!eff_buf.token_len) {
985 lwsl_info("closing connection due to 0 length read\n");
986 libwebsocket_close_and_free_session(context, wsi,
987 LWS_CLOSE_STATUS_NOSTATUS);
988 return 0;
989 }
990
991 /*
992 * give any active extensions a chance to munge the buffer
993 * before parse. We pass in a pointer to an lws_tokens struct
994 * prepared with the default buffer and content length that's in
995 * there. Rather than rewrite the default buffer, extensions
996 * that expect to grow the buffer can adapt .token to
997 * point to their own per-connection buffer in the extension
998 * user allocation. By default with no extensions or no
999 * extension callback handling, just the normal input buffer is
1000 * used then so it is efficient.
1001 */
1002
1003 eff_buf.token = (char *)context->service_buffer;
1004#ifndef LWS_NO_EXTENSIONS
1005 more = 1;
1006 while (more) {
1007
1008 more = 0;
1009
1010 for (n = 0; n < wsi->count_active_extensions; n++) {
1011 m = wsi->active_extensions[n]->callback(context,
1012 wsi->active_extensions[n], wsi,
1013 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
1014 wsi->active_extensions_user[n],
1015 &eff_buf, 0);
1016 if (m < 0) {
1017 lwsl_ext(
1018 "Extension reports fatal error\n");
1019 libwebsocket_close_and_free_session(
1020 context, wsi,
1021 LWS_CLOSE_STATUS_NOSTATUS);
1022 return 0;
1023 }
1024 if (m)
1025 more = 1;
1026 }
1027#endif
1028 /* service incoming data */
1029
1030 if (eff_buf.token_len) {
1031 n = libwebsocket_read(context, wsi,
1032 (unsigned char *)eff_buf.token,
1033 eff_buf.token_len);
1034 if (n < 0)
1035 /* we closed wsi */
1036 return 0;
1037 }
1038#ifndef LWS_NO_EXTENSIONS
1039 eff_buf.token = NULL;
1040 eff_buf.token_len = 0;
1041 }
1042#endif
1043
1044#ifdef LWS_OPENSSL_SUPPORT
1045 if (wsi->ssl && SSL_pending(wsi->ssl))
1046 goto read_pending;
1047#endif
1048 break;
1049
1050 default:
1051#ifdef LWS_NO_CLIENT
1052 break;
1053#else
1054 return lws_client_socket_service(context, wsi, pollfd);
1055#endif
1056 }
1057
1058 return 0;
1059}
1060
1061
1062/**
1063 * libwebsocket_context_destroy() - Destroy the websocket context
1064 * @context: Websocket context
1065 *
1066 * This function closes any active connections and then frees the
1067 * context. After calling this, any further use of the context is
1068 * undefined.
1069 */
1070void
1071libwebsocket_context_destroy(struct libwebsocket_context *context)
1072{
1073#ifndef LWS_NO_EXTENSIONS
1074 int n;
1075 int m;
1076 struct libwebsocket_extension *ext;
1077 struct libwebsocket_protocols *protocol = context->protocols;
1078
1079#ifdef LWS_LATENCY
1080 if (context->worst_latency_info[0])
1081 lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
1082#endif
1083
1084 for (n = 0; n < context->fds_count; n++) {
1085 struct libwebsocket *wsi =
1086 context->lws_lookup[context->fds[n].fd];
1087 libwebsocket_close_and_free_session(context,
1088 wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
1089 n--;
1090 }
1091
1092 /*
1093 * give all extensions a chance to clean up any per-context
1094 * allocations they might have made
1095 */
1096
1097 ext = context->extensions;
1098 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
1099 if (context->listen_port)
1100 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
1101 while (ext && ext->callback) {
1102 ext->callback(context, ext, NULL,
1103 (enum libwebsocket_extension_callback_reasons)m,
1104 NULL, NULL, 0);
1105 ext++;
1106 }
1107
1108 /*
1109 * inform all the protocols that they are done and will have no more
1110 * callbacks
1111 */
1112
1113 while (protocol->callback) {
1114 protocol->callback(context, NULL, LWS_CALLBACK_PROTOCOL_DESTROY,
1115 NULL, NULL, 0);
1116 protocol++;
1117 }
1118
1119#endif
1120
1121#ifdef WIN32
1122#else
1123 close(context->fd_random);
1124#endif
1125
1126#ifdef LWS_OPENSSL_SUPPORT
1127 if (context->ssl_ctx)
1128 SSL_CTX_free(context->ssl_ctx);
1129 if (context->ssl_client_ctx)
1130 SSL_CTX_free(context->ssl_client_ctx);
1131
1132 ERR_remove_state(0);
1133 ERR_free_strings();
1134 EVP_cleanup();
1135 CRYPTO_cleanup_all_ex_data();
1136#endif
1137
1138 if (context->fds)
1139 free(context->fds);
1140 if (context->lws_lookup)
1141 free(context->lws_lookup);
1142
1143 free(context);
1144
1145#ifdef WIN32
1146 WSACleanup();
1147#endif
1148}
1149
1150/**
1151 * libwebsocket_context_user() - get the user data associated with the context
1152 * @context: Websocket context
1153 *
1154 * This returns the optional user allocation that can be attached to
1155 * the context the sockets live in at context_create time. It's a way
1156 * to let all sockets serviced in the same context share data without
1157 * using globals statics in the user code.
1158 */
1159LWS_EXTERN void *
1160libwebsocket_context_user(struct libwebsocket_context *context)
1161{
1162 return context->user_space;
1163}
1164
1165/**
1166 * libwebsocket_service() - Service any pending websocket activity
1167 * @context: Websocket context
1168 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
1169 * service otherwise block and service immediately, returning
1170 * after the timeout if nothing needed service.
1171 *
1172 * This function deals with any pending websocket traffic, for three
1173 * kinds of event. It handles these events on both server and client
1174 * types of connection the same.
1175 *
1176 * 1) Accept new connections to our context's server
1177 *
1178 * 2) Call the receive callback for incoming frame data received by
1179 * server or client connections.
1180 *
1181 * You need to call this service function periodically to all the above
1182 * functions to happen; if your application is single-threaded you can
1183 * just call it in your main event loop.
1184 *
1185 * Alternatively you can fork a new process that asynchronously handles
1186 * calling this service in a loop. In that case you are happy if this
1187 * call blocks your thread until it needs to take care of something and
1188 * would call it with a large nonzero timeout. Your loop then takes no
1189 * CPU while there is nothing happening.
1190 *
1191 * If you are calling it in a single-threaded app, you don't want it to
1192 * wait around blocking other things in your loop from happening, so you
1193 * would call it with a timeout_ms of 0, so it returns immediately if
1194 * nothing is pending, or as soon as it services whatever was pending.
1195 */
1196
1197int
1198libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
1199{
1200 int n;
1201
1202 /* stay dead once we are dead */
1203
1204 if (context == NULL)
1205 return 1;
1206
1207 /* wait for something to need service */
1208
1209 n = poll(context->fds, context->fds_count, timeout_ms);
1210 if (n == 0) /* poll timeout */
1211 return 0;
1212
1213 if (n < 0)
1214 return -1;
1215
1216 /* any socket with events to service? */
1217
1218 for (n = 0; n < context->fds_count; n++)
1219 if (context->fds[n].revents)
1220 if (libwebsocket_service_fd(context,
1221 &context->fds[n]) < 0)
1222 return -1;
1223 return 0;
1224}
1225
1226#ifndef LWS_NO_EXTENSIONS
1227int
1228lws_any_extension_handled(struct libwebsocket_context *context,
1229 struct libwebsocket *wsi,
1230 enum libwebsocket_extension_callback_reasons r,
1231 void *v, size_t len)
1232{
1233 int n;
1234 int handled = 0;
1235
1236 /* maybe an extension will take care of it for us */
1237
1238 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
1239 if (!wsi->active_extensions[n]->callback)
1240 continue;
1241
1242 handled |= wsi->active_extensions[n]->callback(context,
1243 wsi->active_extensions[n], wsi,
1244 r, wsi->active_extensions_user[n], v, len);
1245 }
1246
1247 return handled;
1248}
1249
1250
1251void *
1252lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
1253 struct libwebsocket_extension *ext)
1254{
1255 int n = 0;
1256
1257 if (wsi == NULL)
1258 return NULL;
1259
1260 while (n < wsi->count_active_extensions) {
1261 if (wsi->active_extensions[n] != ext) {
1262 n++;
1263 continue;
1264 }
1265 return wsi->active_extensions_user[n];
1266 }
1267
1268 return NULL;
1269}
1270#endif
1271
1272/**
1273 * libwebsocket_callback_on_writable() - Request a callback when this socket
1274 * becomes able to be written to without
1275 * blocking
1276 *
1277 * @context: libwebsockets context
1278 * @wsi: Websocket connection instance to get callback for
1279 */
1280
1281int
1282libwebsocket_callback_on_writable(struct libwebsocket_context *context,
1283 struct libwebsocket *wsi)
1284{
1285#ifndef LWS_NO_EXTENSIONS
1286 int n;
1287 int handled = 0;
1288
1289 /* maybe an extension will take care of it for us */
1290
1291 for (n = 0; n < wsi->count_active_extensions; n++) {
1292 if (!wsi->active_extensions[n]->callback)
1293 continue;
1294
1295 handled |= wsi->active_extensions[n]->callback(context,
1296 wsi->active_extensions[n], wsi,
1297 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
1298 wsi->active_extensions_user[n], NULL, 0);
1299 }
1300
1301 if (handled)
1302 return 1;
1303#endif
1304 if (wsi->position_in_fds_table < 0) {
1305 lwsl_err("libwebsocket_callback_on_writable: failed to find socket %d\n",
1306 wsi->sock);
1307 return -1;
1308 }
1309
1310 context->fds[wsi->position_in_fds_table].events |= POLLOUT;
1311
1312 /* external POLL support via protocol 0 */
1313 context->protocols[0].callback(context, wsi,
1314 LWS_CALLBACK_SET_MODE_POLL_FD,
1315 (void *)(long)wsi->sock, NULL, POLLOUT);
1316
1317 return 1;
1318}
1319
1320/**
1321 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
1322 * all connections using the given protocol when it
1323 * becomes possible to write to each socket without
1324 * blocking in turn.
1325 *
1326 * @protocol: Protocol whose connections will get callbacks
1327 */
1328
1329int
1330libwebsocket_callback_on_writable_all_protocol(
1331 const struct libwebsocket_protocols *protocol)
1332{
1333 struct libwebsocket_context *context = protocol->owning_server;
1334 int n;
1335 struct libwebsocket *wsi;
1336
1337 for (n = 0; n < context->fds_count; n++) {
1338 wsi = context->lws_lookup[context->fds[n].fd];
1339 if (!wsi)
1340 continue;
1341 if (wsi->protocol == protocol)
1342 libwebsocket_callback_on_writable(context, wsi);
1343 }
1344
1345 return 0;
1346}
1347
1348/**
1349 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
1350 *
1351 * You will not need this unless you are doing something special
1352 *
1353 * @wsi: Websocket connection instance
1354 * @reason: timeout reason
1355 * @secs: how many seconds
1356 */
1357
1358void
1359libwebsocket_set_timeout(struct libwebsocket *wsi,
1360 enum pending_timeout reason, int secs)
1361{
1362 struct timeval tv;
1363
1364 gettimeofday(&tv, NULL);
1365
1366 wsi->pending_timeout_limit = tv.tv_sec + secs;
1367 wsi->pending_timeout = reason;
1368}
1369
1370
1371/**
1372 * libwebsocket_get_socket_fd() - returns the socket file descriptor
1373 *
1374 * You will not need this unless you are doing something special
1375 *
1376 * @wsi: Websocket connection instance
1377 */
1378
1379int
1380libwebsocket_get_socket_fd(struct libwebsocket *wsi)
1381{
1382 return wsi->sock;
1383}
1384
1385#ifdef LWS_LATENCY
1386void
1387lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
1388 const char *action, int ret, int completed)
1389{
1390 struct timeval tv;
1391 unsigned long u;
1392 char buf[256];
1393
1394 gettimeofday(&tv, NULL);
1395
1396 u = (tv.tv_sec * 1000000) + tv.tv_usec;
1397
1398 if (action) {
1399 if (completed) {
1400 if (wsi->action_start == wsi->latency_start)
1401 sprintf(buf,
1402 "Completion first try lat %luus: %p: ret %d: %s\n",
1403 u - wsi->latency_start,
1404 (void *)wsi, ret, action);
1405 else
1406 sprintf(buf,
1407 "Completion %luus: lat %luus: %p: ret %d: %s\n",
1408 u - wsi->action_start,
1409 u - wsi->latency_start,
1410 (void *)wsi, ret, action);
1411 wsi->action_start = 0;
1412 } else
1413 sprintf(buf, "lat %luus: %p: ret %d: %s\n",
1414 u - wsi->latency_start,
1415 (void *)wsi, ret, action);
1416 if (u - wsi->latency_start > context->worst_latency) {
1417 context->worst_latency = u - wsi->latency_start;
1418 strcpy(context->worst_latency_info, buf);
1419 }
1420 lwsl_latency("%s", buf);
1421 } else {
1422 wsi->latency_start = u;
1423 if (!wsi->action_start)
1424 wsi->action_start = u;
1425 }
1426}
1427#endif
1428
1429#ifdef LWS_NO_SERVER
1430int
1431_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1432{
1433 return 0;
1434}
1435#else
1436int
1437_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1438{
1439 struct libwebsocket_context *context = wsi->protocol->owning_server;
1440 int n;
1441
1442 if (!(wsi->u.ws.rxflow_change_to & 2))
1443 return 0;
1444
1445 wsi->u.ws.rxflow_change_to &= ~2;
1446
1447 lwsl_info("rxflow: wsi %p change_to %d\n",
1448 wsi, wsi->u.ws.rxflow_change_to);
1449
1450 /* if we're letting it come again, did we interrupt anything? */
1451 if ((wsi->u.ws.rxflow_change_to & 1) && wsi->u.ws.rxflow_buffer) {
1452 n = libwebsocket_interpret_incoming_packet(wsi, NULL, 0);
1453 if (n < 0) {
1454 lwsl_info("libwebsocket_rx_flow_control: close req\n");
1455 return -1;
1456 }
1457 if (n)
1458 /* oh he stuck again, do nothing */
1459 return 0;
1460 }
1461
1462 if (wsi->u.ws.rxflow_change_to & 1)
1463 context->fds[wsi->position_in_fds_table].events |= POLLIN;
1464 else
1465 context->fds[wsi->position_in_fds_table].events &= ~POLLIN;
1466
1467 if (wsi->u.ws.rxflow_change_to & 1)
1468 /* external POLL support via protocol 0 */
1469 context->protocols[0].callback(context, wsi,
1470 LWS_CALLBACK_SET_MODE_POLL_FD,
1471 (void *)(long)wsi->sock, NULL, POLLIN);
1472 else
1473 /* external POLL support via protocol 0 */
1474 context->protocols[0].callback(context, wsi,
1475 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
1476 (void *)(long)wsi->sock, NULL, POLLIN);
1477
1478 return 1;
1479}
1480#endif
1481
1482/**
1483 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
1484 * receieved packets.
1485 *
1486 * If the output side of a server process becomes choked, this allows flow
1487 * control for the input side.
1488 *
1489 * @wsi: Websocket connection instance to get callback for
1490 * @enable: 0 = disable read servicing for this connection, 1 = enable
1491 */
1492
1493int
1494libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
1495{
1496 wsi->u.ws.rxflow_change_to = 2 | !!enable;
1497
1498 return 0;
1499}
1500
1501
1502/**
1503 * libwebsocket_canonical_hostname() - returns this host's hostname
1504 *
1505 * This is typically used by client code to fill in the host parameter
1506 * when making a client connection. You can only call it after the context
1507 * has been created.
1508 *
1509 * @context: Websocket context
1510 */
1511
1512
1513extern const char *
1514libwebsocket_canonical_hostname(struct libwebsocket_context *context)
1515{
1516 return (const char *)context->canonical_hostname;
1517}
1518
1519
1520static void sigpipe_handler(int x)
1521{
1522}
1523
1524#ifdef LWS_OPENSSL_SUPPORT
1525static int
1526OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
1527{
1528
1529 SSL *ssl;
1530 int n;
1531 struct libwebsocket_context *context;
1532
1533 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
1534 SSL_get_ex_data_X509_STORE_CTX_idx());
1535
1536 /*
1537 * !!! nasty openssl requires the index to come as a library-scope
1538 * static
1539 */
1540 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
1541
1542 n = context->protocols[0].callback(NULL, NULL,
1543 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
1544 x509_ctx, ssl, preverify_ok);
1545
1546 /* convert return code from 0 = OK to 1 = OK */
1547
1548 if (!n)
1549 n = 1;
1550 else
1551 n = 0;
1552
1553 return n;
1554}
1555#endif
1556
1557int user_callback_handle_rxflow(callback_function callback_function,
1558 struct libwebsocket_context *context,
1559 struct libwebsocket *wsi,
1560 enum libwebsocket_callback_reasons reason, void *user,
1561 void *in, size_t len)
1562{
1563 int n;
1564
1565 n = callback_function(context, wsi, reason, user, in, len);
1566 if (!n)
1567 n = _libwebsocket_rx_flow_control(wsi);
1568
1569 return n;
1570}
1571
1572
1573/**
1574 * libwebsocket_create_context() - Create the websocket handler
1575 * @info: pointer to struct with parameters
1576 *
1577 * This function creates the listening socket (if serving) and takes care
1578 * of all initialization in one step.
1579 *
1580 * After initialization, it returns a struct libwebsocket_context * that
1581 * represents this server. After calling, user code needs to take care
1582 * of calling libwebsocket_service() with the context pointer to get the
1583 * server's sockets serviced. This can be done in the same process context
1584 * or a forked process, or another thread,
1585 *
1586 * The protocol callback functions are called for a handful of events
1587 * including http requests coming in, websocket connections becoming
1588 * established, and data arriving; it's also called periodically to allow
1589 * async transmission.
1590 *
1591 * HTTP requests are sent always to the FIRST protocol in @protocol, since
1592 * at that time websocket protocol has not been negotiated. Other
1593 * protocols after the first one never see any HTTP callack activity.
1594 *
1595 * The server created is a simple http server by default; part of the
1596 * websocket standard is upgrading this http connection to a websocket one.
1597 *
1598 * This allows the same server to provide files like scripts and favicon /
1599 * images or whatever over http and dynamic data over websockets all in
1600 * one place; they're all handled in the user callback.
1601 */
1602
1603struct libwebsocket_context *
1604libwebsocket_create_context(struct lws_context_creation_info *info)
1605{
1606 struct libwebsocket_context *context = NULL;
1607 char *p;
1608#ifndef LWS_NO_SERVER
1609 int n;
1610 int opt = 1;
1611 struct libwebsocket *wsi;
1612 struct sockaddr_in serv_addr;
1613#endif
1614#ifndef LWS_NO_EXTENSIONS
1615 int m;
1616 struct libwebsocket_extension *ext;
1617#endif
1618
1619#ifdef LWS_OPENSSL_SUPPORT
1620 SSL_METHOD *method;
1621#endif
1622
1623#ifndef LWS_NO_DAEMONIZE
1624 int pid_daemon = get_daemonize_pid();
1625#endif
1626
1627 lwsl_notice("Initial logging level %d\n", log_level);
1628 lwsl_notice("Library version: %s\n", library_version);
1629 lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n",
1630 LWS_MAX_HEADER_NAME_LENGTH);
1631 lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
1632 lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
1633#ifndef LWS_NO_EXTENSIONS
1634 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n",
1635 LWS_MAX_EXTENSIONS_ACTIVE);
1636#else
1637 lwsl_notice(" Configured without extension support\n");
1638#endif
1639 lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
1640 lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
1641 lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
1642 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
1643 lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
1644
1645#ifdef _WIN32
1646 {
1647 WORD wVersionRequested;
1648 WSADATA wsaData;
1649 int err;
1650 HMODULE wsdll;
1651
1652 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
1653 wVersionRequested = MAKEWORD(2, 2);
1654
1655 err = WSAStartup(wVersionRequested, &wsaData);
1656 if (err != 0) {
1657 /* Tell the user that we could not find a usable */
1658 /* Winsock DLL. */
1659 lwsl_err("WSAStartup failed with error: %d\n", err);
1660 return NULL;
1661 }
1662
1663 /* default to a poll() made out of select() */
1664 poll = emulated_poll;
1665
1666 /* if windows socket lib available, use his WSAPoll */
1667 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
1668 if (wsdll)
1669 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
1670
1671 /* Finally fall back to emulated poll if all else fails */
1672 if (!poll)
1673 poll = emulated_poll;
1674 }
1675#endif
1676
1677 context = (struct libwebsocket_context *)
1678 malloc(sizeof(struct libwebsocket_context));
1679 if (!context) {
1680 lwsl_err("No memory for websocket context\n");
1681 return NULL;
1682 }
1683 memset(context, 0, sizeof(*context));
1684#ifndef LWS_NO_DAEMONIZE
1685 context->started_with_parent = pid_daemon;
1686 lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
1687#endif
1688
1689 context->listen_service_extraseen = 0;
1690 context->protocols = info->protocols;
1691 context->listen_port = info->port;
1692 context->http_proxy_port = 0;
1693 context->http_proxy_address[0] = '\0';
1694 context->options = info->options;
1695 /* to reduce this allocation, */
1696 context->max_fds = getdtablesize();
1697 lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n",
1698 sizeof(struct libwebsocket_context),
1699 sizeof(struct pollfd) + sizeof(struct libwebsocket *),
1700 context->max_fds,
1701 sizeof(struct libwebsocket_context) +
1702 ((sizeof(struct pollfd) + sizeof(struct libwebsocket *)) *
1703 context->max_fds));
1704
1705 context->fds = (struct pollfd *)malloc(sizeof(struct pollfd) *
1706 context->max_fds);
1707 if (context->fds == NULL) {
1708 lwsl_err("Unable to allocate fds array for %d connections\n",
1709 context->max_fds);
1710 free(context);
1711 return NULL;
1712 }
1713 context->lws_lookup = (struct libwebsocket **)
1714 malloc(sizeof(struct libwebsocket *) * context->max_fds);
1715 if (context->lws_lookup == NULL) {
1716 lwsl_err(
1717 "Unable to allocate lws_lookup array for %d connections\n",
1718 context->max_fds);
1719 free(context->fds);
1720 free(context);
1721 return NULL;
1722 }
1723
1724 context->fds_count = 0;
1725#ifndef LWS_NO_EXTENSIONS
1726 context->extensions = info->extensions;
1727#endif
1728 context->last_timeout_check_s = 0;
1729 context->user_space = info->user;
1730
1731#ifdef WIN32
1732 context->fd_random = 0;
1733#else
1734 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
1735 if (context->fd_random < 0) {
1736 lwsl_err("Unable to open random device %s %d\n",
1737 SYSTEM_RANDOM_FILEPATH, context->fd_random);
1738 goto bail;
1739 }
1740#endif
1741
1742#ifdef LWS_OPENSSL_SUPPORT
1743 context->use_ssl = 0;
1744 context->ssl_ctx = NULL;
1745 context->ssl_client_ctx = NULL;
1746 openssl_websocket_private_data_index = 0;
1747#endif
1748
1749 strcpy(context->canonical_hostname, "unknown");
1750
1751#ifndef LWS_NO_SERVER
1752 if (!(info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) {
1753 struct sockaddr sa;
1754 context->service_buffer[0] = '\0';
1755
1756 /* find canonical hostname */
1757
1758 context->service_buffer[
1759 sizeof(context->service_buffer) - 1] = '\0';
1760 memset(&sa, 0, sizeof(sa));
1761 sa.sa_family = AF_INET;
1762 sa.sa_data[sizeof(sa.sa_data) - 1] = '\0';
1763 gethostname((char *)context->service_buffer,
1764 sizeof(context->service_buffer) - 1);
1765
1766 n = 0;
1767
1768 if (strlen((char *)context->service_buffer) <
1769 sizeof(sa.sa_data) - 1) {
1770 strcpy(sa.sa_data, (char *)context->service_buffer);
1771 lwsl_debug("my host name is %s\n", sa.sa_data);
1772 n = getnameinfo(&sa, sizeof(sa),
1773 (char *)context->service_buffer,
1774 sizeof(context->service_buffer) - 1,
1775 NULL, 0, NI_NAMEREQD);
1776 }
1777
1778 if (!n) {
1779 strncpy(context->canonical_hostname,
1780 (char *)context->service_buffer,
1781 sizeof(context->canonical_hostname) - 1);
1782 context->canonical_hostname[
1783 sizeof(context->canonical_hostname) - 1] = '\0';
1784 } else
1785 strncpy(context->canonical_hostname,
1786 (char *)context->service_buffer,
1787 sizeof(context->canonical_hostname) - 1);
1788
1789 lwsl_notice(" canonical_hostname = %s\n",
1790 context->canonical_hostname);
1791 }
1792#endif
1793
1794 /* split the proxy ads:port if given */
1795
1796 p = getenv("http_proxy");
1797 if (p) {
1798 strncpy(context->http_proxy_address, p,
1799 sizeof(context->http_proxy_address) - 1);
1800 context->http_proxy_address[
1801 sizeof(context->http_proxy_address) - 1] = '\0';
1802
1803 p = strchr(context->http_proxy_address, ':');
1804 if (p == NULL) {
1805 lwsl_err("http_proxy needs to be ads:port\n");
1806 goto bail;
1807 }
1808 *p = '\0';
1809 context->http_proxy_port = atoi(p + 1);
1810
1811 lwsl_notice(" Proxy %s:%u\n",
1812 context->http_proxy_address,
1813 context->http_proxy_port);
1814 }
1815
1816#ifndef LWS_NO_SERVER
1817 if (info->port) {
1818
1819#ifdef LWS_OPENSSL_SUPPORT
1820 context->use_ssl = info->ssl_cert_filepath != NULL &&
1821 info->ssl_private_key_filepath != NULL;
1822#ifdef USE_CYASSL
1823 lwsl_notice(" Compiled with CYASSL support\n");
1824#else
1825 lwsl_notice(" Compiled with OpenSSL support\n");
1826#endif
1827 if (context->use_ssl)
1828 lwsl_notice(" Using SSL mode\n");
1829 else
1830 lwsl_notice(" Using non-SSL mode\n");
1831
1832#else
1833 if (info->ssl_cert_filepath != NULL &&
1834 info->ssl_private_key_filepath != NULL) {
1835 lwsl_notice(" Not compiled for OpenSSl support!\n");
1836 goto bail;
1837 }
1838 lwsl_notice(" Compiled without SSL support\n");
1839#endif
1840
1841 lwsl_notice(
1842 " per-conn mem: %u + %u headers + protocol rx buf\n",
1843 sizeof(struct libwebsocket),
1844 sizeof(struct allocated_headers));
1845 }
1846#endif
1847
1848 /* ignore SIGPIPE */
1849#ifdef WIN32
1850#else
1851 signal(SIGPIPE, sigpipe_handler);
1852#endif
1853
1854
1855#ifdef LWS_OPENSSL_SUPPORT
1856
1857 /* basic openssl init */
1858
1859 SSL_library_init();
1860
1861 OpenSSL_add_all_algorithms();
1862 SSL_load_error_strings();
1863
1864 openssl_websocket_private_data_index =
1865 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
1866
1867 /*
1868 * Firefox insists on SSLv23 not SSLv3
1869 * Konq disables SSLv2 by default now, SSLv23 works
1870 */
1871
1872 method = (SSL_METHOD *)SSLv23_server_method();
1873 if (!method) {
1874 lwsl_err("problem creating ssl method: %s\n",
1875 ERR_error_string(ERR_get_error(),
1876 (char *)context->service_buffer));
1877 goto bail;
1878 }
1879 context->ssl_ctx = SSL_CTX_new(method); /* create context */
1880 if (!context->ssl_ctx) {
1881 lwsl_err("problem creating ssl context: %s\n",
1882 ERR_error_string(ERR_get_error(),
1883 (char *)context->service_buffer));
1884 goto bail;
1885 }
1886
1887#ifdef SSL_OP_NO_COMPRESSION
1888 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
1889#endif
1890 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
1891 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
1892
1893#ifndef LWS_NO_CLIENT
1894
1895 /* client context */
1896
1897 if (info->port == CONTEXT_PORT_NO_LISTEN) {
1898 method = (SSL_METHOD *)SSLv23_client_method();
1899 if (!method) {
1900 lwsl_err("problem creating ssl method: %s\n",
1901 ERR_error_string(ERR_get_error(),
1902 (char *)context->service_buffer));
1903 goto bail;
1904 }
1905 /* create context */
1906 context->ssl_client_ctx = SSL_CTX_new(method);
1907 if (!context->ssl_client_ctx) {
1908 lwsl_err("problem creating ssl context: %s\n",
1909 ERR_error_string(ERR_get_error(),
1910 (char *)context->service_buffer));
1911 goto bail;
1912 }
1913
1914#ifdef SSL_OP_NO_COMPRESSION
1915 SSL_CTX_set_options(context->ssl_client_ctx,
1916 SSL_OP_NO_COMPRESSION);
1917#endif
1918 SSL_CTX_set_options(context->ssl_client_ctx,
1919 SSL_OP_CIPHER_SERVER_PREFERENCE);
1920 SSL_CTX_set_cipher_list(context->ssl_client_ctx,
1921 CIPHERS_LIST_STRING);
1922
1923 /* openssl init for cert verification (for client sockets) */
1924 if (!info->ssl_ca_filepath) {
1925 if (!SSL_CTX_load_verify_locations(
1926 context->ssl_client_ctx, NULL,
1927 LWS_OPENSSL_CLIENT_CERTS))
1928 lwsl_err(
1929 "Unable to load SSL Client certs from %s "
1930 "(set by --with-client-cert-dir= "
1931 "in configure) -- client ssl isn't "
1932 "going to work", LWS_OPENSSL_CLIENT_CERTS);
1933 } else
1934 if (!SSL_CTX_load_verify_locations(
1935 context->ssl_client_ctx, info->ssl_ca_filepath,
1936 NULL))
1937 lwsl_err(
1938 "Unable to load SSL Client certs "
1939 "file from %s -- client ssl isn't "
1940 "going to work", info->ssl_ca_filepath);
1941
1942 /*
1943 * callback allowing user code to load extra verification certs
1944 * helping the client to verify server identity
1945 */
1946
1947 context->protocols[0].callback(context, NULL,
1948 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
1949 context->ssl_client_ctx, NULL, 0);
1950 }
1951#endif
1952
1953 /* as a server, are we requiring clients to identify themselves? */
1954
1955 if (info->options &
1956 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
1957
1958 /* absolutely require the client cert */
1959
1960 SSL_CTX_set_verify(context->ssl_ctx,
1961 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1962 OpenSSL_verify_callback);
1963
1964 /*
1965 * give user code a chance to load certs into the server
1966 * allowing it to verify incoming client certs
1967 */
1968
1969 context->protocols[0].callback(context, NULL,
1970 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
1971 context->ssl_ctx, NULL, 0);
1972 }
1973
1974 if (context->use_ssl) {
1975
1976 /* openssl init for server sockets */
1977
1978 /* set the local certificate from CertFile */
1979 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
1980 info->ssl_cert_filepath);
1981 if (n != 1) {
1982 lwsl_err("problem getting cert '%s': %s\n",
1983 info->ssl_cert_filepath,
1984 ERR_error_string(ERR_get_error(),
1985 (char *)context->service_buffer));
1986 goto bail;
1987 }
1988 /* set the private key from KeyFile */
1989 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
1990 info->ssl_private_key_filepath,
1991 SSL_FILETYPE_PEM) != 1) {
1992 lwsl_err("ssl problem getting key '%s': %s\n",
1993 info->ssl_private_key_filepath,
1994 ERR_error_string(ERR_get_error(),
1995 (char *)context->service_buffer));
1996 goto bail;
1997 }
1998 /* verify private key */
1999 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
2000 lwsl_err("Private SSL key doesn't match cert\n");
2001 goto bail;
2002 }
2003
2004 /* SSL is happy and has a cert it's content with */
2005 }
2006#endif
2007
2008 /* selftest */
2009
2010 if (lws_b64_selftest())
2011 goto bail;
2012
2013#ifndef LWS_NO_SERVER
2014 /* set up our external listening socket we serve on */
2015
2016 if (info->port) {
2017 int sockfd;
2018
2019 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2020 if (sockfd < 0) {
2021 lwsl_err("ERROR opening socket\n");
2022 goto bail;
2023 }
2024
2025#ifndef WIN32
2026 /*
2027 * allow us to restart even if old sockets in TIME_WAIT
2028 * (REUSEADDR on Unix means, "don't hang on to this
2029 * address after the listener is closed." On Windows, though,
2030 * it means "don't keep other processes from binding to
2031 * this address while we're using it)
2032 */
2033 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2034 (const void *)&opt, sizeof(opt));
2035#endif
2036
2037 /* Disable Nagle */
2038 opt = 1;
2039 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2040 (const void *)&opt, sizeof(opt));
2041
2042 #ifdef WIN32
2043 opt = 0;
2044 ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt);
2045 #else
2046 fcntl(sockfd, F_SETFL, O_NONBLOCK);
2047 #endif
2048
2049 bzero((char *) &serv_addr, sizeof(serv_addr));
2050 serv_addr.sin_family = AF_INET;
2051 if (info->iface == NULL)
2052 serv_addr.sin_addr.s_addr = INADDR_ANY;
2053 else
2054 interface_to_sa(info->iface, &serv_addr,
2055 sizeof(serv_addr));
2056 serv_addr.sin_port = htons(info->port);
2057
2058 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2059 sizeof(serv_addr));
2060 if (n < 0) {
2061 lwsl_err("ERROR on binding to port %d (%d %d)\n",
2062 info->port, n, errno);
2063 close(sockfd);
2064 goto bail;
2065 }
2066
2067 wsi = (struct libwebsocket *)malloc(
2068 sizeof(struct libwebsocket));
2069 if (wsi == NULL) {
2070 lwsl_err("Out of mem\n");
2071 close(sockfd);
2072 goto bail;
2073 }
2074 memset(wsi, 0, sizeof(struct libwebsocket));
2075 wsi->sock = sockfd;
2076#ifndef LWS_NO_EXTENSIONS
2077 wsi->count_active_extensions = 0;
2078#endif
2079 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
2080
2081 insert_wsi_socket_into_fds(context, wsi);
2082
2083 context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
2084 context->listen_service_count = 0;
2085 context->listen_service_fd = sockfd;
2086
2087 listen(sockfd, LWS_SOMAXCONN);
2088 lwsl_notice(" Listening on port %d\n", info->port);
2089 }
2090#endif
2091
2092 /*
2093 * drop any root privs for this process
2094 * to listen on port < 1023 we would have needed root, but now we are
2095 * listening, we don't want the power for anything else
2096 */
2097#ifdef WIN32
2098#else
2099 if (info->gid != -1)
2100 if (setgid(info->gid))
2101 lwsl_warn("setgid: %s\n", strerror(errno));
2102 if (info->uid != -1)
2103 if (setuid(info->uid))
2104 lwsl_warn("setuid: %s\n", strerror(errno));
2105#endif
2106
2107 /* initialize supported protocols */
2108
2109 for (context->count_protocols = 0;
2110 info->protocols[context->count_protocols].callback;
2111 context->count_protocols++) {
2112
2113 lwsl_parser(" Protocol: %s\n",
2114 info->protocols[context->count_protocols].name);
2115
2116 info->protocols[context->count_protocols].owning_server =
2117 context;
2118 info->protocols[context->count_protocols].protocol_index =
2119 context->count_protocols;
2120
2121 /*
2122 * inform all the protocols that they are doing their one-time
2123 * initialization if they want to
2124 */
2125 info->protocols[context->count_protocols].callback(context,
2126 NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0);
2127 }
2128
2129#ifndef LWS_NO_EXTENSIONS
2130 /*
2131 * give all extensions a chance to create any per-context
2132 * allocations they need
2133 */
2134
2135 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
2136 if (info->port)
2137 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
2138
2139 if (info->extensions) {
2140 ext = info->extensions;
2141 while (ext->callback) {
2142 lwsl_ext(" Extension: %s\n", ext->name);
2143 ext->callback(context, ext, NULL,
2144 (enum libwebsocket_extension_callback_reasons)m,
2145 NULL, NULL, 0);
2146 ext++;
2147 }
2148 }
2149#endif
2150 return context;
2151
2152bail:
2153 libwebsocket_context_destroy(context);
2154 return NULL;
2155}
2156
2157/**
2158 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
2159 * connection.
2160 * @wsi: pointer to struct websocket you want to know the protocol of
2161 *
2162 *
2163 * Some apis can act on all live connections of a given protocol,
2164 * this is how you can get a pointer to the active protocol if needed.
2165 */
2166
2167const struct libwebsocket_protocols *
2168libwebsockets_get_protocol(struct libwebsocket *wsi)
2169{
2170 return wsi->protocol;
2171}
2172
2173int
2174libwebsocket_is_final_fragment(struct libwebsocket *wsi)
2175{
2176 return wsi->u.ws.final;
2177}
2178
2179unsigned char
2180libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
2181{
2182 return wsi->u.ws.rsv;
2183}
2184
2185void *
2186libwebsocket_ensure_user_space(struct libwebsocket *wsi)
2187{
2188 /* allocate the per-connection user memory (if any) */
2189
2190 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
2191 wsi->user_space = malloc(
2192 wsi->protocol->per_session_data_size);
2193 if (wsi->user_space == NULL) {
2194 lwsl_err("Out of memory for conn user space\n");
2195 return NULL;
2196 }
2197 memset(wsi->user_space, 0,
2198 wsi->protocol->per_session_data_size);
2199 }
2200 return wsi->user_space;
2201}
2202
2203static void lwsl_emit_stderr(int level, const char *line)
2204{
2205 char buf[300];
2206 struct timeval tv;
2207 int n;
2208
2209 gettimeofday(&tv, NULL);
2210
2211 buf[0] = '\0';
2212 for (n = 0; n < LLL_COUNT; n++)
2213 if (level == (1 << n)) {
2214 sprintf(buf, "[%ld:%04d] %s: ", tv.tv_sec,
2215 (int)(tv.tv_usec / 100), log_level_names[n]);
2216 break;
2217 }
2218
2219 fprintf(stderr, "%s%s", buf, line);
2220}
2221
2222#ifdef WIN32
2223void lwsl_emit_syslog(int level, const char *line)
2224{
2225 lwsl_emit_stderr(level, line);
2226}
2227#else
2228void lwsl_emit_syslog(int level, const char *line)
2229{
2230 int syslog_level = LOG_DEBUG;
2231
2232 switch (level) {
2233 case LLL_ERR:
2234 syslog_level = LOG_ERR;
2235 break;
2236 case LLL_WARN:
2237 syslog_level = LOG_WARNING;
2238 break;
2239 case LLL_NOTICE:
2240 syslog_level = LOG_NOTICE;
2241 break;
2242 case LLL_INFO:
2243 syslog_level = LOG_INFO;
2244 break;
2245 }
2246 syslog(syslog_level, "%s", line);
2247}
2248#endif
2249
2250void _lws_log(int filter, const char *format, ...)
2251{
2252 char buf[256];
2253 va_list ap;
2254
2255 if (!(log_level & filter))
2256 return;
2257
2258 va_start(ap, format);
2259 vsnprintf(buf, sizeof(buf), format, ap);
2260 buf[sizeof(buf) - 1] = '\0';
2261 va_end(ap);
2262
2263 lwsl_emit(filter, buf);
2264}
2265
2266/**
2267 * lws_set_log_level() - Set the logging bitfield
2268 * @level: OR together the LLL_ debug contexts you want output from
2269 * @log_emit_function: NULL to leave it as it is, or a user-supplied
2270 * function to perform log string emission instead of
2271 * the default stderr one.
2272 *
2273 * log level defaults to "err" and "warn" contexts enabled only and
2274 * emission on stderr.
2275 */
2276
2277void lws_set_log_level(int level, void (*log_emit_function)(int level,
2278 const char *line))
2279{
2280 log_level = level;
2281 if (log_emit_function)
2282 lwsl_emit = log_emit_function;
2283}
22840
=== removed directory '.pc/0002-keepalive.patch'
=== removed directory '.pc/0002-keepalive.patch/lib'
=== removed file '.pc/0002-keepalive.patch/lib/libwebsockets.c'
--- .pc/0002-keepalive.patch/lib/libwebsockets.c 2013-03-28 19:10:28 +0000
+++ .pc/0002-keepalive.patch/lib/libwebsockets.c 1970-01-01 00:00:00 +0000
@@ -1,2251 +0,0 @@
1/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 Andy Green <andy@warmcat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22#include "private-libwebsockets.h"
23
24#ifdef WIN32
25#include <tchar.h>
26#include <io.h>
27#include <mstcpip.h>
28#else
29#ifdef LWS_BUILTIN_GETIFADDRS
30#include <getifaddrs.h>
31#else
32#include <ifaddrs.h>
33#endif
34#include <syslog.h>
35#include <sys/un.h>
36#include <sys/socket.h>
37#include <netdb.h>
38#endif
39
40#ifdef LWS_OPENSSL_SUPPORT
41int openssl_websocket_private_data_index;
42#endif
43
44#ifdef __MINGW32__
45#include "../win32port/win32helpers/websock-w32.c"
46#else
47#ifdef __MINGW64__
48#include "../win32port/win32helpers/websock-w32.c"
49#endif
50#endif
51
52#ifndef LWS_BUILD_HASH
53#define LWS_BUILD_HASH "unknown-build-hash"
54#endif
55
56static int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
57static void lwsl_emit_stderr(int level, const char *line);
58static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
59
60static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
61
62static const char * const log_level_names[] = {
63 "ERR",
64 "WARN",
65 "NOTICE",
66 "INFO",
67 "DEBUG",
68 "PARSER",
69 "HEADER",
70 "EXTENSION",
71 "CLIENT",
72 "LATENCY",
73};
74
75#ifndef LWS_NO_CLIENT
76 extern int lws_client_socket_service(
77 struct libwebsocket_context *context,
78 struct libwebsocket *wsi, struct pollfd *pollfd);
79#endif
80#ifndef LWS_NO_SERVER
81 extern int lws_server_socket_service(
82 struct libwebsocket_context *context,
83 struct libwebsocket *wsi, struct pollfd *pollfd);
84#endif
85
86/**
87 * lws_get_library_version: get version and git hash library built from
88 *
89 * returns a const char * to a string like "1.1 178d78c"
90 * representing the library version followed by the git head hash it
91 * was built from
92 */
93
94const char *
95lws_get_library_version(void)
96{
97 return library_version;
98}
99
100int
101insert_wsi_socket_into_fds(struct libwebsocket_context *context,
102 struct libwebsocket *wsi)
103{
104 if (context->fds_count >= context->max_fds) {
105 lwsl_err("Too many fds (%d)\n", context->max_fds);
106 return 1;
107 }
108
109 if (wsi->sock > context->max_fds) {
110 lwsl_err("Socket fd %d is too high (%d)\n",
111 wsi->sock, context->max_fds);
112 return 1;
113 }
114
115 assert(wsi);
116 assert(wsi->sock);
117
118 lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
119 wsi, wsi->sock, context->fds_count);
120
121 context->lws_lookup[wsi->sock] = wsi;
122 wsi->position_in_fds_table = context->fds_count;
123 context->fds[context->fds_count].fd = wsi->sock;
124 context->fds[context->fds_count].events = POLLIN;
125 context->fds[context->fds_count++].revents = 0;
126
127 /* external POLL support via protocol 0 */
128 context->protocols[0].callback(context, wsi,
129 LWS_CALLBACK_ADD_POLL_FD,
130 (void *)(long)wsi->sock, NULL, POLLIN);
131
132 return 0;
133}
134
135static int
136remove_wsi_socket_from_fds(struct libwebsocket_context *context,
137 struct libwebsocket *wsi)
138{
139 int m;
140
141 if (!--context->fds_count)
142 goto do_ext;
143
144 if (wsi->sock > context->max_fds) {
145 lwsl_err("Socket fd %d too high (%d)\n",
146 wsi->sock, context->max_fds);
147 return 1;
148 }
149
150 lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n",
151 wsi, wsi->sock, wsi->position_in_fds_table);
152
153 m = wsi->position_in_fds_table; /* replace the contents for this */
154
155 /* have the last guy take up the vacant slot */
156 context->fds[m] = context->fds[context->fds_count];
157 /*
158 * end guy's fds_lookup entry remains unchanged
159 * (still same fd pointing to same wsi)
160 */
161 /* end guy's "position in fds table" changed */
162 context->lws_lookup[context->fds[context->fds_count].fd]->
163 position_in_fds_table = m;
164 /* deletion guy's lws_lookup entry needs nuking */
165 context->lws_lookup[wsi->sock] = NULL;
166 /* removed wsi has no position any more */
167 wsi->position_in_fds_table = -1;
168
169do_ext:
170 /* remove also from external POLL support via protocol 0 */
171 if (wsi->sock)
172 context->protocols[0].callback(context, wsi,
173 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
174
175 return 0;
176}
177
178
179void
180libwebsocket_close_and_free_session(struct libwebsocket_context *context,
181 struct libwebsocket *wsi, enum lws_close_status reason)
182{
183 int n;
184 int old_state;
185 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
186 LWS_SEND_BUFFER_POST_PADDING];
187#ifndef LWS_NO_EXTENSIONS
188 int ret;
189 int m;
190 struct lws_tokens eff_buf;
191 struct libwebsocket_extension *ext;
192#endif
193
194 if (!wsi)
195 return;
196
197 old_state = wsi->state;
198
199 if (old_state == WSI_STATE_DEAD_SOCKET)
200 return;
201
202 wsi->u.ws.close_reason = reason;
203
204 if (wsi->mode == LWS_CONNMODE_HTTP_SERVING && wsi->u.http.fd) {
205 close(wsi->u.http.fd);
206 wsi->u.http.fd = 0;
207 }
208
209#ifndef LWS_NO_EXTENSIONS
210 /*
211 * are his extensions okay with him closing? Eg he might be a mux
212 * parent and just his ch1 aspect is closing?
213 */
214
215 for (n = 0; n < wsi->count_active_extensions; n++) {
216 if (!wsi->active_extensions[n]->callback)
217 continue;
218
219 m = wsi->active_extensions[n]->callback(context,
220 wsi->active_extensions[n], wsi,
221 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
222 wsi->active_extensions_user[n], NULL, 0);
223
224 /*
225 * if somebody vetoed actually closing him at this time....
226 * up to the extension to track the attempted close, let's
227 * just bail
228 */
229
230 if (m) {
231 lwsl_ext("extension vetoed close\n");
232 return;
233 }
234 }
235
236 /*
237 * flush any tx pending from extensions, since we may send close packet
238 * if there are problems with send, just nuke the connection
239 */
240
241 ret = 1;
242 while (ret == 1) {
243
244 /* default to nobody has more to spill */
245
246 ret = 0;
247 eff_buf.token = NULL;
248 eff_buf.token_len = 0;
249
250 /* show every extension the new incoming data */
251
252 for (n = 0; n < wsi->count_active_extensions; n++) {
253 m = wsi->active_extensions[n]->callback(
254 wsi->protocol->owning_server,
255 wsi->active_extensions[n], wsi,
256 LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
257 wsi->active_extensions_user[n], &eff_buf, 0);
258 if (m < 0) {
259 lwsl_ext("Extension reports fatal error\n");
260 goto just_kill_connection;
261 }
262 if (m)
263 /*
264 * at least one extension told us he has more
265 * to spill, so we will go around again after
266 */
267 ret = 1;
268 }
269
270 /* assuming they left us something to send, send it */
271
272 if (eff_buf.token_len)
273 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
274 eff_buf.token_len)) {
275 lwsl_debug("close: ext spill failed\n");
276 goto just_kill_connection;
277 }
278 }
279#endif
280
281 /*
282 * signal we are closing, libsocket_write will
283 * add any necessary version-specific stuff. If the write fails,
284 * no worries we are closing anyway. If we didn't initiate this
285 * close, then our state has been changed to
286 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
287 *
288 * Likewise if it's a second call to close this connection after we
289 * sent the close indication to the peer already, we are in state
290 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
291 */
292
293 if (old_state == WSI_STATE_ESTABLISHED &&
294 reason != LWS_CLOSE_STATUS_NOSTATUS) {
295
296 lwsl_debug("sending close indication...\n");
297
298 /* make valgrind happy */
299 memset(buf, 0, sizeof(buf));
300 n = libwebsocket_write(wsi,
301 &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
302 0, LWS_WRITE_CLOSE);
303 if (!n) {
304 /*
305 * we have sent a nice protocol level indication we
306 * now wish to close, we should not send anything more
307 */
308
309 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
310
311 /*
312 * ...and we should wait for a reply for a bit
313 * out of politeness
314 */
315
316 libwebsocket_set_timeout(wsi,
317 PENDING_TIMEOUT_CLOSE_ACK, 1);
318
319 lwsl_debug("sent close indication, awaiting ack\n");
320
321 return;
322 }
323
324 lwsl_info("close: sending close packet failed, hanging up\n");
325
326 /* else, the send failed and we should just hang up */
327 }
328
329#ifndef LWS_NO_EXTENSIONS
330just_kill_connection:
331#endif
332
333 lwsl_debug("close: just_kill_connection\n");
334
335 /*
336 * we won't be servicing or receiving anything further from this guy
337 * delete socket from the internal poll list if still present
338 */
339
340 remove_wsi_socket_from_fds(context, wsi);
341
342 wsi->state = WSI_STATE_DEAD_SOCKET;
343
344 if ((old_state == WSI_STATE_ESTABLISHED ||
345 wsi->mode == LWS_CONNMODE_WS_SERVING ||
346 wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
347
348 if (wsi->u.ws.rx_user_buffer) {
349 free(wsi->u.ws.rx_user_buffer);
350 wsi->u.ws.rx_user_buffer = NULL;
351 }
352 if (wsi->u.ws.rxflow_buffer) {
353 free(wsi->u.ws.rxflow_buffer);
354 wsi->u.ws.rxflow_buffer = NULL;
355 }
356 }
357
358 /* tell the user it's all over for this guy */
359
360 if (wsi->protocol && wsi->protocol->callback &&
361 ((old_state == WSI_STATE_ESTABLISHED) ||
362 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
363 (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
364 lwsl_debug("calling back CLOSED\n");
365 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
366 wsi->user_space, NULL, 0);
367 } else
368 lwsl_debug("not calling back closed\n");
369
370#ifndef LWS_NO_EXTENSIONS
371 /* deallocate any active extension contexts */
372
373 for (n = 0; n < wsi->count_active_extensions; n++) {
374 if (!wsi->active_extensions[n]->callback)
375 continue;
376
377 wsi->active_extensions[n]->callback(context,
378 wsi->active_extensions[n], wsi,
379 LWS_EXT_CALLBACK_DESTROY,
380 wsi->active_extensions_user[n], NULL, 0);
381
382 free(wsi->active_extensions_user[n]);
383 }
384
385 /*
386 * inform all extensions in case they tracked this guy out of band
387 * even though not active on him specifically
388 */
389
390 ext = context->extensions;
391 while (ext && ext->callback) {
392 ext->callback(context, ext, wsi,
393 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
394 NULL, NULL, 0);
395 ext++;
396 }
397#endif
398
399/* lwsl_info("closing fd=%d\n", wsi->sock); */
400
401#ifdef LWS_OPENSSL_SUPPORT
402 if (wsi->ssl) {
403 n = SSL_get_fd(wsi->ssl);
404 SSL_shutdown(wsi->ssl);
405 compatible_close(n);
406 SSL_free(wsi->ssl);
407 } else {
408#endif
409 if (wsi->sock) {
410 n = shutdown(wsi->sock, SHUT_RDWR);
411 if (n)
412 lwsl_debug("closing: shutdown returned %d\n",
413 errno);
414
415 n = compatible_close(wsi->sock);
416 if (n)
417 lwsl_debug("closing: close returned %d\n",
418 errno);
419 }
420#ifdef LWS_OPENSSL_SUPPORT
421 }
422#endif
423 if (wsi->protocol && wsi->protocol->per_session_data_size &&
424 wsi->user_space) /* user code may own */
425 free(wsi->user_space);
426
427 free(wsi);
428}
429
430/**
431 * libwebsockets_get_peer_addresses() - Get client address information
432 * @context: Libwebsockets context
433 * @wsi: Local struct libwebsocket associated with
434 * @fd: Connection socket descriptor
435 * @name: Buffer to take client address name
436 * @name_len: Length of client address name buffer
437 * @rip: Buffer to take client address IP qotted quad
438 * @rip_len: Length of client address IP buffer
439 *
440 * This function fills in @name and @rip with the name and IP of
441 * the client connected with socket descriptor @fd. Names may be
442 * truncated if there is not enough room. If either cannot be
443 * determined, they will be returned as valid zero-length strings.
444 */
445
446void
447libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
448 struct libwebsocket *wsi, int fd, char *name, int name_len,
449 char *rip, int rip_len)
450{
451 unsigned int len;
452 struct sockaddr_in sin;
453 struct hostent *host;
454 struct hostent *host1;
455 char ip[128];
456 unsigned char *p;
457 int n;
458 int ret = -1;
459#ifdef AF_LOCAL
460 struct sockaddr_un *un;
461#endif
462
463 rip[0] = '\0';
464 name[0] = '\0';
465
466 lws_latency_pre(context, wsi);
467
468 len = sizeof(sin);
469 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
470 perror("getpeername");
471 goto bail;
472 }
473
474 host = gethostbyaddr((char *) &sin.sin_addr, sizeof(sin.sin_addr),
475 AF_INET);
476 if (host == NULL) {
477 perror("gethostbyaddr");
478 goto bail;
479 }
480
481 strncpy(name, host->h_name, name_len);
482 name[name_len - 1] = '\0';
483
484 host1 = gethostbyname(host->h_name);
485 if (host1 == NULL)
486 goto bail;
487 p = (unsigned char *)host1;
488 n = 0;
489 while (p != NULL) {
490 p = (unsigned char *)host1->h_addr_list[n++];
491 if (p == NULL)
492 continue;
493 if ((host1->h_addrtype != AF_INET)
494#ifdef AF_LOCAL
495 && (host1->h_addrtype != AF_LOCAL)
496#endif
497 )
498 continue;
499
500 if (host1->h_addrtype == AF_INET)
501 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
502#ifdef AF_LOCAL
503 else {
504 un = (struct sockaddr_un *)p;
505 strncpy(ip, un->sun_path, sizeof(ip) - 1);
506 ip[sizeof(ip) - 1] = '\0';
507 }
508#endif
509 p = NULL;
510 strncpy(rip, ip, rip_len);
511 rip[rip_len - 1] = '\0';
512 }
513
514 ret = 0;
515bail:
516 lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
517}
518
519int libwebsockets_get_random(struct libwebsocket_context *context,
520 void *buf, int len)
521{
522 int n;
523 char *p = (char *)buf;
524
525#ifdef WIN32
526 for (n = 0; n < len; n++)
527 p[n] = (unsigned char)rand();
528#else
529 n = read(context->fd_random, p, len);
530#endif
531
532 return n;
533}
534
535int lws_set_socket_options(struct libwebsocket_context *context, int fd)
536{
537 int optval = 1;
538 socklen_t optlen = sizeof(optval);
539#ifdef WIN32
540 unsigned long optl = 0;
541#endif
542#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
543 struct protoent *tcp_proto;
544#endif
545
546 if (context->ka_time) {
547 /* enable keepalive on this socket */
548 optval = 1;
549 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
550 (const void *)&optval, optlen) < 0)
551 return 1;
552
553#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
554
555 /*
556 * didn't find a way to set these per-socket, need to
557 * tune kernel systemwide values
558 */
559#elif WIN32
560 {
561 DWORD dwBytesRet;
562 struct tcp_keepalive alive;
563 alive.onoff = TRUE;
564 alive.keepalivetime = context->ka_time;
565 alive.keepaliveinterval = context->ka_interval;
566
567 if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
568 NULL, 0, &dwBytesRet, NULL, NULL))
569 return 1;
570 }
571#else
572 /* set the keepalive conditions we want on it too */
573 optval = context->ka_time;
574 if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE,
575 (const void *)&optval, optlen) < 0)
576 return 1;
577
578 optval = context->ka_probes;
579 if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL,
580 (const void *)&optval, optlen) < 0)
581 return 1;
582
583 optval = context->ka_interval;
584 if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT,
585 (const void *)&optval, optlen) < 0)
586 return 1;
587#endif
588 }
589
590 /* Disable Nagle */
591 optval = 1;
592#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
593 setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
594#else
595 tcp_proto = getprotobyname("TCP");
596 setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen);
597#endif
598
599 /* We are nonblocking... */
600#ifdef WIN32
601 ioctlsocket(fd, FIONBIO, &optl);
602#else
603 fcntl(fd, F_SETFL, O_NONBLOCK);
604#endif
605
606 return 0;
607}
608
609int lws_send_pipe_choked(struct libwebsocket *wsi)
610{
611 struct pollfd fds;
612
613 fds.fd = wsi->sock;
614 fds.events = POLLOUT;
615 fds.revents = 0;
616
617 if (poll(&fds, 1, 0) != 1)
618 return 1;
619
620 if ((fds.revents & POLLOUT) == 0)
621 return 1;
622
623 /* okay to send another packet without blocking */
624
625 return 0;
626}
627
628int
629lws_handle_POLLOUT_event(struct libwebsocket_context *context,
630 struct libwebsocket *wsi, struct pollfd *pollfd)
631{
632 int n;
633
634#ifndef LWS_NO_EXTENSIONS
635 struct lws_tokens eff_buf;
636 int ret;
637 int m;
638 int handled = 0;
639
640 for (n = 0; n < wsi->count_active_extensions; n++) {
641 if (!wsi->active_extensions[n]->callback)
642 continue;
643
644 m = wsi->active_extensions[n]->callback(context,
645 wsi->active_extensions[n], wsi,
646 LWS_EXT_CALLBACK_IS_WRITEABLE,
647 wsi->active_extensions_user[n], NULL, 0);
648 if (m > handled)
649 handled = m;
650 }
651
652 if (handled == 1)
653 goto notify_action;
654
655 if (!wsi->extension_data_pending || handled == 2)
656 goto user_service;
657
658 /*
659 * check in on the active extensions, see if they
660 * had pending stuff to spill... they need to get the
661 * first look-in otherwise sequence will be disordered
662 *
663 * NULL, zero-length eff_buf means just spill pending
664 */
665
666 ret = 1;
667 while (ret == 1) {
668
669 /* default to nobody has more to spill */
670
671 ret = 0;
672 eff_buf.token = NULL;
673 eff_buf.token_len = 0;
674
675 /* give every extension a chance to spill */
676
677 for (n = 0; n < wsi->count_active_extensions; n++) {
678 m = wsi->active_extensions[n]->callback(
679 wsi->protocol->owning_server,
680 wsi->active_extensions[n], wsi,
681 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
682 wsi->active_extensions_user[n], &eff_buf, 0);
683 if (m < 0) {
684 lwsl_err("ext reports fatal error\n");
685 return -1;
686 }
687 if (m)
688 /*
689 * at least one extension told us he has more
690 * to spill, so we will go around again after
691 */
692 ret = 1;
693 }
694
695 /* assuming they gave us something to send, send it */
696
697 if (eff_buf.token_len) {
698 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
699 eff_buf.token_len))
700 return -1;
701 } else
702 continue;
703
704 /* no extension has more to spill */
705
706 if (!ret)
707 continue;
708
709 /*
710 * There's more to spill from an extension, but we just sent
711 * something... did that leave the pipe choked?
712 */
713
714 if (!lws_send_pipe_choked(wsi))
715 /* no we could add more */
716 continue;
717
718 lwsl_info("choked in POLLOUT service\n");
719
720 /*
721 * Yes, he's choked. Leave the POLLOUT masked on so we will
722 * come back here when he is unchoked. Don't call the user
723 * callback to enforce ordering of spilling, he'll get called
724 * when we come back here and there's nothing more to spill.
725 */
726
727 return 0;
728 }
729
730 wsi->extension_data_pending = 0;
731
732user_service:
733#endif
734 /* one shot */
735
736 if (pollfd) {
737 pollfd->events &= ~POLLOUT;
738
739 /* external POLL support via protocol 0 */
740 context->protocols[0].callback(context, wsi,
741 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
742 (void *)(long)wsi->sock, NULL, POLLOUT);
743 }
744#ifndef LWS_NO_EXTENSIONS
745notify_action:
746#endif
747
748 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
749 n = LWS_CALLBACK_CLIENT_WRITEABLE;
750 else
751 n = LWS_CALLBACK_SERVER_WRITEABLE;
752
753 return user_callback_handle_rxflow(wsi->protocol->callback, context,
754 wsi, (enum libwebsocket_callback_reasons) n,
755 wsi->user_space, NULL, 0);
756}
757
758
759
760void
761libwebsocket_service_timeout_check(struct libwebsocket_context *context,
762 struct libwebsocket *wsi, unsigned int sec)
763{
764#ifndef LWS_NO_EXTENSIONS
765 int n;
766
767 /*
768 * if extensions want in on it (eg, we are a mux parent)
769 * give them a chance to service child timeouts
770 */
771
772 for (n = 0; n < wsi->count_active_extensions; n++)
773 wsi->active_extensions[n]->callback(
774 context, wsi->active_extensions[n],
775 wsi, LWS_EXT_CALLBACK_1HZ,
776 wsi->active_extensions_user[n], NULL, sec);
777
778#endif
779 if (!wsi->pending_timeout)
780 return;
781
782 /*
783 * if we went beyond the allowed time, kill the
784 * connection
785 */
786
787 if (sec > wsi->pending_timeout_limit) {
788 lwsl_info("TIMEDOUT WAITING\n");
789 libwebsocket_close_and_free_session(context,
790 wsi, LWS_CLOSE_STATUS_NOSTATUS);
791 }
792}
793
794/**
795 * libwebsocket_service_fd() - Service polled socket with something waiting
796 * @context: Websocket context
797 * @pollfd: The pollfd entry describing the socket fd and which events
798 * happened.
799 *
800 * This function takes a pollfd that has POLLIN or POLLOUT activity and
801 * services it according to the state of the associated
802 * struct libwebsocket.
803 *
804 * The one call deals with all "service" that might happen on a socket
805 * including listen accepts, http files as well as websocket protocol.
806 */
807
808int
809libwebsocket_service_fd(struct libwebsocket_context *context,
810 struct pollfd *pollfd)
811{
812 struct libwebsocket *wsi;
813 int n;
814 int m;
815 int listen_socket_fds_index = 0;
816 struct timeval tv;
817
818#ifndef LWS_NO_EXTENSIONS
819 int more = 1;
820#endif
821 struct lws_tokens eff_buf;
822
823 if (context->listen_service_fd)
824 listen_socket_fds_index = context->lws_lookup[
825 context->listen_service_fd]->position_in_fds_table;
826
827 /*
828 * you can call us with pollfd = NULL to just allow the once-per-second
829 * global timeout checks; if less than a second since the last check
830 * it returns immediately then.
831 */
832
833 gettimeofday(&tv, NULL);
834
835 if (context->last_timeout_check_s != tv.tv_sec) {
836 context->last_timeout_check_s = tv.tv_sec;
837
838 #ifndef WIN32
839 /* if our parent went down, don't linger around */
840 if (context->started_with_parent &&
841 kill(context->started_with_parent, 0) < 0)
842 kill(getpid(), SIGTERM);
843 #endif
844
845 /* global timeout check once per second */
846
847 for (n = 0; n < context->fds_count; n++) {
848 struct libwebsocket *new_wsi =
849 context->lws_lookup[context->fds[n].fd];
850 if (!new_wsi)
851 continue;
852 libwebsocket_service_timeout_check(context,
853 new_wsi, tv.tv_sec);
854 }
855 }
856
857 /* just here for timeout management? */
858
859 if (pollfd == NULL)
860 return 0;
861
862 /* no, here to service a socket descriptor */
863
864 /*
865 * deal with listen service piggybacking
866 * every listen_service_modulo services of other fds, we
867 * sneak one in to service the listen socket if there's anything waiting
868 *
869 * To handle connection storms, as found in ab, if we previously saw a
870 * pending connection here, it causes us to check again next time.
871 */
872
873 if (context->listen_service_fd && pollfd !=
874 &context->fds[listen_socket_fds_index]) {
875 context->listen_service_count++;
876 if (context->listen_service_extraseen ||
877 context->listen_service_count ==
878 context->listen_service_modulo) {
879 context->listen_service_count = 0;
880 m = 1;
881 if (context->listen_service_extraseen > 5)
882 m = 2;
883 while (m--) {
884 /*
885 * even with extpoll, we prepared this
886 * internal fds for listen
887 */
888 n = poll(&context->fds[listen_socket_fds_index],
889 1, 0);
890 if (n > 0) { /* there's a conn waiting for us */
891 libwebsocket_service_fd(context,
892 &context->
893 fds[listen_socket_fds_index]);
894 context->listen_service_extraseen++;
895 } else {
896 if (context->listen_service_extraseen)
897 context->
898 listen_service_extraseen--;
899 break;
900 }
901 }
902 }
903
904 }
905
906 /* okay, what we came here to do... */
907
908 wsi = context->lws_lookup[pollfd->fd];
909 if (wsi == NULL) {
910 if (pollfd->fd > 11)
911 lwsl_err("unexpected NULL wsi fd=%d fds_count=%d\n",
912 pollfd->fd, context->fds_count);
913 return 0;
914 }
915
916 switch (wsi->mode) {
917
918#ifndef LWS_NO_SERVER
919 case LWS_CONNMODE_HTTP_SERVING:
920 case LWS_CONNMODE_SERVER_LISTENER:
921 case LWS_CONNMODE_SSL_ACK_PENDING:
922 return lws_server_socket_service(context, wsi, pollfd);
923#endif
924
925 case LWS_CONNMODE_WS_SERVING:
926 case LWS_CONNMODE_WS_CLIENT:
927
928 /* handle session socket closed */
929
930 if (pollfd->revents & (POLLERR | POLLHUP)) {
931
932 lwsl_debug("Session Socket %p (fd=%d) dead\n",
933 (void *)wsi, pollfd->fd);
934
935 libwebsocket_close_and_free_session(context, wsi,
936 LWS_CLOSE_STATUS_NOSTATUS);
937 return 0;
938 }
939
940 /* the guy requested a callback when it was OK to write */
941
942 if ((pollfd->revents & POLLOUT) &&
943 wsi->state == WSI_STATE_ESTABLISHED)
944 if (lws_handle_POLLOUT_event(context, wsi,
945 pollfd) < 0) {
946 lwsl_info("libwebsocket_service_fd: closing\n");
947 libwebsocket_close_and_free_session(
948 context, wsi, LWS_CLOSE_STATUS_NORMAL);
949 return 0;
950 }
951
952
953 /* any incoming data ready? */
954
955 if (!(pollfd->revents & POLLIN))
956 break;
957
958#ifdef LWS_OPENSSL_SUPPORT
959read_pending:
960 if (wsi->ssl) {
961 eff_buf.token_len = SSL_read(wsi->ssl,
962 context->service_buffer,
963 sizeof(context->service_buffer));
964 if (!eff_buf.token_len) {
965 n = SSL_get_error(wsi->ssl, eff_buf.token_len);
966 lwsl_err("SSL_read returned 0 with reason %s\n",
967 ERR_error_string(n,
968 (char *)context->service_buffer));
969 }
970 } else
971#endif
972 eff_buf.token_len = recv(pollfd->fd,
973 context->service_buffer,
974 sizeof(context->service_buffer), 0);
975
976 if (eff_buf.token_len < 0) {
977 lwsl_debug("Socket read returned %d\n",
978 eff_buf.token_len);
979 if (errno != EINTR && errno != EAGAIN)
980 libwebsocket_close_and_free_session(context,
981 wsi, LWS_CLOSE_STATUS_NOSTATUS);
982 return 0;
983 }
984 if (!eff_buf.token_len) {
985 lwsl_info("closing connection due to 0 length read\n");
986 libwebsocket_close_and_free_session(context, wsi,
987 LWS_CLOSE_STATUS_NOSTATUS);
988 return 0;
989 }
990
991 /*
992 * give any active extensions a chance to munge the buffer
993 * before parse. We pass in a pointer to an lws_tokens struct
994 * prepared with the default buffer and content length that's in
995 * there. Rather than rewrite the default buffer, extensions
996 * that expect to grow the buffer can adapt .token to
997 * point to their own per-connection buffer in the extension
998 * user allocation. By default with no extensions or no
999 * extension callback handling, just the normal input buffer is
1000 * used then so it is efficient.
1001 */
1002
1003 eff_buf.token = (char *)context->service_buffer;
1004#ifndef LWS_NO_EXTENSIONS
1005 more = 1;
1006 while (more) {
1007
1008 more = 0;
1009
1010 for (n = 0; n < wsi->count_active_extensions; n++) {
1011 m = wsi->active_extensions[n]->callback(context,
1012 wsi->active_extensions[n], wsi,
1013 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
1014 wsi->active_extensions_user[n],
1015 &eff_buf, 0);
1016 if (m < 0) {
1017 lwsl_ext(
1018 "Extension reports fatal error\n");
1019 libwebsocket_close_and_free_session(
1020 context, wsi,
1021 LWS_CLOSE_STATUS_NOSTATUS);
1022 return 0;
1023 }
1024 if (m)
1025 more = 1;
1026 }
1027#endif
1028 /* service incoming data */
1029
1030 if (eff_buf.token_len) {
1031 n = libwebsocket_read(context, wsi,
1032 (unsigned char *)eff_buf.token,
1033 eff_buf.token_len);
1034 if (n < 0)
1035 /* we closed wsi */
1036 return 0;
1037 }
1038#ifndef LWS_NO_EXTENSIONS
1039 eff_buf.token = NULL;
1040 eff_buf.token_len = 0;
1041 }
1042#endif
1043
1044#ifdef LWS_OPENSSL_SUPPORT
1045 if (wsi->ssl && SSL_pending(wsi->ssl))
1046 goto read_pending;
1047#endif
1048 break;
1049
1050 default:
1051#ifdef LWS_NO_CLIENT
1052 break;
1053#else
1054 return lws_client_socket_service(context, wsi, pollfd);
1055#endif
1056 }
1057
1058 return 0;
1059}
1060
1061
1062/**
1063 * libwebsocket_context_destroy() - Destroy the websocket context
1064 * @context: Websocket context
1065 *
1066 * This function closes any active connections and then frees the
1067 * context. After calling this, any further use of the context is
1068 * undefined.
1069 */
1070void
1071libwebsocket_context_destroy(struct libwebsocket_context *context)
1072{
1073#ifndef LWS_NO_EXTENSIONS
1074 int n;
1075 int m;
1076 struct libwebsocket_extension *ext;
1077 struct libwebsocket_protocols *protocol = context->protocols;
1078
1079#ifdef LWS_LATENCY
1080 if (context->worst_latency_info[0])
1081 lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
1082#endif
1083
1084 for (n = 0; n < context->fds_count; n++) {
1085 struct libwebsocket *wsi =
1086 context->lws_lookup[context->fds[n].fd];
1087 libwebsocket_close_and_free_session(context,
1088 wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
1089 n--;
1090 }
1091
1092 /*
1093 * give all extensions a chance to clean up any per-context
1094 * allocations they might have made
1095 */
1096
1097 ext = context->extensions;
1098 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
1099 if (context->listen_port)
1100 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
1101 while (ext && ext->callback) {
1102 ext->callback(context, ext, NULL,
1103 (enum libwebsocket_extension_callback_reasons)m,
1104 NULL, NULL, 0);
1105 ext++;
1106 }
1107
1108 /*
1109 * inform all the protocols that they are done and will have no more
1110 * callbacks
1111 */
1112
1113 while (protocol->callback) {
1114 protocol->callback(context, NULL, LWS_CALLBACK_PROTOCOL_DESTROY,
1115 NULL, NULL, 0);
1116 protocol++;
1117 }
1118
1119#endif
1120
1121#ifdef WIN32
1122#else
1123 close(context->fd_random);
1124#endif
1125
1126#ifdef LWS_OPENSSL_SUPPORT
1127 if (context->ssl_ctx)
1128 SSL_CTX_free(context->ssl_ctx);
1129 if (context->ssl_client_ctx)
1130 SSL_CTX_free(context->ssl_client_ctx);
1131
1132 ERR_remove_state(0);
1133 ERR_free_strings();
1134 EVP_cleanup();
1135 CRYPTO_cleanup_all_ex_data();
1136#endif
1137
1138 if (context->fds)
1139 free(context->fds);
1140 if (context->lws_lookup)
1141 free(context->lws_lookup);
1142
1143 free(context);
1144
1145#ifdef WIN32
1146 WSACleanup();
1147#endif
1148}
1149
1150/**
1151 * libwebsocket_context_user() - get the user data associated with the context
1152 * @context: Websocket context
1153 *
1154 * This returns the optional user allocation that can be attached to
1155 * the context the sockets live in at context_create time. It's a way
1156 * to let all sockets serviced in the same context share data without
1157 * using globals statics in the user code.
1158 */
1159LWS_EXTERN void *
1160libwebsocket_context_user(struct libwebsocket_context *context)
1161{
1162 return context->user_space;
1163}
1164
1165/**
1166 * libwebsocket_service() - Service any pending websocket activity
1167 * @context: Websocket context
1168 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
1169 * service otherwise block and service immediately, returning
1170 * after the timeout if nothing needed service.
1171 *
1172 * This function deals with any pending websocket traffic, for three
1173 * kinds of event. It handles these events on both server and client
1174 * types of connection the same.
1175 *
1176 * 1) Accept new connections to our context's server
1177 *
1178 * 2) Call the receive callback for incoming frame data received by
1179 * server or client connections.
1180 *
1181 * You need to call this service function periodically to all the above
1182 * functions to happen; if your application is single-threaded you can
1183 * just call it in your main event loop.
1184 *
1185 * Alternatively you can fork a new process that asynchronously handles
1186 * calling this service in a loop. In that case you are happy if this
1187 * call blocks your thread until it needs to take care of something and
1188 * would call it with a large nonzero timeout. Your loop then takes no
1189 * CPU while there is nothing happening.
1190 *
1191 * If you are calling it in a single-threaded app, you don't want it to
1192 * wait around blocking other things in your loop from happening, so you
1193 * would call it with a timeout_ms of 0, so it returns immediately if
1194 * nothing is pending, or as soon as it services whatever was pending.
1195 */
1196
1197int
1198libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
1199{
1200 int n;
1201
1202 /* stay dead once we are dead */
1203
1204 if (context == NULL)
1205 return 1;
1206
1207 /* wait for something to need service */
1208
1209 n = poll(context->fds, context->fds_count, timeout_ms);
1210 if (n == 0) /* poll timeout */
1211 return 0;
1212
1213 if (n < 0)
1214 return -1;
1215
1216 /* any socket with events to service? */
1217
1218 for (n = 0; n < context->fds_count; n++)
1219 if (context->fds[n].revents)
1220 if (libwebsocket_service_fd(context,
1221 &context->fds[n]) < 0)
1222 return -1;
1223 return 0;
1224}
1225
1226#ifndef LWS_NO_EXTENSIONS
1227int
1228lws_any_extension_handled(struct libwebsocket_context *context,
1229 struct libwebsocket *wsi,
1230 enum libwebsocket_extension_callback_reasons r,
1231 void *v, size_t len)
1232{
1233 int n;
1234 int handled = 0;
1235
1236 /* maybe an extension will take care of it for us */
1237
1238 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
1239 if (!wsi->active_extensions[n]->callback)
1240 continue;
1241
1242 handled |= wsi->active_extensions[n]->callback(context,
1243 wsi->active_extensions[n], wsi,
1244 r, wsi->active_extensions_user[n], v, len);
1245 }
1246
1247 return handled;
1248}
1249
1250
1251void *
1252lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
1253 struct libwebsocket_extension *ext)
1254{
1255 int n = 0;
1256
1257 if (wsi == NULL)
1258 return NULL;
1259
1260 while (n < wsi->count_active_extensions) {
1261 if (wsi->active_extensions[n] != ext) {
1262 n++;
1263 continue;
1264 }
1265 return wsi->active_extensions_user[n];
1266 }
1267
1268 return NULL;
1269}
1270#endif
1271
1272/**
1273 * libwebsocket_callback_on_writable() - Request a callback when this socket
1274 * becomes able to be written to without
1275 * blocking
1276 *
1277 * @context: libwebsockets context
1278 * @wsi: Websocket connection instance to get callback for
1279 */
1280
1281int
1282libwebsocket_callback_on_writable(struct libwebsocket_context *context,
1283 struct libwebsocket *wsi)
1284{
1285#ifndef LWS_NO_EXTENSIONS
1286 int n;
1287 int handled = 0;
1288
1289 /* maybe an extension will take care of it for us */
1290
1291 for (n = 0; n < wsi->count_active_extensions; n++) {
1292 if (!wsi->active_extensions[n]->callback)
1293 continue;
1294
1295 handled |= wsi->active_extensions[n]->callback(context,
1296 wsi->active_extensions[n], wsi,
1297 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
1298 wsi->active_extensions_user[n], NULL, 0);
1299 }
1300
1301 if (handled)
1302 return 1;
1303#endif
1304 if (wsi->position_in_fds_table < 0) {
1305 lwsl_err("libwebsocket_callback_on_writable: failed to find socket %d\n",
1306 wsi->sock);
1307 return -1;
1308 }
1309
1310 context->fds[wsi->position_in_fds_table].events |= POLLOUT;
1311
1312 /* external POLL support via protocol 0 */
1313 context->protocols[0].callback(context, wsi,
1314 LWS_CALLBACK_SET_MODE_POLL_FD,
1315 (void *)(long)wsi->sock, NULL, POLLOUT);
1316
1317 return 1;
1318}
1319
1320/**
1321 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
1322 * all connections using the given protocol when it
1323 * becomes possible to write to each socket without
1324 * blocking in turn.
1325 *
1326 * @protocol: Protocol whose connections will get callbacks
1327 */
1328
1329int
1330libwebsocket_callback_on_writable_all_protocol(
1331 const struct libwebsocket_protocols *protocol)
1332{
1333 struct libwebsocket_context *context = protocol->owning_server;
1334 int n;
1335 struct libwebsocket *wsi;
1336
1337 for (n = 0; n < context->fds_count; n++) {
1338 wsi = context->lws_lookup[context->fds[n].fd];
1339 if (!wsi)
1340 continue;
1341 if (wsi->protocol == protocol)
1342 libwebsocket_callback_on_writable(context, wsi);
1343 }
1344
1345 return 0;
1346}
1347
1348/**
1349 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
1350 *
1351 * You will not need this unless you are doing something special
1352 *
1353 * @wsi: Websocket connection instance
1354 * @reason: timeout reason
1355 * @secs: how many seconds
1356 */
1357
1358void
1359libwebsocket_set_timeout(struct libwebsocket *wsi,
1360 enum pending_timeout reason, int secs)
1361{
1362 struct timeval tv;
1363
1364 gettimeofday(&tv, NULL);
1365
1366 wsi->pending_timeout_limit = tv.tv_sec + secs;
1367 wsi->pending_timeout = reason;
1368}
1369
1370
1371/**
1372 * libwebsocket_get_socket_fd() - returns the socket file descriptor
1373 *
1374 * You will not need this unless you are doing something special
1375 *
1376 * @wsi: Websocket connection instance
1377 */
1378
1379int
1380libwebsocket_get_socket_fd(struct libwebsocket *wsi)
1381{
1382 return wsi->sock;
1383}
1384
1385#ifdef LWS_LATENCY
1386void
1387lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
1388 const char *action, int ret, int completed)
1389{
1390 struct timeval tv;
1391 unsigned long u;
1392 char buf[256];
1393
1394 gettimeofday(&tv, NULL);
1395
1396 u = (tv.tv_sec * 1000000) + tv.tv_usec;
1397
1398 if (action) {
1399 if (completed) {
1400 if (wsi->action_start == wsi->latency_start)
1401 sprintf(buf,
1402 "Completion first try lat %luus: %p: ret %d: %s\n",
1403 u - wsi->latency_start,
1404 (void *)wsi, ret, action);
1405 else
1406 sprintf(buf,
1407 "Completion %luus: lat %luus: %p: ret %d: %s\n",
1408 u - wsi->action_start,
1409 u - wsi->latency_start,
1410 (void *)wsi, ret, action);
1411 wsi->action_start = 0;
1412 } else
1413 sprintf(buf, "lat %luus: %p: ret %d: %s\n",
1414 u - wsi->latency_start,
1415 (void *)wsi, ret, action);
1416 if (u - wsi->latency_start > context->worst_latency) {
1417 context->worst_latency = u - wsi->latency_start;
1418 strcpy(context->worst_latency_info, buf);
1419 }
1420 lwsl_latency("%s", buf);
1421 } else {
1422 wsi->latency_start = u;
1423 if (!wsi->action_start)
1424 wsi->action_start = u;
1425 }
1426}
1427#endif
1428
1429#ifdef LWS_NO_SERVER
1430int
1431_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1432{
1433 return 0;
1434}
1435#else
1436int
1437_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1438{
1439 struct libwebsocket_context *context = wsi->protocol->owning_server;
1440 int n;
1441
1442 if (!(wsi->u.ws.rxflow_change_to & 2))
1443 return 0;
1444
1445 wsi->u.ws.rxflow_change_to &= ~2;
1446
1447 lwsl_info("rxflow: wsi %p change_to %d\n",
1448 wsi, wsi->u.ws.rxflow_change_to);
1449
1450 /* if we're letting it come again, did we interrupt anything? */
1451 if ((wsi->u.ws.rxflow_change_to & 1) && wsi->u.ws.rxflow_buffer) {
1452 n = libwebsocket_interpret_incoming_packet(wsi, NULL, 0);
1453 if (n < 0) {
1454 lwsl_info("libwebsocket_rx_flow_control: close req\n");
1455 return -1;
1456 }
1457 if (n)
1458 /* oh he stuck again, do nothing */
1459 return 0;
1460 }
1461
1462 if (wsi->u.ws.rxflow_change_to & 1)
1463 context->fds[wsi->position_in_fds_table].events |= POLLIN;
1464 else
1465 context->fds[wsi->position_in_fds_table].events &= ~POLLIN;
1466
1467 if (wsi->u.ws.rxflow_change_to & 1)
1468 /* external POLL support via protocol 0 */
1469 context->protocols[0].callback(context, wsi,
1470 LWS_CALLBACK_SET_MODE_POLL_FD,
1471 (void *)(long)wsi->sock, NULL, POLLIN);
1472 else
1473 /* external POLL support via protocol 0 */
1474 context->protocols[0].callback(context, wsi,
1475 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
1476 (void *)(long)wsi->sock, NULL, POLLIN);
1477
1478 return 1;
1479}
1480#endif
1481
1482/**
1483 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
1484 * receieved packets.
1485 *
1486 * If the output side of a server process becomes choked, this allows flow
1487 * control for the input side.
1488 *
1489 * @wsi: Websocket connection instance to get callback for
1490 * @enable: 0 = disable read servicing for this connection, 1 = enable
1491 */
1492
1493int
1494libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
1495{
1496 wsi->u.ws.rxflow_change_to = 2 | !!enable;
1497
1498 return 0;
1499}
1500
1501
1502/**
1503 * libwebsocket_canonical_hostname() - returns this host's hostname
1504 *
1505 * This is typically used by client code to fill in the host parameter
1506 * when making a client connection. You can only call it after the context
1507 * has been created.
1508 *
1509 * @context: Websocket context
1510 */
1511
1512
1513extern const char *
1514libwebsocket_canonical_hostname(struct libwebsocket_context *context)
1515{
1516 return (const char *)context->canonical_hostname;
1517}
1518
1519
1520static void sigpipe_handler(int x)
1521{
1522}
1523
1524#ifdef LWS_OPENSSL_SUPPORT
1525static int
1526OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
1527{
1528
1529 SSL *ssl;
1530 int n;
1531 struct libwebsocket_context *context;
1532
1533 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
1534 SSL_get_ex_data_X509_STORE_CTX_idx());
1535
1536 /*
1537 * !!! nasty openssl requires the index to come as a library-scope
1538 * static
1539 */
1540 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
1541
1542 n = context->protocols[0].callback(NULL, NULL,
1543 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
1544 x509_ctx, ssl, preverify_ok);
1545
1546 /* convert return code from 0 = OK to 1 = OK */
1547
1548 if (!n)
1549 n = 1;
1550 else
1551 n = 0;
1552
1553 return n;
1554}
1555#endif
1556
1557int user_callback_handle_rxflow(callback_function callback_function,
1558 struct libwebsocket_context *context,
1559 struct libwebsocket *wsi,
1560 enum libwebsocket_callback_reasons reason, void *user,
1561 void *in, size_t len)
1562{
1563 int n;
1564
1565 n = callback_function(context, wsi, reason, user, in, len);
1566 if (!n)
1567 n = _libwebsocket_rx_flow_control(wsi);
1568
1569 return n;
1570}
1571
1572
1573/**
1574 * libwebsocket_create_context() - Create the websocket handler
1575 * @info: pointer to struct with parameters
1576 *
1577 * This function creates the listening socket (if serving) and takes care
1578 * of all initialization in one step.
1579 *
1580 * After initialization, it returns a struct libwebsocket_context * that
1581 * represents this server. After calling, user code needs to take care
1582 * of calling libwebsocket_service() with the context pointer to get the
1583 * server's sockets serviced. This can be done in the same process context
1584 * or a forked process, or another thread,
1585 *
1586 * The protocol callback functions are called for a handful of events
1587 * including http requests coming in, websocket connections becoming
1588 * established, and data arriving; it's also called periodically to allow
1589 * async transmission.
1590 *
1591 * HTTP requests are sent always to the FIRST protocol in @protocol, since
1592 * at that time websocket protocol has not been negotiated. Other
1593 * protocols after the first one never see any HTTP callack activity.
1594 *
1595 * The server created is a simple http server by default; part of the
1596 * websocket standard is upgrading this http connection to a websocket one.
1597 *
1598 * This allows the same server to provide files like scripts and favicon /
1599 * images or whatever over http and dynamic data over websockets all in
1600 * one place; they're all handled in the user callback.
1601 */
1602
1603struct libwebsocket_context *
1604libwebsocket_create_context(struct lws_context_creation_info *info)
1605{
1606 struct libwebsocket_context *context = NULL;
1607 char *p;
1608#ifndef LWS_NO_SERVER
1609 int n;
1610 int opt = 1;
1611 struct libwebsocket *wsi;
1612 struct sockaddr_in serv_addr;
1613#endif
1614#ifndef LWS_NO_EXTENSIONS
1615 int m;
1616 struct libwebsocket_extension *ext;
1617#endif
1618
1619#ifdef LWS_OPENSSL_SUPPORT
1620 SSL_METHOD *method;
1621#endif
1622
1623#ifndef LWS_NO_DAEMONIZE
1624 int pid_daemon = get_daemonize_pid();
1625#endif
1626
1627 lwsl_notice("Initial logging level %d\n", log_level);
1628 lwsl_notice("Library version: %s\n", library_version);
1629 lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n",
1630 LWS_MAX_HEADER_NAME_LENGTH);
1631 lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
1632 lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
1633#ifndef LWS_NO_EXTENSIONS
1634 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n",
1635 LWS_MAX_EXTENSIONS_ACTIVE);
1636#else
1637 lwsl_notice(" Configured without extension support\n");
1638#endif
1639 lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
1640 lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
1641 lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
1642 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
1643 lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
1644
1645#ifdef _WIN32
1646 {
1647 WORD wVersionRequested;
1648 WSADATA wsaData;
1649 int err;
1650 HMODULE wsdll;
1651
1652 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
1653 wVersionRequested = MAKEWORD(2, 2);
1654
1655 err = WSAStartup(wVersionRequested, &wsaData);
1656 if (err != 0) {
1657 /* Tell the user that we could not find a usable */
1658 /* Winsock DLL. */
1659 lwsl_err("WSAStartup failed with error: %d\n", err);
1660 return NULL;
1661 }
1662
1663 /* default to a poll() made out of select() */
1664 poll = emulated_poll;
1665
1666 /* if windows socket lib available, use his WSAPoll */
1667 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
1668 if (wsdll)
1669 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
1670
1671 /* Finally fall back to emulated poll if all else fails */
1672 if (!poll)
1673 poll = emulated_poll;
1674 }
1675#endif
1676
1677 context = (struct libwebsocket_context *)
1678 malloc(sizeof(struct libwebsocket_context));
1679 if (!context) {
1680 lwsl_err("No memory for websocket context\n");
1681 return NULL;
1682 }
1683 memset(context, 0, sizeof(*context));
1684#ifndef LWS_NO_DAEMONIZE
1685 context->started_with_parent = pid_daemon;
1686 lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
1687#endif
1688
1689 context->listen_service_extraseen = 0;
1690 context->protocols = info->protocols;
1691 context->listen_port = info->port;
1692 context->http_proxy_port = 0;
1693 context->http_proxy_address[0] = '\0';
1694 context->options = info->options;
1695 /* to reduce this allocation, */
1696 context->max_fds = getdtablesize();
1697 lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n",
1698 sizeof(struct libwebsocket_context),
1699 sizeof(struct pollfd) + sizeof(struct libwebsocket *),
1700 context->max_fds,
1701 sizeof(struct libwebsocket_context) +
1702 ((sizeof(struct pollfd) + sizeof(struct libwebsocket *)) *
1703 context->max_fds));
1704
1705 context->fds = (struct pollfd *)malloc(sizeof(struct pollfd) *
1706 context->max_fds);
1707 if (context->fds == NULL) {
1708 lwsl_err("Unable to allocate fds array for %d connections\n",
1709 context->max_fds);
1710 free(context);
1711 return NULL;
1712 }
1713 context->lws_lookup = (struct libwebsocket **)
1714 malloc(sizeof(struct libwebsocket *) * context->max_fds);
1715 if (context->lws_lookup == NULL) {
1716 lwsl_err(
1717 "Unable to allocate lws_lookup array for %d connections\n",
1718 context->max_fds);
1719 free(context->fds);
1720 free(context);
1721 return NULL;
1722 }
1723
1724 context->fds_count = 0;
1725#ifndef LWS_NO_EXTENSIONS
1726 context->extensions = info->extensions;
1727#endif
1728 context->last_timeout_check_s = 0;
1729 context->user_space = info->user;
1730
1731#ifdef WIN32
1732 context->fd_random = 0;
1733#else
1734 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
1735 if (context->fd_random < 0) {
1736 lwsl_err("Unable to open random device %s %d\n",
1737 SYSTEM_RANDOM_FILEPATH, context->fd_random);
1738 goto bail;
1739 }
1740#endif
1741
1742#ifdef LWS_OPENSSL_SUPPORT
1743 context->use_ssl = 0;
1744 context->ssl_ctx = NULL;
1745 context->ssl_client_ctx = NULL;
1746 openssl_websocket_private_data_index = 0;
1747#endif
1748
1749 strcpy(context->canonical_hostname, "unknown");
1750
1751#ifndef LWS_NO_SERVER
1752 if (!(info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) {
1753 /* find canonical hostname */
1754 gethostname((char *)context->canonical_hostname,
1755 sizeof(context->canonical_hostname) - 1);
1756
1757 lwsl_notice(" canonical_hostname = %s\n",
1758 context->canonical_hostname);
1759 }
1760#endif
1761
1762 /* split the proxy ads:port if given */
1763
1764 p = getenv("http_proxy");
1765 if (p) {
1766 strncpy(context->http_proxy_address, p,
1767 sizeof(context->http_proxy_address) - 1);
1768 context->http_proxy_address[
1769 sizeof(context->http_proxy_address) - 1] = '\0';
1770
1771 p = strchr(context->http_proxy_address, ':');
1772 if (p == NULL) {
1773 lwsl_err("http_proxy needs to be ads:port\n");
1774 goto bail;
1775 }
1776 *p = '\0';
1777 context->http_proxy_port = atoi(p + 1);
1778
1779 lwsl_notice(" Proxy %s:%u\n",
1780 context->http_proxy_address,
1781 context->http_proxy_port);
1782 }
1783
1784#ifndef LWS_NO_SERVER
1785 if (info->port) {
1786
1787#ifdef LWS_OPENSSL_SUPPORT
1788 context->use_ssl = info->ssl_cert_filepath != NULL &&
1789 info->ssl_private_key_filepath != NULL;
1790#ifdef USE_CYASSL
1791 lwsl_notice(" Compiled with CYASSL support\n");
1792#else
1793 lwsl_notice(" Compiled with OpenSSL support\n");
1794#endif
1795 if (context->use_ssl)
1796 lwsl_notice(" Using SSL mode\n");
1797 else
1798 lwsl_notice(" Using non-SSL mode\n");
1799
1800#else
1801 if (info->ssl_cert_filepath != NULL &&
1802 info->ssl_private_key_filepath != NULL) {
1803 lwsl_notice(" Not compiled for OpenSSl support!\n");
1804 goto bail;
1805 }
1806 lwsl_notice(" Compiled without SSL support\n");
1807#endif
1808
1809 lwsl_notice(
1810 " per-conn mem: %u + %u headers + protocol rx buf\n",
1811 sizeof(struct libwebsocket),
1812 sizeof(struct allocated_headers));
1813 }
1814#endif
1815
1816 /* ignore SIGPIPE */
1817#ifdef WIN32
1818#else
1819 signal(SIGPIPE, sigpipe_handler);
1820#endif
1821
1822
1823#ifdef LWS_OPENSSL_SUPPORT
1824
1825 /* basic openssl init */
1826
1827 SSL_library_init();
1828
1829 OpenSSL_add_all_algorithms();
1830 SSL_load_error_strings();
1831
1832 openssl_websocket_private_data_index =
1833 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
1834
1835 /*
1836 * Firefox insists on SSLv23 not SSLv3
1837 * Konq disables SSLv2 by default now, SSLv23 works
1838 */
1839
1840 method = (SSL_METHOD *)SSLv23_server_method();
1841 if (!method) {
1842 lwsl_err("problem creating ssl method: %s\n",
1843 ERR_error_string(ERR_get_error(),
1844 (char *)context->service_buffer));
1845 goto bail;
1846 }
1847 context->ssl_ctx = SSL_CTX_new(method); /* create context */
1848 if (!context->ssl_ctx) {
1849 lwsl_err("problem creating ssl context: %s\n",
1850 ERR_error_string(ERR_get_error(),
1851 (char *)context->service_buffer));
1852 goto bail;
1853 }
1854
1855#ifdef SSL_OP_NO_COMPRESSION
1856 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
1857#endif
1858 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
1859 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
1860
1861#ifndef LWS_NO_CLIENT
1862
1863 /* client context */
1864
1865 if (info->port == CONTEXT_PORT_NO_LISTEN) {
1866 method = (SSL_METHOD *)SSLv23_client_method();
1867 if (!method) {
1868 lwsl_err("problem creating ssl method: %s\n",
1869 ERR_error_string(ERR_get_error(),
1870 (char *)context->service_buffer));
1871 goto bail;
1872 }
1873 /* create context */
1874 context->ssl_client_ctx = SSL_CTX_new(method);
1875 if (!context->ssl_client_ctx) {
1876 lwsl_err("problem creating ssl context: %s\n",
1877 ERR_error_string(ERR_get_error(),
1878 (char *)context->service_buffer));
1879 goto bail;
1880 }
1881
1882#ifdef SSL_OP_NO_COMPRESSION
1883 SSL_CTX_set_options(context->ssl_client_ctx,
1884 SSL_OP_NO_COMPRESSION);
1885#endif
1886 SSL_CTX_set_options(context->ssl_client_ctx,
1887 SSL_OP_CIPHER_SERVER_PREFERENCE);
1888 SSL_CTX_set_cipher_list(context->ssl_client_ctx,
1889 CIPHERS_LIST_STRING);
1890
1891 /* openssl init for cert verification (for client sockets) */
1892 if (!info->ssl_ca_filepath) {
1893 if (!SSL_CTX_load_verify_locations(
1894 context->ssl_client_ctx, NULL,
1895 LWS_OPENSSL_CLIENT_CERTS))
1896 lwsl_err(
1897 "Unable to load SSL Client certs from %s "
1898 "(set by --with-client-cert-dir= "
1899 "in configure) -- client ssl isn't "
1900 "going to work", LWS_OPENSSL_CLIENT_CERTS);
1901 } else
1902 if (!SSL_CTX_load_verify_locations(
1903 context->ssl_client_ctx, info->ssl_ca_filepath,
1904 NULL))
1905 lwsl_err(
1906 "Unable to load SSL Client certs "
1907 "file from %s -- client ssl isn't "
1908 "going to work", info->ssl_ca_filepath);
1909
1910 /*
1911 * callback allowing user code to load extra verification certs
1912 * helping the client to verify server identity
1913 */
1914
1915 context->protocols[0].callback(context, NULL,
1916 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
1917 context->ssl_client_ctx, NULL, 0);
1918 }
1919#endif
1920
1921 /* as a server, are we requiring clients to identify themselves? */
1922
1923 if (info->options &
1924 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
1925
1926 /* absolutely require the client cert */
1927
1928 SSL_CTX_set_verify(context->ssl_ctx,
1929 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1930 OpenSSL_verify_callback);
1931
1932 /*
1933 * give user code a chance to load certs into the server
1934 * allowing it to verify incoming client certs
1935 */
1936
1937 context->protocols[0].callback(context, NULL,
1938 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
1939 context->ssl_ctx, NULL, 0);
1940 }
1941
1942 if (context->use_ssl) {
1943
1944 /* openssl init for server sockets */
1945
1946 /* set the local certificate from CertFile */
1947 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
1948 info->ssl_cert_filepath);
1949 if (n != 1) {
1950 lwsl_err("problem getting cert '%s': %s\n",
1951 info->ssl_cert_filepath,
1952 ERR_error_string(ERR_get_error(),
1953 (char *)context->service_buffer));
1954 goto bail;
1955 }
1956 /* set the private key from KeyFile */
1957 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
1958 info->ssl_private_key_filepath,
1959 SSL_FILETYPE_PEM) != 1) {
1960 lwsl_err("ssl problem getting key '%s': %s\n",
1961 info->ssl_private_key_filepath,
1962 ERR_error_string(ERR_get_error(),
1963 (char *)context->service_buffer));
1964 goto bail;
1965 }
1966 /* verify private key */
1967 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
1968 lwsl_err("Private SSL key doesn't match cert\n");
1969 goto bail;
1970 }
1971
1972 /* SSL is happy and has a cert it's content with */
1973 }
1974#endif
1975
1976 /* selftest */
1977
1978 if (lws_b64_selftest())
1979 goto bail;
1980
1981#ifndef LWS_NO_SERVER
1982 /* set up our external listening socket we serve on */
1983
1984 if (info->port) {
1985 int sockfd;
1986
1987 sockfd = socket(AF_INET, SOCK_STREAM, 0);
1988 if (sockfd < 0) {
1989 lwsl_err("ERROR opening socket\n");
1990 goto bail;
1991 }
1992
1993#ifndef WIN32
1994 /*
1995 * allow us to restart even if old sockets in TIME_WAIT
1996 * (REUSEADDR on Unix means, "don't hang on to this
1997 * address after the listener is closed." On Windows, though,
1998 * it means "don't keep other processes from binding to
1999 * this address while we're using it)
2000 */
2001 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2002 (const void *)&opt, sizeof(opt));
2003#endif
2004
2005 /* Disable Nagle */
2006 opt = 1;
2007 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2008 (const void *)&opt, sizeof(opt));
2009
2010 #ifdef WIN32
2011 opt = 0;
2012 ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt);
2013 #else
2014 fcntl(sockfd, F_SETFL, O_NONBLOCK);
2015 #endif
2016
2017 bzero((char *) &serv_addr, sizeof(serv_addr));
2018 serv_addr.sin_family = AF_INET;
2019 if (info->iface == NULL)
2020 serv_addr.sin_addr.s_addr = INADDR_ANY;
2021 else
2022 interface_to_sa(info->iface, &serv_addr,
2023 sizeof(serv_addr));
2024 serv_addr.sin_port = htons(info->port);
2025
2026 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2027 sizeof(serv_addr));
2028 if (n < 0) {
2029 lwsl_err("ERROR on binding to port %d (%d %d)\n",
2030 info->port, n, errno);
2031 close(sockfd);
2032 goto bail;
2033 }
2034
2035 wsi = (struct libwebsocket *)malloc(
2036 sizeof(struct libwebsocket));
2037 if (wsi == NULL) {
2038 lwsl_err("Out of mem\n");
2039 close(sockfd);
2040 goto bail;
2041 }
2042 memset(wsi, 0, sizeof(struct libwebsocket));
2043 wsi->sock = sockfd;
2044#ifndef LWS_NO_EXTENSIONS
2045 wsi->count_active_extensions = 0;
2046#endif
2047 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
2048
2049 insert_wsi_socket_into_fds(context, wsi);
2050
2051 context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
2052 context->listen_service_count = 0;
2053 context->listen_service_fd = sockfd;
2054
2055 listen(sockfd, LWS_SOMAXCONN);
2056 lwsl_notice(" Listening on port %d\n", info->port);
2057 }
2058#endif
2059
2060 /*
2061 * drop any root privs for this process
2062 * to listen on port < 1023 we would have needed root, but now we are
2063 * listening, we don't want the power for anything else
2064 */
2065#ifdef WIN32
2066#else
2067 if (info->gid != -1)
2068 if (setgid(info->gid))
2069 lwsl_warn("setgid: %s\n", strerror(errno));
2070 if (info->uid != -1)
2071 if (setuid(info->uid))
2072 lwsl_warn("setuid: %s\n", strerror(errno));
2073#endif
2074
2075 /* initialize supported protocols */
2076
2077 for (context->count_protocols = 0;
2078 info->protocols[context->count_protocols].callback;
2079 context->count_protocols++) {
2080
2081 lwsl_parser(" Protocol: %s\n",
2082 info->protocols[context->count_protocols].name);
2083
2084 info->protocols[context->count_protocols].owning_server =
2085 context;
2086 info->protocols[context->count_protocols].protocol_index =
2087 context->count_protocols;
2088
2089 /*
2090 * inform all the protocols that they are doing their one-time
2091 * initialization if they want to
2092 */
2093 info->protocols[context->count_protocols].callback(context,
2094 NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0);
2095 }
2096
2097#ifndef LWS_NO_EXTENSIONS
2098 /*
2099 * give all extensions a chance to create any per-context
2100 * allocations they need
2101 */
2102
2103 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
2104 if (info->port)
2105 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
2106
2107 if (info->extensions) {
2108 ext = info->extensions;
2109 while (ext->callback) {
2110 lwsl_ext(" Extension: %s\n", ext->name);
2111 ext->callback(context, ext, NULL,
2112 (enum libwebsocket_extension_callback_reasons)m,
2113 NULL, NULL, 0);
2114 ext++;
2115 }
2116 }
2117#endif
2118 return context;
2119
2120bail:
2121 libwebsocket_context_destroy(context);
2122 return NULL;
2123}
2124
2125/**
2126 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
2127 * connection.
2128 * @wsi: pointer to struct websocket you want to know the protocol of
2129 *
2130 *
2131 * Some apis can act on all live connections of a given protocol,
2132 * this is how you can get a pointer to the active protocol if needed.
2133 */
2134
2135const struct libwebsocket_protocols *
2136libwebsockets_get_protocol(struct libwebsocket *wsi)
2137{
2138 return wsi->protocol;
2139}
2140
2141int
2142libwebsocket_is_final_fragment(struct libwebsocket *wsi)
2143{
2144 return wsi->u.ws.final;
2145}
2146
2147unsigned char
2148libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
2149{
2150 return wsi->u.ws.rsv;
2151}
2152
2153void *
2154libwebsocket_ensure_user_space(struct libwebsocket *wsi)
2155{
2156 /* allocate the per-connection user memory (if any) */
2157
2158 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
2159 wsi->user_space = malloc(
2160 wsi->protocol->per_session_data_size);
2161 if (wsi->user_space == NULL) {
2162 lwsl_err("Out of memory for conn user space\n");
2163 return NULL;
2164 }
2165 memset(wsi->user_space, 0,
2166 wsi->protocol->per_session_data_size);
2167 }
2168 return wsi->user_space;
2169}
2170
2171static void lwsl_emit_stderr(int level, const char *line)
2172{
2173 char buf[300];
2174 struct timeval tv;
2175 int n;
2176
2177 gettimeofday(&tv, NULL);
2178
2179 buf[0] = '\0';
2180 for (n = 0; n < LLL_COUNT; n++)
2181 if (level == (1 << n)) {
2182 sprintf(buf, "[%ld:%04d] %s: ", tv.tv_sec,
2183 (int)(tv.tv_usec / 100), log_level_names[n]);
2184 break;
2185 }
2186
2187 fprintf(stderr, "%s%s", buf, line);
2188}
2189
2190#ifdef WIN32
2191void lwsl_emit_syslog(int level, const char *line)
2192{
2193 lwsl_emit_stderr(level, line);
2194}
2195#else
2196void lwsl_emit_syslog(int level, const char *line)
2197{
2198 int syslog_level = LOG_DEBUG;
2199
2200 switch (level) {
2201 case LLL_ERR:
2202 syslog_level = LOG_ERR;
2203 break;
2204 case LLL_WARN:
2205 syslog_level = LOG_WARNING;
2206 break;
2207 case LLL_NOTICE:
2208 syslog_level = LOG_NOTICE;
2209 break;
2210 case LLL_INFO:
2211 syslog_level = LOG_INFO;
2212 break;
2213 }
2214 syslog(syslog_level, "%s", line);
2215}
2216#endif
2217
2218void _lws_log(int filter, const char *format, ...)
2219{
2220 char buf[256];
2221 va_list ap;
2222
2223 if (!(log_level & filter))
2224 return;
2225
2226 va_start(ap, format);
2227 vsnprintf(buf, sizeof(buf), format, ap);
2228 buf[sizeof(buf) - 1] = '\0';
2229 va_end(ap);
2230
2231 lwsl_emit(filter, buf);
2232}
2233
2234/**
2235 * lws_set_log_level() - Set the logging bitfield
2236 * @level: OR together the LLL_ debug contexts you want output from
2237 * @log_emit_function: NULL to leave it as it is, or a user-supplied
2238 * function to perform log string emission instead of
2239 * the default stderr one.
2240 *
2241 * log level defaults to "err" and "warn" contexts enabled only and
2242 * emission on stderr.
2243 */
2244
2245void lws_set_log_level(int level, void (*log_emit_function)(int level,
2246 const char *line))
2247{
2248 log_level = level;
2249 if (log_emit_function)
2250 lwsl_emit = log_emit_function;
2251}
22520
=== removed directory '.pc/01-visibility.patch'
=== removed directory '.pc/01-visibility.patch/lib'
=== removed file '.pc/01-visibility.patch/lib/Makefile.am'
--- .pc/01-visibility.patch/lib/Makefile.am 2013-03-28 19:10:28 +0000
+++ .pc/01-visibility.patch/lib/Makefile.am 1970-01-01 00:00:00 +0000
@@ -1,89 +0,0 @@
1@applyhash@
2
3lib_LTLIBRARIES=libwebsockets.la
4include_HEADERS=libwebsockets.h
5dist_libwebsockets_la_SOURCES=libwebsockets.c \
6 parsers.c \
7 handshake.c \
8 libwebsockets.h \
9 base64-decode.c \
10 output.c \
11 private-libwebsockets.h
12
13if NO_EXTENSIONS
14else
15dist_libwebsockets_la_SOURCES+= extension.c \
16 extension-deflate-stream.c extension-deflate-stream.h \
17 extension-deflate-frame.c extension-deflate-frame.h
18endif
19
20if NO_DAEMONIZE
21else
22dist_libwebsockets_la_SOURCES+= daemonize.c
23endif
24
25if NO_CLIENT
26else
27dist_libwebsockets_la_SOURCES+= client.c \
28 client-parser.c \
29 client-handshake.c
30endif
31
32if NO_SERVER
33else
34dist_libwebsockets_la_SOURCES+= server.c \
35 server-handshake.c
36endif
37
38if USE_BUILTIN_GETIFADDRS
39dist_libwebsockets_la_SOURCES += getifaddrs.c
40endif
41
42if LIBCRYPTO
43else
44dist_libwebsockets_la_SOURCES += sha-1.c
45endif
46
47libwebsockets_la_CFLAGS=-Wall -std=gnu99 -pedantic
48libwebsockets_la_LDFLAGS=
49
50# uncomment below and use cat ./lib/.libs/*.su | sort -k2g | tac
51# to get a worst-first list of static stack usage if you have gcc 4.6+
52#libwebsockets_la_CFLAGS+= -fstack-usage
53
54if USE_CYASSL
55libwebsockets_la_LDFLAGS+= -lcyassl
56endif
57
58if DISABLE_DEBUG
59libwebsockets_la_CFLAGS+= -O4
60else
61libwebsockets_la_CFLAGS+= -O0 -g
62endif
63
64if MINGW
65libwebsockets_la_CFLAGS+= -w -I../win32port/win32helpers -I ../win32port/zlib/
66libwebsockets_la_LDFLAGS+= -lm -luser32 -ladvapi32 -lkernel32 -lgcc
67else
68libwebsockets_la_CFLAGS+= -rdynamic -fPIC -Werror
69# notice http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html has rules for how to bump this
70libwebsockets_la_LDFLAGS+= -version-info 3:0:0
71endif
72
73libwebsockets_la_CFLAGS+= -c \
74 -DINSTALL_DATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
75if NO_EXTENSIONS
76else
77libwebsockets_la_LDFLAGS+= -lz
78endif
79
80all-local:
81 ../scripts/kernel-doc -html \
82 *.c \
83 libwebsockets.h \
84 > ../libwebsockets-api-doc.html
85 ../scripts/kernel-doc -text \
86 *.c \
87 libwebsockets.h \
88 > ../libwebsockets-api-doc.txt
89
900
=== removed file '.pc/01-visibility.patch/lib/base64-decode.c'
--- .pc/01-visibility.patch/lib/base64-decode.c 2013-03-28 19:10:28 +0000
+++ .pc/01-visibility.patch/lib/base64-decode.c 1970-01-01 00:00:00 +0000
@@ -1,189 +0,0 @@
1/*
2 * This code originally came from here
3 *
4 * http://base64.sourceforge.net/b64.c
5 *
6 * with the following license:
7 *
8 * LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
9 *
10 * Permission is hereby granted, free of charge, to any person
11 * obtaining a copy of this software and associated
12 * documentation files (the "Software"), to deal in the
13 * Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute,
15 * sublicense, and/or sell copies of the Software, and to
16 * permit persons to whom the Software is furnished to do so,
17 * subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall
20 * be included in all copies or substantial portions of the
21 * Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
24 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
25 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
26 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
27 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 * VERSION HISTORY:
33 * Bob Trower 08/04/01 -- Create Version 0.00.00B
34 *
35 * I cleaned it up quite a bit to match the (linux kernel) style of the rest
36 * of libwebsockets; this version is under LGPL2 like the rest of libwebsockets
37 * since he explictly allows sublicensing, but I give the URL above so you can
38 * get the original with Bob's super-liberal terms directly if you prefer.
39 */
40
41
42#include <stdio.h>
43#include <string.h>
44#include "private-libwebsockets.h"
45
46static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
47 "abcdefghijklmnopqrstuvwxyz0123456789+/";
48static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
49 "$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
50
51int
52lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
53{
54 unsigned char triple[3];
55 int i;
56 int len;
57 int line = 0;
58 int done = 0;
59
60 while (in_len) {
61 len = 0;
62 for (i = 0; i < 3; i++) {
63 if (in_len) {
64 triple[i] = *in++;
65 len++;
66 in_len--;
67 } else
68 triple[i] = 0;
69 }
70 if (!len)
71 continue;
72
73 if (done + 4 >= out_size)
74 return -1;
75
76 *out++ = encode[triple[0] >> 2];
77 *out++ = encode[((triple[0] & 0x03) << 4) |
78 ((triple[1] & 0xf0) >> 4)];
79 *out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
80 ((triple[2] & 0xc0) >> 6)] : '=');
81 *out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
82
83 done += 4;
84 line += 4;
85 }
86
87 if (done + 1 >= out_size)
88 return -1;
89
90 *out++ = '\0';
91
92 return done;
93}
94
95/*
96 * returns length of decoded string in out, or -1 if out was too small
97 * according to out_size
98 */
99
100int
101lws_b64_decode_string(const char *in, char *out, int out_size)
102{
103 int len;
104 int i;
105 int done = 0;
106 unsigned char v;
107 unsigned char quad[4];
108
109 while (*in) {
110
111 len = 0;
112 for (i = 0; i < 4 && *in; i++) {
113
114 v = 0;
115 while (*in && !v) {
116
117 v = *in++;
118 v = (v < 43 || v > 122) ? 0 : decode[v - 43];
119 if (v)
120 v = (v == '$') ? 0 : v - 61;
121 if (*in) {
122 len++;
123 if (v)
124 quad[i] = v - 1;
125 } else
126 quad[i] = 0;
127 }
128 }
129 if (!len)
130 continue;
131
132 if (out_size < (done + len - 1))
133 /* out buffer is too small */
134 return -1;
135
136 if (len >= 2)
137 *out++ = quad[0] << 2 | quad[1] >> 4;
138 if (len >= 3)
139 *out++ = quad[1] << 4 | quad[2] >> 2;
140 if (len >= 4)
141 *out++ = ((quad[2] << 6) & 0xc0) | quad[3];
142
143 done += len - 1;
144 }
145
146 if (done + 1 >= out_size)
147 return -1;
148
149 *out++ = '\0';
150
151 return done;
152}
153
154int
155lws_b64_selftest(void)
156{
157 char buf[64];
158 int n;
159 int test;
160 static const char * const plaintext[] = {
161 "sanity check base 64"
162 };
163 static const char * const coded[] = {
164 "c2FuaXR5IGNoZWNrIGJhc2UgNjQ="
165 };
166
167 for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) {
168
169 buf[sizeof(buf) - 1] = '\0';
170 n = lws_b64_encode_string(plaintext[test],
171 strlen(plaintext[test]), buf, sizeof buf);
172 if (n != strlen(coded[test]) || strcmp(buf, coded[test])) {
173 lwsl_err("Failed lws_b64 encode selftest "
174 "%d result '%s' %d\n", test, buf, n);
175 return -1;
176 }
177
178 buf[sizeof(buf) - 1] = '\0';
179 n = lws_b64_decode_string(coded[test], buf, sizeof buf);
180 if (n != strlen(plaintext[test]) ||
181 strcmp(buf, plaintext[test])) {
182 lwsl_err("Failed lws_b64 decode selftest "
183 "%d result '%s' %d\n", test, buf, n);
184 return -1;
185 }
186 }
187
188 return 0;
189}
1900
=== removed file '.pc/01-visibility.patch/lib/client-handshake.c'
--- .pc/01-visibility.patch/lib/client-handshake.c 2013-03-28 19:10:28 +0000
+++ .pc/01-visibility.patch/lib/client-handshake.c 1970-01-01 00:00:00 +0000
@@ -1,329 +0,0 @@
1#include "private-libwebsockets.h"
2
3struct libwebsocket *__libwebsocket_client_connect_2(
4 struct libwebsocket_context *context,
5 struct libwebsocket *wsi
6) {
7 struct pollfd pfd;
8 struct hostent *server_hostent;
9 struct sockaddr_in server_addr;
10 int n;
11 int plen = 0;
12 const char *ads;
13
14 lwsl_client("__libwebsocket_client_connect_2\n");
15
16 /*
17 * proxy?
18 */
19
20 if (context->http_proxy_port) {
21 plen = sprintf((char *)context->service_buffer,
22 "CONNECT %s:%u HTTP/1.0\x0d\x0a"
23 "User-agent: libwebsockets\x0d\x0a"
24/*Proxy-authorization: basic aGVsbG86d29ybGQ= */
25 "\x0d\x0a",
26 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
27 wsi->u.hdr.c_port);
28
29 /* OK from now on we talk via the proxy, so connect to that */
30
31 /*
32 * (will overwrite existing pointer,
33 * leaving old string/frag there but unreferenced)
34 */
35 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
36 context->http_proxy_address))
37 goto oom4;
38 wsi->u.hdr.c_port = context->http_proxy_port;
39 }
40
41 /*
42 * prepare the actual connection (to the proxy, if any)
43 */
44
45 ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
46
47 lwsl_client("__libwebsocket_client_connect_2: address %s\n", ads);
48
49 server_hostent = gethostbyname(ads);
50 if (server_hostent == NULL) {
51 lwsl_err("Unable to get host name from %s\n", ads);
52 goto oom4;
53 }
54
55 wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
56
57 if (wsi->sock < 0) {
58 lwsl_warn("Unable to open socket\n");
59 goto oom4;
60 }
61
62 server_addr.sin_family = AF_INET;
63 server_addr.sin_port = htons(wsi->u.hdr.c_port);
64 server_addr.sin_addr = *((struct in_addr *)server_hostent->h_addr);
65 bzero(&server_addr.sin_zero, 8);
66
67 if (connect(wsi->sock, (struct sockaddr *)&server_addr,
68 sizeof(struct sockaddr)) == -1) {
69 lwsl_debug("Connect failed\n");
70 compatible_close(wsi->sock);
71 goto oom4;
72 }
73
74 lwsl_client("connected\n");
75
76 if (lws_set_socket_options(context, wsi->sock)) {
77 lwsl_err("Failed to set wsi socket options\n");
78 close(wsi->sock);
79 goto oom4;
80 }
81
82 insert_wsi_socket_into_fds(context, wsi);
83
84 /* we are connected to server, or proxy */
85
86 if (context->http_proxy_port) {
87
88 n = send(wsi->sock, context->service_buffer, plen, 0);
89 if (n < 0) {
90 compatible_close(wsi->sock);
91 lwsl_debug("ERROR writing to proxy socket\n");
92 goto oom4;
93 }
94
95 libwebsocket_set_timeout(wsi,
96 PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
97 AWAITING_TIMEOUT);
98
99 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
100
101 return wsi;
102 }
103
104 /*
105 * provoke service to issue the handshake directly
106 * we need to do it this way because in the proxy case, this is the
107 * next state and executed only if and when we get a good proxy
108 * response inside the state machine... but notice in SSL case this
109 * may not have sent anything yet with 0 return, and won't until some
110 * many retries from main loop. To stop that becoming endless,
111 * cover with a timeout.
112 */
113
114 libwebsocket_set_timeout(wsi,
115 PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT);
116
117 wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
118 pfd.fd = wsi->sock;
119 pfd.revents = POLLIN;
120
121 n = libwebsocket_service_fd(context, &pfd);
122
123 if (n < 0)
124 goto oom4;
125
126 if (n) /* returns 1 on failure after closing wsi */
127 return NULL;
128
129 return wsi;
130
131oom4:
132 free(wsi->u.hdr.ah);
133 free(wsi);
134
135 return NULL;
136}
137
138/**
139 * libwebsocket_client_connect() - Connect to another websocket server
140 * @context: Websocket context
141 * @address: Remote server address, eg, "myserver.com"
142 * @port: Port to connect to on the remote server, eg, 80
143 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
144 * signed certs
145 * @path: Websocket path on server
146 * @host: Hostname on server
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: