this repo has no description
1/*
2 web.h - BSD LICENSE - Andreas Fredriksson
3
4ABOUT:
5 This is a web server intended for debugging tools inside a
6 program with a continously running main loop. It's intended to be used when
7 all you need is something tiny and performance isn't a key concern.
8 NOTE: this is a single header port of Andreas Fredriksson
9 Webby(https://github.com/deplinenoise/webby).
10
11 Features
12 - Single header library to be easy to embed into your code.
13 - No dynamic memory allocations -- server memory is completely fixed
14 - No threading, all I/O and serving happens on the calling thread
15 - Supports socket keep-alives
16 - Supports the 100-Continue scheme for file uploading
17 - Basic support for WebSockets is available.
18
19 Because request/response I/O is synchronous on the calling thread, performance
20 will suffer when you are serving data. For the use-cases wby is intended for,
21 this is fine. You can still run wby in a background thread at your
22 discretion if this is a problem.
23
24DEFINES:
25 WBY_IMPLEMENTATION
26 Generates the implementation of the library into the included file.
27 If not provided the library is in header only mode and can be included
28 in other headers or source files without problems. But only ONE file
29 should hold the implementation.
30
31 WBY_STATIC
32 The generated implementation will stay private inside implementation
33 file and all internal symbols and functions will only be visible inside
34 that file.
35
36 WBY_ASSERT
37 WBY_USE_ASSERT
38 If you define WBY_USE_ASSERT without defining ASSERT web.h
39 will use assert.h and asssert(). Otherwise it will use your assert
40 method. If you do not define WBY_USE_ASSERT no additional checks
41 will be added. This is the only C standard library function used
42 by web.
43
44 WBY_UINT_PTR
45 If your compiler is C99 you do not need to define this.
46 Otherwise, web will try default assignments for them
47 and validate them at compile time. If they are incorrect, you will
48 get compile errors and will need to define them yourself.
49
50 You can define this to 'size_t' if you use the standard library,
51 otherwise it needs to be able to hold the maximum addressable memory
52 space. If you do not define this it will default to unsigned long.
53
54
55LICENSE: (BSD)
56 Copyright (c) 2016, Andreas Fredriksson, Micha Mettke
57 All rights reserved.
58
59 Redistribution and use in source and binary forms, with or without
60 modification, are permitted provided that the following conditions are met:
61
62 1. Redistributions of source code must retain the above copyright notice, this
63 list of conditions and the following disclaimer.
64 2. Redistributions in binary form must reproduce the above copyright notice,
65 this list of conditions and the following disclaimer in the documentation
66 and/or other materials provided with the distribution.
67
68 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
69 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
70 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
71 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
72 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
73 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
74 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
75 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
76 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
77 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
78
79CONTRIBUTORS:
80 Andreas Fredriksson (implementation)
81 Micha Mettke (single header conversion)
82
83USAGE:
84 Request handling
85 When you configure the server, you give it a function pointer to your
86 dispatcher. The dispatcher is called by wby when a request has been fully
87 read into memory and is ready for processing. The socket the request came in on
88 has then been switched to blocking mode, and you're free to read any request
89 data using `wby_read()` (if present, check `content_length`) and then write
90 your response.
91 There are two ways to generate a response; explicit size or chunked.
92
93 When you know the size of the data
94 When you know in advance how big the response is going to be, you should pass
95 that size in bytes to `wby_response_begin()` (it will be sent as the
96 Content-Length header). You then call `wby_write()` to push that data out, and
97 finally `wby_response_end()` to finalize the response and prepare the socket
98 for a new request.
99
100 When the response size is dynamic
101 Sometimes you want to generate an arbitrary amount of text in the response, and
102 you don't know how much that will be. Rather than buffering everything in RAM,
103 you can use chunked encoding. First call `wby_response_begin()` as normal, but
104 pass it -1 for the content length. This triggers sending the
105 `Transfer-Encoding: chunked` header. You then call `wby_write()` as desired
106 until the response is complete. When you're done, call `wby_response_end()` to finish up.
107
108EXAMPLES:
109 for a actual working example please look inside tests/wby_test.c */
110#if 0
111/* request and websocket handling callback */
112static int dispatch(struct wby_con *connection, void *pArg);
113static int websocket_connect(struct wby_con *conn, void *pArg);
114static void websocket_connected(struct wby_con *con, void *pArg);
115static int websocket_frame(struct wby_con *conn, const struct wby_frame *frame, void *pArg);
116static void websocket_closed(struct wby_con *connection, void *pArg);
117
118int main(int argc, const char * argv[])
119{
120 /* setup config */
121 struct wby_config config;
122 memset(config, 0, sizeof(config));
123 config.address = "127.0.0.1";
124 config.port = 8888;
125 config.connection_max = 8;
126 config.request_buffer_size = 2048;
127 config.io_buffer_size = 8192;
128 config.dispatch = dispatch;
129 config.ws_connect = websocket_connect;
130 config.ws_connected = websocket_connected;
131 config.ws_frame = websocket_frame;
132 config.ws_closed = websocket_closed;
133
134 /* compute and allocate needed memory and start server */
135 struct wby_server server;
136 size_t needed_memory;
137 wby_server_init(&server, &config, &needed_memory);
138 void *memory = calloc(needed_memory, 1);
139 wby_server_start(&server, memory);
140 while (1) {
141 wby_server_update(&server);
142
143 }
144 wby_server_stop(&server);
145 free(memory);
146}
147#endif
148 /* ===============================================================
149 *
150 * HEADER
151 *
152 * =============================================================== */
153#ifndef WBY_H_
154#define WBY_H_
155
156#ifdef __cplusplus
157extern "C" {
158#endif
159
160#ifdef WBY_STATIC
161#define WBY_API static
162#else
163#define WBY_API extern
164#endif
165
166#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 19901L)
167#include <stdint.h>
168#ifndef WBY_UINT_PTR
169#define WBY_UINT_PTR uintptr_t
170#endif
171#else
172#ifndef WBY_UINT_PTR
173
174#if defined(__i386__) || (!defined(_WIN64) && defined(_WIN32))
175#define WBY_UINT_PTR unsigned long
176#else
177#define WBY_UINT_PTR unsigned long long
178#endif
179
180#endif
181#endif
182typedef unsigned char wby_byte;
183typedef WBY_UINT_PTR wby_size;
184typedef WBY_UINT_PTR wby_ptr;
185
186#define WBY_OK (0)
187#define WBY_FLAG(x) (1 << (x))
188
189#ifndef WBY_MAX_HEADERS
190#define WBY_MAX_HEADERS 64
191#endif
192
193struct wby_header {
194 const char *name;
195 const char *value;
196};
197
198/* A HTTP request. */
199struct wby_request {
200 const char *method;
201 /* The method of the request, e.g. "GET", "POST" and so on */
202 const char *uri;
203 /* The URI that was used. */
204 const char *http_version;
205 /* The used HTTP version */
206 const char *query_params;
207 /* The query parameters passed in the URL, or NULL if none were passed. */
208 int content_length;
209 /* The number of bytes of request body that are available via WebbyRead() */
210 int header_count;
211 /* The number of headers */
212 struct wby_header headers[WBY_MAX_HEADERS];
213 /* Request headers */
214};
215
216/* Connection state, as published to the serving callback. */
217struct wby_con {
218 struct wby_request request;
219 /* The request being served. Read-only. */
220 void *user_data;
221 /* User data. Read-write. wby doesn't care about this. */
222};
223
224struct wby_frame {
225 wby_byte flags;
226 wby_byte opcode;
227 wby_byte header_size;
228 wby_byte padding_;
229 wby_byte mask_key[4];
230 int payload_length;
231};
232
233enum wby_websock_flags {
234 WBY_WSF_FIN = WBY_FLAG(0),
235 WBY_WSF_MASKED = WBY_FLAG(1)
236};
237
238enum wby_websock_operation {
239 WBY_WSOP_CONTINUATION = 0,
240 WBY_WSOP_TEXT_FRAME = 1,
241 WBY_WSOP_BINARY_FRAME = 2,
242 WBY_WSOP_CLOSE = 8,
243 WBY_WSOP_PING = 9,
244 WBY_WSOP_PONG = 10
245};
246
247/* Configuration data required for starting a server. */
248typedef void(*wby_log_f)(const char *msg);
249struct wby_config {
250 void *userdata;
251 /* userdata which will be passed */
252 const char *address;
253 /* The bind address. Must be a textual IP address. */
254 unsigned short port;
255 /* The port to listen to. */
256 unsigned int connection_max;
257 /* Maximum number of simultaneous connections. */
258 wby_size request_buffer_size;
259 /* The size of the request buffer. This must be big enough to contain all
260 * headers and the request line sent by the client. 2-4k is a good size for
261 * this buffer. */
262 wby_size io_buffer_size;
263 /* The size of the I/O buffer, used when writing the reponse. 4k is a good
264 * choice for this buffer.*/
265 wby_log_f log;
266 /* Optional callback function that receives debug log text (without newlines). */
267 int(*dispatch)(struct wby_con *con, void *userdata);
268 /* Request dispatcher function. This function is called when the request
269 * structure is ready.
270 * If you decide to handle the request, call wby_response_begin(),
271 * wby_write() and wby_response_end() and then return 0. Otherwise, return a
272 * non-zero value to have Webby send back a 404 response. */
273 int(*ws_connect)(struct wby_con*, void *userdata);
274 /*WebSocket connection dispatcher. Called when an incoming request wants to
275 * update to a WebSocket connection.
276 * Return 0 to allow the connection.
277 * Return 1 to ignore the connection.*/
278 void (*ws_connected)(struct wby_con*, void *userdata);
279 /* Called when a WebSocket connection has been established.*/
280 void (*ws_closed)(struct wby_con*, void *userdata);
281 /*Called when a WebSocket connection has been closed.*/
282 int (*ws_frame)(struct wby_con*, const struct wby_frame *frame, void *userdata);
283 /*Called when a WebSocket data frame is incoming.
284 * Call wby_read() to read the payload data.
285 * Return non-zero to close the connection.*/
286};
287
288struct wby_connection;
289struct wby_server {
290 struct wby_config config;
291 /* server configuration */
292 wby_size memory_size;
293 /* minimum required memory */
294 wby_ptr socket;
295 /* server socket */
296 wby_size con_count;
297 /* number of active connection */
298 struct wby_connection *con;
299 /* connections */
300#ifdef _WIN32
301 int windows_socket_initialized;
302 /* whether WSAStartup had to be called on Windows */
303#endif
304};
305
306WBY_API void wby_init(struct wby_server*, const struct wby_config*,
307 wby_size *needed_memory);
308/* this function clears the server and calculates the needed memory to run
309 Input:
310 - filled server configuration data to calculate the needed memory
311 Output:
312 - needed memory for the server to run
313*/
314WBY_API int wby_start(struct wby_server*, void *memory);
315/* this function starts running the server in the specificed memory space. Size
316 * must be at least big enough as determined in the wby_server_init().
317 Input:
318 - allocated memory space to create the server into
319*/
320WBY_API void wby_update(struct wby_server*);
321/* updates the server by being called frequenctly (at least once a frame) */
322WBY_API void wby_stop(struct wby_server*);
323/* stops and shutdown the server */
324WBY_API int wby_response_begin(struct wby_con*, int status_code, int content_length,
325 const struct wby_header headers[], int header_count);
326/* this function begins a response
327 Input:
328 - HTTP status code to send. (Normally 200).
329 - size in bytes you intend to write, or -1 for chunked encoding
330 - array of HTTP headers to transmit (can be NULL of header_count == 0)
331 - number of headers in the array
332 Output:
333 - returns 0 on success, non-zero on error.
334*/
335WBY_API void wby_response_end(struct wby_con*);
336/* this function finishes a response. When you're done wirting the response
337 * body, call this function. this makes sure chunked encoding is terminated
338 * correctly and that the connection is setup for reuse. */
339WBY_API int wby_read(struct wby_con*, void *ptr, wby_size len);
340/* this function reads data from the request body. Only read what the client
341 * has priovided (via content_length) parameter, or you will end up blocking
342 * forever.
343 Input:
344 - pointer to a memory block that will be filled
345 - size of the memory block to fill
346*/
347WBY_API int wby_write(struct wby_con*, const void *ptr, wby_size len);
348/* this function writes a response data to the connection. If you're not using
349 * chunked encoding, be careful not to send more than the specified content
350 * length. You can call this function multiple times as long as the total
351 * number of bytes matches up with the content length.
352 Input:
353 - pointer to a memory block that will be send
354 - size of the memory block to send
355*/
356WBY_API int wby_frame_begin(struct wby_con*, int opcode);
357/* this function begins an outgoing websocket frame */
358WBY_API int wby_frame_end(struct wby_con*);
359/* this function finishes an outgoing websocket frame */
360WBY_API int wby_find_query_var(const char *buf, const char *name, char *dst, wby_size dst_len);
361/* this function is a helper function to lookup a query parameter given a URL
362 * encoded string. Returns the size of the returned data, or -1 if the query
363 * var wasn't found. */
364WBY_API const char* wby_find_header(struct wby_con*, const char *name);
365/* this convenience function to find a header in a request. Returns the value
366 * of the specified header, or NULL if its was not present. */
367
368#ifdef __cplusplus
369}
370#endif
371#endif /* WBY_H_ */
372/* ===============================================================
373 *
374 * IMPLEMENTATION
375 *
376 * ===============================================================*/
377#ifdef WBY_IMPLEMENTATION
378
379typedef int wby__check_ptr_size[(sizeof(void*) == sizeof(WBY_UINT_PTR)) ? 1 : -1];
380#define WBY_LEN(a) (sizeof(a)/sizeof((a)[0]))
381#define WBY_UNUSED(a) ((void)(a))
382
383#ifdef WBY_USE_ASSERT
384#ifndef WBY_ASSERT
385#include <assert.h>
386#define WBY_ASSERT(expr) assert(expr)
387#endif
388#else
389#define WBY_ASSERT(expr)
390#endif
391
392#include <string.h>
393#include <stdlib.h>
394#include <stdarg.h>
395#include <stdio.h>
396#include <ctype.h>
397#include <time.h>
398
399#define WBY_SOCK(s) ((wby_socket)(s))
400#define WBY_INTERN static
401#define WBY_GLOBAL static
402#define WBY_STORAGE static
403
404/* ===============================================================
405 * UTIL
406 * ===============================================================*/
407struct wby_buffer {
408 wby_size used;
409 /* current buffer size */
410 wby_size max;
411 /* buffer capacity */
412 wby_byte *data;
413 /* pointer inside a global buffer */
414};
415
416WBY_INTERN void
417wby_dbg(wby_log_f log, const char *fmt, ...)
418{
419 char buffer[1024];
420 va_list args;
421 if (!log) return;
422
423 va_start(args, fmt);
424 vsnprintf(buffer, sizeof buffer, fmt, args);
425 va_end(args);
426 buffer[(sizeof buffer)-1] = '\0';
427 log(buffer);
428}
429
430WBY_INTERN int
431wb_peek_request_size(const wby_byte *buf, int len)
432{
433 int i;
434 int max = len - 3;
435 for (i = 0; i < max; ++i) {
436 if ('\r' != buf[i + 0]) continue;
437 if ('\n' != buf[i + 1]) continue;
438 if ('\r' != buf[i + 2]) continue;
439 if ('\n' != buf[i + 3]) continue;
440 /* OK; we have CRLFCRLF which indicates the end of the header section */
441 return i + 4;
442 }
443 return -1;
444}
445
446WBY_INTERN char*
447wby_skipws(char *p)
448{
449 for (;;) {
450 char ch = *p;
451 if (' ' == ch || '\t' == ch) ++p;
452 else break;
453 }
454 return p;
455}
456
457#define WBY_TOK_SKIPWS WBY_FLAG(0)
458WBY_INTERN int
459wby_tok_inplace(char *buf, const char* separator, char *tokens[], int max, int flags)
460{
461 char *b = buf;
462 char *e = buf;
463 int token_count = 0;
464 int separator_len = (int)strlen(separator);
465 while (token_count < max) {
466 if (flags & WBY_TOK_SKIPWS)
467 b = wby_skipws(b);
468 if (NULL != (e = strstr(b, separator))) {
469 int len = (int) (e - b);
470 if (len > 0)
471 tokens[token_count++] = b;
472 *e = '\0';
473 b = e + separator_len;
474 } else {
475 tokens[token_count++] = b;
476 break;
477 }
478 }
479 return token_count;
480}
481
482WBY_INTERN wby_size
483wby_make_websocket_header(wby_byte buffer[10], wby_byte opcode,
484 int payload_len, int fin)
485{
486 buffer[0] = (wby_byte)((fin ? 0x80 : 0x00) | opcode);
487 if (payload_len < 126) {
488 buffer[1] = (wby_byte)(payload_len & 0x7f);
489 return 2;
490 } else if (payload_len < 65536) {
491 buffer[1] = 126;
492 buffer[2] = (wby_byte)(payload_len >> 8);
493 buffer[3] = (wby_byte)payload_len;
494 return 4;
495 } else {
496 buffer[1] = 127;
497 /* Ignore high 32-bits. I didn't want to require 64-bit types and typdef hell in the API. */
498 buffer[2] = buffer[3] = buffer[4] = buffer[5] = 0;
499 buffer[6] = (wby_byte)(payload_len >> 24);
500 buffer[7] = (wby_byte)(payload_len >> 16);
501 buffer[8] = (wby_byte)(payload_len >> 8);
502 buffer[9] = (wby_byte)payload_len;
503 return 10;
504 }
505}
506
507WBY_INTERN int
508wby_read_buffered_data(int *data_left, struct wby_buffer* buffer,
509 char **dest_ptr, wby_size *dest_len)
510{
511 int offset, read_size;
512 int left = *data_left;
513 int len;
514 if (left == 0)
515 return 0;
516
517 len = (int) *dest_len;
518 offset = (int)buffer->used - left;
519 read_size = (len > left) ? left : len;
520 memcpy(*dest_ptr, buffer->data + offset, (wby_size)read_size);
521
522 (*dest_ptr) += read_size;
523 (*dest_len) -= (wby_size) read_size;
524 (*data_left) -= read_size;
525 return read_size;
526}
527
528/* ---------------------------------------------------------------
529 * SOCKET
530 * ---------------------------------------------------------------*/
531#ifdef _WIN32
532#include <winsock2.h>
533#pragma comment(lib, "Ws2_32.lib")
534typedef SOCKET wby_socket;
535typedef int wby_socklen;
536typedef char wby_sockopt;
537
538#if defined(__GNUC__)
539#define WBY_ALIGN(x) __attribute__((aligned(x)))
540#else
541#define WBY_ALIGN(x) __declspec(align(x))
542#endif
543
544#define WBY_INVALID_SOCKET INVALID_SOCKET
545#define snprintf _snprintf
546
547WBY_INTERN int
548wby_socket_error(void)
549{
550 return WSAGetLastError();
551}
552
553#if !defined(__GNUC__)
554WBY_INTERN int
555strcasecmp(const char *a, const char *b)
556{
557 return _stricmp(a, b);
558}
559
560WBY_INTERN int
561strncasecmp(const char *a, const char *b, wby_size len)
562{
563 return _strnicmp(a, b, len);
564}
565#endif
566
567WBY_INTERN int
568wby_socket_set_blocking(wby_socket socket, int blocking)
569{
570 u_long val = !blocking;
571 return ioctlsocket(socket, FIONBIO, &val);
572}
573
574WBY_INTERN int
575wby_socket_is_valid(wby_socket socket)
576{
577 return (INVALID_SOCKET != socket);
578}
579
580WBY_INTERN void
581wby_socket_close(wby_socket socket)
582{
583 closesocket(socket);
584}
585
586WBY_INTERN int
587wby_socket_is_blocking_error(int error)
588{
589 return WSAEWOULDBLOCK == error;
590}
591
592#else /* UNIX */
593
594#include <sys/socket.h>
595#include <sys/types.h>
596#include <sys/time.h>
597#include <sys/select.h>
598#include <netinet/in.h>
599#include <arpa/inet.h>
600#include <fcntl.h>
601#include <unistd.h>
602#include <errno.h>
603#include <strings.h>
604
605typedef int wby_socket;
606typedef socklen_t wby_socklen;
607typedef int wby_sockopt;
608
609#define WBY_ALIGN(x) __attribute__((aligned(x)))
610#define WBY_INVALID_SOCKET (-1)
611
612WBY_INTERN int
613wby_socket_error(void)
614{
615 return errno;
616}
617
618WBY_INTERN int
619wby_socket_is_valid(wby_socket socket)
620{
621 return (socket > 0);
622}
623
624WBY_INTERN void
625wby_socket_close(wby_socket socket)
626{
627 close(socket);
628}
629
630WBY_INTERN int
631wby_socket_is_blocking_error(int error)
632{
633 return (EAGAIN == error);
634}
635
636WBY_INTERN int
637wby_socket_set_blocking(wby_socket socket, int blocking)
638{
639 int flags = fcntl(socket, F_GETFL, 0);
640 if (flags < 0) return flags;
641 flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
642 return fcntl(socket, F_SETFL, flags);
643}
644#endif
645
646WBY_INTERN int
647wby_socket_config_incoming(wby_socket socket)
648{
649 wby_sockopt off = 0;
650 int err;
651 if ((err = wby_socket_set_blocking(socket, 0)) != WBY_OK) return err;
652 setsockopt(socket, SOL_SOCKET, SO_LINGER, (const char*) &off, sizeof(int));
653 return 0;
654}
655
656WBY_INTERN int
657wby_socket_send(wby_socket socket, const wby_byte *buffer, int size)
658{
659 while (size > 0) {
660 long err = send(socket, (const char*)buffer, (wby_size)size, 0);
661 if (err <= 0) return 1;
662 buffer += err;
663 size -= (int)err;
664 }
665 return 0;
666}
667
668/* Read as much as possible without blocking while there is buffer space. */
669enum {WBY_FILL_OK, WBY_FILL_ERROR, WBY_FILL_FULL};
670WBY_INTERN int
671wby_socket_recv(wby_socket socket, struct wby_buffer *buf, wby_log_f log)
672{
673 long err;
674 int buf_left;
675 for (;;) {
676 buf_left = (int)buf->max - (int)buf->used;
677 wby_dbg(log, "buffer space left = %d", buf_left);
678 if (buf_left == 0)
679 return WBY_FILL_FULL;
680
681 /* Read what we can into the current buffer space. */
682 err = recv(socket, (char*)buf->data + buf->used, (wby_size)buf_left, 0);
683 if (err < 0) {
684 int sock_err = wby_socket_error();
685 if (wby_socket_is_blocking_error(sock_err)) {
686 return WBY_FILL_OK;
687 } else {
688 /* Read error. Give up. */
689 wby_dbg(log, "read error %d - connection dead", sock_err);
690 return WBY_FILL_ERROR;
691 }
692 } else if (err == 0) {
693 /* The peer has closed the connection. */
694 wby_dbg(log, "peer has closed the connection");
695 return WBY_FILL_ERROR;
696 } else buf->used += (wby_size)err;
697 }
698}
699
700WBY_INTERN int
701wby_socket_flush(wby_socket socket, struct wby_buffer *buf)
702{
703 if (buf->used > 0){
704 if (wby_socket_send(socket, buf->data, (int)buf->used) != WBY_OK)
705 return 1;
706 }
707 buf->used = 0;
708 return 0;
709}
710
711/* ---------------------------------------------------------------
712 * URL
713 * ---------------------------------------------------------------*/
714/* URL-decode input buffer into destination buffer.
715 * 0-terminate the destination buffer. Return the length of decoded data.
716 * form-url-encoded data differs from URI encoding in a way that it
717 * uses '+' as character for space, see RFC 1866 section 8.2.1
718 * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
719 *
720 * This bit of code was taken from mongoose.
721 */
722WBY_INTERN wby_size
723wby_url_decode(const char *src, wby_size src_len, char *dst, wby_size dst_len,
724 int is_form_url_encoded)
725{
726 int a, b;
727 wby_size i, j;
728 #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
729 for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
730 if (src[i] == '%' &&
731 isxdigit(*(const wby_byte*)(src + i + 1)) &&
732 isxdigit(*(const wby_byte*)(src + i + 2)))
733 {
734 a = tolower(*(const wby_byte*)(src + i + 1));
735 b = tolower(*(const wby_byte*)(src + i + 2));
736 dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
737 i += 2;
738 } else if (is_form_url_encoded && src[i] == '+') {
739 dst[j] = ' ';
740 } else dst[j] = src[i];
741 }
742 #undef HEXTOI
743 dst[j] = '\0'; /* Null-terminate the destination */
744 return j;
745}
746
747/* Pulled from mongoose */
748WBY_API int
749wby_find_query_var(const char *buf, const char *name, char *dst, wby_size dst_len)
750{
751 const char *p, *e, *s;
752 wby_size name_len;
753 int len;
754 wby_size buf_len = strlen(buf);
755
756 name_len = strlen(name);
757 e = buf + buf_len;
758 len = -1;
759 dst[0] = '\0';
760
761 /* buf is "var1=val1&var2=val2...". Find variable first */
762 for (p = buf; p != NULL && p + name_len < e; p++) {
763 if ((p == buf || p[-1] == '&') && p[name_len] == '=' &&
764 strncasecmp(name, p, name_len) == 0)
765 {
766 /* Point p to variable value */
767 p += name_len + 1;
768 /* Point s to the end of the value */
769 s = (const char *) memchr(p, '&', (wby_size)(e - p));
770 if (s == NULL) s = e;
771 WBY_ASSERT(s >= p);
772 /* Decode variable into destination buffer */
773 if ((wby_size) (s - p) < dst_len)
774 len = (int)wby_url_decode(p, (wby_size)(s - p), dst, dst_len, 1);
775 break;
776 }
777 }
778 return len;
779}
780
781/* ---------------------------------------------------------------
782 * BASE64
783 * ---------------------------------------------------------------*/
784#define WBY_BASE64_QUADS_BEFORE_LINEBREAK 19
785
786WBY_INTERN wby_size
787wby_base64_bufsize(wby_size input_size)
788{
789 wby_size triplets = (input_size + 2) / 3;
790 wby_size base_size = 4 * triplets;
791 wby_size line_breaks = 2 * (triplets / WBY_BASE64_QUADS_BEFORE_LINEBREAK);
792 wby_size null_termination = 1;
793 return base_size + line_breaks + null_termination;
794}
795
796WBY_INTERN int
797wby_base64_encode(char* output, wby_size output_size,
798 const wby_byte *input, wby_size input_size)
799{
800 wby_size i = 0;
801 int line_out = 0;
802 WBY_STORAGE const char enc[] =
803 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
804 "abcdefghijklmnopqrstuvwxyz"
805 "0123456789+/=";
806 if (output_size < wby_base64_bufsize(input_size))
807 return 1;
808
809 while (i < input_size) {
810 unsigned int idx_0, idx_1, idx_2, idx_3;
811 unsigned int i0;
812
813 i0 = (unsigned int)(input[i]) << 16; i++;
814 i0 |= (unsigned int)(i < input_size ? input[i] : 0) << 8; i++;
815 i0 |= (i < input_size ? input[i] : 0); i++;
816
817 idx_0 = (i0 & 0xfc0000) >> 18; i0 <<= 6;
818 idx_1 = (i0 & 0xfc0000) >> 18; i0 <<= 6;
819 idx_2 = (i0 & 0xfc0000) >> 18; i0 <<= 6;
820 idx_3 = (i0 & 0xfc0000) >> 18;
821
822 if (i - 1 > input_size) idx_2 = 64;
823 if (i > input_size) idx_3 = 64;
824
825 *output++ = enc[idx_0];
826 *output++ = enc[idx_1];
827 *output++ = enc[idx_2];
828 *output++ = enc[idx_3];
829
830 if (++line_out == WBY_BASE64_QUADS_BEFORE_LINEBREAK) {
831 *output++ = '\r';
832 *output++ = '\n';
833 }
834 }
835 *output = '\0';
836 return 0;
837}
838
839/* ---------------------------------------------------------------
840 * SHA1
841 * ---------------------------------------------------------------*/
842struct wby_sha1 {
843 unsigned int state[5];
844 unsigned int msg_size[2];
845 wby_size buf_used;
846 wby_byte buffer[64];
847};
848
849WBY_INTERN unsigned int
850wby_sha1_rol(unsigned int value, unsigned int bits)
851{
852 return ((value) << bits) | (value >> (32 - bits));
853}
854
855WBY_INTERN void
856wby_sha1_hash_block(unsigned int state[5], const wby_byte *block)
857{
858 int i;
859 unsigned int a, b, c, d, e;
860 unsigned int w[80];
861
862 /* Prepare message schedule */
863 for (i = 0; i < 16; ++i) {
864 w[i] = (((unsigned int)block[(i*4)+0]) << 24) |
865 (((unsigned int)block[(i*4)+1]) << 16) |
866 (((unsigned int)block[(i*4)+2]) << 8) |
867 (((unsigned int)block[(i*4)+3]) << 0);
868 }
869
870 for (i = 16; i < 80; ++i)
871 w[i] = wby_sha1_rol(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
872 /* Initialize working variables */
873 a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4];
874
875 /* This is the core loop for each 20-word span. */
876 #define SHA1_LOOP(start, end, func, constant) \
877 for (i = (start); i < (end); ++i) { \
878 unsigned int t = wby_sha1_rol(a, 5) + (func) + e + (constant) + w[i]; \
879 e = d; d = c; c = wby_sha1_rol(b, 30); b = a; a = t;}
880
881 SHA1_LOOP( 0, 20, ((b & c) ^ (~b & d)), 0x5a827999)
882 SHA1_LOOP(20, 40, (b ^ c ^ d), 0x6ed9eba1)
883 SHA1_LOOP(40, 60, ((b & c) ^ (b & d) ^ (c & d)), 0x8f1bbcdc)
884 SHA1_LOOP(60, 80, (b ^ c ^ d), 0xca62c1d6)
885 #undef SHA1_LOOP
886
887 /* Update state */
888 state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e;
889}
890
891WBY_INTERN void
892wby_sha1_init(struct wby_sha1 *s)
893{
894 s->state[0] = 0x67452301;
895 s->state[1] = 0xefcdab89;
896 s->state[2] = 0x98badcfe;
897 s->state[3] = 0x10325476;
898 s->state[4] = 0xc3d2e1f0;
899
900 s->msg_size[0] = 0;
901 s->msg_size[1] = 0;
902 s->buf_used = 0;
903}
904
905WBY_INTERN void
906wby_sha1_update(struct wby_sha1 *s, const void *data_, wby_size size)
907{
908 const char *data = (const char*)data_;
909 unsigned int size_lo;
910 unsigned int size_lo_orig;
911 wby_size remain = size;
912
913 while (remain > 0) {
914 wby_size buf_space = sizeof(s->buffer) - s->buf_used;
915 wby_size copy_size = (remain < buf_space) ? remain : buf_space;
916 memcpy(s->buffer + s->buf_used, data, copy_size);
917
918 s->buf_used += copy_size;
919 data += copy_size;
920 remain -= copy_size;
921
922 if (s->buf_used == sizeof(s->buffer)) {
923 wby_sha1_hash_block(s->state, s->buffer);
924 s->buf_used = 0;
925 }
926 }
927
928 size_lo = size_lo_orig = s->msg_size[1];
929 size_lo += (unsigned int)(size * 8);
930 if (size_lo < size_lo_orig)
931 s->msg_size[0] += 1;
932 s->msg_size[1] = size_lo;
933}
934
935WBY_INTERN void
936wby_sha1_final(wby_byte digest[20], struct wby_sha1 *s)
937{
938 wby_byte zero = 0x00;
939 wby_byte one_bit = 0x80;
940 wby_byte count_data[8];
941 int i;
942
943 /* Generate size data in bit endian format */
944 for (i = 0; i < 8; ++i) {
945 unsigned int word = s->msg_size[i >> 2];
946 count_data[i] = (wby_byte)(word >> ((3 - (i & 3)) * 8));
947 }
948
949 /* Set trailing one-bit */
950 wby_sha1_update(s, &one_bit, 1);
951 /* Emit null padding to to make room for 64 bits of size info in the last 512 bit block */
952 while (s->buf_used != 56)
953 wby_sha1_update(s, &zero, 1);
954
955 /* Write size in bits as last 64-bits */
956 wby_sha1_update(s, count_data, 8);
957 /* Make sure we actually finalized our last block */
958 WBY_ASSERT(s->buf_used == 0);
959
960 /* Generate digest */
961 for (i = 0; i < 20; ++i) {
962 unsigned int word = s->state[i >> 2];
963 wby_byte byte = (wby_byte) ((word >> ((3 - (i & 3)) * 8)) & 0xff);
964 digest[i] = byte;
965 }
966}
967
968/* ---------------------------------------------------------------
969 * CONNECTION
970 * ---------------------------------------------------------------*/
971#define WBY_WEBSOCKET_VERSION "13"
972WBY_GLOBAL const char wby_continue_header[] = "HTTP/1.1 100 Continue\r\n\r\n";
973WBY_GLOBAL const wby_size wby_continue_header_len = sizeof(wby_continue_header) - 1;
974WBY_GLOBAL const char wby_websocket_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
975WBY_GLOBAL const wby_size wby_websocket_guid_len = sizeof(wby_websocket_guid) - 1;
976WBY_GLOBAL const wby_byte wby_websocket_pong[] = { 0x80, WBY_WSOP_PONG, 0x00 };
977WBY_GLOBAL const struct wby_header wby_plain_text_headers[]={{"Content-Type","text/plain"}};
978
979enum wby_connection_flags {
980 WBY_CON_FLAG_ALIVE = WBY_FLAG(0),
981 WBY_CON_FLAG_FRESH_CONNECTION = WBY_FLAG(1),
982 WBY_CON_FLAG_CLOSE_AFTER_RESPONSE = WBY_FLAG(2),
983 WBY_CON_FLAG_CHUNKED_RESPONSE = WBY_FLAG(3),
984 WBY_CON_FLAG_WEBSOCKET = WBY_FLAG(4)
985};
986
987enum wby_connection_state {
988 WBY_CON_STATE_REQUEST,
989 WBY_CON_STATE_SEND_CONTINUE,
990 WBY_CON_STATE_SERVE,
991 WBY_CON_STATE_WEBSOCKET
992};
993
994struct wby_connection {
995 struct wby_con public_data;
996 unsigned short flags;
997 unsigned short state;
998
999 wby_ptr socket;
1000 wby_log_f log;
1001
1002 wby_size request_buffer_size;
1003 struct wby_buffer header_buf;
1004 struct wby_buffer io_buf;
1005 wby_size io_buffer_size;
1006
1007 int header_body_left;
1008 int io_data_left;
1009 int continue_data_left;
1010 int body_bytes_read;
1011
1012 struct wby_frame ws_frame;
1013 wby_byte ws_opcode;
1014 wby_size blocking_count;
1015};
1016
1017WBY_INTERN int
1018wby_connection_set_blocking(struct wby_connection *conn)
1019{
1020 if (conn->blocking_count == 0) {
1021 if (wby_socket_set_blocking(WBY_SOCK(conn->socket), 1) != WBY_OK) {
1022 wby_dbg(conn->log, "failed to switch connection to blocking");
1023 conn->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1024 return -1;
1025 }
1026 }
1027 ++conn->blocking_count;
1028 return 0;
1029}
1030
1031WBY_INTERN int
1032wby_connection_set_nonblocking(struct wby_connection *conn)
1033{
1034 wby_size count = conn->blocking_count;
1035 if ((conn->flags & WBY_CON_FLAG_ALIVE) != 0 && count == 1) {
1036 if (wby_socket_set_blocking(WBY_SOCK(conn->socket), 0) != WBY_OK) {
1037 wby_dbg(conn->log, "failed to switch connection to non-blocking");
1038 conn->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1039 return -1;
1040 }
1041 }
1042 conn->blocking_count = count - 1;
1043 return 0;
1044}
1045
1046WBY_INTERN void
1047wby_connection_reset(struct wby_connection *conn, wby_size request_buffer_size,
1048 wby_size io_buffer_size)
1049{
1050 conn->header_buf.used = 0;
1051 conn->header_buf.max = request_buffer_size;
1052 conn->io_buf.used = 0;
1053 conn->io_buf.max = io_buffer_size;
1054 conn->header_body_left = 0;
1055 conn->io_data_left = 0;
1056 conn->continue_data_left = 0;
1057 conn->body_bytes_read = 0;
1058 conn->state = WBY_CON_STATE_REQUEST;
1059 conn->public_data.user_data = NULL;
1060 conn->blocking_count = 0;
1061}
1062
1063WBY_INTERN void
1064wby_connection_close(struct wby_connection* connection)
1065{
1066 if (WBY_SOCK(connection->socket) != WBY_INVALID_SOCKET) {
1067 wby_socket_close(WBY_SOCK(connection->socket));
1068 connection->socket = (wby_ptr)WBY_INVALID_SOCKET;
1069 }
1070 connection->flags = 0;
1071}
1072
1073WBY_INTERN int
1074wby_connection_setup_request(struct wby_connection *connection, int request_size)
1075{
1076 char* lines[WBY_MAX_HEADERS + 2];
1077 int line_count;
1078 char* tok[16];
1079 char* query_params;
1080 int tok_count;
1081
1082 int i;
1083 int header_count;
1084 char *buf = (char*) connection->header_buf.data;
1085 struct wby_request *req = &connection->public_data.request;
1086
1087 /* Null-terminate the request envelope by overwriting the last CRLF with 00LF */
1088 buf[request_size - 2] = '\0';
1089 /* Split header into lines */
1090 line_count = wby_tok_inplace(buf, "\r\n", lines, WBY_LEN(lines), 0);
1091 header_count = line_count - 2;
1092 if (line_count < 1 || header_count > (int) WBY_LEN(req->headers))
1093 return 1;
1094
1095 /* Parse request line */
1096 tok_count = wby_tok_inplace(lines[0], " ", tok, WBY_LEN(tok), 0);
1097 if (3 != tok_count) return 1;
1098
1099 req->method = tok[0];
1100 req->uri = tok[1];
1101 req->http_version = tok[2];
1102 req->content_length = 0;
1103
1104 /* See if there are any query parameters */
1105 if ((query_params = (char*) strchr(req->uri, '?')) != NULL) {
1106 req->query_params = query_params + 1;
1107 *query_params = '\0';
1108 } else req->query_params = NULL;
1109
1110 {
1111 /* Decode the URI in place */
1112 wby_size uri_len = strlen(req->uri);
1113 wby_url_decode(req->uri, uri_len, (char*)req->uri, uri_len + 1, 1);
1114 }
1115
1116 /* Parse headers */
1117 for (i = 0; i < header_count; ++i) {
1118 tok_count = wby_tok_inplace(lines[i + 1], ":", tok, 2, WBY_TOK_SKIPWS);
1119 if (tok_count != 2) return 1;
1120 req->headers[i].name = tok[0];
1121 req->headers[i].value = tok[1];
1122
1123 if (!strcasecmp("content-length", tok[0])) {
1124 req->content_length = (int)strtoul(tok[1], NULL, 10);
1125 wby_dbg(connection->log, "request has body; content length is %d", req->content_length);
1126 } else if (!strcasecmp("transfer-encoding", tok[0])) {
1127 wby_dbg(connection->log, "cowardly refusing to handle Transfer-Encoding: %s", tok[1]);
1128 return 1;
1129 }
1130 }
1131 req->header_count = header_count;
1132 return 0;
1133}
1134
1135WBY_INTERN int
1136wby_connection_send_websocket_upgrade(struct wby_connection* connection)
1137{
1138 const char *hdr;
1139 struct wby_sha1 sha;
1140 wby_byte digest[20];
1141 char output_digest[64];
1142 struct wby_header headers[3];
1143 struct wby_con *conn = &connection->public_data;
1144 if ((hdr = wby_find_header(conn, "Sec-WebSocket-Version")) == NULL) {
1145 wby_dbg(connection->log, "Sec-WebSocket-Version header not present");
1146 return 1;
1147 }
1148 if (strcmp(hdr, WBY_WEBSOCKET_VERSION)) {
1149 wby_dbg(connection->log,"WebSocket version %s not supported (we only do %s)",
1150 hdr, WBY_WEBSOCKET_VERSION);
1151 return 1;
1152 }
1153 if ((hdr = wby_find_header(conn, "Sec-WebSocket-Key")) == NULL) {
1154 wby_dbg(connection->log, "Sec-WebSocket-Key header not present");
1155 return 1;
1156 }
1157 /* Compute SHA1 hash of Sec-Websocket-Key + the websocket guid as required by
1158 * the RFC.
1159 *
1160 * This handshake is bullshit. It adds zero security. Just forces me to drag
1161 * in SHA1 and create a base64 encoder.
1162 */
1163 wby_sha1_init(&sha);
1164 wby_sha1_update(&sha, hdr, strlen(hdr));
1165 wby_sha1_update(&sha, wby_websocket_guid, wby_websocket_guid_len);
1166 wby_sha1_final(&digest[0], &sha);
1167 if (wby_base64_encode(output_digest, sizeof output_digest, &digest[0], sizeof(digest)) != WBY_OK)
1168 return 1;
1169
1170 headers[0].name = "Upgrade";
1171 headers[0].value = "websocket";
1172 headers[1].name = "Connection";
1173 headers[1].value = "Upgrade";
1174 headers[2].name = "Sec-WebSocket-Accept";
1175 headers[2].value = output_digest;
1176 wby_response_begin(&connection->public_data, 101, 0, headers, WBY_LEN(headers));
1177 wby_response_end(&connection->public_data);
1178 return 0;
1179}
1180
1181WBY_INTERN int
1182wby_connection_push(struct wby_connection *conn, const void *data_, int len)
1183{
1184 struct wby_buffer *buf = &conn->io_buf;
1185 const wby_byte* data = (const wby_byte*)data_;
1186 if (conn->state != WBY_CON_STATE_SERVE) {
1187 wby_dbg(conn->log, "attempt to write in non-serve state");
1188 return 1;
1189 }
1190 if (len == 0)
1191 return wby_socket_flush(WBY_SOCK(conn->socket), buf);
1192
1193 while (len > 0) {
1194 int buf_space = (int)buf->max - (int)buf->used;
1195 int copy_size = len < buf_space ? len : buf_space;
1196 memcpy(buf->data + buf->used, data, (wby_size)copy_size);
1197 buf->used += (wby_size)copy_size;
1198
1199 data += copy_size;
1200 len -= copy_size;
1201 if (buf->used == buf->max) {
1202 if (wby_socket_flush(WBY_SOCK(conn->socket), buf) != WBY_OK)
1203 return 1;
1204 if ((wby_size)len >= buf->max)
1205 return wby_socket_send(WBY_SOCK(conn->socket), data, len);
1206 }
1207 }
1208 return 0;
1209}
1210
1211/* ---------------------------------------------------------------
1212 * CON/REQUEST
1213 * ---------------------------------------------------------------*/
1214WBY_INTERN int
1215wby_con_discard_incoming_data(struct wby_con* conn, int count)
1216{
1217 while (count > 0) {
1218 char buffer[1024];
1219 int read_size = (int)(((wby_size)count > sizeof(buffer)) ?
1220 sizeof(buffer) : (wby_size)count);
1221 if (wby_read(conn, buffer, (wby_size)read_size) != WBY_OK)
1222 return -1;
1223 count -= read_size;
1224 }
1225 return 0;
1226}
1227
1228WBY_API const char*
1229wby_find_header(struct wby_con *conn, const char *name)
1230{
1231 int i, count;
1232 for (i = 0, count = conn->request.header_count; i < count; ++i) {
1233 if (!strcasecmp(conn->request.headers[i].name, name))
1234 return conn->request.headers[i].value;
1235 }
1236 return NULL;
1237}
1238
1239WBY_INTERN int
1240wby_con_is_websocket_request(struct wby_con* conn)
1241{
1242 const char *hdr;
1243 if ((hdr = wby_find_header(conn, "Connection")) == NULL) return 0;
1244 if (strcasecmp(hdr, "Upgrade")) return 0;
1245 if ((hdr = wby_find_header(conn, "Upgrade")) == NULL) return 0;
1246 if (strcasecmp(hdr, "websocket")) return 0;
1247 return 1;
1248}
1249
1250WBY_INTERN int
1251wby_scan_websocket_frame(struct wby_frame *frame, const struct wby_buffer *buf)
1252{
1253 wby_byte flags = 0;
1254 unsigned int len = 0;
1255 unsigned int opcode = 0;
1256 wby_byte* data = buf->data;
1257 wby_byte* data_max = data + buf->used;
1258
1259 int i;
1260 int len_bytes = 0;
1261 int mask_bytes = 0;
1262 wby_byte header0, header1;
1263 if (buf->used < 2)
1264 return -1;
1265
1266 header0 = *data++;
1267 header1 = *data++;
1268 if (header0 & 0x80)
1269 flags |= WBY_WSF_FIN;
1270 if (header1 & 0x80) {
1271 flags |= WBY_WSF_MASKED;
1272 mask_bytes = 4;
1273 }
1274
1275 opcode = header0 & 0xf;
1276 len = header1 & 0x7f;
1277 if (len == 126)
1278 len_bytes = 2;
1279 else if (len == 127)
1280 len_bytes = 8;
1281 if (data + len_bytes + mask_bytes > data_max)
1282 return -1;
1283
1284 /* Read big endian length from length bytes (if greater than 125) */
1285 len = len_bytes == 0 ? len : 0;
1286 for (i = 0; i < len_bytes; ++i) {
1287 /* This will totally overflow for 64-bit values. I don't care.
1288 * If you're transmitting more than 4 GB of data using Webby,
1289 * seek help. */
1290 len <<= 8;
1291 len |= *data++;
1292 }
1293
1294 /* Read mask word if present */
1295 for (i = 0; i < mask_bytes; ++i)
1296 frame->mask_key[i] = *data++;
1297 frame->header_size = (wby_byte) (data - buf->data);
1298 frame->flags = flags;
1299 frame->opcode = (wby_byte) opcode;
1300 frame->payload_length = (int)len;
1301 return 0;
1302}
1303
1304WBY_API int
1305wby_frame_begin(struct wby_con *conn_pub, int opcode)
1306{
1307 struct wby_connection *conn = (struct wby_connection*)conn_pub;
1308 conn->ws_opcode = (wby_byte) opcode;
1309 /* Switch socket to blocking mode */
1310 return wby_connection_set_blocking(conn);
1311}
1312
1313WBY_API int
1314wby_frame_end(struct wby_con *conn_pub)
1315{
1316 wby_byte header[10];
1317 wby_size header_size;
1318 struct wby_connection *conn = (struct wby_connection*) conn_pub;
1319 header_size = wby_make_websocket_header(header, conn->ws_opcode, 0, 1);
1320 if (wby_socket_send(WBY_SOCK(conn->socket), header, (int) header_size) != WBY_OK)
1321 conn->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1322 /* Switch socket to non-blocking mode */
1323 return wby_connection_set_nonblocking(conn);
1324}
1325
1326WBY_API int
1327wby_read(struct wby_con *conn, void *ptr_, wby_size len)
1328{
1329 struct wby_connection* conn_prv = (struct wby_connection*)conn;
1330 char *ptr = (char*) ptr_;
1331 int count;
1332
1333 int start_pos = conn_prv->body_bytes_read;
1334 if (conn_prv->header_body_left > 0) {
1335 count = wby_read_buffered_data(&conn_prv->header_body_left, &conn_prv->header_buf, &ptr, &len);
1336 conn_prv->body_bytes_read += count;
1337 }
1338
1339 /* Read buffered websocket data */
1340 if (conn_prv->io_data_left > 0) {
1341 count = wby_read_buffered_data(&conn_prv->io_data_left, &conn_prv->io_buf, &ptr, &len);
1342 conn_prv->body_bytes_read += count;
1343 }
1344
1345 while (len > 0) {
1346 long err = recv(WBY_SOCK(conn_prv->socket), ptr, (wby_size)len, 0);
1347 if (err < 0) {
1348 conn_prv->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1349 return (int)err;
1350 }
1351 len -= (wby_size)err;
1352 ptr += (wby_size)err;
1353 conn_prv->body_bytes_read += (int)err;
1354 }
1355
1356 if ((conn_prv->flags & WBY_CON_FLAG_WEBSOCKET) && (conn_prv->ws_frame.flags & WBY_WSF_MASKED)) {
1357 /* XOR outgoing data with websocket ofuscation key */
1358 int i, end_pos = conn_prv->body_bytes_read;
1359 const wby_byte *mask = conn_prv->ws_frame.mask_key;
1360 ptr = (char*) ptr_; /* start over */
1361 for (i = start_pos; i < end_pos; ++i) {
1362 wby_byte byte = (wby_byte)*ptr;
1363 *ptr++ = (char)(byte ^ mask[i & 3]);
1364 }
1365 }
1366 return 0;
1367}
1368
1369WBY_API int
1370wby_write(struct wby_con *conn, const void *ptr, wby_size len)
1371{
1372 struct wby_connection *conn_priv = (struct wby_connection*) conn;
1373 if (conn_priv->flags & WBY_CON_FLAG_WEBSOCKET) {
1374 wby_byte header[10];
1375 wby_size header_size;
1376 header_size = wby_make_websocket_header(header, conn_priv->ws_opcode, (int)len, 0);
1377
1378 /* Overwrite opcode to be continuation packages from here on out */
1379 conn_priv->ws_opcode = WBY_WSOP_CONTINUATION;
1380 if (wby_socket_send(WBY_SOCK(conn_priv->socket), header, (int)header_size) != WBY_OK) {
1381 conn_priv->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1382 return -1;
1383 }
1384 if (wby_socket_send(WBY_SOCK(conn_priv->socket),(const wby_byte*)ptr, (int)len) != WBY_OK) {
1385 conn_priv->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1386 return -1;
1387 }
1388 return 0;
1389 } else if (conn_priv->flags & WBY_CON_FLAG_CHUNKED_RESPONSE) {
1390 char chunk_header[128];
1391 int header_len = snprintf(chunk_header, sizeof chunk_header, "%x\r\n", (int) len);
1392 wby_connection_push(conn_priv, chunk_header, header_len);
1393 wby_connection_push(conn_priv, ptr, (int)len);
1394 return wby_connection_push(conn_priv, "\r\n", 2);
1395 } else return wby_connection_push(conn_priv, ptr, (int) len);
1396}
1397
1398WBY_INTERN int
1399wby_printf(struct wby_con* conn, const char* fmt, ...)
1400{
1401 int len;
1402 char buffer[1024];
1403 va_list args;
1404 va_start(args, fmt);
1405 len = vsnprintf(buffer, sizeof buffer, fmt, args);
1406 va_end(args);
1407 return wby_write(conn, buffer, (wby_size)len);
1408}
1409
1410/* ---------------------------------------------------------------
1411 * RESPONSE
1412 * ---------------------------------------------------------------*/
1413#define WBY_STATUS_MAP(STATUS)\
1414 STATUS(100, "Continue")\
1415 STATUS(101, "Switching Protocols")\
1416 STATUS(200, "OK")\
1417 STATUS(201, "Created")\
1418 STATUS(202, "Accepted")\
1419 STATUS(203, "Non-Authoritative Information")\
1420 STATUS(204, "No Content")\
1421 STATUS(205, "Reset Content")\
1422 STATUS(206, "Partial Content")\
1423 STATUS(300, "Multiple Choices")\
1424 STATUS(301, "Moved Permanently")\
1425 STATUS(302, "Found")\
1426 STATUS(303, "See Other")\
1427 STATUS(304, "Not Modified")\
1428 STATUS(305, "Use Proxy")\
1429 STATUS(307, "Temporary Redirect")\
1430 STATUS(400, "Bad Request")\
1431 STATUS(401, "Unauthorized")\
1432 STATUS(402, "Payment Required")\
1433 STATUS(403, "Forbidden")\
1434 STATUS(404, "Not Found")\
1435 STATUS(405, "Method Not Allowed")\
1436 STATUS(406, "Not Acceptable")\
1437 STATUS(407, "Proxy Authentication Required")\
1438 STATUS(408, "Request Time-out")\
1439 STATUS(409, "Conflict")\
1440 STATUS(410, "Gone")\
1441 STATUS(411, "Length Required")\
1442 STATUS(412, "Precondition Failed")\
1443 STATUS(413, "Request Entity Too Large")\
1444 STATUS(414, "Request-URI Too Large")\
1445 STATUS(415, "Unsupported Media Type")\
1446 STATUS(416, "Requested range not satisfiable")\
1447 STATUS(417, "Expectation Failed")\
1448 STATUS(500, "Internal Server Error")\
1449 STATUS(501, "Not Implemented")\
1450 STATUS(502, "Bad Gateway")\
1451 STATUS(503, "Service Unavailable")\
1452 STATUS(504, "Gateway Time-out")\
1453 STATUS(505, "HTTP Version not supported")
1454
1455WBY_GLOBAL const short wby_status_nums[] = {
1456#define WBY_STATUS(id, name) id,
1457 WBY_STATUS_MAP(WBY_STATUS)
1458#undef WBY_STATUS
1459};
1460WBY_GLOBAL const char* wby_status_text[] = {
1461#define WBY_STATUS(id, name) name,
1462 WBY_STATUS_MAP(WBY_STATUS)
1463#undef WBY_STATUS
1464};
1465
1466WBY_INTERN const char*
1467wby_response_status_text(int status_code)
1468{
1469 int i;
1470 for (i = 0; i < (int) WBY_LEN(wby_status_nums); ++i) {
1471 if (wby_status_nums[i] == status_code)
1472 return wby_status_text[i];
1473 }
1474 return "Unknown";
1475}
1476
1477WBY_API int
1478wby_response_begin(struct wby_con *conn_pub, int status_code, int content_length,
1479 const struct wby_header *headers, int header_count)
1480{
1481 int i = 0;
1482 struct wby_connection *conn = (struct wby_connection *)conn_pub;
1483 if (conn->body_bytes_read < (int)conn->public_data.request.content_length) {
1484 int body_left = conn->public_data.request.content_length - (int)conn->body_bytes_read;
1485 if (wby_con_discard_incoming_data(conn_pub, body_left) != WBY_OK) {
1486 conn->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1487 return -1;
1488 }
1489 }
1490
1491 wby_printf(conn_pub, "HTTP/1.1 %d %s\r\n", status_code, wby_response_status_text(status_code));
1492 if (content_length >= 0)
1493 wby_printf(conn_pub, "Content-Length: %d\r\n", content_length);
1494 else wby_printf(conn_pub, "Transfer-Encoding: chunked\r\n");
1495 wby_printf(conn_pub, "Server: wby\r\n");
1496
1497 for (i = 0; i < header_count; ++i) {
1498 if (!strcasecmp(headers[i].name, "Connection")) {
1499 if (!strcasecmp(headers[i].value, "close"))
1500 conn->flags |= WBY_CON_FLAG_CLOSE_AFTER_RESPONSE;
1501 }
1502 wby_printf(conn_pub, "%s: %s\r\n", headers[i].name, headers[i].value);
1503 }
1504
1505 if (!(conn->flags & WBY_CON_FLAG_CLOSE_AFTER_RESPONSE)) {
1506 /* See if the client wants us to close the connection. */
1507 const char* connection_header = wby_find_header(conn_pub, "Connection");
1508 if (connection_header && !strcasecmp("close", connection_header)) {
1509 conn->flags |= WBY_CON_FLAG_CLOSE_AFTER_RESPONSE;
1510 wby_printf(conn_pub, "Connection: close\r\n");
1511 }
1512 }
1513 wby_printf(conn_pub, "\r\n");
1514 if (content_length < 0)
1515 conn->flags |= WBY_CON_FLAG_CHUNKED_RESPONSE;
1516 return 0;
1517}
1518
1519WBY_API void
1520wby_response_end(struct wby_con *conn)
1521{
1522 struct wby_connection *conn_priv = (struct wby_connection*) conn;
1523 if (conn_priv->flags & WBY_CON_FLAG_CHUNKED_RESPONSE) {
1524 /* Write final chunk */
1525 wby_connection_push(conn_priv, "0\r\n\r\n", 5);
1526 conn_priv->flags &= (unsigned short)~WBY_CON_FLAG_CHUNKED_RESPONSE;
1527 }
1528 /* Flush buffers */
1529 wby_connection_push(conn_priv, "", 0);
1530
1531 /* Close connection when Content-Length is zero that maybe HTTP/1.0. */
1532 if (conn->request.content_length == 0 && !wby_con_is_websocket_request(conn))
1533 wby_connection_close(conn_priv);
1534}
1535
1536/* ---------------------------------------------------------------
1537 * SERVER
1538 * ---------------------------------------------------------------*/
1539/* Pointer to Integer type conversion for pointer alignment */
1540#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
1541# define WBY_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
1542# define WBY_PTR_TO_UINT(x) ((wby_size)(__PTRDIFF_TYPE__)(x))
1543#elif !defined(__GNUC__) /* works for compilers other than LLVM */
1544# define WBY_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
1545# define WBY_PTR_TO_UINT(x) ((wby_size)(((char*)x)-(char*)0))
1546#elif defined(WBY_USE_FIXED_TYPES) /* used if we have <stdint.h> */
1547# define WBY_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
1548# define WBY_PTR_TO_UINT(x) ((uintptr_t)(x))
1549#else /* generates warning but works */
1550# define WBY_UINT_TO_PTR(x) ((void*)(x))
1551# define WBY_PTR_TO_UINT(x) ((wby_size)(x))
1552#endif
1553
1554/* simple pointer math */
1555#define WBY_PTR_ADD(t, p, i) ((t*)((void*)((wby_byte*)(p) + (i))))
1556#define WBY_ALIGN_PTR(x, mask)\
1557 (WBY_UINT_TO_PTR((WBY_PTR_TO_UINT((wby_byte*)(x) + (mask-1)) & ~(mask-1))))
1558
1559/* pointer alignment */
1560#ifdef __cplusplus
1561template<typename T> struct wby_alignof;
1562template<typename T, int size_diff> struct wby_helper{enum {value = size_diff};};
1563template<typename T> struct wby_helper<T,0>{enum {value = wby_alignof<T>::value};};
1564template<typename T> struct wby_alignof{struct Big {T x; char c;}; enum {
1565 diff = sizeof(Big) - sizeof(T), value = wby_helper<Big, diff>::value};};
1566#define WBY_ALIGNOF(t) (wby_alignof<t>::value);
1567#else
1568#define WBY_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
1569#endif
1570
1571WBY_API void
1572wby_init(struct wby_server *srv, const struct wby_config *cfg, wby_size *needed_memory)
1573{
1574 WBY_STORAGE const wby_size wby_conn_align = WBY_ALIGNOF(struct wby_connection);
1575 WBY_ASSERT(srv);
1576 WBY_ASSERT(cfg);
1577 WBY_ASSERT(needed_memory);
1578
1579 memset(srv, 0, sizeof(*srv));
1580 srv->config = *cfg;
1581 WBY_ASSERT(cfg->dispatch);
1582
1583 *needed_memory = 0;
1584 *needed_memory += cfg->connection_max * sizeof(struct wby_connection);
1585 *needed_memory += cfg->connection_max * cfg->request_buffer_size;
1586 *needed_memory += cfg->connection_max * cfg->io_buffer_size;
1587 *needed_memory += wby_conn_align;
1588 srv->memory_size = *needed_memory;
1589}
1590
1591WBY_API int
1592wby_start(struct wby_server *server, void *memory)
1593{
1594 wby_size i;
1595 wby_socket sock;
1596 wby_sockopt on = 1;
1597 wby_byte *buffer = (wby_byte*)memory;
1598 struct sockaddr_in bind_addr;
1599 WBY_STORAGE const wby_size wby_conn_align = WBY_ALIGNOF(struct wby_connection);
1600
1601 WBY_ASSERT(server);
1602 WBY_ASSERT(memory);
1603 memset(buffer, 0, server->memory_size);
1604
1605 /* setup sever memory */
1606 server->socket = (wby_ptr)WBY_INVALID_SOCKET;
1607 server->con = (struct wby_connection*)WBY_ALIGN_PTR(buffer, wby_conn_align);
1608 buffer += ((wby_byte*)server->con - buffer);
1609 buffer += server->config.connection_max * sizeof(struct wby_connection);
1610
1611 for (i = 0; i < server->config.connection_max; ++i) {
1612 server->con[i].log = server->config.log;
1613 server->con[i].header_buf.data = buffer;
1614 buffer += server->config.request_buffer_size;
1615 server->con[i].io_buf.data = buffer;
1616 server->con[i].request_buffer_size = server->config.request_buffer_size;
1617 server->con[i].io_buffer_size = server->config.io_buffer_size;
1618 buffer += server->config.io_buffer_size;
1619 }
1620 WBY_ASSERT((wby_size)(buffer - (wby_byte*)memory) <= server->memory_size);
1621
1622 /* server socket setup */
1623 sock = (wby_ptr)socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1624#ifdef _WIN32
1625 if (sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) {
1626 /* Make sure WSAStartup has been called. */
1627 wby_dbg(server->config.log, "Calling WSAStartup.");
1628 WSADATA wsaData;
1629 WSAStartup(MAKEWORD(2, 2), &wsaData);
1630 sock = (wby_ptr)socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1631 server->windows_socket_initialized = 1;
1632 }
1633#endif
1634 wby_dbg(server->config.log, "Server socket = %d", (int)sock);
1635 if (!wby_socket_is_valid(sock)) {
1636 wby_dbg(server->config.log, "failed to initialized server socket: %d", wby_socket_error());
1637 goto error;
1638 }
1639
1640 setsockopt(WBY_SOCK(sock), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1641 #ifdef __APPLE__ /* Don't generate SIGPIPE when writing to dead socket, we check all writes. */
1642 signal(SIGPIPE, SIG_IGN);
1643 #endif
1644 if (wby_socket_set_blocking(sock, 0) != WBY_OK) goto error;
1645
1646 /* bind server socket */
1647 wby_dbg(server->config.log, "binding to %s:%d", server->config.address, server->config.port);
1648 memset(&bind_addr, 0, sizeof(bind_addr));
1649 bind_addr.sin_family = AF_INET;
1650 bind_addr.sin_port = htons((unsigned short)server->config.port);
1651 bind_addr.sin_addr.s_addr = inet_addr(server->config.address);
1652 if (bind(sock, (struct sockaddr*) &bind_addr, sizeof(bind_addr)) != WBY_OK) {
1653 wby_dbg(server->config.log, "bind() failed: %d", wby_socket_error());
1654 wby_dbg(server->config.log, "bind() failed: %s", strerror(wby_socket_error()));
1655 goto error;
1656 }
1657
1658 /* set server socket to listening */
1659 if (listen(sock, SOMAXCONN) != WBY_OK) {
1660 wby_dbg(server->config.log, "listen() failed: %d", wby_socket_error());
1661 wby_socket_close(WBY_SOCK(sock));
1662 goto error;
1663 }
1664 server->socket = (wby_ptr)sock;
1665 wby_dbg(server->config.log, "server initialized: %s", strerror(errno));
1666 return 0;
1667
1668error:
1669 if (wby_socket_is_valid(WBY_SOCK(sock)))
1670 wby_socket_close(WBY_SOCK(sock));
1671 return -1;
1672}
1673
1674WBY_API void
1675wby_stop(struct wby_server *srv)
1676{
1677#ifdef _WIN32
1678 if (srv->windows_socket_initialized) {
1679 WSACleanup();
1680 }
1681#endif
1682 wby_size i;
1683 wby_socket_close(WBY_SOCK(srv->socket));
1684 for (i = 0; i < srv->con_count; ++i)
1685 wby_socket_close(WBY_SOCK(srv->con[i].socket));
1686}
1687
1688WBY_INTERN int
1689wby_on_incoming(struct wby_server *srv)
1690{
1691 wby_size connection_index;
1692 char WBY_ALIGN(8) client_addr[64];
1693 struct wby_connection* connection;
1694 wby_socklen client_addr_len = sizeof(client_addr);
1695 wby_socket fd;
1696
1697 /* Make sure we have space for a new connection */
1698 connection_index = srv->con_count;
1699 if (connection_index == srv->config.connection_max) {
1700 wby_dbg(srv->config.log, "out of connection slots");
1701 return 1;
1702 }
1703
1704 /* Accept the incoming connection. */
1705 fd = accept(WBY_SOCK(srv->socket), (struct sockaddr*)&client_addr[0], &client_addr_len);
1706 if (!wby_socket_is_valid(fd)) {
1707 int err = wby_socket_error();
1708 if (!wby_socket_is_blocking_error(err))
1709 wby_dbg(srv->config.log, "accept() failed: %d", err);
1710 return 1;
1711 }
1712
1713 connection = &srv->con[connection_index];
1714 wby_connection_reset(connection, srv->config.request_buffer_size, srv->config.io_buffer_size);
1715 connection->flags = WBY_CON_FLAG_FRESH_CONNECTION;
1716 srv->con_count = connection_index + 1;
1717
1718 /* Configure socket */
1719 if (wby_socket_config_incoming(fd) != WBY_OK) {
1720 wby_socket_close(fd);
1721 return 1;
1722 }
1723
1724 /* OK, keep this connection */
1725 wby_dbg(srv->config.log, "tagging connection %d as alive", connection_index);
1726 connection->flags |= WBY_CON_FLAG_ALIVE;
1727 connection->socket = (wby_ptr)fd;
1728 return 0;
1729}
1730
1731WBY_INTERN void
1732wby_update_connection(struct wby_server *srv, struct wby_connection* connection)
1733{
1734 /* This is no longer a fresh connection. Only read from it when select() says
1735 * so in the future. */
1736 connection->flags &= (unsigned short)~WBY_CON_FLAG_FRESH_CONNECTION;
1737 for (;;)
1738 {
1739 switch (connection->state) {
1740 default: break;
1741 case WBY_CON_STATE_REQUEST: {
1742 const char *expect_header;
1743 int request_size;
1744 int result = wby_socket_recv(WBY_SOCK(connection->socket),
1745 &connection->header_buf, srv->config.log);
1746 if (WBY_FILL_ERROR == result) {
1747 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1748 return;
1749 }
1750
1751 /* Scan to see if the buffer has a complete HTTP request header package. */
1752 request_size = wb_peek_request_size(connection->header_buf.data,
1753 (int)connection->header_buf.used);
1754 if (request_size < 0) {
1755 /* Nothing yet. */
1756 if (connection->header_buf.max == connection->header_buf.used) {
1757 wby_dbg(srv->config.log, "giving up as buffer is full");
1758 /* Give up, we can't fit the request in our buffer. */
1759 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1760 }
1761 return;
1762 }
1763 wby_dbg(srv->config.log, "peek request size: %d", request_size);
1764
1765
1766 /* Set up request data. */
1767 if (wby_connection_setup_request(connection, request_size) != WBY_OK) {
1768 wby_dbg(srv->config.log, "failed to set up request");
1769 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1770 return;
1771 }
1772
1773 /* Remember how much of the remaining buffer is body data. */
1774 connection->header_body_left = (int)connection->header_buf.used - request_size;
1775 /* If the client expects a 100 Continue, send one now. */
1776 if (NULL != (expect_header = wby_find_header(&connection->public_data, "Expect"))) {
1777 if (!strcasecmp(expect_header, "100-continue")) {
1778 wby_dbg(srv->config.log, "connection expects a 100 Continue header.. making him happy");
1779 connection->continue_data_left = (int)wby_continue_header_len;
1780 connection->state = WBY_CON_STATE_SEND_CONTINUE;
1781 } else {
1782 wby_dbg(srv->config.log, "unrecognized Expected header %s", expect_header);
1783 connection->state = WBY_CON_STATE_SERVE;
1784 }
1785 } else connection->state = WBY_CON_STATE_SERVE;
1786 } break; /* WBY_REQUEST */
1787
1788 case WBY_CON_STATE_SEND_CONTINUE: {
1789 int left = connection->continue_data_left;
1790 int offset = (int)wby_continue_header_len - left;
1791 long written = 0;
1792
1793 written = send(WBY_SOCK(connection->socket), wby_continue_header + offset, (wby_size)left, 0);
1794 wby_dbg(srv->config.log, "continue write: %d bytes", written);
1795 if (written < 0) {
1796 wby_dbg(srv->config.log, "failed to write 100-continue header");
1797 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1798 return;
1799 }
1800 left -= (int)written;
1801 connection->continue_data_left = left;
1802 if (left == 0)
1803 connection->state = WBY_CON_STATE_SERVE;
1804 } break; /* WBY_SEND_cONTINUE */
1805
1806 case WBY_CON_STATE_SERVE: {
1807 /* Clear I/O buffer for output */
1808 connection->io_buf.used = 0;
1809 /* Switch socket to blocking mode. */
1810 if (wby_connection_set_blocking(connection) != WBY_OK)
1811 return;
1812
1813 /* Figure out if this is a request to upgrade to WebSockets */
1814 if (wby_con_is_websocket_request(&connection->public_data)) {
1815 wby_dbg(srv->config.log, "received a websocket upgrade request");
1816 if (!srv->config.ws_connect ||
1817 srv->config.ws_connect(&connection->public_data, srv->config.userdata) != WBY_OK)
1818 {
1819 wby_dbg(srv->config.log, "user callback failed connection attempt");
1820 wby_response_begin(&connection->public_data, 400, -1,
1821 wby_plain_text_headers, WBY_LEN(wby_plain_text_headers));
1822 wby_printf(&connection->public_data, "WebSockets not supported at %s\r\n",
1823 connection->public_data.request.uri);
1824 wby_response_end(&connection->public_data);
1825 } else {
1826 /* OK, let's try to upgrade the connection to WebSockets */
1827 if (wby_connection_send_websocket_upgrade(connection) != WBY_OK) {
1828 wby_dbg(srv->config.log, "websocket upgrade failed");
1829 wby_response_begin(&connection->public_data, 400, -1,
1830 wby_plain_text_headers, WBY_LEN(wby_plain_text_headers));
1831 wby_printf(&connection->public_data, "WebSockets couldn't not be enabled\r\n");
1832 wby_response_end(&connection->public_data);
1833 } else {
1834 /* OK, we're now a websocket */
1835 connection->flags |= WBY_CON_FLAG_WEBSOCKET;
1836 wby_dbg(srv->config.log, "connection %d upgraded to websocket",
1837 (int)(connection - srv->con));
1838 srv->config.ws_connected(&connection->public_data, srv->config.userdata);
1839 }
1840 }
1841 } else if (srv->config.dispatch(&connection->public_data, srv->config.userdata) != 0) {
1842 static const struct wby_header headers[] = {{ "Content-Type", "text/plain" }};
1843 wby_response_begin(&connection->public_data, 404, -1, headers, WBY_LEN(headers));
1844 wby_printf(&connection->public_data, "No handler for %s\r\n",
1845 connection->public_data.request.uri);
1846 wby_response_end(&connection->public_data);
1847 }
1848
1849 /* Back to non-blocking mode, can make the socket die. */
1850 wby_connection_set_nonblocking(connection);
1851 /* Ready for another request, unless we should close the connection. */
1852 if (connection->flags & WBY_CON_FLAG_ALIVE) {
1853 if (connection->flags & WBY_CON_FLAG_CLOSE_AFTER_RESPONSE) {
1854 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1855 return;
1856 } else {
1857 /* Reset connection for next request. */
1858 wby_connection_reset(connection, srv->config.request_buffer_size,
1859 srv->config.io_buffer_size);
1860 if (!(connection->flags & WBY_CON_FLAG_WEBSOCKET)) {
1861 /* Loop back to request state */
1862 connection->state = WBY_CON_STATE_REQUEST;
1863 } else {
1864 /* Clear I/O buffer for input */
1865 connection->io_buf.used = 0;
1866 /* Go to the web socket serving state */
1867 connection->state = WBY_CON_STATE_WEBSOCKET;
1868 }
1869 }
1870 }
1871 } break; /* WBY_SERVE */
1872
1873 case WBY_CON_STATE_WEBSOCKET: {
1874 /* In this state, we're trying to read a websocket frame into the I/O
1875 * buffer. Once we have enough data, we call the websocket frame
1876 * callback and let the client read the data through WebbyRead. */
1877 if (WBY_FILL_ERROR == wby_socket_recv(WBY_SOCK(connection->socket),
1878 &connection->io_buf, srv->config.log)) {
1879 /* Give up on this connection */
1880 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1881 return;
1882 }
1883
1884 if (wby_scan_websocket_frame(&connection->ws_frame, &connection->io_buf) != WBY_OK)
1885 return;
1886
1887 connection->body_bytes_read = 0;
1888 connection->io_data_left = (int)connection->io_buf.used - connection->ws_frame.header_size;
1889 wby_dbg(srv->config.log, "%d bytes of incoming websocket data buffered",
1890 (int)connection->io_data_left);
1891
1892 /* Switch socket to blocking mode */
1893 if (wby_connection_set_blocking(connection) != WBY_OK)
1894 return;
1895
1896 switch (connection->ws_frame.opcode)
1897 {
1898 case WBY_WSOP_CLOSE:
1899 wby_dbg(srv->config.log, "received websocket close request");
1900 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1901 return;
1902
1903 case WBY_WSOP_PING:
1904 wby_dbg(srv->config.log, "received websocket ping request");
1905 if (wby_socket_send(WBY_SOCK(connection->socket), wby_websocket_pong,
1906 sizeof wby_websocket_pong)){
1907 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1908 return;
1909 }
1910 break;
1911
1912 default:
1913 /* Dispatch frame to user handler. */
1914 if (srv->config.ws_frame(&connection->public_data,
1915 &connection->ws_frame, srv->config.userdata) != WBY_OK) {
1916 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1917 return;
1918 }
1919 }
1920
1921 /* Discard any data the client didn't read to retain the socket state. */
1922 if (connection->body_bytes_read < connection->ws_frame.payload_length) {
1923 int size = connection->ws_frame.payload_length - connection->body_bytes_read;
1924 if (wby_con_discard_incoming_data(&connection->public_data, size) != WBY_OK) {
1925 connection->flags &= (unsigned short)~WBY_CON_FLAG_ALIVE;
1926 return;
1927 }
1928 }
1929
1930 /* Back to non-blocking mode */
1931 if (wby_connection_set_nonblocking(connection) != WBY_OK)
1932 return;
1933
1934 wby_connection_reset(connection, srv->config.request_buffer_size, srv->config.io_buffer_size);
1935 connection->state = WBY_CON_STATE_WEBSOCKET;
1936 } break; /* WBY_WEBSOCKET */
1937 } /* switch */
1938 } /* for */
1939}
1940
1941WBY_API void
1942wby_update(struct wby_server *srv)
1943{
1944 int err;
1945 wby_size i, count;
1946 wby_socket max_socket;
1947 fd_set read_fds, write_fds, except_fds;
1948 struct timeval timeout;
1949
1950 /* Build set of sockets to check for events */
1951 FD_ZERO(&read_fds);
1952 FD_ZERO(&write_fds);
1953 FD_ZERO(&except_fds);
1954 max_socket = 0;
1955
1956 /* Only accept incoming connections if we have space */
1957 if (srv->con_count < srv->config.connection_max) {
1958 FD_SET(srv->socket, &read_fds);
1959 FD_SET(srv->socket, &except_fds);
1960 max_socket = WBY_SOCK(srv->socket);
1961 }
1962
1963 for (i = 0, count = srv->con_count; i < count; ++i) {
1964 wby_socket socket = WBY_SOCK(srv->con[i].socket);
1965 FD_SET(socket, &read_fds);
1966 FD_SET(socket, &except_fds);
1967 if (srv->con[i].state == WBY_CON_STATE_SEND_CONTINUE)
1968 FD_SET(socket, &write_fds);
1969 if (socket > max_socket)
1970 max_socket = socket;
1971 }
1972
1973 timeout.tv_sec = 0;
1974 timeout.tv_usec = 5;
1975 err = select((int)(max_socket + 1), &read_fds, &write_fds, &except_fds, &timeout);
1976 if (err < 0) {
1977 wby_dbg(srv->config.log, "failed to select");
1978 return;
1979 }
1980
1981 /* Handle incoming connections */
1982 if (FD_ISSET(WBY_SOCK(srv->socket), &read_fds)) {
1983 do {
1984 wby_dbg(srv->config.log, "awake on incoming");
1985 err = wby_on_incoming(srv);
1986 } while (err == 0);
1987 }
1988
1989 /* Handle incoming connection data */
1990 for (i = 0, count = srv->con_count; i < count; ++i) {
1991 struct wby_connection *conn = &srv->con[i];
1992 if (FD_ISSET(WBY_SOCK(conn->socket), &read_fds) ||
1993 FD_ISSET(WBY_SOCK(conn->socket), &write_fds) ||
1994 conn->flags & WBY_CON_FLAG_FRESH_CONNECTION)
1995 {
1996 wby_dbg(srv->config.log, "reading from connection %d", i);
1997 wby_update_connection(srv, conn);
1998 }
1999 }
2000
2001 /* Close stale connections & compact connection array. */
2002 for (i = 0; i < srv->con_count; ) {
2003 struct wby_connection *connection = &srv->con[i];
2004 if (!(connection->flags & WBY_CON_FLAG_ALIVE)) {
2005 wby_size remain;
2006 wby_dbg(srv->config.log, "closing connection %d (%08x)", i, connection->flags);
2007 if (connection->flags & WBY_CON_FLAG_WEBSOCKET)
2008 srv->config.ws_closed(&connection->public_data, srv->config.userdata);
2009 remain = srv->con_count - (wby_size)i - 1;
2010 wby_connection_close(connection);
2011 memmove(&srv->con[i], &srv->con[i + 1], remain*sizeof(srv->con[i]));
2012 --srv->con_count;
2013 } else ++i;
2014 }
2015}
2016
2017#endif /* WBY_IMPLEMENTATION */