Seregon/Hermes

Hermes/Dyforge is a program written in c++ allows you to inject a dll that can analyze all processes in a program, can be used for mod and reverse engeneering

C/3.8 KB/No license
DyMain/include/mongoose.h
Hermes / DyMain / include / mongoose.h
1// Copyright (c) 2004-2013 Sergey Lyubka
2// Copyright (c) 2013-2025 Cesanta Software Limited
3// All rights reserved
4//
5// This software is dual-licensed: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License version 2 as
7// published by the Free Software Foundation. For the terms of this
8// license, see http://www.gnu.org/licenses/
9//
10// You are free to use this software under the terms of the GNU General
11// Public License, but WITHOUT ANY WARRANTY; without even the implied
12// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13// See the GNU General Public License for more details.
14//
15// Alternatively, you can license this software under a commercial
16// license, as set out in https://www.mongoose.ws/licensing/
17//
18// SPDX-License-Identifier: GPL-2.0-only or commercial
19 
20#ifndef MONGOOSE_H
21#define MONGOOSE_H
22 
23#define MG_VERSION "7.17"
24 
25#ifdef __cplusplus
26extern "C" {
27#endif
28 
29 
30#define MG_ARCH_CUSTOM 0 // User creates its own mongoose_config.h
31#define MG_ARCH_UNIX 1 // Linux, BSD, Mac, ...
32#define MG_ARCH_WIN32 2 // Windows
33#define MG_ARCH_ESP32 3 // ESP32
34#define MG_ARCH_ESP8266 4 // ESP8266
35#define MG_ARCH_FREERTOS 5 // FreeRTOS
36#define MG_ARCH_AZURERTOS 6 // MS Azure RTOS
37#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
38#define MG_ARCH_NEWLIB 8 // Bare metal ARM
39#define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX)
40#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
41#define MG_ARCH_PICOSDK 11 // Raspberry Pi Pico-SDK (RP2040, RP2350)
42#define MG_ARCH_ARMCC 12 // Keil MDK-Core with Configuration Wizard
43#define MG_ARCH_CMSIS_RTOS2 13 // CMSIS-RTOS API v2 (Keil RTX5, FreeRTOS)
44#define MG_ARCH_RTTHREAD 14 // RT-Thread RTOS
45#define MG_ARCH_ARMCGT 15 // Texas Semi ARM-CGT
46 
47#if !defined(MG_ARCH)
48#if defined(__unix__) || defined(__APPLE__)
49#define MG_ARCH MG_ARCH_UNIX
50#elif defined(_WIN32)
51#define MG_ARCH MG_ARCH_WIN32
52#endif
53#endif // !defined(MG_ARCH)
54 
55#if !defined(MG_ARCH) || (MG_ARCH == MG_ARCH_CUSTOM)
56#include "mongoose_config.h" // keep this include
57#endif
58 
59#if !defined(MG_ARCH)
60#error "MG_ARCH is not specified and we couldn't guess it. Define MG_ARCH=... in your compiler"
61#endif
62 
63// http://esr.ibiblio.org/?p=5095
64#define MG_BIG_ENDIAN (*(uint16_t *) "\0\xff" < 0x100)
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80#if MG_ARCH == MG_ARCH_ARMCGT
81 
82#include <ctype.h>
83#include <errno.h>
84#include <stdarg.h>
85#include <stdbool.h>
86#include <stdio.h>
87#include <stdlib.h>
88#include <string.h>
89#include <sys/types.h>
90#include <time.h>
91 
92#define MG_PATH_MAX 100
93#define MG_ENABLE_SOCKET 0
94#define MG_ENABLE_DIRLIST 0
95 
96#endif
97 
98 
99#if MG_ARCH == MG_ARCH_AZURERTOS
100 
101#include <stdarg.h>
102#include <stdbool.h>
103#include <stdint.h>
104#include <stdio.h>
105#include <time.h>
106 
107#include <fx_api.h>
108#include <tx_api.h>
109 
110#include <nx_api.h>
111#include <nx_bsd.h>
112#include <nx_port.h>
113#include <tx_port.h>
114 
115#define PATH_MAX FX_MAXIMUM_PATH
116#define MG_DIRSEP '\\'
117 
118#define socklen_t int
119#define closesocket(x) soc_close(x)
120 
121#undef FOPEN_MAX
122 
123#endif
124 
125 
126#if MG_ARCH == MG_ARCH_ESP32
127 
128#include <ctype.h>
129#include <dirent.h>
130#include <errno.h>
131#include <fcntl.h>
132#include <limits.h>
133#include <netdb.h>
134#include <stdarg.h>
135#include <stddef.h>
136#include <stdio.h>
137#include <stdlib.h>
138#include <string.h>
139#include <sys/stat.h>
140#include <sys/types.h>
141#include <time.h>
142 
143#include <esp_ota_ops.h> // Use angle brackets to avoid
144#include <esp_timer.h> // amalgamation ditching them
145 
146#define MG_PATH_MAX 128
147 
148#endif
149 
150 
151#if MG_ARCH == MG_ARCH_ESP8266
152 
153#include <ctype.h>
154#include <dirent.h>
155#include <errno.h>
156#include <fcntl.h>
157#include <limits.h>
158#include <netdb.h>
159#include <stdarg.h>
160#include <stdbool.h>
161#include <stddef.h>
162#include <stdio.h>
163#include <stdlib.h>
164#include <string.h>
165#include <sys/stat.h>
166#include <sys/time.h>
167#include <sys/types.h>
168#include <time.h>
169 
170#include <esp_system.h>
171 
172#define MG_PATH_MAX 128
173 
174#endif
175 
176 
177#if MG_ARCH == MG_ARCH_FREERTOS
178 
179#include <ctype.h>
180#if !defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP
181#include <errno.h>
182#endif
183#include <stdarg.h>
184#include <stdbool.h>
185#include <stddef.h>
186#include <stdint.h>
187#include <stdio.h>
188#include <stdlib.h> // rand(), strtol(), atoi()
189#include <string.h>
190#if defined(__ARMCC_VERSION)
191#define mode_t size_t
192#include <alloca.h>
193#include <time.h>
194#elif defined(__CCRH__)
195#else
196#include <sys/stat.h>
197#endif
198 
199#include <FreeRTOS.h>
200#include <task.h>
201 
202#define calloc(a, b) mg_calloc(a, b)
203#define free(a) vPortFree(a)
204#define malloc(a) pvPortMalloc(a)
205#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
206 
207// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
208static inline void *mg_calloc(size_t cnt, size_t size) {
209 void *p = pvPortMalloc(cnt * size);
210 if (p != NULL) memset(p, 0, size * cnt);
211 return p;
212}
213 
214#define mkdir(a, b) mg_mkdir(a, b)
215static inline int mg_mkdir(const char *path, mode_t mode) {
216 (void) path, (void) mode;
217 return -1;
218}
219 
220#endif // MG_ARCH == MG_ARCH_FREERTOS
221 
222 
223#if MG_ARCH == MG_ARCH_NEWLIB
224#define _POSIX_TIMERS
225 
226#include <ctype.h>
227#include <errno.h>
228#include <stdarg.h>
229#include <stdbool.h>
230#include <stdio.h>
231#include <stdlib.h>
232#include <string.h>
233#include <sys/stat.h>
234#include <sys/time.h>
235#include <sys/types.h>
236#include <time.h>
237#include <unistd.h>
238 
239#define MG_PATH_MAX 100
240#define MG_ENABLE_SOCKET 0
241#define MG_ENABLE_DIRLIST 0
242 
243#endif
244 
245 
246#if MG_ARCH == MG_ARCH_PICOSDK
247#if !defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP
248#include <errno.h>
249#endif
250#include <stdarg.h>
251#include <stdbool.h>
252#include <stdint.h>
253#include <stdio.h>
254#include <stdlib.h>
255#include <string.h>
256#include <time.h>
257 
258#include <pico/stdlib.h>
259#include <pico/rand.h>
260int mkdir(const char *, mode_t);
261 
262#if MG_OTA == MG_OTA_PICOSDK
263#include <hardware/flash.h>
264#include <pico/bootrom.h>
265#endif
266 
267#endif
268 
269 
270#if MG_ARCH == MG_ARCH_RTTHREAD
271 
272#include <rtthread.h>
273#include <ctype.h>
274#include <errno.h>
275#include <fcntl.h>
276#include <sys/socket.h>
277#include <sys/select.h>
278#include <stdarg.h>
279#include <stdbool.h>
280#include <stdint.h>
281#include <stdio.h>
282#include <stdlib.h>
283#include <string.h>
284#include <sys/types.h>
285#include <time.h>
286 
287#ifndef MG_IO_SIZE
288#define MG_IO_SIZE 1460
289#endif
290 
291#endif // MG_ARCH == MG_ARCH_RTTHREAD
292 
293 
294#if MG_ARCH == MG_ARCH_ARMCC || MG_ARCH == MG_ARCH_CMSIS_RTOS1 || \
295 MG_ARCH == MG_ARCH_CMSIS_RTOS2
296 
297#include <ctype.h>
298#include <errno.h>
299#include <stdarg.h>
300#include <stdbool.h>
301#include <stddef.h>
302#include <stdint.h>
303#include <stdio.h>
304#include <stdlib.h>
305#include <alloca.h>
306#include <string.h>
307#include <time.h>
308#if MG_ARCH == MG_ARCH_CMSIS_RTOS1
309#include "cmsis_os.h" // keep this include
310// https://developer.arm.com/documentation/ka003821/latest
311extern uint32_t rt_time_get(void);
312#elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
313#include "cmsis_os2.h" // keep this include
314#endif
315 
316#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
317 
318#if defined(__ARMCC_VERSION)
319#define mode_t size_t
320#define mkdir(a, b) mg_mkdir(a, b)
321static inline int mg_mkdir(const char *path, mode_t mode) {
322 (void) path, (void) mode;
323 return -1;
324}
325#endif
326 
327#if (MG_ARCH == MG_ARCH_CMSIS_RTOS1 || MG_ARCH == MG_ARCH_CMSIS_RTOS2) && \
328 !defined MG_ENABLE_RL && (!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP) && \
329 (!defined(MG_ENABLE_TCPIP) || !MG_ENABLE_TCPIP)
330#define MG_ENABLE_RL 1
331#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
332#define MG_SOCK_LISTEN_BACKLOG_SIZE 3
333#endif
334#endif
335 
336#endif
337 
338 
339#if MG_ARCH == MG_ARCH_TIRTOS
340 
341#include <stdlib.h>
342#include <ctype.h>
343#include <stdarg.h>
344#include <stdbool.h>
345#include <stdint.h>
346#include <stdio.h>
347#include <string.h>
348#include <time.h>
349 
350#include <serrno.h>
351#include <sys/socket.h>
352 
353#include <ti/sysbios/knl/Clock.h>
354 
355#endif
356 
357 
358#if MG_ARCH == MG_ARCH_UNIX
359 
360#define _DARWIN_UNLIMITED_SELECT 1 // No limit on file descriptors
361 
362#if defined(__APPLE__)
363#include <mach/mach_time.h>
364#endif
365 
366#if !defined(MG_ENABLE_EPOLL) && defined(__linux__)
367#define MG_ENABLE_EPOLL 1
368#elif !defined(MG_ENABLE_POLL)
369#define MG_ENABLE_POLL 1
370#endif
371 
372#include <arpa/inet.h>
373#include <ctype.h>
374#include <dirent.h>
375#include <errno.h>
376#include <fcntl.h>
377#include <inttypes.h>
378#include <limits.h>
379#include <netdb.h>
380#include <netinet/in.h>
381#include <netinet/tcp.h>
382#include <signal.h>
383#include <stdarg.h>
384#include <stdbool.h>
385#include <stddef.h>
386#include <stdint.h>
387#include <stdio.h>
388#include <stdlib.h>
389#include <string.h>
390 
391#if defined(MG_ENABLE_EPOLL) && MG_ENABLE_EPOLL
392#include <sys/epoll.h>
393#elif defined(MG_ENABLE_POLL) && MG_ENABLE_POLL
394#include <poll.h>
395#else
396#include <sys/select.h>
397#endif
398 
399#include <sys/socket.h>
400#include <sys/stat.h>
401#include <sys/time.h>
402#include <sys/types.h>
403#include <time.h>
404#include <unistd.h>
405 
406#ifndef MG_ENABLE_DIRLIST
407#define MG_ENABLE_DIRLIST 1
408#endif
409 
410#ifndef MG_PATH_MAX
411#define MG_PATH_MAX FILENAME_MAX
412#endif
413 
414#ifndef MG_ENABLE_POSIX_FS
415#define MG_ENABLE_POSIX_FS 1
416#endif
417 
418#ifndef MG_IO_SIZE
419#define MG_IO_SIZE 16384
420#endif
421 
422#endif
423 
424 
425#if MG_ARCH == MG_ARCH_WIN32
426 
427// Avoid name clashing; (macro expansion producing 'defined' has undefined
428// behaviour). See config.h for user options
429#ifndef MG_ENABLE_WINSOCK
430#if (!defined(MG_ENABLE_TCPIP) || !MG_ENABLE_TCPIP) && \
431 (!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP) && \
432 (!defined(MG_ENABLE_FREERTOS_TCP) || !MG_ENABLE_FREERTOS_TCP)
433#define MG_ENABLE_WINSOCK 1
434#else
435#define MG_ENABLE_WINSOCK 0
436#endif
437#endif
438 
439#ifndef _CRT_RAND_S
440#define _CRT_RAND_S
441#endif
442 
443#ifndef WIN32_LEAN_AND_MEAN
444#define WIN32_LEAN_AND_MEAN
445#endif
446 
447#ifndef _CRT_SECURE_NO_WARNINGS
448#define _CRT_SECURE_NO_WARNINGS
449#endif
450 
451#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
452#define _WINSOCK_DEPRECATED_NO_WARNINGS
453#endif
454 
455#include <ctype.h>
456#include <direct.h>
457#include <errno.h>
458#include <fcntl.h>
459#include <limits.h>
460#include <signal.h>
461#include <stdarg.h>
462#include <stddef.h>
463#include <stdio.h>
464#include <stdlib.h>
465#include <string.h>
466#include <sys/stat.h>
467#include <sys/types.h>
468#include <time.h>
469 
470#if defined(_MSC_VER) && _MSC_VER < 1700
471#define __func__ ""
472typedef __int64 int64_t;
473typedef unsigned __int64 uint64_t;
474typedef unsigned char uint8_t;
475typedef char int8_t;
476typedef unsigned short uint16_t;
477typedef short int16_t;
478typedef unsigned int uint32_t;
479typedef int int32_t;
480typedef enum { false = 0, true = 1 } bool;
481#else
482#include <stdbool.h>
483#include <stdint.h>
484#if MG_ENABLE_WINSOCK
485#include <ws2tcpip.h>
486#endif
487#endif
488 
489#include <process.h>
490#include <winerror.h>
491#include <winsock2.h> // fix missing macros and types
492 
493// For mg_random()
494#if defined(_MSC_VER) && _MSC_VER < 1700
495#ifndef _WIN32_WINNT
496#define _WIN32_WINNT 0x400 // Let vc98 pick up wincrypt.h
497#endif
498#include <wincrypt.h>
499#pragma comment(lib, "advapi32.lib")
500#endif
501 
502#if defined(_MSC_VER) && _MSC_VER <= 1200
503 #ifndef IPPROTO_IP
504 #define IPPROTO_IP 0
505 #endif
506 
507 #ifndef IP_ADD_MEMBERSHIP
508 struct ip_mreq {
509 struct in_addr imr_multiaddr;
510 struct in_addr imr_interface;
511 };
512 #define IP_ADD_MEMBERSHIP 12
513 #endif
514#endif
515 
516// Protect from calls like std::snprintf in app code
517// See https://github.com/cesanta/mongoose/issues/1047
518#ifndef __cplusplus
519#define snprintf _snprintf
520#define vsnprintf _vsnprintf
521#ifndef strdup // For MSVC with _DEBUG, see #1359
522#define strdup(x) _strdup(x)
523#endif
524#endif
525 
526typedef unsigned long nfds_t;
527#if defined(_MSC_VER)
528#if MG_ENABLE_WINSOCK
529#pragma comment(lib, "ws2_32.lib")
530#endif
531#ifndef alloca
532#define alloca(a) _alloca(a)
533#endif
534#endif
535 
536#define MG_DIRSEP '\\'
537 
538#ifndef MG_PATH_MAX
539#define MG_PATH_MAX FILENAME_MAX
540#endif
541 
542#if MG_ENABLE_WINSOCK
543 
544#define MG_INVALID_SOCKET INVALID_SOCKET
545#define MG_SOCKET_TYPE SOCKET
546#define poll(a, b, c) WSAPoll((a), (b), (c))
547#define closesocket(x) closesocket(x)
548typedef int socklen_t;
549 
550#ifndef SO_EXCLUSIVEADDRUSE
551#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
552#endif
553 
554#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? WSAGetLastError() : 0)
555 
556#define MG_SOCK_PENDING(errcode) \
557 (((errcode) < 0) && \
558 (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || \
559 WSAGetLastError() == WSAEWOULDBLOCK))
560 
561#define MG_SOCK_RESET(errcode) \
562 (((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET))
563 
564#endif // MG_ENABLE_WINSOCK
565 
566#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
567#define sleep(x) Sleep((x) *1000)
568#define mkdir(a, b) _mkdir(a)
569#define timegm(x) _mkgmtime(x)
570 
571#ifndef S_ISDIR
572#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
573#endif
574 
575#ifndef MG_ENABLE_DIRLIST
576#define MG_ENABLE_DIRLIST 1
577#endif
578 
579#ifndef SIGPIPE
580#define SIGPIPE 0
581#endif
582 
583#ifndef MG_ENABLE_POSIX_FS
584#define MG_ENABLE_POSIX_FS 1
585#endif
586 
587#ifndef MG_IO_SIZE
588#define MG_IO_SIZE 16384
589#endif
590 
591#endif
592 
593 
594#if MG_ARCH == MG_ARCH_ZEPHYR
595 
596#include <zephyr/kernel.h>
597 
598#include <ctype.h>
599#include <errno.h>
600#include <zephyr/net/socket.h>
601#include <zephyr/posix/fcntl.h>
602#include <zephyr/posix/sys/select.h>
603#include <stdarg.h>
604#include <stdbool.h>
605#include <stdint.h>
606#include <stdio.h>
607#include <stdlib.h>
608#include <string.h>
609#include <sys/types.h>
610#include <time.h>
611 
612#define MG_PUTCHAR(x) printk("%c", x)
613#ifndef strdup
614#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
615#endif
616#define strerror(x) zsock_gai_strerror(x)
617 
618#ifndef FD_CLOEXEC
619#define FD_CLOEXEC 0
620#endif
621 
622#ifndef F_SETFD
623#define F_SETFD 0
624#endif
625 
626#define MG_ENABLE_SSI 0
627 
628int rand(void);
629int sscanf(const char *, const char *, ...);
630 
631#endif
632 
633 
634#if defined(MG_ENABLE_FREERTOS_TCP) && MG_ENABLE_FREERTOS_TCP
635 
636#include <limits.h>
637#include <list.h>
638 
639#include <FreeRTOS_IP.h>
640#include <FreeRTOS_Sockets.h>
641 
642#define MG_SOCKET_TYPE Socket_t
643#define MG_INVALID_SOCKET FREERTOS_INVALID_SOCKET
644 
645// Why FreeRTOS-TCP did not implement a clean BSD API, but its own thing
646// with FreeRTOS_ prefix, is beyond me
647#define IPPROTO_TCP FREERTOS_IPPROTO_TCP
648#define IPPROTO_UDP FREERTOS_IPPROTO_UDP
649#define AF_INET FREERTOS_AF_INET
650#define SOCK_STREAM FREERTOS_SOCK_STREAM
651#define SOCK_DGRAM FREERTOS_SOCK_DGRAM
652#define SO_BROADCAST 0
653#define SO_ERROR 0
654#define SOL_SOCKET 0
655#define SO_REUSEADDR 0
656 
657#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0)
658 
659#define MG_SOCK_PENDING(errcode) \
660 ((errcode) == -pdFREERTOS_ERRNO_EWOULDBLOCK || \
661 (errcode) == -pdFREERTOS_ERRNO_EISCONN || \
662 (errcode) == -pdFREERTOS_ERRNO_EINPROGRESS || \
663 (errcode) == -pdFREERTOS_ERRNO_EAGAIN)
664 
665#define MG_SOCK_RESET(errcode) ((errcode) == -pdFREERTOS_ERRNO_ENOTCONN)
666 
667// actually only if optional timeout is enabled
668#define MG_SOCK_INTR(fd) (fd == NULL)
669 
670#define sockaddr_in freertos_sockaddr
671#define sockaddr freertos_sockaddr
672#if ipFR_TCP_VERSION_MAJOR >= 4
673#define sin_addr sin_address.ulIP_IPv4
674#endif
675#define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
676#define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
677#define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
678#define listen(a, b) FreeRTOS_listen((a), (b))
679#define socket(a, b, c) FreeRTOS_socket((a), (b), (c))
680#define send(a, b, c, d) FreeRTOS_send((a), (b), (c), (d))
681#define recv(a, b, c, d) FreeRTOS_recv((a), (b), (c), (d))
682#define setsockopt(a, b, c, d, e) FreeRTOS_setsockopt((a), (b), (c), (d), (e))
683#define sendto(a, b, c, d, e, f) FreeRTOS_sendto((a), (b), (c), (d), (e), (f))
684#define recvfrom(a, b, c, d, e, f) \
685 FreeRTOS_recvfrom((a), (b), (c), (d), (e), (f))
686#define closesocket(x) FreeRTOS_closesocket(x)
687#define gethostbyname(x) FreeRTOS_gethostbyname(x)
688#define getsockname(a, b, c) mg_getsockname((a), (b), (c))
689#define getpeername(a, b, c) mg_getpeername((a), (b), (c))
690 
691static inline int mg_getsockname(MG_SOCKET_TYPE fd, void *buf, socklen_t *len) {
692 (void) fd, (void) buf, (void) len;
693 return -1;
694}
695 
696static inline int mg_getpeername(MG_SOCKET_TYPE fd, void *buf, socklen_t *len) {
697 (void) fd, (void) buf, (void) len;
698 return 0;
699}
700#endif
701 
702 
703#if defined(MG_ENABLE_LWIP) && MG_ENABLE_LWIP
704 
705#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
706#include <sys/stat.h>
707#endif
708 
709struct timeval;
710 
711#include <lwip/sockets.h>
712 
713#if !LWIP_TIMEVAL_PRIVATE
714#if defined(__GNUC__) && !defined(__ARMCC_VERSION) // armclang sets both
715#include <sys/time.h>
716#else
717struct timeval {
718 time_t tv_sec;
719 long tv_usec;
720};
721#endif
722#endif
723 
724#if LWIP_SOCKET != 1
725// Sockets support disabled in LWIP by default
726#error Set LWIP_SOCKET variable to 1 (in lwipopts.h)
727#endif
728#endif
729 
730 
731#if defined(MG_ENABLE_RL) && MG_ENABLE_RL
732#include <rl_net.h>
733 
734#define closesocket(x) closesocket(x)
735 
736#define TCP_NODELAY SO_KEEPALIVE
737 
738#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0)
739 
740#define MG_SOCK_PENDING(errcode) \
741 ((errcode) == BSD_EWOULDBLOCK || (errcode) == BSD_EALREADY || \
742 (errcode) == BSD_EINPROGRESS)
743 
744#define MG_SOCK_RESET(errcode) \
745 ((errcode) == BSD_ECONNABORTED || (errcode) == BSD_ECONNRESET)
746 
747// In blocking mode, which is enabled by default, accept() waits for a
748// connection request. In non blocking mode, you must call accept()
749// again if the error code BSD_EWOULDBLOCK is returned.
750#define MG_SOCK_INTR(fd) (fd == BSD_EWOULDBLOCK)
751 
752#define socklen_t int
753#endif
754 
755 
756#ifndef MG_ENABLE_LOG
757#define MG_ENABLE_LOG 1
758#endif
759 
760#ifndef MG_ENABLE_CUSTOM_LOG
761#define MG_ENABLE_CUSTOM_LOG 0 // Let user define their own MG_LOG
762#endif
763 
764#ifndef MG_ENABLE_TCPIP
765#define MG_ENABLE_TCPIP 0 // Mongoose built-in network stack
766#endif
767 
768#ifndef MG_ENABLE_LWIP
769#define MG_ENABLE_LWIP 0 // lWIP network stack
770#endif
771 
772#ifndef MG_ENABLE_FREERTOS_TCP
773#define MG_ENABLE_FREERTOS_TCP 0 // Amazon FreeRTOS-TCP network stack
774#endif
775 
776#ifndef MG_ENABLE_RL
777#define MG_ENABLE_RL 0 // ARM MDK network stack
778#endif
779 
780#ifndef MG_ENABLE_SOCKET
781#define MG_ENABLE_SOCKET !MG_ENABLE_TCPIP
782#endif
783 
784#ifndef MG_ENABLE_POLL
785#define MG_ENABLE_POLL 0
786#endif
787 
788#ifndef MG_ENABLE_EPOLL
789#define MG_ENABLE_EPOLL 0
790#endif
791 
792#ifndef MG_ENABLE_FATFS
793#define MG_ENABLE_FATFS 0
794#endif
795 
796#ifndef MG_ENABLE_SSI
797#define MG_ENABLE_SSI 0
798#endif
799 
800#ifndef MG_ENABLE_IPV6
801#define MG_ENABLE_IPV6 0
802#endif
803 
804#ifndef MG_IPV6_V6ONLY
805#define MG_IPV6_V6ONLY 0 // IPv6 socket binds only to V6, not V4 address
806#endif
807 
808#ifndef MG_ENABLE_MD5
809#define MG_ENABLE_MD5 1
810#endif
811 
812// Set MG_ENABLE_WINSOCK=0 for Win32 builds with other external IP stack not
813// mentioned in arch_win32.h
814#ifndef MG_ENABLE_WINSOCK
815#define MG_ENABLE_WINSOCK 1
816#endif
817 
818#ifndef MG_ENABLE_DIRLIST
819#define MG_ENABLE_DIRLIST 0
820#endif
821 
822#ifndef MG_ENABLE_CUSTOM_RANDOM
823#define MG_ENABLE_CUSTOM_RANDOM 0
824#endif
825 
826#ifndef MG_ENABLE_CUSTOM_MILLIS
827#define MG_ENABLE_CUSTOM_MILLIS 0
828#endif
829 
830#ifndef MG_ENABLE_PACKED_FS
831#define MG_ENABLE_PACKED_FS 0
832#endif
833 
834#ifndef MG_ENABLE_ASSERT
835#define MG_ENABLE_ASSERT 0
836#endif
837 
838#ifndef MG_IO_SIZE
839#define MG_IO_SIZE 512 // Granularity of the send/recv IO buffer growth
840#endif
841 
842#ifndef MG_MAX_RECV_SIZE
843#define MG_MAX_RECV_SIZE (3UL * 1024UL * 1024UL) // Maximum recv IO buffer size
844#endif
845 
846#ifndef MG_DATA_SIZE
847#define MG_DATA_SIZE 32 // struct mg_connection :: data size
848#endif
849 
850#ifndef MG_MAX_HTTP_HEADERS
851#define MG_MAX_HTTP_HEADERS 30
852#endif
853 
854#ifndef MG_HTTP_INDEX
855#define MG_HTTP_INDEX "index.html"
856#endif
857 
858#ifndef MG_PATH_MAX
859#ifdef PATH_MAX
860#define MG_PATH_MAX PATH_MAX
861#else
862#define MG_PATH_MAX 128
863#endif
864#endif
865 
866#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
867#define MG_SOCK_LISTEN_BACKLOG_SIZE 128
868#endif
869 
870#ifndef MG_DIRSEP
871#define MG_DIRSEP '/'
872#endif
873 
874#ifndef MG_ENABLE_POSIX_FS
875#define MG_ENABLE_POSIX_FS 0
876#endif
877 
878#ifndef MG_INVALID_SOCKET
879#define MG_INVALID_SOCKET (-1)
880#endif
881 
882#ifndef MG_SOCKET_TYPE
883#define MG_SOCKET_TYPE int
884#endif
885 
886#ifndef MG_SOCKET_ERRNO
887#define MG_SOCKET_ERRNO errno
888#endif
889 
890#if MG_ENABLE_EPOLL
891#define MG_EPOLL_ADD(c) \
892 do { \
893 struct epoll_event ev = {EPOLLIN | EPOLLERR | EPOLLHUP, {c}}; \
894 epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_ADD, (int) (size_t) c->fd, &ev); \
895 } while (0)
896#define MG_EPOLL_MOD(c, wr) \
897 do { \
898 struct epoll_event ev = {EPOLLIN | EPOLLERR | EPOLLHUP, {c}}; \
899 if (wr) ev.events |= EPOLLOUT; \
900 epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_MOD, (int) (size_t) c->fd, &ev); \
901 } while (0)
902#else
903#define MG_EPOLL_ADD(c)
904#define MG_EPOLL_MOD(c, wr)
905#endif
906 
907#ifndef MG_ENABLE_PROFILE
908#define MG_ENABLE_PROFILE 0
909#endif
910 
911#ifndef MG_ENABLE_TCPIP_DRIVER_INIT // mg_mgr_init() will also initialize
912#define MG_ENABLE_TCPIP_DRIVER_INIT 1 // enabled built-in driver for
913#endif // Mongoose built-in network stack
914 
915#ifndef MG_TCPIP_IP // e.g. MG_IPV4(192, 168, 0, 223)
916#define MG_TCPIP_IP MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP)
917#endif
918 
919#ifndef MG_TCPIP_MASK
920#define MG_TCPIP_MASK MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP)
921#endif
922 
923#ifndef MG_TCPIP_GW
924#define MG_TCPIP_GW MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP)
925#endif
926 
927#ifndef MG_SET_MAC_ADDRESS
928#define MG_SET_MAC_ADDRESS(mac)
929#endif
930 
931#ifndef MG_SET_WIFI_CONFIG
932#define MG_SET_WIFI_CONFIG(data)
933#endif
934 
935#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
936#define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
937#endif
938 
939 
940 
941 
942// Describes an arbitrary chunk of memory
943struct mg_str {
944 char *buf; // String data
945 size_t len; // String length
946};
947 
948// Using macro to avoid shadowing C++ struct constructor, see #1298
949#define mg_str(s) mg_str_s(s)
950 
951struct mg_str mg_str(const char *s);
952struct mg_str mg_str_n(const char *s, size_t n);
953int mg_casecmp(const char *s1, const char *s2);
954int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
955int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2);
956struct mg_str mg_strdup(const struct mg_str s);
957bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps);
958bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char delim);
959 
960bool mg_str_to_num(struct mg_str, int base, void *val, size_t val_len);
961 
962 
963 
964 
965// Single producer, single consumer non-blocking queue
966 
967struct mg_queue {
968 char *buf;
969 size_t size;
970 volatile size_t tail;
971 volatile size_t head;
972};
973 
974void mg_queue_init(struct mg_queue *, char *, size_t); // Init queue
975size_t mg_queue_book(struct mg_queue *, char **buf, size_t); // Reserve space
976void mg_queue_add(struct mg_queue *, size_t); // Add new message
977size_t mg_queue_next(struct mg_queue *, char **); // Get oldest message
978void mg_queue_del(struct mg_queue *, size_t); // Delete oldest message
979 
980 
981 
982 
983typedef void (*mg_pfn_t)(char, void *); // Output function
984typedef size_t (*mg_pm_t)(mg_pfn_t, void *, va_list *); // %M printer
985 
986size_t mg_vxprintf(void (*)(char, void *), void *, const char *fmt, va_list *);
987size_t mg_xprintf(void (*fn)(char, void *), void *, const char *fmt, ...);
988 
989 
990 
991 
992 
993 
994// Convenience wrappers around mg_xprintf
995size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap);
996size_t mg_snprintf(char *, size_t, const char *fmt, ...);
997char *mg_vmprintf(const char *fmt, va_list *ap);
998char *mg_mprintf(const char *fmt, ...);
999size_t mg_queue_vprintf(struct mg_queue *, const char *fmt, va_list *);
1000size_t mg_queue_printf(struct mg_queue *, const char *fmt, ...);
1001 
1002// %M print helper functions
1003size_t mg_print_base64(void (*out)(char, void *), void *arg, va_list *ap);
1004size_t mg_print_esc(void (*out)(char, void *), void *arg, va_list *ap);
1005size_t mg_print_hex(void (*out)(char, void *), void *arg, va_list *ap);
1006size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap);
1007size_t mg_print_ip_port(void (*out)(char, void *), void *arg, va_list *ap);
1008size_t mg_print_ip4(void (*out)(char, void *), void *arg, va_list *ap);
1009size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap);
1010size_t mg_print_mac(void (*out)(char, void *), void *arg, va_list *ap);
1011 
1012// Various output functions
1013void mg_pfn_iobuf(char ch, void *param); // param: struct mg_iobuf *
1014void mg_pfn_stdout(char c, void *param); // param: ignored
1015 
1016// A helper macro for printing JSON: mg_snprintf(buf, len, "%m", MG_ESC("hi"))
1017#define MG_ESC(str) mg_print_esc, 0, (str)
1018 
1019 
1020 
1021 
1022 
1023 
1024enum { MG_LL_NONE, MG_LL_ERROR, MG_LL_INFO, MG_LL_DEBUG, MG_LL_VERBOSE };
1025extern int mg_log_level; // Current log level, one of MG_LL_*
1026 
1027void mg_log(const char *fmt, ...);
1028void mg_log_prefix(int ll, const char *file, int line, const char *fname);
1029// bool mg_log2(int ll, const char *file, int line, const char *fmt, ...);
1030void mg_hexdump(const void *buf, size_t len);
1031void mg_log_set_fn(mg_pfn_t fn, void *param);
1032 
1033#define mg_log_set(level_) mg_log_level = (level_)
1034 
1035#if MG_ENABLE_LOG
1036#define MG_LOG(level, args) \
1037 do { \
1038 if ((level) <= mg_log_level) { \
1039 mg_log_prefix((level), __FILE__, __LINE__, __func__); \
1040 mg_log args; \
1041 } \
1042 } while (0)
1043#else
1044#define MG_LOG(level, args) \
1045 do { \
1046 if (0) mg_log args; \
1047 } while (0)
1048#endif
1049 
1050#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
1051#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
1052#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
1053#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
1054 
1055 
1056 
1057 
1058struct mg_timer {
1059 uint64_t period_ms; // Timer period in milliseconds
1060 uint64_t expire; // Expiration timestamp in milliseconds
1061 unsigned flags; // Possible flags values below
1062#define MG_TIMER_ONCE 0 // Call function once
1063#define MG_TIMER_REPEAT 1 // Call function periodically
1064#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
1065#define MG_TIMER_CALLED 4 // Timer function was called at least once
1066#define MG_TIMER_AUTODELETE 8 // free() timer when done
1067 void (*fn)(void *); // Function to call
1068 void *arg; // Function argument
1069 struct mg_timer *next; // Linkage
1070};
1071 
1072void mg_timer_init(struct mg_timer **head, struct mg_timer *timer,
1073 uint64_t milliseconds, unsigned flags, void (*fn)(void *),
1074 void *arg);
1075void mg_timer_free(struct mg_timer **head, struct mg_timer *);
1076void mg_timer_poll(struct mg_timer **head, uint64_t new_ms);
1077bool mg_timer_expired(uint64_t *expiration, uint64_t period, uint64_t now);
1078 
1079 
1080 
1081 
1082 
1083enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };
1084 
1085// Filesystem API functions
1086// st() returns MG_FS_* flags and populates file size and modification time
1087// ls() calls fn() for every directory entry, allowing to list a directory
1088//
1089// NOTE: UNIX-style shorthand names for the API functions are deliberately
1090// chosen to avoid conflicts with some libraries that make macros for e.g.
1091// stat(), write(), read() calls.
1092struct mg_fs {
1093 int (*st)(const char *path, size_t *size, time_t *mtime); // stat file
1094 void (*ls)(const char *path, void (*fn)(const char *, void *),
1095 void *); // List directory entries: call fn(file_name, fn_data)
1096 // for each directory entry
1097 void *(*op)(const char *path, int flags); // Open file
1098 void (*cl)(void *fd); // Close file
1099 size_t (*rd)(void *fd, void *buf, size_t len); // Read file
1100 size_t (*wr)(void *fd, const void *buf, size_t len); // Write file
1101 size_t (*sk)(void *fd, size_t offset); // Set file position
1102 bool (*mv)(const char *from, const char *to); // Rename file
1103 bool (*rm)(const char *path); // Delete file
1104 bool (*mkd)(const char *path); // Create directory
1105};
1106 
1107extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
1108extern struct mg_fs mg_fs_packed; // see tutorials/core/embedded-filesystem
1109extern struct mg_fs mg_fs_fat; // FAT FS
1110 
1111// File descriptor
1112struct mg_fd {
1113 void *fd;
1114 struct mg_fs *fs;
1115};
1116 
1117struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags);
1118void mg_fs_close(struct mg_fd *fd);
1119bool mg_fs_ls(struct mg_fs *fs, const char *path, char *buf, size_t len);
1120struct mg_str mg_file_read(struct mg_fs *fs, const char *path);
1121bool mg_file_write(struct mg_fs *fs, const char *path, const void *, size_t);
1122bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...);
1123 
1124// Packed API
1125const char *mg_unpack(const char *path, size_t *size, time_t *mtime);
1126const char *mg_unlist(size_t no); // Get no'th packed filename
1127struct mg_str mg_unpacked(const char *path); // Packed file as mg_str
1128 
1129 
1130 
1131 
1132 
1133 
1134 
1135#if MG_ENABLE_ASSERT
1136#include <assert.h>
1137#elif !defined(assert)
1138#define assert(x)
1139#endif
1140 
1141void mg_bzero(volatile unsigned char *buf, size_t len);
1142bool mg_random(void *buf, size_t len);
1143char *mg_random_str(char *buf, size_t len);
1144uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
1145uint64_t mg_millis(void); // Return milliseconds since boot
1146bool mg_path_is_sane(const struct mg_str path);
1147void mg_delayms(unsigned int ms);
1148 
1149#define MG_U32(a, b, c, d) \
1150 (((uint32_t) ((a) &255) << 24) | ((uint32_t) ((b) &255) << 16) | \
1151 ((uint32_t) ((c) &255) << 8) | (uint32_t) ((d) &255))
1152 
1153#define MG_IPV4(a, b, c, d) mg_htonl(MG_U32(a, b, c, d))
1154 
1155// For printing IPv4 addresses: printf("%d.%d.%d.%d\n", MG_IPADDR_PARTS(&ip))
1156#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
1157#define MG_IPADDR_PARTS(ADDR) \
1158 MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3]
1159 
1160#define MG_LOAD_BE16(p) \
1161 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
1162#define MG_LOAD_BE24(p) \
1163 ((uint32_t) (((uint32_t) MG_U8P(p)[0] << 16U) | \
1164 ((uint32_t) MG_U8P(p)[1] << 8U) | MG_U8P(p)[2]))
1165#define MG_LOAD_BE32(p) \
1166 ((uint32_t) (((uint32_t) MG_U8P(p)[0] << 24U) | \
1167 ((uint32_t) MG_U8P(p)[1] << 16U) | \
1168 ((uint32_t) MG_U8P(p)[2] << 8U) | MG_U8P(p)[3]))
1169#define MG_STORE_BE16(p, n) \
1170 do { \
1171 MG_U8P(p)[0] = ((n) >> 8U) & 255; \
1172 MG_U8P(p)[1] = (n) &255; \
1173 } while (0)
1174#define MG_STORE_BE24(p, n) \
1175 do { \
1176 MG_U8P(p)[0] = ((n) >> 16U) & 255; \
1177 MG_U8P(p)[1] = ((n) >> 8U) & 255; \
1178 MG_U8P(p)[2] = (n) &255; \
1179 } while (0)
1180#define MG_STORE_BE32(p, n) \
1181 do { \
1182 MG_U8P(p)[0] = ((n) >> 24U) & 255; \
1183 MG_U8P(p)[1] = ((n) >> 16U) & 255; \
1184 MG_U8P(p)[2] = ((n) >> 8U) & 255; \
1185 MG_U8P(p)[3] = (n) &255; \
1186 } while (0)
1187 
1188uint16_t mg_ntohs(uint16_t net);
1189uint32_t mg_ntohl(uint32_t net);
1190#define mg_htons(x) mg_ntohs(x)
1191#define mg_htonl(x) mg_ntohl(x)
1192 
1193#define MG_REG(x) ((volatile uint32_t *) (x))[0]
1194#define MG_BIT(x) (((uint32_t) 1U) << (x))
1195#define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK)
1196 
1197#define MG_ROUND_UP(x, a) ((a) == 0 ? (x) : ((((x) + (a) -1) / (a)) * (a)))
1198#define MG_ROUND_DOWN(x, a) ((a) == 0 ? (x) : (((x) / (a)) * (a)))
1199 
1200#if defined(__GNUC__)
1201#define MG_ARM_DISABLE_IRQ() asm volatile("cpsid i" : : : "memory")
1202#define MG_ARM_ENABLE_IRQ() asm volatile("cpsie i" : : : "memory")
1203#elif defined(__CCRH__)
1204#define MG_RH850_DISABLE_IRQ() __DI()
1205#define MG_RH850_ENABLE_IRQ() __EI()
1206#else
1207#define MG_ARM_DISABLE_IRQ()
1208#define MG_ARM_ENABLE_IRQ()
1209#endif
1210 
1211#if defined(__CC_ARM)
1212#define MG_DSB() __dsb(0xf)
1213#elif defined(__ARMCC_VERSION)
1214#define MG_DSB() __builtin_arm_dsb(0xf)
1215#elif defined(__GNUC__) && defined(__arm__) && defined(__thumb__)
1216#define MG_DSB() asm("DSB 0xf")
1217#elif defined(__ICCARM__)
1218#define MG_DSB() __iar_builtin_DSB()
1219#else
1220#define MG_DSB()
1221#endif
1222 
1223struct mg_addr;
1224int mg_check_ip_acl(struct mg_str acl, struct mg_addr *remote_ip);
1225 
1226// Linked list management macros
1227#define LIST_ADD_HEAD(type_, head_, elem_) \
1228 do { \
1229 (elem_)->next = (*head_); \
1230 *(head_) = (elem_); \
1231 } while (0)
1232 
1233#define LIST_ADD_TAIL(type_, head_, elem_) \
1234 do { \
1235 type_ **h = head_; \
1236 while (*h != NULL) h = &(*h)->next; \
1237 *h = (elem_); \
1238 } while (0)
1239 
1240#define LIST_DELETE(type_, head_, elem_) \
1241 do { \
1242 type_ **h = head_; \
1243 while (*h != (elem_)) h = &(*h)->next; \
1244 *h = (elem_)->next; \
1245 } while (0)
1246 
1247 
1248 
1249unsigned short mg_url_port(const char *url);
1250int mg_url_is_ssl(const char *url);
1251struct mg_str mg_url_host(const char *url);
1252struct mg_str mg_url_user(const char *url);
1253struct mg_str mg_url_pass(const char *url);
1254const char *mg_url_uri(const char *url);
1255 
1256 
1257 
1258 
1259struct mg_iobuf {
1260 unsigned char *buf; // Pointer to stored data
1261 size_t size; // Total size available
1262 size_t len; // Current number of bytes
1263 size_t align; // Alignment during allocation
1264};
1265 
1266int mg_iobuf_init(struct mg_iobuf *, size_t, size_t);
1267int mg_iobuf_resize(struct mg_iobuf *, size_t);
1268void mg_iobuf_free(struct mg_iobuf *);
1269size_t mg_iobuf_add(struct mg_iobuf *, size_t, const void *, size_t);
1270size_t mg_iobuf_del(struct mg_iobuf *, size_t ofs, size_t len);
1271 
1272 
1273size_t mg_base64_update(unsigned char input_byte, char *buf, size_t len);
1274size_t mg_base64_final(char *buf, size_t len);
1275size_t mg_base64_encode(const unsigned char *p, size_t n, char *buf, size_t);
1276size_t mg_base64_decode(const char *src, size_t n, char *dst, size_t);
1277 
1278 
1279 
1280 
1281typedef struct {
1282 uint32_t buf[4];
1283 uint32_t bits[2];
1284 unsigned char in[64];
1285} mg_md5_ctx;
1286 
1287void mg_md5_init(mg_md5_ctx *c);
1288void mg_md5_update(mg_md5_ctx *c, const unsigned char *data, size_t len);
1289void mg_md5_final(mg_md5_ctx *c, unsigned char[16]);
1290 
1291 
1292 
1293 
1294typedef struct {
1295 uint32_t state[5];
1296 uint32_t count[2];
1297 unsigned char buffer[64];
1298} mg_sha1_ctx;
1299 
1300void mg_sha1_init(mg_sha1_ctx *);
1301void mg_sha1_update(mg_sha1_ctx *, const unsigned char *data, size_t len);
1302void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *);
1303// https://github.com/B-Con/crypto-algorithms
1304// Author: Brad Conte (brad AT bradconte.com)
1305// Disclaimer: This code is presented "as is" without any guarantees.
1306// Details: Defines the API for the corresponding SHA1 implementation.
1307// Copyright: public domain
1308 
1309 
1310 
1311 
1312 
1313typedef struct {
1314 uint32_t state[8];
1315 uint64_t bits;
1316 uint32_t len;
1317 unsigned char buffer[64];
1318} mg_sha256_ctx;
1319 
1320 
1321void mg_sha256_init(mg_sha256_ctx *);
1322void mg_sha256_update(mg_sha256_ctx *, const unsigned char *data, size_t len);
1323void mg_sha256_final(unsigned char digest[32], mg_sha256_ctx *);
1324void mg_sha256(uint8_t dst[32], uint8_t *data, size_t datasz);
1325void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
1326 size_t datasz);
1327 
1328typedef struct {
1329 uint64_t state[8];
1330 uint8_t buffer[128];
1331 uint64_t bitlen[2];
1332 uint32_t datalen;
1333} mg_sha384_ctx;
1334void mg_sha384_init(mg_sha384_ctx *ctx);
1335void mg_sha384_update(mg_sha384_ctx *ctx, const uint8_t *data, size_t len);
1336void mg_sha384_final(uint8_t digest[48], mg_sha384_ctx *ctx);
1337void mg_sha384(uint8_t dst[48], uint8_t *data, size_t datasz);
1338 
1339#ifndef TLS_X15519_H
1340#define TLS_X15519_H
1341 
1342 
1343 
1344#define X25519_BYTES 32
1345extern const uint8_t X25519_BASE_POINT[X25519_BYTES];
1346 
1347int mg_tls_x25519(uint8_t out[X25519_BYTES], const uint8_t scalar[X25519_BYTES],
1348 const uint8_t x1[X25519_BYTES], int clamp);
1349 
1350 
1351#endif /* TLS_X15519_H */
1352/******************************************************************************
1353 *
1354 * THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
1355 *
1356 * This is a simple and straightforward implementation of AES-GCM authenticated
1357 * encryption. The focus of this work was correctness & accuracy. It is written
1358 * in straight 'C' without any particular focus upon optimization or speed. It
1359 * should be endian (memory byte order) neutral since the few places that care
1360 * are handled explicitly.
1361 *
1362 * This implementation of AES-GCM was created by Steven M. Gibson of GRC.com.
1363 *
1364 * It is intended for general purpose use, but was written in support of GRC's
1365 * reference implementation of the SQRL (Secure Quick Reliable Login) client.
1366 *
1367 * See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
1368 * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ \
1369 * gcm/gcm-revised-spec.pdf
1370 *
1371 * NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
1372 * REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
1373 *
1374 *******************************************************************************/
1375#ifndef TLS_AES128_H
1376#define TLS_AES128_H
1377 
1378/******************************************************************************
1379 * AES_CONTEXT : cipher context / holds inter-call data
1380 ******************************************************************************/
1381typedef struct {
1382 int mode; // 1 for Encryption, 0 for Decryption
1383 int rounds; // keysize-based rounds count
1384 uint32_t *rk; // pointer to current round key
1385 uint32_t buf[68]; // key expansion buffer
1386} aes_context;
1387 
1388 
1389#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
1390 
1391/******************************************************************************
1392 * GCM_CONTEXT : MUST be called once before ANY use of this library
1393 ******************************************************************************/
1394int mg_gcm_initialize(void);
1395 
1396//
1397// aes-gcm.h
1398// MKo
1399//
1400// Created by Markus Kosmal on 20/11/14.
1401//
1402//
1403int mg_aes_gcm_encrypt(unsigned char *output, const unsigned char *input,
1404 size_t input_length, const unsigned char *key,
1405 const size_t key_len, const unsigned char *iv,
1406 const size_t iv_len, unsigned char *aead,
1407 size_t aead_len, unsigned char *tag,
1408 const size_t tag_len);
1409 
1410int mg_aes_gcm_decrypt(unsigned char *output, const unsigned char *input,
1411 size_t input_length, const unsigned char *key,
1412 const size_t key_len, const unsigned char *iv,
1413 const size_t iv_len);
1414 
1415#endif /* TLS_AES128_H */
1416 
1417// End of aes128 PD
1418 
1419 
1420 
1421#define MG_UECC_SUPPORTS_secp256r1 1
1422/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1423 
1424#ifndef _UECC_H_
1425#define _UECC_H_
1426 
1427/* Platform selection options.
1428If MG_UECC_PLATFORM is not defined, the code will try to guess it based on
1429compiler macros. Possible values for MG_UECC_PLATFORM are defined below: */
1430#define mg_uecc_arch_other 0
1431#define mg_uecc_x86 1
1432#define mg_uecc_x86_64 2
1433#define mg_uecc_arm 3
1434#define mg_uecc_arm_thumb 4
1435#define mg_uecc_arm_thumb2 5
1436#define mg_uecc_arm64 6
1437#define mg_uecc_avr 7
1438 
1439/* If desired, you can define MG_UECC_WORD_SIZE as appropriate for your platform
1440(1, 4, or 8 bytes). If MG_UECC_WORD_SIZE is not explicitly defined then it will
1441be automatically set based on your platform. */
1442 
1443/* Optimization level; trade speed for code size.
1444 Larger values produce code that is faster but larger.
1445 Currently supported values are 0 - 4; 0 is unusably slow for most
1446 applications. Optimization level 4 currently only has an effect ARM platforms
1447 where more than one curve is enabled. */
1448#ifndef MG_UECC_OPTIMIZATION_LEVEL
1449#define MG_UECC_OPTIMIZATION_LEVEL 2
1450#endif
1451 
1452/* MG_UECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a
1453specific function to be used for (scalar) squaring instead of the generic
1454multiplication function. This can make things faster somewhat faster, but
1455increases the code size. */
1456#ifndef MG_UECC_SQUARE_FUNC
1457#define MG_UECC_SQUARE_FUNC 0
1458#endif
1459 
1460/* MG_UECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will
1461switch to native little-endian format for *all* arrays passed in and out of the
1462public API. This includes public and private keys, shared secrets, signatures
1463and message hashes. Using this switch reduces the amount of call stack memory
1464used by uECC, since less intermediate translations are required. Note that this
1465will *only* work on native little-endian processors and it will treat the
1466uint8_t arrays passed into the public API as word arrays, therefore requiring
1467the provided byte arrays to be word aligned on architectures that do not support
1468unaligned accesses. IMPORTANT: Keys and signatures generated with
1469MG_UECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible with keys and signatures
1470generated with MG_UECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use the same
1471endianness. */
1472#ifndef MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
1473#define MG_UECC_VLI_NATIVE_LITTLE_ENDIAN 0
1474#endif
1475 
1476/* Curve support selection. Set to 0 to remove that curve. */
1477#ifndef MG_UECC_SUPPORTS_secp160r1
1478#define MG_UECC_SUPPORTS_secp160r1 0
1479#endif
1480#ifndef MG_UECC_SUPPORTS_secp192r1
1481#define MG_UECC_SUPPORTS_secp192r1 0
1482#endif
1483#ifndef MG_UECC_SUPPORTS_secp224r1
1484#define MG_UECC_SUPPORTS_secp224r1 0
1485#endif
1486#ifndef MG_UECC_SUPPORTS_secp256r1
1487#define MG_UECC_SUPPORTS_secp256r1 1
1488#endif
1489#ifndef MG_UECC_SUPPORTS_secp256k1
1490#define MG_UECC_SUPPORTS_secp256k1 0
1491#endif
1492 
1493/* Specifies whether compressed point format is supported.
1494 Set to 0 to disable point compression/decompression functions. */
1495#ifndef MG_UECC_SUPPORT_COMPRESSED_POINT
1496#define MG_UECC_SUPPORT_COMPRESSED_POINT 1
1497#endif
1498 
1499struct MG_UECC_Curve_t;
1500typedef const struct MG_UECC_Curve_t *MG_UECC_Curve;
1501 
1502#ifdef __cplusplus
1503extern "C" {
1504#endif
1505 
1506#if MG_UECC_SUPPORTS_secp160r1
1507MG_UECC_Curve mg_uecc_secp160r1(void);
1508#endif
1509#if MG_UECC_SUPPORTS_secp192r1
1510MG_UECC_Curve mg_uecc_secp192r1(void);
1511#endif
1512#if MG_UECC_SUPPORTS_secp224r1
1513MG_UECC_Curve mg_uecc_secp224r1(void);
1514#endif
1515#if MG_UECC_SUPPORTS_secp256r1
1516MG_UECC_Curve mg_uecc_secp256r1(void);
1517#endif
1518#if MG_UECC_SUPPORTS_secp256k1
1519MG_UECC_Curve mg_uecc_secp256k1(void);
1520#endif
1521 
1522/* MG_UECC_RNG_Function type
1523The RNG function should fill 'size' random bytes into 'dest'. It should return 1
1524if 'dest' was filled with random data, or 0 if the random data could not be
1525generated. The filled-in values should be either truly random, or from a
1526cryptographically-secure PRNG.
1527 
1528A correctly functioning RNG function must be set (using mg_uecc_set_rng())
1529before calling mg_uecc_make_key() or mg_uecc_sign().
1530 
1531Setting a correctly functioning RNG function improves the resistance to
1532side-channel attacks for mg_uecc_shared_secret() and
1533mg_uecc_sign_deterministic().
1534 
1535A correct RNG function is set by default when building for Windows, Linux, or OS
1536X. If you are building on another POSIX-compliant system that supports
1537/dev/random or /dev/urandom, you can define MG_UECC_POSIX to use the predefined
1538RNG. For embedded platforms there is no predefined RNG function; you must
1539provide your own.
1540*/
1541typedef int (*MG_UECC_RNG_Function)(uint8_t *dest, unsigned size);
1542 
1543/* mg_uecc_set_rng() function.
1544Set the function that will be used to generate random bytes. The RNG function
1545should return 1 if the random data was generated, or 0 if the random data could
1546not be generated.
1547 
1548On platforms where there is no predefined RNG function (eg embedded platforms),
1549this must be called before mg_uecc_make_key() or mg_uecc_sign() are used.
1550 
1551Inputs:
1552 rng_function - The function that will be used to generate random bytes.
1553*/
1554void mg_uecc_set_rng(MG_UECC_RNG_Function rng_function);
1555 
1556/* mg_uecc_get_rng() function.
1557 
1558Returns the function that will be used to generate random bytes.
1559*/
1560MG_UECC_RNG_Function mg_uecc_get_rng(void);
1561 
1562/* mg_uecc_curve_private_key_size() function.
1563 
1564Returns the size of a private key for the curve in bytes.
1565*/
1566int mg_uecc_curve_private_key_size(MG_UECC_Curve curve);
1567 
1568/* mg_uecc_curve_public_key_size() function.
1569 
1570Returns the size of a public key for the curve in bytes.
1571*/
1572int mg_uecc_curve_public_key_size(MG_UECC_Curve curve);
1573 
1574/* mg_uecc_make_key() function.
1575Create a public/private key pair.
1576 
1577Outputs:
1578 public_key - Will be filled in with the public key. Must be at least 2 *
1579the curve size (in bytes) long. For example, if the curve is secp256r1,
1580public_key must be 64 bytes long. private_key - Will be filled in with the
1581private key. Must be as long as the curve order; this is typically the same as
1582the curve size, except for secp160r1. For example, if the curve is secp256r1,
1583private_key must be 32 bytes long.
1584 
1585 For secp160r1, private_key must be 21 bytes long! Note that
1586the first byte will almost always be 0 (there is about a 1 in 2^80 chance of it
1587being non-zero).
1588 
1589Returns 1 if the key pair was generated successfully, 0 if an error occurred.
1590*/
1591int mg_uecc_make_key(uint8_t *public_key, uint8_t *private_key,
1592 MG_UECC_Curve curve);
1593 
1594/* mg_uecc_shared_secret() function.
1595Compute a shared secret given your secret key and someone else's public key. If
1596the public key is not from a trusted source and has not been previously
1597verified, you should verify it first using mg_uecc_valid_public_key(). Note: It
1598is recommended that you hash the result of mg_uecc_shared_secret() before using
1599it for symmetric encryption or HMAC.
1600 
1601Inputs:
1602 public_key - The public key of the remote party.
1603 private_key - Your private key.
1604 
1605Outputs:
1606 secret - Will be filled in with the shared secret value. Must be the same
1607size as the curve size; for example, if the curve is secp256r1, secret must be
160832 bytes long.
1609 
1610Returns 1 if the shared secret was generated successfully, 0 if an error
1611occurred.
1612*/
1613int mg_uecc_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
1614 uint8_t *secret, MG_UECC_Curve curve);
1615 
1616#if MG_UECC_SUPPORT_COMPRESSED_POINT
1617/* mg_uecc_compress() function.
1618Compress a public key.
1619 
1620Inputs:
1621 public_key - The public key to compress.
1622 
1623Outputs:
1624 compressed - Will be filled in with the compressed public key. Must be at
1625least (curve size + 1) bytes long; for example, if the curve is secp256r1,
1626 compressed must be 33 bytes long.
1627*/
1628void mg_uecc_compress(const uint8_t *public_key, uint8_t *compressed,
1629 MG_UECC_Curve curve);
1630 
1631/* mg_uecc_decompress() function.
1632Decompress a compressed public key.
1633 
1634Inputs:
1635 compressed - The compressed public key.
1636 
1637Outputs:
1638 public_key - Will be filled in with the decompressed public key.
1639*/
1640void mg_uecc_decompress(const uint8_t *compressed, uint8_t *public_key,
1641 MG_UECC_Curve curve);
1642#endif /* MG_UECC_SUPPORT_COMPRESSED_POINT */
1643 
1644/* mg_uecc_valid_public_key() function.
1645Check to see if a public key is valid.
1646 
1647Note that you are not required to check for a valid public key before using any
1648other uECC functions. However, you may wish to avoid spending CPU time computing
1649a shared secret or verifying a signature using an invalid public key.
1650 
1651Inputs:
1652 public_key - The public key to check.
1653 
1654Returns 1 if the public key is valid, 0 if it is invalid.
1655*/
1656int mg_uecc_valid_public_key(const uint8_t *public_key, MG_UECC_Curve curve);
1657 
1658/* mg_uecc_compute_public_key() function.
1659Compute the corresponding public key for a private key.
1660 
1661Inputs:
1662 private_key - The private key to compute the public key for
1663 
1664Outputs:
1665 public_key - Will be filled in with the corresponding public key
1666 
1667Returns 1 if the key was computed successfully, 0 if an error occurred.
1668*/
1669int mg_uecc_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
1670 MG_UECC_Curve curve);
1671 
1672/* mg_uecc_sign() function.
1673Generate an ECDSA signature for a given hash value.
1674 
1675Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and
1676pass it in to this function along with your private key.
1677 
1678Inputs:
1679 private_key - Your private key.
1680 message_hash - The hash of the message to sign.
1681 hash_size - The size of message_hash in bytes.
1682 
1683Outputs:
1684 signature - Will be filled in with the signature value. Must be at least 2 *
1685curve size long. For example, if the curve is secp256r1, signature must be 64
1686bytes long.
1687 
1688Returns 1 if the signature generated successfully, 0 if an error occurred.
1689*/
1690int mg_uecc_sign(const uint8_t *private_key, const uint8_t *message_hash,
1691 unsigned hash_size, uint8_t *signature, MG_UECC_Curve curve);
1692 
1693/* MG_UECC_HashContext structure.
1694This is used to pass in an arbitrary hash function to
1695mg_uecc_sign_deterministic(). The structure will be used for multiple hash
1696computations; each time a new hash is computed, init_hash() will be called,
1697followed by one or more calls to update_hash(), and finally a call to
1698finish_hash() to produce the resulting hash.
1699 
1700The intention is that you will create a structure that includes
1701MG_UECC_HashContext followed by any hash-specific data. For example:
1702 
1703typedef struct SHA256_HashContext {
1704 MG_UECC_HashContext uECC;
1705 SHA256_CTX ctx;
1706} SHA256_HashContext;
1707 
1708void init_SHA256(MG_UECC_HashContext *base) {
1709 SHA256_HashContext *context = (SHA256_HashContext *)base;
1710 SHA256_Init(&context->ctx);
1711}
1712 
1713void update_SHA256(MG_UECC_HashContext *base,
1714 const uint8_t *message,
1715 unsigned message_size) {
1716 SHA256_HashContext *context = (SHA256_HashContext *)base;
1717 SHA256_Update(&context->ctx, message, message_size);
1718}
1719 
1720void finish_SHA256(MG_UECC_HashContext *base, uint8_t *hash_result) {
1721 SHA256_HashContext *context = (SHA256_HashContext *)base;
1722 SHA256_Final(hash_result, &context->ctx);
1723}
1724 
1725... when signing ...
1726{
1727 uint8_t tmp[32 + 32 + 64];
1728 SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64,
172932, tmp}}; mg_uecc_sign_deterministic(key, message_hash, &ctx.uECC, signature);
1730}
1731*/
1732typedef struct MG_UECC_HashContext {
1733 void (*init_hash)(const struct MG_UECC_HashContext *context);
1734 void (*update_hash)(const struct MG_UECC_HashContext *context,
1735 const uint8_t *message, unsigned message_size);
1736 void (*finish_hash)(const struct MG_UECC_HashContext *context,
1737 uint8_t *hash_result);
1738 unsigned
1739 block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
1740 unsigned
1741 result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
1742 uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size +
1743 block_size) bytes. */
1744} MG_UECC_HashContext;
1745 
1746/* mg_uecc_sign_deterministic() function.
1747Generate an ECDSA signature for a given hash value, using a deterministic
1748algorithm (see RFC 6979). You do not need to set the RNG using mg_uecc_set_rng()
1749before calling this function; however, if the RNG is defined it will improve
1750resistance to side-channel attacks.
1751 
1752Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and
1753pass it to this function along with your private key and a hash context. Note
1754that the message_hash does not need to be computed with the same hash function
1755used by hash_context.
1756 
1757Inputs:
1758 private_key - Your private key.
1759 message_hash - The hash of the message to sign.
1760 hash_size - The size of message_hash in bytes.
1761 hash_context - A hash context to use.
1762 
1763Outputs:
1764 signature - Will be filled in with the signature value.
1765 
1766Returns 1 if the signature generated successfully, 0 if an error occurred.
1767*/
1768int mg_uecc_sign_deterministic(const uint8_t *private_key,
1769 const uint8_t *message_hash, unsigned hash_size,
1770 const MG_UECC_HashContext *hash_context,
1771 uint8_t *signature, MG_UECC_Curve curve);
1772 
1773/* mg_uecc_verify() function.
1774Verify an ECDSA signature.
1775 
1776Usage: Compute the hash of the signed data using the same hash as the signer and
1777pass it to this function along with the signer's public key and the signature
1778values (r and s).
1779 
1780Inputs:
1781 public_key - The signer's public key.
1782 message_hash - The hash of the signed data.
1783 hash_size - The size of message_hash in bytes.
1784 signature - The signature value.
1785 
1786Returns 1 if the signature is valid, 0 if it is invalid.
1787*/
1788int mg_uecc_verify(const uint8_t *public_key, const uint8_t *message_hash,
1789 unsigned hash_size, const uint8_t *signature,
1790 MG_UECC_Curve curve);
1791 
1792#ifdef __cplusplus
1793} /* end of extern "C" */
1794#endif
1795 
1796#endif /* _UECC_H_ */
1797 
1798/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1799 
1800#ifndef _UECC_TYPES_H_
1801#define _UECC_TYPES_H_
1802 
1803#ifndef MG_UECC_PLATFORM
1804#if defined(__AVR__) && __AVR__
1805#define MG_UECC_PLATFORM mg_uecc_avr
1806#elif defined(__thumb2__) || \
1807 defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */
1808#define MG_UECC_PLATFORM mg_uecc_arm_thumb2
1809#elif defined(__thumb__)
1810#define MG_UECC_PLATFORM mg_uecc_arm_thumb
1811#elif defined(__arm__) || defined(_M_ARM)
1812#define MG_UECC_PLATFORM mg_uecc_arm
1813#elif defined(__aarch64__)
1814#define MG_UECC_PLATFORM mg_uecc_arm64
1815#elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || \
1816 defined(__I86__)
1817#define MG_UECC_PLATFORM mg_uecc_x86
1818#elif defined(__amd64__) || defined(_M_X64)
1819#define MG_UECC_PLATFORM mg_uecc_x86_64
1820#else
1821#define MG_UECC_PLATFORM mg_uecc_arch_other
1822#endif
1823#endif
1824 
1825#ifndef MG_UECC_ARM_USE_UMAAL
1826#if (MG_UECC_PLATFORM == mg_uecc_arm) && (__ARM_ARCH >= 6)
1827#define MG_UECC_ARM_USE_UMAAL 1
1828#elif (MG_UECC_PLATFORM == mg_uecc_arm_thumb2) && (__ARM_ARCH >= 6) && \
1829 (!defined(__ARM_ARCH_7M__) || !__ARM_ARCH_7M__)
1830#define MG_UECC_ARM_USE_UMAAL 1
1831#else
1832#define MG_UECC_ARM_USE_UMAAL 0
1833#endif
1834#endif
1835 
1836#ifndef MG_UECC_WORD_SIZE
1837#if MG_UECC_PLATFORM == mg_uecc_avr
1838#define MG_UECC_WORD_SIZE 1
1839#elif (MG_UECC_PLATFORM == mg_uecc_x86_64 || MG_UECC_PLATFORM == mg_uecc_arm64)
1840#define MG_UECC_WORD_SIZE 8
1841#else
1842#define MG_UECC_WORD_SIZE 4
1843#endif
1844#endif
1845 
1846#if (MG_UECC_WORD_SIZE != 1) && (MG_UECC_WORD_SIZE != 4) && \
1847 (MG_UECC_WORD_SIZE != 8)
1848#error "Unsupported value for MG_UECC_WORD_SIZE"
1849#endif
1850 
1851#if ((MG_UECC_PLATFORM == mg_uecc_avr) && (MG_UECC_WORD_SIZE != 1))
1852#pragma message("MG_UECC_WORD_SIZE must be 1 for AVR")
1853#undef MG_UECC_WORD_SIZE
1854#define MG_UECC_WORD_SIZE 1
1855#endif
1856 
1857#if ((MG_UECC_PLATFORM == mg_uecc_arm || \
1858 MG_UECC_PLATFORM == mg_uecc_arm_thumb || \
1859 MG_UECC_PLATFORM == mg_uecc_arm_thumb2) && \
1860 (MG_UECC_WORD_SIZE != 4))
1861#pragma message("MG_UECC_WORD_SIZE must be 4 for ARM")
1862#undef MG_UECC_WORD_SIZE
1863#define MG_UECC_WORD_SIZE 4
1864#endif
1865 
1866typedef int8_t wordcount_t;
1867typedef int16_t bitcount_t;
1868typedef int8_t cmpresult_t;
1869 
1870#if (MG_UECC_WORD_SIZE == 1)
1871 
1872typedef uint8_t mg_uecc_word_t;
1873typedef uint16_t mg_uecc_dword_t;
1874 
1875#define HIGH_BIT_SET 0x80
1876#define MG_UECC_WORD_BITS 8
1877#define MG_UECC_WORD_BITS_SHIFT 3
1878#define MG_UECC_WORD_BITS_MASK 0x07
1879 
1880#elif (MG_UECC_WORD_SIZE == 4)
1881 
1882typedef uint32_t mg_uecc_word_t;
1883typedef uint64_t mg_uecc_dword_t;
1884 
1885#define HIGH_BIT_SET 0x80000000
1886#define MG_UECC_WORD_BITS 32
1887#define MG_UECC_WORD_BITS_SHIFT 5
1888#define MG_UECC_WORD_BITS_MASK 0x01F
1889 
1890#elif (MG_UECC_WORD_SIZE == 8)
1891 
1892typedef uint64_t mg_uecc_word_t;
1893 
1894#define HIGH_BIT_SET 0x8000000000000000U
1895#define MG_UECC_WORD_BITS 64
1896#define MG_UECC_WORD_BITS_SHIFT 6
1897#define MG_UECC_WORD_BITS_MASK 0x03F
1898 
1899#endif /* MG_UECC_WORD_SIZE */
1900 
1901#endif /* _UECC_TYPES_H_ */
1902 
1903/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1904 
1905#ifndef _UECC_VLI_H_
1906#define _UECC_VLI_H_
1907 
1908//
1909//
1910 
1911/* Functions for raw large-integer manipulation. These are only available
1912 if uECC.c is compiled with MG_UECC_ENABLE_VLI_API defined to 1. */
1913#ifndef MG_UECC_ENABLE_VLI_API
1914#define MG_UECC_ENABLE_VLI_API 0
1915#endif
1916 
1917#ifdef __cplusplus
1918extern "C" {
1919#endif
1920 
1921#if MG_UECC_ENABLE_VLI_API
1922 
1923void mg_uecc_vli_clear(mg_uecc_word_t *vli, wordcount_t num_words);
1924 
1925/* Constant-time comparison to zero - secure way to compare long integers */
1926/* Returns 1 if vli == 0, 0 otherwise. */
1927mg_uecc_word_t mg_uecc_vli_isZero(const mg_uecc_word_t *vli,
1928 wordcount_t num_words);
1929 
1930/* Returns nonzero if bit 'bit' of vli is set. */
1931mg_uecc_word_t mg_uecc_vli_testBit(const mg_uecc_word_t *vli, bitcount_t bit);
1932 
1933/* Counts the number of bits required to represent vli. */
1934bitcount_t mg_uecc_vli_numBits(const mg_uecc_word_t *vli,
1935 const wordcount_t max_words);
1936 
1937/* Sets dest = src. */
1938void mg_uecc_vli_set(mg_uecc_word_t *dest, const mg_uecc_word_t *src,
1939 wordcount_t num_words);
1940 
1941/* Constant-time comparison function - secure way to compare long integers */
1942/* Returns one if left == right, zero otherwise */
1943mg_uecc_word_t mg_uecc_vli_equal(const mg_uecc_word_t *left,
1944 const mg_uecc_word_t *right,
1945 wordcount_t num_words);
1946 
1947/* Constant-time comparison function - secure way to compare long integers */
1948/* Returns sign of left - right, in constant time. */
1949cmpresult_t mg_uecc_vli_cmp(const mg_uecc_word_t *left,
1950 const mg_uecc_word_t *right, wordcount_t num_words);
1951 
1952/* Computes vli = vli >> 1. */
1953void mg_uecc_vli_rshift1(mg_uecc_word_t *vli, wordcount_t num_words);
1954 
1955/* Computes result = left + right, returning carry. Can modify in place. */
1956mg_uecc_word_t mg_uecc_vli_add(mg_uecc_word_t *result,
1957 const mg_uecc_word_t *left,
1958 const mg_uecc_word_t *right,
1959 wordcount_t num_words);
1960 
1961/* Computes result = left - right, returning borrow. Can modify in place. */
1962mg_uecc_word_t mg_uecc_vli_sub(mg_uecc_word_t *result,
1963 const mg_uecc_word_t *left,
1964 const mg_uecc_word_t *right,
1965 wordcount_t num_words);
1966 
1967/* Computes result = left * right. Result must be 2 * num_words long. */
1968void mg_uecc_vli_mult(mg_uecc_word_t *result, const mg_uecc_word_t *left,
1969 const mg_uecc_word_t *right, wordcount_t num_words);
1970 
1971/* Computes result = left^2. Result must be 2 * num_words long. */
1972void mg_uecc_vli_square(mg_uecc_word_t *result, const mg_uecc_word_t *left,
1973 wordcount_t num_words);
1974 
1975/* Computes result = (left + right) % mod.
1976 Assumes that left < mod and right < mod, and that result does not overlap
1977 mod. */
1978void mg_uecc_vli_modAdd(mg_uecc_word_t *result, const mg_uecc_word_t *left,
1979 const mg_uecc_word_t *right, const mg_uecc_word_t *mod,
1980 wordcount_t num_words);
1981 
1982/* Computes result = (left - right) % mod.
1983 Assumes that left < mod and right < mod, and that result does not overlap
1984 mod. */
1985void mg_uecc_vli_modSub(mg_uecc_word_t *result, const mg_uecc_word_t *left,
1986 const mg_uecc_word_t *right, const mg_uecc_word_t *mod,
1987 wordcount_t num_words);
1988 
1989/* Computes result = product % mod, where product is 2N words long.
1990 Currently only designed to work for mod == curve->p or curve_n. */
1991void mg_uecc_vli_mmod(mg_uecc_word_t *result, mg_uecc_word_t *product,
1992 const mg_uecc_word_t *mod, wordcount_t num_words);
1993 
1994/* Calculates result = product (mod curve->p), where product is up to
1995 2 * curve->num_words long. */
1996void mg_uecc_vli_mmod_fast(mg_uecc_word_t *result, mg_uecc_word_t *product,
1997 MG_UECC_Curve curve);
1998 
1999/* Computes result = (left * right) % mod.
2000 Currently only designed to work for mod == curve->p or curve_n. */
2001void mg_uecc_vli_modMult(mg_uecc_word_t *result, const mg_uecc_word_t *left,
2002 const mg_uecc_word_t *right, const mg_uecc_word_t *mod,
2003 wordcount_t num_words);
2004 
2005/* Computes result = (left * right) % curve->p. */
2006void mg_uecc_vli_modMult_fast(mg_uecc_word_t *result,
2007 const mg_uecc_word_t *left,
2008 const mg_uecc_word_t *right, MG_UECC_Curve curve);
2009 
2010/* Computes result = left^2 % mod.
2011 Currently only designed to work for mod == curve->p or curve_n. */
2012void mg_uecc_vli_modSquare(mg_uecc_word_t *result, const mg_uecc_word_t *left,
2013 const mg_uecc_word_t *mod, wordcount_t num_words);
2014 
2015/* Computes result = left^2 % curve->p. */
2016void mg_uecc_vli_modSquare_fast(mg_uecc_word_t *result,
2017 const mg_uecc_word_t *left,
2018 MG_UECC_Curve curve);
2019 
2020/* Computes result = (1 / input) % mod.*/
2021void mg_uecc_vli_modInv(mg_uecc_word_t *result, const mg_uecc_word_t *input,
2022 const mg_uecc_word_t *mod, wordcount_t num_words);
2023 
2024#if MG_UECC_SUPPORT_COMPRESSED_POINT
2025/* Calculates a = sqrt(a) (mod curve->p) */
2026void mg_uecc_vli_mod_sqrt(mg_uecc_word_t *a, MG_UECC_Curve curve);
2027#endif
2028 
2029/* Converts an integer in uECC native format to big-endian bytes. */
2030void mg_uecc_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
2031 const mg_uecc_word_t *native);
2032/* Converts big-endian bytes to an integer in uECC native format. */
2033void mg_uecc_vli_bytesToNative(mg_uecc_word_t *native, const uint8_t *bytes,
2034 int num_bytes);
2035 
2036unsigned mg_uecc_curve_num_words(MG_UECC_Curve curve);
2037unsigned mg_uecc_curve_num_bytes(MG_UECC_Curve curve);
2038unsigned mg_uecc_curve_num_bits(MG_UECC_Curve curve);
2039unsigned mg_uecc_curve_num_n_words(MG_UECC_Curve curve);
2040unsigned mg_uecc_curve_num_n_bytes(MG_UECC_Curve curve);
2041unsigned mg_uecc_curve_num_n_bits(MG_UECC_Curve curve);
2042 
2043const mg_uecc_word_t *mg_uecc_curve_p(MG_UECC_Curve curve);
2044const mg_uecc_word_t *mg_uecc_curve_n(MG_UECC_Curve curve);
2045const mg_uecc_word_t *mg_uecc_curve_G(MG_UECC_Curve curve);
2046const mg_uecc_word_t *mg_uecc_curve_b(MG_UECC_Curve curve);
2047 
2048int mg_uecc_valid_point(const mg_uecc_word_t *point, MG_UECC_Curve curve);
2049 
2050/* Multiplies a point by a scalar. Points are represented by the X coordinate
2051 followed by the Y coordinate in the same array, both coordinates are
2052 curve->num_words long. Note that scalar must be curve->num_n_words long (NOT
2053 curve->num_words). */
2054void mg_uecc_point_mult(mg_uecc_word_t *result, const mg_uecc_word_t *point,
2055 const mg_uecc_word_t *scalar, MG_UECC_Curve curve);
2056 
2057/* Generates a random integer in the range 0 < random < top.
2058 Both random and top have num_words words. */
2059int mg_uecc_generate_random_int(mg_uecc_word_t *random,
2060 const mg_uecc_word_t *top,
2061 wordcount_t num_words);
2062 
2063#endif /* MG_UECC_ENABLE_VLI_API */
2064 
2065#ifdef __cplusplus
2066} /* end of extern "C" */
2067#endif
2068 
2069#endif /* _UECC_VLI_H_ */
2070 
2071// End of uecc BSD-2
2072// portable8439 v1.0.1
2073// Source: https://github.com/DavyLandman/portable8439
2074// Licensed under CC0-1.0
2075// Contains poly1305-donna e6ad6e091d30d7f4ec2d4f978be1fcfcbce72781 (Public
2076// Domain)
2077 
2078 
2079 
2080 
2081#ifndef __PORTABLE_8439_H
2082#define __PORTABLE_8439_H
2083#if defined(__cplusplus)
2084extern "C" {
2085#endif
2086 
2087// provide your own decl specificier like -DPORTABLE_8439_DECL=ICACHE_RAM_ATTR
2088#ifndef PORTABLE_8439_DECL
2089#define PORTABLE_8439_DECL
2090#endif
2091 
2092/*
2093 This library implements RFC 8439 a.k.a. ChaCha20-Poly1305 AEAD
2094 
2095 You can use this library to avoid attackers mutating or reusing your
2096 encrypted messages. This does assume you never reuse a nonce+key pair and,
2097 if possible, carefully pick your associated data.
2098*/
2099 
2100/* Make sure we are either nested in C++ or running in a C99+ compiler
2101#if !defined(__cplusplus) && !defined(_MSC_VER) && \
2102 (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
2103#error "C99 or newer required"
2104#endif */
2105 
2106// #if CHAR_BIT > 8
2107// # error "Systems without native octals not suppoted"
2108// #endif
2109 
2110#if defined(_MSC_VER) || defined(__cplusplus)
2111// add restrict support is possible
2112#if (defined(_MSC_VER) && _MSC_VER >= 1900) || defined(__clang__) || \
2113 defined(__GNUC__)
2114#define restrict __restrict
2115#else
2116#define restrict
2117#endif
2118#endif
2119 
2120#define RFC_8439_TAG_SIZE (16)
2121#define RFC_8439_KEY_SIZE (32)
2122#define RFC_8439_NONCE_SIZE (12)
2123 
2124/*
2125 Encrypt/Seal plain text bytes into a cipher text that can only be
2126 decrypted by knowing the key, nonce and associated data.
2127 
2128 input:
2129 - key: RFC_8439_KEY_SIZE bytes that all parties have agreed
2130 upon beforehand
2131 - nonce: RFC_8439_NONCE_SIZE bytes that should never be repeated
2132 for the same key. A counter or a pseudo-random value are fine.
2133 - ad: associated data to include with calculating the tag of the
2134 cipher text. Can be null for empty.
2135 - plain_text: data to be encrypted, pointer + size should not overlap
2136 with cipher_text pointer
2137 
2138 output:
2139 - cipher_text: encrypted plain_text with a tag appended. Make sure to
2140 allocate at least plain_text_size + RFC_8439_TAG_SIZE
2141 
2142 returns:
2143 - size of bytes written to cipher_text, can be -1 if overlapping
2144 pointers are passed for plain_text and cipher_text
2145*/
2146PORTABLE_8439_DECL size_t mg_chacha20_poly1305_encrypt(
2147 uint8_t *restrict cipher_text, const uint8_t key[RFC_8439_KEY_SIZE],
2148 const uint8_t nonce[RFC_8439_NONCE_SIZE], const uint8_t *restrict ad,
2149 size_t ad_size, const uint8_t *restrict plain_text, size_t plain_text_size);
2150 
2151/*
2152 Decrypt/unseal cipher text given the right key, nonce, and additional data.
2153 
2154 input:
2155 - key: RFC_8439_KEY_SIZE bytes that all parties have agreed
2156 upon beforehand
2157 - nonce: RFC_8439_NONCE_SIZE bytes that should never be repeated for
2158 the same key. A counter or a pseudo-random value are fine.
2159 - ad: associated data to include with calculating the tag of the
2160 cipher text. Can be null for empty.
2161 - cipher_text: encrypted message.
2162 
2163 output:
2164 - plain_text: data to be encrypted, pointer + size should not overlap
2165 with cipher_text pointer, leave at least enough room for
2166 cipher_text_size - RFC_8439_TAG_SIZE
2167 
2168 returns:
2169 - size of bytes written to plain_text, -1 signals either:
2170 - incorrect key/nonce/ad
2171 - corrupted cipher_text
2172 - overlapping pointers are passed for plain_text and cipher_text
2173*/
2174PORTABLE_8439_DECL size_t mg_chacha20_poly1305_decrypt(
2175 uint8_t *restrict plain_text, const uint8_t key[RFC_8439_KEY_SIZE],
2176 const uint8_t nonce[RFC_8439_NONCE_SIZE],
2177 const uint8_t *restrict cipher_text, size_t cipher_text_size);
2178#if defined(__cplusplus)
2179}
2180#endif
2181#endif
2182#ifndef TLS_RSA_H
2183#define TLS_RSA_H
2184 
2185 
2186int mg_rsa_mod_pow(const uint8_t *mod, size_t modsz, const uint8_t *exp, size_t expsz, const uint8_t *msg, size_t msgsz, uint8_t *out, size_t outsz);
2187 
2188#endif // TLS_RSA_H
2189 
2190 
2191struct mg_connection;
2192typedef void (*mg_event_handler_t)(struct mg_connection *, int ev,
2193 void *ev_data);
2194void mg_call(struct mg_connection *c, int ev, void *ev_data);
2195void mg_error(struct mg_connection *c, const char *fmt, ...);
2196 
2197enum {
2198 MG_EV_ERROR, // Error char *error_message
2199 MG_EV_OPEN, // Connection created NULL
2200 MG_EV_POLL, // mg_mgr_poll iteration uint64_t *uptime_millis
2201 MG_EV_RESOLVE, // Host name is resolved NULL
2202 MG_EV_CONNECT, // Connection established NULL
2203 MG_EV_ACCEPT, // Connection accepted NULL
2204 MG_EV_TLS_HS, // TLS handshake succeeded NULL
2205 MG_EV_READ, // Data received from socket long *bytes_read
2206 MG_EV_WRITE, // Data written to socket long *bytes_written
2207 MG_EV_CLOSE, // Connection closed NULL
2208 MG_EV_HTTP_HDRS, // HTTP headers struct mg_http_message *
2209 MG_EV_HTTP_MSG, // Full HTTP request/response struct mg_http_message *
2210 MG_EV_WS_OPEN, // Websocket handshake done struct mg_http_message *
2211 MG_EV_WS_MSG, // Websocket msg, text or bin struct mg_ws_message *
2212 MG_EV_WS_CTL, // Websocket control msg struct mg_ws_message *
2213 MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
2214 MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
2215 MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
2216 MG_EV_SNTP_TIME, // SNTP time received uint64_t *epoch_millis
2217 MG_EV_WAKEUP, // mg_wakeup() data received struct mg_str *data
2218 MG_EV_USER // Starting ID for user events
2219};
2220 
2221 
2222 
2223 
2224 
2225 
2226 
2227 
2228 
2229 
2230struct mg_dns {
2231 const char *url; // DNS server URL
2232 struct mg_connection *c; // DNS server connection
2233};
2234 
2235struct mg_addr {
2236 uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order
2237 uint16_t port; // TCP or UDP port in network byte order
2238 uint8_t scope_id; // IPv6 scope ID
2239 bool is_ip6; // True when address is IPv6 address
2240};
2241 
2242struct mg_mgr {
2243 struct mg_connection *conns; // List of active connections
2244 struct mg_dns dns4; // DNS for IPv4
2245 struct mg_dns dns6; // DNS for IPv6
2246 int dnstimeout; // DNS resolve timeout in milliseconds
2247 bool use_dns6; // Use DNS6 server by default, see #1532
2248 unsigned long nextid; // Next connection ID
2249 void *userdata; // Arbitrary user data pointer
2250 void *tls_ctx; // TLS context shared by all TLS sessions
2251 uint16_t mqtt_id; // MQTT IDs for pub/sub
2252 void *active_dns_requests; // DNS requests in progress
2253 struct mg_timer *timers; // Active timers
2254 int epoll_fd; // Used when MG_EPOLL_ENABLE=1
2255 struct mg_tcpip_if *ifp; // Builtin TCP/IP stack only. Interface pointer
2256 size_t extraconnsize; // Builtin TCP/IP stack only. Extra space
2257 MG_SOCKET_TYPE pipe; // Socketpair end for mg_wakeup()
2258#if MG_ENABLE_FREERTOS_TCP
2259 SocketSet_t ss; // NOTE(lsm): referenced from socket struct
2260#endif
2261};
2262 
2263struct mg_connection {
2264 struct mg_connection *next; // Linkage in struct mg_mgr :: connections
2265 struct mg_mgr *mgr; // Our container
2266 struct mg_addr loc; // Local address
2267 struct mg_addr rem; // Remote address
2268 void *fd; // Connected socket, or LWIP data
2269 unsigned long id; // Auto-incrementing unique connection ID
2270 struct mg_iobuf recv; // Incoming data
2271 struct mg_iobuf send; // Outgoing data
2272 struct mg_iobuf prof; // Profile data enabled by MG_ENABLE_PROFILE
2273 struct mg_iobuf rtls; // TLS only. Incoming encrypted data
2274 mg_event_handler_t fn; // User-specified event handler function
2275 void *fn_data; // User-specified function parameter
2276 mg_event_handler_t pfn; // Protocol-specific handler function
2277 void *pfn_data; // Protocol-specific function parameter
2278 char data[MG_DATA_SIZE]; // Arbitrary connection data
2279 void *tls; // TLS specific data
2280 unsigned is_listening : 1; // Listening connection
2281 unsigned is_client : 1; // Outbound (client) connection
2282 unsigned is_accepted : 1; // Accepted (server) connection
2283 unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
2284 unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress
2285 unsigned is_connecting : 1; // Non-blocking connect is in progress
2286 unsigned is_tls : 1; // TLS-enabled connection
2287 unsigned is_tls_hs : 1; // TLS handshake is in progress
2288 unsigned is_udp : 1; // UDP connection
2289 unsigned is_websocket : 1; // WebSocket connection
2290 unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator
2291 unsigned is_hexdumping : 1; // Hexdump in/out traffic
2292 unsigned is_draining : 1; // Send remaining data, then close and free
2293 unsigned is_closing : 1; // Close and free the connection immediately
2294 unsigned is_full : 1; // Stop reads, until cleared
2295 unsigned is_tls_throttled : 1; // Last TLS write: MG_SOCK_PENDING() was true
2296 unsigned is_resp : 1; // Response is still being generated
2297 unsigned is_readable : 1; // Connection is ready to read
2298 unsigned is_writable : 1; // Connection is ready to write
2299};
2300 
2301void mg_mgr_poll(struct mg_mgr *, int ms);
2302void mg_mgr_init(struct mg_mgr *);
2303void mg_mgr_free(struct mg_mgr *);
2304 
2305struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
2306 mg_event_handler_t fn, void *fn_data);
2307struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
2308 mg_event_handler_t fn, void *fn_data);
2309struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
2310 mg_event_handler_t fn, void *fn_data);
2311void mg_connect_resolved(struct mg_connection *);
2312bool mg_send(struct mg_connection *, const void *, size_t);
2313size_t mg_printf(struct mg_connection *, const char *fmt, ...);
2314size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
2315bool mg_aton(struct mg_str str, struct mg_addr *addr);
2316 
2317// These functions are used to integrate with custom network stacks
2318struct mg_connection *mg_alloc_conn(struct mg_mgr *);
2319void mg_close_conn(struct mg_connection *c);
2320bool mg_open_listener(struct mg_connection *c, const char *url);
2321 
2322// Utility functions
2323bool mg_wakeup(struct mg_mgr *, unsigned long id, const void *buf, size_t len);
2324bool mg_wakeup_init(struct mg_mgr *);
2325struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
2326 unsigned flags, void (*fn)(void *), void *arg);
2327 
2328 
2329 
2330 
2331 
2332 
2333 
2334 
2335struct mg_http_header {
2336 struct mg_str name; // Header name
2337 struct mg_str value; // Header value
2338};
2339 
2340struct mg_http_message {
2341 struct mg_str method, uri, query, proto; // Request/response line
2342 struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
2343 struct mg_str body; // Body
2344 struct mg_str head; // Request + headers
2345 struct mg_str message; // Request + headers + body
2346};
2347 
2348// Parameter for mg_http_serve_dir()
2349struct mg_http_serve_opts {
2350 const char *root_dir; // Web root directory, must be non-NULL
2351 const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
2352 const char *extra_headers; // Extra HTTP headers to add in responses
2353 const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
2354 const char *page404; // Path to the 404 page, or NULL by default
2355 struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
2356};
2357 
2358// Parameter for mg_http_next_multipart
2359struct mg_http_part {
2360 struct mg_str name; // Form field name
2361 struct mg_str filename; // Filename for file uploads
2362 struct mg_str body; // Part contents
2363};
2364 
2365int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
2366int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
2367void mg_http_printf_chunk(struct mg_connection *cnn, const char *fmt, ...);
2368void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
2369void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
2370struct mg_connection *mg_http_listen(struct mg_mgr *, const char *url,
2371 mg_event_handler_t fn, void *fn_data);
2372struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
2373 mg_event_handler_t fn, void *fn_data);
2374void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
2375 const struct mg_http_serve_opts *);
2376void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm,
2377 const char *path, const struct mg_http_serve_opts *);
2378void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
2379 const char *body_fmt, ...);
2380struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
2381struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
2382int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
2383int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
2384size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
2385void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
2386long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
2387 struct mg_fs *fs, const char *dir, size_t max_size);
2388void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
2389struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
2390size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
2391int mg_http_status(const struct mg_http_message *hm);
2392void mg_hello(const char *url);
2393 
2394 
2395void mg_http_serve_ssi(struct mg_connection *c, const char *root,
2396 const char *fullpath);
2397 
2398 
2399#define MG_TLS_NONE 0 // No TLS support
2400#define MG_TLS_MBED 1 // mbedTLS
2401#define MG_TLS_OPENSSL 2 // OpenSSL
2402#define MG_TLS_WOLFSSL 5 // WolfSSL (based on OpenSSL)
2403#define MG_TLS_BUILTIN 3 // Built-in
2404#define MG_TLS_CUSTOM 4 // Custom implementation
2405 
2406#ifndef MG_TLS
2407#define MG_TLS MG_TLS_NONE
2408#endif
2409 
2410 
2411 
2412 
2413 
2414struct mg_tls_opts {
2415 struct mg_str ca; // PEM or DER
2416 struct mg_str cert; // PEM or DER
2417 struct mg_str key; // PEM or DER
2418 struct mg_str name; // If not empty, enable host name verification
2419 int skip_verification; // Skip certificate and host name verification
2420};
2421 
2422void mg_tls_init(struct mg_connection *, const struct mg_tls_opts *opts);
2423void mg_tls_free(struct mg_connection *);
2424long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
2425long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
2426size_t mg_tls_pending(struct mg_connection *);
2427void mg_tls_handshake(struct mg_connection *);
2428 
2429// Private
2430void mg_tls_ctx_init(struct mg_mgr *);
2431void mg_tls_ctx_free(struct mg_mgr *);
2432 
2433// Low-level IO primives used by TLS layer
2434enum { MG_IO_ERR = -1, MG_IO_WAIT = -2, MG_IO_RESET = -3 };
2435long mg_io_send(struct mg_connection *c, const void *buf, size_t len);
2436long mg_io_recv(struct mg_connection *c, void *buf, size_t len);
2437 
2438 
2439 
2440 
2441 
2442 
2443 
2444#if MG_TLS == MG_TLS_MBED
2445#include <mbedtls/debug.h>
2446#include <mbedtls/net_sockets.h>
2447#include <mbedtls/ssl.h>
2448#include <mbedtls/ssl_ticket.h>
2449 
2450struct mg_tls_ctx {
2451 int dummy;
2452#ifdef MBEDTLS_SSL_SESSION_TICKETS
2453 mbedtls_ssl_ticket_context tickets;
2454#endif
2455};
2456 
2457struct mg_tls {
2458 mbedtls_x509_crt ca; // Parsed CA certificate
2459 mbedtls_x509_crt cert; // Parsed certificate
2460 mbedtls_pk_context pk; // Private key context
2461 mbedtls_ssl_context ssl; // SSL/TLS context
2462 mbedtls_ssl_config conf; // SSL-TLS config
2463#ifdef MBEDTLS_SSL_SESSION_TICKETS
2464 mbedtls_ssl_ticket_context ticket; // Session tickets context
2465#endif
2466 // https://github.com/Mbed-TLS/mbedtls/blob/3b3c652d/include/mbedtls/ssl.h#L5071C18-L5076C29
2467 unsigned char *throttled_buf; // see #3074
2468 size_t throttled_len;
2469};
2470#endif
2471 
2472 
2473#if MG_TLS == MG_TLS_OPENSSL || MG_TLS == MG_TLS_WOLFSSL
2474 
2475#include <openssl/err.h>
2476#include <openssl/ssl.h>
2477 
2478struct mg_tls {
2479 BIO_METHOD *bm;
2480 SSL_CTX *ctx;
2481 SSL *ssl;
2482};
2483#endif
2484 
2485 
2486#define WEBSOCKET_OP_CONTINUE 0
2487#define WEBSOCKET_OP_TEXT 1
2488#define WEBSOCKET_OP_BINARY 2
2489#define WEBSOCKET_OP_CLOSE 8
2490#define WEBSOCKET_OP_PING 9
2491#define WEBSOCKET_OP_PONG 10
2492 
2493 
2494 
2495struct mg_ws_message {
2496 struct mg_str data; // Websocket message data
2497 uint8_t flags; // Websocket message flags
2498};
2499 
2500struct mg_connection *mg_ws_connect(struct mg_mgr *, const char *url,
2501 mg_event_handler_t fn, void *fn_data,
2502 const char *fmt, ...);
2503void mg_ws_upgrade(struct mg_connection *, struct mg_http_message *,
2504 const char *fmt, ...);
2505size_t mg_ws_send(struct mg_connection *, const void *buf, size_t len, int op);
2506size_t mg_ws_wrap(struct mg_connection *, size_t len, int op);
2507size_t mg_ws_printf(struct mg_connection *c, int op, const char *fmt, ...);
2508size_t mg_ws_vprintf(struct mg_connection *c, int op, const char *fmt,
2509 va_list *);
2510 
2511 
2512 
2513 
2514struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
2515 mg_event_handler_t fn, void *fn_data);
2516void mg_sntp_request(struct mg_connection *c);
2517int64_t mg_sntp_parse(const unsigned char *buf, size_t len);
2518 
2519uint64_t mg_now(void); // Return milliseconds since Epoch
2520 
2521 
2522 
2523 
2524 
2525#define MQTT_CMD_CONNECT 1
2526#define MQTT_CMD_CONNACK 2
2527#define MQTT_CMD_PUBLISH 3
2528#define MQTT_CMD_PUBACK 4
2529#define MQTT_CMD_PUBREC 5
2530#define MQTT_CMD_PUBREL 6
2531#define MQTT_CMD_PUBCOMP 7
2532#define MQTT_CMD_SUBSCRIBE 8
2533#define MQTT_CMD_SUBACK 9
2534#define MQTT_CMD_UNSUBSCRIBE 10
2535#define MQTT_CMD_UNSUBACK 11
2536#define MQTT_CMD_PINGREQ 12
2537#define MQTT_CMD_PINGRESP 13
2538#define MQTT_CMD_DISCONNECT 14
2539#define MQTT_CMD_AUTH 15
2540 
2541#define MQTT_PROP_PAYLOAD_FORMAT_INDICATOR 0x01
2542#define MQTT_PROP_MESSAGE_EXPIRY_INTERVAL 0x02
2543#define MQTT_PROP_CONTENT_TYPE 0x03
2544#define MQTT_PROP_RESPONSE_TOPIC 0x08
2545#define MQTT_PROP_CORRELATION_DATA 0x09
2546#define MQTT_PROP_SUBSCRIPTION_IDENTIFIER 0x0B
2547#define MQTT_PROP_SESSION_EXPIRY_INTERVAL 0x11
2548#define MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER 0x12
2549#define MQTT_PROP_SERVER_KEEP_ALIVE 0x13
2550#define MQTT_PROP_AUTHENTICATION_METHOD 0x15
2551#define MQTT_PROP_AUTHENTICATION_DATA 0x16
2552#define MQTT_PROP_REQUEST_PROBLEM_INFORMATION 0x17
2553#define MQTT_PROP_WILL_DELAY_INTERVAL 0x18
2554#define MQTT_PROP_REQUEST_RESPONSE_INFORMATION 0x19
2555#define MQTT_PROP_RESPONSE_INFORMATION 0x1A
2556#define MQTT_PROP_SERVER_REFERENCE 0x1C
2557#define MQTT_PROP_REASON_STRING 0x1F
2558#define MQTT_PROP_RECEIVE_MAXIMUM 0x21
2559#define MQTT_PROP_TOPIC_ALIAS_MAXIMUM 0x22
2560#define MQTT_PROP_TOPIC_ALIAS 0x23
2561#define MQTT_PROP_MAXIMUM_QOS 0x24
2562#define MQTT_PROP_RETAIN_AVAILABLE 0x25
2563#define MQTT_PROP_USER_PROPERTY 0x26
2564#define MQTT_PROP_MAXIMUM_PACKET_SIZE 0x27
2565#define MQTT_PROP_WILDCARD_SUBSCRIPTION_AVAILABLE 0x28
2566#define MQTT_PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE 0x29
2567#define MQTT_PROP_SHARED_SUBSCRIPTION_AVAILABLE 0x2A
2568 
2569enum {
2570 MQTT_PROP_TYPE_BYTE,
2571 MQTT_PROP_TYPE_STRING,
2572 MQTT_PROP_TYPE_STRING_PAIR,
2573 MQTT_PROP_TYPE_BINARY_DATA,
2574 MQTT_PROP_TYPE_VARIABLE_INT,
2575 MQTT_PROP_TYPE_INT,
2576 MQTT_PROP_TYPE_SHORT
2577};
2578 
2579enum { MQTT_OK, MQTT_INCOMPLETE, MQTT_MALFORMED };
2580 
2581struct mg_mqtt_prop {
2582 uint8_t id; // Enumerated at MQTT5 Reference
2583 uint32_t iv; // Integer value for 8-, 16-, 32-bit integers types
2584 struct mg_str key; // Non-NULL only for user property type
2585 struct mg_str val; // Non-NULL only for UTF-8 types and user properties
2586};
2587 
2588struct mg_mqtt_opts {
2589 struct mg_str user; // Username, can be empty
2590 struct mg_str pass; // Password, can be empty
2591 struct mg_str client_id; // Client ID
2592 struct mg_str topic; // message/subscription topic
2593 struct mg_str message; // message content
2594 uint8_t qos; // message quality of service
2595 uint8_t version; // Can be 4 (3.1.1), or 5. If 0, assume 4
2596 uint16_t keepalive; // Keep-alive timer in seconds
2597 uint16_t retransmit_id; // For PUBLISH, init to 0
2598 bool retain; // Retain flag
2599 bool clean; // Clean session flag
2600 struct mg_mqtt_prop *props; // MQTT5 props array
2601 size_t num_props; // number of props
2602 struct mg_mqtt_prop *will_props; // Valid only for CONNECT packet (MQTT5)
2603 size_t num_will_props; // Number of will props
2604};
2605 
2606struct mg_mqtt_message {
2607 struct mg_str topic; // Parsed topic for PUBLISH
2608 struct mg_str data; // Parsed message for PUBLISH
2609 struct mg_str dgram; // Whole MQTT packet, including headers
2610 uint16_t id; // For PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
2611 uint8_t cmd; // MQTT command, one of MQTT_CMD_*
2612 uint8_t qos; // Quality of service
2613 uint8_t ack; // CONNACK return code, 0 = success
2614 size_t props_start; // Offset to the start of the properties (MQTT5)
2615 size_t props_size; // Length of the properties
2616};
2617 
2618struct mg_connection *mg_mqtt_connect(struct mg_mgr *, const char *url,
2619 const struct mg_mqtt_opts *opts,
2620 mg_event_handler_t fn, void *fn_data);
2621struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
2622 mg_event_handler_t fn, void *fn_data);
2623void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts);
2624uint16_t mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts);
2625void mg_mqtt_sub(struct mg_connection *, const struct mg_mqtt_opts *opts);
2626int mg_mqtt_parse(const uint8_t *, size_t, uint8_t, struct mg_mqtt_message *);
2627void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
2628 uint32_t len);
2629void mg_mqtt_ping(struct mg_connection *);
2630void mg_mqtt_pong(struct mg_connection *);
2631void mg_mqtt_disconnect(struct mg_connection *, const struct mg_mqtt_opts *);
2632size_t mg_mqtt_next_prop(struct mg_mqtt_message *, struct mg_mqtt_prop *,
2633 size_t ofs);
2634 
2635 
2636 
2637 
2638 
2639// Mongoose sends DNS queries that contain only one question:
2640// either A (IPv4) or AAAA (IPv6) address lookup.
2641// Therefore, we expect zero or one answer.
2642// If `resolved` is true, then `addr` contains resolved IPv4 or IPV6 address.
2643struct mg_dns_message {
2644 uint16_t txnid; // Transaction ID
2645 bool resolved; // Resolve successful, addr is set
2646 struct mg_addr addr; // Resolved address
2647 char name[256]; // Host name
2648};
2649 
2650struct mg_dns_header {
2651 uint16_t txnid; // Transaction ID
2652 uint16_t flags;
2653 uint16_t num_questions;
2654 uint16_t num_answers;
2655 uint16_t num_authority_prs;
2656 uint16_t num_other_prs;
2657};
2658 
2659// DNS resource record
2660struct mg_dns_rr {
2661 uint16_t nlen; // Name or pointer length
2662 uint16_t atype; // Address type
2663 uint16_t aclass; // Address class
2664 uint16_t alen; // Address length
2665};
2666 
2667void mg_resolve(struct mg_connection *, const char *url);
2668void mg_resolve_cancel(struct mg_connection *);
2669bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
2670size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
2671 bool is_question, struct mg_dns_rr *);
2672
2673struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name);
2674 
2675 
2676 
2677 
2678 
2679#ifndef MG_JSON_MAX_DEPTH
2680#define MG_JSON_MAX_DEPTH 30
2681#endif
2682 
2683// Error return values - negative. Successful returns are >= 0
2684enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
2685int mg_json_get(struct mg_str json, const char *path, int *toklen);
2686 
2687struct mg_str mg_json_get_tok(struct mg_str json, const char *path);
2688bool mg_json_get_num(struct mg_str json, const char *path, double *v);
2689bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);
2690long mg_json_get_long(struct mg_str json, const char *path, long dflt);
2691char *mg_json_get_str(struct mg_str json, const char *path);
2692char *mg_json_get_hex(struct mg_str json, const char *path, int *len);
2693char *mg_json_get_b64(struct mg_str json, const char *path, int *len);
2694 
2695bool mg_json_unescape(struct mg_str str, char *buf, size_t len);
2696size_t mg_json_next(struct mg_str obj, size_t ofs, struct mg_str *key,
2697 struct mg_str *val);
2698 
2699 
2700 
2701 
2702// JSON-RPC request descriptor
2703struct mg_rpc_req {
2704 struct mg_rpc **head; // RPC handlers list head
2705 struct mg_rpc *rpc; // RPC handler being called
2706 mg_pfn_t pfn; // Response printing function
2707 void *pfn_data; // Response printing function data
2708 void *req_data; // Arbitrary request data
2709 struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
2710};
2711 
2712// JSON-RPC method handler
2713struct mg_rpc {
2714 struct mg_rpc *next; // Next in list
2715 struct mg_str method; // Method pattern
2716 void (*fn)(struct mg_rpc_req *); // Handler function
2717 void *fn_data; // Handler function argument
2718};
2719 
2720void mg_rpc_add(struct mg_rpc **head, struct mg_str method_pattern,
2721 void (*handler)(struct mg_rpc_req *), void *handler_data);
2722void mg_rpc_del(struct mg_rpc **head, void (*handler)(struct mg_rpc_req *));
2723void mg_rpc_process(struct mg_rpc_req *);
2724 
2725// Helper functions to print result or error frame
2726void mg_rpc_ok(struct mg_rpc_req *, const char *fmt, ...);
2727void mg_rpc_vok(struct mg_rpc_req *, const char *fmt, va_list *ap);
2728void mg_rpc_err(struct mg_rpc_req *, int code, const char *fmt, ...);
2729void mg_rpc_verr(struct mg_rpc_req *, int code, const char *fmt, va_list *);
2730void mg_rpc_list(struct mg_rpc_req *r);
2731// Copyright (c) 2023 Cesanta Software Limited
2732// All rights reserved
2733 
2734 
2735 
2736 
2737 
2738#define MG_OTA_NONE 0 // No OTA support
2739#define MG_OTA_STM32H5 1 // STM32 H5
2740#define MG_OTA_STM32H7 2 // STM32 H7
2741#define MG_OTA_STM32H7_DUAL_CORE 3 // STM32 H7 dual core
2742#define MG_OTA_STM32F 4 // STM32 F7/F4/F2
2743#define MG_OTA_CH32V307 100 // WCH CH32V307
2744#define MG_OTA_U2A 200 // Renesas U2A16, U2A8, U2A6
2745#define MG_OTA_RT1020 300 // IMXRT1020
2746#define MG_OTA_RT1050 301 // IMXRT1050
2747#define MG_OTA_RT1060 302 // IMXRT1060
2748#define MG_OTA_RT1064 303 // IMXRT1064
2749#define MG_OTA_RT1170 304 // IMXRT1170
2750#define MG_OTA_MCXN 310 // MCXN947
2751#define MG_OTA_FLASH 900 // OTA via an internal flash
2752#define MG_OTA_ESP32 910 // ESP32 OTA implementation
2753#define MG_OTA_PICOSDK 920 // RP2040/2350 using Pico-SDK hardware_flash
2754#define MG_OTA_CUSTOM 1000 // Custom implementation
2755 
2756#ifndef MG_OTA
2757#define MG_OTA MG_OTA_NONE
2758#else
2759#ifndef MG_IRAM
2760#if defined(__GNUC__)
2761#define MG_IRAM __attribute__((noinline, section(".iram")))
2762#else
2763#define MG_IRAM
2764#endif // compiler
2765#endif // IRAM
2766#endif // OTA
2767 
2768// Firmware update API
2769bool mg_ota_begin(size_t new_firmware_size); // Start writing
2770bool mg_ota_write(const void *buf, size_t len); // Write chunk, aligned to 1k
2771bool mg_ota_end(void); // Stop writing
2772 
2773 
2774 
2775#if MG_OTA != MG_OTA_NONE && MG_OTA != MG_OTA_CUSTOM
2776 
2777struct mg_flash {
2778 void *start; // Address at which flash starts
2779 size_t size; // Flash size
2780 size_t secsz; // Sector size
2781 size_t align; // Write alignment
2782 bool (*write_fn)(void *, const void *, size_t); // Write function
2783 bool (*swap_fn)(void); // Swap partitions
2784};
2785 
2786bool mg_ota_flash_begin(size_t new_firmware_size, struct mg_flash *flash);
2787bool mg_ota_flash_write(const void *buf, size_t len, struct mg_flash *flash);
2788bool mg_ota_flash_end(struct mg_flash *flash);
2789 
2790#endif
2791 
2792 
2793 
2794 
2795 
2796 
2797struct mg_wifi_scan_bss_data {
2798 struct mg_str SSID;
2799 char *BSSID;
2800 int16_t RSSI;
2801 uint8_t security;
2802#define MG_WIFI_SECURITY_OPEN 0
2803#define MG_WIFI_SECURITY_WEP MG_BIT(0)
2804#define MG_WIFI_SECURITY_WPA MG_BIT(1)
2805#define MG_WIFI_SECURITY_WPA2 MG_BIT(2)
2806#define MG_WIFI_SECURITY_WPA3 MG_BIT(3)
2807 uint8_t channel;
2808 unsigned band :2;
2809#define MG_WIFI_BAND_2G 0
2810#define MG_WIFI_BAND_5G 1
2811 unsigned has_n :1;
2812};
2813 
2814 
2815bool mg_wifi_scan(void);
2816bool mg_wifi_connect(char *ssid, char *pass);
2817bool mg_wifi_disconnect(void);
2818bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel);
2819bool mg_wifi_ap_stop(void);
2820 
2821 
2822#if MG_ENABLE_TCPIP
2823 
2824 
2825 
2826 
2827 
2828 
2829struct mg_tcpip_if; // Mongoose TCP/IP network interface
2830 
2831struct mg_tcpip_driver {
2832 bool (*init)(struct mg_tcpip_if *); // Init driver
2833 size_t (*tx)(const void *, size_t, struct mg_tcpip_if *); // Transmit frame
2834 size_t (*rx)(void *buf, size_t len, struct mg_tcpip_if *); // Receive frame
2835 bool (*poll)(struct mg_tcpip_if *, bool); // Poll, return Up/down status
2836};
2837 
2838typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev,
2839 void *ev_data);
2840 
2841enum {
2842 MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
2843 MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
2844 MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
2845 MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str *
2846 MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL
2847 MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct mg_wifi_scan_bss_data *
2848 MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL
2849 MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and chip specific
2850 MG_TCPIP_EV_DRIVER, // Driver event driver specific
2851 MG_TCPIP_EV_USER // Starting ID for user events
2852};
2853 
2854// Network interface
2855struct mg_tcpip_if {
2856 uint8_t mac[6]; // MAC address. Must be set to a valid MAC
2857 uint32_t ip, mask, gw; // IP address, mask, default gateway
2858 struct mg_str tx; // Output (TX) buffer
2859 bool enable_dhcp_client; // Enable DCHP client
2860 bool enable_dhcp_server; // Enable DCHP server
2861 bool enable_get_gateway; // DCHP server sets client as gateway
2862 bool enable_req_dns; // DCHP client requests DNS server
2863 bool enable_req_sntp; // DCHP client requests SNTP server
2864 bool enable_crc32_check; // Do a CRC check on RX frames and strip it
2865 bool enable_mac_check; // Do a MAC check on RX frames
2866 bool update_mac_hash_table; // Signal drivers to update MAC controller
2867 struct mg_tcpip_driver *driver; // Low level driver
2868 void *driver_data; // Driver-specific data
2869 mg_tcpip_event_handler_t fn; // User-specified event handler function
2870 struct mg_mgr *mgr; // Mongoose event manager
2871 struct mg_queue recv_queue; // Receive queue
2872 char dhcp_name[12]; // Name reported to DHCP, "mip" if unset
2873 uint16_t mtu; // Interface MTU
2874#define MG_TCPIP_MTU_DEFAULT 1500
2875 
2876 // Internal state, user can use it but should not change it
2877 uint8_t gwmac[6]; // Router's MAC
2878 uint64_t now; // Current time
2879 uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
2880 uint64_t lease_expire; // Lease expiration time, in ms
2881 uint16_t eport; // Next ephemeral port
2882 volatile uint32_t ndrop; // Number of received, but dropped frames
2883 volatile uint32_t nrecv; // Number of received frames
2884 volatile uint32_t nsent; // Number of transmitted frames
2885 volatile uint32_t nerr; // Number of driver errors
2886 uint8_t state; // Current state
2887#define MG_TCPIP_STATE_DOWN 0 // Interface is down
2888#define MG_TCPIP_STATE_UP 1 // Interface is up
2889#define MG_TCPIP_STATE_REQ 2 // Interface is up, DHCP REQUESTING state
2890#define MG_TCPIP_STATE_IP 3 // Interface is up and has an IP assigned
2891#define MG_TCPIP_STATE_READY 4 // Interface has fully come up, ready to work
2892};
2893 
2894void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
2895void mg_tcpip_free(struct mg_tcpip_if *);
2896void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
2897void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac);
2898 
2899extern struct mg_tcpip_driver mg_tcpip_driver_stm32f;
2900extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
2901extern struct mg_tcpip_driver mg_tcpip_driver_w5100;
2902extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
2903extern struct mg_tcpip_driver mg_tcpip_driver_tms570;
2904extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
2905extern struct mg_tcpip_driver mg_tcpip_driver_imxrt;
2906extern struct mg_tcpip_driver mg_tcpip_driver_same54;
2907extern struct mg_tcpip_driver mg_tcpip_driver_cmsis;
2908extern struct mg_tcpip_driver mg_tcpip_driver_ra;
2909extern struct mg_tcpip_driver mg_tcpip_driver_xmc;
2910extern struct mg_tcpip_driver mg_tcpip_driver_xmc7;
2911extern struct mg_tcpip_driver mg_tcpip_driver_ppp;
2912extern struct mg_tcpip_driver mg_tcpip_driver_pico_w;
2913extern struct mg_tcpip_driver mg_tcpip_driver_rw612;
2914extern struct mg_tcpip_driver mg_tcpip_driver_cyw;
2915 
2916// Drivers that require SPI, can use this SPI abstraction
2917struct mg_tcpip_spi {
2918 void *spi; // Opaque SPI bus descriptor
2919 void (*begin)(void *); // SPI begin: slave select low
2920 void (*end)(void *); // SPI end: slave select high
2921 uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
2922};
2923 
2924#endif
2925 
2926 
2927 
2928// Macros to record timestamped events that happens with a connection.
2929// They are saved into a c->prof IO buffer, each event is a name and a 32-bit
2930// timestamp in milliseconds since connection init time.
2931//
2932// Test (run in two separate terminals):
2933// make -C tutorials/http/http-server/ CFLAGS_EXTRA=-DMG_ENABLE_PROFILE=1
2934// curl localhost:8000
2935// Output:
2936// 1ea1f1e7 2 net.c:150:mg_close_conn 3 profile:
2937// 1ea1f1e8 2 net.c:150:mg_close_conn 1ea1f1e6 init
2938// 1ea1f1e8 2 net.c:150:mg_close_conn 0 EV_OPEN
2939// 1ea1f1e8 2 net.c:150:mg_close_conn 0 EV_ACCEPT
2940// 1ea1f1e8 2 net.c:150:mg_close_conn 0 EV_READ
2941// 1ea1f1e8 2 net.c:150:mg_close_conn 0 EV_HTTP_MSG
2942// 1ea1f1e8 2 net.c:150:mg_close_conn 0 EV_WRITE
2943// 1ea1f1e8 2 net.c:150:mg_close_conn 1 EV_CLOSE
2944//
2945// Usage:
2946// Enable profiling by setting MG_ENABLE_PROFILE=1
2947// Invoke MG_PROF_ADD(c, "MY_EVENT_1") in the places you'd like to measure
2948 
2949#if MG_ENABLE_PROFILE
2950struct mg_profitem {
2951 const char *name; // Event name
2952 uint32_t timestamp; // Milliseconds since connection creation (MG_EV_OPEN)
2953};
2954 
2955#define MG_PROFILE_ALLOC_GRANULARITY 256 // Can save 32 items wih to realloc
2956 
2957// Adding a profile item to the c->prof. Must be as fast as possible.
2958// Reallocation of the c->prof iobuf is not desirable here, that's why we
2959// pre-allocate c->prof with MG_PROFILE_ALLOC_GRANULARITY.
2960// This macro just inits and copies 8 bytes, and calls mg_millis(),
2961// which should be fast enough.
2962#define MG_PROF_ADD(c, name_) \
2963 do { \
2964 struct mg_iobuf *io = &c->prof; \
2965 uint32_t inittime = ((struct mg_profitem *) io->buf)->timestamp; \
2966 struct mg_profitem item = {name_, (uint32_t) mg_millis() - inittime}; \
2967 mg_iobuf_add(io, io->len, &item, sizeof(item)); \
2968 } while (0)
2969 
2970// Initialising profile for a new connection. Not time sensitive
2971#define MG_PROF_INIT(c) \
2972 do { \
2973 struct mg_profitem first = {"init", (uint32_t) mg_millis()}; \
2974 mg_iobuf_init(&(c)->prof, 0, MG_PROFILE_ALLOC_GRANULARITY); \
2975 mg_iobuf_add(&c->prof, c->prof.len, &first, sizeof(first)); \
2976 } while (0)
2977 
2978#define MG_PROF_FREE(c) mg_iobuf_free(&(c)->prof)
2979 
2980// Dumping the profile. Not time sensitive
2981#define MG_PROF_DUMP(c) \
2982 do { \
2983 struct mg_iobuf *io = &c->prof; \
2984 struct mg_profitem *p = (struct mg_profitem *) io->buf; \
2985 struct mg_profitem *e = &p[io->len / sizeof(*p)]; \
2986 MG_INFO(("%lu profile:", c->id)); \
2987 while (p < e) { \
2988 MG_INFO(("%5lx %s", (unsigned long) p->timestamp, p->name)); \
2989 p++; \
2990 } \
2991 } while (0)
2992 
2993#else
2994#define MG_PROF_INIT(c)
2995#define MG_PROF_FREE(c)
2996#define MG_PROF_ADD(c, name)
2997#define MG_PROF_DUMP(c)
2998#endif
2999 
3000 
3001#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CMSIS) && MG_ENABLE_DRIVER_CMSIS
3002 
3003#include "Driver_ETH_MAC.h" // keep this include
3004#include "Driver_ETH_PHY.h" // keep this include
3005 
3006#endif
3007 
3008 
3009#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
3010 
3011struct mg_tcpip_spi_ {
3012 void *spi; // Opaque SPI bus descriptor
3013 void (*begin)(void *); // SPI begin: slave select low
3014 void (*end)(void *); // SPI end: slave select high
3015 void (*txn)(void *, uint8_t *, uint8_t *,
3016 size_t len); // SPI transaction: write-read len bytes
3017};
3018 
3019struct mg_tcpip_driver_cyw_firmware {
3020 const uint8_t *code_addr;
3021 size_t code_len;
3022 const uint8_t *nvram_addr;
3023 size_t nvram_len;
3024 const uint8_t *clm_addr;
3025 size_t clm_len;
3026};
3027 
3028struct mg_tcpip_driver_cyw_data {
3029 struct mg_tcpip_spi_ *spi;
3030 struct mg_tcpip_driver_cyw_firmware *fw;
3031 char *ssid;
3032 char *pass;
3033 char *apssid;
3034 char *appass;
3035 uint8_t security; // TBD
3036 uint8_t apsecurity; // TBD
3037 uint8_t apchannel;
3038 bool apmode; // start in AP mode; 'false' starts connection to 'ssid' if not NULL
3039 bool hs; // use chip "high-speed" mode; otherwise SPI CPOL0 CPHA0 (DS 4.2.3 Table 6)
3040};
3041 
3042#if 0
3043#define MG_TCPIP_DRIVER_INIT(mgr) \
3044 do { \
3045 static struct mg_tcpip_driver_cyw_data driver_data_; \
3046 static struct mg_tcpip_if mif_; \
3047 MG_SET_WIFI_CONFIG(&driver_data_); \
3048 mif_.ip = MG_TCPIP_IP; \
3049 mif_.mask = MG_TCPIP_MASK; \
3050 mif_.gw = MG_TCPIP_GW; \
3051 mif_.driver = &mg_tcpip_driver_pico_w; \
3052 mif_.driver_data = &driver_data_; \
3053 mif_.recv_queue.size = 8192; \
3054 mif_.mac[0] = 2; /* MAC read from OTP at driver init */ \
3055 mg_tcpip_init(mgr, &mif_); \
3056 MG_INFO(("Driver: cyw, MAC: %M", mg_print_mac, mif_.mac)); \
3057 } while (0)
3058#endif
3059 
3060#endif
3061 
3062 
3063#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
3064 
3065struct mg_tcpip_driver_imxrt_data {
3066 // MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
3067 // must not exceed 2.5MHz. Configuration for clock range 2.36~2.50 MHz
3068 // 37.5.1.8.2, Table 37-46 : f = ipg_clk / (2(mdc_cr + 1))
3069 // ipg_clk mdc_cr VALUE
3070 // --------------------------
3071 // -1 <-- TODO() tell driver to guess the value
3072 // 25 MHz 4
3073 // 33 MHz 6
3074 // 40 MHz 7
3075 // 50 MHz 9
3076 // 66 MHz 13
3077 int mdc_cr; // Valid values: -1 to 63
3078 
3079 uint8_t phy_addr; // PHY address
3080};
3081 
3082#ifndef MG_TCPIP_PHY_ADDR
3083#define MG_TCPIP_PHY_ADDR 2
3084#endif
3085 
3086#ifndef MG_DRIVER_MDC_CR
3087#define MG_DRIVER_MDC_CR 24
3088#endif
3089 
3090#define MG_TCPIP_DRIVER_INIT(mgr) \
3091 do { \
3092 static struct mg_tcpip_driver_imxrt_data driver_data_; \
3093 static struct mg_tcpip_if mif_; \
3094 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3095 driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
3096 mif_.ip = MG_TCPIP_IP; \
3097 mif_.mask = MG_TCPIP_MASK; \
3098 mif_.gw = MG_TCPIP_GW; \
3099 mif_.driver = &mg_tcpip_driver_imxrt; \
3100 mif_.driver_data = &driver_data_; \
3101 MG_SET_MAC_ADDRESS(mif_.mac); \
3102 mg_tcpip_init(mgr, &mif_); \
3103 MG_INFO(("Driver: imxrt, MAC: %M", mg_print_mac, mif_.mac)); \
3104 } while (0)
3105 
3106#endif
3107 
3108 
3109 
3110 
3111struct mg_phy {
3112 uint16_t (*read_reg)(uint8_t addr, uint8_t reg);
3113 void (*write_reg)(uint8_t addr, uint8_t reg, uint16_t value);
3114};
3115 
3116// PHY configuration settings, bitmask
3117enum {
3118 // Set if PHY LEDs are connected to ground
3119 MG_PHY_LEDS_ACTIVE_HIGH = (1 << 0),
3120 // Set when PHY clocks MAC. Otherwise, MAC clocks PHY
3121 MG_PHY_CLOCKS_MAC = (1 << 1)
3122};
3123 
3124enum { MG_PHY_SPEED_10M, MG_PHY_SPEED_100M, MG_PHY_SPEED_1000M };
3125 
3126void mg_phy_init(struct mg_phy *, uint8_t addr, uint8_t config);
3127bool mg_phy_up(struct mg_phy *, uint8_t addr, bool *full_duplex,
3128 uint8_t *speed);
3129 
3130 
3131#if MG_ENABLE_TCPIP && MG_ARCH == MG_ARCH_PICOSDK && \
3132 defined(MG_ENABLE_DRIVER_PICO_W) && MG_ENABLE_DRIVER_PICO_W
3133 
3134#include "cyw43.h" // keep this include
3135#include "pico/cyw43_arch.h" // keep this include
3136#include "pico/unique_id.h" // keep this include
3137 
3138struct mg_tcpip_driver_pico_w_data {
3139 char *ssid;
3140 char *pass;
3141 char *apssid;
3142 char *appass;
3143 uint8_t security; // TBD
3144 uint8_t apsecurity; // TBD
3145 uint8_t apchannel;
3146 bool apmode; // start in AP mode; 'false' starts connection to 'ssid' if not NULL
3147};
3148 
3149#define MG_TCPIP_DRIVER_INIT(mgr) \
3150 do { \
3151 static struct mg_tcpip_driver_pico_w_data driver_data_; \
3152 static struct mg_tcpip_if mif_; \
3153 MG_SET_WIFI_CONFIG(&driver_data_); \
3154 mif_.ip = MG_TCPIP_IP; \
3155 mif_.mask = MG_TCPIP_MASK; \
3156 mif_.gw = MG_TCPIP_GW; \
3157 mif_.driver = &mg_tcpip_driver_pico_w; \
3158 mif_.driver_data = &driver_data_; \
3159 mif_.recv_queue.size = 8192; \
3160 mif_.mac[0] = 2; /* MAC read from OTP at driver init */ \
3161 mg_tcpip_init(mgr, &mif_); \
3162 MG_INFO(("Driver: pico-w, MAC: %M", mg_print_mac, mif_.mac)); \
3163 } while (0)
3164 
3165#endif
3166 
3167 
3168struct mg_tcpip_driver_ppp_data {
3169 void *uart; // Opaque UART bus descriptor
3170 void (*reset)(void *); // Modem hardware reset
3171 void (*tx)(void *, uint8_t); // UART transmit single byte
3172 int (*rx)(void *); // UART receive single byte
3173 const char **script; // List of AT commands and expected replies
3174 int script_index; // Index of the current AT command in the list
3175 uint64_t deadline; // AT command deadline in ms
3176};
3177 
3178 
3179#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
3180 
3181struct mg_tcpip_driver_ra_data {
3182 // MDC clock "divider". MDC clock is software generated,
3183 uint32_t clock; // core clock frequency in Hz
3184 uint16_t irqno; // IRQn, R_ICU->IELSR[irqno]
3185 uint8_t phy_addr; // PHY address
3186};
3187 
3188#endif
3189 
3190 
3191#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RW612) && MG_ENABLE_DRIVER_RW612
3192 
3193struct mg_tcpip_driver_rw612_data {
3194 // 38.1.8 MII Speed Control Register (MSCR)
3195 // MDC clock frequency must not exceed 2.5 MHz and is calculated as follows:
3196 // MDC_freq = P_clock / ((mdc_cr + 1) * 2), where P_clock is the
3197 // peripheral bus clock.
3198 // IEEE802.3 clause 22 defines a minimum of 10 ns for the hold time on the
3199 // MDIO output. Depending on the host bus frequency, the setting may need
3200 // to be increased.
3201 int mdc_cr;
3202 int mdc_holdtime; // Valid values: [0-7]
3203 uint8_t phy_addr;
3204};
3205 
3206#ifndef MG_TCPIP_PHY_ADDR
3207#define MG_TCPIP_PHY_ADDR 2
3208#endif
3209 
3210#ifndef MG_DRIVER_MDC_CR
3211#define MG_DRIVER_MDC_CR 51
3212#endif
3213 
3214#ifndef MG_DRIVER_MDC_HOLDTIME
3215#define MG_DRIVER_MDC_HOLDTIME 3
3216#endif
3217 
3218#define MG_TCPIP_DRIVER_INIT(mgr) \
3219 do { \
3220 static struct mg_tcpip_driver_rw612_data driver_data_; \
3221 static struct mg_tcpip_if mif_; \
3222 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3223 driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
3224 mif_.ip = MG_TCPIP_IP; \
3225 mif_.mask = MG_TCPIP_MASK; \
3226 mif_.gw = MG_TCPIP_GW; \
3227 mif_.driver = &mg_tcpip_driver_rw612; \
3228 mif_.driver_data = &driver_data_; \
3229 MG_SET_MAC_ADDRESS(mif_.mac); \
3230 mg_tcpip_init(mgr, &mif_); \
3231 MG_INFO(("Driver: rw612, MAC: %M", mg_print_mac, mif_.mac)); \
3232 } while (0)
3233 
3234#endif
3235 
3236 
3237#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
3238 
3239struct mg_tcpip_driver_same54_data {
3240 int mdc_cr;
3241};
3242 
3243#ifndef MG_DRIVER_MDC_CR
3244#define MG_DRIVER_MDC_CR 5
3245#endif
3246 
3247#endif
3248 
3249 
3250#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_STM32F) && \
3251 MG_ENABLE_DRIVER_STM32F
3252 
3253struct mg_tcpip_driver_stm32f_data {
3254 // MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz
3255 // HCLK range DIVIDER mdc_cr VALUE
3256 // -------------------------------------
3257 // -1 <-- tell driver to guess the value
3258 // 60-100 MHz HCLK/42 0
3259 // 100-150 MHz HCLK/62 1
3260 // 20-35 MHz HCLK/16 2
3261 // 35-60 MHz HCLK/26 3
3262 // 150-216 MHz HCLK/102 4 <-- value for Nucleo-F* on max speed
3263 // 216-310 MHz HCLK/124 5
3264 // 110, 111 Reserved
3265 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
3266 
3267 uint8_t phy_addr; // PHY address
3268};
3269 
3270#ifndef MG_TCPIP_PHY_ADDR
3271#define MG_TCPIP_PHY_ADDR 0
3272#endif
3273 
3274#ifndef MG_DRIVER_MDC_CR
3275#define MG_DRIVER_MDC_CR 4
3276#endif
3277 
3278#define MG_TCPIP_DRIVER_INIT(mgr) \
3279 do { \
3280 static struct mg_tcpip_driver_stm32f_data driver_data_; \
3281 static struct mg_tcpip_if mif_; \
3282 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3283 driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
3284 mif_.ip = MG_TCPIP_IP; \
3285 mif_.mask = MG_TCPIP_MASK; \
3286 mif_.gw = MG_TCPIP_GW; \
3287 mif_.driver = &mg_tcpip_driver_stm32f; \
3288 mif_.driver_data = &driver_data_; \
3289 MG_SET_MAC_ADDRESS(mif_.mac); \
3290 mg_tcpip_init(mgr, &mif_); \
3291 MG_INFO(("Driver: stm32f, MAC: %M", mg_print_mac, mif_.mac)); \
3292 } while (0)
3293 
3294#endif
3295 
3296 
3297#if MG_ENABLE_TCPIP
3298#if !defined(MG_ENABLE_DRIVER_STM32H)
3299#define MG_ENABLE_DRIVER_STM32H 0
3300#endif
3301#if !defined(MG_ENABLE_DRIVER_MCXN)
3302#define MG_ENABLE_DRIVER_MCXN 0
3303#endif
3304#if MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN
3305 
3306struct mg_tcpip_driver_stm32h_data {
3307 // MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz
3308 // HCLK range DIVIDER mdc_cr VALUE
3309 // -------------------------------------
3310 // -1 <-- tell driver to guess the value
3311 // 60-100 MHz HCLK/42 0
3312 // 100-150 MHz HCLK/62 1
3313 // 20-35 MHz HCLK/16 2
3314 // 35-60 MHz HCLK/26 3
3315 // 150-250 MHz HCLK/102 4 <-- value for max speed HSI
3316 // 250-300 MHz HCLK/124 5 <-- value for Nucleo-H* on CSI
3317 // 300-500 MHz HCLK/204 6
3318 // 500-800 MHz HCLK/324 7
3319 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
3320 
3321 uint8_t phy_addr; // PHY address
3322 uint8_t phy_conf; // PHY config
3323};
3324 
3325#ifndef MG_TCPIP_PHY_CONF
3326#define MG_TCPIP_PHY_CONF MG_PHY_CLOCKS_MAC
3327#endif
3328 
3329#ifndef MG_TCPIP_PHY_ADDR
3330#define MG_TCPIP_PHY_ADDR 0
3331#endif
3332 
3333#ifndef MG_DRIVER_MDC_CR
3334#define MG_DRIVER_MDC_CR 4
3335#endif
3336 
3337#define MG_TCPIP_DRIVER_INIT(mgr) \
3338 do { \
3339 static struct mg_tcpip_driver_stm32h_data driver_data_; \
3340 static struct mg_tcpip_if mif_; \
3341 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3342 driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
3343 driver_data_.phy_conf = MG_TCPIP_PHY_CONF; \
3344 mif_.ip = MG_TCPIP_IP; \
3345 mif_.mask = MG_TCPIP_MASK; \
3346 mif_.gw = MG_TCPIP_GW; \
3347 mif_.driver = &mg_tcpip_driver_stm32h; \
3348 mif_.driver_data = &driver_data_; \
3349 MG_SET_MAC_ADDRESS(mif_.mac); \
3350 mg_tcpip_init(mgr, &mif_); \
3351 MG_INFO(("Driver: stm32h, MAC: %M", mg_print_mac, mif_.mac)); \
3352 } while (0)
3353 
3354#endif
3355#endif
3356 
3357 
3358#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TM4C) && MG_ENABLE_DRIVER_TM4C
3359 
3360struct mg_tcpip_driver_tm4c_data {
3361 // MDC clock divider. MDC clock is derived from SYSCLK, must not exceed 2.5MHz
3362 // SYSCLK range DIVIDER mdc_cr VALUE
3363 // -------------------------------------
3364 // -1 <-- tell driver to guess the value
3365 // 60-100 MHz SYSCLK/42 0
3366 // 100-150 MHz SYSCLK/62 1 <-- value for EK-TM4C129* on max speed
3367 // 20-35 MHz SYSCLK/16 2
3368 // 35-60 MHz SYSCLK/26 3
3369 // 0x4-0xF Reserved
3370 int mdc_cr; // Valid values: -1, 0, 1, 2, 3
3371};
3372 
3373#ifndef MG_DRIVER_MDC_CR
3374#define MG_DRIVER_MDC_CR 1
3375#endif
3376 
3377#define MG_TCPIP_DRIVER_INIT(mgr) \
3378 do { \
3379 static struct mg_tcpip_driver_tm4c_data driver_data_; \
3380 static struct mg_tcpip_if mif_; \
3381 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3382 mif_.ip = MG_TCPIP_IP; \
3383 mif_.mask = MG_TCPIP_MASK; \
3384 mif_.gw = MG_TCPIP_GW; \
3385 mif_.driver = &mg_tcpip_driver_tm4c; \
3386 mif_.driver_data = &driver_data_; \
3387 MG_SET_MAC_ADDRESS(mif_.mac); \
3388 mg_tcpip_init(mgr, &mif_); \
3389 MG_INFO(("Driver: tm4c, MAC: %M", mg_print_mac, mif_.mac)); \
3390 } while (0)
3391 
3392#endif
3393 
3394 
3395#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TMS570) && MG_ENABLE_DRIVER_TMS570
3396struct mg_tcpip_driver_tms570_data {
3397 int mdc_cr;
3398 int phy_addr;
3399};
3400 
3401#ifndef MG_TCPIP_PHY_ADDR
3402#define MG_TCPIP_PHY_ADDR 0
3403#endif
3404 
3405#ifndef MG_DRIVER_MDC_CR
3406#define MG_DRIVER_MDC_CR 1
3407#endif
3408 
3409#define MG_TCPIP_DRIVER_INIT(mgr) \
3410 do { \
3411 static struct mg_tcpip_driver_tms570_data driver_data_; \
3412 static struct mg_tcpip_if mif_; \
3413 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3414 driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
3415 mif_.ip = MG_TCPIP_IP; \
3416 mif_.mask = MG_TCPIP_MASK; \
3417 mif_.gw = MG_TCPIP_GW; \
3418 mif_.driver = &mg_tcpip_driver_tms570; \
3419 mif_.driver_data = &driver_data_; \
3420 MG_SET_MAC_ADDRESS(mif_.mac); \
3421 mg_tcpip_init(mgr, &mif_); \
3422 MG_INFO(("Driver: tms570, MAC: %M", mg_print_mac, mif_.mac));\
3423 } while (0)
3424#endif
3425 
3426 
3427 
3428#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC
3429 
3430struct mg_tcpip_driver_xmc_data {
3431 // 13.2.8.1 Station Management Functions
3432 // MDC clock divider (). MDC clock is derived from ETH MAC clock
3433 // It must not exceed 2.5MHz
3434 // ETH Clock range DIVIDER mdc_cr VALUE
3435 // --------------------------------------------
3436 // -1 <-- tell driver to guess the value
3437 // 60-100 MHz ETH Clock/42 0
3438 // 100-150 MHz ETH Clock/62 1
3439 // 20-35 MHz ETH Clock/16 2
3440 // 35-60 MHz ETH Clock/26 3
3441 // 150-250 MHz ETH Clock/102 4
3442 // 250-300 MHz ETH Clock/124 5
3443 // 110, 111 Reserved
3444 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
3445 uint8_t phy_addr;
3446};
3447 
3448#ifndef MG_TCPIP_PHY_ADDR
3449#define MG_TCPIP_PHY_ADDR 0
3450#endif
3451 
3452#ifndef MG_DRIVER_MDC_CR
3453#define MG_DRIVER_MDC_CR 4
3454#endif
3455 
3456#define MG_TCPIP_DRIVER_INIT(mgr) \
3457 do { \
3458 static struct mg_tcpip_driver_xmc_data driver_data_; \
3459 static struct mg_tcpip_if mif_; \
3460 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3461 driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
3462 mif_.ip = MG_TCPIP_IP; \
3463 mif_.mask = MG_TCPIP_MASK; \
3464 mif_.gw = MG_TCPIP_GW; \
3465 mif_.driver = &mg_tcpip_driver_xmc; \
3466 mif_.driver_data = &driver_data_; \
3467 MG_SET_MAC_ADDRESS(mif_.mac); \
3468 mg_tcpip_init(mgr, &mif_); \
3469 MG_INFO(("Driver: xmc, MAC: %M", mg_print_mac, mif_.mac)); \
3470 } while (0)
3471 
3472#endif
3473 
3474 
3475#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7
3476 
3477struct mg_tcpip_driver_xmc7_data {
3478 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
3479 uint8_t phy_addr;
3480};
3481 
3482#ifndef MG_TCPIP_PHY_ADDR
3483#define MG_TCPIP_PHY_ADDR 0
3484#endif
3485 
3486#ifndef MG_DRIVER_MDC_CR
3487#define MG_DRIVER_MDC_CR 3
3488#endif
3489 
3490#define MG_TCPIP_DRIVER_INIT(mgr) \
3491 do { \
3492 static struct mg_tcpip_driver_xmc7_data driver_data_; \
3493 static struct mg_tcpip_if mif_; \
3494 driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
3495 driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
3496 mif_.ip = MG_TCPIP_IP; \
3497 mif_.mask = MG_TCPIP_MASK; \
3498 mif_.gw = MG_TCPIP_GW; \
3499 mif_.driver = &mg_tcpip_driver_xmc7; \
3500 mif_.driver_data = &driver_data_; \
3501 MG_SET_MAC_ADDRESS(mif_.mac); \
3502 mg_tcpip_init(mgr, &mif_); \
3503 MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \
3504 } while (0)
3505 
3506#endif
3507 
3508 
3509#ifdef __cplusplus
3510}
3511#endif
3512#endif // MONGOOSE_H
3513