proxy auth fix
[platform/upstream/libwebsockets.git] / lib / libwebsockets.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22 #include "private-libwebsockets.h"
23
24 int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
25 static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
26
27 static const char * const log_level_names[] = {
28         "ERR",
29         "WARN",
30         "NOTICE",
31         "INFO",
32         "DEBUG",
33         "PARSER",
34         "HEADER",
35         "EXTENSION",
36         "CLIENT",
37         "LATENCY",
38 };
39
40 void
41 lws_free_wsi(struct libwebsocket *wsi)
42 {
43         if (!wsi)
44                 return;
45
46         /* Protocol user data may be allocated either internally by lws
47          * or by specified the user. Important we don't free external user data */
48         if (wsi->protocol && wsi->protocol->per_session_data_size
49                 && wsi->user_space && !wsi->user_space_externally_allocated) {
50                 lws_free(wsi->user_space);
51         }
52
53         lws_free2(wsi->rxflow_buffer);
54         lws_free2(wsi->truncated_send_malloc);
55
56         // TODO: Probably should handle the union structs in wsi->u here depending
57         //       on connection mode as well. Too spaghetti for me to follow however...
58
59         lws_free_header_table(wsi);
60         lws_free(wsi);
61 }
62
63 void
64 libwebsocket_close_and_free_session(struct libwebsocket_context *context,
65                          struct libwebsocket *wsi, enum lws_close_status reason)
66 {
67         int n, m, ret;
68         int old_state;
69         unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
70                                                   LWS_SEND_BUFFER_POST_PADDING];
71         struct lws_tokens eff_buf;
72
73         if (!wsi)
74                 return;
75
76         old_state = wsi->state;
77
78         if (wsi->socket_is_permanently_unusable ||
79             reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY)
80                 goto just_kill_connection;
81
82         switch (old_state) {
83         case WSI_STATE_DEAD_SOCKET:
84                 return;
85
86         /* we tried the polite way... */
87         case WSI_STATE_AWAITING_CLOSE_ACK:
88                 goto just_kill_connection;
89
90         case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
91                 if (wsi->truncated_send_len) {
92                         libwebsocket_callback_on_writable(context, wsi);
93                         return;
94                 }
95                 lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
96                 goto just_kill_connection;
97         default:
98                 if (wsi->truncated_send_len) {
99                         lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
100                         wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
101                         libwebsocket_set_timeout(wsi, PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE, 5);
102                         return;
103                 }
104                 break;
105         }
106
107         wsi->u.ws.close_reason = reason;
108
109         if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
110                         wsi->mode == LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE)
111                 goto just_kill_connection;
112
113         if (wsi->mode == LWS_CONNMODE_HTTP_SERVING)
114                 context->protocols[0].callback(context, wsi,
115                         LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
116
117         if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
118                 if (wsi->u.http.fd != LWS_INVALID_FILE) {
119                         // TODO: If we're just closing with LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY this file descriptor might leak?
120                         lwsl_debug("closing http file\n");
121                         compatible_file_close(wsi->u.http.fd);
122                         wsi->u.http.fd = LWS_INVALID_FILE;
123                         context->protocols[0].callback(context, wsi,
124                                 LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
125                 }
126         }
127
128         /*
129          * are his extensions okay with him closing?  Eg he might be a mux
130          * parent and just his ch1 aspect is closing?
131          */
132         
133         if (lws_ext_callback_for_each_active(wsi,
134                       LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE, NULL, 0) > 0) {
135                 lwsl_ext("extension vetoed close\n");
136                 return;
137         }
138
139         /*
140          * flush any tx pending from extensions, since we may send close packet
141          * if there are problems with send, just nuke the connection
142          */
143
144         do {
145                 ret = 0;
146                 eff_buf.token = NULL;
147                 eff_buf.token_len = 0;
148
149                 /* show every extension the new incoming data */
150
151                 m = lws_ext_callback_for_each_active(wsi,
152                           LWS_EXT_CALLBACK_FLUSH_PENDING_TX, &eff_buf, 0);
153                 if (m < 0) {
154                         lwsl_ext("Extension reports fatal error\n");
155                         goto just_kill_connection;
156                 }
157                 if (m)
158                         /*
159                          * at least one extension told us he has more
160                          * to spill, so we will go around again after
161                          */
162                         ret = 1;
163
164                 /* assuming they left us something to send, send it */
165
166                 if (eff_buf.token_len)
167                         if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
168                                       eff_buf.token_len) != eff_buf.token_len) {
169                                 lwsl_debug("close: ext spill failed\n");
170                                 goto just_kill_connection;
171                         }
172         } while (ret);
173
174         /*
175          * signal we are closing, libwebsocket_write will
176          * add any necessary version-specific stuff.  If the write fails,
177          * no worries we are closing anyway.  If we didn't initiate this
178          * close, then our state has been changed to
179          * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
180          *
181          * Likewise if it's a second call to close this connection after we
182          * sent the close indication to the peer already, we are in state
183          * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
184          */
185
186         if (old_state == WSI_STATE_ESTABLISHED &&
187             reason != LWS_CLOSE_STATUS_NOSTATUS &&
188             reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY) {
189
190                 lwsl_debug("sending close indication...\n");
191
192                 /* make valgrind happy */
193                 memset(buf, 0, sizeof(buf));
194                 n = libwebsocket_write(wsi,
195                                 &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
196                                                             0, LWS_WRITE_CLOSE);
197                 if (n >= 0) {
198                         /*
199                          * we have sent a nice protocol level indication we
200                          * now wish to close, we should not send anything more
201                          */
202
203                         wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
204
205                         /*
206                          * ...and we should wait for a reply for a bit
207                          * out of politeness
208                          */
209
210                         libwebsocket_set_timeout(wsi,
211                                                   PENDING_TIMEOUT_CLOSE_ACK, 1);
212
213                         lwsl_debug("sent close indication, awaiting ack\n");
214
215                         return;
216                 }
217
218                 lwsl_info("close: sending close packet failed, hanging up\n");
219
220                 /* else, the send failed and we should just hang up */
221         }
222
223 just_kill_connection:
224
225         lwsl_debug("close: just_kill_connection\n");
226
227         /*
228          * we won't be servicing or receiving anything further from this guy
229          * delete socket from the internal poll list if still present
230          */
231
232         lws_ssl_remove_wsi_from_buffered_list(context, wsi);
233
234         // checking return redundant since we anyway close
235         remove_wsi_socket_from_fds(context, wsi);
236
237         wsi->state = WSI_STATE_DEAD_SOCKET;
238
239         lws_free2(wsi->rxflow_buffer);
240         lws_free_header_table(wsi);
241
242         if ((old_state == WSI_STATE_ESTABLISHED ||
243              wsi->mode == LWS_CONNMODE_WS_SERVING ||
244              wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
245
246                 lws_free2(wsi->u.ws.rx_user_buffer);
247
248                 if (wsi->truncated_send_malloc) {
249                         /* not going to be completed... nuke it */
250                         lws_free2(wsi->truncated_send_malloc);
251                         wsi->truncated_send_len = 0;
252                 }
253                 if (wsi->u.ws.ping_payload_buf) {
254                         lws_free2(wsi->u.ws.ping_payload_buf);
255                         wsi->u.ws.ping_payload_alloc = 0;
256                         wsi->u.ws.ping_payload_len = 0;
257                         wsi->u.ws.ping_pending_flag = 0;
258                 }
259         }
260
261         /* tell the user it's all over for this guy */
262
263         if (wsi->protocol && wsi->protocol->callback &&
264                         ((old_state == WSI_STATE_ESTABLISHED) ||
265                          (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
266                          (old_state == WSI_STATE_AWAITING_CLOSE_ACK) ||
267                          (old_state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE))) {
268                 lwsl_debug("calling back CLOSED\n");
269                 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
270                                                       wsi->user_space, NULL, 0);
271         } else if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
272                 lwsl_debug("calling back CLOSED_HTTP\n");
273                 context->protocols[0].callback(context, wsi,
274                         LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0 );
275         } else if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY ||
276                    wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT) {
277                 lwsl_debug("Connection closed before server reply\n");
278                 context->protocols[0].callback(context, wsi,
279                                 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
280                                 wsi->user_space, NULL, 0 );
281         } else
282                 lwsl_debug("not calling back closed mode=%d state=%d\n",
283                            wsi->mode, old_state);
284
285         /* deallocate any active extension contexts */
286         
287         if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_DESTROY, NULL, 0) < 0)
288                 lwsl_warn("extension destruction failed\n");
289 #ifndef LWS_NO_EXTENSIONS
290         for (n = 0; n < wsi->count_active_extensions; n++)
291                 lws_free(wsi->active_extensions_user[n]);
292 #endif
293         /*
294          * inform all extensions in case they tracked this guy out of band
295          * even though not active on him specifically
296          */
297         if (lws_ext_callback_for_each_extension_type(context, wsi,
298                        LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING, NULL, 0) < 0)
299                 lwsl_warn("ext destroy wsi failed\n");
300
301 /*      lwsl_info("closing fd=%d\n", wsi->sock); */
302
303         if (!lws_ssl_close(wsi) && lws_socket_is_valid(wsi->sock)) {
304 #if LWS_POSIX
305                 n = shutdown(wsi->sock, SHUT_RDWR);
306                 if (n)
307                         lwsl_debug("closing: shutdown ret %d\n", LWS_ERRNO);
308
309                 n = compatible_close(wsi->sock);
310                 if (n)
311                         lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
312
313 #else
314                 compatible_close(wsi->sock);
315 #endif
316                 wsi->sock = LWS_SOCK_INVALID;
317         }
318
319         /* outermost destroy notification for wsi (user_space still intact) */
320         context->protocols[0].callback(context, wsi,
321                         LWS_CALLBACK_WSI_DESTROY, wsi->user_space, NULL, 0);
322
323         lws_free_wsi(wsi);
324 }
325
326 LWS_VISIBLE int
327 libwebsockets_get_addresses(struct libwebsocket_context *context,
328                             void *ads, char *name, int name_len,
329                             char *rip, int rip_len)
330 {
331 #if LWS_POSIX
332         struct addrinfo ai, *res;
333         struct sockaddr_in addr4;
334
335         rip[0] = '\0';
336         name[0] = '\0';
337         addr4.sin_family = AF_UNSPEC;
338
339 #ifdef LWS_USE_IPV6
340         if (LWS_IPV6_ENABLED(context)) {
341                 if (!lws_plat_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ads)->sin6_addr, rip, rip_len)) {
342                         lwsl_err("inet_ntop", strerror(LWS_ERRNO));
343                         return -1;
344                 }
345
346                 // Strip off the IPv4 to IPv6 header if one exists
347                 if (strncmp(rip, "::ffff:", 7) == 0)
348                         memmove(rip, rip + 7, strlen(rip) - 6);
349
350                 getnameinfo((struct sockaddr *)ads,
351                                 sizeof(struct sockaddr_in6), name,
352                                                         name_len, NULL, 0, 0);
353                 
354                 return 0;
355         } else
356 #endif
357         {
358                 struct addrinfo *result;
359
360                 memset(&ai, 0, sizeof ai);
361                 ai.ai_family = PF_UNSPEC;
362                 ai.ai_socktype = SOCK_STREAM;
363                 ai.ai_flags = AI_CANONNAME;
364
365                 if (getnameinfo((struct sockaddr *)ads,
366                                 sizeof(struct sockaddr_in),
367                                 name, name_len, NULL, 0, 0))
368                         return -1;
369
370                 if (!rip)
371                         return 0;
372
373                 if (getaddrinfo(name, NULL, &ai, &result))
374                         return -1;
375
376                 res = result;
377                 while (addr4.sin_family == AF_UNSPEC && res) {
378                         switch (res->ai_family) {
379                         case AF_INET:
380                                 addr4.sin_addr = ((struct sockaddr_in *)res->ai_addr)->sin_addr;
381                                 addr4.sin_family = AF_INET;
382                                 break;
383                         }
384
385                         res = res->ai_next;
386                 }
387                 freeaddrinfo(result);
388         }
389
390         if (addr4.sin_family == AF_UNSPEC)
391                 return -1;
392
393         lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, rip_len);
394
395         return 0;
396 #else
397         (void)context;
398         (void)ads;
399         (void)name;
400         (void)name_len;
401         (void)rip;
402         (void)rip_len;
403
404         return -1;
405 #endif
406 }
407
408 /**
409  * libwebsockets_get_peer_addresses() - Get client address information
410  * @context:    Libwebsockets context
411  * @wsi:        Local struct libwebsocket associated with
412  * @fd:         Connection socket descriptor
413  * @name:       Buffer to take client address name
414  * @name_len:   Length of client address name buffer
415  * @rip:        Buffer to take client address IP dotted quad
416  * @rip_len:    Length of client address IP buffer
417  *
418  *      This function fills in @name and @rip with the name and IP of
419  *      the client connected with socket descriptor @fd.  Names may be
420  *      truncated if there is not enough room.  If either cannot be
421  *      determined, they will be returned as valid zero-length strings.
422  */
423
424 LWS_VISIBLE void
425 libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
426         struct libwebsocket *wsi, lws_sockfd_type fd, char *name, int name_len,
427                                         char *rip, int rip_len)
428 {
429 #if LWS_POSIX
430         socklen_t len;
431 #ifdef LWS_USE_IPV6
432         struct sockaddr_in6 sin6;
433 #endif
434         struct sockaddr_in sin4;
435         int ret = -1;
436         void *p;
437
438         rip[0] = '\0';
439         name[0] = '\0';
440
441         lws_latency_pre(context, wsi);
442
443 #ifdef LWS_USE_IPV6
444         if (LWS_IPV6_ENABLED(context)) {
445                 len = sizeof(sin6);
446                 p = &sin6;
447         } else
448 #endif
449         {
450                 len = sizeof(sin4);
451                 p = &sin4;
452         }
453
454         if (getpeername(fd, p, &len) < 0) {
455                 lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
456                 goto bail;
457         }
458         
459         ret = libwebsockets_get_addresses(context, p, name, name_len, rip, rip_len);
460
461 bail:
462         lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
463 #else
464         (void)context;
465         (void)wsi;
466         (void)fd;
467         (void)name;
468         (void)name_len;
469         (void)rip;
470         (void)rip_len;
471 #endif
472 }
473
474 /**
475  * libwebsocket_context_user() - get the user data associated with the context
476  * @context: Websocket context
477  *
478  *      This returns the optional user allocation that can be attached to
479  *      the context the sockets live in at context_create time.  It's a way
480  *      to let all sockets serviced in the same context share data without
481  *      using globals statics in the user code.
482  */
483 LWS_EXTERN void *
484 libwebsocket_context_user(struct libwebsocket_context *context)
485 {
486         return context->user_space;
487 }
488
489
490 /**
491  * libwebsocket_callback_all_protocol() - Callback all connections using
492  *                              the given protocol with the given reason
493  *
494  * @protocol:   Protocol whose connections will get callbacks
495  * @reason:     Callback reason index
496  */
497
498 LWS_VISIBLE int
499 libwebsocket_callback_all_protocol(
500                 const struct libwebsocket_protocols *protocol, int reason)
501 {
502         struct libwebsocket_context *context = protocol->owning_server;
503         int n;
504         struct libwebsocket *wsi;
505
506         for (n = 0; n < context->fds_count; n++) {
507                 wsi = wsi_from_fd(context, context->fds[n].fd);
508                 if (!wsi)
509                         continue;
510                 if (wsi->protocol == protocol)
511                         protocol->callback(context, wsi,
512                                         reason, wsi->user_space, NULL, 0);
513         }
514
515         return 0;
516 }
517
518 /**
519  * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
520  *
521  * You will not need this unless you are doing something special
522  *
523  * @wsi:        Websocket connection instance
524  * @reason:     timeout reason
525  * @secs:       how many seconds
526  */
527
528 LWS_VISIBLE void
529 libwebsocket_set_timeout(struct libwebsocket *wsi,
530                                           enum pending_timeout reason, int secs)
531 {
532         time_t now;
533
534         time(&now);
535
536         wsi->pending_timeout_limit = now + secs;
537         wsi->pending_timeout = reason;
538 }
539
540
541 #if LWS_POSIX
542
543 /**
544  * libwebsocket_get_socket_fd() - returns the socket file descriptor
545  *
546  * You will not need this unless you are doing something special
547  *
548  * @wsi:        Websocket connection instance
549  */
550
551 LWS_VISIBLE int
552 libwebsocket_get_socket_fd(struct libwebsocket *wsi)
553 {
554         return wsi->sock;
555 }
556
557 #endif
558
559 #ifdef LWS_LATENCY
560 void
561 lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
562                                      const char *action, int ret, int completed)
563 {
564         unsigned long long u;
565         char buf[256];
566
567         u = time_in_microseconds();
568
569         if (!action) {
570                 wsi->latency_start = u;
571                 if (!wsi->action_start)
572                         wsi->action_start = u;
573                 return;
574         }
575         if (completed) {
576                 if (wsi->action_start == wsi->latency_start)
577                         sprintf(buf,
578                           "Completion first try lat %lluus: %p: ret %d: %s\n",
579                                         u - wsi->latency_start,
580                                                       (void *)wsi, ret, action);
581                 else
582                         sprintf(buf,
583                           "Completion %lluus: lat %lluus: %p: ret %d: %s\n",
584                                 u - wsi->action_start,
585                                         u - wsi->latency_start,
586                                                       (void *)wsi, ret, action);
587                 wsi->action_start = 0;
588         } else
589                 sprintf(buf, "lat %lluus: %p: ret %d: %s\n",
590                               u - wsi->latency_start, (void *)wsi, ret, action);
591
592         if (u - wsi->latency_start > context->worst_latency) {
593                 context->worst_latency = u - wsi->latency_start;
594                 strcpy(context->worst_latency_info, buf);
595         }
596         lwsl_latency("%s", buf);
597 }
598 #endif
599
600
601
602 /**
603  * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
604  *                              received packets.
605  *
606  * If the output side of a server process becomes choked, this allows flow
607  * control for the input side.
608  *
609  * @wsi:        Websocket connection instance to get callback for
610  * @enable:     0 = disable read servicing for this connection, 1 = enable
611  */
612
613 LWS_VISIBLE int
614 libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
615 {
616         if (enable == (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW))
617                 return 0;
618
619         lwsl_info("libwebsocket_rx_flow_control(0x%p, %d)\n", wsi, enable);
620         wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | !!enable;
621
622         return 0;
623 }
624
625 /**
626  * libwebsocket_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive
627  *
628  * When the user server code realizes it can accept more input, it can
629  * call this to have the RX flow restriction removed from all connections using
630  * the given protocol.
631  *
632  * @protocol:   all connections using this protocol will be allowed to receive
633  */
634
635 LWS_VISIBLE void
636 libwebsocket_rx_flow_allow_all_protocol(
637                                 const struct libwebsocket_protocols *protocol)
638 {
639         struct libwebsocket_context *context = protocol->owning_server;
640         int n;
641         struct libwebsocket *wsi;
642
643         for (n = 0; n < context->fds_count; n++) {
644                 wsi = wsi_from_fd(context, context->fds[n].fd);
645                 if (!wsi)
646                         continue;
647                 if (wsi->protocol == protocol)
648                         libwebsocket_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
649         }
650 }
651
652
653 /**
654  * libwebsocket_canonical_hostname() - returns this host's hostname
655  *
656  * This is typically used by client code to fill in the host parameter
657  * when making a client connection.  You can only call it after the context
658  * has been created.
659  *
660  * @context:    Websocket context
661  */
662 LWS_VISIBLE extern const char *
663 libwebsocket_canonical_hostname(struct libwebsocket_context *context)
664 {
665         return (const char *)context->canonical_hostname;
666 }
667
668 int user_callback_handle_rxflow(callback_function callback_function,
669                 struct libwebsocket_context *context,
670                         struct libwebsocket *wsi,
671                          enum libwebsocket_callback_reasons reason, void *user,
672                                                           void *in, size_t len)
673 {
674         int n;
675
676         n = callback_function(context, wsi, reason, user, in, len);
677         if (!n)
678                 n = _libwebsocket_rx_flow_control(wsi);
679
680         return n;
681 }
682
683
684 /**
685  * libwebsocket_set_proxy() - Setups proxy to libwebsocket_context.
686  * @context:    pointer to struct libwebsocket_context you want set proxy to
687  * @proxy: pointer to c string containing proxy in format address:port
688  *
689  * Returns 0 if proxy string was parsed and proxy was setup. 
690  * Returns -1 if @proxy is NULL or has incorrect format.
691  *
692  * This is only required if your OS does not provide the http_proxy
693  * environment variable (eg, OSX)
694  *
695  *   IMPORTANT! You should call this function right after creation of the
696  *   libwebsocket_context and before call to connect. If you call this
697  *   function after connect behavior is undefined.
698  *   This function will override proxy settings made on libwebsocket_context
699  *   creation with genenv() call.
700  */
701
702 LWS_VISIBLE int
703 libwebsocket_set_proxy(struct libwebsocket_context *context, const char *proxy)
704 {
705         char *p;
706         char authstring[96];
707         
708         if (!proxy)
709                 return -1;
710
711         p = strchr(proxy, '@');
712         if (p) { /* auth is around */
713
714                 if ((unsigned int)(p - proxy) > sizeof(authstring) - 1)
715                         goto auth_too_long;
716
717                 strncpy(authstring, proxy, p - proxy);
718                 // null termination not needed on input
719                 if (lws_b64_encode_string(authstring, (p - proxy),
720                     context->proxy_basic_auth_token,
721                     sizeof context->proxy_basic_auth_token) < 0)
722                         goto auth_too_long;
723
724                 lwsl_notice(" Proxy auth in use\n");
725                         
726                 proxy = p + 1;
727         } else
728                 context->proxy_basic_auth_token[0] = '\0';
729
730         strncpy(context->http_proxy_address, proxy,
731                                 sizeof(context->http_proxy_address) - 1);
732         context->http_proxy_address[
733                                 sizeof(context->http_proxy_address) - 1] = '\0';
734
735         p = strchr(context->http_proxy_address, ':');
736         if (!p && !context->http_proxy_port) {
737                 lwsl_err("http_proxy needs to be ads:port\n");
738
739                 return -1;
740         } else {
741                 *p = '\0';
742                 context->http_proxy_port = atoi(p + 1);
743         }
744
745         lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address,
746                                                 context->http_proxy_port);
747
748         return 0;
749
750 auth_too_long:
751         lwsl_err("proxy auth too long\n");
752
753         return -1;
754 }
755
756 /**
757  * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
758  *                                connection.
759  * @wsi:        pointer to struct websocket you want to know the protocol of
760  *
761  *
762  *      Some apis can act on all live connections of a given protocol,
763  *      this is how you can get a pointer to the active protocol if needed.
764  */
765
766 LWS_VISIBLE const struct libwebsocket_protocols *
767 libwebsockets_get_protocol(struct libwebsocket *wsi)
768 {
769         return wsi->protocol;
770 }
771
772 LWS_VISIBLE int
773 libwebsocket_is_final_fragment(struct libwebsocket *wsi)
774 {
775         return wsi->u.ws.final;
776 }
777
778 LWS_VISIBLE unsigned char
779 libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
780 {
781         return wsi->u.ws.rsv;
782 }
783
784 int
785 libwebsocket_ensure_user_space(struct libwebsocket *wsi)
786 {
787         lwsl_info("%s: %p protocol %p\n", __func__, wsi, wsi->protocol);
788         if (!wsi->protocol)
789                 return 1;
790
791         /* allocate the per-connection user memory (if any) */
792
793         if (wsi->protocol->per_session_data_size && !wsi->user_space) {
794                 wsi->user_space = lws_zalloc(wsi->protocol->per_session_data_size);
795                 if (wsi->user_space  == NULL) {
796                         lwsl_err("Out of memory for conn user space\n");
797                         return 1;
798                 }
799         } else
800                 lwsl_info("%s: %p protocol pss %u, user_space=%d\n", __func__, wsi, wsi->protocol->per_session_data_size, wsi->user_space);
801         return 0;
802 }
803
804 LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
805 {
806         char buf[300];
807         unsigned long long now;
808         int n;
809
810         buf[0] = '\0';
811         for (n = 0; n < LLL_COUNT; n++)
812                 if (level == (1 << n)) {
813                         now = time_in_microseconds() / 100;
814                         sprintf(buf, "[%llu:%04d] %s: ", (unsigned long long) now / 10000,
815                                 (int)(now % 10000), log_level_names[n]);
816                         break;
817                 }
818
819         fprintf(stderr, "%s%s", buf, line);
820 }
821
822
823 LWS_VISIBLE void _lws_logv(int filter, const char *format, va_list vl)
824 {
825         char buf[256];
826
827         if (!(log_level & filter))
828                 return;
829
830         vsnprintf(buf, sizeof(buf), format, vl);
831         buf[sizeof(buf) - 1] = '\0';
832
833         lwsl_emit(filter, buf);
834 }
835
836 LWS_VISIBLE void _lws_log(int filter, const char *format, ...)
837 {
838         va_list ap;
839
840         va_start(ap, format);
841         _lws_logv(filter, format, ap);
842         va_end(ap);
843 }
844
845 /**
846  * lws_set_log_level() - Set the logging bitfield
847  * @level:      OR together the LLL_ debug contexts you want output from
848  * @log_emit_function:  NULL to leave it as it is, or a user-supplied
849  *                      function to perform log string emission instead of
850  *                      the default stderr one.
851  *
852  *      log level defaults to "err", "warn" and "notice" contexts enabled and
853  *      emission on stderr.
854  */
855
856 LWS_VISIBLE void lws_set_log_level(int level, void (*log_emit_function)(int level,
857                                                               const char *line))
858 {
859         log_level = level;
860         if (log_emit_function)
861                 lwsl_emit = log_emit_function;
862 }
863
864 /**
865  * lws_use_ssl() - Find out if connection is using SSL
866  * @wsi:        websocket connection to check
867  *
868  *      Returns 0 if the connection is not using SSL, 1 if using SSL and
869  *      using verified cert, and 2 if using SSL but the cert was not
870  *      checked (appears for client wsi told to skip check on connection)
871  */
872 LWS_VISIBLE int
873 lws_is_ssl(struct libwebsocket *wsi)
874 {
875 #ifdef LWS_OPENSSL_SUPPORT
876         return wsi->use_ssl;
877 #else
878         (void)wsi;
879         return 0;
880 #endif
881 }
882
883 /**
884  * lws_partial_buffered() - find out if lws buffered the last write
885  * @wsi:        websocket connection to check
886  *
887  * Returns 1 if you cannot use libwebsocket_write because the last
888  * write on this connection is still buffered, and can't be cleared without
889  * returning to the service loop and waiting for the connection to be
890  * writeable again.
891  * 
892  * If you will try to do >1 libwebsocket_write call inside a single
893  * WRITEABLE callback, you must check this after every write and bail if
894  * set, ask for a new writeable callback and continue writing from there.
895  * 
896  * This is never set at the start of a writeable callback, but any write
897  * may set it.
898  */
899
900 LWS_VISIBLE int
901 lws_partial_buffered(struct libwebsocket *wsi)
902 {
903         return !!wsi->truncated_send_len;       
904 }
905
906 void lws_set_protocol_write_pending(struct libwebsocket_context *context,
907                                     struct libwebsocket *wsi,
908                                     enum lws_pending_protocol_send pend)
909 {
910         lwsl_info("setting pps %d\n", pend);
911         
912         if (wsi->pps)
913                 lwsl_err("pps overwrite\n");
914         wsi->pps = pend;
915         libwebsocket_rx_flow_control(wsi, 0);
916         libwebsocket_callback_on_writable(context, wsi);
917 }
918
919 LWS_VISIBLE size_t
920 lws_get_peer_write_allowance(struct libwebsocket *wsi)
921 {
922 #ifdef LWS_USE_HTTP2
923         /* only if we are using HTTP2 on this connection */
924         if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING)
925                 return -1;
926         /* user is only interested in how much he can send, or that he can't  */
927         if (wsi->u.http2.tx_credit <= 0)
928                 return 0;
929         
930         return wsi->u.http2.tx_credit;
931 #else
932         (void)wsi;
933         return -1;
934 #endif
935 }
936
937 LWS_VISIBLE void
938 lws_union_transition(struct libwebsocket *wsi, enum connection_mode mode)
939 {
940         memset(&wsi->u, 0, sizeof(wsi->u));
941         wsi->mode = mode;
942 }