/src/kamailio/src/core/receive.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 | | * SPDX-License-Identifier: GPL-2.0-or-later |
7 | | * |
8 | | * Kamailio is free software; you can redistribute it and/or modify |
9 | | * it under the terms of the GNU General Public License as published by |
10 | | * the Free Software Foundation; either version 2 of the License, or |
11 | | * (at your option) any later version |
12 | | * |
13 | | * Kamailio is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | * |
22 | | */ |
23 | | |
24 | | /*! |
25 | | * \file |
26 | | * \brief Kamailio core :: |
27 | | * \ingroup core |
28 | | * Module: \ref core |
29 | | */ |
30 | | |
31 | | |
32 | | #include <string.h> |
33 | | #include <stdlib.h> |
34 | | #include <sys/time.h> |
35 | | |
36 | | #include "receive.h" |
37 | | #include "globals.h" |
38 | | #include "dprint.h" |
39 | | #include "route.h" |
40 | | #include "parser/msg_parser.h" |
41 | | #include "forward.h" |
42 | | #include "action.h" |
43 | | #include "mem/mem.h" |
44 | | #include "ip_addr.h" |
45 | | #include "script_cb.h" |
46 | | #include "nonsip_hooks.h" |
47 | | #include "dset.h" |
48 | | #include "fmsg.h" |
49 | | #include "usr_avp.h" |
50 | | #include "xavp.h" |
51 | | #include "select_buf.h" |
52 | | #include "locking.h" |
53 | | |
54 | | #include "tcp_server.h" /* for tcpconn_add_alias */ |
55 | | #include "tcp_options.h" /* for access to tcp_accept_aliases*/ |
56 | | #include "cfg/cfg.h" |
57 | | #include "core_stats.h" |
58 | | #include "kemi.h" |
59 | | |
60 | | #ifdef DEBUG_DMALLOC |
61 | | #include <mem/dmalloc.h> |
62 | | #endif |
63 | | |
64 | | int _sr_ip_free_bind = 0; |
65 | | |
66 | | unsigned int msg_no = 0; |
67 | | /* address preset vars */ |
68 | | str default_global_address = {0, 0}; |
69 | | str default_global_port = {0, 0}; |
70 | | str default_via_address = {0, 0}; |
71 | | str default_via_port = {0, 0}; |
72 | | |
73 | | int ksr_route_locks_size = 0; |
74 | | static rec_lock_set_t *ksr_route_locks_set = NULL; |
75 | | |
76 | | int ksr_route_locks_set_init(void) |
77 | 0 | { |
78 | 0 | if(ksr_route_locks_set != NULL || ksr_route_locks_size <= 0) |
79 | 0 | return 0; |
80 | | |
81 | 0 | ksr_route_locks_set = rec_lock_set_alloc(ksr_route_locks_size); |
82 | 0 | if(ksr_route_locks_set == NULL) { |
83 | 0 | LM_ERR("failed to allocate route locks set\n"); |
84 | 0 | return -1; |
85 | 0 | } |
86 | 0 | if(rec_lock_set_init(ksr_route_locks_set) == NULL) { |
87 | 0 | LM_ERR("failed to init route locks set\n"); |
88 | 0 | return -1; |
89 | 0 | } |
90 | 0 | return 0; |
91 | 0 | } |
92 | | |
93 | | void ksr_route_locks_set_destroy(void) |
94 | 0 | { |
95 | 0 | if(ksr_route_locks_set == NULL) |
96 | 0 | return; |
97 | | |
98 | 0 | rec_lock_set_destroy(ksr_route_locks_set); |
99 | 0 | rec_lock_set_dealloc(ksr_route_locks_set); |
100 | 0 | ksr_route_locks_set = NULL; |
101 | 0 | } |
102 | | |
103 | | /** |
104 | | * increment msg_no and return the new value |
105 | | */ |
106 | | unsigned int inc_msg_no(void) |
107 | 0 | { |
108 | 0 | return ++msg_no; |
109 | 0 | } |
110 | | |
111 | | /** |
112 | | * |
113 | | */ |
114 | | int sip_check_fline(char *buf, unsigned int len) |
115 | 0 | { |
116 | 0 | char *p; |
117 | 0 | int m; |
118 | |
|
119 | 0 | m = 0; |
120 | 0 | for(p = buf; p < buf + len; p++) { |
121 | | /* first check if is a reply - starts with SIP/2.0 */ |
122 | 0 | if(m == 0) { |
123 | 0 | if(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') |
124 | 0 | continue; |
125 | 0 | if(buf + len - p < 10) |
126 | 0 | return -1; |
127 | 0 | if(strncmp(p, "SIP/2.0 ", 8) == 0) { |
128 | 0 | LM_DBG("first line indicates a SIP reply\n"); |
129 | 0 | return 0; |
130 | 0 | } |
131 | 0 | m = 1; |
132 | 0 | } else { |
133 | | /* check if a request - before end of first line is SIP/2.0 */ |
134 | 0 | if(*p != '\r' && *p != '\n') |
135 | 0 | continue; |
136 | 0 | if(p - 10 >= buf) { |
137 | 0 | if(strncmp(p - 8, " SIP/2.0", 8) == 0) { |
138 | 0 | LM_DBG("first line indicates a SIP request\n"); |
139 | 0 | return 0; |
140 | 0 | } |
141 | 0 | } |
142 | 0 | return -1; |
143 | 0 | } |
144 | 0 | } |
145 | 0 | return -1; |
146 | 0 | } |
147 | | |
148 | | /** |
149 | | * |
150 | | */ |
151 | | static sr_net_info_t *ksr_evrt_rcvnetinfo = NULL; |
152 | | int ksr_evrt_received_mode = 0; |
153 | | str kemi_received_route_callback = STR_NULL; |
154 | | |
155 | | /** |
156 | | * |
157 | | */ |
158 | | sr_net_info_t *ksr_evrt_rcvnetinfo_get(void) |
159 | 0 | { |
160 | 0 | return ksr_evrt_rcvnetinfo; |
161 | 0 | } |
162 | | |
163 | | /** |
164 | | * |
165 | | */ |
166 | | int ksr_evrt_received(char *buf, unsigned int *len, receive_info_t *rcv_info) |
167 | 0 | { |
168 | 0 | sr_kemi_eng_t *keng = NULL; |
169 | 0 | sr_net_info_t netinfo; |
170 | 0 | int ret = 0; |
171 | 0 | int rt = -1; |
172 | 0 | run_act_ctx_t ra_ctx; |
173 | 0 | run_act_ctx_t *bctx = NULL; |
174 | 0 | sip_msg_t *fmsg = NULL; |
175 | 0 | str evname = str_init("core:msg-received"); |
176 | |
|
177 | 0 | if(len == 0 || rcv_info == NULL || buf == NULL) { |
178 | 0 | LM_ERR("required parameters are not available\n"); |
179 | 0 | return -1; |
180 | 0 | } |
181 | | |
182 | 0 | if(kemi_received_route_callback.len > 0) { |
183 | 0 | keng = sr_kemi_eng_get(); |
184 | 0 | if(keng == NULL) { |
185 | 0 | LM_DBG("kemi enabled with no core:msg-receive event route " |
186 | 0 | "callback\n"); |
187 | 0 | return 0; |
188 | 0 | } |
189 | 0 | } else { |
190 | 0 | rt = route_lookup(&event_rt, evname.s); |
191 | 0 | if(rt < 0 || event_rt.rlist[rt] == NULL) { |
192 | 0 | LM_DBG("event route core:msg-received not defined\n"); |
193 | 0 | return 0; |
194 | 0 | } |
195 | 0 | } |
196 | 0 | memset(&netinfo, 0, sizeof(sr_net_info_t)); |
197 | 0 | netinfo.data.s = buf; |
198 | 0 | netinfo.data.len = *len; |
199 | 0 | netinfo.bufsize = BUF_SIZE; |
200 | 0 | netinfo.rcv = rcv_info; |
201 | |
|
202 | 0 | ksr_evrt_rcvnetinfo = &netinfo; |
203 | 0 | set_route_type(REQUEST_ROUTE); |
204 | 0 | fmsg = faked_msg_get_next(); |
205 | 0 | init_run_actions_ctx(&ra_ctx); |
206 | 0 | if(keng) { |
207 | 0 | bctx = sr_kemi_act_ctx_get(); |
208 | 0 | sr_kemi_act_ctx_set(&ra_ctx); |
209 | 0 | ret = sr_kemi_route( |
210 | 0 | keng, fmsg, REQUEST_ROUTE, &kemi_received_route_callback, NULL); |
211 | 0 | sr_kemi_act_ctx_set(bctx); |
212 | 0 | } else { |
213 | 0 | ret = run_actions(&ra_ctx, event_rt.rlist[rt], fmsg); |
214 | 0 | } |
215 | 0 | if(ra_ctx.run_flags & DROP_R_F) { |
216 | 0 | LM_DBG("dropping received message\n"); |
217 | 0 | ret = -1; |
218 | 0 | } |
219 | 0 | *len = netinfo.data.len; |
220 | 0 | ksr_evrt_rcvnetinfo = NULL; |
221 | |
|
222 | 0 | return ret; |
223 | 0 | } |
224 | | |
225 | | |
226 | | static int ksr_evrt_pre_routing_idx = -1; |
227 | | str kemi_pre_routing_callback = STR_NULL; |
228 | | |
229 | | |
230 | | /** |
231 | | * |
232 | | */ |
233 | | int ksr_evrt_pre_routing(sip_msg_t *msg) |
234 | 0 | { |
235 | 0 | int ret = 0; |
236 | 0 | int rt = -1; |
237 | 0 | run_act_ctx_t ra_ctx; |
238 | 0 | run_act_ctx_t *bctx = NULL; |
239 | 0 | sr_kemi_eng_t *keng = NULL; |
240 | 0 | str evname = str_init("core:pre-routing"); |
241 | 0 | recv_flags_t brflags; |
242 | |
|
243 | 0 | if(msg->rcv.rflags & RECV_F_INTERNAL) { |
244 | 0 | DBG("skip internal routed message\n"); |
245 | 0 | return 0; |
246 | 0 | } |
247 | | |
248 | 0 | if(kemi_pre_routing_callback.len > 0) { |
249 | 0 | keng = sr_kemi_eng_get(); |
250 | 0 | if(keng == NULL) { |
251 | 0 | LM_DBG("kemi enabled with no core:pre-routing event route " |
252 | 0 | "callback\n"); |
253 | 0 | return 0; |
254 | 0 | } |
255 | 0 | } else { |
256 | 0 | if(ksr_evrt_pre_routing_idx == -1) { |
257 | 0 | rt = route_lookup(&event_rt, evname.s); |
258 | 0 | if(rt < 0 || event_rt.rlist[rt] == NULL) { |
259 | 0 | ksr_evrt_pre_routing_idx = -2; |
260 | 0 | } |
261 | 0 | } else { |
262 | 0 | rt = ksr_evrt_pre_routing_idx; |
263 | 0 | } |
264 | 0 | if(rt < 0 || event_rt.rlist[rt] == NULL) { |
265 | 0 | LM_DBG("event route core:pre-routing not defined\n"); |
266 | 0 | return 0; |
267 | 0 | } |
268 | 0 | } |
269 | | |
270 | 0 | set_route_type(REQUEST_ROUTE); |
271 | 0 | init_run_actions_ctx(&ra_ctx); |
272 | 0 | brflags = msg->rcv.rflags; |
273 | 0 | msg->rcv.rflags |= RECV_F_PREROUTING; |
274 | 0 | if(keng) { |
275 | 0 | bctx = sr_kemi_act_ctx_get(); |
276 | 0 | sr_kemi_act_ctx_set(&ra_ctx); |
277 | 0 | ret = sr_kemi_route( |
278 | 0 | keng, msg, REQUEST_ROUTE, &kemi_pre_routing_callback, &evname); |
279 | 0 | sr_kemi_act_ctx_set(bctx); |
280 | 0 | } else { |
281 | 0 | ret = run_actions(&ra_ctx, event_rt.rlist[rt], msg); |
282 | 0 | } |
283 | 0 | msg->rcv.rflags = brflags; |
284 | 0 | if(ra_ctx.run_flags & DROP_R_F) { |
285 | 0 | LM_DBG("drop was used\n"); |
286 | 0 | return 1; |
287 | 0 | } |
288 | 0 | LM_DBG("execution returned %d\n", ret); |
289 | |
|
290 | 0 | return 0; |
291 | 0 | } |
292 | | |
293 | | /** Receive message |
294 | | * WARNING: buf must be 0 terminated (buf[len]=0) or some things might |
295 | | * break (e.g.: modules/textops) |
296 | | */ |
297 | | int receive_msg(char *buf, unsigned int len, receive_info_t *rcv_info) |
298 | 0 | { |
299 | 0 | struct sip_msg *msg = NULL; |
300 | 0 | struct run_act_ctx ctx; |
301 | 0 | struct run_act_ctx *bctx = NULL; |
302 | 0 | int ret = -1; |
303 | 0 | struct timeval tvb = {0}, tve = {0}; |
304 | 0 | unsigned int diff = 0; |
305 | 0 | str inb = STR_NULL; |
306 | 0 | sr_net_info_t netinfo = {0}; |
307 | 0 | sr_kemi_eng_t *keng = NULL; |
308 | 0 | sr_event_param_t evp = {0}; |
309 | 0 | unsigned int cidlockidx = 0; |
310 | 0 | unsigned int cidlockset = 0; |
311 | 0 | int errsipmsg = 0; |
312 | 0 | int exectime = 0; |
313 | |
|
314 | 0 | if(rcv_info->bind_address == NULL) { |
315 | 0 | LM_ERR("critical - incoming message without local socket [%.*s ...]\n", |
316 | 0 | (len > 128) ? 128 : len, buf); |
317 | 0 | return -1; |
318 | 0 | } |
319 | | |
320 | 0 | if(ksr_evrt_received_mode != 0) { |
321 | 0 | if(ksr_evrt_received(buf, &len, rcv_info) < 0) { |
322 | 0 | LM_DBG("dropping the received message\n"); |
323 | 0 | goto error00; |
324 | 0 | } |
325 | 0 | } |
326 | 0 | if(sr_event_enabled(SREV_NET_DATA_RECV)) { |
327 | 0 | if(sip_check_fline(buf, len) == 0) { |
328 | 0 | memset(&netinfo, 0, sizeof(sr_net_info_t)); |
329 | 0 | netinfo.data.s = buf; |
330 | 0 | netinfo.data.len = len; |
331 | 0 | netinfo.rcv = rcv_info; |
332 | 0 | evp.data = (void *)&netinfo; |
333 | 0 | sr_event_exec(SREV_NET_DATA_RECV, &evp); |
334 | 0 | } |
335 | 0 | } |
336 | |
|
337 | 0 | inb.s = buf; |
338 | 0 | inb.len = len; |
339 | 0 | evp.data = (void *)&inb; |
340 | 0 | evp.rcv = rcv_info; |
341 | 0 | sr_event_exec(SREV_NET_DATA_IN, &evp); |
342 | 0 | len = inb.len; |
343 | |
|
344 | 0 | msg = pkg_malloc(sizeof(struct sip_msg)); |
345 | 0 | if(unlikely(msg == 0)) { |
346 | 0 | PKG_MEM_ERROR; |
347 | 0 | goto error00; |
348 | 0 | } |
349 | 0 | msg_no++; |
350 | | /* number of vias parsed -- good for diagnostic info in replies */ |
351 | 0 | via_cnt = 0; |
352 | |
|
353 | 0 | memset(msg, 0, sizeof(struct sip_msg)); /* init everything to 0 */ |
354 | | /* fill in msg */ |
355 | 0 | msg->buf = buf; |
356 | 0 | msg->len = len; |
357 | | /* zero termination (termination of orig message below not that |
358 | | * useful as most of the work is done with scratch-pad; -jiri */ |
359 | | /* buf[len]=0; */ /* WARNING: zero term removed! */ |
360 | 0 | msg->rcv = *rcv_info; |
361 | 0 | msg->id = msg_no; |
362 | 0 | msg->pid = my_pid(); |
363 | 0 | msg->set_global_address = default_global_address; |
364 | 0 | msg->set_global_port = default_global_port; |
365 | |
|
366 | 0 | if(likely(sr_msg_time == 1)) |
367 | 0 | msg_set_time(msg); |
368 | |
|
369 | 0 | if(parse_msg(buf, len, msg) != 0) { |
370 | 0 | errsipmsg = 1; |
371 | 0 | evp.data = (void *)msg; |
372 | 0 | if((ret = sr_event_exec(SREV_RCV_NOSIP, &evp)) < NONSIP_MSG_DROP) { |
373 | 0 | LM_DBG("attempt of nonsip message processing failed\n"); |
374 | 0 | } else if(ret == NONSIP_MSG_DROP) { |
375 | 0 | LM_DBG("nonsip message processing completed\n"); |
376 | 0 | goto end; |
377 | 0 | } |
378 | 0 | } |
379 | 0 | if(errsipmsg == 1) { |
380 | 0 | LOG(cfg_get(core, core_cfg, sip_parser_log), |
381 | 0 | "core parsing of SIP message failed (%s:%d/%d)\n", |
382 | 0 | ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port, |
383 | 0 | (int)msg->rcv.proto); |
384 | 0 | sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR); |
385 | 0 | goto error02; |
386 | 0 | } |
387 | | |
388 | 0 | if(unlikely(parse_headers(msg, |
389 | 0 | HDR_FROM_F | HDR_TO_F | HDR_CALLID_F | HDR_CSEQ_F, 0) |
390 | 0 | < 0)) { |
391 | 0 | LOG(cfg_get(core, core_cfg, sip_parser_log), |
392 | 0 | "parsing relevant headers failed\n"); |
393 | 0 | } |
394 | 0 | LM_DBG("--- received sip message - %s - call-id: [%.*s] - cseq: [%.*s]\n", |
395 | 0 | (msg->first_line.type == SIP_REQUEST) ? "request" : "reply", |
396 | 0 | (msg->callid && msg->callid->body.s) ? msg->callid->body.len : 0, |
397 | 0 | (msg->callid && msg->callid->body.s) ? msg->callid->body.s : "", |
398 | 0 | (msg->cseq && msg->cseq->body.s) ? msg->cseq->body.len : 0, |
399 | 0 | (msg->cseq && msg->cseq->body.s) ? msg->cseq->body.s : ""); |
400 | | |
401 | | /* set log prefix */ |
402 | 0 | log_prefix_set(msg); |
403 | | |
404 | | /* ... clear branches from previous message */ |
405 | 0 | clear_branches(); |
406 | |
|
407 | 0 | ret = ksr_evrt_pre_routing(msg); |
408 | 0 | if(ret < 0) { |
409 | 0 | goto error02; |
410 | 0 | } |
411 | 0 | if(ret == 1) { |
412 | | /* finished */ |
413 | 0 | goto end; |
414 | 0 | } |
415 | | |
416 | 0 | if(unlikely(ksr_route_locks_set != NULL && msg->callid |
417 | 0 | && msg->callid->body.s && msg->callid->body.len > 0)) { |
418 | 0 | cidlockidx = get_hash1_raw(msg->callid->body.s, msg->callid->body.len); |
419 | 0 | cidlockidx = cidlockidx % ksr_route_locks_set->size; |
420 | 0 | cidlockset = 1; |
421 | 0 | } |
422 | | |
423 | |
|
424 | 0 | if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))) { |
425 | 0 | exectime = 1; |
426 | 0 | } |
427 | |
|
428 | 0 | if(msg->first_line.type == SIP_REQUEST) { |
429 | 0 | ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */ |
430 | 0 | if(!IS_SIP(msg)) { |
431 | 0 | LM_DBG("handling non-sip request message\n"); |
432 | 0 | if((ret = nonsip_msg_run_hooks(msg)) != NONSIP_MSG_ACCEPT) { |
433 | 0 | if(unlikely(ret == NONSIP_MSG_ERROR)) { |
434 | 0 | LM_DBG("failed handling non-sip request message\n"); |
435 | 0 | goto error03; |
436 | 0 | } |
437 | 0 | LM_DBG("finished handling non-sip request message\n"); |
438 | 0 | goto end; /* drop the message */ |
439 | 0 | } |
440 | 0 | } |
441 | | /* sanity checks */ |
442 | 0 | if(unlikely((msg->via1 == 0) || (msg->via1->error != PARSE_OK))) { |
443 | | /* no via, send back error ? */ |
444 | 0 | LOG(cfg_get(core, core_cfg, sip_parser_log), |
445 | 0 | "no via found in request\n"); |
446 | 0 | STATS_BAD_MSG(); |
447 | 0 | goto error02; |
448 | 0 | } |
449 | 0 | if(unlikely((msg->callid == 0) || (msg->cseq == 0) || (msg->from == 0) |
450 | 0 | || (msg->to == 0))) { |
451 | | /* no required headers -- send back error ? */ |
452 | 0 | LOG(cfg_get(core, core_cfg, sip_parser_log), |
453 | 0 | "required headers not found in request\n"); |
454 | 0 | STATS_BAD_MSG(); |
455 | 0 | goto error02; |
456 | 0 | } |
457 | | /* check if necessary to add receive?->moved to forward_req */ |
458 | | /* check for the alias stuff */ |
459 | 0 | #ifdef USE_TCP |
460 | 0 | if(msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) |
461 | 0 | && (((rcv_info->proto == PROTO_TCP) && !tcp_disable) |
462 | 0 | #ifdef USE_TLS |
463 | 0 | || ((rcv_info->proto == PROTO_TLS) && !tls_disable) |
464 | 0 | #endif |
465 | 0 | )) { |
466 | 0 | if(tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port, |
467 | 0 | rcv_info->proto) |
468 | 0 | != 0) { |
469 | 0 | LM_ERR("tcp alias failed\n"); |
470 | | /* continue */ |
471 | 0 | } |
472 | 0 | } |
473 | 0 | #endif |
474 | | |
475 | | /* skip: */ |
476 | 0 | LM_DBG("preparing to run routing scripts...\n"); |
477 | 0 | if(exectime) { |
478 | 0 | gettimeofday(&tvb, NULL); |
479 | 0 | } |
480 | | /* execute pre-script callbacks, if any; -jiri */ |
481 | | /* if some of the callbacks said not to continue with |
482 | | * script processing, don't do so |
483 | | * if we are here basic sanity checks are already done |
484 | | * (like presence of at least one via), so you can count |
485 | | * on via1 being parsed in a pre-script callback --andrei |
486 | | */ |
487 | 0 | if(exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0) { |
488 | 0 | STATS_REQ_FWD_DROP(); |
489 | 0 | goto end; /* drop the request */ |
490 | 0 | } |
491 | | |
492 | 0 | set_route_type(REQUEST_ROUTE); |
493 | | /* exec the routing script */ |
494 | 0 | if(unlikely(main_rt.rlist[DEFAULT_RT] == NULL)) { |
495 | 0 | keng = sr_kemi_eng_get(); |
496 | 0 | if(keng == NULL) { |
497 | 0 | LM_ERR("no request_route {...} and no other config routing" |
498 | 0 | " engine registered\n"); |
499 | 0 | goto error_req; |
500 | 0 | } |
501 | 0 | if(unlikely(cidlockset)) { |
502 | 0 | rec_lock_set_get(ksr_route_locks_set, cidlockidx); |
503 | 0 | if(sr_kemi_route(keng, msg, REQUEST_ROUTE, NULL, NULL) < 0) |
504 | 0 | LM_NOTICE("negative return code from engine function\n"); |
505 | 0 | rec_lock_set_release(ksr_route_locks_set, cidlockidx); |
506 | 0 | } else { |
507 | 0 | if(sr_kemi_route(keng, msg, REQUEST_ROUTE, NULL, NULL) < 0) |
508 | 0 | LM_NOTICE("negative return code from engine function\n"); |
509 | 0 | } |
510 | 0 | } else { |
511 | 0 | if(unlikely(cidlockset)) { |
512 | 0 | rec_lock_set_get(ksr_route_locks_set, cidlockidx); |
513 | 0 | if(run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0) < 0) { |
514 | 0 | rec_lock_set_release(ksr_route_locks_set, cidlockidx); |
515 | 0 | LM_WARN("error while trying script\n"); |
516 | 0 | goto error_req; |
517 | 0 | } |
518 | 0 | rec_lock_set_release(ksr_route_locks_set, cidlockidx); |
519 | 0 | } else { |
520 | 0 | if(run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0) < 0) { |
521 | 0 | LM_WARN("error while trying script\n"); |
522 | 0 | goto error_req; |
523 | 0 | } |
524 | 0 | } |
525 | 0 | } |
526 | | |
527 | 0 | if(exectime) { |
528 | 0 | gettimeofday(&tve, NULL); |
529 | 0 | diff = (tve.tv_sec - tvb.tv_sec) * 1000000 |
530 | 0 | + (tve.tv_usec - tvb.tv_usec); |
531 | 0 | if(cfg_get(core, core_cfg, latency_limit_cfg) == 0 |
532 | 0 | || cfg_get(core, core_cfg, latency_limit_cfg) <= diff) { |
533 | 0 | LOG(cfg_get(core, core_cfg, latency_cfg_log), |
534 | 0 | "request-route executed in: %d usec\n", diff); |
535 | 0 | } |
536 | 0 | } |
537 | | |
538 | | /* execute post request-script callbacks */ |
539 | 0 | exec_post_script_cb(msg, REQUEST_CB_TYPE); |
540 | 0 | } else if(msg->first_line.type == SIP_REPLY) { |
541 | | /* sanity checks */ |
542 | 0 | if((msg->via1 == 0) || (msg->via1->error != PARSE_OK)) { |
543 | | /* no via, send back error ? */ |
544 | 0 | LM_ERR("no via found in reply\n"); |
545 | 0 | STATS_BAD_RPL(); |
546 | 0 | goto error02; |
547 | 0 | } |
548 | 0 | if(unlikely((msg->callid == 0) || (msg->cseq == 0) || (msg->from == 0) |
549 | 0 | || (msg->to == 0))) { |
550 | | /* no required headers -- send back error ? */ |
551 | 0 | LOG(cfg_get(core, core_cfg, sip_parser_log), |
552 | 0 | "required headers not found in reply\n"); |
553 | 0 | STATS_BAD_RPL(); |
554 | 0 | goto error02; |
555 | 0 | } |
556 | | |
557 | 0 | if(exectime) { |
558 | 0 | gettimeofday(&tvb, NULL); |
559 | 0 | } |
560 | | |
561 | | /* execute pre-script callbacks, if any; -jiri */ |
562 | | /* if some of the callbacks said not to continue with |
563 | | * script processing, don't do so |
564 | | * if we are here basic sanity checks are already done |
565 | | * (like presence of at least one via), so you can count |
566 | | * on via1 being parsed in a pre-script callback --andrei |
567 | | */ |
568 | 0 | if(exec_pre_script_cb(msg, ONREPLY_CB_TYPE) == 0) { |
569 | 0 | STATS_RPL_FWD_DROP(); |
570 | 0 | goto end; /* drop the reply */ |
571 | 0 | } |
572 | | |
573 | | /* exec the onreply routing script */ |
574 | 0 | if(kemi_reply_route_callback.len > 0) { |
575 | 0 | keng = sr_kemi_eng_get(); |
576 | 0 | } |
577 | 0 | if(onreply_rt.rlist[DEFAULT_RT] != NULL || keng != NULL) { |
578 | 0 | set_route_type(CORE_ONREPLY_ROUTE); |
579 | 0 | ret = 1; |
580 | 0 | if(unlikely(keng != NULL)) { |
581 | 0 | bctx = sr_kemi_act_ctx_get(); |
582 | 0 | init_run_actions_ctx(&ctx); |
583 | 0 | sr_kemi_act_ctx_set(&ctx); |
584 | 0 | if(unlikely(cidlockset)) { |
585 | 0 | rec_lock_set_get(ksr_route_locks_set, cidlockidx); |
586 | 0 | ret = sr_kemi_route( |
587 | 0 | keng, msg, CORE_ONREPLY_ROUTE, NULL, NULL); |
588 | 0 | rec_lock_set_release(ksr_route_locks_set, cidlockidx); |
589 | 0 | } else { |
590 | 0 | ret = sr_kemi_route( |
591 | 0 | keng, msg, CORE_ONREPLY_ROUTE, NULL, NULL); |
592 | 0 | } |
593 | 0 | sr_kemi_act_ctx_set(bctx); |
594 | 0 | } else { |
595 | 0 | if(unlikely(cidlockset)) { |
596 | 0 | rec_lock_set_get(ksr_route_locks_set, cidlockidx); |
597 | 0 | ret = run_top_route( |
598 | 0 | onreply_rt.rlist[DEFAULT_RT], msg, &ctx); |
599 | 0 | rec_lock_set_release(ksr_route_locks_set, cidlockidx); |
600 | 0 | } else { |
601 | 0 | ret = run_top_route( |
602 | 0 | onreply_rt.rlist[DEFAULT_RT], msg, &ctx); |
603 | 0 | } |
604 | 0 | } |
605 | 0 | #ifndef NO_ONREPLY_ROUTE_ERROR |
606 | 0 | if(unlikely(ret < 0)) { |
607 | 0 | LM_WARN("error while trying onreply script\n"); |
608 | 0 | goto error_rpl; |
609 | 0 | } else |
610 | 0 | #endif /* NO_ONREPLY_ROUTE_ERROR */ |
611 | 0 | if(unlikely(ret == 0 || (ctx.run_flags & DROP_R_F))) { |
612 | 0 | STATS_RPL_FWD_DROP(); |
613 | 0 | LM_DBG("drop flag set - skip forwarding the reply\n"); |
614 | 0 | goto skip_send_reply; /* drop the message, no error */ |
615 | 0 | } |
616 | 0 | } |
617 | | /* send the msg */ |
618 | 0 | forward_reply(msg); |
619 | 0 | skip_send_reply: |
620 | 0 | if(exectime) { |
621 | 0 | gettimeofday(&tve, NULL); |
622 | 0 | diff = (tve.tv_sec - tvb.tv_sec) * 1000000 |
623 | 0 | + (tve.tv_usec - tvb.tv_usec); |
624 | 0 | if(cfg_get(core, core_cfg, latency_limit_cfg) == 0 |
625 | 0 | || cfg_get(core, core_cfg, latency_limit_cfg) <= diff) { |
626 | 0 | LOG(cfg_get(core, core_cfg, latency_cfg_log), |
627 | 0 | "reply-route executed in: %d usec\n", diff); |
628 | 0 | } |
629 | 0 | } |
630 | | |
631 | | /* execute post reply-script callbacks */ |
632 | 0 | exec_post_script_cb(msg, ONREPLY_CB_TYPE); |
633 | 0 | } |
634 | | |
635 | 0 | end: |
636 | 0 | ksr_msg_env_reset(); |
637 | 0 | LM_DBG("cleaning up\n"); |
638 | 0 | free_sip_msg(msg); |
639 | 0 | pkg_free(msg); |
640 | | /* reset log prefix */ |
641 | 0 | log_prefix_set(NULL); |
642 | 0 | return 0; |
643 | | |
644 | 0 | #ifndef NO_ONREPLY_ROUTE_ERROR |
645 | 0 | error_rpl: |
646 | | /* execute post reply-script callbacks */ |
647 | 0 | exec_post_script_cb(msg, ONREPLY_CB_TYPE); |
648 | 0 | goto error02; |
649 | 0 | #endif /* NO_ONREPLY_ROUTE_ERROR */ |
650 | 0 | error_req: |
651 | 0 | LM_DBG("error:...\n"); |
652 | | /* execute post request-script callbacks */ |
653 | 0 | exec_post_script_cb(msg, REQUEST_CB_TYPE); |
654 | 0 | error03: |
655 | 0 | error02: |
656 | 0 | free_sip_msg(msg); |
657 | 0 | pkg_free(msg); |
658 | 0 | error00: |
659 | 0 | ksr_msg_env_reset(); |
660 | | /* reset log prefix */ |
661 | 0 | log_prefix_set(NULL); |
662 | 0 | return -1; |
663 | 0 | } |
664 | | |
665 | | /** |
666 | | * clean up msg environment, such as avp, xavp and xavu lists |
667 | | */ |
668 | | void ksr_msg_env_reset(void) |
669 | 0 | { |
670 | 0 | reset_avps(); |
671 | 0 | xavp_reset_list(); |
672 | 0 | xavu_reset_list(); |
673 | 0 | xavi_reset_list(); |
674 | 0 | } |