Newer
Older
#ifdef __AVR__
#include "avrsupport.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
* This software is dual-licensed: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. For the terms of this
* license, see <http://www.gnu.org/licenses/>.
*
* You are free to use this software under the terms of the GNU General
* Public License, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* Alternatively, you can license this software under a commercial
* license, as set out in <https://www.cesanta.com/license>.
*/
#define MG_FOSSA_VERSION "2.0.0"
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
#ifndef OSDEP_HEADER_INCLUDED
#define OSDEP_HEADER_INCLUDED
#if !defined(MG_DISABLE_FILESYSTEM) && defined(AVR_NOFS)
#define MG_DISABLE_FILESYSTEM
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#endif
#undef UNICODE /* Use ANSI WinAPI functions */
#undef _UNICODE /* Use multibyte encoding on Windows */
#define _MBCS /* Use multibyte encoding on Windows */
#define _INTEGRAL_MAX_BITS 64 /* Enable _stati64() on Windows */
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */
#endif
#undef WIN32_LEAN_AND_MEAN /* Let windows.h always include winsock2.h */
#undef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
#define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
#define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
#ifndef _LARGEFILE_SOURCE
#define _LARGEFILE_SOURCE /* Enable fseeko() and ftello() functions */
#endif
#define _FILE_OFFSET_BITS 64 /* Enable 64-bit file offsets */
#if !(defined(AVR_LIBC) || defined(PICOTCP))
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#endif
#ifndef BYTE_ORDER
#define LITTLE_ENDIAN 0x41424344
#define BIG_ENDIAN 0x44434241
#define PDP_ENDIAN 0x42414443
/* TODO(lsm): fix for big-endian machines. 'ABCD' is not portable */
/*#define BYTE_ORDER 'ABCD'*/
#define BYTE_ORDER LITTLE_ENDIAN
#endif
/*
* MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
* MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
* MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
* MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
* MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
* MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)
* MSVC++ 7.0 _MSC_VER == 1300
* MSVC++ 6.0 _MSC_VER == 1200
* MSVC++ 5.0 _MSC_VER == 1100
*/
#ifdef _MSC_VER
#pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */
#pragma warning(disable : 4204) /* missing c99 support */
#endif
#ifdef PICOTCP
#define time(x) PICO_TIME()
#ifndef SOMAXCONN
#define SOMAXCONN (16)
#endif
#ifdef _POSIX_VERSION
#define signal(...)
#endif
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef va_copy
#ifdef __va_copy
#define va_copy __va_copy
#else
#define va_copy(x, y) (x) = (y)
#endif
#endif
#ifdef _WIN32
#define random() rand()
#ifdef _MSC_VER
#pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
#endif
#include <windows.h>
#include <process.h>
#ifndef EINPROGRESS
#define EINPROGRESS WSAEINPROGRESS
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#ifndef __func__
#define STRX(x) #x
#define STR(x) STRX(x)
#define __func__ __FILE__ ":" STR(__LINE__)
#endif
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define sleep(x) Sleep((x) *1000)
#define to64(x) _atoi64(x)
#define popen(x, y) _popen((x), (y))
#define pclose(x) _pclose(x)
#if defined(_MSC_VER) && _MSC_VER >= 1400
#define fseeko(x, y, z) _fseeki64((x), (y), (z))
#else
#define fseeko(x, y, z) fseek((x), (y), (z))
#endif
#define random() rand()
typedef int socklen_t;
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
typedef SOCKET sock_t;
typedef uint32_t in_addr_t;
#ifndef UINT16_MAX
#define UINT16_MAX 65535
#endif
#ifndef UINT32_MAX
#define UINT32_MAX 4294967295
#endif
#ifndef pid_t
#define pid_t HANDLE
#endif
#define INT64_FMT "I64d"
#define SIZE_T_FMT "Iu"
#ifdef __MINGW32__
typedef struct stat cs_stat_t;
#else
typedef struct _stati64 cs_stat_t;
#endif
#ifndef S_ISDIR
#define S_ISDIR(x) ((x) &_S_IFDIR)
#endif
#define DIRSEP '\\'
/* POSIX opendir/closedir/readdir API for Windows. */
struct dirent {
char d_name[MAX_PATH];
};
typedef struct DIR {
HANDLE handle;
WIN32_FIND_DATAW info;
struct dirent result;
} DIR;
DIR *opendir(const char *name);
int closedir(DIR *dir);
struct dirent *readdir(DIR *dir);
#elif /* not _WIN32 */ defined(MG_CC3200)
#include <fcntl.h>
#include <unistd.h>
#include <cc3200_libc.h>
#include <cc3200_socket.h>
#elif /* not CC3200 */ defined(MG_ESP8266) && defined(RTOS_SDK)
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include <lwip/dns.h>
#include <esp_libc.h>
#define random() os_random()
/* TODO(alashkin): check if zero is OK */
#define SOMAXCONN 0
#include <stdlib.h>
#elif /* not ESP8266 RTOS */ !defined(NO_LIBC) && !defined(NO_BSD_SOCKETS)
#include <dirent.h>
#include <fcntl.h>
#include <netdb.h>
#include <pthread.h>
#include <unistd.h>
#include <arpa/inet.h> /* For inet_pton() when MG_ENABLE_IPV6 is defined */
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#endif
#ifndef _WIN32
#include <errno.h>
#include <inttypes.h>
#include <stdarg.h>
#ifndef AVR_LIBC
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#define closesocket(x) close(x)
#endif
#ifndef __cdecl
#define __cdecl
#endif
#define INVALID_SOCKET (-1)
#define INT64_FMT PRId64
#define SIZE_T_FMT "zu"
#define to64(x) strtoll(x, NULL, 10)
typedef int sock_t;
typedef struct stat cs_stat_t;
#define DIRSEP '/'
#endif /* !AVR_LIBC */
#ifdef __APPLE__
int64_t strtoll(const char *str, char **endptr, int base);
#endif
#endif /* !_WIN32 */
#define __DBG(x) \
do { \
printf("%-20s ", __func__); \
printf x; \
putchar('\n'); \
fflush(stdout); \
} while (0)
#ifdef MG_ENABLE_DEBUG
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
#define DBG __DBG
#else
#define DBG(x)
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
#endif /* OSDEP_HEADER_INCLUDED */
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
/*
* === Memory Buffers
*
* Mbufs are mutable/growing memory buffers, like C++ strings.
* Mbuf can append data to the end of a buffer, or insert data into arbitrary
* position in the middle of a buffer. The buffer grows automatically when
* needed.
*/
#ifndef MBUF_H_INCLUDED
#define MBUF_H_INCLUDED
#if defined(__cplusplus)
extern "C" {
#endif
#include <stdlib.h>
#ifndef MBUF_SIZE_MULTIPLIER
#define MBUF_SIZE_MULTIPLIER 1.5
#endif
/* Memory buffer descriptor */
struct mbuf {
char *buf; /* Buffer pointer */
size_t len; /* Data length. Data is located between offset 0 and len. */
size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
};
/*
* Initialize an Mbuf.
* `initial_capacity` specifies the initial capacity of the mbuf.
*/
void mbuf_init(struct mbuf *, size_t initial_capacity);
/* Free the space allocated for the mbuffer and resets the mbuf structure. */
void mbuf_free(struct mbuf *);
/*
* Appends data to the Mbuf.
*
* Return the number of bytes appended, or 0 if out of memory.
*/
size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
/*
* Insert data at a specified offset in the Mbuf.
*
* Existing data will be shifted forwards and the buffer will
* be grown if necessary.
* Return the number of bytes inserted.
*/
size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
/* Remove `data_size` bytes from the beginning of the buffer. */
void mbuf_remove(struct mbuf *, size_t data_size);
/*
* Resize an Mbuf.
*
* If `new_size` is smaller than buffer's `len`, the
* resize is not performed.
*/
void mbuf_resize(struct mbuf *, size_t new_size);
/* Shrink an Mbuf by resizing its `size` to `len`. */
void mbuf_trim(struct mbuf *);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* MBUF_H_INCLUDED */
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#if !defined(MG_SHA1_HEADER_INCLUDED) && !defined(DISABLE_SHA1)
#define MG_SHA1_HEADER_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} cs_sha1_ctx;
void cs_sha1_init(cs_sha1_ctx *);
void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
void cs_hmac_sha1(const unsigned char *key, size_t key_len,
const unsigned char *text, size_t text_len,
unsigned char out[20]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MG_SHA1_HEADER_INCLUDED */
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef MD5_HEADER_DEFINED
#define MD5_HEADER_DEFINED
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct MD5Context {
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
} MD5_CTX;
void MD5_Init(MD5_CTX *c);
void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len);
void MD5_Final(unsigned char *md, MD5_CTX *c);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#if !defined(BASE64_H_INCLUDED) && !defined(DISABLE_BASE64)
#define BASE64_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*cs_base64_putc_t)(char, void *);
struct cs_base64_ctx {
/* cannot call it putc because it's a macro on some environments */
cs_base64_putc_t b64_putc;
unsigned char chunk[3];
int chunk_size;
void *user_data;
};
void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc,
void *user_data);
void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len);
void cs_base64_finish(struct cs_base64_ctx *ctx);
void cs_base64_encode(const unsigned char *src, int src_len, char *dst);
void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len);
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
int cs_base64_decode(const unsigned char *s, int len, char *dst);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2015 Cesanta Software Limited
* All rights reserved
*/
#ifndef STR_UTIL_H
#define STR_UTIL_H
#include <stdarg.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
int c_snprintf(char *buf, size_t buf_size, const char *format, ...);
int c_vsnprintf(char *buf, size_t buf_size, const char *format, va_list ap);
#if !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L) && \
!(__DARWIN_C_LEVEL >= 200809L) && !defined(RTOS_SDK) || \
defined(_WIN32)
int strnlen(const char *s, size_t maxlen);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
* Copyright (c) 2013 Cesanta Software Limited
* All rights reserved
*
* This library is dual-licensed: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. For the terms of this
* license, see <http: *www.gnu.org/licenses/>.
*
* You are free to use this library under the terms of the GNU General
* Public License, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* Alternatively, you can license this library under a commercial
* license, as set out in <https://www.cesanta.com/license>.
*/
#ifndef FROZEN_HEADER_INCLUDED
#define FROZEN_HEADER_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdarg.h>
enum json_type {
JSON_TYPE_EOF = 0, /* End of parsed tokens marker */
JSON_TYPE_STRING = 1,
JSON_TYPE_NUMBER = 2,
JSON_TYPE_OBJECT = 3,
JSON_TYPE_TRUE = 4,
JSON_TYPE_FALSE = 5,
JSON_TYPE_NULL = 6,
JSON_TYPE_ARRAY = 7
};
struct json_token {
const char *ptr; /* Points to the beginning of the token */
int len; /* Token length */
int num_desc; /* For arrays and object, total number of descendants */
enum json_type type; /* Type of the token, possible values above */
};
/* Error codes */
#define JSON_STRING_INVALID -1
#define JSON_STRING_INCOMPLETE -2
#define JSON_TOKEN_ARRAY_TOO_SMALL -3
int parse_json(const char *json_string, int json_string_length,
struct json_token *tokens_array, int size_of_tokens_array);
struct json_token *parse_json2(const char *json_string, int string_length);
struct json_token *find_json_token(struct json_token *toks, const char *path);
int json_emit_long(char *buf, int buf_len, long value);
int json_emit_double(char *buf, int buf_len, double value);
int json_emit_quoted_str(char *buf, int buf_len, const char *str, int len);
int json_emit_unquoted_str(char *buf, int buf_len, const char *str, int len);
int json_emit(char *buf, int buf_len, const char *fmt, ...);
int json_emit_va(char *buf, int buf_len, const char *fmt, va_list);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* FROZEN_HEADER_INCLUDED */
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
* This software is dual-licensed: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. For the terms of this
* license, see <http://www.gnu.org/licenses/>.
*
* You are free to use this software under the terms of the GNU General
* Public License, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* Alternatively, you can license this software under a commercial
* license, as set out in <https://www.cesanta.com/license>.
*/
/*
* === Core: TCP/UDP/SSL
*
* NOTE: Mongoose manager is single threaded. It does not protect
* its data structures by mutexes, therefore all functions that are dealing
* with particular event manager should be called from the same thread,
* with exception of `mg_broadcast()` function. It is fine to have different
* event managers handled by different threads.
*/
#ifndef MG_NET_HEADER_INCLUDED
#define MG_NET_HEADER_INCLUDED
#ifdef MG_ENABLE_SSL
#ifdef __APPLE__
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <openssl/ssl.h>
#else
typedef void *SSL;
typedef void *SSL_CTX;
#endif
#ifdef MG_USE_READ_WRITE
#define MG_EV_RECV_FUNC(s, b, l, f) read(s, b, l)
#define MG_EV_SEND_FUNC(s, b, l, f) write(s, b, l)
#define MG_EV_RECV_FUNC(s, b, l, f) recv(s, b, l, f)
#define MG_EV_SEND_FUNC(s, b, l, f) send(s, b, l, f)
#endif /* __cplusplus */
union socket_address {
struct sockaddr sa;
struct sockaddr_in sin;
#ifdef MG_ENABLE_IPV6
struct sockaddr_in6 sin6;
#else
struct sockaddr sin6;
#endif
};
/* Describes chunk of memory */
struct mg_str {
const char *p; /* Memory chunk pointer */
size_t len; /* Memory chunk length */
};
#define MG_STR(str_literal) \
{ str_literal, sizeof(str_literal) - 1 }
/*
* Callback function (event handler) prototype, must be defined by user.
* Mongoose calls event handler, passing events defined below.
*/
struct mg_connection;
typedef void (*mg_event_handler_t)(struct mg_connection *, int ev, void *);
/* Events. Meaning of event parameter (evp) is given in the comment. */
#define MG_EV_POLL 0 /* Sent to each connection on each mg_mgr_poll() call */
#define MG_EV_ACCEPT 1 /* New connection accepted. union socket_address * */
#define MG_EV_CONNECT 2 /* connect() succeeded or failed. int * */
#define MG_EV_RECV 3 /* Data has benn received. int *num_bytes */
#define MG_EV_SEND 4 /* Data has been written to a socket. int *num_bytes */
#define MG_EV_CLOSE 5 /* Connection is closed. NULL */
/*
* Mongoose event manager.
*/
struct mg_mgr {
struct mg_connection *active_connections;
const char *hexdump_file; /* Debug hexdump file path */
sock_t ctl[2]; /* Socketpair for mg_wakeup() */
void *user_data; /* User data */
void *mgr_data; /* Implementation-specific event manager's data. */
};
/*
* Mongoose connection.
*/
struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */
struct mg_connection *listener; /* Set only for accept()-ed connections */
struct mg_mgr *mgr; /* Pointer to containing manager */
sock_t sock; /* Socket to the remote peer */
union socket_address sa; /* Remote peer address */
size_t recv_mbuf_limit; /* Max size of recv buffer */
struct mbuf recv_mbuf; /* Received data */
struct mbuf send_mbuf; /* Data scheduled for sending */
SSL *ssl;
SSL_CTX *ssl_ctx;
time_t last_io_time; /* Timestamp of the last socket IO */
mg_event_handler_t proto_handler; /* Protocol-specific event handler */
void *proto_data; /* Protocol-specific data */
mg_event_handler_t handler; /* Event handler function */
void *user_data; /* User-specific data */
void *priv_1; /* Used by mg_enable_multithreading() */
void *priv_2; /* Used by mg_enable_multithreading() */
void *mgr_data; /* Implementation-specific event manager's data. */
unsigned long flags;
/* Flags set by Mongoose */
#define MG_F_LISTENING (1 << 0) /* This connection is listening */
#define MG_F_UDP (1 << 1) /* This connection is UDP */
#define MG_F_RESOLVING (1 << 2) /* Waiting for async resolver */
#define MG_F_CONNECTING (1 << 3) /* connect() call in progress */
#define MG_F_SSL_HANDSHAKE_DONE (1 << 4) /* SSL specific */
#define MG_F_WANT_READ (1 << 5) /* SSL specific */
#define MG_F_WANT_WRITE (1 << 6) /* SSL specific */
#define MG_F_IS_WEBSOCKET (1 << 7) /* Websocket specific */
/* Flags that are settable by user */
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
#define MG_F_DONT_SEND (1 << 11) /* Do not send data to peer */
#define MG_F_CLOSE_IMMEDIATELY (1 << 12) /* Disconnect */
#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 13) /* Websocket specific */
#define MG_F_DELETE_CHUNK (1 << 14) /* HTTP specific */
#define MG_F_USER_1 (1 << 20) /* Flags left for application */
#define MG_F_USER_2 (1 << 21)
#define MG_F_USER_3 (1 << 22)
#define MG_F_USER_4 (1 << 23)
#define MG_F_USER_5 (1 << 24)
#define MG_F_USER_6 (1 << 25)
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
};
/*
* Initialize Mongoose manager. Side effect: ignores SIGPIPE signal.
* `mgr->user_data` field will be initialized with `user_data` parameter.
* That is an arbitrary pointer, where user code can associate some data
* with the particular Mongoose manager. For example, a C++ wrapper class
* could be written, in which case `user_data` can hold a pointer to the
* class instance.
*/
void mg_mgr_init(struct mg_mgr *mgr, void *user_data);
/*
* De-initializes Mongoose manager.
*
* Close and deallocate all active connections.
*/
void mg_mgr_free(struct mg_mgr *);
/*
* This function performs the actual IO, and must be called in a loop
* (an event loop). Returns the current timestamp.
* `milli` is the maximum number of milliseconds to sleep.
* `mg_mgr_poll()` checks all connection for IO readiness. If at least one
* of the connections is IO-ready, `mg_mgr_poll()` triggers respective
* event handlers and returns.
*/
time_t mg_mgr_poll(struct mg_mgr *, int milli);
/*
* Pass a message of a given length to all connections.
*
* Must be called from a thread that does NOT call `mg_mgr_poll()`.
* Note that `mg_broadcast()` is the only function
* that can be, and must be, called from a different (non-IO) thread.
*
* `func` callback function will be called by the IO thread for each
* connection. When called, event would be `MG_EV_POLL`, and message will
* be passed as `ev_data` pointer. Maximum message size is capped
* by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
*/
void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
/*
* Iterate over all active connections.
*
* Returns next connection from the list
* of active connections, or `NULL` if there is no more connections. Below
* is the iteration idiom:
*
* [source,c]
* ----
* for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) {
* // Do something with connection `c`
* }
* ----
*/
struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
/*
* Optional parameters to mg_add_sock_opt()
* `flags` is an initial `struct mg_connection::flags` bitmask to set,
* see `MG_F_*` flags definitions.
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
*/
struct mg_add_sock_opts {
void *user_data; /* Initial value for connection's user_data */
unsigned int flags; /* Initial connection flags */
const char **error_string; /* Placeholder for the error string */
};
/*
* Create a connection, associate it with the given socket and event handler,
* and add it to the manager.
*
* For more options see the `mg_add_sock_opt` variant.
*/
struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
/*
* Create a connection, associate it with the given socket and event handler,
* and add to the manager.
*
* See the `mg_add_sock_opts` structure for a description of the options.
*/
struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
mg_event_handler_t,
struct mg_add_sock_opts);
/*
* Optional parameters to mg_bind_opt()
* `flags` is an initial `struct mg_connection::flags` bitmask to set,
* see `MG_F_*` flags definitions.
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
*/
struct mg_bind_opts {
void *user_data; /* Initial value for connection's user_data */
unsigned int flags; /* Extra connection flags */
const char **error_string; /* Placeholder for the error string */
};
/*
* Create listening connection.
*
* See `mg_bind_opt` for full documentation.
*/
struct mg_connection *mg_bind(struct mg_mgr *, const char *,
mg_event_handler_t);
/*
* Create listening connection.
*
* `address` parameter tells which address to bind to. It's format is the same
* as for the `mg_connect()` call, where `HOST` part is optional. `address`
* can be just a port number, e.g. `:8000`. To bind to a specific interface,
* an IP address can be specified, e.g. `1.2.3.4:8000`. By default, a TCP
* connection is created. To create UDP connection, prepend `udp://` prefix,
* e.g. `udp://:8000`. To summarize, `address` paramer has following format:
* `[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or `udp`.
*
* See the `mg_bind_opts` structure for a description of the optional
* parameters.
*
* Return a new listening connection, or `NULL` on error.
* NOTE: Connection remains owned by the manager, do not free().
*/
struct mg_connection *mg_bind_opt(struct mg_mgr *, const char *,
mg_event_handler_t, struct mg_bind_opts);
/* Optional parameters to mg_connect_opt() */
struct mg_connect_opts {
void *user_data; /* Initial value for connection's user_data */
unsigned int flags; /* Extra connection flags */
const char **error_string; /* Placeholder for the error string */
};
/*
* Connect to a remote host.
*
* See `mg_connect_opt()` for full documentation.
*/
struct mg_connection *mg_connect(struct mg_mgr *, const char *,
mg_event_handler_t);
/*
* Connect to a remote host.
*
* `address` format is `[PROTO://]HOST:PORT`. `PROTO` could be `tcp` or `udp`.
* `HOST` could be an IP address,
* IPv6 address (if Mongoose is compiled with `-DMG_ENABLE_IPV6`), or a host
* name. If `HOST` is a name, Mongoose will resolve it asynchronously. Examples
* of valid addresses: `google.com:80`, `udp://1.2.3.4:53`, `10.0.0.1:443`,
* `[::1]:80`
*
* See the `mg_connect_opts` structure for a description of the optional
* parameters.
*
* Returns a new outbound connection, or `NULL` on error.
*
* NOTE: Connection remains owned by the manager, do not free().
*
* NOTE: To enable IPv6 addresses, `-DMG_ENABLE_IPV6` should be specified
* in the compilation flags.
*
* NOTE: New connection will receive `MG_EV_CONNECT` as it's first event
* which will report connect success status.
* If asynchronous resolution fail, or `connect()` syscall fail for whatever
* reason (e.g. with `ECONNREFUSED` or `ENETUNREACH`), then `MG_EV_CONNECT`
* event report failure. Code example below:
*
* [source,c]
* ----
* static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
* int connect_status;
*
* switch (ev) {
* case MG_EV_CONNECT:
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
* connect_status = * (int *) ev_data;
* if (connect_status == 0) {
* // Success
* } else {
* // Error
* printf("connect() error: %s\n", strerror(connect_status));
* }
* break;
* ...
* }
* }
*
* ...
* mg_connect(mgr, "my_site.com:80", ev_handler);
* ----
*/
struct mg_connection *mg_connect_opt(struct mg_mgr *, const char *,
mg_event_handler_t,
struct mg_connect_opts);
/*
* Enable SSL for a given connection.
* `cert` is a server certificate file name for a listening connection,
* or a client certificate file name for an outgoing connection.
* Certificate files must be in PEM format. Server certificate file
* must contain a certificate, concatenated with a private key, optionally
* concatenated with parameters.
* `ca_cert` is a CA certificate, or NULL if peer verification is not
* required.
* Return: NULL on success, or error message on error.
*/
const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
const char *ca_cert);
/*
* Send data to the connection.
*
* Return number of written bytes. Note that sending
* functions do not actually push data to the socket. They just append data
* to the output buffer. The exception is UDP connections. For UDP, data is
* sent immediately, and returned value indicates an actual number of bytes
* sent to the socket.
*/
int mg_send(struct mg_connection *, const void *buf, int len);
/*
* Send `printf`-style formatted data to the connection.
*
* See `mg_send` for more details on send semantics.
*/
int mg_printf(struct mg_connection *, const char *fmt, ...);
/* Same as `mg_printf()`, but takes `va_list ap` as an argument. */
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
/*
* Create a socket pair.
* `sock_type` can be either `SOCK_STREAM` or `SOCK_DGRAM`.
* Return 0 on failure, 1 on success.
*/
int mg_socketpair(sock_t[2], int sock_type);
/*
* Convert domain name into IP address.
*
* This is a utility function. If compilation flags have
* `-DMG_ENABLE_GETADDRINFO`, then `getaddrinfo()` call is used for name
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
* resolution. Otherwise, `gethostbyname()` is used.
*
* CAUTION: this function can block.
* Return 1 on success, 0 on failure.
*/
int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
/*
* Verify given IP address against the ACL.
*
* `remote_ip` - an IPv4 address to check, in host byte order
* `acl` - a comma separated list of IP subnets: `x.x.x.x/x` or `x.x.x.x`.
* Each subnet is
* prepended by either a - or a + sign. A plus sign means allow, where a
* minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`,
* this means to deny only that single IP address.
* Subnet masks may vary from 0 to 32, inclusive. The default setting
* is to allow all accesses. On each request the full list is traversed,
* and the last match wins. Example:
*
* `-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet
*
* To learn more about subnet masks, see the
* link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork]
*
* Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
*/
int mg_check_ip_acl(const char *acl, uint32_t remote_ip);
/*
* Enable multi-threaded handling for the given listening connection `nc`.
* For each accepted connection, Mongoose will create a separate thread
* and run event handler in that thread. Thus, if an event hanler is doing
* a blocking call or some long computation, that will not slow down
* other connections.
*/
void mg_enable_multithreading(struct mg_connection *nc);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MG_NET_HEADER_INCLUDED */
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
/*
* === Utilities
*/
#ifndef MG_UTIL_HEADER_DEFINED
#define MG_UTIL_HEADER_DEFINED
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef MAX_PATH_SIZE
#define MAX_PATH_SIZE 500
#endif
/*
* Fetch substring from input string `s`, `end` into `v`.
* Skips initial delimiter characters. Records first non-delimiter character
* as the beginning of substring `v`. Then scans the rest of the string
* until a delimiter character or end-of-string is found.
* `delimiters` is a 0-terminated string containing delimiter characters.
* Either one of `delimiters` or `end_string` terminates the search.
* Return an `s` pointer, advanced forward where parsing stopped.
*/
const char *mg_skip(const char *s, const char *end_string,
const char *delimiters, struct mg_str *v);
/*
* Cross-platform version of `strncasecmp()`.
*/