forked from cesanta/mongoose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmongoose.h
2650 lines (2309 loc) · 82.4 KB
/
mongoose.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
142
143
144
145
146
147
148
149
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
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
254
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
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
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
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
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
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
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
770
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
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
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
919
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
962
963
964
965
966
967
968
969
970
971
972
973
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
#ifdef __AVR__
#include "avrsupport.h"
#endif
/*
* Copyright (c) 2004-2013 Sergey Lyubka
* Copyright (c) 2013-2015 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_VERSION "6.0"
/* Local tweaks, applied before any of Mongoose's own headers. */
#ifdef MG_LOCALS
#include <mg_locals.h>
#endif
/*
* 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
#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++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
* 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 fileno _fileno
#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 signed char int8_t;
typedef unsigned char uint8_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
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_LWIP)
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include <lwip/dns.h>
#if defined(MG_ESP8266) && defined(RTOS_SDK)
#include <esp_libc.h>
#define random() os_random()
#endif
/* 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
#ifndef MG_ESP8266
#define closesocket(x) close(x)
#endif
#ifndef __cdecl
#define __cdecl
#endif
#define INVALID_SOCKET (-1)
#define INT64_FMT PRId64
#if defined(ESP8266) || defined(MG_ESP8266) || defined(MG_CC3200)
#define SIZE_T_FMT "u"
#else
#define SIZE_T_FMT "zu"
#endif
#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
#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 */
/*
* 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);
/*
* Return stringified MD5 hash for NULL terminated list of strings.
* Example:
*
* char buf[33];
* cs_md5(buf, "foo", "bar", NULL);
*/
char *cs_md5(char buf[33], ...);
/*
* Stringify binary data. Output buffer size must be 2 * size_of_input + 1
* because each byte of input takes 2 bytes in string representation
* plus 1 byte for the terminating \0 character.
*/
void cs_to_hex(char *to, const unsigned char *p, size_t len);
#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
#include <stdio.h>
#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);
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)
size_t strnlen(const char *s, size_t maxlen);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2004-2013 Sergey Lyubka <[email protected]>
* 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_JAVASCRIPT
#define EXCLUDE_COMMON
#include <v7.h>
#endif
#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_RECV_FUNC(s, b, l, f) read(s, b, l)
#define MG_SEND_FUNC(s, b, l, f) write(s, b, l)
#else
#define MG_RECV_FUNC(s, b, l, f) recv(s, b, l, f)
#define MG_SEND_FUNC(s, b, l, f) send(s, b, l, f)
#endif
#ifdef __cplusplus
extern "C" {
#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. */
#ifdef MG_ENABLE_JAVASCRIPT
struct v7 *v7;
#endif
};
/*
* Mongoose connection.
*/
struct mg_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 */
int err;
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)
};
/*
* 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);
#ifndef MG_DISABLE_SOCKETPAIR
/*
* 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);
#endif
/*
* 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.
*/
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.
*/
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:
* 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.
*
* Note that sending functions do not actually push data to the socket.
* They just append data to the output buffer. MG_EV_SEND will be delivered when
* the data has actually been pushed out.
*/
void mg_send(struct mg_connection *, const void *buf, int len);
/* Enables format string warnings for mg_printf */
#if defined(__GNUC__)
__attribute__((format(printf, 2, 3)))
#endif
/* don't separate from mg_printf declaration */
/*
* 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
* resolution. Otherwise, `gethostbyname()` is used.
*
* CAUTION: this function can block.
* Return 1 on success, 0 on failure.
*/
#ifndef MG_DISABLE_SYNC_RESOLVER
int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
#endif
/*
* 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`.