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
1=== modified file '.gitignore'
2--- .gitignore 2013-03-28 19:10:28 +0000
3+++ .gitignore 2015-02-19 16:44:02 +0000
4@@ -29,7 +29,6 @@
5 configure
6 compile
7 config.guess
8-*.in
9 *~
10 *.orig
11 autom4te.cache/
12
13=== removed directory '.pc/0001-getnameinfo.patch'
14=== removed directory '.pc/0001-getnameinfo.patch/lib'
15=== removed file '.pc/0001-getnameinfo.patch/lib/libwebsockets.c'
16--- .pc/0001-getnameinfo.patch/lib/libwebsockets.c 2013-03-28 19:10:28 +0000
17+++ .pc/0001-getnameinfo.patch/lib/libwebsockets.c 1970-01-01 00:00:00 +0000
18@@ -1,2283 +0,0 @@
19-/*
20- * libwebsockets - small server side websockets and web server implementation
21- *
22- * Copyright (C) 2010 Andy Green <andy@warmcat.com>
23- *
24- * This library is free software; you can redistribute it and/or
25- * modify it under the terms of the GNU Lesser General Public
26- * License as published by the Free Software Foundation:
27- * version 2.1 of the License.
28- *
29- * This library is distributed in the hope that it will be useful,
30- * but WITHOUT ANY WARRANTY; without even the implied warranty of
31- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32- * Lesser General Public License for more details.
33- *
34- * You should have received a copy of the GNU Lesser General Public
35- * License along with this library; if not, write to the Free Software
36- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
37- * MA 02110-1301 USA
38- */
39-
40-#include "private-libwebsockets.h"
41-
42-#ifdef WIN32
43-#include <tchar.h>
44-#include <io.h>
45-#include <mstcpip.h>
46-#else
47-#ifdef LWS_BUILTIN_GETIFADDRS
48-#include <getifaddrs.h>
49-#else
50-#include <ifaddrs.h>
51-#endif
52-#include <syslog.h>
53-#include <sys/un.h>
54-#include <sys/socket.h>
55-#include <netdb.h>
56-#endif
57-
58-#ifdef LWS_OPENSSL_SUPPORT
59-int openssl_websocket_private_data_index;
60-#endif
61-
62-#ifdef __MINGW32__
63-#include "../win32port/win32helpers/websock-w32.c"
64-#else
65-#ifdef __MINGW64__
66-#include "../win32port/win32helpers/websock-w32.c"
67-#endif
68-#endif
69-
70-#ifndef LWS_BUILD_HASH
71-#define LWS_BUILD_HASH "unknown-build-hash"
72-#endif
73-
74-static int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
75-static void lwsl_emit_stderr(int level, const char *line);
76-static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
77-
78-static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
79-
80-static const char * const log_level_names[] = {
81- "ERR",
82- "WARN",
83- "NOTICE",
84- "INFO",
85- "DEBUG",
86- "PARSER",
87- "HEADER",
88- "EXTENSION",
89- "CLIENT",
90- "LATENCY",
91-};
92-
93-#ifndef LWS_NO_CLIENT
94- extern int lws_client_socket_service(
95- struct libwebsocket_context *context,
96- struct libwebsocket *wsi, struct pollfd *pollfd);
97-#endif
98-#ifndef LWS_NO_SERVER
99- extern int lws_server_socket_service(
100- struct libwebsocket_context *context,
101- struct libwebsocket *wsi, struct pollfd *pollfd);
102-#endif
103-
104-/**
105- * lws_get_library_version: get version and git hash library built from
106- *
107- * returns a const char * to a string like "1.1 178d78c"
108- * representing the library version followed by the git head hash it
109- * was built from
110- */
111-
112-const char *
113-lws_get_library_version(void)
114-{
115- return library_version;
116-}
117-
118-int
119-insert_wsi_socket_into_fds(struct libwebsocket_context *context,
120- struct libwebsocket *wsi)
121-{
122- if (context->fds_count >= context->max_fds) {
123- lwsl_err("Too many fds (%d)\n", context->max_fds);
124- return 1;
125- }
126-
127- if (wsi->sock > context->max_fds) {
128- lwsl_err("Socket fd %d is too high (%d)\n",
129- wsi->sock, context->max_fds);
130- return 1;
131- }
132-
133- assert(wsi);
134- assert(wsi->sock);
135-
136- lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
137- wsi, wsi->sock, context->fds_count);
138-
139- context->lws_lookup[wsi->sock] = wsi;
140- wsi->position_in_fds_table = context->fds_count;
141- context->fds[context->fds_count].fd = wsi->sock;
142- context->fds[context->fds_count].events = POLLIN;
143- context->fds[context->fds_count++].revents = 0;
144-
145- /* external POLL support via protocol 0 */
146- context->protocols[0].callback(context, wsi,
147- LWS_CALLBACK_ADD_POLL_FD,
148- (void *)(long)wsi->sock, NULL, POLLIN);
149-
150- return 0;
151-}
152-
153-static int
154-remove_wsi_socket_from_fds(struct libwebsocket_context *context,
155- struct libwebsocket *wsi)
156-{
157- int m;
158-
159- if (!--context->fds_count)
160- goto do_ext;
161-
162- if (wsi->sock > context->max_fds) {
163- lwsl_err("Socket fd %d too high (%d)\n",
164- wsi->sock, context->max_fds);
165- return 1;
166- }
167-
168- lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n",
169- wsi, wsi->sock, wsi->position_in_fds_table);
170-
171- m = wsi->position_in_fds_table; /* replace the contents for this */
172-
173- /* have the last guy take up the vacant slot */
174- context->fds[m] = context->fds[context->fds_count];
175- /*
176- * end guy's fds_lookup entry remains unchanged
177- * (still same fd pointing to same wsi)
178- */
179- /* end guy's "position in fds table" changed */
180- context->lws_lookup[context->fds[context->fds_count].fd]->
181- position_in_fds_table = m;
182- /* deletion guy's lws_lookup entry needs nuking */
183- context->lws_lookup[wsi->sock] = NULL;
184- /* removed wsi has no position any more */
185- wsi->position_in_fds_table = -1;
186-
187-do_ext:
188- /* remove also from external POLL support via protocol 0 */
189- if (wsi->sock)
190- context->protocols[0].callback(context, wsi,
191- LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
192-
193- return 0;
194-}
195-
196-
197-void
198-libwebsocket_close_and_free_session(struct libwebsocket_context *context,
199- struct libwebsocket *wsi, enum lws_close_status reason)
200-{
201- int n;
202- int old_state;
203- unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
204- LWS_SEND_BUFFER_POST_PADDING];
205-#ifndef LWS_NO_EXTENSIONS
206- int ret;
207- int m;
208- struct lws_tokens eff_buf;
209- struct libwebsocket_extension *ext;
210-#endif
211-
212- if (!wsi)
213- return;
214-
215- old_state = wsi->state;
216-
217- if (old_state == WSI_STATE_DEAD_SOCKET)
218- return;
219-
220- wsi->u.ws.close_reason = reason;
221-
222- if (wsi->mode == LWS_CONNMODE_HTTP_SERVING && wsi->u.http.fd) {
223- close(wsi->u.http.fd);
224- wsi->u.http.fd = 0;
225- }
226-
227-#ifndef LWS_NO_EXTENSIONS
228- /*
229- * are his extensions okay with him closing? Eg he might be a mux
230- * parent and just his ch1 aspect is closing?
231- */
232-
233- for (n = 0; n < wsi->count_active_extensions; n++) {
234- if (!wsi->active_extensions[n]->callback)
235- continue;
236-
237- m = wsi->active_extensions[n]->callback(context,
238- wsi->active_extensions[n], wsi,
239- LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
240- wsi->active_extensions_user[n], NULL, 0);
241-
242- /*
243- * if somebody vetoed actually closing him at this time....
244- * up to the extension to track the attempted close, let's
245- * just bail
246- */
247-
248- if (m) {
249- lwsl_ext("extension vetoed close\n");
250- return;
251- }
252- }
253-
254- /*
255- * flush any tx pending from extensions, since we may send close packet
256- * if there are problems with send, just nuke the connection
257- */
258-
259- ret = 1;
260- while (ret == 1) {
261-
262- /* default to nobody has more to spill */
263-
264- ret = 0;
265- eff_buf.token = NULL;
266- eff_buf.token_len = 0;
267-
268- /* show every extension the new incoming data */
269-
270- for (n = 0; n < wsi->count_active_extensions; n++) {
271- m = wsi->active_extensions[n]->callback(
272- wsi->protocol->owning_server,
273- wsi->active_extensions[n], wsi,
274- LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
275- wsi->active_extensions_user[n], &eff_buf, 0);
276- if (m < 0) {
277- lwsl_ext("Extension reports fatal error\n");
278- goto just_kill_connection;
279- }
280- if (m)
281- /*
282- * at least one extension told us he has more
283- * to spill, so we will go around again after
284- */
285- ret = 1;
286- }
287-
288- /* assuming they left us something to send, send it */
289-
290- if (eff_buf.token_len)
291- if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
292- eff_buf.token_len)) {
293- lwsl_debug("close: ext spill failed\n");
294- goto just_kill_connection;
295- }
296- }
297-#endif
298-
299- /*
300- * signal we are closing, libsocket_write will
301- * add any necessary version-specific stuff. If the write fails,
302- * no worries we are closing anyway. If we didn't initiate this
303- * close, then our state has been changed to
304- * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
305- *
306- * Likewise if it's a second call to close this connection after we
307- * sent the close indication to the peer already, we are in state
308- * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
309- */
310-
311- if (old_state == WSI_STATE_ESTABLISHED &&
312- reason != LWS_CLOSE_STATUS_NOSTATUS) {
313-
314- lwsl_debug("sending close indication...\n");
315-
316- /* make valgrind happy */
317- memset(buf, 0, sizeof(buf));
318- n = libwebsocket_write(wsi,
319- &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
320- 0, LWS_WRITE_CLOSE);
321- if (!n) {
322- /*
323- * we have sent a nice protocol level indication we
324- * now wish to close, we should not send anything more
325- */
326-
327- wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
328-
329- /*
330- * ...and we should wait for a reply for a bit
331- * out of politeness
332- */
333-
334- libwebsocket_set_timeout(wsi,
335- PENDING_TIMEOUT_CLOSE_ACK, 1);
336-
337- lwsl_debug("sent close indication, awaiting ack\n");
338-
339- return;
340- }
341-
342- lwsl_info("close: sending close packet failed, hanging up\n");
343-
344- /* else, the send failed and we should just hang up */
345- }
346-
347-#ifndef LWS_NO_EXTENSIONS
348-just_kill_connection:
349-#endif
350-
351- lwsl_debug("close: just_kill_connection\n");
352-
353- /*
354- * we won't be servicing or receiving anything further from this guy
355- * delete socket from the internal poll list if still present
356- */
357-
358- remove_wsi_socket_from_fds(context, wsi);
359-
360- wsi->state = WSI_STATE_DEAD_SOCKET;
361-
362- if ((old_state == WSI_STATE_ESTABLISHED ||
363- wsi->mode == LWS_CONNMODE_WS_SERVING ||
364- wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
365-
366- if (wsi->u.ws.rx_user_buffer) {
367- free(wsi->u.ws.rx_user_buffer);
368- wsi->u.ws.rx_user_buffer = NULL;
369- }
370- if (wsi->u.ws.rxflow_buffer) {
371- free(wsi->u.ws.rxflow_buffer);
372- wsi->u.ws.rxflow_buffer = NULL;
373- }
374- }
375-
376- /* tell the user it's all over for this guy */
377-
378- if (wsi->protocol && wsi->protocol->callback &&
379- ((old_state == WSI_STATE_ESTABLISHED) ||
380- (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
381- (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
382- lwsl_debug("calling back CLOSED\n");
383- wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
384- wsi->user_space, NULL, 0);
385- } else
386- lwsl_debug("not calling back closed\n");
387-
388-#ifndef LWS_NO_EXTENSIONS
389- /* deallocate any active extension contexts */
390-
391- for (n = 0; n < wsi->count_active_extensions; n++) {
392- if (!wsi->active_extensions[n]->callback)
393- continue;
394-
395- wsi->active_extensions[n]->callback(context,
396- wsi->active_extensions[n], wsi,
397- LWS_EXT_CALLBACK_DESTROY,
398- wsi->active_extensions_user[n], NULL, 0);
399-
400- free(wsi->active_extensions_user[n]);
401- }
402-
403- /*
404- * inform all extensions in case they tracked this guy out of band
405- * even though not active on him specifically
406- */
407-
408- ext = context->extensions;
409- while (ext && ext->callback) {
410- ext->callback(context, ext, wsi,
411- LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
412- NULL, NULL, 0);
413- ext++;
414- }
415-#endif
416-
417-/* lwsl_info("closing fd=%d\n", wsi->sock); */
418-
419-#ifdef LWS_OPENSSL_SUPPORT
420- if (wsi->ssl) {
421- n = SSL_get_fd(wsi->ssl);
422- SSL_shutdown(wsi->ssl);
423- compatible_close(n);
424- SSL_free(wsi->ssl);
425- } else {
426-#endif
427- if (wsi->sock) {
428- n = shutdown(wsi->sock, SHUT_RDWR);
429- if (n)
430- lwsl_debug("closing: shutdown returned %d\n",
431- errno);
432-
433- n = compatible_close(wsi->sock);
434- if (n)
435- lwsl_debug("closing: close returned %d\n",
436- errno);
437- }
438-#ifdef LWS_OPENSSL_SUPPORT
439- }
440-#endif
441- if (wsi->protocol && wsi->protocol->per_session_data_size &&
442- wsi->user_space) /* user code may own */
443- free(wsi->user_space);
444-
445- free(wsi);
446-}
447-
448-/**
449- * libwebsockets_get_peer_addresses() - Get client address information
450- * @context: Libwebsockets context
451- * @wsi: Local struct libwebsocket associated with
452- * @fd: Connection socket descriptor
453- * @name: Buffer to take client address name
454- * @name_len: Length of client address name buffer
455- * @rip: Buffer to take client address IP qotted quad
456- * @rip_len: Length of client address IP buffer
457- *
458- * This function fills in @name and @rip with the name and IP of
459- * the client connected with socket descriptor @fd. Names may be
460- * truncated if there is not enough room. If either cannot be
461- * determined, they will be returned as valid zero-length strings.
462- */
463-
464-void
465-libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
466- struct libwebsocket *wsi, int fd, char *name, int name_len,
467- char *rip, int rip_len)
468-{
469- unsigned int len;
470- struct sockaddr_in sin;
471- struct hostent *host;
472- struct hostent *host1;
473- char ip[128];
474- unsigned char *p;
475- int n;
476- int ret = -1;
477-#ifdef AF_LOCAL
478- struct sockaddr_un *un;
479-#endif
480-
481- rip[0] = '\0';
482- name[0] = '\0';
483-
484- lws_latency_pre(context, wsi);
485-
486- len = sizeof(sin);
487- if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
488- perror("getpeername");
489- goto bail;
490- }
491-
492- host = gethostbyaddr((char *) &sin.sin_addr, sizeof(sin.sin_addr),
493- AF_INET);
494- if (host == NULL) {
495- perror("gethostbyaddr");
496- goto bail;
497- }
498-
499- strncpy(name, host->h_name, name_len);
500- name[name_len - 1] = '\0';
501-
502- host1 = gethostbyname(host->h_name);
503- if (host1 == NULL)
504- goto bail;
505- p = (unsigned char *)host1;
506- n = 0;
507- while (p != NULL) {
508- p = (unsigned char *)host1->h_addr_list[n++];
509- if (p == NULL)
510- continue;
511- if ((host1->h_addrtype != AF_INET)
512-#ifdef AF_LOCAL
513- && (host1->h_addrtype != AF_LOCAL)
514-#endif
515- )
516- continue;
517-
518- if (host1->h_addrtype == AF_INET)
519- sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
520-#ifdef AF_LOCAL
521- else {
522- un = (struct sockaddr_un *)p;
523- strncpy(ip, un->sun_path, sizeof(ip) - 1);
524- ip[sizeof(ip) - 1] = '\0';
525- }
526-#endif
527- p = NULL;
528- strncpy(rip, ip, rip_len);
529- rip[rip_len - 1] = '\0';
530- }
531-
532- ret = 0;
533-bail:
534- lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
535-}
536-
537-int libwebsockets_get_random(struct libwebsocket_context *context,
538- void *buf, int len)
539-{
540- int n;
541- char *p = (char *)buf;
542-
543-#ifdef WIN32
544- for (n = 0; n < len; n++)
545- p[n] = (unsigned char)rand();
546-#else
547- n = read(context->fd_random, p, len);
548-#endif
549-
550- return n;
551-}
552-
553-int lws_set_socket_options(struct libwebsocket_context *context, int fd)
554-{
555- int optval = 1;
556- socklen_t optlen = sizeof(optval);
557-#ifdef WIN32
558- unsigned long optl = 0;
559-#endif
560-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
561- struct protoent *tcp_proto;
562-#endif
563-
564- if (context->ka_time) {
565- /* enable keepalive on this socket */
566- optval = 1;
567- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
568- (const void *)&optval, optlen) < 0)
569- return 1;
570-
571-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
572-
573- /*
574- * didn't find a way to set these per-socket, need to
575- * tune kernel systemwide values
576- */
577-#elif WIN32
578- {
579- DWORD dwBytesRet;
580- struct tcp_keepalive alive;
581- alive.onoff = TRUE;
582- alive.keepalivetime = context->ka_time;
583- alive.keepaliveinterval = context->ka_interval;
584-
585- if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
586- NULL, 0, &dwBytesRet, NULL, NULL))
587- return 1;
588- }
589-#else
590- /* set the keepalive conditions we want on it too */
591- optval = context->ka_time;
592- if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE,
593- (const void *)&optval, optlen) < 0)
594- return 1;
595-
596- optval = context->ka_probes;
597- if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL,
598- (const void *)&optval, optlen) < 0)
599- return 1;
600-
601- optval = context->ka_interval;
602- if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT,
603- (const void *)&optval, optlen) < 0)
604- return 1;
605-#endif
606- }
607-
608- /* Disable Nagle */
609- optval = 1;
610-#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
611- setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
612-#else
613- tcp_proto = getprotobyname("TCP");
614- setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen);
615-#endif
616-
617- /* We are nonblocking... */
618-#ifdef WIN32
619- ioctlsocket(fd, FIONBIO, &optl);
620-#else
621- fcntl(fd, F_SETFL, O_NONBLOCK);
622-#endif
623-
624- return 0;
625-}
626-
627-int lws_send_pipe_choked(struct libwebsocket *wsi)
628-{
629- struct pollfd fds;
630-
631- fds.fd = wsi->sock;
632- fds.events = POLLOUT;
633- fds.revents = 0;
634-
635- if (poll(&fds, 1, 0) != 1)
636- return 1;
637-
638- if ((fds.revents & POLLOUT) == 0)
639- return 1;
640-
641- /* okay to send another packet without blocking */
642-
643- return 0;
644-}
645-
646-int
647-lws_handle_POLLOUT_event(struct libwebsocket_context *context,
648- struct libwebsocket *wsi, struct pollfd *pollfd)
649-{
650- int n;
651-
652-#ifndef LWS_NO_EXTENSIONS
653- struct lws_tokens eff_buf;
654- int ret;
655- int m;
656- int handled = 0;
657-
658- for (n = 0; n < wsi->count_active_extensions; n++) {
659- if (!wsi->active_extensions[n]->callback)
660- continue;
661-
662- m = wsi->active_extensions[n]->callback(context,
663- wsi->active_extensions[n], wsi,
664- LWS_EXT_CALLBACK_IS_WRITEABLE,
665- wsi->active_extensions_user[n], NULL, 0);
666- if (m > handled)
667- handled = m;
668- }
669-
670- if (handled == 1)
671- goto notify_action;
672-
673- if (!wsi->extension_data_pending || handled == 2)
674- goto user_service;
675-
676- /*
677- * check in on the active extensions, see if they
678- * had pending stuff to spill... they need to get the
679- * first look-in otherwise sequence will be disordered
680- *
681- * NULL, zero-length eff_buf means just spill pending
682- */
683-
684- ret = 1;
685- while (ret == 1) {
686-
687- /* default to nobody has more to spill */
688-
689- ret = 0;
690- eff_buf.token = NULL;
691- eff_buf.token_len = 0;
692-
693- /* give every extension a chance to spill */
694-
695- for (n = 0; n < wsi->count_active_extensions; n++) {
696- m = wsi->active_extensions[n]->callback(
697- wsi->protocol->owning_server,
698- wsi->active_extensions[n], wsi,
699- LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
700- wsi->active_extensions_user[n], &eff_buf, 0);
701- if (m < 0) {
702- lwsl_err("ext reports fatal error\n");
703- return -1;
704- }
705- if (m)
706- /*
707- * at least one extension told us he has more
708- * to spill, so we will go around again after
709- */
710- ret = 1;
711- }
712-
713- /* assuming they gave us something to send, send it */
714-
715- if (eff_buf.token_len) {
716- if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
717- eff_buf.token_len))
718- return -1;
719- } else
720- continue;
721-
722- /* no extension has more to spill */
723-
724- if (!ret)
725- continue;
726-
727- /*
728- * There's more to spill from an extension, but we just sent
729- * something... did that leave the pipe choked?
730- */
731-
732- if (!lws_send_pipe_choked(wsi))
733- /* no we could add more */
734- continue;
735-
736- lwsl_info("choked in POLLOUT service\n");
737-
738- /*
739- * Yes, he's choked. Leave the POLLOUT masked on so we will
740- * come back here when he is unchoked. Don't call the user
741- * callback to enforce ordering of spilling, he'll get called
742- * when we come back here and there's nothing more to spill.
743- */
744-
745- return 0;
746- }
747-
748- wsi->extension_data_pending = 0;
749-
750-user_service:
751-#endif
752- /* one shot */
753-
754- if (pollfd) {
755- pollfd->events &= ~POLLOUT;
756-
757- /* external POLL support via protocol 0 */
758- context->protocols[0].callback(context, wsi,
759- LWS_CALLBACK_CLEAR_MODE_POLL_FD,
760- (void *)(long)wsi->sock, NULL, POLLOUT);
761- }
762-#ifndef LWS_NO_EXTENSIONS
763-notify_action:
764-#endif
765-
766- if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
767- n = LWS_CALLBACK_CLIENT_WRITEABLE;
768- else
769- n = LWS_CALLBACK_SERVER_WRITEABLE;
770-
771- return user_callback_handle_rxflow(wsi->protocol->callback, context,
772- wsi, (enum libwebsocket_callback_reasons) n,
773- wsi->user_space, NULL, 0);
774-}
775-
776-
777-
778-void
779-libwebsocket_service_timeout_check(struct libwebsocket_context *context,
780- struct libwebsocket *wsi, unsigned int sec)
781-{
782-#ifndef LWS_NO_EXTENSIONS
783- int n;
784-
785- /*
786- * if extensions want in on it (eg, we are a mux parent)
787- * give them a chance to service child timeouts
788- */
789-
790- for (n = 0; n < wsi->count_active_extensions; n++)
791- wsi->active_extensions[n]->callback(
792- context, wsi->active_extensions[n],
793- wsi, LWS_EXT_CALLBACK_1HZ,
794- wsi->active_extensions_user[n], NULL, sec);
795-
796-#endif
797- if (!wsi->pending_timeout)
798- return;
799-
800- /*
801- * if we went beyond the allowed time, kill the
802- * connection
803- */
804-
805- if (sec > wsi->pending_timeout_limit) {
806- lwsl_info("TIMEDOUT WAITING\n");
807- libwebsocket_close_and_free_session(context,
808- wsi, LWS_CLOSE_STATUS_NOSTATUS);
809- }
810-}
811-
812-/**
813- * libwebsocket_service_fd() - Service polled socket with something waiting
814- * @context: Websocket context
815- * @pollfd: The pollfd entry describing the socket fd and which events
816- * happened.
817- *
818- * This function takes a pollfd that has POLLIN or POLLOUT activity and
819- * services it according to the state of the associated
820- * struct libwebsocket.
821- *
822- * The one call deals with all "service" that might happen on a socket
823- * including listen accepts, http files as well as websocket protocol.
824- */
825-
826-int
827-libwebsocket_service_fd(struct libwebsocket_context *context,
828- struct pollfd *pollfd)
829-{
830- struct libwebsocket *wsi;
831- int n;
832- int m;
833- int listen_socket_fds_index = 0;
834- struct timeval tv;
835-
836-#ifndef LWS_NO_EXTENSIONS
837- int more = 1;
838-#endif
839- struct lws_tokens eff_buf;
840-
841- if (context->listen_service_fd)
842- listen_socket_fds_index = context->lws_lookup[
843- context->listen_service_fd]->position_in_fds_table;
844-
845- /*
846- * you can call us with pollfd = NULL to just allow the once-per-second
847- * global timeout checks; if less than a second since the last check
848- * it returns immediately then.
849- */
850-
851- gettimeofday(&tv, NULL);
852-
853- if (context->last_timeout_check_s != tv.tv_sec) {
854- context->last_timeout_check_s = tv.tv_sec;
855-
856- #ifndef WIN32
857- /* if our parent went down, don't linger around */
858- if (context->started_with_parent &&
859- kill(context->started_with_parent, 0) < 0)
860- kill(getpid(), SIGTERM);
861- #endif
862-
863- /* global timeout check once per second */
864-
865- for (n = 0; n < context->fds_count; n++) {
866- struct libwebsocket *new_wsi =
867- context->lws_lookup[context->fds[n].fd];
868- if (!new_wsi)
869- continue;
870- libwebsocket_service_timeout_check(context,
871- new_wsi, tv.tv_sec);
872- }
873- }
874-
875- /* just here for timeout management? */
876-
877- if (pollfd == NULL)
878- return 0;
879-
880- /* no, here to service a socket descriptor */
881-
882- /*
883- * deal with listen service piggybacking
884- * every listen_service_modulo services of other fds, we
885- * sneak one in to service the listen socket if there's anything waiting
886- *
887- * To handle connection storms, as found in ab, if we previously saw a
888- * pending connection here, it causes us to check again next time.
889- */
890-
891- if (context->listen_service_fd && pollfd !=
892- &context->fds[listen_socket_fds_index]) {
893- context->listen_service_count++;
894- if (context->listen_service_extraseen ||
895- context->listen_service_count ==
896- context->listen_service_modulo) {
897- context->listen_service_count = 0;
898- m = 1;
899- if (context->listen_service_extraseen > 5)
900- m = 2;
901- while (m--) {
902- /*
903- * even with extpoll, we prepared this
904- * internal fds for listen
905- */
906- n = poll(&context->fds[listen_socket_fds_index],
907- 1, 0);
908- if (n > 0) { /* there's a conn waiting for us */
909- libwebsocket_service_fd(context,
910- &context->
911- fds[listen_socket_fds_index]);
912- context->listen_service_extraseen++;
913- } else {
914- if (context->listen_service_extraseen)
915- context->
916- listen_service_extraseen--;
917- break;
918- }
919- }
920- }
921-
922- }
923-
924- /* okay, what we came here to do... */
925-
926- wsi = context->lws_lookup[pollfd->fd];
927- if (wsi == NULL) {
928- if (pollfd->fd > 11)
929- lwsl_err("unexpected NULL wsi fd=%d fds_count=%d\n",
930- pollfd->fd, context->fds_count);
931- return 0;
932- }
933-
934- switch (wsi->mode) {
935-
936-#ifndef LWS_NO_SERVER
937- case LWS_CONNMODE_HTTP_SERVING:
938- case LWS_CONNMODE_SERVER_LISTENER:
939- case LWS_CONNMODE_SSL_ACK_PENDING:
940- return lws_server_socket_service(context, wsi, pollfd);
941-#endif
942-
943- case LWS_CONNMODE_WS_SERVING:
944- case LWS_CONNMODE_WS_CLIENT:
945-
946- /* handle session socket closed */
947-
948- if (pollfd->revents & (POLLERR | POLLHUP)) {
949-
950- lwsl_debug("Session Socket %p (fd=%d) dead\n",
951- (void *)wsi, pollfd->fd);
952-
953- libwebsocket_close_and_free_session(context, wsi,
954- LWS_CLOSE_STATUS_NOSTATUS);
955- return 0;
956- }
957-
958- /* the guy requested a callback when it was OK to write */
959-
960- if ((pollfd->revents & POLLOUT) &&
961- wsi->state == WSI_STATE_ESTABLISHED)
962- if (lws_handle_POLLOUT_event(context, wsi,
963- pollfd) < 0) {
964- lwsl_info("libwebsocket_service_fd: closing\n");
965- libwebsocket_close_and_free_session(
966- context, wsi, LWS_CLOSE_STATUS_NORMAL);
967- return 0;
968- }
969-
970-
971- /* any incoming data ready? */
972-
973- if (!(pollfd->revents & POLLIN))
974- break;
975-
976-#ifdef LWS_OPENSSL_SUPPORT
977-read_pending:
978- if (wsi->ssl) {
979- eff_buf.token_len = SSL_read(wsi->ssl,
980- context->service_buffer,
981- sizeof(context->service_buffer));
982- if (!eff_buf.token_len) {
983- n = SSL_get_error(wsi->ssl, eff_buf.token_len);
984- lwsl_err("SSL_read returned 0 with reason %s\n",
985- ERR_error_string(n,
986- (char *)context->service_buffer));
987- }
988- } else
989-#endif
990- eff_buf.token_len = recv(pollfd->fd,
991- context->service_buffer,
992- sizeof(context->service_buffer), 0);
993-
994- if (eff_buf.token_len < 0) {
995- lwsl_debug("Socket read returned %d\n",
996- eff_buf.token_len);
997- if (errno != EINTR && errno != EAGAIN)
998- libwebsocket_close_and_free_session(context,
999- wsi, LWS_CLOSE_STATUS_NOSTATUS);
1000- return 0;
1001- }
1002- if (!eff_buf.token_len) {
1003- lwsl_info("closing connection due to 0 length read\n");
1004- libwebsocket_close_and_free_session(context, wsi,
1005- LWS_CLOSE_STATUS_NOSTATUS);
1006- return 0;
1007- }
1008-
1009- /*
1010- * give any active extensions a chance to munge the buffer
1011- * before parse. We pass in a pointer to an lws_tokens struct
1012- * prepared with the default buffer and content length that's in
1013- * there. Rather than rewrite the default buffer, extensions
1014- * that expect to grow the buffer can adapt .token to
1015- * point to their own per-connection buffer in the extension
1016- * user allocation. By default with no extensions or no
1017- * extension callback handling, just the normal input buffer is
1018- * used then so it is efficient.
1019- */
1020-
1021- eff_buf.token = (char *)context->service_buffer;
1022-#ifndef LWS_NO_EXTENSIONS
1023- more = 1;
1024- while (more) {
1025-
1026- more = 0;
1027-
1028- for (n = 0; n < wsi->count_active_extensions; n++) {
1029- m = wsi->active_extensions[n]->callback(context,
1030- wsi->active_extensions[n], wsi,
1031- LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
1032- wsi->active_extensions_user[n],
1033- &eff_buf, 0);
1034- if (m < 0) {
1035- lwsl_ext(
1036- "Extension reports fatal error\n");
1037- libwebsocket_close_and_free_session(
1038- context, wsi,
1039- LWS_CLOSE_STATUS_NOSTATUS);
1040- return 0;
1041- }
1042- if (m)
1043- more = 1;
1044- }
1045-#endif
1046- /* service incoming data */
1047-
1048- if (eff_buf.token_len) {
1049- n = libwebsocket_read(context, wsi,
1050- (unsigned char *)eff_buf.token,
1051- eff_buf.token_len);
1052- if (n < 0)
1053- /* we closed wsi */
1054- return 0;
1055- }
1056-#ifndef LWS_NO_EXTENSIONS
1057- eff_buf.token = NULL;
1058- eff_buf.token_len = 0;
1059- }
1060-#endif
1061-
1062-#ifdef LWS_OPENSSL_SUPPORT
1063- if (wsi->ssl && SSL_pending(wsi->ssl))
1064- goto read_pending;
1065-#endif
1066- break;
1067-
1068- default:
1069-#ifdef LWS_NO_CLIENT
1070- break;
1071-#else
1072- return lws_client_socket_service(context, wsi, pollfd);
1073-#endif
1074- }
1075-
1076- return 0;
1077-}
1078-
1079-
1080-/**
1081- * libwebsocket_context_destroy() - Destroy the websocket context
1082- * @context: Websocket context
1083- *
1084- * This function closes any active connections and then frees the
1085- * context. After calling this, any further use of the context is
1086- * undefined.
1087- */
1088-void
1089-libwebsocket_context_destroy(struct libwebsocket_context *context)
1090-{
1091-#ifndef LWS_NO_EXTENSIONS
1092- int n;
1093- int m;
1094- struct libwebsocket_extension *ext;
1095- struct libwebsocket_protocols *protocol = context->protocols;
1096-
1097-#ifdef LWS_LATENCY
1098- if (context->worst_latency_info[0])
1099- lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
1100-#endif
1101-
1102- for (n = 0; n < context->fds_count; n++) {
1103- struct libwebsocket *wsi =
1104- context->lws_lookup[context->fds[n].fd];
1105- libwebsocket_close_and_free_session(context,
1106- wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
1107- n--;
1108- }
1109-
1110- /*
1111- * give all extensions a chance to clean up any per-context
1112- * allocations they might have made
1113- */
1114-
1115- ext = context->extensions;
1116- m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
1117- if (context->listen_port)
1118- m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
1119- while (ext && ext->callback) {
1120- ext->callback(context, ext, NULL,
1121- (enum libwebsocket_extension_callback_reasons)m,
1122- NULL, NULL, 0);
1123- ext++;
1124- }
1125-
1126- /*
1127- * inform all the protocols that they are done and will have no more
1128- * callbacks
1129- */
1130-
1131- while (protocol->callback) {
1132- protocol->callback(context, NULL, LWS_CALLBACK_PROTOCOL_DESTROY,
1133- NULL, NULL, 0);
1134- protocol++;
1135- }
1136-
1137-#endif
1138-
1139-#ifdef WIN32
1140-#else
1141- close(context->fd_random);
1142-#endif
1143-
1144-#ifdef LWS_OPENSSL_SUPPORT
1145- if (context->ssl_ctx)
1146- SSL_CTX_free(context->ssl_ctx);
1147- if (context->ssl_client_ctx)
1148- SSL_CTX_free(context->ssl_client_ctx);
1149-
1150- ERR_remove_state(0);
1151- ERR_free_strings();
1152- EVP_cleanup();
1153- CRYPTO_cleanup_all_ex_data();
1154-#endif
1155-
1156- if (context->fds)
1157- free(context->fds);
1158- if (context->lws_lookup)
1159- free(context->lws_lookup);
1160-
1161- free(context);
1162-
1163-#ifdef WIN32
1164- WSACleanup();
1165-#endif
1166-}
1167-
1168-/**
1169- * libwebsocket_context_user() - get the user data associated with the context
1170- * @context: Websocket context
1171- *
1172- * This returns the optional user allocation that can be attached to
1173- * the context the sockets live in at context_create time. It's a way
1174- * to let all sockets serviced in the same context share data without
1175- * using globals statics in the user code.
1176- */
1177-LWS_EXTERN void *
1178-libwebsocket_context_user(struct libwebsocket_context *context)
1179-{
1180- return context->user_space;
1181-}
1182-
1183-/**
1184- * libwebsocket_service() - Service any pending websocket activity
1185- * @context: Websocket context
1186- * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
1187- * service otherwise block and service immediately, returning
1188- * after the timeout if nothing needed service.
1189- *
1190- * This function deals with any pending websocket traffic, for three
1191- * kinds of event. It handles these events on both server and client
1192- * types of connection the same.
1193- *
1194- * 1) Accept new connections to our context's server
1195- *
1196- * 2) Call the receive callback for incoming frame data received by
1197- * server or client connections.
1198- *
1199- * You need to call this service function periodically to all the above
1200- * functions to happen; if your application is single-threaded you can
1201- * just call it in your main event loop.
1202- *
1203- * Alternatively you can fork a new process that asynchronously handles
1204- * calling this service in a loop. In that case you are happy if this
1205- * call blocks your thread until it needs to take care of something and
1206- * would call it with a large nonzero timeout. Your loop then takes no
1207- * CPU while there is nothing happening.
1208- *
1209- * If you are calling it in a single-threaded app, you don't want it to
1210- * wait around blocking other things in your loop from happening, so you
1211- * would call it with a timeout_ms of 0, so it returns immediately if
1212- * nothing is pending, or as soon as it services whatever was pending.
1213- */
1214-
1215-int
1216-libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
1217-{
1218- int n;
1219-
1220- /* stay dead once we are dead */
1221-
1222- if (context == NULL)
1223- return 1;
1224-
1225- /* wait for something to need service */
1226-
1227- n = poll(context->fds, context->fds_count, timeout_ms);
1228- if (n == 0) /* poll timeout */
1229- return 0;
1230-
1231- if (n < 0)
1232- return -1;
1233-
1234- /* any socket with events to service? */
1235-
1236- for (n = 0; n < context->fds_count; n++)
1237- if (context->fds[n].revents)
1238- if (libwebsocket_service_fd(context,
1239- &context->fds[n]) < 0)
1240- return -1;
1241- return 0;
1242-}
1243-
1244-#ifndef LWS_NO_EXTENSIONS
1245-int
1246-lws_any_extension_handled(struct libwebsocket_context *context,
1247- struct libwebsocket *wsi,
1248- enum libwebsocket_extension_callback_reasons r,
1249- void *v, size_t len)
1250-{
1251- int n;
1252- int handled = 0;
1253-
1254- /* maybe an extension will take care of it for us */
1255-
1256- for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
1257- if (!wsi->active_extensions[n]->callback)
1258- continue;
1259-
1260- handled |= wsi->active_extensions[n]->callback(context,
1261- wsi->active_extensions[n], wsi,
1262- r, wsi->active_extensions_user[n], v, len);
1263- }
1264-
1265- return handled;
1266-}
1267-
1268-
1269-void *
1270-lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
1271- struct libwebsocket_extension *ext)
1272-{
1273- int n = 0;
1274-
1275- if (wsi == NULL)
1276- return NULL;
1277-
1278- while (n < wsi->count_active_extensions) {
1279- if (wsi->active_extensions[n] != ext) {
1280- n++;
1281- continue;
1282- }
1283- return wsi->active_extensions_user[n];
1284- }
1285-
1286- return NULL;
1287-}
1288-#endif
1289-
1290-/**
1291- * libwebsocket_callback_on_writable() - Request a callback when this socket
1292- * becomes able to be written to without
1293- * blocking
1294- *
1295- * @context: libwebsockets context
1296- * @wsi: Websocket connection instance to get callback for
1297- */
1298-
1299-int
1300-libwebsocket_callback_on_writable(struct libwebsocket_context *context,
1301- struct libwebsocket *wsi)
1302-{
1303-#ifndef LWS_NO_EXTENSIONS
1304- int n;
1305- int handled = 0;
1306-
1307- /* maybe an extension will take care of it for us */
1308-
1309- for (n = 0; n < wsi->count_active_extensions; n++) {
1310- if (!wsi->active_extensions[n]->callback)
1311- continue;
1312-
1313- handled |= wsi->active_extensions[n]->callback(context,
1314- wsi->active_extensions[n], wsi,
1315- LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
1316- wsi->active_extensions_user[n], NULL, 0);
1317- }
1318-
1319- if (handled)
1320- return 1;
1321-#endif
1322- if (wsi->position_in_fds_table < 0) {
1323- lwsl_err("libwebsocket_callback_on_writable: failed to find socket %d\n",
1324- wsi->sock);
1325- return -1;
1326- }
1327-
1328- context->fds[wsi->position_in_fds_table].events |= POLLOUT;
1329-
1330- /* external POLL support via protocol 0 */
1331- context->protocols[0].callback(context, wsi,
1332- LWS_CALLBACK_SET_MODE_POLL_FD,
1333- (void *)(long)wsi->sock, NULL, POLLOUT);
1334-
1335- return 1;
1336-}
1337-
1338-/**
1339- * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
1340- * all connections using the given protocol when it
1341- * becomes possible to write to each socket without
1342- * blocking in turn.
1343- *
1344- * @protocol: Protocol whose connections will get callbacks
1345- */
1346-
1347-int
1348-libwebsocket_callback_on_writable_all_protocol(
1349- const struct libwebsocket_protocols *protocol)
1350-{
1351- struct libwebsocket_context *context = protocol->owning_server;
1352- int n;
1353- struct libwebsocket *wsi;
1354-
1355- for (n = 0; n < context->fds_count; n++) {
1356- wsi = context->lws_lookup[context->fds[n].fd];
1357- if (!wsi)
1358- continue;
1359- if (wsi->protocol == protocol)
1360- libwebsocket_callback_on_writable(context, wsi);
1361- }
1362-
1363- return 0;
1364-}
1365-
1366-/**
1367- * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
1368- *
1369- * You will not need this unless you are doing something special
1370- *
1371- * @wsi: Websocket connection instance
1372- * @reason: timeout reason
1373- * @secs: how many seconds
1374- */
1375-
1376-void
1377-libwebsocket_set_timeout(struct libwebsocket *wsi,
1378- enum pending_timeout reason, int secs)
1379-{
1380- struct timeval tv;
1381-
1382- gettimeofday(&tv, NULL);
1383-
1384- wsi->pending_timeout_limit = tv.tv_sec + secs;
1385- wsi->pending_timeout = reason;
1386-}
1387-
1388-
1389-/**
1390- * libwebsocket_get_socket_fd() - returns the socket file descriptor
1391- *
1392- * You will not need this unless you are doing something special
1393- *
1394- * @wsi: Websocket connection instance
1395- */
1396-
1397-int
1398-libwebsocket_get_socket_fd(struct libwebsocket *wsi)
1399-{
1400- return wsi->sock;
1401-}
1402-
1403-#ifdef LWS_LATENCY
1404-void
1405-lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
1406- const char *action, int ret, int completed)
1407-{
1408- struct timeval tv;
1409- unsigned long u;
1410- char buf[256];
1411-
1412- gettimeofday(&tv, NULL);
1413-
1414- u = (tv.tv_sec * 1000000) + tv.tv_usec;
1415-
1416- if (action) {
1417- if (completed) {
1418- if (wsi->action_start == wsi->latency_start)
1419- sprintf(buf,
1420- "Completion first try lat %luus: %p: ret %d: %s\n",
1421- u - wsi->latency_start,
1422- (void *)wsi, ret, action);
1423- else
1424- sprintf(buf,
1425- "Completion %luus: lat %luus: %p: ret %d: %s\n",
1426- u - wsi->action_start,
1427- u - wsi->latency_start,
1428- (void *)wsi, ret, action);
1429- wsi->action_start = 0;
1430- } else
1431- sprintf(buf, "lat %luus: %p: ret %d: %s\n",
1432- u - wsi->latency_start,
1433- (void *)wsi, ret, action);
1434- if (u - wsi->latency_start > context->worst_latency) {
1435- context->worst_latency = u - wsi->latency_start;
1436- strcpy(context->worst_latency_info, buf);
1437- }
1438- lwsl_latency("%s", buf);
1439- } else {
1440- wsi->latency_start = u;
1441- if (!wsi->action_start)
1442- wsi->action_start = u;
1443- }
1444-}
1445-#endif
1446-
1447-#ifdef LWS_NO_SERVER
1448-int
1449-_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1450-{
1451- return 0;
1452-}
1453-#else
1454-int
1455-_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1456-{
1457- struct libwebsocket_context *context = wsi->protocol->owning_server;
1458- int n;
1459-
1460- if (!(wsi->u.ws.rxflow_change_to & 2))
1461- return 0;
1462-
1463- wsi->u.ws.rxflow_change_to &= ~2;
1464-
1465- lwsl_info("rxflow: wsi %p change_to %d\n",
1466- wsi, wsi->u.ws.rxflow_change_to);
1467-
1468- /* if we're letting it come again, did we interrupt anything? */
1469- if ((wsi->u.ws.rxflow_change_to & 1) && wsi->u.ws.rxflow_buffer) {
1470- n = libwebsocket_interpret_incoming_packet(wsi, NULL, 0);
1471- if (n < 0) {
1472- lwsl_info("libwebsocket_rx_flow_control: close req\n");
1473- return -1;
1474- }
1475- if (n)
1476- /* oh he stuck again, do nothing */
1477- return 0;
1478- }
1479-
1480- if (wsi->u.ws.rxflow_change_to & 1)
1481- context->fds[wsi->position_in_fds_table].events |= POLLIN;
1482- else
1483- context->fds[wsi->position_in_fds_table].events &= ~POLLIN;
1484-
1485- if (wsi->u.ws.rxflow_change_to & 1)
1486- /* external POLL support via protocol 0 */
1487- context->protocols[0].callback(context, wsi,
1488- LWS_CALLBACK_SET_MODE_POLL_FD,
1489- (void *)(long)wsi->sock, NULL, POLLIN);
1490- else
1491- /* external POLL support via protocol 0 */
1492- context->protocols[0].callback(context, wsi,
1493- LWS_CALLBACK_CLEAR_MODE_POLL_FD,
1494- (void *)(long)wsi->sock, NULL, POLLIN);
1495-
1496- return 1;
1497-}
1498-#endif
1499-
1500-/**
1501- * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
1502- * receieved packets.
1503- *
1504- * If the output side of a server process becomes choked, this allows flow
1505- * control for the input side.
1506- *
1507- * @wsi: Websocket connection instance to get callback for
1508- * @enable: 0 = disable read servicing for this connection, 1 = enable
1509- */
1510-
1511-int
1512-libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
1513-{
1514- wsi->u.ws.rxflow_change_to = 2 | !!enable;
1515-
1516- return 0;
1517-}
1518-
1519-
1520-/**
1521- * libwebsocket_canonical_hostname() - returns this host's hostname
1522- *
1523- * This is typically used by client code to fill in the host parameter
1524- * when making a client connection. You can only call it after the context
1525- * has been created.
1526- *
1527- * @context: Websocket context
1528- */
1529-
1530-
1531-extern const char *
1532-libwebsocket_canonical_hostname(struct libwebsocket_context *context)
1533-{
1534- return (const char *)context->canonical_hostname;
1535-}
1536-
1537-
1538-static void sigpipe_handler(int x)
1539-{
1540-}
1541-
1542-#ifdef LWS_OPENSSL_SUPPORT
1543-static int
1544-OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
1545-{
1546-
1547- SSL *ssl;
1548- int n;
1549- struct libwebsocket_context *context;
1550-
1551- ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
1552- SSL_get_ex_data_X509_STORE_CTX_idx());
1553-
1554- /*
1555- * !!! nasty openssl requires the index to come as a library-scope
1556- * static
1557- */
1558- context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
1559-
1560- n = context->protocols[0].callback(NULL, NULL,
1561- LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
1562- x509_ctx, ssl, preverify_ok);
1563-
1564- /* convert return code from 0 = OK to 1 = OK */
1565-
1566- if (!n)
1567- n = 1;
1568- else
1569- n = 0;
1570-
1571- return n;
1572-}
1573-#endif
1574-
1575-int user_callback_handle_rxflow(callback_function callback_function,
1576- struct libwebsocket_context *context,
1577- struct libwebsocket *wsi,
1578- enum libwebsocket_callback_reasons reason, void *user,
1579- void *in, size_t len)
1580-{
1581- int n;
1582-
1583- n = callback_function(context, wsi, reason, user, in, len);
1584- if (!n)
1585- n = _libwebsocket_rx_flow_control(wsi);
1586-
1587- return n;
1588-}
1589-
1590-
1591-/**
1592- * libwebsocket_create_context() - Create the websocket handler
1593- * @info: pointer to struct with parameters
1594- *
1595- * This function creates the listening socket (if serving) and takes care
1596- * of all initialization in one step.
1597- *
1598- * After initialization, it returns a struct libwebsocket_context * that
1599- * represents this server. After calling, user code needs to take care
1600- * of calling libwebsocket_service() with the context pointer to get the
1601- * server's sockets serviced. This can be done in the same process context
1602- * or a forked process, or another thread,
1603- *
1604- * The protocol callback functions are called for a handful of events
1605- * including http requests coming in, websocket connections becoming
1606- * established, and data arriving; it's also called periodically to allow
1607- * async transmission.
1608- *
1609- * HTTP requests are sent always to the FIRST protocol in @protocol, since
1610- * at that time websocket protocol has not been negotiated. Other
1611- * protocols after the first one never see any HTTP callack activity.
1612- *
1613- * The server created is a simple http server by default; part of the
1614- * websocket standard is upgrading this http connection to a websocket one.
1615- *
1616- * This allows the same server to provide files like scripts and favicon /
1617- * images or whatever over http and dynamic data over websockets all in
1618- * one place; they're all handled in the user callback.
1619- */
1620-
1621-struct libwebsocket_context *
1622-libwebsocket_create_context(struct lws_context_creation_info *info)
1623-{
1624- struct libwebsocket_context *context = NULL;
1625- char *p;
1626-#ifndef LWS_NO_SERVER
1627- int n;
1628- int opt = 1;
1629- struct libwebsocket *wsi;
1630- struct sockaddr_in serv_addr;
1631-#endif
1632-#ifndef LWS_NO_EXTENSIONS
1633- int m;
1634- struct libwebsocket_extension *ext;
1635-#endif
1636-
1637-#ifdef LWS_OPENSSL_SUPPORT
1638- SSL_METHOD *method;
1639-#endif
1640-
1641-#ifndef LWS_NO_DAEMONIZE
1642- int pid_daemon = get_daemonize_pid();
1643-#endif
1644-
1645- lwsl_notice("Initial logging level %d\n", log_level);
1646- lwsl_notice("Library version: %s\n", library_version);
1647- lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n",
1648- LWS_MAX_HEADER_NAME_LENGTH);
1649- lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
1650- lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
1651-#ifndef LWS_NO_EXTENSIONS
1652- lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n",
1653- LWS_MAX_EXTENSIONS_ACTIVE);
1654-#else
1655- lwsl_notice(" Configured without extension support\n");
1656-#endif
1657- lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
1658- lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
1659- lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
1660- lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
1661- lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
1662-
1663-#ifdef _WIN32
1664- {
1665- WORD wVersionRequested;
1666- WSADATA wsaData;
1667- int err;
1668- HMODULE wsdll;
1669-
1670- /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
1671- wVersionRequested = MAKEWORD(2, 2);
1672-
1673- err = WSAStartup(wVersionRequested, &wsaData);
1674- if (err != 0) {
1675- /* Tell the user that we could not find a usable */
1676- /* Winsock DLL. */
1677- lwsl_err("WSAStartup failed with error: %d\n", err);
1678- return NULL;
1679- }
1680-
1681- /* default to a poll() made out of select() */
1682- poll = emulated_poll;
1683-
1684- /* if windows socket lib available, use his WSAPoll */
1685- wsdll = GetModuleHandle(_T("Ws2_32.dll"));
1686- if (wsdll)
1687- poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
1688-
1689- /* Finally fall back to emulated poll if all else fails */
1690- if (!poll)
1691- poll = emulated_poll;
1692- }
1693-#endif
1694-
1695- context = (struct libwebsocket_context *)
1696- malloc(sizeof(struct libwebsocket_context));
1697- if (!context) {
1698- lwsl_err("No memory for websocket context\n");
1699- return NULL;
1700- }
1701- memset(context, 0, sizeof(*context));
1702-#ifndef LWS_NO_DAEMONIZE
1703- context->started_with_parent = pid_daemon;
1704- lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
1705-#endif
1706-
1707- context->listen_service_extraseen = 0;
1708- context->protocols = info->protocols;
1709- context->listen_port = info->port;
1710- context->http_proxy_port = 0;
1711- context->http_proxy_address[0] = '\0';
1712- context->options = info->options;
1713- /* to reduce this allocation, */
1714- context->max_fds = getdtablesize();
1715- lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n",
1716- sizeof(struct libwebsocket_context),
1717- sizeof(struct pollfd) + sizeof(struct libwebsocket *),
1718- context->max_fds,
1719- sizeof(struct libwebsocket_context) +
1720- ((sizeof(struct pollfd) + sizeof(struct libwebsocket *)) *
1721- context->max_fds));
1722-
1723- context->fds = (struct pollfd *)malloc(sizeof(struct pollfd) *
1724- context->max_fds);
1725- if (context->fds == NULL) {
1726- lwsl_err("Unable to allocate fds array for %d connections\n",
1727- context->max_fds);
1728- free(context);
1729- return NULL;
1730- }
1731- context->lws_lookup = (struct libwebsocket **)
1732- malloc(sizeof(struct libwebsocket *) * context->max_fds);
1733- if (context->lws_lookup == NULL) {
1734- lwsl_err(
1735- "Unable to allocate lws_lookup array for %d connections\n",
1736- context->max_fds);
1737- free(context->fds);
1738- free(context);
1739- return NULL;
1740- }
1741-
1742- context->fds_count = 0;
1743-#ifndef LWS_NO_EXTENSIONS
1744- context->extensions = info->extensions;
1745-#endif
1746- context->last_timeout_check_s = 0;
1747- context->user_space = info->user;
1748-
1749-#ifdef WIN32
1750- context->fd_random = 0;
1751-#else
1752- context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
1753- if (context->fd_random < 0) {
1754- lwsl_err("Unable to open random device %s %d\n",
1755- SYSTEM_RANDOM_FILEPATH, context->fd_random);
1756- goto bail;
1757- }
1758-#endif
1759-
1760-#ifdef LWS_OPENSSL_SUPPORT
1761- context->use_ssl = 0;
1762- context->ssl_ctx = NULL;
1763- context->ssl_client_ctx = NULL;
1764- openssl_websocket_private_data_index = 0;
1765-#endif
1766-
1767- strcpy(context->canonical_hostname, "unknown");
1768-
1769-#ifndef LWS_NO_SERVER
1770- if (!(info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) {
1771- struct sockaddr sa;
1772- context->service_buffer[0] = '\0';
1773-
1774- /* find canonical hostname */
1775-
1776- context->service_buffer[
1777- sizeof(context->service_buffer) - 1] = '\0';
1778- memset(&sa, 0, sizeof(sa));
1779- sa.sa_family = AF_INET;
1780- sa.sa_data[sizeof(sa.sa_data) - 1] = '\0';
1781- gethostname((char *)context->service_buffer,
1782- sizeof(context->service_buffer) - 1);
1783-
1784- n = 0;
1785-
1786- if (strlen((char *)context->service_buffer) <
1787- sizeof(sa.sa_data) - 1) {
1788- strcpy(sa.sa_data, (char *)context->service_buffer);
1789- lwsl_debug("my host name is %s\n", sa.sa_data);
1790- n = getnameinfo(&sa, sizeof(sa),
1791- (char *)context->service_buffer,
1792- sizeof(context->service_buffer) - 1,
1793- NULL, 0, NI_NAMEREQD);
1794- }
1795-
1796- if (!n) {
1797- strncpy(context->canonical_hostname,
1798- (char *)context->service_buffer,
1799- sizeof(context->canonical_hostname) - 1);
1800- context->canonical_hostname[
1801- sizeof(context->canonical_hostname) - 1] = '\0';
1802- } else
1803- strncpy(context->canonical_hostname,
1804- (char *)context->service_buffer,
1805- sizeof(context->canonical_hostname) - 1);
1806-
1807- lwsl_notice(" canonical_hostname = %s\n",
1808- context->canonical_hostname);
1809- }
1810-#endif
1811-
1812- /* split the proxy ads:port if given */
1813-
1814- p = getenv("http_proxy");
1815- if (p) {
1816- strncpy(context->http_proxy_address, p,
1817- sizeof(context->http_proxy_address) - 1);
1818- context->http_proxy_address[
1819- sizeof(context->http_proxy_address) - 1] = '\0';
1820-
1821- p = strchr(context->http_proxy_address, ':');
1822- if (p == NULL) {
1823- lwsl_err("http_proxy needs to be ads:port\n");
1824- goto bail;
1825- }
1826- *p = '\0';
1827- context->http_proxy_port = atoi(p + 1);
1828-
1829- lwsl_notice(" Proxy %s:%u\n",
1830- context->http_proxy_address,
1831- context->http_proxy_port);
1832- }
1833-
1834-#ifndef LWS_NO_SERVER
1835- if (info->port) {
1836-
1837-#ifdef LWS_OPENSSL_SUPPORT
1838- context->use_ssl = info->ssl_cert_filepath != NULL &&
1839- info->ssl_private_key_filepath != NULL;
1840-#ifdef USE_CYASSL
1841- lwsl_notice(" Compiled with CYASSL support\n");
1842-#else
1843- lwsl_notice(" Compiled with OpenSSL support\n");
1844-#endif
1845- if (context->use_ssl)
1846- lwsl_notice(" Using SSL mode\n");
1847- else
1848- lwsl_notice(" Using non-SSL mode\n");
1849-
1850-#else
1851- if (info->ssl_cert_filepath != NULL &&
1852- info->ssl_private_key_filepath != NULL) {
1853- lwsl_notice(" Not compiled for OpenSSl support!\n");
1854- goto bail;
1855- }
1856- lwsl_notice(" Compiled without SSL support\n");
1857-#endif
1858-
1859- lwsl_notice(
1860- " per-conn mem: %u + %u headers + protocol rx buf\n",
1861- sizeof(struct libwebsocket),
1862- sizeof(struct allocated_headers));
1863- }
1864-#endif
1865-
1866- /* ignore SIGPIPE */
1867-#ifdef WIN32
1868-#else
1869- signal(SIGPIPE, sigpipe_handler);
1870-#endif
1871-
1872-
1873-#ifdef LWS_OPENSSL_SUPPORT
1874-
1875- /* basic openssl init */
1876-
1877- SSL_library_init();
1878-
1879- OpenSSL_add_all_algorithms();
1880- SSL_load_error_strings();
1881-
1882- openssl_websocket_private_data_index =
1883- SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
1884-
1885- /*
1886- * Firefox insists on SSLv23 not SSLv3
1887- * Konq disables SSLv2 by default now, SSLv23 works
1888- */
1889-
1890- method = (SSL_METHOD *)SSLv23_server_method();
1891- if (!method) {
1892- lwsl_err("problem creating ssl method: %s\n",
1893- ERR_error_string(ERR_get_error(),
1894- (char *)context->service_buffer));
1895- goto bail;
1896- }
1897- context->ssl_ctx = SSL_CTX_new(method); /* create context */
1898- if (!context->ssl_ctx) {
1899- lwsl_err("problem creating ssl context: %s\n",
1900- ERR_error_string(ERR_get_error(),
1901- (char *)context->service_buffer));
1902- goto bail;
1903- }
1904-
1905-#ifdef SSL_OP_NO_COMPRESSION
1906- SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
1907-#endif
1908- SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
1909- SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
1910-
1911-#ifndef LWS_NO_CLIENT
1912-
1913- /* client context */
1914-
1915- if (info->port == CONTEXT_PORT_NO_LISTEN) {
1916- method = (SSL_METHOD *)SSLv23_client_method();
1917- if (!method) {
1918- lwsl_err("problem creating ssl method: %s\n",
1919- ERR_error_string(ERR_get_error(),
1920- (char *)context->service_buffer));
1921- goto bail;
1922- }
1923- /* create context */
1924- context->ssl_client_ctx = SSL_CTX_new(method);
1925- if (!context->ssl_client_ctx) {
1926- lwsl_err("problem creating ssl context: %s\n",
1927- ERR_error_string(ERR_get_error(),
1928- (char *)context->service_buffer));
1929- goto bail;
1930- }
1931-
1932-#ifdef SSL_OP_NO_COMPRESSION
1933- SSL_CTX_set_options(context->ssl_client_ctx,
1934- SSL_OP_NO_COMPRESSION);
1935-#endif
1936- SSL_CTX_set_options(context->ssl_client_ctx,
1937- SSL_OP_CIPHER_SERVER_PREFERENCE);
1938- SSL_CTX_set_cipher_list(context->ssl_client_ctx,
1939- CIPHERS_LIST_STRING);
1940-
1941- /* openssl init for cert verification (for client sockets) */
1942- if (!info->ssl_ca_filepath) {
1943- if (!SSL_CTX_load_verify_locations(
1944- context->ssl_client_ctx, NULL,
1945- LWS_OPENSSL_CLIENT_CERTS))
1946- lwsl_err(
1947- "Unable to load SSL Client certs from %s "
1948- "(set by --with-client-cert-dir= "
1949- "in configure) -- client ssl isn't "
1950- "going to work", LWS_OPENSSL_CLIENT_CERTS);
1951- } else
1952- if (!SSL_CTX_load_verify_locations(
1953- context->ssl_client_ctx, info->ssl_ca_filepath,
1954- NULL))
1955- lwsl_err(
1956- "Unable to load SSL Client certs "
1957- "file from %s -- client ssl isn't "
1958- "going to work", info->ssl_ca_filepath);
1959-
1960- /*
1961- * callback allowing user code to load extra verification certs
1962- * helping the client to verify server identity
1963- */
1964-
1965- context->protocols[0].callback(context, NULL,
1966- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
1967- context->ssl_client_ctx, NULL, 0);
1968- }
1969-#endif
1970-
1971- /* as a server, are we requiring clients to identify themselves? */
1972-
1973- if (info->options &
1974- LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
1975-
1976- /* absolutely require the client cert */
1977-
1978- SSL_CTX_set_verify(context->ssl_ctx,
1979- SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1980- OpenSSL_verify_callback);
1981-
1982- /*
1983- * give user code a chance to load certs into the server
1984- * allowing it to verify incoming client certs
1985- */
1986-
1987- context->protocols[0].callback(context, NULL,
1988- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
1989- context->ssl_ctx, NULL, 0);
1990- }
1991-
1992- if (context->use_ssl) {
1993-
1994- /* openssl init for server sockets */
1995-
1996- /* set the local certificate from CertFile */
1997- n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
1998- info->ssl_cert_filepath);
1999- if (n != 1) {
2000- lwsl_err("problem getting cert '%s': %s\n",
2001- info->ssl_cert_filepath,
2002- ERR_error_string(ERR_get_error(),
2003- (char *)context->service_buffer));
2004- goto bail;
2005- }
2006- /* set the private key from KeyFile */
2007- if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2008- info->ssl_private_key_filepath,
2009- SSL_FILETYPE_PEM) != 1) {
2010- lwsl_err("ssl problem getting key '%s': %s\n",
2011- info->ssl_private_key_filepath,
2012- ERR_error_string(ERR_get_error(),
2013- (char *)context->service_buffer));
2014- goto bail;
2015- }
2016- /* verify private key */
2017- if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
2018- lwsl_err("Private SSL key doesn't match cert\n");
2019- goto bail;
2020- }
2021-
2022- /* SSL is happy and has a cert it's content with */
2023- }
2024-#endif
2025-
2026- /* selftest */
2027-
2028- if (lws_b64_selftest())
2029- goto bail;
2030-
2031-#ifndef LWS_NO_SERVER
2032- /* set up our external listening socket we serve on */
2033-
2034- if (info->port) {
2035- int sockfd;
2036-
2037- sockfd = socket(AF_INET, SOCK_STREAM, 0);
2038- if (sockfd < 0) {
2039- lwsl_err("ERROR opening socket\n");
2040- goto bail;
2041- }
2042-
2043-#ifndef WIN32
2044- /*
2045- * allow us to restart even if old sockets in TIME_WAIT
2046- * (REUSEADDR on Unix means, "don't hang on to this
2047- * address after the listener is closed." On Windows, though,
2048- * it means "don't keep other processes from binding to
2049- * this address while we're using it)
2050- */
2051- setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2052- (const void *)&opt, sizeof(opt));
2053-#endif
2054-
2055- /* Disable Nagle */
2056- opt = 1;
2057- setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2058- (const void *)&opt, sizeof(opt));
2059-
2060- #ifdef WIN32
2061- opt = 0;
2062- ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt);
2063- #else
2064- fcntl(sockfd, F_SETFL, O_NONBLOCK);
2065- #endif
2066-
2067- bzero((char *) &serv_addr, sizeof(serv_addr));
2068- serv_addr.sin_family = AF_INET;
2069- if (info->iface == NULL)
2070- serv_addr.sin_addr.s_addr = INADDR_ANY;
2071- else
2072- interface_to_sa(info->iface, &serv_addr,
2073- sizeof(serv_addr));
2074- serv_addr.sin_port = htons(info->port);
2075-
2076- n = bind(sockfd, (struct sockaddr *) &serv_addr,
2077- sizeof(serv_addr));
2078- if (n < 0) {
2079- lwsl_err("ERROR on binding to port %d (%d %d)\n",
2080- info->port, n, errno);
2081- close(sockfd);
2082- goto bail;
2083- }
2084-
2085- wsi = (struct libwebsocket *)malloc(
2086- sizeof(struct libwebsocket));
2087- if (wsi == NULL) {
2088- lwsl_err("Out of mem\n");
2089- close(sockfd);
2090- goto bail;
2091- }
2092- memset(wsi, 0, sizeof(struct libwebsocket));
2093- wsi->sock = sockfd;
2094-#ifndef LWS_NO_EXTENSIONS
2095- wsi->count_active_extensions = 0;
2096-#endif
2097- wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
2098-
2099- insert_wsi_socket_into_fds(context, wsi);
2100-
2101- context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
2102- context->listen_service_count = 0;
2103- context->listen_service_fd = sockfd;
2104-
2105- listen(sockfd, LWS_SOMAXCONN);
2106- lwsl_notice(" Listening on port %d\n", info->port);
2107- }
2108-#endif
2109-
2110- /*
2111- * drop any root privs for this process
2112- * to listen on port < 1023 we would have needed root, but now we are
2113- * listening, we don't want the power for anything else
2114- */
2115-#ifdef WIN32
2116-#else
2117- if (info->gid != -1)
2118- if (setgid(info->gid))
2119- lwsl_warn("setgid: %s\n", strerror(errno));
2120- if (info->uid != -1)
2121- if (setuid(info->uid))
2122- lwsl_warn("setuid: %s\n", strerror(errno));
2123-#endif
2124-
2125- /* initialize supported protocols */
2126-
2127- for (context->count_protocols = 0;
2128- info->protocols[context->count_protocols].callback;
2129- context->count_protocols++) {
2130-
2131- lwsl_parser(" Protocol: %s\n",
2132- info->protocols[context->count_protocols].name);
2133-
2134- info->protocols[context->count_protocols].owning_server =
2135- context;
2136- info->protocols[context->count_protocols].protocol_index =
2137- context->count_protocols;
2138-
2139- /*
2140- * inform all the protocols that they are doing their one-time
2141- * initialization if they want to
2142- */
2143- info->protocols[context->count_protocols].callback(context,
2144- NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0);
2145- }
2146-
2147-#ifndef LWS_NO_EXTENSIONS
2148- /*
2149- * give all extensions a chance to create any per-context
2150- * allocations they need
2151- */
2152-
2153- m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
2154- if (info->port)
2155- m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
2156-
2157- if (info->extensions) {
2158- ext = info->extensions;
2159- while (ext->callback) {
2160- lwsl_ext(" Extension: %s\n", ext->name);
2161- ext->callback(context, ext, NULL,
2162- (enum libwebsocket_extension_callback_reasons)m,
2163- NULL, NULL, 0);
2164- ext++;
2165- }
2166- }
2167-#endif
2168- return context;
2169-
2170-bail:
2171- libwebsocket_context_destroy(context);
2172- return NULL;
2173-}
2174-
2175-/**
2176- * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
2177- * connection.
2178- * @wsi: pointer to struct websocket you want to know the protocol of
2179- *
2180- *
2181- * Some apis can act on all live connections of a given protocol,
2182- * this is how you can get a pointer to the active protocol if needed.
2183- */
2184-
2185-const struct libwebsocket_protocols *
2186-libwebsockets_get_protocol(struct libwebsocket *wsi)
2187-{
2188- return wsi->protocol;
2189-}
2190-
2191-int
2192-libwebsocket_is_final_fragment(struct libwebsocket *wsi)
2193-{
2194- return wsi->u.ws.final;
2195-}
2196-
2197-unsigned char
2198-libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
2199-{
2200- return wsi->u.ws.rsv;
2201-}
2202-
2203-void *
2204-libwebsocket_ensure_user_space(struct libwebsocket *wsi)
2205-{
2206- /* allocate the per-connection user memory (if any) */
2207-
2208- if (wsi->protocol->per_session_data_size && !wsi->user_space) {
2209- wsi->user_space = malloc(
2210- wsi->protocol->per_session_data_size);
2211- if (wsi->user_space == NULL) {
2212- lwsl_err("Out of memory for conn user space\n");
2213- return NULL;
2214- }
2215- memset(wsi->user_space, 0,
2216- wsi->protocol->per_session_data_size);
2217- }
2218- return wsi->user_space;
2219-}
2220-
2221-static void lwsl_emit_stderr(int level, const char *line)
2222-{
2223- char buf[300];
2224- struct timeval tv;
2225- int n;
2226-
2227- gettimeofday(&tv, NULL);
2228-
2229- buf[0] = '\0';
2230- for (n = 0; n < LLL_COUNT; n++)
2231- if (level == (1 << n)) {
2232- sprintf(buf, "[%ld:%04d] %s: ", tv.tv_sec,
2233- (int)(tv.tv_usec / 100), log_level_names[n]);
2234- break;
2235- }
2236-
2237- fprintf(stderr, "%s%s", buf, line);
2238-}
2239-
2240-#ifdef WIN32
2241-void lwsl_emit_syslog(int level, const char *line)
2242-{
2243- lwsl_emit_stderr(level, line);
2244-}
2245-#else
2246-void lwsl_emit_syslog(int level, const char *line)
2247-{
2248- int syslog_level = LOG_DEBUG;
2249-
2250- switch (level) {
2251- case LLL_ERR:
2252- syslog_level = LOG_ERR;
2253- break;
2254- case LLL_WARN:
2255- syslog_level = LOG_WARNING;
2256- break;
2257- case LLL_NOTICE:
2258- syslog_level = LOG_NOTICE;
2259- break;
2260- case LLL_INFO:
2261- syslog_level = LOG_INFO;
2262- break;
2263- }
2264- syslog(syslog_level, "%s", line);
2265-}
2266-#endif
2267-
2268-void _lws_log(int filter, const char *format, ...)
2269-{
2270- char buf[256];
2271- va_list ap;
2272-
2273- if (!(log_level & filter))
2274- return;
2275-
2276- va_start(ap, format);
2277- vsnprintf(buf, sizeof(buf), format, ap);
2278- buf[sizeof(buf) - 1] = '\0';
2279- va_end(ap);
2280-
2281- lwsl_emit(filter, buf);
2282-}
2283-
2284-/**
2285- * lws_set_log_level() - Set the logging bitfield
2286- * @level: OR together the LLL_ debug contexts you want output from
2287- * @log_emit_function: NULL to leave it as it is, or a user-supplied
2288- * function to perform log string emission instead of
2289- * the default stderr one.
2290- *
2291- * log level defaults to "err" and "warn" contexts enabled only and
2292- * emission on stderr.
2293- */
2294-
2295-void lws_set_log_level(int level, void (*log_emit_function)(int level,
2296- const char *line))
2297-{
2298- log_level = level;
2299- if (log_emit_function)
2300- lwsl_emit = log_emit_function;
2301-}
2302
2303=== removed directory '.pc/0002-keepalive.patch'
2304=== removed directory '.pc/0002-keepalive.patch/lib'
2305=== removed file '.pc/0002-keepalive.patch/lib/libwebsockets.c'
2306--- .pc/0002-keepalive.patch/lib/libwebsockets.c 2013-03-28 19:10:28 +0000
2307+++ .pc/0002-keepalive.patch/lib/libwebsockets.c 1970-01-01 00:00:00 +0000
2308@@ -1,2251 +0,0 @@
2309-/*
2310- * libwebsockets - small server side websockets and web server implementation
2311- *
2312- * Copyright (C) 2010 Andy Green <andy@warmcat.com>
2313- *
2314- * This library is free software; you can redistribute it and/or
2315- * modify it under the terms of the GNU Lesser General Public
2316- * License as published by the Free Software Foundation:
2317- * version 2.1 of the License.
2318- *
2319- * This library is distributed in the hope that it will be useful,
2320- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2321- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2322- * Lesser General Public License for more details.
2323- *
2324- * You should have received a copy of the GNU Lesser General Public
2325- * License along with this library; if not, write to the Free Software
2326- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
2327- * MA 02110-1301 USA
2328- */
2329-
2330-#include "private-libwebsockets.h"
2331-
2332-#ifdef WIN32
2333-#include <tchar.h>
2334-#include <io.h>
2335-#include <mstcpip.h>
2336-#else
2337-#ifdef LWS_BUILTIN_GETIFADDRS
2338-#include <getifaddrs.h>
2339-#else
2340-#include <ifaddrs.h>
2341-#endif
2342-#include <syslog.h>
2343-#include <sys/un.h>
2344-#include <sys/socket.h>
2345-#include <netdb.h>
2346-#endif
2347-
2348-#ifdef LWS_OPENSSL_SUPPORT
2349-int openssl_websocket_private_data_index;
2350-#endif
2351-
2352-#ifdef __MINGW32__
2353-#include "../win32port/win32helpers/websock-w32.c"
2354-#else
2355-#ifdef __MINGW64__
2356-#include "../win32port/win32helpers/websock-w32.c"
2357-#endif
2358-#endif
2359-
2360-#ifndef LWS_BUILD_HASH
2361-#define LWS_BUILD_HASH "unknown-build-hash"
2362-#endif
2363-
2364-static int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
2365-static void lwsl_emit_stderr(int level, const char *line);
2366-static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
2367-
2368-static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
2369-
2370-static const char * const log_level_names[] = {
2371- "ERR",
2372- "WARN",
2373- "NOTICE",
2374- "INFO",
2375- "DEBUG",
2376- "PARSER",
2377- "HEADER",
2378- "EXTENSION",
2379- "CLIENT",
2380- "LATENCY",
2381-};
2382-
2383-#ifndef LWS_NO_CLIENT
2384- extern int lws_client_socket_service(
2385- struct libwebsocket_context *context,
2386- struct libwebsocket *wsi, struct pollfd *pollfd);
2387-#endif
2388-#ifndef LWS_NO_SERVER
2389- extern int lws_server_socket_service(
2390- struct libwebsocket_context *context,
2391- struct libwebsocket *wsi, struct pollfd *pollfd);
2392-#endif
2393-
2394-/**
2395- * lws_get_library_version: get version and git hash library built from
2396- *
2397- * returns a const char * to a string like "1.1 178d78c"
2398- * representing the library version followed by the git head hash it
2399- * was built from
2400- */
2401-
2402-const char *
2403-lws_get_library_version(void)
2404-{
2405- return library_version;
2406-}
2407-
2408-int
2409-insert_wsi_socket_into_fds(struct libwebsocket_context *context,
2410- struct libwebsocket *wsi)
2411-{
2412- if (context->fds_count >= context->max_fds) {
2413- lwsl_err("Too many fds (%d)\n", context->max_fds);
2414- return 1;
2415- }
2416-
2417- if (wsi->sock > context->max_fds) {
2418- lwsl_err("Socket fd %d is too high (%d)\n",
2419- wsi->sock, context->max_fds);
2420- return 1;
2421- }
2422-
2423- assert(wsi);
2424- assert(wsi->sock);
2425-
2426- lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
2427- wsi, wsi->sock, context->fds_count);
2428-
2429- context->lws_lookup[wsi->sock] = wsi;
2430- wsi->position_in_fds_table = context->fds_count;
2431- context->fds[context->fds_count].fd = wsi->sock;
2432- context->fds[context->fds_count].events = POLLIN;
2433- context->fds[context->fds_count++].revents = 0;
2434-
2435- /* external POLL support via protocol 0 */
2436- context->protocols[0].callback(context, wsi,
2437- LWS_CALLBACK_ADD_POLL_FD,
2438- (void *)(long)wsi->sock, NULL, POLLIN);
2439-
2440- return 0;
2441-}
2442-
2443-static int
2444-remove_wsi_socket_from_fds(struct libwebsocket_context *context,
2445- struct libwebsocket *wsi)
2446-{
2447- int m;
2448-
2449- if (!--context->fds_count)
2450- goto do_ext;
2451-
2452- if (wsi->sock > context->max_fds) {
2453- lwsl_err("Socket fd %d too high (%d)\n",
2454- wsi->sock, context->max_fds);
2455- return 1;
2456- }
2457-
2458- lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n",
2459- wsi, wsi->sock, wsi->position_in_fds_table);
2460-
2461- m = wsi->position_in_fds_table; /* replace the contents for this */
2462-
2463- /* have the last guy take up the vacant slot */
2464- context->fds[m] = context->fds[context->fds_count];
2465- /*
2466- * end guy's fds_lookup entry remains unchanged
2467- * (still same fd pointing to same wsi)
2468- */
2469- /* end guy's "position in fds table" changed */
2470- context->lws_lookup[context->fds[context->fds_count].fd]->
2471- position_in_fds_table = m;
2472- /* deletion guy's lws_lookup entry needs nuking */
2473- context->lws_lookup[wsi->sock] = NULL;
2474- /* removed wsi has no position any more */
2475- wsi->position_in_fds_table = -1;
2476-
2477-do_ext:
2478- /* remove also from external POLL support via protocol 0 */
2479- if (wsi->sock)
2480- context->protocols[0].callback(context, wsi,
2481- LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
2482-
2483- return 0;
2484-}
2485-
2486-
2487-void
2488-libwebsocket_close_and_free_session(struct libwebsocket_context *context,
2489- struct libwebsocket *wsi, enum lws_close_status reason)
2490-{
2491- int n;
2492- int old_state;
2493- unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
2494- LWS_SEND_BUFFER_POST_PADDING];
2495-#ifndef LWS_NO_EXTENSIONS
2496- int ret;
2497- int m;
2498- struct lws_tokens eff_buf;
2499- struct libwebsocket_extension *ext;
2500-#endif
2501-
2502- if (!wsi)
2503- return;
2504-
2505- old_state = wsi->state;
2506-
2507- if (old_state == WSI_STATE_DEAD_SOCKET)
2508- return;
2509-
2510- wsi->u.ws.close_reason = reason;
2511-
2512- if (wsi->mode == LWS_CONNMODE_HTTP_SERVING && wsi->u.http.fd) {
2513- close(wsi->u.http.fd);
2514- wsi->u.http.fd = 0;
2515- }
2516-
2517-#ifndef LWS_NO_EXTENSIONS
2518- /*
2519- * are his extensions okay with him closing? Eg he might be a mux
2520- * parent and just his ch1 aspect is closing?
2521- */
2522-
2523- for (n = 0; n < wsi->count_active_extensions; n++) {
2524- if (!wsi->active_extensions[n]->callback)
2525- continue;
2526-
2527- m = wsi->active_extensions[n]->callback(context,
2528- wsi->active_extensions[n], wsi,
2529- LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
2530- wsi->active_extensions_user[n], NULL, 0);
2531-
2532- /*
2533- * if somebody vetoed actually closing him at this time....
2534- * up to the extension to track the attempted close, let's
2535- * just bail
2536- */
2537-
2538- if (m) {
2539- lwsl_ext("extension vetoed close\n");
2540- return;
2541- }
2542- }
2543-
2544- /*
2545- * flush any tx pending from extensions, since we may send close packet
2546- * if there are problems with send, just nuke the connection
2547- */
2548-
2549- ret = 1;
2550- while (ret == 1) {
2551-
2552- /* default to nobody has more to spill */
2553-
2554- ret = 0;
2555- eff_buf.token = NULL;
2556- eff_buf.token_len = 0;
2557-
2558- /* show every extension the new incoming data */
2559-
2560- for (n = 0; n < wsi->count_active_extensions; n++) {
2561- m = wsi->active_extensions[n]->callback(
2562- wsi->protocol->owning_server,
2563- wsi->active_extensions[n], wsi,
2564- LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
2565- wsi->active_extensions_user[n], &eff_buf, 0);
2566- if (m < 0) {
2567- lwsl_ext("Extension reports fatal error\n");
2568- goto just_kill_connection;
2569- }
2570- if (m)
2571- /*
2572- * at least one extension told us he has more
2573- * to spill, so we will go around again after
2574- */
2575- ret = 1;
2576- }
2577-
2578- /* assuming they left us something to send, send it */
2579-
2580- if (eff_buf.token_len)
2581- if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
2582- eff_buf.token_len)) {
2583- lwsl_debug("close: ext spill failed\n");
2584- goto just_kill_connection;
2585- }
2586- }
2587-#endif
2588-
2589- /*
2590- * signal we are closing, libsocket_write will
2591- * add any necessary version-specific stuff. If the write fails,
2592- * no worries we are closing anyway. If we didn't initiate this
2593- * close, then our state has been changed to
2594- * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
2595- *
2596- * Likewise if it's a second call to close this connection after we
2597- * sent the close indication to the peer already, we are in state
2598- * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
2599- */
2600-
2601- if (old_state == WSI_STATE_ESTABLISHED &&
2602- reason != LWS_CLOSE_STATUS_NOSTATUS) {
2603-
2604- lwsl_debug("sending close indication...\n");
2605-
2606- /* make valgrind happy */
2607- memset(buf, 0, sizeof(buf));
2608- n = libwebsocket_write(wsi,
2609- &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
2610- 0, LWS_WRITE_CLOSE);
2611- if (!n) {
2612- /*
2613- * we have sent a nice protocol level indication we
2614- * now wish to close, we should not send anything more
2615- */
2616-
2617- wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
2618-
2619- /*
2620- * ...and we should wait for a reply for a bit
2621- * out of politeness
2622- */
2623-
2624- libwebsocket_set_timeout(wsi,
2625- PENDING_TIMEOUT_CLOSE_ACK, 1);
2626-
2627- lwsl_debug("sent close indication, awaiting ack\n");
2628-
2629- return;
2630- }
2631-
2632- lwsl_info("close: sending close packet failed, hanging up\n");
2633-
2634- /* else, the send failed and we should just hang up */
2635- }
2636-
2637-#ifndef LWS_NO_EXTENSIONS
2638-just_kill_connection:
2639-#endif
2640-
2641- lwsl_debug("close: just_kill_connection\n");
2642-
2643- /*
2644- * we won't be servicing or receiving anything further from this guy
2645- * delete socket from the internal poll list if still present
2646- */
2647-
2648- remove_wsi_socket_from_fds(context, wsi);
2649-
2650- wsi->state = WSI_STATE_DEAD_SOCKET;
2651-
2652- if ((old_state == WSI_STATE_ESTABLISHED ||
2653- wsi->mode == LWS_CONNMODE_WS_SERVING ||
2654- wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
2655-
2656- if (wsi->u.ws.rx_user_buffer) {
2657- free(wsi->u.ws.rx_user_buffer);
2658- wsi->u.ws.rx_user_buffer = NULL;
2659- }
2660- if (wsi->u.ws.rxflow_buffer) {
2661- free(wsi->u.ws.rxflow_buffer);
2662- wsi->u.ws.rxflow_buffer = NULL;
2663- }
2664- }
2665-
2666- /* tell the user it's all over for this guy */
2667-
2668- if (wsi->protocol && wsi->protocol->callback &&
2669- ((old_state == WSI_STATE_ESTABLISHED) ||
2670- (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
2671- (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
2672- lwsl_debug("calling back CLOSED\n");
2673- wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
2674- wsi->user_space, NULL, 0);
2675- } else
2676- lwsl_debug("not calling back closed\n");
2677-
2678-#ifndef LWS_NO_EXTENSIONS
2679- /* deallocate any active extension contexts */
2680-
2681- for (n = 0; n < wsi->count_active_extensions; n++) {
2682- if (!wsi->active_extensions[n]->callback)
2683- continue;
2684-
2685- wsi->active_extensions[n]->callback(context,
2686- wsi->active_extensions[n], wsi,
2687- LWS_EXT_CALLBACK_DESTROY,
2688- wsi->active_extensions_user[n], NULL, 0);
2689-
2690- free(wsi->active_extensions_user[n]);
2691- }
2692-
2693- /*
2694- * inform all extensions in case they tracked this guy out of band
2695- * even though not active on him specifically
2696- */
2697-
2698- ext = context->extensions;
2699- while (ext && ext->callback) {
2700- ext->callback(context, ext, wsi,
2701- LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
2702- NULL, NULL, 0);
2703- ext++;
2704- }
2705-#endif
2706-
2707-/* lwsl_info("closing fd=%d\n", wsi->sock); */
2708-
2709-#ifdef LWS_OPENSSL_SUPPORT
2710- if (wsi->ssl) {
2711- n = SSL_get_fd(wsi->ssl);
2712- SSL_shutdown(wsi->ssl);
2713- compatible_close(n);
2714- SSL_free(wsi->ssl);
2715- } else {
2716-#endif
2717- if (wsi->sock) {
2718- n = shutdown(wsi->sock, SHUT_RDWR);
2719- if (n)
2720- lwsl_debug("closing: shutdown returned %d\n",
2721- errno);
2722-
2723- n = compatible_close(wsi->sock);
2724- if (n)
2725- lwsl_debug("closing: close returned %d\n",
2726- errno);
2727- }
2728-#ifdef LWS_OPENSSL_SUPPORT
2729- }
2730-#endif
2731- if (wsi->protocol && wsi->protocol->per_session_data_size &&
2732- wsi->user_space) /* user code may own */
2733- free(wsi->user_space);
2734-
2735- free(wsi);
2736-}
2737-
2738-/**
2739- * libwebsockets_get_peer_addresses() - Get client address information
2740- * @context: Libwebsockets context
2741- * @wsi: Local struct libwebsocket associated with
2742- * @fd: Connection socket descriptor
2743- * @name: Buffer to take client address name
2744- * @name_len: Length of client address name buffer
2745- * @rip: Buffer to take client address IP qotted quad
2746- * @rip_len: Length of client address IP buffer
2747- *
2748- * This function fills in @name and @rip with the name and IP of
2749- * the client connected with socket descriptor @fd. Names may be
2750- * truncated if there is not enough room. If either cannot be
2751- * determined, they will be returned as valid zero-length strings.
2752- */
2753-
2754-void
2755-libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
2756- struct libwebsocket *wsi, int fd, char *name, int name_len,
2757- char *rip, int rip_len)
2758-{
2759- unsigned int len;
2760- struct sockaddr_in sin;
2761- struct hostent *host;
2762- struct hostent *host1;
2763- char ip[128];
2764- unsigned char *p;
2765- int n;
2766- int ret = -1;
2767-#ifdef AF_LOCAL
2768- struct sockaddr_un *un;
2769-#endif
2770-
2771- rip[0] = '\0';
2772- name[0] = '\0';
2773-
2774- lws_latency_pre(context, wsi);
2775-
2776- len = sizeof(sin);
2777- if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
2778- perror("getpeername");
2779- goto bail;
2780- }
2781-
2782- host = gethostbyaddr((char *) &sin.sin_addr, sizeof(sin.sin_addr),
2783- AF_INET);
2784- if (host == NULL) {
2785- perror("gethostbyaddr");
2786- goto bail;
2787- }
2788-
2789- strncpy(name, host->h_name, name_len);
2790- name[name_len - 1] = '\0';
2791-
2792- host1 = gethostbyname(host->h_name);
2793- if (host1 == NULL)
2794- goto bail;
2795- p = (unsigned char *)host1;
2796- n = 0;
2797- while (p != NULL) {
2798- p = (unsigned char *)host1->h_addr_list[n++];
2799- if (p == NULL)
2800- continue;
2801- if ((host1->h_addrtype != AF_INET)
2802-#ifdef AF_LOCAL
2803- && (host1->h_addrtype != AF_LOCAL)
2804-#endif
2805- )
2806- continue;
2807-
2808- if (host1->h_addrtype == AF_INET)
2809- sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
2810-#ifdef AF_LOCAL
2811- else {
2812- un = (struct sockaddr_un *)p;
2813- strncpy(ip, un->sun_path, sizeof(ip) - 1);
2814- ip[sizeof(ip) - 1] = '\0';
2815- }
2816-#endif
2817- p = NULL;
2818- strncpy(rip, ip, rip_len);
2819- rip[rip_len - 1] = '\0';
2820- }
2821-
2822- ret = 0;
2823-bail:
2824- lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
2825-}
2826-
2827-int libwebsockets_get_random(struct libwebsocket_context *context,
2828- void *buf, int len)
2829-{
2830- int n;
2831- char *p = (char *)buf;
2832-
2833-#ifdef WIN32
2834- for (n = 0; n < len; n++)
2835- p[n] = (unsigned char)rand();
2836-#else
2837- n = read(context->fd_random, p, len);
2838-#endif
2839-
2840- return n;
2841-}
2842-
2843-int lws_set_socket_options(struct libwebsocket_context *context, int fd)
2844-{
2845- int optval = 1;
2846- socklen_t optlen = sizeof(optval);
2847-#ifdef WIN32
2848- unsigned long optl = 0;
2849-#endif
2850-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
2851- struct protoent *tcp_proto;
2852-#endif
2853-
2854- if (context->ka_time) {
2855- /* enable keepalive on this socket */
2856- optval = 1;
2857- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
2858- (const void *)&optval, optlen) < 0)
2859- return 1;
2860-
2861-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
2862-
2863- /*
2864- * didn't find a way to set these per-socket, need to
2865- * tune kernel systemwide values
2866- */
2867-#elif WIN32
2868- {
2869- DWORD dwBytesRet;
2870- struct tcp_keepalive alive;
2871- alive.onoff = TRUE;
2872- alive.keepalivetime = context->ka_time;
2873- alive.keepaliveinterval = context->ka_interval;
2874-
2875- if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
2876- NULL, 0, &dwBytesRet, NULL, NULL))
2877- return 1;
2878- }
2879-#else
2880- /* set the keepalive conditions we want on it too */
2881- optval = context->ka_time;
2882- if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE,
2883- (const void *)&optval, optlen) < 0)
2884- return 1;
2885-
2886- optval = context->ka_probes;
2887- if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL,
2888- (const void *)&optval, optlen) < 0)
2889- return 1;
2890-
2891- optval = context->ka_interval;
2892- if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT,
2893- (const void *)&optval, optlen) < 0)
2894- return 1;
2895-#endif
2896- }
2897-
2898- /* Disable Nagle */
2899- optval = 1;
2900-#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
2901- setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
2902-#else
2903- tcp_proto = getprotobyname("TCP");
2904- setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen);
2905-#endif
2906-
2907- /* We are nonblocking... */
2908-#ifdef WIN32
2909- ioctlsocket(fd, FIONBIO, &optl);
2910-#else
2911- fcntl(fd, F_SETFL, O_NONBLOCK);
2912-#endif
2913-
2914- return 0;
2915-}
2916-
2917-int lws_send_pipe_choked(struct libwebsocket *wsi)
2918-{
2919- struct pollfd fds;
2920-
2921- fds.fd = wsi->sock;
2922- fds.events = POLLOUT;
2923- fds.revents = 0;
2924-
2925- if (poll(&fds, 1, 0) != 1)
2926- return 1;
2927-
2928- if ((fds.revents & POLLOUT) == 0)
2929- return 1;
2930-
2931- /* okay to send another packet without blocking */
2932-
2933- return 0;
2934-}
2935-
2936-int
2937-lws_handle_POLLOUT_event(struct libwebsocket_context *context,
2938- struct libwebsocket *wsi, struct pollfd *pollfd)
2939-{
2940- int n;
2941-
2942-#ifndef LWS_NO_EXTENSIONS
2943- struct lws_tokens eff_buf;
2944- int ret;
2945- int m;
2946- int handled = 0;
2947-
2948- for (n = 0; n < wsi->count_active_extensions; n++) {
2949- if (!wsi->active_extensions[n]->callback)
2950- continue;
2951-
2952- m = wsi->active_extensions[n]->callback(context,
2953- wsi->active_extensions[n], wsi,
2954- LWS_EXT_CALLBACK_IS_WRITEABLE,
2955- wsi->active_extensions_user[n], NULL, 0);
2956- if (m > handled)
2957- handled = m;
2958- }
2959-
2960- if (handled == 1)
2961- goto notify_action;
2962-
2963- if (!wsi->extension_data_pending || handled == 2)
2964- goto user_service;
2965-
2966- /*
2967- * check in on the active extensions, see if they
2968- * had pending stuff to spill... they need to get the
2969- * first look-in otherwise sequence will be disordered
2970- *
2971- * NULL, zero-length eff_buf means just spill pending
2972- */
2973-
2974- ret = 1;
2975- while (ret == 1) {
2976-
2977- /* default to nobody has more to spill */
2978-
2979- ret = 0;
2980- eff_buf.token = NULL;
2981- eff_buf.token_len = 0;
2982-
2983- /* give every extension a chance to spill */
2984-
2985- for (n = 0; n < wsi->count_active_extensions; n++) {
2986- m = wsi->active_extensions[n]->callback(
2987- wsi->protocol->owning_server,
2988- wsi->active_extensions[n], wsi,
2989- LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
2990- wsi->active_extensions_user[n], &eff_buf, 0);
2991- if (m < 0) {
2992- lwsl_err("ext reports fatal error\n");
2993- return -1;
2994- }
2995- if (m)
2996- /*
2997- * at least one extension told us he has more
2998- * to spill, so we will go around again after
2999- */
3000- ret = 1;
3001- }
3002-
3003- /* assuming they gave us something to send, send it */
3004-
3005- if (eff_buf.token_len) {
3006- if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
3007- eff_buf.token_len))
3008- return -1;
3009- } else
3010- continue;
3011-
3012- /* no extension has more to spill */
3013-
3014- if (!ret)
3015- continue;
3016-
3017- /*
3018- * There's more to spill from an extension, but we just sent
3019- * something... did that leave the pipe choked?
3020- */
3021-
3022- if (!lws_send_pipe_choked(wsi))
3023- /* no we could add more */
3024- continue;
3025-
3026- lwsl_info("choked in POLLOUT service\n");
3027-
3028- /*
3029- * Yes, he's choked. Leave the POLLOUT masked on so we will
3030- * come back here when he is unchoked. Don't call the user
3031- * callback to enforce ordering of spilling, he'll get called
3032- * when we come back here and there's nothing more to spill.
3033- */
3034-
3035- return 0;
3036- }
3037-
3038- wsi->extension_data_pending = 0;
3039-
3040-user_service:
3041-#endif
3042- /* one shot */
3043-
3044- if (pollfd) {
3045- pollfd->events &= ~POLLOUT;
3046-
3047- /* external POLL support via protocol 0 */
3048- context->protocols[0].callback(context, wsi,
3049- LWS_CALLBACK_CLEAR_MODE_POLL_FD,
3050- (void *)(long)wsi->sock, NULL, POLLOUT);
3051- }
3052-#ifndef LWS_NO_EXTENSIONS
3053-notify_action:
3054-#endif
3055-
3056- if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
3057- n = LWS_CALLBACK_CLIENT_WRITEABLE;
3058- else
3059- n = LWS_CALLBACK_SERVER_WRITEABLE;
3060-
3061- return user_callback_handle_rxflow(wsi->protocol->callback, context,
3062- wsi, (enum libwebsocket_callback_reasons) n,
3063- wsi->user_space, NULL, 0);
3064-}
3065-
3066-
3067-
3068-void
3069-libwebsocket_service_timeout_check(struct libwebsocket_context *context,
3070- struct libwebsocket *wsi, unsigned int sec)
3071-{
3072-#ifndef LWS_NO_EXTENSIONS
3073- int n;
3074-
3075- /*
3076- * if extensions want in on it (eg, we are a mux parent)
3077- * give them a chance to service child timeouts
3078- */
3079-
3080- for (n = 0; n < wsi->count_active_extensions; n++)
3081- wsi->active_extensions[n]->callback(
3082- context, wsi->active_extensions[n],
3083- wsi, LWS_EXT_CALLBACK_1HZ,
3084- wsi->active_extensions_user[n], NULL, sec);
3085-
3086-#endif
3087- if (!wsi->pending_timeout)
3088- return;
3089-
3090- /*
3091- * if we went beyond the allowed time, kill the
3092- * connection
3093- */
3094-
3095- if (sec > wsi->pending_timeout_limit) {
3096- lwsl_info("TIMEDOUT WAITING\n");
3097- libwebsocket_close_and_free_session(context,
3098- wsi, LWS_CLOSE_STATUS_NOSTATUS);
3099- }
3100-}
3101-
3102-/**
3103- * libwebsocket_service_fd() - Service polled socket with something waiting
3104- * @context: Websocket context
3105- * @pollfd: The pollfd entry describing the socket fd and which events
3106- * happened.
3107- *
3108- * This function takes a pollfd that has POLLIN or POLLOUT activity and
3109- * services it according to the state of the associated
3110- * struct libwebsocket.
3111- *
3112- * The one call deals with all "service" that might happen on a socket
3113- * including listen accepts, http files as well as websocket protocol.
3114- */
3115-
3116-int
3117-libwebsocket_service_fd(struct libwebsocket_context *context,
3118- struct pollfd *pollfd)
3119-{
3120- struct libwebsocket *wsi;
3121- int n;
3122- int m;
3123- int listen_socket_fds_index = 0;
3124- struct timeval tv;
3125-
3126-#ifndef LWS_NO_EXTENSIONS
3127- int more = 1;
3128-#endif
3129- struct lws_tokens eff_buf;
3130-
3131- if (context->listen_service_fd)
3132- listen_socket_fds_index = context->lws_lookup[
3133- context->listen_service_fd]->position_in_fds_table;
3134-
3135- /*
3136- * you can call us with pollfd = NULL to just allow the once-per-second
3137- * global timeout checks; if less than a second since the last check
3138- * it returns immediately then.
3139- */
3140-
3141- gettimeofday(&tv, NULL);
3142-
3143- if (context->last_timeout_check_s != tv.tv_sec) {
3144- context->last_timeout_check_s = tv.tv_sec;
3145-
3146- #ifndef WIN32
3147- /* if our parent went down, don't linger around */
3148- if (context->started_with_parent &&
3149- kill(context->started_with_parent, 0) < 0)
3150- kill(getpid(), SIGTERM);
3151- #endif
3152-
3153- /* global timeout check once per second */
3154-
3155- for (n = 0; n < context->fds_count; n++) {
3156- struct libwebsocket *new_wsi =
3157- context->lws_lookup[context->fds[n].fd];
3158- if (!new_wsi)
3159- continue;
3160- libwebsocket_service_timeout_check(context,
3161- new_wsi, tv.tv_sec);
3162- }
3163- }
3164-
3165- /* just here for timeout management? */
3166-
3167- if (pollfd == NULL)
3168- return 0;
3169-
3170- /* no, here to service a socket descriptor */
3171-
3172- /*
3173- * deal with listen service piggybacking
3174- * every listen_service_modulo services of other fds, we
3175- * sneak one in to service the listen socket if there's anything waiting
3176- *
3177- * To handle connection storms, as found in ab, if we previously saw a
3178- * pending connection here, it causes us to check again next time.
3179- */
3180-
3181- if (context->listen_service_fd && pollfd !=
3182- &context->fds[listen_socket_fds_index]) {
3183- context->listen_service_count++;
3184- if (context->listen_service_extraseen ||
3185- context->listen_service_count ==
3186- context->listen_service_modulo) {
3187- context->listen_service_count = 0;
3188- m = 1;
3189- if (context->listen_service_extraseen > 5)
3190- m = 2;
3191- while (m--) {
3192- /*
3193- * even with extpoll, we prepared this
3194- * internal fds for listen
3195- */
3196- n = poll(&context->fds[listen_socket_fds_index],
3197- 1, 0);
3198- if (n > 0) { /* there's a conn waiting for us */
3199- libwebsocket_service_fd(context,
3200- &context->
3201- fds[listen_socket_fds_index]);
3202- context->listen_service_extraseen++;
3203- } else {
3204- if (context->listen_service_extraseen)
3205- context->
3206- listen_service_extraseen--;
3207- break;
3208- }
3209- }
3210- }
3211-
3212- }
3213-
3214- /* okay, what we came here to do... */
3215-
3216- wsi = context->lws_lookup[pollfd->fd];
3217- if (wsi == NULL) {
3218- if (pollfd->fd > 11)
3219- lwsl_err("unexpected NULL wsi fd=%d fds_count=%d\n",
3220- pollfd->fd, context->fds_count);
3221- return 0;
3222- }
3223-
3224- switch (wsi->mode) {
3225-
3226-#ifndef LWS_NO_SERVER
3227- case LWS_CONNMODE_HTTP_SERVING:
3228- case LWS_CONNMODE_SERVER_LISTENER:
3229- case LWS_CONNMODE_SSL_ACK_PENDING:
3230- return lws_server_socket_service(context, wsi, pollfd);
3231-#endif
3232-
3233- case LWS_CONNMODE_WS_SERVING:
3234- case LWS_CONNMODE_WS_CLIENT:
3235-
3236- /* handle session socket closed */
3237-
3238- if (pollfd->revents & (POLLERR | POLLHUP)) {
3239-
3240- lwsl_debug("Session Socket %p (fd=%d) dead\n",
3241- (void *)wsi, pollfd->fd);
3242-
3243- libwebsocket_close_and_free_session(context, wsi,
3244- LWS_CLOSE_STATUS_NOSTATUS);
3245- return 0;
3246- }
3247-
3248- /* the guy requested a callback when it was OK to write */
3249-
3250- if ((pollfd->revents & POLLOUT) &&
3251- wsi->state == WSI_STATE_ESTABLISHED)
3252- if (lws_handle_POLLOUT_event(context, wsi,
3253- pollfd) < 0) {
3254- lwsl_info("libwebsocket_service_fd: closing\n");
3255- libwebsocket_close_and_free_session(
3256- context, wsi, LWS_CLOSE_STATUS_NORMAL);
3257- return 0;
3258- }
3259-
3260-
3261- /* any incoming data ready? */
3262-
3263- if (!(pollfd->revents & POLLIN))
3264- break;
3265-
3266-#ifdef LWS_OPENSSL_SUPPORT
3267-read_pending:
3268- if (wsi->ssl) {
3269- eff_buf.token_len = SSL_read(wsi->ssl,
3270- context->service_buffer,
3271- sizeof(context->service_buffer));
3272- if (!eff_buf.token_len) {
3273- n = SSL_get_error(wsi->ssl, eff_buf.token_len);
3274- lwsl_err("SSL_read returned 0 with reason %s\n",
3275- ERR_error_string(n,
3276- (char *)context->service_buffer));
3277- }
3278- } else
3279-#endif
3280- eff_buf.token_len = recv(pollfd->fd,
3281- context->service_buffer,
3282- sizeof(context->service_buffer), 0);
3283-
3284- if (eff_buf.token_len < 0) {
3285- lwsl_debug("Socket read returned %d\n",
3286- eff_buf.token_len);
3287- if (errno != EINTR && errno != EAGAIN)
3288- libwebsocket_close_and_free_session(context,
3289- wsi, LWS_CLOSE_STATUS_NOSTATUS);
3290- return 0;
3291- }
3292- if (!eff_buf.token_len) {
3293- lwsl_info("closing connection due to 0 length read\n");
3294- libwebsocket_close_and_free_session(context, wsi,
3295- LWS_CLOSE_STATUS_NOSTATUS);
3296- return 0;
3297- }
3298-
3299- /*
3300- * give any active extensions a chance to munge the buffer
3301- * before parse. We pass in a pointer to an lws_tokens struct
3302- * prepared with the default buffer and content length that's in
3303- * there. Rather than rewrite the default buffer, extensions
3304- * that expect to grow the buffer can adapt .token to
3305- * point to their own per-connection buffer in the extension
3306- * user allocation. By default with no extensions or no
3307- * extension callback handling, just the normal input buffer is
3308- * used then so it is efficient.
3309- */
3310-
3311- eff_buf.token = (char *)context->service_buffer;
3312-#ifndef LWS_NO_EXTENSIONS
3313- more = 1;
3314- while (more) {
3315-
3316- more = 0;
3317-
3318- for (n = 0; n < wsi->count_active_extensions; n++) {
3319- m = wsi->active_extensions[n]->callback(context,
3320- wsi->active_extensions[n], wsi,
3321- LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
3322- wsi->active_extensions_user[n],
3323- &eff_buf, 0);
3324- if (m < 0) {
3325- lwsl_ext(
3326- "Extension reports fatal error\n");
3327- libwebsocket_close_and_free_session(
3328- context, wsi,
3329- LWS_CLOSE_STATUS_NOSTATUS);
3330- return 0;
3331- }
3332- if (m)
3333- more = 1;
3334- }
3335-#endif
3336- /* service incoming data */
3337-
3338- if (eff_buf.token_len) {
3339- n = libwebsocket_read(context, wsi,
3340- (unsigned char *)eff_buf.token,
3341- eff_buf.token_len);
3342- if (n < 0)
3343- /* we closed wsi */
3344- return 0;
3345- }
3346-#ifndef LWS_NO_EXTENSIONS
3347- eff_buf.token = NULL;
3348- eff_buf.token_len = 0;
3349- }
3350-#endif
3351-
3352-#ifdef LWS_OPENSSL_SUPPORT
3353- if (wsi->ssl && SSL_pending(wsi->ssl))
3354- goto read_pending;
3355-#endif
3356- break;
3357-
3358- default:
3359-#ifdef LWS_NO_CLIENT
3360- break;
3361-#else
3362- return lws_client_socket_service(context, wsi, pollfd);
3363-#endif
3364- }
3365-
3366- return 0;
3367-}
3368-
3369-
3370-/**
3371- * libwebsocket_context_destroy() - Destroy the websocket context
3372- * @context: Websocket context
3373- *
3374- * This function closes any active connections and then frees the
3375- * context. After calling this, any further use of the context is
3376- * undefined.
3377- */
3378-void
3379-libwebsocket_context_destroy(struct libwebsocket_context *context)
3380-{
3381-#ifndef LWS_NO_EXTENSIONS
3382- int n;
3383- int m;
3384- struct libwebsocket_extension *ext;
3385- struct libwebsocket_protocols *protocol = context->protocols;
3386-
3387-#ifdef LWS_LATENCY
3388- if (context->worst_latency_info[0])
3389- lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
3390-#endif
3391-
3392- for (n = 0; n < context->fds_count; n++) {
3393- struct libwebsocket *wsi =
3394- context->lws_lookup[context->fds[n].fd];
3395- libwebsocket_close_and_free_session(context,
3396- wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
3397- n--;
3398- }
3399-
3400- /*
3401- * give all extensions a chance to clean up any per-context
3402- * allocations they might have made
3403- */
3404-
3405- ext = context->extensions;
3406- m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
3407- if (context->listen_port)
3408- m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
3409- while (ext && ext->callback) {
3410- ext->callback(context, ext, NULL,
3411- (enum libwebsocket_extension_callback_reasons)m,
3412- NULL, NULL, 0);
3413- ext++;
3414- }
3415-
3416- /*
3417- * inform all the protocols that they are done and will have no more
3418- * callbacks
3419- */
3420-
3421- while (protocol->callback) {
3422- protocol->callback(context, NULL, LWS_CALLBACK_PROTOCOL_DESTROY,
3423- NULL, NULL, 0);
3424- protocol++;
3425- }
3426-
3427-#endif
3428-
3429-#ifdef WIN32
3430-#else
3431- close(context->fd_random);
3432-#endif
3433-
3434-#ifdef LWS_OPENSSL_SUPPORT
3435- if (context->ssl_ctx)
3436- SSL_CTX_free(context->ssl_ctx);
3437- if (context->ssl_client_ctx)
3438- SSL_CTX_free(context->ssl_client_ctx);
3439-
3440- ERR_remove_state(0);
3441- ERR_free_strings();
3442- EVP_cleanup();
3443- CRYPTO_cleanup_all_ex_data();
3444-#endif
3445-
3446- if (context->fds)
3447- free(context->fds);
3448- if (context->lws_lookup)
3449- free(context->lws_lookup);
3450-
3451- free(context);
3452-
3453-#ifdef WIN32
3454- WSACleanup();
3455-#endif
3456-}
3457-
3458-/**
3459- * libwebsocket_context_user() - get the user data associated with the context
3460- * @context: Websocket context
3461- *
3462- * This returns the optional user allocation that can be attached to
3463- * the context the sockets live in at context_create time. It's a way
3464- * to let all sockets serviced in the same context share data without
3465- * using globals statics in the user code.
3466- */
3467-LWS_EXTERN void *
3468-libwebsocket_context_user(struct libwebsocket_context *context)
3469-{
3470- return context->user_space;
3471-}
3472-
3473-/**
3474- * libwebsocket_service() - Service any pending websocket activity
3475- * @context: Websocket context
3476- * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
3477- * service otherwise block and service immediately, returning
3478- * after the timeout if nothing needed service.
3479- *
3480- * This function deals with any pending websocket traffic, for three
3481- * kinds of event. It handles these events on both server and client
3482- * types of connection the same.
3483- *
3484- * 1) Accept new connections to our context's server
3485- *
3486- * 2) Call the receive callback for incoming frame data received by
3487- * server or client connections.
3488- *
3489- * You need to call this service function periodically to all the above
3490- * functions to happen; if your application is single-threaded you can
3491- * just call it in your main event loop.
3492- *
3493- * Alternatively you can fork a new process that asynchronously handles
3494- * calling this service in a loop. In that case you are happy if this
3495- * call blocks your thread until it needs to take care of something and
3496- * would call it with a large nonzero timeout. Your loop then takes no
3497- * CPU while there is nothing happening.
3498- *
3499- * If you are calling it in a single-threaded app, you don't want it to
3500- * wait around blocking other things in your loop from happening, so you
3501- * would call it with a timeout_ms of 0, so it returns immediately if
3502- * nothing is pending, or as soon as it services whatever was pending.
3503- */
3504-
3505-int
3506-libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
3507-{
3508- int n;
3509-
3510- /* stay dead once we are dead */
3511-
3512- if (context == NULL)
3513- return 1;
3514-
3515- /* wait for something to need service */
3516-
3517- n = poll(context->fds, context->fds_count, timeout_ms);
3518- if (n == 0) /* poll timeout */
3519- return 0;
3520-
3521- if (n < 0)
3522- return -1;
3523-
3524- /* any socket with events to service? */
3525-
3526- for (n = 0; n < context->fds_count; n++)
3527- if (context->fds[n].revents)
3528- if (libwebsocket_service_fd(context,
3529- &context->fds[n]) < 0)
3530- return -1;
3531- return 0;
3532-}
3533-
3534-#ifndef LWS_NO_EXTENSIONS
3535-int
3536-lws_any_extension_handled(struct libwebsocket_context *context,
3537- struct libwebsocket *wsi,
3538- enum libwebsocket_extension_callback_reasons r,
3539- void *v, size_t len)
3540-{
3541- int n;
3542- int handled = 0;
3543-
3544- /* maybe an extension will take care of it for us */
3545-
3546- for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
3547- if (!wsi->active_extensions[n]->callback)
3548- continue;
3549-
3550- handled |= wsi->active_extensions[n]->callback(context,
3551- wsi->active_extensions[n], wsi,
3552- r, wsi->active_extensions_user[n], v, len);
3553- }
3554-
3555- return handled;
3556-}
3557-
3558-
3559-void *
3560-lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
3561- struct libwebsocket_extension *ext)
3562-{
3563- int n = 0;
3564-
3565- if (wsi == NULL)
3566- return NULL;
3567-
3568- while (n < wsi->count_active_extensions) {
3569- if (wsi->active_extensions[n] != ext) {
3570- n++;
3571- continue;
3572- }
3573- return wsi->active_extensions_user[n];
3574- }
3575-
3576- return NULL;
3577-}
3578-#endif
3579-
3580-/**
3581- * libwebsocket_callback_on_writable() - Request a callback when this socket
3582- * becomes able to be written to without
3583- * blocking
3584- *
3585- * @context: libwebsockets context
3586- * @wsi: Websocket connection instance to get callback for
3587- */
3588-
3589-int
3590-libwebsocket_callback_on_writable(struct libwebsocket_context *context,
3591- struct libwebsocket *wsi)
3592-{
3593-#ifndef LWS_NO_EXTENSIONS
3594- int n;
3595- int handled = 0;
3596-
3597- /* maybe an extension will take care of it for us */
3598-
3599- for (n = 0; n < wsi->count_active_extensions; n++) {
3600- if (!wsi->active_extensions[n]->callback)
3601- continue;
3602-
3603- handled |= wsi->active_extensions[n]->callback(context,
3604- wsi->active_extensions[n], wsi,
3605- LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
3606- wsi->active_extensions_user[n], NULL, 0);
3607- }
3608-
3609- if (handled)
3610- return 1;
3611-#endif
3612- if (wsi->position_in_fds_table < 0) {
3613- lwsl_err("libwebsocket_callback_on_writable: failed to find socket %d\n",
3614- wsi->sock);
3615- return -1;
3616- }
3617-
3618- context->fds[wsi->position_in_fds_table].events |= POLLOUT;
3619-
3620- /* external POLL support via protocol 0 */
3621- context->protocols[0].callback(context, wsi,
3622- LWS_CALLBACK_SET_MODE_POLL_FD,
3623- (void *)(long)wsi->sock, NULL, POLLOUT);
3624-
3625- return 1;
3626-}
3627-
3628-/**
3629- * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
3630- * all connections using the given protocol when it
3631- * becomes possible to write to each socket without
3632- * blocking in turn.
3633- *
3634- * @protocol: Protocol whose connections will get callbacks
3635- */
3636-
3637-int
3638-libwebsocket_callback_on_writable_all_protocol(
3639- const struct libwebsocket_protocols *protocol)
3640-{
3641- struct libwebsocket_context *context = protocol->owning_server;
3642- int n;
3643- struct libwebsocket *wsi;
3644-
3645- for (n = 0; n < context->fds_count; n++) {
3646- wsi = context->lws_lookup[context->fds[n].fd];
3647- if (!wsi)
3648- continue;
3649- if (wsi->protocol == protocol)
3650- libwebsocket_callback_on_writable(context, wsi);
3651- }
3652-
3653- return 0;
3654-}
3655-
3656-/**
3657- * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
3658- *
3659- * You will not need this unless you are doing something special
3660- *
3661- * @wsi: Websocket connection instance
3662- * @reason: timeout reason
3663- * @secs: how many seconds
3664- */
3665-
3666-void
3667-libwebsocket_set_timeout(struct libwebsocket *wsi,
3668- enum pending_timeout reason, int secs)
3669-{
3670- struct timeval tv;
3671-
3672- gettimeofday(&tv, NULL);
3673-
3674- wsi->pending_timeout_limit = tv.tv_sec + secs;
3675- wsi->pending_timeout = reason;
3676-}
3677-
3678-
3679-/**
3680- * libwebsocket_get_socket_fd() - returns the socket file descriptor
3681- *
3682- * You will not need this unless you are doing something special
3683- *
3684- * @wsi: Websocket connection instance
3685- */
3686-
3687-int
3688-libwebsocket_get_socket_fd(struct libwebsocket *wsi)
3689-{
3690- return wsi->sock;
3691-}
3692-
3693-#ifdef LWS_LATENCY
3694-void
3695-lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
3696- const char *action, int ret, int completed)
3697-{
3698- struct timeval tv;
3699- unsigned long u;
3700- char buf[256];
3701-
3702- gettimeofday(&tv, NULL);
3703-
3704- u = (tv.tv_sec * 1000000) + tv.tv_usec;
3705-
3706- if (action) {
3707- if (completed) {
3708- if (wsi->action_start == wsi->latency_start)
3709- sprintf(buf,
3710- "Completion first try lat %luus: %p: ret %d: %s\n",
3711- u - wsi->latency_start,
3712- (void *)wsi, ret, action);
3713- else
3714- sprintf(buf,
3715- "Completion %luus: lat %luus: %p: ret %d: %s\n",
3716- u - wsi->action_start,
3717- u - wsi->latency_start,
3718- (void *)wsi, ret, action);
3719- wsi->action_start = 0;
3720- } else
3721- sprintf(buf, "lat %luus: %p: ret %d: %s\n",
3722- u - wsi->latency_start,
3723- (void *)wsi, ret, action);
3724- if (u - wsi->latency_start > context->worst_latency) {
3725- context->worst_latency = u - wsi->latency_start;
3726- strcpy(context->worst_latency_info, buf);
3727- }
3728- lwsl_latency("%s", buf);
3729- } else {
3730- wsi->latency_start = u;
3731- if (!wsi->action_start)
3732- wsi->action_start = u;
3733- }
3734-}
3735-#endif
3736-
3737-#ifdef LWS_NO_SERVER
3738-int
3739-_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
3740-{
3741- return 0;
3742-}
3743-#else
3744-int
3745-_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
3746-{
3747- struct libwebsocket_context *context = wsi->protocol->owning_server;
3748- int n;
3749-
3750- if (!(wsi->u.ws.rxflow_change_to & 2))
3751- return 0;
3752-
3753- wsi->u.ws.rxflow_change_to &= ~2;
3754-
3755- lwsl_info("rxflow: wsi %p change_to %d\n",
3756- wsi, wsi->u.ws.rxflow_change_to);
3757-
3758- /* if we're letting it come again, did we interrupt anything? */
3759- if ((wsi->u.ws.rxflow_change_to & 1) && wsi->u.ws.rxflow_buffer) {
3760- n = libwebsocket_interpret_incoming_packet(wsi, NULL, 0);
3761- if (n < 0) {
3762- lwsl_info("libwebsocket_rx_flow_control: close req\n");
3763- return -1;
3764- }
3765- if (n)
3766- /* oh he stuck again, do nothing */
3767- return 0;
3768- }
3769-
3770- if (wsi->u.ws.rxflow_change_to & 1)
3771- context->fds[wsi->position_in_fds_table].events |= POLLIN;
3772- else
3773- context->fds[wsi->position_in_fds_table].events &= ~POLLIN;
3774-
3775- if (wsi->u.ws.rxflow_change_to & 1)
3776- /* external POLL support via protocol 0 */
3777- context->protocols[0].callback(context, wsi,
3778- LWS_CALLBACK_SET_MODE_POLL_FD,
3779- (void *)(long)wsi->sock, NULL, POLLIN);
3780- else
3781- /* external POLL support via protocol 0 */
3782- context->protocols[0].callback(context, wsi,
3783- LWS_CALLBACK_CLEAR_MODE_POLL_FD,
3784- (void *)(long)wsi->sock, NULL, POLLIN);
3785-
3786- return 1;
3787-}
3788-#endif
3789-
3790-/**
3791- * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
3792- * receieved packets.
3793- *
3794- * If the output side of a server process becomes choked, this allows flow
3795- * control for the input side.
3796- *
3797- * @wsi: Websocket connection instance to get callback for
3798- * @enable: 0 = disable read servicing for this connection, 1 = enable
3799- */
3800-
3801-int
3802-libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
3803-{
3804- wsi->u.ws.rxflow_change_to = 2 | !!enable;
3805-
3806- return 0;
3807-}
3808-
3809-
3810-/**
3811- * libwebsocket_canonical_hostname() - returns this host's hostname
3812- *
3813- * This is typically used by client code to fill in the host parameter
3814- * when making a client connection. You can only call it after the context
3815- * has been created.
3816- *
3817- * @context: Websocket context
3818- */
3819-
3820-
3821-extern const char *
3822-libwebsocket_canonical_hostname(struct libwebsocket_context *context)
3823-{
3824- return (const char *)context->canonical_hostname;
3825-}
3826-
3827-
3828-static void sigpipe_handler(int x)
3829-{
3830-}
3831-
3832-#ifdef LWS_OPENSSL_SUPPORT
3833-static int
3834-OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
3835-{
3836-
3837- SSL *ssl;
3838- int n;
3839- struct libwebsocket_context *context;
3840-
3841- ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
3842- SSL_get_ex_data_X509_STORE_CTX_idx());
3843-
3844- /*
3845- * !!! nasty openssl requires the index to come as a library-scope
3846- * static
3847- */
3848- context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
3849-
3850- n = context->protocols[0].callback(NULL, NULL,
3851- LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
3852- x509_ctx, ssl, preverify_ok);
3853-
3854- /* convert return code from 0 = OK to 1 = OK */
3855-
3856- if (!n)
3857- n = 1;
3858- else
3859- n = 0;
3860-
3861- return n;
3862-}
3863-#endif
3864-
3865-int user_callback_handle_rxflow(callback_function callback_function,
3866- struct libwebsocket_context *context,
3867- struct libwebsocket *wsi,
3868- enum libwebsocket_callback_reasons reason, void *user,
3869- void *in, size_t len)
3870-{
3871- int n;
3872-
3873- n = callback_function(context, wsi, reason, user, in, len);
3874- if (!n)
3875- n = _libwebsocket_rx_flow_control(wsi);
3876-
3877- return n;
3878-}
3879-
3880-
3881-/**
3882- * libwebsocket_create_context() - Create the websocket handler
3883- * @info: pointer to struct with parameters
3884- *
3885- * This function creates the listening socket (if serving) and takes care
3886- * of all initialization in one step.
3887- *
3888- * After initialization, it returns a struct libwebsocket_context * that
3889- * represents this server. After calling, user code needs to take care
3890- * of calling libwebsocket_service() with the context pointer to get the
3891- * server's sockets serviced. This can be done in the same process context
3892- * or a forked process, or another thread,
3893- *
3894- * The protocol callback functions are called for a handful of events
3895- * including http requests coming in, websocket connections becoming
3896- * established, and data arriving; it's also called periodically to allow
3897- * async transmission.
3898- *
3899- * HTTP requests are sent always to the FIRST protocol in @protocol, since
3900- * at that time websocket protocol has not been negotiated. Other
3901- * protocols after the first one never see any HTTP callack activity.
3902- *
3903- * The server created is a simple http server by default; part of the
3904- * websocket standard is upgrading this http connection to a websocket one.
3905- *
3906- * This allows the same server to provide files like scripts and favicon /
3907- * images or whatever over http and dynamic data over websockets all in
3908- * one place; they're all handled in the user callback.
3909- */
3910-
3911-struct libwebsocket_context *
3912-libwebsocket_create_context(struct lws_context_creation_info *info)
3913-{
3914- struct libwebsocket_context *context = NULL;
3915- char *p;
3916-#ifndef LWS_NO_SERVER
3917- int n;
3918- int opt = 1;
3919- struct libwebsocket *wsi;
3920- struct sockaddr_in serv_addr;
3921-#endif
3922-#ifndef LWS_NO_EXTENSIONS
3923- int m;
3924- struct libwebsocket_extension *ext;
3925-#endif
3926-
3927-#ifdef LWS_OPENSSL_SUPPORT
3928- SSL_METHOD *method;
3929-#endif
3930-
3931-#ifndef LWS_NO_DAEMONIZE
3932- int pid_daemon = get_daemonize_pid();
3933-#endif
3934-
3935- lwsl_notice("Initial logging level %d\n", log_level);
3936- lwsl_notice("Library version: %s\n", library_version);
3937- lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n",
3938- LWS_MAX_HEADER_NAME_LENGTH);
3939- lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
3940- lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
3941-#ifndef LWS_NO_EXTENSIONS
3942- lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n",
3943- LWS_MAX_EXTENSIONS_ACTIVE);
3944-#else
3945- lwsl_notice(" Configured without extension support\n");
3946-#endif
3947- lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
3948- lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
3949- lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
3950- lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
3951- lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
3952-
3953-#ifdef _WIN32
3954- {
3955- WORD wVersionRequested;
3956- WSADATA wsaData;
3957- int err;
3958- HMODULE wsdll;
3959-
3960- /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
3961- wVersionRequested = MAKEWORD(2, 2);
3962-
3963- err = WSAStartup(wVersionRequested, &wsaData);
3964- if (err != 0) {
3965- /* Tell the user that we could not find a usable */
3966- /* Winsock DLL. */
3967- lwsl_err("WSAStartup failed with error: %d\n", err);
3968- return NULL;
3969- }
3970-
3971- /* default to a poll() made out of select() */
3972- poll = emulated_poll;
3973-
3974- /* if windows socket lib available, use his WSAPoll */
3975- wsdll = GetModuleHandle(_T("Ws2_32.dll"));
3976- if (wsdll)
3977- poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
3978-
3979- /* Finally fall back to emulated poll if all else fails */
3980- if (!poll)
3981- poll = emulated_poll;
3982- }
3983-#endif
3984-
3985- context = (struct libwebsocket_context *)
3986- malloc(sizeof(struct libwebsocket_context));
3987- if (!context) {
3988- lwsl_err("No memory for websocket context\n");
3989- return NULL;
3990- }
3991- memset(context, 0, sizeof(*context));
3992-#ifndef LWS_NO_DAEMONIZE
3993- context->started_with_parent = pid_daemon;
3994- lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
3995-#endif
3996-
3997- context->listen_service_extraseen = 0;
3998- context->protocols = info->protocols;
3999- context->listen_port = info->port;
4000- context->http_proxy_port = 0;
4001- context->http_proxy_address[0] = '\0';
4002- context->options = info->options;
4003- /* to reduce this allocation, */
4004- context->max_fds = getdtablesize();
4005- lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n",
4006- sizeof(struct libwebsocket_context),
4007- sizeof(struct pollfd) + sizeof(struct libwebsocket *),
4008- context->max_fds,
4009- sizeof(struct libwebsocket_context) +
4010- ((sizeof(struct pollfd) + sizeof(struct libwebsocket *)) *
4011- context->max_fds));
4012-
4013- context->fds = (struct pollfd *)malloc(sizeof(struct pollfd) *
4014- context->max_fds);
4015- if (context->fds == NULL) {
4016- lwsl_err("Unable to allocate fds array for %d connections\n",
4017- context->max_fds);
4018- free(context);
4019- return NULL;
4020- }
4021- context->lws_lookup = (struct libwebsocket **)
4022- malloc(sizeof(struct libwebsocket *) * context->max_fds);
4023- if (context->lws_lookup == NULL) {
4024- lwsl_err(
4025- "Unable to allocate lws_lookup array for %d connections\n",
4026- context->max_fds);
4027- free(context->fds);
4028- free(context);
4029- return NULL;
4030- }
4031-
4032- context->fds_count = 0;
4033-#ifndef LWS_NO_EXTENSIONS
4034- context->extensions = info->extensions;
4035-#endif
4036- context->last_timeout_check_s = 0;
4037- context->user_space = info->user;
4038-
4039-#ifdef WIN32
4040- context->fd_random = 0;
4041-#else
4042- context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
4043- if (context->fd_random < 0) {
4044- lwsl_err("Unable to open random device %s %d\n",
4045- SYSTEM_RANDOM_FILEPATH, context->fd_random);
4046- goto bail;
4047- }
4048-#endif
4049-
4050-#ifdef LWS_OPENSSL_SUPPORT
4051- context->use_ssl = 0;
4052- context->ssl_ctx = NULL;
4053- context->ssl_client_ctx = NULL;
4054- openssl_websocket_private_data_index = 0;
4055-#endif
4056-
4057- strcpy(context->canonical_hostname, "unknown");
4058-
4059-#ifndef LWS_NO_SERVER
4060- if (!(info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) {
4061- /* find canonical hostname */
4062- gethostname((char *)context->canonical_hostname,
4063- sizeof(context->canonical_hostname) - 1);
4064-
4065- lwsl_notice(" canonical_hostname = %s\n",
4066- context->canonical_hostname);
4067- }
4068-#endif
4069-
4070- /* split the proxy ads:port if given */
4071-
4072- p = getenv("http_proxy");
4073- if (p) {
4074- strncpy(context->http_proxy_address, p,
4075- sizeof(context->http_proxy_address) - 1);
4076- context->http_proxy_address[
4077- sizeof(context->http_proxy_address) - 1] = '\0';
4078-
4079- p = strchr(context->http_proxy_address, ':');
4080- if (p == NULL) {
4081- lwsl_err("http_proxy needs to be ads:port\n");
4082- goto bail;
4083- }
4084- *p = '\0';
4085- context->http_proxy_port = atoi(p + 1);
4086-
4087- lwsl_notice(" Proxy %s:%u\n",
4088- context->http_proxy_address,
4089- context->http_proxy_port);
4090- }
4091-
4092-#ifndef LWS_NO_SERVER
4093- if (info->port) {
4094-
4095-#ifdef LWS_OPENSSL_SUPPORT
4096- context->use_ssl = info->ssl_cert_filepath != NULL &&
4097- info->ssl_private_key_filepath != NULL;
4098-#ifdef USE_CYASSL
4099- lwsl_notice(" Compiled with CYASSL support\n");
4100-#else
4101- lwsl_notice(" Compiled with OpenSSL support\n");
4102-#endif
4103- if (context->use_ssl)
4104- lwsl_notice(" Using SSL mode\n");
4105- else
4106- lwsl_notice(" Using non-SSL mode\n");
4107-
4108-#else
4109- if (info->ssl_cert_filepath != NULL &&
4110- info->ssl_private_key_filepath != NULL) {
4111- lwsl_notice(" Not compiled for OpenSSl support!\n");
4112- goto bail;
4113- }
4114- lwsl_notice(" Compiled without SSL support\n");
4115-#endif
4116-
4117- lwsl_notice(
4118- " per-conn mem: %u + %u headers + protocol rx buf\n",
4119- sizeof(struct libwebsocket),
4120- sizeof(struct allocated_headers));
4121- }
4122-#endif
4123-
4124- /* ignore SIGPIPE */
4125-#ifdef WIN32
4126-#else
4127- signal(SIGPIPE, sigpipe_handler);
4128-#endif
4129-
4130-
4131-#ifdef LWS_OPENSSL_SUPPORT
4132-
4133- /* basic openssl init */
4134-
4135- SSL_library_init();
4136-
4137- OpenSSL_add_all_algorithms();
4138- SSL_load_error_strings();
4139-
4140- openssl_websocket_private_data_index =
4141- SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
4142-
4143- /*
4144- * Firefox insists on SSLv23 not SSLv3
4145- * Konq disables SSLv2 by default now, SSLv23 works
4146- */
4147-
4148- method = (SSL_METHOD *)SSLv23_server_method();
4149- if (!method) {
4150- lwsl_err("problem creating ssl method: %s\n",
4151- ERR_error_string(ERR_get_error(),
4152- (char *)context->service_buffer));
4153- goto bail;
4154- }
4155- context->ssl_ctx = SSL_CTX_new(method); /* create context */
4156- if (!context->ssl_ctx) {
4157- lwsl_err("problem creating ssl context: %s\n",
4158- ERR_error_string(ERR_get_error(),
4159- (char *)context->service_buffer));
4160- goto bail;
4161- }
4162-
4163-#ifdef SSL_OP_NO_COMPRESSION
4164- SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
4165-#endif
4166- SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
4167- SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
4168-
4169-#ifndef LWS_NO_CLIENT
4170-
4171- /* client context */
4172-
4173- if (info->port == CONTEXT_PORT_NO_LISTEN) {
4174- method = (SSL_METHOD *)SSLv23_client_method();
4175- if (!method) {
4176- lwsl_err("problem creating ssl method: %s\n",
4177- ERR_error_string(ERR_get_error(),
4178- (char *)context->service_buffer));
4179- goto bail;
4180- }
4181- /* create context */
4182- context->ssl_client_ctx = SSL_CTX_new(method);
4183- if (!context->ssl_client_ctx) {
4184- lwsl_err("problem creating ssl context: %s\n",
4185- ERR_error_string(ERR_get_error(),
4186- (char *)context->service_buffer));
4187- goto bail;
4188- }
4189-
4190-#ifdef SSL_OP_NO_COMPRESSION
4191- SSL_CTX_set_options(context->ssl_client_ctx,
4192- SSL_OP_NO_COMPRESSION);
4193-#endif
4194- SSL_CTX_set_options(context->ssl_client_ctx,
4195- SSL_OP_CIPHER_SERVER_PREFERENCE);
4196- SSL_CTX_set_cipher_list(context->ssl_client_ctx,
4197- CIPHERS_LIST_STRING);
4198-
4199- /* openssl init for cert verification (for client sockets) */
4200- if (!info->ssl_ca_filepath) {
4201- if (!SSL_CTX_load_verify_locations(
4202- context->ssl_client_ctx, NULL,
4203- LWS_OPENSSL_CLIENT_CERTS))
4204- lwsl_err(
4205- "Unable to load SSL Client certs from %s "
4206- "(set by --with-client-cert-dir= "
4207- "in configure) -- client ssl isn't "
4208- "going to work", LWS_OPENSSL_CLIENT_CERTS);
4209- } else
4210- if (!SSL_CTX_load_verify_locations(
4211- context->ssl_client_ctx, info->ssl_ca_filepath,
4212- NULL))
4213- lwsl_err(
4214- "Unable to load SSL Client certs "
4215- "file from %s -- client ssl isn't "
4216- "going to work", info->ssl_ca_filepath);
4217-
4218- /*
4219- * callback allowing user code to load extra verification certs
4220- * helping the client to verify server identity
4221- */
4222-
4223- context->protocols[0].callback(context, NULL,
4224- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
4225- context->ssl_client_ctx, NULL, 0);
4226- }
4227-#endif
4228-
4229- /* as a server, are we requiring clients to identify themselves? */
4230-
4231- if (info->options &
4232- LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
4233-
4234- /* absolutely require the client cert */
4235-
4236- SSL_CTX_set_verify(context->ssl_ctx,
4237- SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
4238- OpenSSL_verify_callback);
4239-
4240- /*
4241- * give user code a chance to load certs into the server
4242- * allowing it to verify incoming client certs
4243- */
4244-
4245- context->protocols[0].callback(context, NULL,
4246- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
4247- context->ssl_ctx, NULL, 0);
4248- }
4249-
4250- if (context->use_ssl) {
4251-
4252- /* openssl init for server sockets */
4253-
4254- /* set the local certificate from CertFile */
4255- n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
4256- info->ssl_cert_filepath);
4257- if (n != 1) {
4258- lwsl_err("problem getting cert '%s': %s\n",
4259- info->ssl_cert_filepath,
4260- ERR_error_string(ERR_get_error(),
4261- (char *)context->service_buffer));
4262- goto bail;
4263- }
4264- /* set the private key from KeyFile */
4265- if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
4266- info->ssl_private_key_filepath,
4267- SSL_FILETYPE_PEM) != 1) {
4268- lwsl_err("ssl problem getting key '%s': %s\n",
4269- info->ssl_private_key_filepath,
4270- ERR_error_string(ERR_get_error(),
4271- (char *)context->service_buffer));
4272- goto bail;
4273- }
4274- /* verify private key */
4275- if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
4276- lwsl_err("Private SSL key doesn't match cert\n");
4277- goto bail;
4278- }
4279-
4280- /* SSL is happy and has a cert it's content with */
4281- }
4282-#endif
4283-
4284- /* selftest */
4285-
4286- if (lws_b64_selftest())
4287- goto bail;
4288-
4289-#ifndef LWS_NO_SERVER
4290- /* set up our external listening socket we serve on */
4291-
4292- if (info->port) {
4293- int sockfd;
4294-
4295- sockfd = socket(AF_INET, SOCK_STREAM, 0);
4296- if (sockfd < 0) {
4297- lwsl_err("ERROR opening socket\n");
4298- goto bail;
4299- }
4300-
4301-#ifndef WIN32
4302- /*
4303- * allow us to restart even if old sockets in TIME_WAIT
4304- * (REUSEADDR on Unix means, "don't hang on to this
4305- * address after the listener is closed." On Windows, though,
4306- * it means "don't keep other processes from binding to
4307- * this address while we're using it)
4308- */
4309- setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
4310- (const void *)&opt, sizeof(opt));
4311-#endif
4312-
4313- /* Disable Nagle */
4314- opt = 1;
4315- setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
4316- (const void *)&opt, sizeof(opt));
4317-
4318- #ifdef WIN32
4319- opt = 0;
4320- ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt);
4321- #else
4322- fcntl(sockfd, F_SETFL, O_NONBLOCK);
4323- #endif
4324-
4325- bzero((char *) &serv_addr, sizeof(serv_addr));
4326- serv_addr.sin_family = AF_INET;
4327- if (info->iface == NULL)
4328- serv_addr.sin_addr.s_addr = INADDR_ANY;
4329- else
4330- interface_to_sa(info->iface, &serv_addr,
4331- sizeof(serv_addr));
4332- serv_addr.sin_port = htons(info->port);
4333-
4334- n = bind(sockfd, (struct sockaddr *) &serv_addr,
4335- sizeof(serv_addr));
4336- if (n < 0) {
4337- lwsl_err("ERROR on binding to port %d (%d %d)\n",
4338- info->port, n, errno);
4339- close(sockfd);
4340- goto bail;
4341- }
4342-
4343- wsi = (struct libwebsocket *)malloc(
4344- sizeof(struct libwebsocket));
4345- if (wsi == NULL) {
4346- lwsl_err("Out of mem\n");
4347- close(sockfd);
4348- goto bail;
4349- }
4350- memset(wsi, 0, sizeof(struct libwebsocket));
4351- wsi->sock = sockfd;
4352-#ifndef LWS_NO_EXTENSIONS
4353- wsi->count_active_extensions = 0;
4354-#endif
4355- wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
4356-
4357- insert_wsi_socket_into_fds(context, wsi);
4358-
4359- context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
4360- context->listen_service_count = 0;
4361- context->listen_service_fd = sockfd;
4362-
4363- listen(sockfd, LWS_SOMAXCONN);
4364- lwsl_notice(" Listening on port %d\n", info->port);
4365- }
4366-#endif
4367-
4368- /*
4369- * drop any root privs for this process
4370- * to listen on port < 1023 we would have needed root, but now we are
4371- * listening, we don't want the power for anything else
4372- */
4373-#ifdef WIN32
4374-#else
4375- if (info->gid != -1)
4376- if (setgid(info->gid))
4377- lwsl_warn("setgid: %s\n", strerror(errno));
4378- if (info->uid != -1)
4379- if (setuid(info->uid))
4380- lwsl_warn("setuid: %s\n", strerror(errno));
4381-#endif
4382-
4383- /* initialize supported protocols */
4384-
4385- for (context->count_protocols = 0;
4386- info->protocols[context->count_protocols].callback;
4387- context->count_protocols++) {
4388-
4389- lwsl_parser(" Protocol: %s\n",
4390- info->protocols[context->count_protocols].name);
4391-
4392- info->protocols[context->count_protocols].owning_server =
4393- context;
4394- info->protocols[context->count_protocols].protocol_index =
4395- context->count_protocols;
4396-
4397- /*
4398- * inform all the protocols that they are doing their one-time
4399- * initialization if they want to
4400- */
4401- info->protocols[context->count_protocols].callback(context,
4402- NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0);
4403- }
4404-
4405-#ifndef LWS_NO_EXTENSIONS
4406- /*
4407- * give all extensions a chance to create any per-context
4408- * allocations they need
4409- */
4410-
4411- m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
4412- if (info->port)
4413- m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
4414-
4415- if (info->extensions) {
4416- ext = info->extensions;
4417- while (ext->callback) {
4418- lwsl_ext(" Extension: %s\n", ext->name);
4419- ext->callback(context, ext, NULL,
4420- (enum libwebsocket_extension_callback_reasons)m,
4421- NULL, NULL, 0);
4422- ext++;
4423- }
4424- }
4425-#endif
4426- return context;
4427-
4428-bail:
4429- libwebsocket_context_destroy(context);
4430- return NULL;
4431-}
4432-
4433-/**
4434- * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
4435- * connection.
4436- * @wsi: pointer to struct websocket you want to know the protocol of
4437- *
4438- *
4439- * Some apis can act on all live connections of a given protocol,
4440- * this is how you can get a pointer to the active protocol if needed.
4441- */
4442-
4443-const struct libwebsocket_protocols *
4444-libwebsockets_get_protocol(struct libwebsocket *wsi)
4445-{
4446- return wsi->protocol;
4447-}
4448-
4449-int
4450-libwebsocket_is_final_fragment(struct libwebsocket *wsi)
4451-{
4452- return wsi->u.ws.final;
4453-}
4454-
4455-unsigned char
4456-libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
4457-{
4458- return wsi->u.ws.rsv;
4459-}
4460-
4461-void *
4462-libwebsocket_ensure_user_space(struct libwebsocket *wsi)
4463-{
4464- /* allocate the per-connection user memory (if any) */
4465-
4466- if (wsi->protocol->per_session_data_size && !wsi->user_space) {
4467- wsi->user_space = malloc(
4468- wsi->protocol->per_session_data_size);
4469- if (wsi->user_space == NULL) {
4470- lwsl_err("Out of memory for conn user space\n");
4471- return NULL;
4472- }
4473- memset(wsi->user_space, 0,
4474- wsi->protocol->per_session_data_size);
4475- }
4476- return wsi->user_space;
4477-}
4478-
4479-static void lwsl_emit_stderr(int level, const char *line)
4480-{
4481- char buf[300];
4482- struct timeval tv;
4483- int n;
4484-
4485- gettimeofday(&tv, NULL);
4486-
4487- buf[0] = '\0';
4488- for (n = 0; n < LLL_COUNT; n++)
4489- if (level == (1 << n)) {
4490- sprintf(buf, "[%ld:%04d] %s: ", tv.tv_sec,
4491- (int)(tv.tv_usec / 100), log_level_names[n]);
4492- break;
4493- }
4494-
4495- fprintf(stderr, "%s%s", buf, line);
4496-}
4497-
4498-#ifdef WIN32
4499-void lwsl_emit_syslog(int level, const char *line)
4500-{
4501- lwsl_emit_stderr(level, line);
4502-}
4503-#else
4504-void lwsl_emit_syslog(int level, const char *line)
4505-{
4506- int syslog_level = LOG_DEBUG;
4507-
4508- switch (level) {
4509- case LLL_ERR:
4510- syslog_level = LOG_ERR;
4511- break;
4512- case LLL_WARN:
4513- syslog_level = LOG_WARNING;
4514- break;
4515- case LLL_NOTICE:
4516- syslog_level = LOG_NOTICE;
4517- break;
4518- case LLL_INFO:
4519- syslog_level = LOG_INFO;
4520- break;
4521- }
4522- syslog(syslog_level, "%s", line);
4523-}
4524-#endif
4525-
4526-void _lws_log(int filter, const char *format, ...)
4527-{
4528- char buf[256];
4529- va_list ap;
4530-
4531- if (!(log_level & filter))
4532- return;
4533-
4534- va_start(ap, format);
4535- vsnprintf(buf, sizeof(buf), format, ap);
4536- buf[sizeof(buf) - 1] = '\0';
4537- va_end(ap);
4538-
4539- lwsl_emit(filter, buf);
4540-}
4541-
4542-/**
4543- * lws_set_log_level() - Set the logging bitfield
4544- * @level: OR together the LLL_ debug contexts you want output from
4545- * @log_emit_function: NULL to leave it as it is, or a user-supplied
4546- * function to perform log string emission instead of
4547- * the default stderr one.
4548- *
4549- * log level defaults to "err" and "warn" contexts enabled only and
4550- * emission on stderr.
4551- */
4552-
4553-void lws_set_log_level(int level, void (*log_emit_function)(int level,
4554- const char *line))
4555-{
4556- log_level = level;
4557- if (log_emit_function)
4558- lwsl_emit = log_emit_function;
4559-}
4560
4561=== removed directory '.pc/01-visibility.patch'
4562=== removed directory '.pc/01-visibility.patch/lib'
4563=== removed file '.pc/01-visibility.patch/lib/Makefile.am'
4564--- .pc/01-visibility.patch/lib/Makefile.am 2013-03-28 19:10:28 +0000
4565+++ .pc/01-visibility.patch/lib/Makefile.am 1970-01-01 00:00:00 +0000
4566@@ -1,89 +0,0 @@
4567-@applyhash@
4568-
4569-lib_LTLIBRARIES=libwebsockets.la
4570-include_HEADERS=libwebsockets.h
4571-dist_libwebsockets_la_SOURCES=libwebsockets.c \
4572- parsers.c \
4573- handshake.c \
4574- libwebsockets.h \
4575- base64-decode.c \
4576- output.c \
4577- private-libwebsockets.h
4578-
4579-if NO_EXTENSIONS
4580-else
4581-dist_libwebsockets_la_SOURCES+= extension.c \
4582- extension-deflate-stream.c extension-deflate-stream.h \
4583- extension-deflate-frame.c extension-deflate-frame.h
4584-endif
4585-
4586-if NO_DAEMONIZE
4587-else
4588-dist_libwebsockets_la_SOURCES+= daemonize.c
4589-endif
4590-
4591-if NO_CLIENT
4592-else
4593-dist_libwebsockets_la_SOURCES+= client.c \
4594- client-parser.c \
4595- client-handshake.c
4596-endif
4597-
4598-if NO_SERVER
4599-else
4600-dist_libwebsockets_la_SOURCES+= server.c \
4601- server-handshake.c
4602-endif
4603-
4604-if USE_BUILTIN_GETIFADDRS
4605-dist_libwebsockets_la_SOURCES += getifaddrs.c
4606-endif
4607-
4608-if LIBCRYPTO
4609-else
4610-dist_libwebsockets_la_SOURCES += sha-1.c
4611-endif
4612-
4613-libwebsockets_la_CFLAGS=-Wall -std=gnu99 -pedantic
4614-libwebsockets_la_LDFLAGS=
4615-
4616-# uncomment below and use cat ./lib/.libs/*.su | sort -k2g | tac
4617-# to get a worst-first list of static stack usage if you have gcc 4.6+
4618-#libwebsockets_la_CFLAGS+= -fstack-usage
4619-
4620-if USE_CYASSL
4621-libwebsockets_la_LDFLAGS+= -lcyassl
4622-endif
4623-
4624-if DISABLE_DEBUG
4625-libwebsockets_la_CFLAGS+= -O4
4626-else
4627-libwebsockets_la_CFLAGS+= -O0 -g
4628-endif
4629-
4630-if MINGW
4631-libwebsockets_la_CFLAGS+= -w -I../win32port/win32helpers -I ../win32port/zlib/
4632-libwebsockets_la_LDFLAGS+= -lm -luser32 -ladvapi32 -lkernel32 -lgcc
4633-else
4634-libwebsockets_la_CFLAGS+= -rdynamic -fPIC -Werror
4635-# notice http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html has rules for how to bump this
4636-libwebsockets_la_LDFLAGS+= -version-info 3:0:0
4637-endif
4638-
4639-libwebsockets_la_CFLAGS+= -c \
4640- -DINSTALL_DATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
4641-if NO_EXTENSIONS
4642-else
4643-libwebsockets_la_LDFLAGS+= -lz
4644-endif
4645-
4646-all-local:
4647- ../scripts/kernel-doc -html \
4648- *.c \
4649- libwebsockets.h \
4650- > ../libwebsockets-api-doc.html
4651- ../scripts/kernel-doc -text \
4652- *.c \
4653- libwebsockets.h \
4654- > ../libwebsockets-api-doc.txt
4655-
4656
4657=== removed file '.pc/01-visibility.patch/lib/base64-decode.c'
4658--- .pc/01-visibility.patch/lib/base64-decode.c 2013-03-28 19:10:28 +0000
4659+++ .pc/01-visibility.patch/lib/base64-decode.c 1970-01-01 00:00:00 +0000
4660@@ -1,189 +0,0 @@
4661-/*
4662- * This code originally came from here
4663- *
4664- * http://base64.sourceforge.net/b64.c
4665- *
4666- * with the following license:
4667- *
4668- * LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
4669- *
4670- * Permission is hereby granted, free of charge, to any person
4671- * obtaining a copy of this software and associated
4672- * documentation files (the "Software"), to deal in the
4673- * Software without restriction, including without limitation
4674- * the rights to use, copy, modify, merge, publish, distribute,
4675- * sublicense, and/or sell copies of the Software, and to
4676- * permit persons to whom the Software is furnished to do so,
4677- * subject to the following conditions:
4678- *
4679- * The above copyright notice and this permission notice shall
4680- * be included in all copies or substantial portions of the
4681- * Software.
4682- *
4683- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
4684- * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
4685- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
4686- * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
4687- * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
4688- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
4689- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
4690- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4691- *
4692- * VERSION HISTORY:
4693- * Bob Trower 08/04/01 -- Create Version 0.00.00B
4694- *
4695- * I cleaned it up quite a bit to match the (linux kernel) style of the rest
4696- * of libwebsockets; this version is under LGPL2 like the rest of libwebsockets
4697- * since he explictly allows sublicensing, but I give the URL above so you can
4698- * get the original with Bob's super-liberal terms directly if you prefer.
4699- */
4700-
4701-
4702-#include <stdio.h>
4703-#include <string.h>
4704-#include "private-libwebsockets.h"
4705-
4706-static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4707- "abcdefghijklmnopqrstuvwxyz0123456789+/";
4708-static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
4709- "$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
4710-
4711-int
4712-lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
4713-{
4714- unsigned char triple[3];
4715- int i;
4716- int len;
4717- int line = 0;
4718- int done = 0;
4719-
4720- while (in_len) {
4721- len = 0;
4722- for (i = 0; i < 3; i++) {
4723- if (in_len) {
4724- triple[i] = *in++;
4725- len++;
4726- in_len--;
4727- } else
4728- triple[i] = 0;
4729- }
4730- if (!len)
4731- continue;
4732-
4733- if (done + 4 >= out_size)
4734- return -1;
4735-
4736- *out++ = encode[triple[0] >> 2];
4737- *out++ = encode[((triple[0] & 0x03) << 4) |
4738- ((triple[1] & 0xf0) >> 4)];
4739- *out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
4740- ((triple[2] & 0xc0) >> 6)] : '=');
4741- *out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
4742-
4743- done += 4;
4744- line += 4;
4745- }
4746-
4747- if (done + 1 >= out_size)
4748- return -1;
4749-
4750- *out++ = '\0';
4751-
4752- return done;
4753-}
4754-
4755-/*
4756- * returns length of decoded string in out, or -1 if out was too small
4757- * according to out_size
4758- */
4759-
4760-int
4761-lws_b64_decode_string(const char *in, char *out, int out_size)
4762-{
4763- int len;
4764- int i;
4765- int done = 0;
4766- unsigned char v;
4767- unsigned char quad[4];
4768-
4769- while (*in) {
4770-
4771- len = 0;
4772- for (i = 0; i < 4 && *in; i++) {
4773-
4774- v = 0;
4775- while (*in && !v) {
4776-
4777- v = *in++;
4778- v = (v < 43 || v > 122) ? 0 : decode[v - 43];
4779- if (v)
4780- v = (v == '$') ? 0 : v - 61;
4781- if (*in) {
4782- len++;
4783- if (v)
4784- quad[i] = v - 1;
4785- } else
4786- quad[i] = 0;
4787- }
4788- }
4789- if (!len)
4790- continue;
4791-
4792- if (out_size < (done + len - 1))
4793- /* out buffer is too small */
4794- return -1;
4795-
4796- if (len >= 2)
4797- *out++ = quad[0] << 2 | quad[1] >> 4;
4798- if (len >= 3)
4799- *out++ = quad[1] << 4 | quad[2] >> 2;
4800- if (len >= 4)
4801- *out++ = ((quad[2] << 6) & 0xc0) | quad[3];
4802-
4803- done += len - 1;
4804- }
4805-
4806- if (done + 1 >= out_size)
4807- return -1;
4808-
4809- *out++ = '\0';
4810-
4811- return done;
4812-}
4813-
4814-int
4815-lws_b64_selftest(void)
4816-{
4817- char buf[64];
4818- int n;
4819- int test;
4820- static const char * const plaintext[] = {
4821- "sanity check base 64"
4822- };
4823- static const char * const coded[] = {
4824- "c2FuaXR5IGNoZWNrIGJhc2UgNjQ="
4825- };
4826-
4827- for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) {
4828-
4829- buf[sizeof(buf) - 1] = '\0';
4830- n = lws_b64_encode_string(plaintext[test],
4831- strlen(plaintext[test]), buf, sizeof buf);
4832- if (n != strlen(coded[test]) || strcmp(buf, coded[test])) {
4833- lwsl_err("Failed lws_b64 encode selftest "
4834- "%d result '%s' %d\n", test, buf, n);
4835- return -1;
4836- }
4837-
4838- buf[sizeof(buf) - 1] = '\0';
4839- n = lws_b64_decode_string(coded[test], buf, sizeof buf);
4840- if (n != strlen(plaintext[test]) ||
4841- strcmp(buf, plaintext[test])) {
4842- lwsl_err("Failed lws_b64 decode selftest "
4843- "%d result '%s' %d\n", test, buf, n);
4844- return -1;
4845- }
4846- }
4847-
4848- return 0;
4849-}
4850
4851=== removed file '.pc/01-visibility.patch/lib/client-handshake.c'
4852--- .pc/01-visibility.patch/lib/client-handshake.c 2013-03-28 19:10:28 +0000
4853+++ .pc/01-visibility.patch/lib/client-handshake.c 1970-01-01 00:00:00 +0000
4854@@ -1,329 +0,0 @@
4855-#include "private-libwebsockets.h"
4856-
4857-struct libwebsocket *__libwebsocket_client_connect_2(
4858- struct libwebsocket_context *context,
4859- struct libwebsocket *wsi
4860-) {
4861- struct pollfd pfd;
4862- struct hostent *server_hostent;
4863- struct sockaddr_in server_addr;
4864- int n;
4865- int plen = 0;
4866- const char *ads;
4867-
4868- lwsl_client("__libwebsocket_client_connect_2\n");
4869-
4870- /*
4871- * proxy?
4872- */
4873-
4874- if (context->http_proxy_port) {
4875- plen = sprintf((char *)context->service_buffer,
4876- "CONNECT %s:%u HTTP/1.0\x0d\x0a"
4877- "User-agent: libwebsockets\x0d\x0a"
4878-/*Proxy-authorization: basic aGVsbG86d29ybGQ= */
4879- "\x0d\x0a",
4880- lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
4881- wsi->u.hdr.c_port);
4882-
4883- /* OK from now on we talk via the proxy, so connect to that */
4884-
4885- /*
4886- * (will overwrite existing pointer,
4887- * leaving old string/frag there but unreferenced)
4888- */
4889- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
4890- context->http_proxy_address))
4891- goto oom4;
4892- wsi->u.hdr.c_port = context->http_proxy_port;
4893- }
4894-
4895- /*
4896- * prepare the actual connection (to the proxy, if any)
4897- */
4898-
4899- ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
4900-
4901- lwsl_client("__libwebsocket_client_connect_2: address %s\n", ads);
4902-
4903- server_hostent = gethostbyname(ads);
4904- if (server_hostent == NULL) {
4905- lwsl_err("Unable to get host name from %s\n", ads);
4906- goto oom4;
4907- }
4908-
4909- wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
4910-
4911- if (wsi->sock < 0) {
4912- lwsl_warn("Unable to open socket\n");
4913- goto oom4;
4914- }
4915-
4916- server_addr.sin_family = AF_INET;
4917- server_addr.sin_port = htons(wsi->u.hdr.c_port);
4918- server_addr.sin_addr = *((struct in_addr *)server_hostent->h_addr);
4919- bzero(&server_addr.sin_zero, 8);
4920-
4921- if (connect(wsi->sock, (struct sockaddr *)&server_addr,
4922- sizeof(struct sockaddr)) == -1) {
4923- lwsl_debug("Connect failed\n");
4924- compatible_close(wsi->sock);
4925- goto oom4;
4926- }
4927-
4928- lwsl_client("connected\n");
4929-
4930- if (lws_set_socket_options(context, wsi->sock)) {
4931- lwsl_err("Failed to set wsi socket options\n");
4932- close(wsi->sock);
4933- goto oom4;
4934- }
4935-
4936- insert_wsi_socket_into_fds(context, wsi);
4937-
4938- /* we are connected to server, or proxy */
4939-
4940- if (context->http_proxy_port) {
4941-
4942- n = send(wsi->sock, context->service_buffer, plen, 0);
4943- if (n < 0) {
4944- compatible_close(wsi->sock);
4945- lwsl_debug("ERROR writing to proxy socket\n");
4946- goto oom4;
4947- }
4948-
4949- libwebsocket_set_timeout(wsi,
4950- PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
4951- AWAITING_TIMEOUT);
4952-
4953- wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
4954-
4955- return wsi;
4956- }
4957-
4958- /*
4959- * provoke service to issue the handshake directly
4960- * we need to do it this way because in the proxy case, this is the
4961- * next state and executed only if and when we get a good proxy
4962- * response inside the state machine... but notice in SSL case this
4963- * may not have sent anything yet with 0 return, and won't until some
4964- * many retries from main loop. To stop that becoming endless,
4965- * cover with a timeout.
4966- */
4967-
4968- libwebsocket_set_timeout(wsi,
4969- PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT);
4970-
4971- wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
4972- pfd.fd = wsi->sock;
4973- pfd.revents = POLLIN;
4974-
4975- n = libwebsocket_service_fd(context, &pfd);
4976-
4977- if (n < 0)
4978- goto oom4;
4979-
4980- if (n) /* returns 1 on failure after closing wsi */
4981- return NULL;
4982-
4983- return wsi;
4984-
4985-oom4:
4986- free(wsi->u.hdr.ah);
4987- free(wsi);
4988-
4989- return NULL;
4990-}
4991-
4992-/**
4993- * libwebsocket_client_connect() - Connect to another websocket server
4994- * @context: Websocket context
4995- * @address: Remote server address, eg, "myserver.com"
4996- * @port: Port to connect to on the remote server, eg, 80
4997- * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
4998- * signed certs
4999- * @path: Websocket path on server
5000- * @host: Hostname on server
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: