/src/kamailio/src/core/tcp_read.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-2003 FhG Fokus |
3 | | * |
4 | | * This file is part of Kamailio, a free SIP server. |
5 | | * |
6 | | * Kamailio is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * Kamailio is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | /** Kamailio core :: tcp readers processes, tcp read and pre-parse msg. functions. |
22 | | * @file tcp_read.c |
23 | | * @ingroup core |
24 | | * Module: @ref core |
25 | | */ |
26 | | |
27 | | #ifdef USE_TCP |
28 | | |
29 | | #include <stdio.h> |
30 | | #include <errno.h> |
31 | | #include <string.h> |
32 | | |
33 | | |
34 | | #include <sys/time.h> |
35 | | #include <sys/types.h> |
36 | | #include <sys/select.h> |
37 | | #include <sys/socket.h> |
38 | | |
39 | | #include <unistd.h> |
40 | | #include <stdlib.h> /* for abort() */ |
41 | | |
42 | | #include "dprint.h" |
43 | | #include "tcp_conn.h" |
44 | | #include "tcp_read.h" |
45 | | #include "tcp_stats.h" |
46 | | #include "tcp_ev.h" |
47 | | #include "pass_fd.h" |
48 | | #include "globals.h" |
49 | | #include "receive.h" |
50 | | #include "timer.h" |
51 | | #include "local_timer.h" |
52 | | #include "ut.h" |
53 | | #include "trim.h" |
54 | | #include "pt.h" |
55 | | #include "daemonize.h" |
56 | | #include "cfg/cfg_struct.h" |
57 | | #ifdef CORE_TLS |
58 | | #include "tls/tls_server.h" |
59 | | #else |
60 | | #include "tls_hooks.h" |
61 | | #endif /* CORE_TLS */ |
62 | | #ifdef USE_DST_BLOCKLIST |
63 | | #include "dst_blocklist.h" |
64 | | #endif /* USE_DST_BLOCKLIST */ |
65 | | |
66 | | #define HANDLE_IO_INLINE |
67 | | #include "io_wait.h" |
68 | | #include <fcntl.h> /* must be included after io_wait.h if SIGIO_RT is used */ |
69 | | #include "tsend.h" |
70 | | #include "forward.h" |
71 | | #include "events.h" |
72 | | #include "stun.h" |
73 | | #include "nonsip_hooks.h" |
74 | | |
75 | | #ifdef READ_HTTP11 |
76 | 0 | #define HTTP11CONTINUE "HTTP/1.1 100 Continue\r\nContent-Length: 0\r\n\r\n" |
77 | 0 | #define HTTP11CONTINUE_LEN (sizeof(HTTP11CONTINUE) - 1) |
78 | | #endif |
79 | | |
80 | | #define TCPCONN_TIMEOUT_MIN_RUN 1 /* run the timers each new tick */ |
81 | | |
82 | | /* types used in io_wait* */ |
83 | | enum fd_types |
84 | | { |
85 | | F_NONE, |
86 | | F_TCPMAIN, |
87 | | F_TCPCONN |
88 | | }; |
89 | | |
90 | | /* list of tcp connections handled by this process */ |
91 | | static struct tcp_connection *tcp_conn_lst = 0; |
92 | | static io_wait_h io_w; /* io_wait handler*/ |
93 | | static int tcpmain_sock = -1; |
94 | | |
95 | | static struct local_timer tcp_reader_ltimer; |
96 | | static ticks_t tcp_reader_prev_ticks; |
97 | | |
98 | | int is_msg_complete(struct tcp_req *r); |
99 | | |
100 | | int ksr_tcp_accept_hep3 = 0; |
101 | | int ksr_tcp_accept_haproxy = 0; |
102 | | |
103 | 0 | #define TCP_SCRIPT_MODE_CONTINUE (1 << 0) |
104 | | int ksr_tcp_script_mode = 0; |
105 | | |
106 | | /** |
107 | | * control cloning of TCP receive buffer |
108 | | * - needed for operations working directly inside the buffer |
109 | | * (like msg_apply_changes()) |
110 | | */ |
111 | | #define TCP_CLONE_RCVBUF |
112 | | static int tcp_clone_rcvbuf = 0; |
113 | | |
114 | | int tcp_set_clone_rcvbuf(int v) |
115 | 0 | { |
116 | 0 | int r; |
117 | 0 | r = tcp_clone_rcvbuf; |
118 | 0 | tcp_clone_rcvbuf = v; |
119 | 0 | return r; |
120 | 0 | } |
121 | | |
122 | | int tcp_get_clone_rcvbuf(void) |
123 | 0 | { |
124 | 0 | return tcp_clone_rcvbuf; |
125 | 0 | } |
126 | | |
127 | | #ifdef READ_HTTP11 |
128 | | int tcp_http11_continue(struct tcp_connection *c) |
129 | 0 | { |
130 | 0 | struct dest_info dst; |
131 | 0 | char *p; |
132 | 0 | struct msg_start fline; |
133 | 0 | int ret; |
134 | 0 | str msg; |
135 | |
|
136 | 0 | ret = 0; |
137 | |
|
138 | 0 | msg.s = c->req.start; |
139 | 0 | msg.len = c->req.pos - c->req.start; |
140 | 0 | #ifdef READ_MSRP |
141 | | /* skip if MSRP message */ |
142 | 0 | if(c->req.flags & F_TCP_REQ_MSRP_FRAME) |
143 | 0 | return 0; |
144 | 0 | #endif |
145 | 0 | p = parse_first_line(msg.s, msg.len, &fline); |
146 | 0 | if(p == NULL) |
147 | 0 | return 0; |
148 | | |
149 | 0 | if(fline.type != SIP_REQUEST) |
150 | 0 | return 0; |
151 | | |
152 | | /* check if http request */ |
153 | 0 | if(fline.u.request.version.len < HTTP_VERSION_LEN |
154 | 0 | || strncasecmp( |
155 | 0 | fline.u.request.version.s, HTTP_VERSION, HTTP_VERSION_LEN)) |
156 | 0 | return 0; |
157 | | |
158 | | /* check for Expect header */ |
159 | 0 | if(str_casesearch_strz(&msg, "Expect: 100-continue") != NULL) { |
160 | 0 | init_dst_from_rcv(&dst, &c->rcv); |
161 | 0 | if(tcp_send(&dst, 0, HTTP11CONTINUE, HTTP11CONTINUE_LEN) < 0) { |
162 | 0 | LM_ERR("HTTP/1.1 continue failed\n"); |
163 | 0 | } |
164 | 0 | } |
165 | | /* check for Transfer-Encoding header */ |
166 | 0 | if(str_casesearch_strz(&msg, "Transfer-Encoding: chunked") != NULL) { |
167 | 0 | c->req.flags |= F_TCP_REQ_BCHUNKED; |
168 | 0 | ret = 1; |
169 | 0 | } |
170 | | /* check for HTTP Via header |
171 | | * - HTTP Via format is different that SIP Via |
172 | | * - workaround: replace with Hia to be ignored by SIP parser |
173 | | */ |
174 | 0 | if((p = str_casesearch_strz(&msg, "\nVia:")) != NULL) { |
175 | 0 | p++; |
176 | 0 | *p = 'H'; |
177 | 0 | LM_DBG("replaced HTTP Via with Hia [[\n%.*s]]\n", msg.len, msg.s); |
178 | 0 | } |
179 | 0 | return ret; |
180 | 0 | } |
181 | | #endif /* HTTP11 */ |
182 | | |
183 | | |
184 | | /** reads data from an existing tcp connection. |
185 | | * Side-effects: blocklisting, sets connection state to S_CONN_OK, tcp stats. |
186 | | * @param fd - connection file descriptor |
187 | | * @param c - tcp connection structure. c->state might be changed and |
188 | | * receive info might be used for blocklisting. |
189 | | * @param buf - buffer where the received data will be stored. |
190 | | * @param b_size - buffer size. |
191 | | * @param flags - value/result - used to signal a seen or "forced" EOF on the |
192 | | * connection (when it is known that no more data will come after the |
193 | | * current socket buffer is emptied )=> return/signal EOF on the first |
194 | | * short read (=> don't use it on POLLPRI, as OOB data will cause short |
195 | | * reads even if there are still remaining bytes in the socket buffer) |
196 | | * input: RD_CONN_FORCE_EOF - force EOF after the first successful read |
197 | | * (bytes_read >=0 ) |
198 | | * output: RD_CONN_SHORT_READ - if the read exhausted all the bytes |
199 | | * in the socket read buffer. |
200 | | * RD_CONN_EOF - if EOF detected (0 bytes read) or forced via |
201 | | * RD_CONN_FORCE_EOF. |
202 | | * RD_CONN_REPEAT_READ - the read should be repeated immediately |
203 | | * (used only by the tls code for now). |
204 | | * Note: RD_CONN_SHORT_READ & RD_CONN_EOF _are_ not cleared internally, |
205 | | * so one should clear them before calling this function. |
206 | | * @return number of bytes read, 0 on EOF or -1 on error, |
207 | | * on EOF it also sets c->state to S_CONN_EOF. |
208 | | * (to distinguish from reads that would block which could return 0) |
209 | | * RD_CONN_SHORT_READ is also set in *flags for short reads. |
210 | | * EOF checking should be done by checking the RD_CONN_EOF flag. |
211 | | */ |
212 | | int tcp_read_data(int fd, struct tcp_connection *c, char *buf, int b_size, |
213 | | rd_conn_flags_t *flags) |
214 | 0 | { |
215 | 0 | int bytes_read; |
216 | |
|
217 | 0 | again: |
218 | 0 | bytes_read = read(fd, buf, b_size); |
219 | |
|
220 | 0 | if(likely(bytes_read != b_size)) { |
221 | 0 | if(unlikely(bytes_read == -1)) { |
222 | 0 | if(errno == EWOULDBLOCK || errno == EAGAIN) { |
223 | 0 | bytes_read = 0; /* nothing has been read */ |
224 | 0 | } else if(errno == EINTR) { |
225 | 0 | goto again; |
226 | 0 | } else { |
227 | 0 | if(unlikely(c->state == S_CONN_CONNECT)) { |
228 | 0 | switch(errno) { |
229 | 0 | case ECONNRESET: |
230 | 0 | #ifdef USE_DST_BLOCKLIST |
231 | 0 | dst_blocklist_su(BLST_ERR_CONNECT, c->rcv.proto, |
232 | 0 | &c->rcv.src_su, &c->send_flags, 0); |
233 | 0 | #endif /* USE_DST_BLOCKLIST */ |
234 | 0 | TCP_EV_CONNECT_RST(errno, TCP_LADDR(c), |
235 | 0 | TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c)); |
236 | 0 | break; |
237 | 0 | case ETIMEDOUT: |
238 | 0 | #ifdef USE_DST_BLOCKLIST |
239 | 0 | dst_blocklist_su(BLST_ERR_CONNECT, c->rcv.proto, |
240 | 0 | &c->rcv.src_su, &c->send_flags, 0); |
241 | 0 | #endif /* USE_DST_BLOCKLIST */ |
242 | 0 | TCP_EV_CONNECT_TIMEOUT(errno, TCP_LADDR(c), |
243 | 0 | TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c)); |
244 | 0 | break; |
245 | 0 | default: |
246 | 0 | TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c), |
247 | 0 | TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c)); |
248 | 0 | } |
249 | 0 | TCP_STATS_CONNECT_FAILED(); |
250 | 0 | } else { |
251 | 0 | switch(errno) { |
252 | 0 | case ECONNRESET: |
253 | 0 | TCP_STATS_CON_RESET(); |
254 | 0 | #ifdef USE_DST_BLOCKLIST |
255 | 0 | dst_blocklist_su(BLST_ERR_SEND, c->rcv.proto, |
256 | 0 | &c->rcv.src_su, &c->send_flags, 0); |
257 | 0 | #endif /* USE_DST_BLOCKLIST */ |
258 | 0 | break; |
259 | 0 | case ETIMEDOUT: |
260 | 0 | #ifdef USE_DST_BLOCKLIST |
261 | 0 | dst_blocklist_su(BLST_ERR_SEND, c->rcv.proto, |
262 | 0 | &c->rcv.src_su, &c->send_flags, 0); |
263 | 0 | #endif /* USE_DST_BLOCKLIST */ |
264 | 0 | break; |
265 | 0 | } |
266 | 0 | } |
267 | 0 | LOG(cfg_get(core, core_cfg, corelog), |
268 | 0 | "error reading: %s (%d) ([%s]:%u ->", strerror(errno), |
269 | 0 | errno, ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); |
270 | 0 | LOG(cfg_get(core, core_cfg, corelog), "-> [%s]:%u)\n", |
271 | 0 | ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
272 | 0 | if(errno == ETIMEDOUT) { |
273 | 0 | c->event = TCP_CLOSED_TIMEOUT; |
274 | 0 | } else if(errno == ECONNRESET) { |
275 | 0 | c->event = TCP_CLOSED_RESET; |
276 | 0 | } |
277 | 0 | return -1; |
278 | 0 | } |
279 | 0 | } else if(unlikely((bytes_read == 0) || (*flags & RD_CONN_FORCE_EOF))) { |
280 | 0 | LM_DBG("EOF on connection %p (state: %u, flags: %x) - FD %d," |
281 | 0 | " bytes %d, rd-flags %x ([%s]:%u -> [%s]:%u)", |
282 | 0 | c, c->state, c->flags, fd, bytes_read, *flags, |
283 | 0 | ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, |
284 | 0 | ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
285 | 0 | c->state = S_CONN_EOF; |
286 | 0 | *flags |= RD_CONN_EOF; |
287 | 0 | c->event = TCP_CLOSED_EOF; |
288 | 0 | } else { |
289 | 0 | if(unlikely(c->state == S_CONN_CONNECT |
290 | 0 | || c->state == S_CONN_ACCEPT)) { |
291 | 0 | TCP_STATS_ESTABLISHED(c->state); |
292 | 0 | c->state = S_CONN_OK; |
293 | 0 | } |
294 | 0 | } |
295 | | /* short read */ |
296 | 0 | *flags |= RD_CONN_SHORT_READ; |
297 | 0 | } else { /* else normal full read */ |
298 | 0 | if(unlikely(c->state == S_CONN_CONNECT || c->state == S_CONN_ACCEPT)) { |
299 | 0 | TCP_STATS_ESTABLISHED(c->state); |
300 | 0 | c->state = S_CONN_OK; |
301 | 0 | } |
302 | 0 | } |
303 | 0 | return bytes_read; |
304 | 0 | } |
305 | | |
306 | | |
307 | | /* reads next available bytes |
308 | | * c- tcp connection used for reading, tcp_read changes also c->state on |
309 | | * EOF and c->req.error on read error |
310 | | * * flags - value/result - used to signal a seen or "forced" EOF on the |
311 | | * connection (when it is known that no more data will come after the |
312 | | * current socket buffer is emptied )=> return/signal EOF on the first |
313 | | * short read (=> don't use it on POLLPRI, as OOB data will cause short |
314 | | * reads even if there are still remaining bytes in the socket buffer) |
315 | | * return number of bytes read, 0 on EOF or -1 on error, |
316 | | * on EOF it also sets c->state to S_CONN_EOF. |
317 | | * (to distinguish from reads that would block which could return 0) |
318 | | * RD_CONN_SHORT_READ is also set in *flags for short reads. |
319 | | * sets also r->error */ |
320 | | int tcp_read(struct tcp_connection *c, rd_conn_flags_t *flags) |
321 | 0 | { |
322 | 0 | int bytes_free, bytes_read; |
323 | 0 | struct tcp_req *r; |
324 | 0 | int fd; |
325 | |
|
326 | 0 | r = &c->req; |
327 | 0 | fd = c->fd; |
328 | 0 | bytes_free = r->b_size - (unsigned int)(r->pos - r->buf); |
329 | |
|
330 | 0 | if(unlikely(bytes_free <= 0)) { |
331 | 0 | LM_ERR("buffer overrun, dropping ([%s]:%u -> [%s]:%u)\n", |
332 | 0 | ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, |
333 | 0 | ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
334 | 0 | r->error = TCP_REQ_OVERRUN; |
335 | 0 | return -1; |
336 | 0 | } |
337 | 0 | bytes_read = tcp_read_data(fd, c, r->pos, bytes_free, flags); |
338 | 0 | if(unlikely(bytes_read < 0)) { |
339 | 0 | r->error = TCP_READ_ERROR; |
340 | 0 | return -1; |
341 | 0 | } |
342 | | #ifdef EXTRA_DEBUG |
343 | | LM_DBG("read %d bytes:\n%.*s\n", bytes_read, bytes_read, r->pos); |
344 | | #endif |
345 | 0 | r->pos += bytes_read; |
346 | 0 | return bytes_read; |
347 | 0 | } |
348 | | |
349 | | |
350 | | /* reads all headers (until double crlf), & parses the content-length header |
351 | | * (WARNING: inefficient, tries to reuse receive_msg but will go through |
352 | | * the headers twice [once here looking for Content-Length and for the end |
353 | | * of the headers and once in receive_msg]; a more speed efficient version will |
354 | | * result in either major code duplication or major changes to the receive code) |
355 | | * returns number of bytes read & sets r->state & r->body |
356 | | * when either r->body!=0 or r->state==H_BODY => |
357 | | * all headers have been read. It should be called in a while loop. |
358 | | * returns < 0 if error or 0 if EOF */ |
359 | | int tcp_read_headers(struct tcp_connection *c, rd_conn_flags_t *read_flags) |
360 | 0 | { |
361 | 0 | int bytes, remaining; |
362 | 0 | char *p; |
363 | 0 | struct tcp_req *r; |
364 | 0 | unsigned int mc; /* magic cookie */ |
365 | 0 | unsigned short body_len; |
366 | 0 | struct timeval tvnow; |
367 | 0 | long long tvdiff; |
368 | |
|
369 | 0 | #ifdef READ_MSRP |
370 | 0 | char *mfline; |
371 | 0 | str mtransid; |
372 | 0 | #endif |
373 | |
|
374 | 0 | #define crlf_default_skip_case \ |
375 | 0 | case '\n': \ |
376 | 0 | r->state = H_LF; \ |
377 | 0 | break; \ |
378 | 0 | default: \ |
379 | 0 | r->state = H_SKIP |
380 | |
|
381 | 0 | #define content_len_beg_case \ |
382 | 0 | case ' ': \ |
383 | 0 | case '\t': \ |
384 | 0 | if(!TCP_REQ_HAS_CLEN(r)) \ |
385 | 0 | r->state = H_STARTWS; \ |
386 | 0 | else \ |
387 | 0 | r->state = H_SKIP; \ |
388 | | /* not interested if we already found one */ \ |
389 | 0 | break; \ |
390 | 0 | case 'C': \ |
391 | 0 | case 'c': \ |
392 | 0 | if(!TCP_REQ_HAS_CLEN(r)) \ |
393 | 0 | r->state = H_CONT_LEN1; \ |
394 | 0 | else \ |
395 | 0 | r->state = H_SKIP; \ |
396 | 0 | break; \ |
397 | 0 | case 'l': \ |
398 | 0 | case 'L': \ |
399 | | /* short form for Content-Length */ \ |
400 | 0 | if(!TCP_REQ_HAS_CLEN(r)) \ |
401 | 0 | r->state = H_L_COLON; \ |
402 | 0 | else \ |
403 | 0 | r->state = H_SKIP; \ |
404 | 0 | break |
405 | |
|
406 | 0 | #define change_state(upper, lower, newstate) \ |
407 | 0 | switch(*p) { \ |
408 | 0 | case upper: \ |
409 | 0 | case lower: \ |
410 | 0 | r->state = (newstate); \ |
411 | 0 | break; \ |
412 | 0 | crlf_default_skip_case; \ |
413 | 0 | } |
414 | |
|
415 | 0 | #define change_state_case(state0, upper, lower, newstate) \ |
416 | 0 | case state0: \ |
417 | 0 | change_state(upper, lower, newstate); \ |
418 | 0 | p++; \ |
419 | 0 | break |
420 | | |
421 | |
|
422 | 0 | r = &c->req; |
423 | 0 | if(r->parsed < r->buf || r->parsed > r->buf + r->b_size) { |
424 | 0 | if(r->parsed < r->buf && (unsigned char)r->state == H_SKIP_EMPTY) { |
425 | | /* give it a chance to parse from beginning */ |
426 | 0 | LM_WARN("resetting parsed pointer (buf:%p parsed:%p bsize:%u)\n", |
427 | 0 | r->buf, r->parsed, r->b_size); |
428 | 0 | r->parsed = r->buf; |
429 | 0 | } else { |
430 | 0 | LM_ERR("out of bounds parsed pointer (buf:%p parsed:%p bsize:%u)\n", |
431 | 0 | r->buf, r->parsed, r->b_size); |
432 | 0 | r->parsed = r->buf; |
433 | 0 | r->content_len = 0; |
434 | 0 | r->error = TCP_REQ_BAD_LEN; |
435 | 0 | r->state = H_SKIP; /* skip state now */ |
436 | 0 | return -1; |
437 | 0 | } |
438 | 0 | } |
439 | | /* if we still have some unparsed part, parse it first, don't do the read*/ |
440 | 0 | if(unlikely(r->parsed < r->pos)) { |
441 | 0 | bytes = 0; |
442 | 0 | } else { |
443 | 0 | #ifdef USE_TLS |
444 | 0 | if(unlikely(c->type == PROTO_TLS)) |
445 | 0 | bytes = tls_read(c, read_flags); |
446 | 0 | else |
447 | 0 | #endif |
448 | 0 | bytes = tcp_read(c, read_flags); |
449 | 0 | if(bytes <= 0) |
450 | 0 | return bytes; |
451 | 0 | gettimeofday(&tvnow, NULL); |
452 | 0 | tvdiff = 1000000 * (tvnow.tv_sec - r->tvrstart.tv_sec) |
453 | 0 | + (tvnow.tv_usec - r->tvrstart.tv_usec); |
454 | 0 | if(tvdiff >= ksr_tcp_msg_read_timeout * 1000000) { |
455 | 0 | LM_ERR("message reading timeout after %lld usec\n", tvdiff); |
456 | 0 | r->parsed = r->buf; |
457 | 0 | r->content_len = 0; |
458 | 0 | r->error = TCP_REQ_BAD_LEN; |
459 | 0 | r->state = H_SKIP; /* skip now */ |
460 | 0 | return -1; |
461 | 0 | } |
462 | 0 | } |
463 | 0 | p = r->parsed; |
464 | |
|
465 | 0 | while(p < r->pos && r->error == TCP_REQ_OK) { |
466 | 0 | switch((unsigned char)r->state) { |
467 | 0 | case H_BODY: /* read the body*/ |
468 | 0 | remaining = r->pos - p; |
469 | 0 | if(remaining > r->bytes_to_go) |
470 | 0 | remaining = r->bytes_to_go; |
471 | 0 | r->bytes_to_go -= remaining; |
472 | 0 | p += remaining; |
473 | 0 | if(r->bytes_to_go == 0) { |
474 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
475 | 0 | goto skip; |
476 | 0 | } |
477 | 0 | break; |
478 | | |
479 | 0 | case H_SKIP: |
480 | | /* find lf, we are in this state if we are not interested |
481 | | * in anything till end of line*/ |
482 | 0 | p = q_memchr(p, '\n', r->pos - p); |
483 | 0 | if(p) { |
484 | 0 | #ifdef READ_MSRP |
485 | | /* catch if it is MSRP or not with first '\n' */ |
486 | 0 | if(!((r->flags & F_TCP_REQ_MSRP_NO) |
487 | 0 | || (r->flags & F_TCP_REQ_MSRP_FRAME))) { |
488 | 0 | if((r->pos - r->start) > 5 |
489 | 0 | && strncmp(r->start, "MSRP ", 5) == 0) { |
490 | 0 | r->flags |= F_TCP_REQ_MSRP_FRAME; |
491 | 0 | } else { |
492 | 0 | r->flags |= F_TCP_REQ_MSRP_NO; |
493 | 0 | } |
494 | 0 | } |
495 | 0 | #endif |
496 | 0 | p++; |
497 | 0 | r->state = H_LF; |
498 | 0 | } else { |
499 | 0 | p = r->pos; |
500 | 0 | } |
501 | 0 | break; |
502 | | |
503 | 0 | case H_LF: |
504 | | /* terminate on LF CR LF or LF LF */ |
505 | 0 | switch(*p) { |
506 | 0 | case '\r': |
507 | 0 | r->state = H_LFCR; |
508 | 0 | break; |
509 | 0 | case '\n': |
510 | | /* found LF LF */ |
511 | 0 | r->state = H_BODY; |
512 | 0 | #ifdef READ_HTTP11 |
513 | 0 | if(cfg_get(tcp, tcp_cfg, accept_no_cl) != 0) |
514 | 0 | tcp_http11_continue(c); |
515 | 0 | #endif |
516 | 0 | if(TCP_REQ_HAS_CLEN(r)) { |
517 | 0 | r->body = p + 1; |
518 | 0 | r->bytes_to_go = r->content_len; |
519 | 0 | if(r->bytes_to_go == 0) { |
520 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
521 | 0 | p++; |
522 | 0 | goto skip; |
523 | 0 | } |
524 | 0 | } else { |
525 | 0 | if(cfg_get(tcp, tcp_cfg, accept_no_cl) != 0) { |
526 | 0 | #ifdef READ_MSRP |
527 | | /* if MSRP message */ |
528 | 0 | if(c->req.flags & F_TCP_REQ_MSRP_FRAME) { |
529 | 0 | r->body = p + 1; |
530 | | /* at least 3 bytes: 0\r\n */ |
531 | 0 | r->bytes_to_go = 3; |
532 | 0 | p++; |
533 | 0 | r->content_len = 0; |
534 | 0 | r->state = H_MSRP_BODY; |
535 | 0 | break; |
536 | 0 | } |
537 | 0 | #endif |
538 | | |
539 | 0 | #ifdef READ_HTTP11 |
540 | 0 | if(TCP_REQ_BCHUNKED(r)) { |
541 | 0 | r->body = p + 1; |
542 | | /* at least 3 bytes: 0\r\n */ |
543 | 0 | r->bytes_to_go = 3; |
544 | 0 | p++; |
545 | 0 | r->content_len = 0; |
546 | 0 | r->state = H_HTTP11_CHUNK_START; |
547 | 0 | break; |
548 | 0 | } |
549 | 0 | #endif |
550 | 0 | r->body = p + 1; |
551 | 0 | r->bytes_to_go = 0; |
552 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
553 | 0 | p++; |
554 | 0 | goto skip; |
555 | 0 | } else { |
556 | 0 | LM_DBG("no clen, p=%X\n", *p); |
557 | 0 | r->error = TCP_REQ_BAD_LEN; |
558 | 0 | } |
559 | 0 | } |
560 | 0 | break; |
561 | 0 | case '-': |
562 | 0 | r->state = H_SKIP; |
563 | 0 | #ifdef READ_MSRP |
564 | | /* catch end of MSRP frame without body |
565 | | * '-------sessid$\r\n' |
566 | | * follows headers without extra CRLF */ |
567 | 0 | if(r->flags & F_TCP_REQ_MSRP_FRAME) { |
568 | 0 | p--; |
569 | 0 | r->state = H_MSRP_BODY_END; |
570 | 0 | } |
571 | 0 | #endif |
572 | 0 | break; |
573 | 0 | content_len_beg_case; |
574 | 0 | default: |
575 | 0 | r->state = H_SKIP; |
576 | 0 | } |
577 | 0 | p++; |
578 | 0 | break; |
579 | 0 | case H_LFCR: |
580 | 0 | if(*p == '\n') { |
581 | | /* found LF CR LF */ |
582 | 0 | r->state = H_BODY; |
583 | 0 | #ifdef READ_HTTP11 |
584 | 0 | if(cfg_get(tcp, tcp_cfg, accept_no_cl) != 0) |
585 | 0 | tcp_http11_continue(c); |
586 | 0 | #endif |
587 | 0 | if(TCP_REQ_HAS_CLEN(r)) { |
588 | 0 | r->body = p + 1; |
589 | 0 | r->bytes_to_go = r->content_len; |
590 | 0 | if(r->bytes_to_go == 0) { |
591 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
592 | 0 | p++; |
593 | 0 | goto skip; |
594 | 0 | } |
595 | 0 | } else { |
596 | 0 | if(cfg_get(tcp, tcp_cfg, accept_no_cl) != 0) { |
597 | 0 | #ifdef READ_MSRP |
598 | | /* if MSRP message */ |
599 | 0 | if(c->req.flags & F_TCP_REQ_MSRP_FRAME) { |
600 | 0 | r->body = p + 1; |
601 | | /* at least 3 bytes: 0\r\n */ |
602 | 0 | r->bytes_to_go = 3; |
603 | 0 | p++; |
604 | 0 | r->content_len = 0; |
605 | 0 | r->state = H_MSRP_BODY; |
606 | 0 | break; |
607 | 0 | } |
608 | 0 | #endif |
609 | | |
610 | 0 | #ifdef READ_HTTP11 |
611 | 0 | if(TCP_REQ_BCHUNKED(r)) { |
612 | 0 | r->body = p + 1; |
613 | | /* at least 3 bytes: 0\r\n */ |
614 | 0 | r->bytes_to_go = 3; |
615 | 0 | p++; |
616 | 0 | r->content_len = 0; |
617 | 0 | r->state = H_HTTP11_CHUNK_START; |
618 | 0 | break; |
619 | 0 | } |
620 | 0 | #endif |
621 | 0 | r->body = p + 1; |
622 | 0 | r->bytes_to_go = 0; |
623 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
624 | 0 | p++; |
625 | 0 | goto skip; |
626 | 0 | } else { |
627 | 0 | LM_DBG("no clen, p=%X\n", *p); |
628 | 0 | r->error = TCP_REQ_BAD_LEN; |
629 | 0 | } |
630 | 0 | } |
631 | 0 | } else |
632 | 0 | r->state = H_SKIP; |
633 | 0 | p++; |
634 | 0 | break; |
635 | | |
636 | 0 | case H_STARTWS: |
637 | 0 | switch(*p) { |
638 | 0 | content_len_beg_case; |
639 | 0 | crlf_default_skip_case; |
640 | 0 | } |
641 | 0 | p++; |
642 | 0 | break; |
643 | 0 | case H_SKIP_EMPTY: |
644 | 0 | switch(*p) { |
645 | 0 | case '\n': |
646 | 0 | break; |
647 | 0 | case '\r': |
648 | 0 | if(cfg_get(tcp, tcp_cfg, crlf_ping)) { |
649 | 0 | r->state = H_SKIP_EMPTY_CR_FOUND; |
650 | 0 | r->start = p; |
651 | 0 | } |
652 | 0 | break; |
653 | 0 | case ' ': |
654 | 0 | case '\t': |
655 | | /* skip empty lines */ |
656 | 0 | break; |
657 | 0 | case 'C': |
658 | 0 | case 'c': |
659 | 0 | r->state = H_CONT_LEN1; |
660 | 0 | r->start = p; |
661 | 0 | break; |
662 | 0 | case 'l': |
663 | 0 | case 'L': |
664 | | /* short form for Content-Length */ |
665 | 0 | r->state = H_L_COLON; |
666 | 0 | r->start = p; |
667 | 0 | break; |
668 | 0 | default: |
669 | | /* stun test */ |
670 | 0 | if(unlikely(sr_event_enabled(SREV_STUN_IN)) |
671 | 0 | && (unsigned char)*p == 0x00) { |
672 | 0 | r->state = H_STUN_MSG; |
673 | | /* body is used as pointer to the last used byte */ |
674 | 0 | r->body = p; |
675 | 0 | r->content_len = 0; |
676 | 0 | LM_DBG("stun msg detected\n"); |
677 | 0 | } else { |
678 | 0 | r->state = H_SKIP; |
679 | 0 | } |
680 | 0 | r->start = p; |
681 | 0 | }; |
682 | 0 | p++; |
683 | 0 | break; |
684 | | |
685 | 0 | case H_SKIP_EMPTY_CR_FOUND: |
686 | 0 | if(*p == '\n') { |
687 | 0 | r->state = H_SKIP_EMPTY_CRLF_FOUND; |
688 | 0 | p++; |
689 | 0 | } else { |
690 | 0 | r->state = H_SKIP_EMPTY; |
691 | 0 | } |
692 | 0 | break; |
693 | | |
694 | 0 | case H_SKIP_EMPTY_CRLF_FOUND: |
695 | 0 | if(*p == '\r') { |
696 | 0 | r->state = H_SKIP_EMPTY_CRLFCR_FOUND; |
697 | 0 | p++; |
698 | 0 | } else { |
699 | 0 | r->state = H_SKIP_EMPTY; |
700 | 0 | } |
701 | 0 | break; |
702 | | |
703 | 0 | case H_SKIP_EMPTY_CRLFCR_FOUND: |
704 | 0 | if(*p == '\n') { |
705 | 0 | r->state = H_PING_CRLF; |
706 | 0 | r->flags |= |
707 | 0 | F_TCP_REQ_HAS_CLEN |
708 | 0 | | F_TCP_REQ_COMPLETE; /* hack to avoid error check */ |
709 | 0 | p++; |
710 | 0 | goto skip; |
711 | 0 | } else { |
712 | 0 | r->state = H_SKIP_EMPTY; |
713 | 0 | } |
714 | 0 | break; |
715 | | |
716 | 0 | case H_STUN_MSG: |
717 | 0 | if((r->pos - r->body) >= sizeof(struct stun_hdr)) { |
718 | | /* copy second short from buffer where should be body |
719 | | * length |
720 | | */ |
721 | 0 | memcpy(&body_len, &r->start[sizeof(unsigned short)], |
722 | 0 | sizeof(unsigned short)); |
723 | |
|
724 | 0 | body_len = ntohs(body_len); |
725 | | |
726 | | /* check if there is valid magic cookie */ |
727 | 0 | memcpy(&mc, &r->start[sizeof(unsigned int)], |
728 | 0 | sizeof(unsigned int)); |
729 | 0 | mc = ntohl(mc); |
730 | | /* using has_content_len as a flag if there should be |
731 | | * fingerprint or no |
732 | | */ |
733 | 0 | r->flags |= (mc == MAGIC_COOKIE) ? F_TCP_REQ_HAS_CLEN : 0; |
734 | |
|
735 | 0 | r->body += sizeof(struct stun_hdr); |
736 | 0 | p = r->body; |
737 | |
|
738 | 0 | if(body_len > 0) { |
739 | 0 | r->state = H_STUN_READ_BODY; |
740 | 0 | } else { |
741 | 0 | if(is_msg_complete(r) != 0) { |
742 | 0 | goto skip; |
743 | 0 | } else { |
744 | | /* set content_len to length of fingerprint */ |
745 | 0 | body_len = sizeof(struct stun_attr) + 20; |
746 | | /* 20 is SHA_DIGEST_LENGTH from openssl/sha.h */ |
747 | 0 | } |
748 | 0 | } |
749 | 0 | r->content_len = body_len; |
750 | 0 | } else { |
751 | 0 | p = r->pos; |
752 | 0 | } |
753 | 0 | break; |
754 | | |
755 | 0 | case H_STUN_READ_BODY: |
756 | | /* check if the whole body was read */ |
757 | 0 | body_len = r->content_len; |
758 | 0 | if((r->pos - r->body) >= body_len) { |
759 | 0 | r->body += body_len; |
760 | 0 | p = r->body; |
761 | 0 | if(is_msg_complete(r) != 0) { |
762 | 0 | r->content_len = 0; |
763 | 0 | goto skip; |
764 | 0 | } else { |
765 | | /* set content_len to length of fingerprint */ |
766 | 0 | body_len = sizeof(struct stun_attr) + 20; |
767 | | /* 20 is SHA_DIGEST_LENGTH from openssl/sha.h */ |
768 | 0 | r->content_len = body_len; |
769 | 0 | } |
770 | 0 | } else { |
771 | 0 | p = r->pos; |
772 | 0 | } |
773 | 0 | break; |
774 | | |
775 | 0 | case H_STUN_FP: |
776 | | /* content_len contains length of fingerprint in this place! */ |
777 | 0 | body_len = r->content_len; |
778 | 0 | if((r->pos - r->body) >= body_len) { |
779 | 0 | r->body += body_len; |
780 | 0 | p = r->body; |
781 | 0 | r->state = H_STUN_END; |
782 | 0 | r->flags |= |
783 | 0 | F_TCP_REQ_COMPLETE |
784 | 0 | | F_TCP_REQ_HAS_CLEN; /* hack to avoid error check */ |
785 | 0 | r->content_len = 0; |
786 | 0 | goto skip; |
787 | 0 | } else { |
788 | 0 | p = r->pos; |
789 | 0 | } |
790 | 0 | break; |
791 | | |
792 | 0 | change_state_case(H_CONT_LEN1, 'O', 'o', H_CONT_LEN2); |
793 | 0 | change_state_case(H_CONT_LEN2, 'N', 'n', H_CONT_LEN3); |
794 | 0 | change_state_case(H_CONT_LEN3, 'T', 't', H_CONT_LEN4); |
795 | 0 | change_state_case(H_CONT_LEN4, 'E', 'e', H_CONT_LEN5); |
796 | 0 | change_state_case(H_CONT_LEN5, 'N', 'n', H_CONT_LEN6); |
797 | 0 | change_state_case(H_CONT_LEN6, 'T', 't', H_CONT_LEN7); |
798 | 0 | change_state_case(H_CONT_LEN7, '-', '_', H_CONT_LEN8); |
799 | 0 | change_state_case(H_CONT_LEN8, 'L', 'l', H_CONT_LEN9); |
800 | 0 | change_state_case(H_CONT_LEN9, 'E', 'e', H_CONT_LEN10); |
801 | 0 | change_state_case(H_CONT_LEN10, 'N', 'n', H_CONT_LEN11); |
802 | 0 | change_state_case(H_CONT_LEN11, 'G', 'g', H_CONT_LEN12); |
803 | 0 | change_state_case(H_CONT_LEN12, 'T', 't', H_CONT_LEN13); |
804 | 0 | change_state_case(H_CONT_LEN13, 'H', 'h', H_L_COLON); |
805 | | |
806 | 0 | case H_L_COLON: |
807 | 0 | switch(*p) { |
808 | 0 | case ' ': |
809 | 0 | case '\t': |
810 | 0 | break; /* skip space */ |
811 | 0 | case ':': |
812 | 0 | r->state = H_CONT_LEN_BODY; |
813 | 0 | break; |
814 | 0 | crlf_default_skip_case; |
815 | 0 | }; |
816 | 0 | p++; |
817 | 0 | break; |
818 | | |
819 | 0 | case H_CONT_LEN_BODY: |
820 | 0 | switch(*p) { |
821 | 0 | case ' ': |
822 | 0 | case '\t': |
823 | 0 | break; /* eat space */ |
824 | 0 | case '0': |
825 | 0 | case '1': |
826 | 0 | case '2': |
827 | 0 | case '3': |
828 | 0 | case '4': |
829 | 0 | case '5': |
830 | 0 | case '6': |
831 | 0 | case '7': |
832 | 0 | case '8': |
833 | 0 | case '9': |
834 | 0 | r->state = H_CONT_LEN_BODY_PARSE; |
835 | 0 | r->content_len = (*p - '0'); |
836 | 0 | break; |
837 | | /* note: review case of content-length |
838 | | * on different lines */ |
839 | 0 | crlf_default_skip_case; |
840 | 0 | } |
841 | 0 | p++; |
842 | 0 | break; |
843 | | |
844 | 0 | case H_CONT_LEN_BODY_PARSE: |
845 | 0 | switch(*p) { |
846 | 0 | case '0': |
847 | 0 | case '1': |
848 | 0 | case '2': |
849 | 0 | case '3': |
850 | 0 | case '4': |
851 | 0 | case '5': |
852 | 0 | case '6': |
853 | 0 | case '7': |
854 | 0 | case '8': |
855 | 0 | case '9': |
856 | 0 | r->content_len = r->content_len * 10 + (*p - '0'); |
857 | 0 | break; |
858 | 0 | case '\r': |
859 | 0 | case ' ': |
860 | 0 | case '\t': |
861 | 0 | if(r->content_len < 0) { |
862 | 0 | LM_ERR("bad Content-Length header value %d in" |
863 | 0 | " state %d\n", |
864 | 0 | r->content_len, r->state); |
865 | 0 | r->content_len = 0; |
866 | 0 | r->error = TCP_REQ_BAD_LEN; |
867 | 0 | r->state = H_SKIP; /* skip now */ |
868 | 0 | } |
869 | 0 | r->state = H_SKIP; |
870 | 0 | r->flags |= F_TCP_REQ_HAS_CLEN; |
871 | 0 | break; |
872 | 0 | case '\n': |
873 | | /* end of line, parse successful */ |
874 | 0 | if(r->content_len < 0) { |
875 | 0 | LM_ERR("bad Content-Length header value %d in" |
876 | 0 | " state %d\n", |
877 | 0 | r->content_len, r->state); |
878 | 0 | r->content_len = 0; |
879 | 0 | r->error = TCP_REQ_BAD_LEN; |
880 | 0 | r->state = H_SKIP; /* skip now */ |
881 | 0 | } |
882 | 0 | r->state = H_LF; |
883 | 0 | r->flags |= F_TCP_REQ_HAS_CLEN; |
884 | 0 | break; |
885 | 0 | default: |
886 | 0 | LM_ERR("bad Content-Length header value, unexpected " |
887 | 0 | "char %c in state %d\n", |
888 | 0 | *p, r->state); |
889 | 0 | r->state = H_SKIP; /* try to find another?*/ |
890 | 0 | } |
891 | 0 | p++; |
892 | 0 | break; |
893 | | |
894 | 0 | #ifdef READ_HTTP11 |
895 | 0 | case H_HTTP11_CHUNK_START: /* start a new body chunk: SIZE\r\nBODY\r\n */ |
896 | 0 | r->chunk_size = 0; |
897 | 0 | r->state = H_HTTP11_CHUNK_SIZE; |
898 | 0 | break; |
899 | 0 | case H_HTTP11_CHUNK_BODY: /* content of chunk */ |
900 | 0 | remaining = r->pos - p; |
901 | 0 | if(remaining > r->bytes_to_go) |
902 | 0 | remaining = r->bytes_to_go; |
903 | 0 | r->bytes_to_go -= remaining; |
904 | 0 | p += remaining; |
905 | 0 | if(r->bytes_to_go == 0) { |
906 | 0 | r->state = H_HTTP11_CHUNK_END; |
907 | | /* shift back body content */ |
908 | 0 | if(r->chunk_size > 0 && p - r->chunk_size > r->body) { |
909 | 0 | memmove(r->body + r->content_len, p - r->chunk_size, |
910 | 0 | r->chunk_size); |
911 | 0 | r->content_len += r->chunk_size; |
912 | 0 | } |
913 | 0 | goto skip; |
914 | 0 | } |
915 | 0 | break; |
916 | | |
917 | 0 | case H_HTTP11_CHUNK_END: |
918 | 0 | switch(*p) { |
919 | 0 | case '\r': |
920 | 0 | case ' ': |
921 | 0 | case '\t': /* skip */ |
922 | 0 | break; |
923 | 0 | case '\n': |
924 | 0 | r->state = H_HTTP11_CHUNK_START; |
925 | 0 | break; |
926 | 0 | default: |
927 | 0 | LM_ERR("bad chunk, unexpected " |
928 | 0 | "char %c in state %d\n", |
929 | 0 | *p, r->state); |
930 | 0 | r->state = H_SKIP; /* try to find another?*/ |
931 | 0 | } |
932 | 0 | p++; |
933 | 0 | break; |
934 | | |
935 | 0 | case H_HTTP11_CHUNK_SIZE: |
936 | 0 | switch(*p) { |
937 | 0 | case '0': |
938 | 0 | case '1': |
939 | 0 | case '2': |
940 | 0 | case '3': |
941 | 0 | case '4': |
942 | 0 | case '5': |
943 | 0 | case '6': |
944 | 0 | case '7': |
945 | 0 | case '8': |
946 | 0 | case '9': |
947 | 0 | r->chunk_size <<= 4; |
948 | 0 | r->chunk_size += *p - '0'; |
949 | 0 | break; |
950 | 0 | case 'a': |
951 | 0 | case 'b': |
952 | 0 | case 'c': |
953 | 0 | case 'd': |
954 | 0 | case 'e': |
955 | 0 | case 'f': |
956 | 0 | r->chunk_size <<= 4; |
957 | 0 | r->chunk_size += *p - 'a' + 10; |
958 | 0 | break; |
959 | 0 | case 'A': |
960 | 0 | case 'B': |
961 | 0 | case 'C': |
962 | 0 | case 'D': |
963 | 0 | case 'E': |
964 | 0 | case 'F': |
965 | 0 | r->chunk_size <<= 4; |
966 | 0 | r->chunk_size += *p - 'A' + 10; |
967 | 0 | break; |
968 | 0 | case '\r': |
969 | 0 | case ' ': |
970 | 0 | case '\t': /* skip */ |
971 | 0 | break; |
972 | 0 | case '\n': |
973 | | /* end of line, parse successful */ |
974 | 0 | r->state = H_HTTP11_CHUNK_BODY; |
975 | 0 | r->bytes_to_go = r->chunk_size; |
976 | 0 | if(r->bytes_to_go == 0) { |
977 | 0 | r->state = H_HTTP11_CHUNK_FINISH; |
978 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
979 | 0 | p++; |
980 | 0 | goto skip; |
981 | 0 | } |
982 | 0 | break; |
983 | 0 | default: |
984 | 0 | LM_ERR("bad chunk size value, unexpected " |
985 | 0 | "char %c in state %d\n", |
986 | 0 | *p, r->state); |
987 | 0 | r->state = H_SKIP; /* try to find another?*/ |
988 | 0 | } |
989 | 0 | p++; |
990 | 0 | break; |
991 | 0 | #endif |
992 | 0 | #ifdef READ_MSRP |
993 | 0 | case H_MSRP_BODY: /* body of msrp frame */ |
994 | | /* find lf, we are in this state if we are not interested |
995 | | * in anything till end of line*/ |
996 | 0 | r->flags |= F_TCP_REQ_MSRP_BODY; |
997 | 0 | p = q_memchr(p, '\n', r->pos - p); |
998 | 0 | if(p) { |
999 | 0 | p++; |
1000 | 0 | r->state = H_MSRP_BODY_LF; |
1001 | 0 | } else { |
1002 | 0 | p = r->pos; |
1003 | 0 | } |
1004 | 0 | break; |
1005 | 0 | case H_MSRP_BODY_LF: /* LF in body of msrp frame */ |
1006 | 0 | switch(*p) { |
1007 | 0 | case '-': |
1008 | 0 | p--; |
1009 | 0 | r->state = H_MSRP_BODY_END; |
1010 | 0 | break; |
1011 | 0 | default: |
1012 | 0 | r->state = H_MSRP_BODY; |
1013 | 0 | } |
1014 | 0 | p++; |
1015 | 0 | break; |
1016 | 0 | case H_MSRP_BODY_END: /* end of body for msrp frame */ |
1017 | | /* find LF and check if it is end-line */ |
1018 | 0 | p = q_memchr(p, '\n', r->pos - p); |
1019 | 0 | if(p) { |
1020 | | /* check if it is end line '-------sessid$\r\n' */ |
1021 | 0 | if(r->pos - r->start < 10) { |
1022 | 0 | LM_ERR("weird situation when reading MSRP frame" |
1023 | 0 | " - continue reading\n"); |
1024 | | /* *p=='\n' */ |
1025 | 0 | r->state = H_MSRP_BODY_LF; |
1026 | 0 | p++; |
1027 | 0 | break; |
1028 | 0 | } |
1029 | 0 | if(*(p - 1) != '\r') { |
1030 | | /* not ending in '\r\n' - not end-line */ |
1031 | | /* *p=='\n' */ |
1032 | 0 | r->state = H_MSRP_BODY_LF; |
1033 | 0 | p++; |
1034 | 0 | break; |
1035 | 0 | } |
1036 | | /* locate transaction id in first line |
1037 | | * -- first line exists, that's why we are here */ |
1038 | 0 | mfline = q_memchr(r->start, '\n', r->pos - r->start); |
1039 | 0 | mtransid.s = q_memchr( |
1040 | 0 | r->start + 5 /* 'MSRP ' */, ' ', mfline - r->start); |
1041 | 0 | mtransid.len = mtransid.s - r->start - 5; |
1042 | 0 | mtransid.s = r->start + 5; |
1043 | 0 | trim(&mtransid); |
1044 | 0 | if(memcmp(mtransid.s, |
1045 | 0 | p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ |
1046 | 0 | - mtransid.len, |
1047 | 0 | mtransid.len) |
1048 | 0 | != 0) { |
1049 | | /* no match on session id - not end-line */ |
1050 | | /* *p=='\n' */ |
1051 | 0 | r->state = H_MSRP_BODY_LF; |
1052 | 0 | p++; |
1053 | 0 | break; |
1054 | 0 | } |
1055 | 0 | if(memcmp(p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - mtransid.len |
1056 | 0 | - 7 /* 7 x '-' */ - 1 /* '\n' */, |
1057 | 0 | "\n-------", 8) |
1058 | 0 | != 0) { |
1059 | | /* no match on "\n-------" - not end-line */ |
1060 | | /* *p=='\n' */ |
1061 | 0 | r->state = H_MSRP_BODY_LF; |
1062 | 0 | p++; |
1063 | 0 | break; |
1064 | 0 | } |
1065 | 0 | r->state = H_MSRP_FINISH; |
1066 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
1067 | 0 | p++; |
1068 | 0 | goto skip; |
1069 | |
|
1070 | 0 | } else { |
1071 | 0 | p = r->pos; |
1072 | 0 | } |
1073 | 0 | break; |
1074 | 0 | #endif |
1075 | | |
1076 | 0 | default: |
1077 | 0 | LM_CRIT("unexpected state %d\n", r->state); |
1078 | 0 | abort(); |
1079 | 0 | } |
1080 | 0 | } |
1081 | 0 | skip: |
1082 | 0 | r->parsed = p; |
1083 | 0 | return bytes; |
1084 | 0 | } |
1085 | | |
1086 | | |
1087 | | #ifdef READ_MSRP |
1088 | | int msrp_process_msg(char *tcpbuf, unsigned int len, |
1089 | | struct receive_info *rcv_info, struct tcp_connection *con) |
1090 | 0 | { |
1091 | 0 | int ret; |
1092 | 0 | tcp_event_info_t tev; |
1093 | 0 | sr_event_param_t evp = {0}; |
1094 | |
|
1095 | 0 | ret = 0; |
1096 | 0 | LM_DBG("MSRP Message: [[>>>\n%.*s<<<]]\n", len, tcpbuf); |
1097 | 0 | if(likely(sr_event_enabled(SREV_TCP_MSRP_FRAME))) { |
1098 | 0 | memset(&tev, 0, sizeof(tcp_event_info_t)); |
1099 | 0 | tev.type = SREV_TCP_MSRP_FRAME; |
1100 | 0 | tev.buf = tcpbuf; |
1101 | 0 | tev.len = len; |
1102 | 0 | tev.rcv = rcv_info; |
1103 | 0 | tev.con = con; |
1104 | 0 | evp.data = (void *)(&tev); |
1105 | 0 | ret = sr_event_exec(SREV_TCP_MSRP_FRAME, &evp); |
1106 | 0 | } else { |
1107 | 0 | LM_DBG("no callback registering for handling MSRP - dropping!\n"); |
1108 | 0 | } |
1109 | 0 | return ret; |
1110 | 0 | } |
1111 | | #endif |
1112 | | |
1113 | | #ifdef READ_WS |
1114 | | static int tcp_read_ws(struct tcp_connection *c, rd_conn_flags_t *read_flags) |
1115 | 0 | { |
1116 | 0 | int bytes; |
1117 | 0 | uint32_t size, pos, mask_present, len; |
1118 | 0 | char *p; |
1119 | 0 | struct tcp_req *r; |
1120 | |
|
1121 | 0 | r = &c->req; |
1122 | 0 | #ifdef USE_TLS |
1123 | 0 | if(unlikely(c->type == PROTO_WSS)) |
1124 | 0 | bytes = tls_read(c, read_flags); |
1125 | 0 | else |
1126 | 0 | #endif |
1127 | 0 | bytes = tcp_read(c, read_flags); |
1128 | |
|
1129 | 0 | if(bytes < 0) { |
1130 | | /* read error */ |
1131 | 0 | return bytes; |
1132 | 0 | } |
1133 | 0 | if(r->parsed == r->pos) { |
1134 | | /* nothing else to parse */ |
1135 | 0 | return bytes; |
1136 | 0 | } |
1137 | 0 | if(r->parsed > r->pos) { |
1138 | 0 | LM_ERR("req buf pos (%p) before parsed (%p) [%d]\n", r->pos, r->parsed, |
1139 | 0 | bytes); |
1140 | 0 | return -1; |
1141 | 0 | } |
1142 | 0 | if(r->pos > r->buf + r->b_size) { |
1143 | 0 | LM_ERR("req pos (%p) over buf (%p / %u) - parsed (%p) [%d]\n", r->pos, |
1144 | 0 | r->buf, r->b_size, r->parsed, bytes); |
1145 | 0 | return -1; |
1146 | 0 | } |
1147 | 0 | if(r->buf > r->parsed) { |
1148 | 0 | LM_ERR("req parsed (%p) before buf (%p / %u) - pos (%p) [%d]\n", |
1149 | 0 | r->parsed, r->buf, r->b_size, r->pos, bytes); |
1150 | 0 | return -1; |
1151 | 0 | } |
1152 | | |
1153 | 0 | size = r->pos - r->parsed; |
1154 | |
|
1155 | 0 | p = r->parsed; |
1156 | 0 | pos = 0; |
1157 | | |
1158 | | /* |
1159 | | 0 1 2 3 |
1160 | | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
1161 | | +-+-+-+-+-------+-+-------------+-------------------------------+ |
1162 | | |F|R|R|R| opcode|M| Payload len | Extended payload length | |
1163 | | |I|S|S|S| (4) |A| (7) | (16/64) | |
1164 | | |N|V|V|V| |S| | (if payload len==126/127) | |
1165 | | | |1|2|3| |K| | | |
1166 | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + |
1167 | | | Extended payload length continued, if payload len == 127 | |
1168 | | + - - - - - - - - - - - - - - - +-------------------------------+ |
1169 | | | |Masking-key, if MASK set to 1 | |
1170 | | +-------------------------------+-------------------------------+ |
1171 | | | Masking-key (continued) | Payload Data | |
1172 | | +-------------------------------- - - - - - - - - - - - - - - - + |
1173 | | : Payload Data continued ... : |
1174 | | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |
1175 | | | Payload Data continued ... | |
1176 | | +---------------------------------------------------------------+ |
1177 | | |
1178 | | Do minimal parse required to make sure the full message has been |
1179 | | received (websocket module will do full parse and validation). |
1180 | | */ |
1181 | | |
1182 | | /* Process first two bytes */ |
1183 | 0 | if(size < pos + 2) |
1184 | 0 | goto skip; |
1185 | 0 | pos++; |
1186 | 0 | mask_present = p[pos] & 0x80; |
1187 | 0 | len = (p[pos] & 0xff) & ~0x80; |
1188 | 0 | pos++; |
1189 | | |
1190 | | /* Work out real length */ |
1191 | 0 | if(len == 126) { |
1192 | | /* 2 bytes store the payload size */ |
1193 | 0 | if(size < pos + 2) |
1194 | 0 | goto skip; |
1195 | | |
1196 | 0 | len = ((p[pos + 0] & 0xff) << 8) | ((p[pos + 1] & 0xff) << 0); |
1197 | 0 | pos += 2; |
1198 | 0 | } else if(len == 127) { |
1199 | | /* 8 bytes store the payload size */ |
1200 | 0 | if(size < pos + 8) { |
1201 | 0 | goto skip; |
1202 | 0 | } |
1203 | | |
1204 | | /* Only decoding the last four bytes of the length... |
1205 | | This limits the size of WebSocket messages that can be |
1206 | | handled to 2^32 - which should be plenty for SIP! */ |
1207 | 0 | if((p[pos] & 0xff) != 0 || (p[pos + 1] & 0xff) != 0 |
1208 | 0 | || (p[pos + 2] & 0xff) != 0 || (p[pos + 3] & 0xff) != 0) { |
1209 | 0 | LM_WARN("advertised length is too large (more than 2^32)\n"); |
1210 | 0 | goto skip; |
1211 | 0 | } |
1212 | 0 | len = ((p[pos + 4] & 0xff) << 24) | ((p[pos + 5] & 0xff) << 16) |
1213 | 0 | | ((p[pos + 6] & 0xff) << 8) | ((p[pos + 7] & 0xff) << 0); |
1214 | 0 | pos += 8; |
1215 | 0 | } |
1216 | | |
1217 | | /* Skip mask */ |
1218 | 0 | if(mask_present) { |
1219 | 0 | if(size < pos + 4) |
1220 | 0 | goto skip; |
1221 | 0 | pos += 4; |
1222 | 0 | } |
1223 | | |
1224 | | /* check if advertised length fits in read buffer */ |
1225 | 0 | if(len >= r->b_size) { |
1226 | 0 | LM_WARN("advertised length (%u) greater than buffer size (%u)\n", len, |
1227 | 0 | r->b_size); |
1228 | 0 | goto skip; |
1229 | 0 | } |
1230 | | /* Now check the whole message has been received */ |
1231 | 0 | if(size < pos + len) |
1232 | 0 | goto skip; |
1233 | | |
1234 | 0 | pos += len; |
1235 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
1236 | 0 | r->parsed = &p[pos]; |
1237 | |
|
1238 | 0 | skip: |
1239 | 0 | return bytes; |
1240 | 0 | } |
1241 | | |
1242 | | static int ws_process_msg(char *tcpbuf, unsigned int len, |
1243 | | struct receive_info *rcv_info, struct tcp_connection *con) |
1244 | 0 | { |
1245 | 0 | int ret; |
1246 | 0 | tcp_event_info_t tev; |
1247 | 0 | sr_event_param_t evp = {0}; |
1248 | |
|
1249 | 0 | ret = 0; |
1250 | 0 | LM_DBG("WebSocket Message: [[>>>\n%.*s<<<]]\n", len, tcpbuf); |
1251 | 0 | if(likely(sr_event_enabled(SREV_TCP_WS_FRAME_IN))) { |
1252 | 0 | memset(&tev, 0, sizeof(tcp_event_info_t)); |
1253 | 0 | tev.type = SREV_TCP_WS_FRAME_IN; |
1254 | 0 | tev.buf = tcpbuf; |
1255 | 0 | tev.len = len; |
1256 | 0 | tev.rcv = rcv_info; |
1257 | 0 | tev.con = con; |
1258 | 0 | evp.data = (void *)(&tev); |
1259 | 0 | ret = sr_event_exec(SREV_TCP_WS_FRAME_IN, &evp); |
1260 | 0 | } else { |
1261 | 0 | LM_DBG("no callback registering for handling WebSockets - dropping!\n"); |
1262 | 0 | } |
1263 | 0 | return ret; |
1264 | 0 | } |
1265 | | #endif |
1266 | | |
1267 | | static int tcp_read_hep3(struct tcp_connection *c, rd_conn_flags_t *read_flags) |
1268 | 0 | { |
1269 | 0 | int bytes; |
1270 | 0 | uint32_t size, len; |
1271 | 0 | char *p; |
1272 | 0 | struct tcp_req *r; |
1273 | |
|
1274 | 0 | r = &c->req; |
1275 | 0 | #ifdef USE_TLS |
1276 | 0 | if(unlikely(c->type == PROTO_TLS)) { |
1277 | 0 | bytes = tls_read(c, read_flags); |
1278 | 0 | } else { |
1279 | 0 | #endif |
1280 | 0 | bytes = tcp_read(c, read_flags); |
1281 | 0 | #ifdef USE_TLS |
1282 | 0 | } |
1283 | 0 | #endif |
1284 | |
|
1285 | 0 | if(bytes <= 0) { |
1286 | 0 | if(likely(r->parsed >= r->pos)) { |
1287 | 0 | LM_DBG("no new bytes to read, but still unparsed content\n"); |
1288 | 0 | return 0; |
1289 | 0 | } |
1290 | 0 | } |
1291 | | |
1292 | 0 | size = r->pos - r->parsed; |
1293 | |
|
1294 | 0 | p = r->parsed; |
1295 | | |
1296 | | /* Process first six bytes (HEP3 + 2 bytes the size)*/ |
1297 | 0 | if(size < 6) { |
1298 | 0 | LM_DBG("not enough bytes to parse (%u)\n", size); |
1299 | 0 | goto skip; |
1300 | 0 | } |
1301 | | |
1302 | 0 | if(p[0] != 'H' || p[1] != 'E' || p[2] != 'P' || p[3] != '3') { |
1303 | | /* not hep3 */ |
1304 | 0 | LM_DBG("not HEP3 packet header (%u): %c %c %c %c / %x %x %x %x\n", size, |
1305 | 0 | p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3]); |
1306 | 0 | goto skip; |
1307 | 0 | } |
1308 | 0 | r->flags |= F_TCP_REQ_HEP3; |
1309 | |
|
1310 | 0 | len = ((uint32_t)(p[4] & 0xff) << 8) + (p[5] & 0xff); |
1311 | | |
1312 | | /* check if advertised length fits in read buffer */ |
1313 | 0 | if(len >= r->b_size) { |
1314 | 0 | LM_WARN("advertised length (%u) greater than buffer size (%u)\n", len, |
1315 | 0 | r->b_size); |
1316 | 0 | goto skip; |
1317 | 0 | } |
1318 | | /* check the whole message has been received */ |
1319 | 0 | if(size < len) { |
1320 | 0 | LM_DBG("incomplete HEP3 packet (%u / %u)\n", len, size); |
1321 | 0 | goto skip; |
1322 | 0 | } |
1323 | | |
1324 | 0 | r->flags |= F_TCP_REQ_COMPLETE; |
1325 | 0 | r->parsed = p + len; |
1326 | 0 | LM_DBG("reading of HEP3 packet is complete (%u / %u)\n", len, size); |
1327 | |
|
1328 | 0 | skip: |
1329 | 0 | return bytes; |
1330 | 0 | } |
1331 | | |
1332 | | static int hep3_process_msg(char *tcpbuf, unsigned int len, |
1333 | | struct receive_info *rcv_info, struct tcp_connection *con) |
1334 | 0 | { |
1335 | 0 | sip_msg_t msg; |
1336 | 0 | int ret; |
1337 | 0 | sr_event_param_t evp = {0}; |
1338 | |
|
1339 | 0 | memset(&msg, 0, sizeof(sip_msg_t)); /* init everything to 0 */ |
1340 | | /* fill in msg */ |
1341 | 0 | msg.buf = tcpbuf; |
1342 | 0 | msg.len = len; |
1343 | | /* zero termination (termination of orig message below not that |
1344 | | * useful as most of the work is done with scratch-pad; -jiri */ |
1345 | | /* buf[len]=0; */ /* WARNING: zero term removed! */ |
1346 | 0 | msg.rcv = *rcv_info; |
1347 | 0 | msg.id = msg_no; |
1348 | 0 | msg.pid = my_pid(); |
1349 | 0 | msg.set_global_address = default_global_address; |
1350 | 0 | msg.set_global_port = default_global_port; |
1351 | |
|
1352 | 0 | if(likely(sr_msg_time == 1)) |
1353 | 0 | msg_set_time(&msg); |
1354 | 0 | evp.data = (void *)(&msg); |
1355 | 0 | ret = sr_event_exec(SREV_RCV_NOSIP, &evp); |
1356 | 0 | LM_DBG("running hep3 handling event returned %d\n", ret); |
1357 | 0 | if(ret == NONSIP_MSG_DROP) { |
1358 | 0 | free_sip_msg(&msg); |
1359 | 0 | return 0; |
1360 | 0 | } |
1361 | 0 | if(ret < 0) { |
1362 | 0 | LM_ERR("error running hep3 handling event: %d\n", ret); |
1363 | 0 | free_sip_msg(&msg); |
1364 | 0 | return -1; |
1365 | 0 | } |
1366 | | |
1367 | 0 | ret = receive_msg(msg.buf, msg.len, &msg.rcv); |
1368 | 0 | LM_DBG("running hep3-enclosed sip request route returned %d\n", ret); |
1369 | 0 | free_sip_msg(&msg); |
1370 | |
|
1371 | 0 | return ret; |
1372 | 0 | } |
1373 | | |
1374 | | /** |
1375 | | * @brief wrapper around receive_msg() to clone the tcpbuf content |
1376 | | * |
1377 | | * When receiving over TCP, tcpbuf points inside the TCP stream buffer, but during |
1378 | | * processing of config, msg->buf content might be changed and may corrupt |
1379 | | * the content of the stream. Safer, make a clone of buf content in a local |
1380 | | * buffer and give that to receive_msg() to link to msg->buf |
1381 | | */ |
1382 | | int receive_tcp_msg(char *tcpbuf, unsigned int len, |
1383 | | struct receive_info *rcv_info, struct tcp_connection *con) |
1384 | 0 | { |
1385 | 0 | int ret = 0; |
1386 | 0 | #ifdef TCP_CLONE_RCVBUF |
1387 | 0 | static char *buf = NULL; |
1388 | 0 | static unsigned int bsize = 0; |
1389 | 0 | int blen; |
1390 | | |
1391 | | /* cloning is disabled via parameter */ |
1392 | 0 | if(likely(tcp_clone_rcvbuf == 0)) { |
1393 | 0 | #ifdef READ_MSRP |
1394 | 0 | if(unlikely(con->req.flags & F_TCP_REQ_MSRP_FRAME)) |
1395 | 0 | return msrp_process_msg(tcpbuf, len, rcv_info, con); |
1396 | 0 | #endif |
1397 | 0 | #ifdef READ_WS |
1398 | 0 | if(unlikely(con->type == PROTO_WS || con->type == PROTO_WSS)) |
1399 | 0 | return ws_process_msg(tcpbuf, len, rcv_info, con); |
1400 | 0 | #endif |
1401 | 0 | if(unlikely(con->req.flags & F_TCP_REQ_HEP3)) |
1402 | 0 | return hep3_process_msg(tcpbuf, len, rcv_info, con); |
1403 | | |
1404 | 0 | ret = receive_msg(tcpbuf, len, rcv_info); |
1405 | 0 | if(ksr_tcp_script_mode & TCP_SCRIPT_MODE_CONTINUE) { |
1406 | 0 | return 0; |
1407 | 0 | } |
1408 | 0 | return ret; |
1409 | 0 | } |
1410 | | |
1411 | | /* min buffer size is BUF_SIZE */ |
1412 | 0 | blen = len; |
1413 | 0 | if(blen < BUF_SIZE) |
1414 | 0 | blen = BUF_SIZE; |
1415 | | |
1416 | | /* allocate buffer when needed |
1417 | | * - no buffer yet |
1418 | | * - existing buffer too small (min size is BUF_SIZE - to accommodate most |
1419 | | * of SIP messages; expected larger for HTTP/XCAP) |
1420 | | * - existing buffer too large (e.g., we got a too big message in the past, |
1421 | | * let's free it) |
1422 | | * |
1423 | | * - also, use system memory, not to eat from PKG (same as static buffer |
1424 | | * from PKG pov) |
1425 | | */ |
1426 | 0 | if(buf == NULL || bsize < blen || blen < bsize / 2) { |
1427 | 0 | if(buf != NULL) |
1428 | 0 | free(buf); |
1429 | 0 | buf = malloc(blen + 1); |
1430 | 0 | if(buf == 0) { |
1431 | 0 | SYS_MEM_ERROR; |
1432 | 0 | return -1; |
1433 | 0 | } |
1434 | 0 | bsize = blen; |
1435 | 0 | } |
1436 | | |
1437 | 0 | memcpy(buf, tcpbuf, len); |
1438 | 0 | buf[len] = '\0'; |
1439 | 0 | #ifdef READ_MSRP |
1440 | 0 | if(unlikely(con->req.flags & F_TCP_REQ_MSRP_FRAME)) |
1441 | 0 | return msrp_process_msg(buf, len, rcv_info, con); |
1442 | 0 | #endif |
1443 | 0 | #ifdef READ_WS |
1444 | 0 | if(unlikely(con->type == PROTO_WS || con->type == PROTO_WSS)) |
1445 | 0 | return ws_process_msg(buf, len, rcv_info, con); |
1446 | 0 | #endif |
1447 | 0 | if(unlikely(con->req.flags & F_TCP_REQ_HEP3)) |
1448 | 0 | return hep3_process_msg(tcpbuf, len, rcv_info, con); |
1449 | 0 | ret = receive_msg(buf, len, rcv_info); |
1450 | 0 | if(ksr_tcp_script_mode & TCP_SCRIPT_MODE_CONTINUE) { |
1451 | 0 | return 0; |
1452 | 0 | } |
1453 | 0 | return ret; |
1454 | | #else /* TCP_CLONE_RCVBUF */ |
1455 | | #ifdef READ_MSRP |
1456 | | if(unlikely(con->req.flags & F_TCP_REQ_MSRP_FRAME)) |
1457 | | return msrp_process_msg(tcpbuf, len, rcv_info, con); |
1458 | | #endif |
1459 | | #ifdef READ_WS |
1460 | | if(unlikely(con->type == PROTO_WS || con->type == PROTO_WSS)) |
1461 | | return ws_process_msg(tcpbuf, len, rcv_info, con); |
1462 | | #endif |
1463 | | if(unlikely(con->req.flags & F_TCP_REQ_HEP3)) |
1464 | | return hep3_process_msg(tcpbuf, len, rcv_info, con); |
1465 | | ret = receive_msg(tcpbuf, len, rcv_info); |
1466 | | if(ksr_tcp_script_mode & TCP_SCRIPT_MODE_CONTINUE) { |
1467 | | return 0; |
1468 | | } |
1469 | | return ret; |
1470 | | #endif /* TCP_CLONE_RCVBUF */ |
1471 | 0 | } |
1472 | | |
1473 | | int tcp_read_req(struct tcp_connection *con, int *bytes_read, |
1474 | | rd_conn_flags_t *read_flags) |
1475 | 0 | { |
1476 | 0 | int bytes; |
1477 | 0 | int total_bytes; |
1478 | 0 | int resp; |
1479 | 0 | long size; |
1480 | 0 | struct tcp_req *req; |
1481 | 0 | struct dest_info dst; |
1482 | 0 | char c; |
1483 | 0 | int ret; |
1484 | |
|
1485 | 0 | bytes = -1; |
1486 | 0 | total_bytes = 0; |
1487 | 0 | resp = CONN_RELEASE; |
1488 | 0 | req = &con->req; |
1489 | 0 | if(req->tvrstart.tv_sec == 0) { |
1490 | 0 | gettimeofday(&req->tvrstart, NULL); |
1491 | 0 | } |
1492 | |
|
1493 | 0 | again: |
1494 | 0 | if(likely(req->error == TCP_REQ_OK)) { |
1495 | 0 | #ifdef READ_WS |
1496 | 0 | if(unlikely(con->type == PROTO_WS || con->type == PROTO_WSS)) { |
1497 | 0 | bytes = tcp_read_ws(con, read_flags); |
1498 | 0 | } else { |
1499 | 0 | #endif |
1500 | 0 | if(unlikely(ksr_tcp_accept_hep3 != 0)) { |
1501 | 0 | bytes = tcp_read_hep3(con, read_flags); |
1502 | 0 | if(bytes >= 0) { |
1503 | 0 | if(!(con->req.flags & F_TCP_REQ_HEP3)) { |
1504 | | /* not hep3, try to read headers */ |
1505 | 0 | bytes = tcp_read_headers(con, read_flags); |
1506 | 0 | } |
1507 | 0 | } |
1508 | 0 | } else { |
1509 | 0 | bytes = tcp_read_headers(con, read_flags); |
1510 | 0 | } |
1511 | 0 | #ifdef READ_WS |
1512 | 0 | } |
1513 | 0 | #endif |
1514 | |
|
1515 | 0 | if(ksr_msg_recv_max_size <= (int)(req->parsed - req->start)) { |
1516 | 0 | LOG(cfg_get(core, core_cfg, corelog), |
1517 | 0 | "read message too large: %d - c: %p r: %p (%d)\n", |
1518 | 0 | (int)(req->parsed - req->start), con, req, bytes); |
1519 | 0 | resp = CONN_ERROR; |
1520 | 0 | goto end_req; |
1521 | 0 | } |
1522 | | |
1523 | 0 | if(unlikely(bytes < 0)) { |
1524 | 0 | LOG(cfg_get(core, core_cfg, corelog), |
1525 | 0 | "ERROR: tcp_read_req: error reading - c: %p r: %p (%d)\n", |
1526 | 0 | con, req, bytes); |
1527 | 0 | resp = CONN_ERROR; |
1528 | 0 | goto end_req; |
1529 | 0 | } |
1530 | | |
1531 | | #ifdef EXTRA_DEBUG |
1532 | | /* if timeout state=0; goto end__req; */ |
1533 | | LM_DBG("read= %d bytes, parsed=%d, state=%d, error=%d\n", bytes, |
1534 | | (int)(req->parsed - req->start), req->state, req->error); |
1535 | | LM_DBG("last char=0x%02X, parsed msg=\n%.*s\n", *(req->parsed - 1), |
1536 | | (int)(req->parsed - req->start), req->start); |
1537 | | #endif |
1538 | 0 | total_bytes += bytes; |
1539 | | /* eof check: |
1540 | | * is EOF if eof on fd and req. not complete yet, |
1541 | | * if req. is complete we might have a second unparsed |
1542 | | * request after it, so postpone release_with_eof |
1543 | | */ |
1544 | 0 | if(unlikely((con->state == S_CONN_EOF) && (!TCP_REQ_COMPLETE(req)))) { |
1545 | 0 | LM_DBG("EOF\n"); |
1546 | 0 | resp = CONN_EOF; |
1547 | 0 | goto end_req; |
1548 | 0 | } |
1549 | 0 | } |
1550 | 0 | if(unlikely(req->error != TCP_REQ_OK)) { |
1551 | 0 | if(req->buf != NULL && req->start != NULL && req->pos != NULL |
1552 | 0 | && req->pos >= req->buf && req->parsed >= req->start) { |
1553 | 0 | LM_ERR("bad request, state=%d, error=%d " |
1554 | 0 | "buf:\n%.*s\nparsed:\n%.*s\n", |
1555 | 0 | req->state, req->error, (int)(req->pos - req->buf), |
1556 | 0 | req->buf, (int)(req->parsed - req->start), req->start); |
1557 | 0 | } else { |
1558 | 0 | LM_ERR("bad request, state=%d, error=%d buf:%d - %p," |
1559 | 0 | " parsed:%d - %p\n", |
1560 | 0 | req->state, req->error, (int)(req->pos - req->buf), |
1561 | 0 | req->buf, (int)(req->parsed - req->start), req->start); |
1562 | 0 | } |
1563 | 0 | LM_DBG("received from: port %d\n", con->rcv.src_port); |
1564 | 0 | print_ip("received from: ip", &con->rcv.src_ip, "\n"); |
1565 | 0 | resp = CONN_ERROR; |
1566 | 0 | goto end_req; |
1567 | 0 | } |
1568 | 0 | if(likely(TCP_REQ_COMPLETE(req))) { |
1569 | | #ifdef EXTRA_DEBUG |
1570 | | LM_DBG("end of header part\n"); |
1571 | | LM_DBG("received from: port %d\n", con->rcv.src_port); |
1572 | | print_ip("received from: ip", &con->rcv.src_ip, "\n"); |
1573 | | LM_DBG("headers:\n%.*s.\n", (int)(req->body - req->start), req->start); |
1574 | | #endif |
1575 | 0 | if(likely(TCP_REQ_HAS_CLEN(req))) { |
1576 | 0 | LM_DBG("content-length=%d\n", req->content_len); |
1577 | | #ifdef EXTRA_DEBUG |
1578 | | LM_DBG("body:\n%.*s\n", req->content_len, req->body); |
1579 | | #endif |
1580 | 0 | } else { |
1581 | 0 | if(cfg_get(tcp, tcp_cfg, accept_no_cl) == 0) { |
1582 | 0 | req->error = TCP_REQ_BAD_LEN; |
1583 | 0 | LM_ERR("content length not present or unparsable\n"); |
1584 | 0 | resp = CONN_ERROR; |
1585 | 0 | goto end_req; |
1586 | 0 | } |
1587 | 0 | } |
1588 | | /* if we are here everything is nice and ok*/ |
1589 | 0 | resp = CONN_RELEASE; |
1590 | 0 | if(req->state != H_PING_CRLF) { |
1591 | 0 | req->dxstate |= KSR_TCP_REQSTATE_DATARECV; |
1592 | 0 | } |
1593 | | #ifdef EXTRA_DEBUG |
1594 | | LM_DBG("receiving msg(%p, %d)\n", req->start, |
1595 | | (int)(req->parsed - req->start)); |
1596 | | #endif |
1597 | | /* rcv.bind_address should always be !=0 */ |
1598 | 0 | bind_address = con->rcv.bind_address; |
1599 | |
|
1600 | 0 | con->rcv.proto_reserved1 = con->id; /* copy the id */ |
1601 | 0 | c = *req->parsed; /* ugly hack: zero term the msg & save the |
1602 | | previous char, req->parsed should be ok |
1603 | | because we always alloc BUF_SIZE+1 */ |
1604 | 0 | *req->parsed = 0; |
1605 | |
|
1606 | 0 | if(req->state == H_PING_CRLF) { |
1607 | 0 | init_dst_from_rcv(&dst, &con->rcv); |
1608 | |
|
1609 | 0 | if(tcp_send(&dst, 0, CRLF, CRLF_LEN) < 0) { |
1610 | 0 | LM_ERR("CRLF ping: tcp_send() failed ([%s]:%u -> [%s]:%u)\n", |
1611 | 0 | ip_addr2a(&con->rcv.src_ip), con->rcv.src_port, |
1612 | 0 | ip_addr2a(&con->rcv.dst_ip), con->rcv.dst_port); |
1613 | 0 | } |
1614 | 0 | ret = 0; |
1615 | 0 | } else if(unlikely(req->state == H_STUN_END)) { |
1616 | | /* stun request */ |
1617 | 0 | ret = stun_process_msg( |
1618 | 0 | req->start, req->parsed - req->start, &con->rcv); |
1619 | 0 | } else |
1620 | 0 | #ifdef READ_MSRP |
1621 | | // if (unlikely(req->flags&F_TCP_REQ_MSRP_FRAME)){ |
1622 | 0 | if(unlikely(req->state == H_MSRP_FINISH)) { |
1623 | | /* msrp frame */ |
1624 | 0 | ret = receive_tcp_msg( |
1625 | 0 | req->start, req->parsed - req->start, &con->rcv, con); |
1626 | 0 | } else |
1627 | 0 | #endif |
1628 | 0 | #ifdef READ_HTTP11 |
1629 | 0 | if(unlikely(req->state == H_HTTP11_CHUNK_FINISH)) { |
1630 | | /* http chunked request */ |
1631 | 0 | req->body[req->content_len] = 0; |
1632 | 0 | ret = receive_tcp_msg(req->start, |
1633 | 0 | req->body + req->content_len - req->start, &con->rcv, |
1634 | 0 | con); |
1635 | 0 | } else |
1636 | 0 | #endif |
1637 | 0 | #ifdef READ_WS |
1638 | 0 | if(unlikely(con->type == PROTO_WS |
1639 | 0 | || con->type == PROTO_WSS)) { |
1640 | 0 | ret = receive_tcp_msg( |
1641 | 0 | req->start, req->parsed - req->start, &con->rcv, con); |
1642 | 0 | } else |
1643 | 0 | #endif |
1644 | 0 | ret = receive_tcp_msg( |
1645 | 0 | req->start, req->parsed - req->start, &con->rcv, con); |
1646 | |
|
1647 | 0 | if(unlikely(ret < 0)) { |
1648 | 0 | *req->parsed = c; |
1649 | 0 | resp = CONN_ERROR; |
1650 | 0 | goto end_req; |
1651 | 0 | } |
1652 | 0 | *req->parsed = c; |
1653 | | |
1654 | | /* prepare for next request */ |
1655 | 0 | size = req->pos - req->parsed; |
1656 | 0 | req->start = req->buf; |
1657 | 0 | req->body = 0; |
1658 | 0 | req->error = TCP_REQ_OK; |
1659 | 0 | req->state = H_SKIP_EMPTY; |
1660 | 0 | req->flags = 0; |
1661 | 0 | req->content_len = 0; |
1662 | 0 | req->bytes_to_go = 0; |
1663 | 0 | req->pos = req->buf + size; |
1664 | 0 | req->tvrstart.tv_sec = 0; |
1665 | 0 | req->tvrstart.tv_usec = 0; |
1666 | |
|
1667 | 0 | if(unlikely(size)) { |
1668 | 0 | gettimeofday(&req->tvrstart, NULL); |
1669 | 0 | memmove(req->buf, req->parsed, size); |
1670 | 0 | req->parsed = req->buf; /* fix req->parsed after using it */ |
1671 | | #ifdef EXTRA_DEBUG |
1672 | | LM_DBG("preparing for new request, kept %ld bytes\n", size); |
1673 | | #endif |
1674 | | /*if we still have some unparsed bytes, try to parse them too*/ |
1675 | 0 | goto again; |
1676 | 0 | } else if(unlikely(con->state == S_CONN_EOF)) { |
1677 | 0 | LM_DBG("EOF after reading complete request ([%s]:%u -> [%s]:%u)\n", |
1678 | 0 | ip_addr2a(&con->rcv.src_ip), con->rcv.src_port, |
1679 | 0 | ip_addr2a(&con->rcv.dst_ip), con->rcv.dst_port); |
1680 | 0 | resp = CONN_EOF; |
1681 | 0 | } |
1682 | 0 | req->parsed = req->buf; /* fix req->parsed */ |
1683 | 0 | } |
1684 | | |
1685 | 0 | end_req: |
1686 | 0 | if(likely(bytes_read)) |
1687 | 0 | *bytes_read = total_bytes; |
1688 | 0 | return resp; |
1689 | 0 | } |
1690 | | |
1691 | | |
1692 | | void release_tcpconn(struct tcp_connection *c, long state, int unix_sock) |
1693 | 0 | { |
1694 | 0 | long response[2]; |
1695 | |
|
1696 | 0 | LM_DBG("releasing con %p, state %ld, fd=%d, id=%d ([%s]:%u -> [%s]:%u)\n", |
1697 | 0 | c, state, c->fd, c->id, ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, |
1698 | 0 | ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
1699 | 0 | LM_DBG("extra_data %p\n", c->extra_data); |
1700 | | /* release req & signal the parent */ |
1701 | 0 | c->reader_pid = 0; /* reset it */ |
1702 | 0 | if(c->fd != -1) { |
1703 | 0 | close(c->fd); |
1704 | 0 | c->fd = -1; |
1705 | 0 | } |
1706 | | /* errno==EINTR, EWOULDBLOCK a.s.o todo */ |
1707 | 0 | response[0] = (long)c; |
1708 | 0 | response[1] = state; |
1709 | |
|
1710 | 0 | if(tsend_stream(unix_sock, (char *)response, sizeof(response), -1) <= 0) |
1711 | 0 | LM_ERR("tsend_stream failed\n"); |
1712 | 0 | } |
1713 | | |
1714 | | |
1715 | | static ticks_t tcpconn_read_timeout(ticks_t t, struct timer_ln *tl, void *data) |
1716 | 0 | { |
1717 | 0 | struct tcp_connection *c; |
1718 | |
|
1719 | 0 | c = (struct tcp_connection *)data; |
1720 | | /* or (struct tcp...*)(tl-offset(c->timer)) */ |
1721 | |
|
1722 | 0 | if(likely(!(c->state < 0) && TICKS_LT(t, c->timeout))) { |
1723 | | /* timeout extended, exit */ |
1724 | 0 | return (ticks_t)(c->timeout - t); |
1725 | 0 | } |
1726 | | /* if conn->state is ERROR or BAD => force timeout too */ |
1727 | 0 | if(unlikely(io_watch_del(&io_w, c->fd, -1, IO_FD_CLOSING) < 0)) { |
1728 | 0 | LM_ERR("io_watch_del failed for %p" |
1729 | 0 | " id %d fd %d, state %d, flags %x, main fd %d" |
1730 | 0 | " ([%s]:%u -> [%s]:%u)\n", |
1731 | 0 | c, c->id, c->fd, c->state, c->flags, c->s, |
1732 | 0 | ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, |
1733 | 0 | ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port); |
1734 | 0 | } |
1735 | 0 | if(tcp_conn_lst != NULL) { |
1736 | 0 | tcpconn_listrm(tcp_conn_lst, c, c_next, c_prev); |
1737 | 0 | c->event = TCP_CLOSED_TIMEOUT; |
1738 | 0 | release_tcpconn( |
1739 | 0 | c, (c->state < 0) ? CONN_ERROR : CONN_RELEASE, tcpmain_sock); |
1740 | 0 | } |
1741 | 0 | return 0; |
1742 | 0 | } |
1743 | | |
1744 | | |
1745 | | /* handle io routine, based on the fd_map type |
1746 | | * (it will be called from io_wait_loop* ) |
1747 | | * params: fm - pointer to a fd hash entry |
1748 | | * idx - index in the fd_array (or -1 if not known) |
1749 | | * return: -1 on error, or when we are not interested any more on reads |
1750 | | * from this fd (e.g.: we are closing it ) |
1751 | | * 0 on EAGAIN or when by some other way it is known that no more |
1752 | | * io events are queued on the fd (the receive buffer is empty). |
1753 | | * Useful to detect when there are no more io events queued for |
1754 | | * sigio_rt, epoll_et, kqueue. |
1755 | | * >0 on successfull read from the fd (when there might be more io |
1756 | | * queued -- the receive buffer might still be non-empty) |
1757 | | */ |
1758 | | inline static int handle_io(struct fd_map *fm, short events, int idx) |
1759 | 0 | { |
1760 | 0 | int ret; |
1761 | 0 | int n; |
1762 | 0 | rd_conn_flags_t read_flags; |
1763 | 0 | struct tcp_connection *con; |
1764 | 0 | int s; |
1765 | 0 | long resp; |
1766 | 0 | ticks_t t; |
1767 | 0 | fd_map_t *ee = NULL; |
1768 | | |
1769 | | /* update the local config */ |
1770 | 0 | cfg_update(); |
1771 | |
|
1772 | 0 | switch(fm->type) { |
1773 | 0 | case F_TCPMAIN: |
1774 | 0 | again: |
1775 | 0 | ret = n = receive_fd(fm->fd, &con, sizeof(con), &s, 0); |
1776 | 0 | LM_DBG("received n=%d con=%p, fd=%d\n", n, con, s); |
1777 | 0 | if(unlikely(n < 0)) { |
1778 | 0 | if(errno == EWOULDBLOCK || errno == EAGAIN) { |
1779 | 0 | ret = 0; |
1780 | 0 | break; |
1781 | 0 | } else if(errno == EINTR) |
1782 | 0 | goto again; |
1783 | 0 | else { |
1784 | 0 | LM_CRIT("read_fd: %s \n", strerror(errno)); |
1785 | 0 | abort(); /* big error*/ |
1786 | 0 | } |
1787 | 0 | } |
1788 | 0 | if(unlikely(n == 0)) { |
1789 | 0 | LM_ERR("0 bytes read\n"); |
1790 | 0 | goto error; |
1791 | 0 | } |
1792 | 0 | if(unlikely(con == 0)) { |
1793 | 0 | LM_CRIT("null pointer\n"); |
1794 | 0 | goto error; |
1795 | 0 | } |
1796 | 0 | con->fd = s; |
1797 | 0 | if(unlikely(s == -1)) { |
1798 | 0 | LM_ERR("read_fd: no fd read\n"); |
1799 | 0 | goto con_error; |
1800 | 0 | } |
1801 | 0 | con->reader_pid = my_pid(); |
1802 | 0 | if(unlikely(con == tcp_conn_lst)) { |
1803 | 0 | LM_CRIT("duplicate connection received: %p, id %d, fd %d, " |
1804 | 0 | "refcnt %d" |
1805 | 0 | " state %d (n=%d)\n", |
1806 | 0 | con, con->id, con->fd, atomic_get(&con->refcnt), |
1807 | 0 | con->state, n); |
1808 | 0 | goto con_error; |
1809 | 0 | break; /* try to recover */ |
1810 | 0 | } |
1811 | 0 | if(unlikely(con->state == S_CONN_BAD)) { |
1812 | 0 | LM_WARN("received an already bad connection: %p id %d refcnt " |
1813 | 0 | "%d\n", |
1814 | 0 | con, con->id, atomic_get(&con->refcnt)); |
1815 | 0 | goto con_error; |
1816 | 0 | } |
1817 | | /* if we received the fd there is most likely data waiting to |
1818 | | * be read => process it first to avoid extra sys calls */ |
1819 | 0 | read_flags = ((con->flags & (F_CONN_EOF_SEEN | F_CONN_FORCE_EOF)) |
1820 | 0 | && !(con->flags & F_CONN_OOB_DATA)) |
1821 | 0 | ? RD_CONN_FORCE_EOF |
1822 | 0 | : 0; |
1823 | 0 | #ifdef USE_TLS |
1824 | 0 | repeat_1st_read: |
1825 | 0 | #endif /* USE_TLS */ |
1826 | 0 | resp = tcp_read_req(con, &n, &read_flags); |
1827 | 0 | if(unlikely(resp < 0)) { |
1828 | | /* some error occurred, but on the new fd, not on the tcp |
1829 | | * main fd, so keep the ret value */ |
1830 | 0 | if(unlikely(resp != CONN_EOF)) |
1831 | 0 | con->state = S_CONN_BAD; |
1832 | 0 | release_tcpconn(con, resp, tcpmain_sock); |
1833 | 0 | break; |
1834 | 0 | } |
1835 | 0 | #ifdef USE_TLS |
1836 | | /* repeat read if requested (for now only tls might do this) */ |
1837 | 0 | if(unlikely(read_flags & RD_CONN_REPEAT_READ)) |
1838 | 0 | goto repeat_1st_read; |
1839 | 0 | #endif /* USE_TLS */ |
1840 | | |
1841 | | /* must be before io_watch_add, io_watch_add might catch some |
1842 | | * already existing events => might call handle_io and |
1843 | | * handle_io might decide to del. the new connection => |
1844 | | * must be in the list */ |
1845 | 0 | tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev); |
1846 | 0 | t = get_ticks_raw(); |
1847 | 0 | con->timeout = t + S_TO_TICKS(TCP_CHILD_TIMEOUT); |
1848 | | /* re-activate the timer */ |
1849 | 0 | con->timer.f = tcpconn_read_timeout; |
1850 | 0 | local_timer_reinit(&con->timer); |
1851 | 0 | local_timer_add(&tcp_reader_ltimer, &con->timer, |
1852 | 0 | S_TO_TICKS(TCP_CHILD_TIMEOUT), t); |
1853 | 0 | if(unlikely(io_watch_add(&io_w, s, POLLIN, F_TCPCONN, con) < 0)) { |
1854 | 0 | LM_CRIT("io_watch_add failed for %p id %d fd %d, state %d, " |
1855 | 0 | "flags %x," |
1856 | 0 | " main fd %d, refcnt %d ([%s]:%u -> [%s]:%u)\n", |
1857 | 0 | con, con->id, con->fd, con->state, con->flags, con->s, |
1858 | 0 | atomic_get(&con->refcnt), ip_addr2a(&con->rcv.src_ip), |
1859 | 0 | con->rcv.src_port, ip_addr2a(&con->rcv.dst_ip), |
1860 | 0 | con->rcv.dst_port); |
1861 | 0 | ee = get_fd_map(&io_w, s); |
1862 | 0 | if(ee != 0 && ee->type == F_TCPCONN) { |
1863 | 0 | tcp_connection_t *ec; |
1864 | 0 | ec = (tcp_connection_t *)ee->data; |
1865 | 0 | LM_CRIT("existing tcp con %p id %d fd %d, state %d, flags " |
1866 | 0 | "%x," |
1867 | 0 | " main fd %d, refcnt %d ([%s]:%u -> [%s]:%u)\n", |
1868 | 0 | ec, ec->id, ec->fd, ec->state, ec->flags, ec->s, |
1869 | 0 | atomic_get(&ec->refcnt), ip_addr2a(&ec->rcv.src_ip), |
1870 | 0 | ec->rcv.src_port, ip_addr2a(&ec->rcv.dst_ip), |
1871 | 0 | ec->rcv.dst_port); |
1872 | 0 | } |
1873 | 0 | if(tcp_conn_lst != NULL) { |
1874 | 0 | tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev); |
1875 | 0 | local_timer_del(&tcp_reader_ltimer, &con->timer); |
1876 | 0 | } |
1877 | 0 | goto con_error; |
1878 | 0 | } |
1879 | 0 | break; |
1880 | 0 | case F_TCPCONN: |
1881 | 0 | con = (struct tcp_connection *)fm->data; |
1882 | 0 | if(unlikely(con->state == S_CONN_BAD)) { |
1883 | 0 | resp = CONN_ERROR; |
1884 | 0 | if(!(con->send_flags.f & SND_F_CON_CLOSE)) |
1885 | 0 | LM_WARN("F_TCPCONN connection marked as bad: %p id %d fd %d" |
1886 | 0 | " refcnt %d ([%s]:%u -> [%s]:%u)\n", |
1887 | 0 | con, con->id, con->fd, atomic_get(&con->refcnt), |
1888 | 0 | ip_addr2a(&con->rcv.src_ip), con->rcv.src_port, |
1889 | 0 | ip_addr2a(&con->rcv.dst_ip), con->rcv.dst_port); |
1890 | 0 | goto read_error; |
1891 | 0 | } |
1892 | 0 | read_flags = |
1893 | 0 | (( |
1894 | 0 | #ifdef POLLRDHUP |
1895 | 0 | (events & POLLRDHUP) | |
1896 | 0 | #endif /* POLLRDHUP */ |
1897 | 0 | (events & (POLLHUP | POLLERR)) |
1898 | 0 | | (con->flags |
1899 | 0 | & (F_CONN_EOF_SEEN | F_CONN_FORCE_EOF))) |
1900 | 0 | && !(events & POLLPRI)) |
1901 | 0 | ? RD_CONN_FORCE_EOF |
1902 | 0 | : 0; |
1903 | 0 | #ifdef USE_TLS |
1904 | 0 | repeat_read: |
1905 | 0 | #endif /* USE_TLS */ |
1906 | 0 | resp = tcp_read_req(con, &ret, &read_flags); |
1907 | 0 | if(unlikely(resp < 0)) { |
1908 | 0 | read_error: |
1909 | 0 | ret = -1; /* some error occurred */ |
1910 | 0 | if(unlikely(io_watch_del(&io_w, con->fd, idx, IO_FD_CLOSING) |
1911 | 0 | < 0)) { |
1912 | 0 | LM_CRIT("io_watch_del failed for %p id %d fd %d," |
1913 | 0 | " state %d, flags %x, main fd %d, refcnt %d" |
1914 | 0 | " ([%s]:%u -> [%s]:%u)\n", |
1915 | 0 | con, con->id, con->fd, con->state, con->flags, |
1916 | 0 | con->s, atomic_get(&con->refcnt), |
1917 | 0 | ip_addr2a(&con->rcv.src_ip), con->rcv.src_port, |
1918 | 0 | ip_addr2a(&con->rcv.dst_ip), con->rcv.dst_port); |
1919 | 0 | } |
1920 | 0 | if(tcp_conn_lst != NULL) { |
1921 | 0 | LM_DBG("removing from list %p id %d fd %d," |
1922 | 0 | " state %d, flags %x, main fd %d, refcnt %d" |
1923 | 0 | " ([%s]:%u -> [%s]:%u)\n", |
1924 | 0 | con, con->id, con->fd, con->state, con->flags, |
1925 | 0 | con->s, atomic_get(&con->refcnt), |
1926 | 0 | ip_addr2a(&con->rcv.src_ip), con->rcv.src_port, |
1927 | 0 | ip_addr2a(&con->rcv.dst_ip), con->rcv.dst_port); |
1928 | 0 | tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev); |
1929 | 0 | local_timer_del(&tcp_reader_ltimer, &con->timer); |
1930 | 0 | if(unlikely(resp != CONN_EOF)) |
1931 | 0 | con->state = S_CONN_BAD; |
1932 | 0 | release_tcpconn(con, resp, tcpmain_sock); |
1933 | 0 | } |
1934 | 0 | } else { |
1935 | 0 | #ifdef USE_TLS |
1936 | 0 | if(unlikely(read_flags & RD_CONN_REPEAT_READ)) |
1937 | 0 | goto repeat_read; |
1938 | 0 | #endif /* USE_TLS */ |
1939 | | /* update timeout */ |
1940 | 0 | con->timeout = get_ticks_raw() + S_TO_TICKS(TCP_CHILD_TIMEOUT); |
1941 | | /* ret= 0 (read the whole socket buffer) if short read |
1942 | | * & !POLLPRI, bytes read otherwise */ |
1943 | 0 | ret &= (((read_flags & RD_CONN_SHORT_READ) |
1944 | 0 | && !(events & POLLPRI)) |
1945 | 0 | - 1); |
1946 | 0 | } |
1947 | 0 | break; |
1948 | 0 | case F_NONE: |
1949 | 0 | LM_CRIT("empty fd map %p (%d): {%d, %d, %p}\n", fm, |
1950 | 0 | (int)(fm - io_w.fd_hash), fm->fd, fm->type, fm->data); |
1951 | 0 | goto error; |
1952 | 0 | default: |
1953 | 0 | LM_CRIT("unknown fd type %d\n", fm->type); |
1954 | 0 | goto error; |
1955 | 0 | } |
1956 | | |
1957 | 0 | return ret; |
1958 | 0 | con_error: |
1959 | 0 | con->state = S_CONN_BAD; |
1960 | 0 | release_tcpconn(con, CONN_ERROR, tcpmain_sock); |
1961 | 0 | return ret; |
1962 | 0 | error: |
1963 | 0 | return -1; |
1964 | 0 | } |
1965 | | |
1966 | | |
1967 | | inline static void tcp_reader_timer_run(void) |
1968 | 0 | { |
1969 | 0 | ticks_t ticks; |
1970 | |
|
1971 | 0 | ticks = get_ticks_raw(); |
1972 | 0 | if(unlikely((ticks - tcp_reader_prev_ticks) < TCPCONN_TIMEOUT_MIN_RUN)) |
1973 | 0 | return; |
1974 | 0 | tcp_reader_prev_ticks = ticks; |
1975 | 0 | local_timer_run(&tcp_reader_ltimer, ticks); |
1976 | 0 | } |
1977 | | |
1978 | | |
1979 | | void tcp_receive_loop(int unix_sock) |
1980 | 0 | { |
1981 | | |
1982 | | /* init */ |
1983 | 0 | tcpmain_sock = unix_sock; /* init com. socket */ |
1984 | 0 | if(init_io_wait(&io_w, get_max_open_fds(), tcp_poll_method) < 0) |
1985 | 0 | goto error; |
1986 | 0 | tcp_reader_prev_ticks = get_ticks_raw(); |
1987 | 0 | if(init_local_timer(&tcp_reader_ltimer, get_ticks_raw()) != 0) |
1988 | 0 | goto error; |
1989 | | /* add the unix socket */ |
1990 | 0 | if(io_watch_add(&io_w, tcpmain_sock, POLLIN, F_TCPMAIN, 0) < 0) { |
1991 | 0 | LM_CRIT("failed to add tcp main socket to the fd list\n"); |
1992 | 0 | goto error; |
1993 | 0 | } |
1994 | | |
1995 | | /* initialize the config framework */ |
1996 | 0 | if(cfg_child_init()) |
1997 | 0 | goto error; |
1998 | | |
1999 | | /* main loop */ |
2000 | 0 | switch(io_w.poll_method) { |
2001 | 0 | case POLL_POLL: |
2002 | 0 | while(1) { |
2003 | 0 | io_wait_loop_poll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); |
2004 | 0 | tcp_reader_timer_run(); |
2005 | 0 | } |
2006 | 0 | break; |
2007 | 0 | #ifdef HAVE_SELECT |
2008 | 0 | case POLL_SELECT: |
2009 | 0 | while(1) { |
2010 | 0 | io_wait_loop_select(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); |
2011 | 0 | tcp_reader_timer_run(); |
2012 | 0 | } |
2013 | 0 | break; |
2014 | 0 | #endif |
2015 | 0 | #ifdef HAVE_SIGIO_RT |
2016 | 0 | case POLL_SIGIO_RT: |
2017 | 0 | while(1) { |
2018 | 0 | io_wait_loop_sigio_rt(&io_w, TCP_CHILD_SELECT_TIMEOUT); |
2019 | 0 | tcp_reader_timer_run(); |
2020 | 0 | } |
2021 | 0 | break; |
2022 | 0 | #endif |
2023 | 0 | #ifdef HAVE_EPOLL |
2024 | 0 | case POLL_EPOLL_LT: |
2025 | 0 | while(1) { |
2026 | 0 | io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); |
2027 | 0 | tcp_reader_timer_run(); |
2028 | 0 | } |
2029 | 0 | break; |
2030 | 0 | case POLL_EPOLL_ET: |
2031 | 0 | while(1) { |
2032 | 0 | io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 1); |
2033 | 0 | tcp_reader_timer_run(); |
2034 | 0 | } |
2035 | 0 | break; |
2036 | 0 | #endif |
2037 | | #ifdef HAVE_KQUEUE |
2038 | | case POLL_KQUEUE: |
2039 | | while(1) { |
2040 | | io_wait_loop_kqueue(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); |
2041 | | tcp_reader_timer_run(); |
2042 | | } |
2043 | | break; |
2044 | | #endif |
2045 | | #ifdef HAVE_DEVPOLL |
2046 | | case POLL_DEVPOLL: |
2047 | | while(1) { |
2048 | | io_wait_loop_devpoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); |
2049 | | tcp_reader_timer_run(); |
2050 | | } |
2051 | | break; |
2052 | | #endif |
2053 | 0 | default: |
2054 | 0 | LM_CRIT("no support for poll method %s (%d)\n", |
2055 | 0 | poll_method_name(io_w.poll_method), io_w.poll_method); |
2056 | 0 | goto error; |
2057 | 0 | } |
2058 | 0 | error: |
2059 | 0 | destroy_io_wait(&io_w); |
2060 | 0 | LM_CRIT("exiting..."); |
2061 | 0 | ksr_exit(-1); |
2062 | 0 | } |
2063 | | |
2064 | | |
2065 | | int is_msg_complete(struct tcp_req *r) |
2066 | 0 | { |
2067 | 0 | if(TCP_REQ_HAS_CLEN(r)) { |
2068 | 0 | r->state = H_STUN_FP; |
2069 | 0 | return 0; |
2070 | 0 | } else { |
2071 | | /* STUN message is complete */ |
2072 | 0 | r->state = H_STUN_END; |
2073 | 0 | r->flags |= F_TCP_REQ_COMPLETE |
2074 | 0 | | F_TCP_REQ_HAS_CLEN; /* hack to avoid error check */ |
2075 | 0 | return 1; |
2076 | 0 | } |
2077 | 0 | } |
2078 | | |
2079 | | #endif /* USE_TCP */ |