forked from cesanta/mongoose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.c
141 lines (132 loc) · 4.81 KB
/
util.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "util.h"
#if MG_ENABLE_CUSTOM_RANDOM
#else
void mg_random(void *buf, size_t len) {
bool done = false;
unsigned char *p = (unsigned char *) buf;
#if MG_ARCH == MG_ARCH_ESP32
while (len--) *p++ = (unsigned char) (esp_random() & 255);
done = true;
#elif MG_ARCH == MG_ARCH_WIN32
#elif MG_ARCH == MG_ARCH_UNIX
FILE *fp = fopen("/dev/urandom", "rb");
if (fp != NULL) {
if (fread(buf, 1, len, fp) == len) done = true;
fclose(fp);
}
#endif
// If everything above did not work, fallback to a pseudo random generator
while (!done && len--) *p++ = (unsigned char) (rand() & 255);
}
#endif
char *mg_random_str(char *buf, size_t len) {
size_t i;
mg_random(buf, len);
for (i = 0; i < len; i++) {
uint8_t c = ((uint8_t *) buf)[i] % 62U;
buf[i] = i == len - 1 ? (char) '\0' // 0-terminate last byte
: c < 26 ? (char) ('a' + c) // lowercase
: c < 52 ? (char) ('A' + c - 26) // uppercase
: (char) ('0' + c - 52); // numeric
}
return buf;
}
uint32_t mg_ntohl(uint32_t net) {
uint8_t data[4] = {0, 0, 0, 0};
memcpy(&data, &net, sizeof(data));
return (((uint32_t) data[3]) << 0) | (((uint32_t) data[2]) << 8) |
(((uint32_t) data[1]) << 16) | (((uint32_t) data[0]) << 24);
}
uint16_t mg_ntohs(uint16_t net) {
uint8_t data[2] = {0, 0};
memcpy(&data, &net, sizeof(data));
return (uint16_t) ((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
}
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
static const uint32_t crclut[16] = {
// table for polynomial 0xEDB88320 (reflected)
0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
crc = ~crc;
while (len--) {
uint8_t byte = *(uint8_t *)buf++;
crc = crclut[(crc ^ byte) & 0x0F] ^ (crc >> 4);
crc = crclut[(crc ^ (byte >> 4)) & 0x0F] ^ (crc >> 4);
}
return ~crc;
}
static int isbyte(int n) {
return n >= 0 && n <= 255;
}
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) {
int n, a, b, c, d, slash = 32, len = 0;
if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 &&
slash < 33) {
len = n;
*net = ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t) c << 8) |
(uint32_t) d;
*mask = slash ? (uint32_t) (0xffffffffU << (32 - slash)) : (uint32_t) 0;
}
return len;
}
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip) {
struct mg_str k, v;
int allowed = acl.len == 0 ? '+' : '-'; // If any ACL is set, deny by default
while (mg_commalist(&acl, &k, &v)) {
uint32_t net, mask;
if (k.ptr[0] != '+' && k.ptr[0] != '-') return -1;
if (parse_net(&k.ptr[1], &net, &mask) == 0) return -2;
if ((mg_ntohl(remote_ip) & mask) == net) allowed = k.ptr[0];
}
return allowed == '+';
}
#if MG_ENABLE_CUSTOM_MILLIS
#else
uint64_t mg_millis(void) {
#if MG_ARCH == MG_ARCH_WIN32
return GetTickCount();
#elif MG_ARCH == MG_ARCH_RP2040
return time_us_64() / 1000;
#elif MG_ARCH == MG_ARCH_ESP32
return esp_timer_get_time() / 1000;
#elif MG_ARCH == MG_ARCH_ESP8266 || MG_ARCH == MG_ARCH_FREERTOS
return xTaskGetTickCount() * portTICK_PERIOD_MS;
#elif MG_ARCH == MG_ARCH_AZURERTOS
return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
#elif MG_ARCH == MG_ARCH_TIRTOS
return (uint64_t) Clock_getTicks();
#elif MG_ARCH == MG_ARCH_ZEPHYR
return (uint64_t) k_uptime_get();
#elif MG_ARCH == MG_ARCH_CMSIS_RTOS1
return (uint64_t)rt_time_get();
#elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
return (uint64_t)((osKernelGetTickCount() * 1000) / osKernelGetTickFreq());
#elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
// Apple CLOCK_MONOTONIC_RAW is equivalent to CLOCK_BOOTTIME on linux
// Apple CLOCK_UPTIME_RAW is equivalent to CLOCK_MONOTONIC_RAW on linux
return clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000;
#elif MG_ARCH == MG_ARCH_UNIX
struct timespec ts = {0, 0};
// See #1615 - prefer monotonic clock
#if defined(CLOCK_MONOTONIC_RAW)
// Raw hardware-based time that is not subject to NTP adjustment
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
#elif defined(CLOCK_MONOTONIC)
// Affected by the incremental adjustments performed by adjtime and NTP
clock_gettime(CLOCK_MONOTONIC, &ts);
#else
// Affected by discontinuous jumps in the system time and by the incremental
// adjustments performed by adjtime and NTP
clock_gettime(CLOCK_REALTIME, &ts);
#endif
return ((uint64_t) ts.tv_sec * 1000 + (uint64_t) ts.tv_nsec / 1000000);
#elif defined(ARDUINO)
return (uint64_t) millis();
#else
return (uint64_t) (time(NULL) * 1000);
#endif
}
#endif