Coverage Report

Created: 2026-10-28 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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.9k
#define POOL_SIZE       8000
40
1
#define PJSIP_TEST_MEM_SIZE         (2*1024*1024)
41
42
15.9k
#define kMinInputLength 10
43
7.96k
#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
/* Stub resolver.
56
 *
57
 * Message content can direct a response to an arbitrary host name (e.g. via
58
 * the Via "maddr" parameter, see RFC 3261 section 18.2.2), which would make
59
 * the endpoint perform a real DNS lookup with getaddrinfo(). Blocking network
60
 * I/O is not allowed in the fuzzing environment, so resolve every target to
61
 * the loopback address on the loop transport instead.
62
 */
63
static void fuzz_resolve(pjsip_resolver_t *resolver, pj_pool_t *pool,
64
                         const pjsip_host_info *target, void *token,
65
                         pjsip_resolver_callback *cb)
66
1.55k
{
67
1.55k
    pjsip_server_addresses svr_addr;
68
1.55k
    pj_uint16_t port;
69
70
1.55k
    PJ_UNUSED_ARG(resolver);
71
1.55k
    PJ_UNUSED_ARG(pool);
72
73
1.55k
    port = (pj_uint16_t)(target->addr.port? target->addr.port : 5060);
74
75
1.55k
    pj_bzero(&svr_addr, sizeof(svr_addr));
76
1.55k
    svr_addr.count = 1;
77
1.55k
    svr_addr.entry[0].name = target->addr.host;
78
1.55k
    svr_addr.entry[0].type = PJSIP_TRANSPORT_LOOP_DGRAM;
79
1.55k
    pj_sockaddr_in_init(&svr_addr.entry[0].addr.ipv4, NULL, port);
80
1.55k
    svr_addr.entry[0].addr.ipv4.sin_addr.s_addr = pj_htonl(0x7F000001);
81
1.55k
    svr_addr.entry[0].addr_len = sizeof(pj_sockaddr_in);
82
83
1.55k
    (*cb)(PJ_SUCCESS, token, &svr_addr);
84
1.55k
}
85
86
static pjsip_ext_resolver fuzz_ext_resolver = { &fuzz_resolve };
87
88
/* Standard header types to test */
89
static const pjsip_hdr_e hdr_types[] = {
90
    PJSIP_H_AUTHORIZATION,
91
    PJSIP_H_PROXY_AUTHORIZATION,
92
    PJSIP_H_WWW_AUTHENTICATE,
93
    PJSIP_H_PROXY_AUTHENTICATE,
94
    PJSIP_H_ROUTE,
95
    PJSIP_H_RECORD_ROUTE,
96
    PJSIP_H_CONTACT
97
};
98
99
static pjsip_msg* parse_message(pj_pool_t *pool, char *data, size_t size)
100
7.96k
{
101
7.96k
    pjsip_parser_err_report err_list;
102
7.96k
    pj_list_init(&err_list);
103
7.96k
    return pjsip_parse_msg(pool, data, size, &err_list);
104
7.96k
}
105
106
/* Multipart body parsing */
107
static void do_test_multipart(pj_pool_t *pool, pjsip_msg *msg)
108
4.83k
{
109
4.83k
    if (!msg->body)
110
4.66k
        return;
111
112
171
    pjsip_msg_body *body = msg->body;
113
114
171
    if (body->content_type.type.slen > 0 &&
115
171
        pj_stricmp2(&body->content_type.type, "multipart") == 0)
116
69
    {
117
69
        pjsip_msg_body *multipart_body = NULL;
118
69
        if (body->data && body->len > 0) {
119
0
            multipart_body = pjsip_multipart_parse(pool, (char *)body->data,
120
0
                                                   body->len, &body->content_type, 0);
121
0
            if (!multipart_body)
122
0
                return;
123
69
        } else {
124
69
            multipart_body = body;
125
69
        }
126
127
69
        pjsip_multipart_part *part = pjsip_multipart_get_first_part(multipart_body);
128
129
6.31k
        while (part) {
130
6.24k
            pjsip_media_type ctype_app, ctype_text;
131
132
6.24k
            ctype_app.type = pj_str("application");
133
6.24k
            ctype_app.subtype = pj_str("sdp");
134
6.24k
            ctype_text.type = pj_str("text");
135
6.24k
            ctype_text.subtype = pj_str("plain");
136
137
6.24k
            pjsip_multipart_find_part(multipart_body, &ctype_app, NULL);
138
6.24k
            pjsip_multipart_find_part(multipart_body, &ctype_text, NULL);
139
140
6.24k
            part = pjsip_multipart_get_next_part(multipart_body, part);
141
6.24k
        }
142
143
69
        pjsip_media_type search_type;
144
69
        search_type.type = pj_str("application");
145
69
        search_type.subtype = pj_str("sdp");
146
69
        pjsip_multipart_find_part(multipart_body, &search_type, NULL);
147
69
    }
148
171
}
149
150
/* Tel URI parsing */
151
static void do_test_tel_uri(pj_pool_t *pool, char *data, size_t size)
152
7.96k
{
153
7.96k
    pj_str_t uri_str;
154
7.96k
    pjsip_uri *uri;
155
156
7.96k
    if (size < 4 || size > 256)
157
1.63k
        return;
158
159
6.32k
    uri_str.ptr = data;
160
6.32k
    uri_str.slen = (pj_ssize_t)size;
161
162
6.32k
    uri = pjsip_parse_uri(pool, uri_str.ptr, uri_str.slen, 0);
163
164
6.32k
    if (uri && size > 20) {
165
706
        pj_str_t uri2_str;
166
706
        pjsip_uri *uri2;
167
168
706
        uri2_str.ptr = data + 10;
169
706
        uri2_str.slen = (pj_ssize_t)(size - 10);
170
171
706
        uri2 = pjsip_parse_uri(pool, uri2_str.ptr, uri2_str.slen, 0);
172
706
        if (uri2) {
173
634
            pjsip_uri_cmp(PJSIP_URI_IN_FROMTO_HDR, uri, uri2);
174
634
            pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, uri, uri2);
175
634
        }
176
706
    }
177
6.32k
}
178
179
/* Test UAS transaction creation and message feeding */
180
static void do_test_transaction_layer(pjsip_msg *msg, pjsip_rx_data *rdata)
181
4.83k
{
182
4.83k
    pj_str_t tsx_key;
183
4.83k
    pjsip_via_hdr *via_hdr;
184
185
4.83k
    if (!msg || msg->type != PJSIP_REQUEST_MSG || !rdata)
186
3.05k
        return;
187
188
1.78k
    if (!rdata->msg_info.via || !rdata->msg_info.cseq ||
189
1.61k
        !rdata->msg_info.from || !rdata->msg_info.cid)
190
175
        return;
191
192
1.60k
    via_hdr = rdata->msg_info.via;
193
194
    /* Skip transaction creation if transport not available */
195
1.60k
    if (!rdata->tp_info.transport)
196
0
        return;
197
198
    /* Ensure From/To headers have tags */
199
1.60k
    pjsip_from_hdr *from_hdr = (pjsip_from_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL);
200
1.60k
    pjsip_to_hdr *to_hdr = (pjsip_to_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL);
201
202
1.60k
    if (from_hdr && pj_stricmp2(&from_hdr->tag, "") == 0)
203
1.56k
        from_hdr->tag = pj_str("from-tag-123");
204
205
1.60k
    if (to_hdr && pj_stricmp2(&to_hdr->tag, "") == 0)
206
1.58k
        to_hdr->tag = pj_str("to-tag-456");
207
208
    /* Ensure Via header has valid host/port for response addressing */
209
1.60k
    if (via_hdr->sent_by.host.slen == 0) {
210
0
        via_hdr->sent_by.host = pj_str("127.0.0.1");
211
0
        via_hdr->sent_by.port = 5060;
212
0
    }
213
214
    /* Test transaction key generation */
215
1.60k
    if (pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAS,
216
1.60k
                             &msg->line.req.method, rdata) == PJ_SUCCESS) {
217
1.60k
        pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE);
218
1.60k
    }
219
1.60k
}
220
221
/* Test synthetic transaction creation */
222
static void do_test_transaction_synthetic(void)
223
1
{
224
1
    pj_str_t target_uri_str = pj_str("sip:test@example.com");
225
1
    pj_str_t from_str = pj_str("sip:caller@example.com");
226
1
    pj_str_t to_str = pj_str("sip:callee@example.com");
227
1
    pj_str_t call_id_str = pj_str("call-id-fuzz-test@example.com");
228
1
    pjsip_tx_data *tdata;
229
230
1
    if (pjsip_endpt_create_request(endpt, &pjsip_invite_method,
231
1
                                   &target_uri_str, &from_str, &to_str,
232
1
                                   NULL, &call_id_str, -1, NULL, &tdata) == PJ_SUCCESS) {
233
1
        pjsip_tx_data_dec_ref(tdata);
234
1
    }
235
1
}
236
237
/* Test UAC transaction response handling */
238
static void do_test_transaction_uac(pjsip_msg *msg, pjsip_rx_data *rdata)
239
3.05k
{
240
3.05k
    pj_str_t tsx_key;
241
242
3.05k
    if (!msg || msg->type != PJSIP_RESPONSE_MSG || !rdata)
243
0
        return;
244
245
3.05k
    if (!rdata->msg_info.via || !rdata->msg_info.cseq ||
246
84
        !rdata->msg_info.from || !rdata->msg_info.cid)
247
2.96k
        return;
248
249
    /* Skip if no transport available */
250
81
    if (!rdata->tp_info.transport)
251
0
        return;
252
253
    /* Test transaction key generation for responses */
254
81
    if (pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAC,
255
81
                             &rdata->msg_info.cseq->method, rdata) == PJ_SUCCESS) {
256
81
        pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE);
257
81
    }
258
81
}
259
260
/* Test authentication client */
261
static void do_test_auth_client(pj_pool_t *pool, pjsip_msg *msg)
262
4.83k
{
263
4.83k
    pjsip_auth_clt_sess auth_sess;
264
4.83k
    pjsip_hdr *hdr = NULL;
265
4.83k
    pj_status_t status;
266
267
    /* Only test with 401/407 responses */
268
4.83k
    if (!msg || msg->type != PJSIP_RESPONSE_MSG)
269
1.78k
        return;
270
271
3.05k
    if (msg->line.status.code != 401 && msg->line.status.code != 407)
272
2.29k
        return;
273
274
    /* Initialize auth client session */
275
758
    if (pjsip_auth_clt_init(&auth_sess, endpt, pool, 0) != PJ_SUCCESS)
276
0
        return;
277
278
    /* Set up credentials */
279
758
    pjsip_cred_info cred;
280
758
    pj_bzero(&cred, sizeof(cred));
281
758
    cred.realm = pj_str("test");
282
758
    cred.username = pj_str("user");
283
758
    cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
284
758
    cred.data = pj_str("password");
285
286
758
    if (pjsip_auth_clt_set_credentials(&auth_sess, 1, &cred) != PJ_SUCCESS)
287
0
        goto cleanup;
288
289
    /* Parse authentication headers */
290
758
    if (msg->line.status.code == 401)
291
745
        hdr = pjsip_msg_find_hdr(msg, PJSIP_H_WWW_AUTHENTICATE, NULL);
292
13
    else
293
13
        hdr = pjsip_msg_find_hdr(msg, PJSIP_H_PROXY_AUTHENTICATE, NULL);
294
295
758
    if (hdr) {
296
        /* Create a dummy request to test reinit */
297
592
        pjsip_tx_data *tdata = NULL;
298
592
        pjsip_method method;
299
592
        pj_str_t target_uri = pj_str("sip:server.com");
300
592
        pj_str_t from_uri = pj_str("sip:client@local");
301
592
        pj_str_t to_uri = pj_str("sip:server.com");
302
592
        pj_str_t contact = pj_str("sip:client@local");
303
304
592
        pjsip_method_set(&method, PJSIP_REGISTER_METHOD);
305
306
592
        status = pjsip_endpt_create_request(endpt, &method, &target_uri,
307
592
                                           &from_uri, &to_uri, &contact,
308
592
                                           NULL, -1, NULL, &tdata);
309
592
        if (status != PJ_SUCCESS || !tdata)
310
0
            goto cleanup;
311
312
        /* Initialize request with auth */
313
592
        pjsip_auth_clt_init_req(&auth_sess, tdata);
314
315
        /* Create rx_data from the 401/407 message */
316
592
        pjsip_rx_data rdata;
317
592
        pj_bzero(&rdata, sizeof(rdata));
318
592
        rdata.msg_info.msg = msg;
319
592
        rdata.msg_info.info = NULL;
320
592
        rdata.msg_info.len = 1024;
321
322
        /* Try to reinit with the challenge */
323
592
        pjsip_tx_data *new_tdata = NULL;
324
592
        if (pjsip_auth_clt_reinit_req(&auth_sess, &rdata, tdata, &new_tdata) == PJ_SUCCESS && new_tdata) {
325
263
            pjsip_tx_data_dec_ref(new_tdata);
326
263
        }
327
328
592
        pjsip_tx_data_dec_ref(tdata);
329
592
    }
330
331
758
cleanup:
332
758
    pjsip_auth_clt_deinit(&auth_sess);
333
758
}
334
335
/* Test dialog creation */
336
static void do_test_dialog(pjsip_msg *msg)
337
4.83k
{
338
4.83k
    pjsip_dialog *dlg = NULL;
339
4.83k
    pjsip_to_hdr *to;
340
4.83k
    pjsip_from_hdr *from;
341
4.83k
    pj_str_t local_uri = pj_str("sip:local@test.com");
342
4.83k
    pj_str_t remote_uri = pj_str("sip:remote@test.com");
343
4.83k
    pj_str_t target = pj_str("sip:remote@test.com");
344
345
4.83k
    if (!msg || msg->type != PJSIP_REQUEST_MSG)
346
3.05k
        return;
347
348
1.78k
    if (msg->line.req.method.id != PJSIP_INVITE_METHOD)
349
1.61k
        return;
350
351
    /* Get To and From headers */
352
164
    to = (pjsip_to_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL);
353
164
    from = (pjsip_from_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL);
354
164
    if (!to || !from)
355
3
        return;
356
357
    /* Create UAC dialog */
358
161
    if (pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL,
359
161
                             &remote_uri, &target, &dlg) == PJ_SUCCESS && dlg) {
360
161
        pjsip_dlg_inc_lock(dlg);
361
362
        /* Build route set from all Route headers */
363
161
        pjsip_route_hdr route_set;
364
161
        pjsip_route_hdr *route;
365
161
        pj_list_init(&route_set);
366
161
        route = (pjsip_route_hdr*)
367
161
                pjsip_msg_find_hdr(msg, PJSIP_H_ROUTE, NULL);
368
2.69k
        while (route) {
369
2.53k
            pjsip_route_hdr *route_clone = (pjsip_route_hdr*)
370
2.53k
                    pjsip_hdr_clone(dlg->pool, route);
371
2.53k
            pj_list_push_back(&route_set, route_clone);
372
2.53k
            route = (pjsip_route_hdr*)
373
2.53k
                    pjsip_msg_find_hdr(msg, PJSIP_H_ROUTE,
374
2.53k
                                        route->next);
375
2.53k
        }
376
161
        if (!pj_list_empty(&route_set)) {
377
88
            pjsip_dlg_set_route_set(dlg, &route_set);
378
88
        }
379
380
161
        pjsip_dlg_dec_lock(dlg);
381
161
    }
382
161
}
383
384
extern int
385
LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
386
7.97k
{
387
7.97k
    char *DataFx;
388
7.97k
    pj_pool_t *pool;
389
7.97k
    pjsip_msg *msg;
390
7.97k
    static int initialized = 0;
391
392
7.97k
    if (Size < kMinInputLength || Size > kMaxInputLength)
393
10
        return 1;
394
395
7.96k
    DataFx = (char *)calloc((Size+1), sizeof(char));
396
7.96k
    if (DataFx == NULL)
397
0
        return 0;
398
7.96k
    memcpy((void *)DataFx, (void *)Data, Size);
399
400
7.96k
    if (!initialized) {
401
1
        pj_log_set_level(0);
402
403
1
        if (pj_init() != PJ_SUCCESS || pjlib_util_init() != PJ_SUCCESS) {
404
0
            free(DataFx);
405
0
            return 0;
406
0
        }
407
408
1
        pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy,
409
1
                            PJSIP_TEST_MEM_SIZE);
410
411
1
        if (pjsip_endpt_create(&caching_pool.factory, "endpt", &endpt) != PJ_SUCCESS || !endpt) {
412
0
            free(DataFx);
413
0
            return 0;
414
0
        }
415
416
1
        if (pjsip_tsx_layer_init_module(endpt) != PJ_SUCCESS ||
417
1
            pjsip_loop_start(endpt, NULL) != PJ_SUCCESS) {
418
0
            free(DataFx);
419
0
            return 0;
420
0
        }
421
422
1
        if (pjsip_endpt_set_ext_resolver(endpt, &fuzz_ext_resolver)
423
1
            != PJ_SUCCESS)
424
0
        {
425
0
            free(DataFx);
426
0
            return 0;
427
0
        }
428
429
1
        pjsip_ua_init_module(endpt, NULL);
430
431
        /* Register the specialised SIP header parsers. The core SIP parser
432
         * only installs grammars for headers whose owning module has been
433
         * initialised; without these calls the headers below are parsed as
434
         * generic string headers and the hand-written grammars in
435
         * evsub_msg.c (Event/Subscription-State/Allow-Events),
436
         * sip_replaces.c (Replaces) and sip_timer.c (Session-Expires/Min-SE)
437
         * are never exercised even when present in the input message. */
438
1
        if (pjsip_evsub_init_module(endpt) != PJ_SUCCESS ||
439
1
            pjsip_replaces_init_module(endpt) != PJ_SUCCESS ||
440
1
            pjsip_timer_init_module(endpt) != PJ_SUCCESS) {
441
0
            free(DataFx);
442
0
            return 0;
443
0
        }
444
445
        /* Initialize transaction user module */
446
1
        pj_bzero(&tsx_user_module, sizeof(tsx_user_module));
447
1
        tsx_user_module.name = pj_str("tsx-user");
448
1
        tsx_user_module.id = -1;
449
1
        tsx_user_module.priority = PJSIP_MOD_PRIORITY_APPLICATION;
450
1
        tsx_user_module.on_tsx_state = &on_tsx_state;
451
1
        pjsip_endpt_register_module(endpt, &tsx_user_module);
452
453
1
        do_test_transaction_synthetic();
454
455
1
        initialized = 1;
456
1
    }
457
458
7.96k
    pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
459
7.96k
    msg = parse_message(pool, DataFx, Size);
460
461
7.96k
    if (msg) {
462
4.83k
        pjsip_rx_data rdata;
463
4.83k
        pj_sockaddr remote_addr;
464
4.83k
        pjsip_transport *fake_transport = NULL;
465
4.83k
        int i;
466
467
4.83k
        do_test_multipart(pool, msg);
468
469
        /* Test named headers */
470
4.83k
        const char *hdr_names[] = {
471
4.83k
            "Replaces", "Refer-To", "Refer-Sub", "Subscription-State",
472
4.83k
            "Session-Expires", "Min-SE", "RSeq", "RAck"
473
4.83k
        };
474
43.4k
        for (i = 0; i < (int)(sizeof(hdr_names) / sizeof(hdr_names[0])); i++) {
475
38.6k
            pj_str_t hdr_name = pj_str((char *)hdr_names[i]);
476
38.6k
            pjsip_msg_find_hdr_by_name(msg, &hdr_name, NULL);
477
38.6k
        }
478
479
        /* Test standard header types */
480
38.6k
        for (i = 0; i < (int)(sizeof(hdr_types) / sizeof(hdr_types[0])); i++) {
481
33.8k
            pjsip_msg_find_hdr(msg, hdr_types[i], NULL);
482
33.8k
        }
483
484
        /* Setup rx_data for transaction testing */
485
4.83k
        pj_bzero(&rdata, sizeof(rdata));
486
4.83k
        rdata.msg_info.msg = msg;
487
4.83k
        rdata.msg_info.len = Size;
488
4.83k
        rdata.msg_info.info = DataFx;
489
4.83k
        rdata.tp_info.pool = pool;
490
491
        /* Populate header shortcuts */
492
4.83k
        rdata.msg_info.from = (pjsip_from_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL);
493
4.83k
        rdata.msg_info.to = (pjsip_to_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL);
494
4.83k
        rdata.msg_info.via = (pjsip_via_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_VIA, NULL);
495
4.83k
        rdata.msg_info.cseq = (pjsip_cseq_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL);
496
4.83k
        rdata.msg_info.cid = (pjsip_cid_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CALL_ID, NULL);
497
4.83k
        rdata.msg_info.max_fwd = (pjsip_max_fwd_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_MAX_FORWARDS, NULL);
498
499
        /* Setup transport info */
500
4.83k
        pj_sockaddr_init(pj_AF_INET(), &remote_addr, NULL, 5060);
501
4.83k
        remote_addr.ipv4.sin_addr.s_addr = pj_htonl(0x7F000001);
502
503
4.83k
        pj_memcpy(&rdata.pkt_info.src_addr, &remote_addr,
504
4.83k
                  sizeof(remote_addr.ipv4));
505
4.83k
        rdata.pkt_info.src_addr_len = sizeof(remote_addr.ipv4);
506
4.83k
        pj_ansi_snprintf(rdata.pkt_info.src_name, sizeof(rdata.pkt_info.src_name),
507
4.83k
                         "127.0.0.1");
508
4.83k
        rdata.pkt_info.src_port = 5060;
509
4.83k
        if (Size < sizeof(rdata.pkt_info.packet)) {
510
4.74k
            pj_memcpy(rdata.pkt_info.packet, DataFx, Size);
511
4.74k
            rdata.pkt_info.len = Size;
512
4.74k
        } else {
513
86
            pj_memcpy(rdata.pkt_info.packet, DataFx, sizeof(rdata.pkt_info.packet));
514
86
            rdata.pkt_info.len = sizeof(rdata.pkt_info.packet);
515
86
        }
516
517
        /* Acquire loop datagram transport */
518
4.83k
        if (pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
519
4.83k
                                          &remote_addr,
520
4.83k
                                          sizeof(remote_addr.ipv4),
521
4.83k
                                          NULL, &fake_transport) == PJ_SUCCESS) {
522
4.83k
            rdata.tp_info.transport = fake_transport;
523
4.83k
        }
524
525
4.83k
        do_test_transaction_layer(msg, &rdata);
526
527
4.83k
        if (msg->type == PJSIP_RESPONSE_MSG) {
528
3.05k
            do_test_transaction_uac(msg, &rdata);
529
3.05k
        }
530
531
4.83k
        do_test_auth_client(pool, msg);
532
4.83k
        do_test_dialog(msg);
533
534
4.83k
        if (msg->type == PJSIP_REQUEST_MSG && rdata.msg_info.via) {
535
1.63k
            pj_strdup2(pool, &rdata.msg_info.via->recvd_param,
536
1.63k
                       rdata.pkt_info.src_name);
537
1.63k
            if (rdata.msg_info.via->rport_param == 0) {
538
29
                rdata.msg_info.via->rport_param = rdata.pkt_info.src_port;
539
29
            }
540
1.63k
        }
541
542
        /* Route through the full endpoint module pipeline */
543
4.83k
        if (rdata.tp_info.transport &&
544
4.83k
            rdata.msg_info.from && rdata.msg_info.to &&
545
1.73k
            rdata.msg_info.via && rdata.msg_info.cseq &&
546
1.62k
            rdata.msg_info.cid && rdata.msg_info.cid->id.slen != 0) {
547
1.62k
            pjsip_transaction *tsx;
548
1.62k
            pj_time_val timeout = {0, 0};
549
1.62k
            unsigned i;
550
551
1.62k
            pjsip_endpt_process_rx_data(endpt, &rdata, NULL, NULL);
552
553
1.62k
            tsx = pjsip_rdata_get_tsx(&rdata);
554
1.62k
            if (tsx) {
555
0
                pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
556
0
            }
557
558
            /* Pump events repeatedly */
559
14.6k
            for (i = 0; i < 8; ++i) {
560
13.0k
                pjsip_endpt_handle_events(endpt, &timeout);
561
13.0k
            }
562
1.62k
        }
563
564
        /* Release transport */
565
4.83k
        if (fake_transport) {
566
4.83k
            pjsip_transport_dec_ref(fake_transport);
567
4.83k
        }
568
4.83k
    }
569
570
7.96k
    do_test_tel_uri(pool, DataFx, Size);
571
572
7.96k
    pjsip_endpt_release_pool(endpt, pool);
573
7.96k
    free(DataFx);
574
575
7.96k
    return 0;
576
7.96k
}
577