~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjsip-apps/src/samples/proxy.h

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: proxy.h 3553 2011-05-05 06:14:19Z nanang $ */
2
 
/*
3
 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
 
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5
 
 *
6
 
 * This program 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
 
 * This program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
 */
20
 
#include <pjsip.h>
21
 
#include <pjlib-util.h>
22
 
#include <pjlib.h>
23
 
 
24
 
 
25
 
/* Options */
26
 
static struct global_struct
27
 
{
28
 
    pj_caching_pool      cp;
29
 
    pjsip_endpoint      *endpt;
30
 
    int                  port;
31
 
    pj_pool_t           *pool;
32
 
 
33
 
    pj_thread_t         *thread;
34
 
    pj_bool_t            quit_flag;
35
 
 
36
 
    pj_bool_t            record_route;
37
 
 
38
 
    unsigned             name_cnt;
39
 
    pjsip_host_port      name[16];
40
 
} global;
41
 
 
42
 
 
43
 
 
44
 
static void app_perror(const char *msg, pj_status_t status)
45
 
{
46
 
    char errmsg[PJ_ERR_MSG_SIZE];
47
 
 
48
 
    pj_strerror(status, errmsg, sizeof(errmsg));
49
 
    PJ_LOG(1,(THIS_FILE, "%s: %s", msg, errmsg));
50
 
}
51
 
 
52
 
 
53
 
static void usage(void)
54
 
{
55
 
    puts("Options:\n"
56
 
         "\n"
57
 
         " -p, --port N       Set local listener port to N\n"
58
 
         " -R, --rr           Perform record routing\n"
59
 
         " -L, --log-level N  Set log level to N (default: 4)\n"
60
 
         " -h, --help         Show this help screen\n"
61
 
         );
62
 
}
63
 
 
64
 
 
65
 
static pj_status_t init_options(int argc, char *argv[])
66
 
{
67
 
    struct pj_getopt_option long_opt[] = {
68
 
        { "port",       1, 0, 'p'},
69
 
        { "rr",         0, 0, 'R'},
70
 
        { "log-level",  1, 0, 'L'},
71
 
        { "help",       0, 0, 'h'},
72
 
        { NULL,         0, 0, 0}
73
 
    };
74
 
    int c;
75
 
    int opt_ind;
76
 
 
77
 
    pj_optind = 0;
78
 
    while((c=pj_getopt_long(argc, argv, "p:L:Rh", long_opt, &opt_ind))!=-1) {
79
 
        switch (c) {
80
 
        case 'p':
81
 
            global.port = atoi(pj_optarg);
82
 
            printf("Port is set to %d\n", global.port);
83
 
            break;
84
 
 
85
 
        case 'R':
86
 
            global.record_route = PJ_TRUE;
87
 
            printf("Using record route mode\n");
88
 
            break;
89
 
 
90
 
        case 'L':
91
 
            pj_log_set_level(atoi(pj_optarg));
92
 
            break;
93
 
 
94
 
        case 'h':
95
 
            usage();
96
 
            return -1;
97
 
 
98
 
        default:
99
 
            puts("Unknown option. Run with --help for help.");
100
 
            return -1;
101
 
        }
102
 
    }
103
 
 
104
 
    return PJ_SUCCESS;
105
 
}
106
 
 
107
 
 
108
 
/*****************************************************************************
109
 
 * This is a very simple PJSIP module, whose sole purpose is to display
110
 
 * incoming and outgoing messages to log. This module will have priority
111
 
 * higher than transport layer, which means:
112
 
 *
113
 
 *  - incoming messages will come to this module first before reaching
114
 
 *    transaction layer.
115
 
 *
116
 
 *  - outgoing messages will come to this module last, after the message
117
 
 *    has been 'printed' to contiguous buffer by transport layer and
118
 
 *    appropriate transport instance has been decided for this message.
119
 
 *
120
 
 */
121
 
 
122
 
/* Notification on incoming messages */
123
 
static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
124
 
{
125
 
    PJ_LOG(5,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
126
 
                         "%.*s\n"
127
 
                         "--end msg--",
128
 
                         rdata->msg_info.len,
129
 
                         pjsip_rx_data_get_info(rdata),
130
 
                         rdata->tp_info.transport->type_name,
131
 
                         rdata->pkt_info.src_name,
132
 
                         rdata->pkt_info.src_port,
133
 
                         (int)rdata->msg_info.len,
134
 
                         rdata->msg_info.msg_buf));
135
 
 
136
 
    /* Always return false, otherwise messages will not get processed! */
137
 
    return PJ_FALSE;
138
 
}
139
 
 
140
 
/* Notification on outgoing messages */
141
 
static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
142
 
{
143
 
 
144
 
    /* Important note:
145
 
     *  tp_info field is only valid after outgoing messages has passed
146
 
     *  transport layer. So don't try to access tp_info when the module
147
 
     *  has lower priority than transport layer.
148
 
     */
149
 
 
150
 
    PJ_LOG(5,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
151
 
                         "%.*s\n"
152
 
                         "--end msg--",
153
 
                         (tdata->buf.cur - tdata->buf.start),
154
 
                         pjsip_tx_data_get_info(tdata),
155
 
                         tdata->tp_info.transport->type_name,
156
 
                         tdata->tp_info.dst_name,
157
 
                         tdata->tp_info.dst_port,
158
 
                         (int)(tdata->buf.cur - tdata->buf.start),
159
 
                         tdata->buf.start));
160
 
 
161
 
    /* Always return success, otherwise message will not get sent! */
162
 
    return PJ_SUCCESS;
163
 
}
164
 
 
165
 
/* The module instance. */
166
 
static pjsip_module mod_msg_logger =
167
 
{
168
 
    NULL, NULL,                         /* prev, next.          */
169
 
    { "mod-msg-logger", 14 },           /* Name.                */
170
 
    -1,                                 /* Id                   */
171
 
    PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority            */
172
 
    NULL,                               /* load()               */
173
 
    NULL,                               /* start()              */
174
 
    NULL,                               /* stop()               */
175
 
    NULL,                               /* unload()             */
176
 
    &logging_on_rx_msg,                 /* on_rx_request()      */
177
 
    &logging_on_rx_msg,                 /* on_rx_response()     */
178
 
    &logging_on_tx_msg,                 /* on_tx_request.       */
179
 
    &logging_on_tx_msg,                 /* on_tx_response()     */
180
 
    NULL,                               /* on_tsx_state()       */
181
 
 
182
 
};
183
 
 
184
 
 
185
 
static pj_status_t init_stack(void)
186
 
{
187
 
    pj_status_t status;
188
 
 
189
 
    /* Must init PJLIB first: */
190
 
    status = pj_init();
191
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
192
 
 
193
 
 
194
 
    /* Then init PJLIB-UTIL: */
195
 
    status = pjlib_util_init();
196
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
197
 
 
198
 
 
199
 
    /* Must create a pool factory before we can allocate any memory. */
200
 
    pj_caching_pool_init(&global.cp, &pj_pool_factory_default_policy, 0);
201
 
 
202
 
    /* Create the endpoint: */
203
 
    status = pjsip_endpt_create(&global.cp.factory, NULL, &global.endpt);
204
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
205
 
 
206
 
    /* Init transaction layer for stateful proxy only */
207
 
#if STATEFUL
208
 
    status = pjsip_tsx_layer_init_module(global.endpt);
209
 
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
210
 
#endif
211
 
 
212
 
    /* Create listening transport */
213
 
    {
214
 
        pj_sockaddr_in addr;
215
 
 
216
 
        addr.sin_family = pj_AF_INET();
217
 
        addr.sin_addr.s_addr = 0;
218
 
        addr.sin_port = pj_htons((pj_uint16_t)global.port);
219
 
 
220
 
        status = pjsip_udp_transport_start( global.endpt, &addr,
221
 
                                            NULL, 1, NULL);
222
 
        if (status != PJ_SUCCESS)
223
 
            return status;
224
 
    }
225
 
 
226
 
    /* Create pool for the application */
227
 
    global.pool = pj_pool_create(&global.cp.factory, "proxyapp",
228
 
                                 4000, 4000, NULL);
229
 
 
230
 
    /* Register the logger module */
231
 
    pjsip_endpt_register_module(global.endpt, &mod_msg_logger);
232
 
 
233
 
    return PJ_SUCCESS;
234
 
}
235
 
 
236
 
 
237
 
static pj_status_t init_proxy(void)
238
 
{
239
 
    pj_sockaddr pri_addr;
240
 
    pj_sockaddr addr_list[16];
241
 
    unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list);
242
 
    unsigned i;
243
 
 
244
 
    /* List all names matching local endpoint.
245
 
     * Note that PJLIB version 0.6 and newer has a function to
246
 
     * enumerate local IP interface (pj_enum_ip_interface()), so
247
 
     * by using it would be possible to list all IP interfaces in
248
 
     * this host.
249
 
     */
250
 
 
251
 
    /* The first address is important since this would be the one
252
 
     * to be added in Record-Route.
253
 
     */
254
 
    if (pj_gethostip(pj_AF_INET(), &pri_addr)==PJ_SUCCESS) {
255
 
        pj_strdup2(global.pool, &global.name[global.name_cnt].host,
256
 
                   pj_inet_ntoa(pri_addr.ipv4.sin_addr));
257
 
        global.name[global.name_cnt].port = global.port;
258
 
        global.name_cnt++;
259
 
    }
260
 
 
261
 
    /* Get the rest of IP interfaces */
262
 
    if (pj_enum_ip_interface(pj_AF_INET(), &addr_cnt, addr_list) == PJ_SUCCESS) {
263
 
        for (i=0; i<addr_cnt; ++i) {
264
 
 
265
 
            if (addr_list[i].ipv4.sin_addr.s_addr == pri_addr.ipv4.sin_addr.s_addr)
266
 
                continue;
267
 
 
268
 
            pj_strdup2(global.pool, &global.name[global.name_cnt].host,
269
 
                       pj_inet_ntoa(addr_list[i].ipv4.sin_addr));
270
 
            global.name[global.name_cnt].port = global.port;
271
 
            global.name_cnt++;
272
 
        }
273
 
    }
274
 
 
275
 
    /* Add loopback address. */
276
 
#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
277
 
    global.name[global.name_cnt].host = pj_str("127.0.0.1");
278
 
    global.name[global.name_cnt].port = global.port;
279
 
    global.name_cnt++;
280
 
#endif
281
 
 
282
 
    global.name[global.name_cnt].host = *pj_gethostname();
283
 
    global.name[global.name_cnt].port = global.port;
284
 
    global.name_cnt++;
285
 
 
286
 
    global.name[global.name_cnt].host = pj_str("localhost");
287
 
    global.name[global.name_cnt].port = global.port;
288
 
    global.name_cnt++;
289
 
 
290
 
    PJ_LOG(3,(THIS_FILE, "Proxy started, listening on port %d", global.port));
291
 
    PJ_LOG(3,(THIS_FILE, "Local host aliases:"));
292
 
    for (i=0; i<global.name_cnt; ++i) {
293
 
        PJ_LOG(3,(THIS_FILE, " %.*s:%d",
294
 
                  (int)global.name[i].host.slen,
295
 
                  global.name[i].host.ptr,
296
 
                  global.name[i].port));
297
 
    }
298
 
 
299
 
    if (global.record_route) {
300
 
        PJ_LOG(3,(THIS_FILE, "Using Record-Route mode"));
301
 
    }
302
 
 
303
 
    return PJ_SUCCESS;
304
 
}
305
 
 
306
 
 
307
 
#if PJ_HAS_THREADS
308
 
static int worker_thread(void *p)
309
 
{
310
 
    pj_time_val delay = {0, 10};
311
 
 
312
 
    PJ_UNUSED_ARG(p);
313
 
 
314
 
    while (!global.quit_flag) {
315
 
        pjsip_endpt_handle_events(global.endpt, &delay);
316
 
    }
317
 
 
318
 
    return 0;
319
 
}
320
 
#endif
321
 
 
322
 
 
323
 
/* Utility to determine if URI is local to this host. */
324
 
static pj_bool_t is_uri_local(const pjsip_sip_uri *uri)
325
 
{
326
 
    unsigned i;
327
 
    for (i=0; i<global.name_cnt; ++i) {
328
 
        if ((uri->port == global.name[i].port ||
329
 
             (uri->port==0 && global.name[i].port==5060)) &&
330
 
            pj_stricmp(&uri->host, &global.name[i].host)==0)
331
 
        {
332
 
            /* Match */
333
 
            return PJ_TRUE;
334
 
        }
335
 
    }
336
 
 
337
 
    /* Doesn't match */
338
 
    return PJ_FALSE;
339
 
}
340
 
 
341
 
 
342
 
/* Proxy utility to verify incoming requests.
343
 
 * Return non-zero if verification failed.
344
 
 */
345
 
static pj_status_t proxy_verify_request(pjsip_rx_data *rdata)
346
 
{
347
 
    const pj_str_t STR_PROXY_REQUIRE = {"Proxy-Require", 13};
348
 
 
349
 
    /* RFC 3261 Section 16.3 Request Validation */
350
 
 
351
 
    /* Before an element can proxy a request, it MUST verify the message's
352
 
     * validity.  A valid message must pass the following checks:
353
 
     *
354
 
     * 1. Reasonable Syntax
355
 
     * 2. URI scheme
356
 
     * 3. Max-Forwards
357
 
     * 4. (Optional) Loop Detection
358
 
     * 5. Proxy-Require
359
 
     * 6. Proxy-Authorization
360
 
     */
361
 
 
362
 
    /* 1. Reasonable Syntax.
363
 
     * This would have been checked by transport layer.
364
 
     */
365
 
 
366
 
    /* 2. URI scheme.
367
 
     * We only want to support "sip:" URI scheme for this simple proxy.
368
 
     */
369
 
    if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.msg->line.req.uri)) {
370
 
        pjsip_endpt_respond_stateless(global.endpt, rdata,
371
 
                                      PJSIP_SC_UNSUPPORTED_URI_SCHEME, NULL,
372
 
                                      NULL, NULL);
373
 
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_UNSUPPORTED_URI_SCHEME);
374
 
    }
375
 
 
376
 
    /* 3. Max-Forwards.
377
 
     * Send error if Max-Forwards is 1 or lower.
378
 
     */
379
 
    if (rdata->msg_info.max_fwd && rdata->msg_info.max_fwd->ivalue <= 1) {
380
 
        pjsip_endpt_respond_stateless(global.endpt, rdata,
381
 
                                      PJSIP_SC_TOO_MANY_HOPS, NULL,
382
 
                                      NULL, NULL);
383
 
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TOO_MANY_HOPS);
384
 
    }
385
 
 
386
 
    /* 4. (Optional) Loop Detection.
387
 
     * Nah, we don't do that with this simple proxy.
388
 
     */
389
 
 
390
 
    /* 5. Proxy-Require */
391
 
    if (pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_PROXY_REQUIRE,
392
 
                                   NULL) != NULL)
393
 
    {
394
 
        pjsip_endpt_respond_stateless(global.endpt, rdata,
395
 
                                      PJSIP_SC_BAD_EXTENSION, NULL,
396
 
                                      NULL, NULL);
397
 
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION);
398
 
    }
399
 
 
400
 
    /* 6. Proxy-Authorization.
401
 
     * Nah, we don't require any authorization with this sample.
402
 
     */
403
 
 
404
 
    return PJ_SUCCESS;
405
 
}
406
 
 
407
 
 
408
 
/* Process route information in the reqeust */
409
 
static pj_status_t proxy_process_routing(pjsip_tx_data *tdata)
410
 
{
411
 
    pjsip_sip_uri *target;
412
 
    pjsip_route_hdr *hroute;
413
 
 
414
 
    /* RFC 3261 Section 16.4 Route Information Preprocessing */
415
 
 
416
 
    target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
417
 
 
418
 
    /* The proxy MUST inspect the Request-URI of the request.  If the
419
 
     * Request-URI of the request contains a value this proxy previously
420
 
     * placed into a Record-Route header field (see Section 16.6 item 4),
421
 
     * the proxy MUST replace the Request-URI in the request with the last
422
 
     * value from the Route header field, and remove that value from the
423
 
     * Route header field.  The proxy MUST then proceed as if it received
424
 
     * this modified request.
425
 
     */
426
 
    if (is_uri_local(target)) {
427
 
        pjsip_route_hdr *r;
428
 
        pjsip_sip_uri *uri;
429
 
 
430
 
        /* Find the first Route header */
431
 
        r = hroute = (pjsip_route_hdr*)
432
 
                     pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);
433
 
        if (r == NULL) {
434
 
            /* No Route header. This request is destined for this proxy. */
435
 
            return PJ_SUCCESS;
436
 
        }
437
 
 
438
 
        /* Find the last Route header */
439
 
        while ( (r=(pjsip_route_hdr*)pjsip_msg_find_hdr(tdata->msg,
440
 
                                                        PJSIP_H_ROUTE,
441
 
                                                        r->next)) != NULL )
442
 
        {
443
 
            hroute = r;
444
 
        }
445
 
 
446
 
        /* If the last Route header doesn't have ";lr" parameter, then
447
 
         * this is a strict-routed request indeed, and we follow the steps
448
 
         * in processing strict-route requests above.
449
 
         *
450
 
         * But if it does contain ";lr" parameter, skip the strict-route
451
 
         * processing.
452
 
         */
453
 
        uri = (pjsip_sip_uri*)
454
 
              pjsip_uri_get_uri(&hroute->name_addr);
455
 
        if (uri->lr_param == 0) {
456
 
            /* Yes this is strict route, so:
457
 
             * - replace req URI with the URI in Route header,
458
 
             * - remove the Route header,
459
 
             * - proceed as if it received this modified request.
460
 
            */
461
 
            tdata->msg->line.req.uri = hroute->name_addr.uri;
462
 
            target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
463
 
            pj_list_erase(hroute);
464
 
        }
465
 
    }
466
 
 
467
 
    /* If the Request-URI contains a maddr parameter, the proxy MUST check
468
 
     * to see if its value is in the set of addresses or domains the proxy
469
 
     * is configured to be responsible for.  If the Request-URI has a maddr
470
 
     * parameter with a value the proxy is responsible for, and the request
471
 
     * was received using the port and transport indicated (explicitly or by
472
 
     * default) in the Request-URI, the proxy MUST strip the maddr and any
473
 
     * non-default port or transport parameter and continue processing as if
474
 
     * those values had not been present in the request.
475
 
     */
476
 
    if (target->maddr_param.slen != 0) {
477
 
        pjsip_sip_uri maddr_uri;
478
 
 
479
 
        maddr_uri.host = target->maddr_param;
480
 
        maddr_uri.port = global.port;
481
 
 
482
 
        if (is_uri_local(&maddr_uri)) {
483
 
            target->maddr_param.slen = 0;
484
 
            target->port = 0;
485
 
            target->transport_param.slen = 0;
486
 
        }
487
 
    }
488
 
 
489
 
    /* If the first value in the Route header field indicates this proxy,
490
 
     * the proxy MUST remove that value from the request.
491
 
     */
492
 
    hroute = (pjsip_route_hdr*)
493
 
              pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);
494
 
    if (hroute && is_uri_local((pjsip_sip_uri*)hroute->name_addr.uri)) {
495
 
        pj_list_erase(hroute);
496
 
    }
497
 
 
498
 
    return PJ_SUCCESS;
499
 
}
500
 
 
501
 
 
502
 
/* Postprocess the request before forwarding it */
503
 
static void proxy_postprocess(pjsip_tx_data *tdata)
504
 
{
505
 
    /* Optionally record-route */
506
 
    if (global.record_route) {
507
 
        char uribuf[128];
508
 
        pj_str_t uri;
509
 
        const pj_str_t H_RR = { "Record-Route", 12 };
510
 
        pjsip_generic_string_hdr *rr;
511
 
 
512
 
        pj_ansi_snprintf(uribuf, sizeof(uribuf), "<sip:%.*s:%d;lr>",
513
 
                         (int)global.name[0].host.slen,
514
 
                         global.name[0].host.ptr,
515
 
                         global.name[0].port);
516
 
        uri = pj_str(uribuf);
517
 
        rr = pjsip_generic_string_hdr_create(tdata->pool,
518
 
                                             &H_RR, &uri);
519
 
        pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)rr);
520
 
    }
521
 
}
522
 
 
523
 
 
524
 
/* Calculate new target for the request */
525
 
static pj_status_t proxy_calculate_target(pjsip_rx_data *rdata,
526
 
                                          pjsip_tx_data *tdata)
527
 
{
528
 
    pjsip_sip_uri *target;
529
 
 
530
 
    /* RFC 3261 Section 16.5 Determining Request Targets */
531
 
 
532
 
    target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
533
 
 
534
 
    /* If the Request-URI of the request contains an maddr parameter, the
535
 
     * Request-URI MUST be placed into the target set as the only target
536
 
     * URI, and the proxy MUST proceed to Section 16.6.
537
 
     */
538
 
    if (target->maddr_param.slen) {
539
 
        proxy_postprocess(tdata);
540
 
        return PJ_SUCCESS;
541
 
    }
542
 
 
543
 
 
544
 
    /* If the domain of the Request-URI indicates a domain this element is
545
 
     * not responsible for, the Request-URI MUST be placed into the target
546
 
     * set as the only target, and the element MUST proceed to the task of
547
 
     * Request Forwarding (Section 16.6).
548
 
     */
549
 
    if (!is_uri_local(target)) {
550
 
        proxy_postprocess(tdata);
551
 
        return PJ_SUCCESS;
552
 
    }
553
 
 
554
 
    /* If the target set for the request has not been predetermined as
555
 
     * described above, this implies that the element is responsible for the
556
 
     * domain in the Request-URI, and the element MAY use whatever mechanism
557
 
     * it desires to determine where to send the request.
558
 
     */
559
 
 
560
 
    /* We're not interested to receive request destined to us, so
561
 
     * respond with 404/Not Found (only if request is not ACK!).
562
 
     */
563
 
    if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
564
 
        pjsip_endpt_respond_stateless(global.endpt, rdata,
565
 
                                      PJSIP_SC_NOT_FOUND, NULL,
566
 
                                      NULL, NULL);
567
 
    }
568
 
 
569
 
    /* Delete the request since we're not forwarding it */
570
 
    pjsip_tx_data_dec_ref(tdata);
571
 
 
572
 
    return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_FOUND);
573
 
}
574
 
 
575
 
 
576
 
/* Destroy stack */
577
 
static void destroy_stack(void)
578
 
{
579
 
    pjsip_endpt_destroy(global.endpt);
580
 
    pj_pool_release(global.pool);
581
 
    pj_caching_pool_destroy(&global.cp);
582
 
 
583
 
    pj_shutdown();
584
 
}