Line data Source code
1 : #include <minipot_utils.h>
2 : #include <fcntl.h>
3 : #include <stdarg.h>
4 : #include <errno.h>
5 : #include <sys/socket.h>
6 : #include <stdlib.h>
7 : #include <unistd.h>
8 :
9 : int minipot_set_nonblock(int fd) {
10 0 : int flags = fcntl(fd, F_GETFL);
11 0 : if (flags == -1)
12 : return -1;
13 0 : flags |= O_NONBLOCK;
14 0 : if (fcntl(fd, F_SETFL, flags) == -1)
15 0 : return -1;
16 : return 0;
17 : }
18 :
19 : int minipot_send_all(int fd, const void *data, size_t len) {
20 0 : while (len > 0) {
21 0 : ssize_t sent = send(fd, data, len, MSG_NOSIGNAL);
22 0 : if (sent == -1) {
23 0 : if (errno == EAGAIN || errno == EINTR)
24 0 : continue;
25 : return -1;
26 : }
27 0 : data += (size_t)sent;
28 0 : len -= (size_t)sent;
29 : }
30 : return 0;
31 : }
32 :
33 : int minipot_check_data(const uint8_t *buff, size_t len) {
34 0 : enum state{S0, S1, S2, S3, S4, S5, S6, S7} state = S0;
35 0 : for (size_t i = 0; i < len; i++) {
36 0 : switch (state) {
37 0 : case S0:
38 0 : if (buff[i] >= 1 && buff[i] <= 127)
39 : ; // stay at current state
40 0 : else if (buff[i] >= 194 && buff[i] <= 223)
41 : state = S1;
42 0 : else if (buff[i] == 224)
43 : state = S2;
44 : else if ((buff[i] >= 225 && buff[i] <= 236) ||
45 : (buff[i] >= 238 && buff[i] <= 239))
46 : state = S3;
47 : else if (buff[i] == 237)
48 : state = S4;
49 : else if (buff[i] == 240)
50 : state = S5;
51 : else if (buff[i] >= 241 && buff[i] <= 243)
52 : state = S6;
53 : else if (buff[i] == 244)
54 : state = S7;
55 : else
56 : return -1;
57 : break;
58 0 : case S1:
59 0 : if (buff[i] >= 128 && buff[i] <= 191)
60 : state = S0;
61 : else
62 : return -1;
63 : break;
64 0 : case S2:
65 0 : if (buff[i] >= 160 && buff[i] <= 191)
66 : state = S1;
67 : else
68 : return -1;
69 : break;
70 0 : case S3:
71 0 : if (buff[i] >= 128 && buff[i] <= 191)
72 : state = S1;
73 : else
74 : return -1;
75 : break;
76 0 : case S4:
77 0 : if (buff[i] >= 128 && buff[i] <= 159)
78 : state = S1;
79 : else
80 : return -1;
81 : break;
82 0 : case S5:
83 0 : if (buff[i] >= 144 && buff[i] <= 191)
84 : state = S3;
85 : else
86 : return -1;
87 : break;
88 0 : case S6:
89 0 : if (buff[i] >= 128 && buff[i] <= 191)
90 : state = S3;
91 : else
92 : return -1;
93 : break;
94 0 : case S7:
95 0 : if (buff[i] >= 128 && buff[i] <= 143)
96 : state = S3;
97 : else
98 : return -1;
99 : break;
100 : }
101 : }
102 : // check if the string is complete
103 0 : if (state == S0)
104 0 : return 0;
105 : return -1;
106 : }
107 :
108 : int minipot_write_all(int fd, const void *data, size_t len) {
109 0 : while (len > 0) {
110 0 : ssize_t written = write(fd, data, len);
111 0 : if (written == -1) {
112 0 : if (errno == EAGAIN || errno == EINTR)
113 0 : continue;
114 : return -1;
115 : }
116 0 : data += (size_t)written;
117 0 : len -= (size_t)written;
118 : }
119 : return 0;
120 : }
121 :
122 : int minipot_report(int fd, minipot_sentinel_msg_packer_t pk,
123 : struct minipot_sentinel_msg *msg) {
124 0 : if (minipot_check_sentinel_msg(msg))
125 : return -1;
126 0 : minipot_sentinel_msg_packer_pack(pk, msg);
127 0 : char *data = minipot_sentinel_msg_packer_retreive_data(pk);
128 0 : size_t dlen = minipot_sentinel_msg_packer_retreive_dlen(pk);
129 : // first send data length
130 0 : if (minipot_write_all(fd, &dlen, sizeof(dlen)))
131 : return -1;
132 : // then data
133 0 : return minipot_write_all(fd, data, dlen);
134 : }
135 :
136 : const uint8_t *minipot_skip_sel_bytes(const uint8_t *str, size_t str_len,
137 : const uint8_t *to_skip, size_t to_skip_len) {
138 0 : const uint8_t *end_ptr = str + str_len;
139 0 : size_t i = 0;
140 0 : while (str < end_ptr && i < to_skip_len)
141 0 : for (i = 0; i < to_skip_len; i++)
142 0 : if (*str == to_skip[i]) {
143 0 : str++;
144 0 : break;
145 : }
146 0 : return str;
147 : }
148 :
149 : const uint8_t *minipot_find_first_occur(const uint8_t *str, size_t str_len,
150 : const uint8_t *find, size_t find_len) {
151 0 : const uint8_t *end_ptr = str + str_len;
152 0 : while (str < end_ptr) {
153 0 : for (size_t i = 0; i < find_len; i++)
154 0 : if (*str == find[i])
155 0 : return str;
156 0 : str++;
157 : }
158 : return str;
159 : }
160 :
161 : size_t minipot_tokenize(const uint8_t *str, size_t str_len,
162 : struct minipot_token *tokens, size_t tokens_len,
163 : const uint8_t *separators, size_t sep_len) {
164 0 : size_t tokens_cnt = 0;
165 0 : const uint8_t *str_end = str + str_len;
166 0 : const uint8_t *token_start = str;
167 0 : size_t token_len = str_len;
168 0 : while (1) {
169 0 : token_start = minipot_skip_sel_bytes(token_start, token_len, separators,
170 : sep_len);
171 0 : if (token_start == str_end)
172 : break;
173 0 : token_len = str_end - token_start;
174 0 : const uint8_t *token_end = minipot_find_first_occur(token_start,
175 : token_len, separators, sep_len);
176 0 : tokens_cnt++;
177 : // fill token
178 0 : if (tokens_cnt <= tokens_len) {
179 0 : tokens[tokens_cnt - 1].start_ptr = token_start;
180 0 : tokens[tokens_cnt - 1].len = token_end - token_start;
181 : }
182 0 : if (token_end == str_end)
183 : break;
184 : token_start = token_end;
185 : }
186 0 : return tokens_cnt;
187 : }
|