/src/pjsip/tests/fuzz/fuzz-sip.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
3 | | * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation; either version 2 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program; if not, write to the Free Software |
17 | | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | | */ |
19 | | #include <stdio.h> |
20 | | #include <stdint.h> |
21 | | #include <stdlib.h> |
22 | | |
23 | | #include <pjlib.h> |
24 | | #include <pjlib-util.h> |
25 | | #include <pjsip.h> |
26 | | #include <pjsip/sip_types.h> |
27 | | #include <pjsip/sip_multipart.h> |
28 | | #include <pjsip/sip_tel_uri.h> |
29 | | #include <pjsip/sip_auth.h> |
30 | | #include <pjsip/sip_transaction.h> |
31 | | #include <pjsip/sip_dialog.h> |
32 | | #include <pjsip-simple/evsub.h> |
33 | | #include <pjsip-ua/sip_replaces.h> |
34 | | #include <pjsip-ua/sip_timer.h> |
35 | | |
36 | | pjsip_endpoint *endpt; |
37 | | pj_caching_pool caching_pool; |
38 | | |
39 | 15.2k | #define POOL_SIZE 8000 |
40 | 1 | #define PJSIP_TEST_MEM_SIZE (2*1024*1024) |
41 | | |
42 | 15.2k | #define kMinInputLength 10 |
43 | 7.60k | #define kMaxInputLength 5120 |
44 | | |
45 | | /* Transaction user module */ |
46 | | static pjsip_module tsx_user_module; |
47 | | |
48 | | /* Transaction state callback */ |
49 | | static void on_tsx_state(pjsip_transaction *tsx, pjsip_event *event) |
50 | 0 | { |
51 | 0 | PJ_UNUSED_ARG(tsx); |
52 | 0 | PJ_UNUSED_ARG(event); |
53 | 0 | } |
54 | | |
55 | | /* Standard header types to test */ |
56 | | static const pjsip_hdr_e hdr_types[] = { |
57 | | PJSIP_H_AUTHORIZATION, |
58 | | PJSIP_H_PROXY_AUTHORIZATION, |
59 | | PJSIP_H_WWW_AUTHENTICATE, |
60 | | PJSIP_H_PROXY_AUTHENTICATE, |
61 | | PJSIP_H_ROUTE, |
62 | | PJSIP_H_RECORD_ROUTE, |
63 | | PJSIP_H_CONTACT |
64 | | }; |
65 | | |
66 | | static pjsip_msg* parse_message(pj_pool_t *pool, char *data, size_t size) |
67 | 7.60k | { |
68 | 7.60k | pjsip_parser_err_report err_list; |
69 | 7.60k | pj_list_init(&err_list); |
70 | 7.60k | return pjsip_parse_msg(pool, data, size, &err_list); |
71 | 7.60k | } |
72 | | |
73 | | /* Multipart body parsing */ |
74 | | static void do_test_multipart(pj_pool_t *pool, pjsip_msg *msg) |
75 | 4.48k | { |
76 | 4.48k | if (!msg->body) |
77 | 4.31k | return; |
78 | | |
79 | 165 | pjsip_msg_body *body = msg->body; |
80 | | |
81 | 165 | if (body->content_type.type.slen > 0 && |
82 | 165 | pj_stricmp2(&body->content_type.type, "multipart") == 0) |
83 | 60 | { |
84 | 60 | pjsip_msg_body *multipart_body = NULL; |
85 | 60 | if (body->data && body->len > 0) { |
86 | 0 | multipart_body = pjsip_multipart_parse(pool, (char *)body->data, |
87 | 0 | body->len, &body->content_type, 0); |
88 | 0 | if (!multipart_body) |
89 | 0 | return; |
90 | 60 | } else { |
91 | 60 | multipart_body = body; |
92 | 60 | } |
93 | | |
94 | 60 | pjsip_multipart_part *part = pjsip_multipart_get_first_part(multipart_body); |
95 | | |
96 | 3.58k | while (part) { |
97 | 3.52k | pjsip_media_type ctype_app, ctype_text; |
98 | | |
99 | 3.52k | ctype_app.type = pj_str("application"); |
100 | 3.52k | ctype_app.subtype = pj_str("sdp"); |
101 | 3.52k | ctype_text.type = pj_str("text"); |
102 | 3.52k | ctype_text.subtype = pj_str("plain"); |
103 | | |
104 | 3.52k | pjsip_multipart_find_part(multipart_body, &ctype_app, NULL); |
105 | 3.52k | pjsip_multipart_find_part(multipart_body, &ctype_text, NULL); |
106 | | |
107 | 3.52k | part = pjsip_multipart_get_next_part(multipart_body, part); |
108 | 3.52k | } |
109 | | |
110 | 60 | pjsip_media_type search_type; |
111 | 60 | search_type.type = pj_str("application"); |
112 | 60 | search_type.subtype = pj_str("sdp"); |
113 | 60 | pjsip_multipart_find_part(multipart_body, &search_type, NULL); |
114 | 60 | } |
115 | 165 | } |
116 | | |
117 | | /* Tel URI parsing */ |
118 | | static void do_test_tel_uri(pj_pool_t *pool, char *data, size_t size) |
119 | 7.60k | { |
120 | 7.60k | pj_str_t uri_str; |
121 | 7.60k | pjsip_uri *uri; |
122 | | |
123 | 7.60k | if (size < 4 || size > 256) |
124 | 1.64k | return; |
125 | | |
126 | 5.95k | uri_str.ptr = data; |
127 | 5.95k | uri_str.slen = (pj_ssize_t)size; |
128 | | |
129 | 5.95k | uri = pjsip_parse_uri(pool, uri_str.ptr, uri_str.slen, 0); |
130 | | |
131 | 5.95k | if (uri && size > 20) { |
132 | 655 | pj_str_t uri2_str; |
133 | 655 | pjsip_uri *uri2; |
134 | | |
135 | 655 | uri2_str.ptr = data + 10; |
136 | 655 | uri2_str.slen = (pj_ssize_t)(size - 10); |
137 | | |
138 | 655 | uri2 = pjsip_parse_uri(pool, uri2_str.ptr, uri2_str.slen, 0); |
139 | 655 | if (uri2) { |
140 | 585 | pjsip_uri_cmp(PJSIP_URI_IN_FROMTO_HDR, uri, uri2); |
141 | 585 | pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, uri, uri2); |
142 | 585 | } |
143 | 655 | } |
144 | 5.95k | } |
145 | | |
146 | | /* Test UAS transaction creation and message feeding */ |
147 | | static void do_test_transaction_layer(pjsip_msg *msg, pjsip_rx_data *rdata) |
148 | 4.48k | { |
149 | 4.48k | pj_str_t tsx_key; |
150 | 4.48k | pjsip_via_hdr *via_hdr; |
151 | | |
152 | 4.48k | if (!msg || msg->type != PJSIP_REQUEST_MSG || !rdata) |
153 | 2.88k | return; |
154 | | |
155 | 1.59k | if (!rdata->msg_info.via || !rdata->msg_info.cseq || |
156 | 1.42k | !rdata->msg_info.from || !rdata->msg_info.cid) |
157 | 172 | return; |
158 | | |
159 | 1.42k | via_hdr = rdata->msg_info.via; |
160 | | |
161 | | /* Skip transaction creation if transport not available */ |
162 | 1.42k | if (!rdata->tp_info.transport) |
163 | 0 | return; |
164 | | |
165 | | /* Ensure From/To headers have tags */ |
166 | 1.42k | pjsip_from_hdr *from_hdr = (pjsip_from_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL); |
167 | 1.42k | pjsip_to_hdr *to_hdr = (pjsip_to_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL); |
168 | | |
169 | 1.42k | if (from_hdr && pj_stricmp2(&from_hdr->tag, "") == 0) |
170 | 1.38k | from_hdr->tag = pj_str("from-tag-123"); |
171 | | |
172 | 1.42k | if (to_hdr && pj_stricmp2(&to_hdr->tag, "") == 0) |
173 | 1.40k | to_hdr->tag = pj_str("to-tag-456"); |
174 | | |
175 | | /* Ensure Via header has valid host/port for response addressing */ |
176 | 1.42k | if (via_hdr->sent_by.host.slen == 0) { |
177 | 0 | via_hdr->sent_by.host = pj_str("127.0.0.1"); |
178 | 0 | via_hdr->sent_by.port = 5060; |
179 | 0 | } |
180 | | |
181 | | /* Test transaction key generation */ |
182 | 1.42k | if (pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAS, |
183 | 1.42k | &msg->line.req.method, rdata) == PJ_SUCCESS) { |
184 | 1.42k | pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE); |
185 | 1.42k | } |
186 | 1.42k | } |
187 | | |
188 | | /* Test synthetic transaction creation */ |
189 | | static void do_test_transaction_synthetic(void) |
190 | 1 | { |
191 | 1 | pj_str_t target_uri_str = pj_str("sip:test@example.com"); |
192 | 1 | pj_str_t from_str = pj_str("sip:caller@example.com"); |
193 | 1 | pj_str_t to_str = pj_str("sip:callee@example.com"); |
194 | 1 | pj_str_t call_id_str = pj_str("call-id-fuzz-test@example.com"); |
195 | 1 | pjsip_tx_data *tdata; |
196 | | |
197 | 1 | if (pjsip_endpt_create_request(endpt, &pjsip_invite_method, |
198 | 1 | &target_uri_str, &from_str, &to_str, |
199 | 1 | NULL, &call_id_str, -1, NULL, &tdata) == PJ_SUCCESS) { |
200 | 1 | pjsip_tx_data_dec_ref(tdata); |
201 | 1 | } |
202 | 1 | } |
203 | | |
204 | | /* Test UAC transaction response handling */ |
205 | | static void do_test_transaction_uac(pjsip_msg *msg, pjsip_rx_data *rdata) |
206 | 2.88k | { |
207 | 2.88k | pj_str_t tsx_key; |
208 | | |
209 | 2.88k | if (!msg || msg->type != PJSIP_RESPONSE_MSG || !rdata) |
210 | 0 | return; |
211 | | |
212 | 2.88k | if (!rdata->msg_info.via || !rdata->msg_info.cseq || |
213 | 54 | !rdata->msg_info.from || !rdata->msg_info.cid) |
214 | 2.83k | return; |
215 | | |
216 | | /* Skip if no transport available */ |
217 | 50 | if (!rdata->tp_info.transport) |
218 | 0 | return; |
219 | | |
220 | | /* Test transaction key generation for responses */ |
221 | 50 | if (pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAC, |
222 | 50 | &rdata->msg_info.cseq->method, rdata) == PJ_SUCCESS) { |
223 | 50 | pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE); |
224 | 50 | } |
225 | 50 | } |
226 | | |
227 | | /* Test authentication client */ |
228 | | static void do_test_auth_client(pj_pool_t *pool, pjsip_msg *msg) |
229 | 4.48k | { |
230 | 4.48k | pjsip_auth_clt_sess auth_sess; |
231 | 4.48k | pjsip_hdr *hdr = NULL; |
232 | 4.48k | pj_status_t status; |
233 | | |
234 | | /* Only test with 401/407 responses */ |
235 | 4.48k | if (!msg || msg->type != PJSIP_RESPONSE_MSG) |
236 | 1.59k | return; |
237 | | |
238 | 2.88k | if (msg->line.status.code != 401 && msg->line.status.code != 407) |
239 | 2.16k | return; |
240 | | |
241 | | /* Initialize auth client session */ |
242 | 721 | if (pjsip_auth_clt_init(&auth_sess, endpt, pool, 0) != PJ_SUCCESS) |
243 | 0 | return; |
244 | | |
245 | | /* Set up credentials */ |
246 | 721 | pjsip_cred_info cred; |
247 | 721 | pj_bzero(&cred, sizeof(cred)); |
248 | 721 | cred.realm = pj_str("test"); |
249 | 721 | cred.username = pj_str("user"); |
250 | 721 | cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; |
251 | 721 | cred.data = pj_str("password"); |
252 | | |
253 | 721 | if (pjsip_auth_clt_set_credentials(&auth_sess, 1, &cred) != PJ_SUCCESS) |
254 | 0 | goto cleanup; |
255 | | |
256 | | /* Parse authentication headers */ |
257 | 721 | if (msg->line.status.code == 401) |
258 | 707 | hdr = pjsip_msg_find_hdr(msg, PJSIP_H_WWW_AUTHENTICATE, NULL); |
259 | 14 | else |
260 | 14 | hdr = pjsip_msg_find_hdr(msg, PJSIP_H_PROXY_AUTHENTICATE, NULL); |
261 | | |
262 | 721 | if (hdr) { |
263 | | /* Create a dummy request to test reinit */ |
264 | 591 | pjsip_tx_data *tdata = NULL; |
265 | 591 | pjsip_method method; |
266 | 591 | pj_str_t target_uri = pj_str("sip:server.com"); |
267 | 591 | pj_str_t from_uri = pj_str("sip:client@local"); |
268 | 591 | pj_str_t to_uri = pj_str("sip:server.com"); |
269 | 591 | pj_str_t contact = pj_str("sip:client@local"); |
270 | | |
271 | 591 | pjsip_method_set(&method, PJSIP_REGISTER_METHOD); |
272 | | |
273 | 591 | status = pjsip_endpt_create_request(endpt, &method, &target_uri, |
274 | 591 | &from_uri, &to_uri, &contact, |
275 | 591 | NULL, -1, NULL, &tdata); |
276 | 591 | if (status != PJ_SUCCESS || !tdata) |
277 | 0 | goto cleanup; |
278 | | |
279 | | /* Initialize request with auth */ |
280 | 591 | pjsip_auth_clt_init_req(&auth_sess, tdata); |
281 | | |
282 | | /* Create rx_data from the 401/407 message */ |
283 | 591 | pjsip_rx_data rdata; |
284 | 591 | pj_bzero(&rdata, sizeof(rdata)); |
285 | 591 | rdata.msg_info.msg = msg; |
286 | 591 | rdata.msg_info.info = NULL; |
287 | 591 | rdata.msg_info.len = 1024; |
288 | | |
289 | | /* Try to reinit with the challenge */ |
290 | 591 | pjsip_tx_data *new_tdata = NULL; |
291 | 591 | if (pjsip_auth_clt_reinit_req(&auth_sess, &rdata, tdata, &new_tdata) == PJ_SUCCESS && new_tdata) { |
292 | 256 | pjsip_tx_data_dec_ref(new_tdata); |
293 | 256 | } |
294 | | |
295 | 591 | pjsip_tx_data_dec_ref(tdata); |
296 | 591 | } |
297 | | |
298 | 721 | cleanup: |
299 | 721 | pjsip_auth_clt_deinit(&auth_sess); |
300 | 721 | } |
301 | | |
302 | | /* Test dialog creation */ |
303 | | static void do_test_dialog(pjsip_msg *msg) |
304 | 4.48k | { |
305 | 4.48k | pjsip_dialog *dlg = NULL; |
306 | 4.48k | pjsip_to_hdr *to; |
307 | 4.48k | pjsip_from_hdr *from; |
308 | 4.48k | pj_str_t local_uri = pj_str("sip:local@test.com"); |
309 | 4.48k | pj_str_t remote_uri = pj_str("sip:remote@test.com"); |
310 | 4.48k | pj_str_t target = pj_str("sip:remote@test.com"); |
311 | | |
312 | 4.48k | if (!msg || msg->type != PJSIP_REQUEST_MSG) |
313 | 2.88k | return; |
314 | | |
315 | 1.59k | if (msg->line.req.method.id != PJSIP_INVITE_METHOD) |
316 | 1.27k | return; |
317 | | |
318 | | /* Get To and From headers */ |
319 | 326 | to = (pjsip_to_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL); |
320 | 326 | from = (pjsip_from_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL); |
321 | 326 | if (!to || !from) |
322 | 4 | return; |
323 | | |
324 | | /* Create UAC dialog */ |
325 | 322 | if (pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL, |
326 | 322 | &remote_uri, &target, &dlg) == PJ_SUCCESS && dlg) { |
327 | 322 | pjsip_dlg_inc_lock(dlg); |
328 | | |
329 | | /* Build route set from all Route headers */ |
330 | 322 | pjsip_route_hdr route_set; |
331 | 322 | pjsip_route_hdr *route; |
332 | 322 | pj_list_init(&route_set); |
333 | 322 | route = (pjsip_route_hdr*) |
334 | 322 | pjsip_msg_find_hdr(msg, PJSIP_H_ROUTE, NULL); |
335 | 3.44k | while (route) { |
336 | 3.12k | pjsip_route_hdr *route_clone = (pjsip_route_hdr*) |
337 | 3.12k | pjsip_hdr_clone(dlg->pool, route); |
338 | 3.12k | pj_list_push_back(&route_set, route_clone); |
339 | 3.12k | route = (pjsip_route_hdr*) |
340 | 3.12k | pjsip_msg_find_hdr(msg, PJSIP_H_ROUTE, |
341 | 3.12k | route->next); |
342 | 3.12k | } |
343 | 322 | if (!pj_list_empty(&route_set)) { |
344 | 92 | pjsip_dlg_set_route_set(dlg, &route_set); |
345 | 92 | } |
346 | | |
347 | 322 | pjsip_dlg_dec_lock(dlg); |
348 | 322 | } |
349 | 322 | } |
350 | | |
351 | | extern int |
352 | | LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) |
353 | 7.61k | { |
354 | 7.61k | char *DataFx; |
355 | 7.61k | pj_pool_t *pool; |
356 | 7.61k | pjsip_msg *msg; |
357 | 7.61k | static int initialized = 0; |
358 | | |
359 | 7.61k | if (Size < kMinInputLength || Size > kMaxInputLength) |
360 | 10 | return 1; |
361 | | |
362 | 7.60k | DataFx = (char *)calloc((Size+1), sizeof(char)); |
363 | 7.60k | if (DataFx == NULL) |
364 | 0 | return 0; |
365 | 7.60k | memcpy((void *)DataFx, (void *)Data, Size); |
366 | | |
367 | 7.60k | if (!initialized) { |
368 | 1 | pj_log_set_level(0); |
369 | | |
370 | 1 | if (pj_init() != PJ_SUCCESS || pjlib_util_init() != PJ_SUCCESS) { |
371 | 0 | free(DataFx); |
372 | 0 | return 0; |
373 | 0 | } |
374 | | |
375 | 1 | pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy, |
376 | 1 | PJSIP_TEST_MEM_SIZE); |
377 | | |
378 | 1 | if (pjsip_endpt_create(&caching_pool.factory, "endpt", &endpt) != PJ_SUCCESS || !endpt) { |
379 | 0 | free(DataFx); |
380 | 0 | return 0; |
381 | 0 | } |
382 | | |
383 | 1 | if (pjsip_tsx_layer_init_module(endpt) != PJ_SUCCESS || |
384 | 1 | pjsip_loop_start(endpt, NULL) != PJ_SUCCESS) { |
385 | 0 | free(DataFx); |
386 | 0 | return 0; |
387 | 0 | } |
388 | | |
389 | 1 | pjsip_ua_init_module(endpt, NULL); |
390 | | |
391 | | /* Register the specialised SIP header parsers. The core SIP parser |
392 | | * only installs grammars for headers whose owning module has been |
393 | | * initialised; without these calls the headers below are parsed as |
394 | | * generic string headers and the hand-written grammars in |
395 | | * evsub_msg.c (Event/Subscription-State/Allow-Events), |
396 | | * sip_replaces.c (Replaces) and sip_timer.c (Session-Expires/Min-SE) |
397 | | * are never exercised even when present in the input message. */ |
398 | 1 | if (pjsip_evsub_init_module(endpt) != PJ_SUCCESS || |
399 | 1 | pjsip_replaces_init_module(endpt) != PJ_SUCCESS || |
400 | 1 | pjsip_timer_init_module(endpt) != PJ_SUCCESS) { |
401 | 0 | free(DataFx); |
402 | 0 | return 0; |
403 | 0 | } |
404 | | |
405 | | /* Initialize transaction user module */ |
406 | 1 | pj_bzero(&tsx_user_module, sizeof(tsx_user_module)); |
407 | 1 | tsx_user_module.name = pj_str("tsx-user"); |
408 | 1 | tsx_user_module.id = -1; |
409 | 1 | tsx_user_module.priority = PJSIP_MOD_PRIORITY_APPLICATION; |
410 | 1 | tsx_user_module.on_tsx_state = &on_tsx_state; |
411 | 1 | pjsip_endpt_register_module(endpt, &tsx_user_module); |
412 | | |
413 | 1 | do_test_transaction_synthetic(); |
414 | | |
415 | 1 | initialized = 1; |
416 | 1 | } |
417 | | |
418 | 7.60k | pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE); |
419 | 7.60k | msg = parse_message(pool, DataFx, Size); |
420 | | |
421 | 7.60k | if (msg) { |
422 | 4.48k | pjsip_rx_data rdata; |
423 | 4.48k | pj_sockaddr remote_addr; |
424 | 4.48k | pjsip_transport *fake_transport = NULL; |
425 | 4.48k | int i; |
426 | | |
427 | 4.48k | do_test_multipart(pool, msg); |
428 | | |
429 | | /* Test named headers */ |
430 | 4.48k | const char *hdr_names[] = { |
431 | 4.48k | "Replaces", "Refer-To", "Refer-Sub", "Subscription-State", |
432 | 4.48k | "Session-Expires", "Min-SE", "RSeq", "RAck" |
433 | 4.48k | }; |
434 | 40.3k | for (i = 0; i < (int)(sizeof(hdr_names) / sizeof(hdr_names[0])); i++) { |
435 | 35.8k | pj_str_t hdr_name = pj_str((char *)hdr_names[i]); |
436 | 35.8k | pjsip_msg_find_hdr_by_name(msg, &hdr_name, NULL); |
437 | 35.8k | } |
438 | | |
439 | | /* Test standard header types */ |
440 | 35.8k | for (i = 0; i < (int)(sizeof(hdr_types) / sizeof(hdr_types[0])); i++) { |
441 | 31.3k | pjsip_msg_find_hdr(msg, hdr_types[i], NULL); |
442 | 31.3k | } |
443 | | |
444 | | /* Setup rx_data for transaction testing */ |
445 | 4.48k | pj_bzero(&rdata, sizeof(rdata)); |
446 | 4.48k | rdata.msg_info.msg = msg; |
447 | 4.48k | rdata.msg_info.len = Size; |
448 | 4.48k | rdata.msg_info.info = DataFx; |
449 | 4.48k | rdata.tp_info.pool = pool; |
450 | | |
451 | | /* Populate header shortcuts */ |
452 | 4.48k | rdata.msg_info.from = (pjsip_from_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL); |
453 | 4.48k | rdata.msg_info.to = (pjsip_to_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL); |
454 | 4.48k | rdata.msg_info.via = (pjsip_via_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_VIA, NULL); |
455 | 4.48k | rdata.msg_info.cseq = (pjsip_cseq_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL); |
456 | 4.48k | rdata.msg_info.cid = (pjsip_cid_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CALL_ID, NULL); |
457 | 4.48k | rdata.msg_info.max_fwd = (pjsip_max_fwd_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_MAX_FORWARDS, NULL); |
458 | | |
459 | | /* Setup transport info */ |
460 | 4.48k | pj_sockaddr_init(pj_AF_INET(), &remote_addr, NULL, 5060); |
461 | 4.48k | remote_addr.ipv4.sin_addr.s_addr = pj_htonl(0x7F000001); |
462 | | |
463 | 4.48k | pj_memcpy(&rdata.pkt_info.src_addr, &remote_addr, |
464 | 4.48k | sizeof(remote_addr.ipv4)); |
465 | 4.48k | rdata.pkt_info.src_addr_len = sizeof(remote_addr.ipv4); |
466 | 4.48k | pj_ansi_snprintf(rdata.pkt_info.src_name, sizeof(rdata.pkt_info.src_name), |
467 | 4.48k | "127.0.0.1"); |
468 | 4.48k | rdata.pkt_info.src_port = 5060; |
469 | 4.48k | if (Size < sizeof(rdata.pkt_info.packet)) { |
470 | 4.39k | pj_memcpy(rdata.pkt_info.packet, DataFx, Size); |
471 | 4.39k | rdata.pkt_info.len = Size; |
472 | 4.39k | } else { |
473 | 84 | pj_memcpy(rdata.pkt_info.packet, DataFx, sizeof(rdata.pkt_info.packet)); |
474 | 84 | rdata.pkt_info.len = sizeof(rdata.pkt_info.packet); |
475 | 84 | } |
476 | | |
477 | | /* Acquire loop datagram transport */ |
478 | 4.48k | if (pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, |
479 | 4.48k | &remote_addr, |
480 | 4.48k | sizeof(remote_addr.ipv4), |
481 | 4.48k | NULL, &fake_transport) == PJ_SUCCESS) { |
482 | 4.48k | rdata.tp_info.transport = fake_transport; |
483 | 4.48k | } |
484 | | |
485 | 4.48k | do_test_transaction_layer(msg, &rdata); |
486 | | |
487 | 4.48k | if (msg->type == PJSIP_RESPONSE_MSG) { |
488 | 2.88k | do_test_transaction_uac(msg, &rdata); |
489 | 2.88k | } |
490 | | |
491 | 4.48k | do_test_auth_client(pool, msg); |
492 | 4.48k | do_test_dialog(msg); |
493 | | |
494 | 4.48k | if (msg->type == PJSIP_REQUEST_MSG && rdata.msg_info.via) { |
495 | 1.44k | pj_strdup2(pool, &rdata.msg_info.via->recvd_param, |
496 | 1.44k | rdata.pkt_info.src_name); |
497 | 1.44k | if (rdata.msg_info.via->rport_param == 0) { |
498 | 26 | rdata.msg_info.via->rport_param = rdata.pkt_info.src_port; |
499 | 26 | } |
500 | 1.44k | } |
501 | | |
502 | | /* Route through the full endpoint module pipeline */ |
503 | 4.48k | if (rdata.tp_info.transport && |
504 | 4.48k | rdata.msg_info.from && rdata.msg_info.to && |
505 | 1.55k | rdata.msg_info.via && rdata.msg_info.cseq && |
506 | 1.44k | rdata.msg_info.cid && rdata.msg_info.cid->id.slen != 0) { |
507 | 1.44k | pjsip_transaction *tsx; |
508 | 1.44k | pj_time_val timeout = {0, 0}; |
509 | 1.44k | unsigned i; |
510 | | |
511 | 1.44k | pjsip_endpt_process_rx_data(endpt, &rdata, NULL, NULL); |
512 | | |
513 | 1.44k | tsx = pjsip_rdata_get_tsx(&rdata); |
514 | 1.44k | if (tsx) { |
515 | 0 | pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED); |
516 | 0 | } |
517 | | |
518 | | /* Pump events repeatedly */ |
519 | 13.0k | for (i = 0; i < 8; ++i) { |
520 | 11.5k | pjsip_endpt_handle_events(endpt, &timeout); |
521 | 11.5k | } |
522 | 1.44k | } |
523 | | |
524 | | /* Release transport */ |
525 | 4.48k | if (fake_transport) { |
526 | 4.48k | pjsip_transport_dec_ref(fake_transport); |
527 | 4.48k | } |
528 | 4.48k | } |
529 | | |
530 | 7.60k | do_test_tel_uri(pool, DataFx, Size); |
531 | | |
532 | 7.60k | pjsip_endpt_release_pool(endpt, pool); |
533 | 7.60k | free(DataFx); |
534 | | |
535 | 7.60k | return 0; |
536 | 7.60k | } |
537 | | |