~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip/src/pjsip/sip_endpoint.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* 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: sip_endpoint.c 4411 2013-03-04 04:34:38Z 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/sip_endpoint.h>
 
21
#include <pjsip/sip_transaction.h>
 
22
#include <pjsip/sip_private.h>
 
23
#include <pjsip/sip_event.h>
 
24
#include <pjsip/sip_resolve.h>
 
25
#include <pjsip/sip_module.h>
 
26
#include <pjsip/sip_util.h>
 
27
#include <pjsip/sip_errno.h>
 
28
#include <pj/except.h>
 
29
#include <pj/log.h>
 
30
#include <pj/string.h>
 
31
#include <pj/os.h>
 
32
#include <pj/pool.h>
 
33
#include <pj/hash.h>
 
34
#include <pj/assert.h>
 
35
#include <pj/errno.h>
 
36
#include <pj/lock.h>
 
37
 
 
38
#define PJSIP_EX_NO_MEMORY  pj_NO_MEMORY_EXCEPTION()
 
39
#define THIS_FILE           "sip_endpoint.c"
 
40
 
 
41
#define MAX_METHODS   32
 
42
 
 
43
 
 
44
/* List of SIP endpoint exit callback. */
 
45
typedef struct exit_cb
 
46
{
 
47
    PJ_DECL_LIST_MEMBER             (struct exit_cb);
 
48
    pjsip_endpt_exit_callback       func;
 
49
} exit_cb;
 
50
 
 
51
 
 
52
/**
 
53
 * The SIP endpoint.
 
54
 */
 
55
struct pjsip_endpoint
 
56
{
 
57
    /** Pool to allocate memory for the endpoint. */
 
58
    pj_pool_t           *pool;
 
59
 
 
60
    /** Mutex for the pool, hash table, and event list/queue. */
 
61
    pj_mutex_t          *mutex;
 
62
 
 
63
    /** Pool factory. */
 
64
    pj_pool_factory     *pf;
 
65
 
 
66
    /** Name. */
 
67
    pj_str_t             name;
 
68
 
 
69
    /** Timer heap. */
 
70
    pj_timer_heap_t     *timer_heap;
 
71
 
 
72
    /** Transport manager. */
 
73
    pjsip_tpmgr         *transport_mgr;
 
74
 
 
75
    /** Ioqueue. */
 
76
    pj_ioqueue_t        *ioqueue;
 
77
 
 
78
    /** Last ioqueue err */
 
79
    pj_status_t          ioq_last_err;
 
80
 
 
81
    /** DNS Resolver. */
 
82
    pjsip_resolver_t    *resolver;
 
83
 
 
84
    /** Modules lock. */
 
85
    pj_rwmutex_t        *mod_mutex;
 
86
 
 
87
    /** Modules. */
 
88
    pjsip_module        *modules[PJSIP_MAX_MODULE];
 
89
 
 
90
    /** Module list, sorted by priority. */
 
91
    pjsip_module         module_list;
 
92
 
 
93
    /** Capability header list. */
 
94
    pjsip_hdr            cap_hdr;
 
95
 
 
96
    /** Additional request headers. */
 
97
    pjsip_hdr            req_hdr;
 
98
 
 
99
    /** List of exit callback. */
 
100
    exit_cb              exit_cb_list;
 
101
};
 
102
 
 
103
 
 
104
#if defined(PJSIP_SAFE_MODULE) && PJSIP_SAFE_MODULE!=0
 
105
#   define LOCK_MODULE_ACCESS(ept)      pj_rwmutex_lock_read(ept->mod_mutex)
 
106
#   define UNLOCK_MODULE_ACCESS(ept)    pj_rwmutex_unlock_read(ept->mod_mutex)
 
107
#else
 
108
#   define LOCK_MODULE_ACCESS(endpt)
 
109
#   define UNLOCK_MODULE_ACCESS(endpt)
 
110
#endif
 
111
 
 
112
 
 
113
 
 
114
/*
 
115
 * Prototypes.
 
116
 */
 
117
static void endpt_on_rx_msg( pjsip_endpoint*, 
 
118
                             pj_status_t, pjsip_rx_data*);
 
119
static pj_status_t endpt_on_tx_msg( pjsip_endpoint *endpt,
 
120
                                    pjsip_tx_data *tdata );
 
121
static pj_status_t unload_module(pjsip_endpoint *endpt,
 
122
                                 pjsip_module *mod);
 
123
 
 
124
/* Defined in sip_parser.c */
 
125
void init_sip_parser(void);
 
126
void deinit_sip_parser(void);
 
127
 
 
128
/* Defined in sip_tel_uri.c */
 
129
pj_status_t pjsip_tel_uri_subsys_init(void);
 
130
 
 
131
 
 
132
/*
 
133
 * This is the global handler for memory allocation failure, for pools that
 
134
 * are created by the endpoint (by default, all pools ARE allocated by 
 
135
 * endpoint). The error is handled by throwing exception, and hopefully,
 
136
 * the exception will be handled by the application (or this library).
 
137
 */
 
138
static void pool_callback( pj_pool_t *pool, pj_size_t size )
 
139
{
 
140
    PJ_UNUSED_ARG(pool);
 
141
    PJ_UNUSED_ARG(size);
 
142
 
 
143
    PJ_THROW(PJSIP_EX_NO_MEMORY);
 
144
}
 
145
 
 
146
 
 
147
/* Compare module name, used for searching module based on name. */
 
148
static int cmp_mod_name(void *name, const void *mod)
 
149
{
 
150
    return pj_stricmp((const pj_str_t*)name, &((pjsip_module*)mod)->name);
 
151
}
 
152
 
 
153
/*
 
154
 * Register new module to the endpoint.
 
155
 * The endpoint will then call the load and start function in the module to 
 
156
 * properly initialize the module, and assign a unique module ID for the 
 
157
 * module.
 
158
 */
 
159
PJ_DEF(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt,
 
160
                                                 pjsip_module *mod )
 
161
{
 
162
    pj_status_t status = PJ_SUCCESS;
 
163
    pjsip_module *m;
 
164
    unsigned i;
 
165
 
 
166
    pj_rwmutex_lock_write(endpt->mod_mutex);
 
167
 
 
168
    /* Make sure that this module has not been registered. */
 
169
    PJ_ASSERT_ON_FAIL(  pj_list_find_node(&endpt->module_list, mod) == NULL,
 
170
                        {status = PJ_EEXISTS; goto on_return;});
 
171
 
 
172
    /* Make sure that no module with the same name has been registered. */
 
173
    PJ_ASSERT_ON_FAIL(  pj_list_search(&endpt->module_list, &mod->name, 
 
174
                                       &cmp_mod_name)==NULL,
 
175
                        {status = PJ_EEXISTS; goto on_return; });
 
176
 
 
177
    /* Find unused ID for this module. */
 
178
    for (i=0; i<PJ_ARRAY_SIZE(endpt->modules); ++i) {
 
179
        if (endpt->modules[i] == NULL)
 
180
            break;
 
181
    }
 
182
    if (i == PJ_ARRAY_SIZE(endpt->modules)) {
 
183
        pj_assert(!"Too many modules registered!");
 
184
        status = PJ_ETOOMANY;
 
185
        goto on_return;
 
186
    }
 
187
 
 
188
    /* Assign the ID. */
 
189
    mod->id = i;
 
190
 
 
191
    /* Try to load the module. */
 
192
    if (mod->load) {
 
193
        status = (*mod->load)(endpt);
 
194
        if (status != PJ_SUCCESS)
 
195
            goto on_return;
 
196
    }
 
197
 
 
198
    /* Try to start the module. */
 
199
    if (mod->start) {
 
200
        status = (*mod->start)();
 
201
        if (status != PJ_SUCCESS)
 
202
            goto on_return;
 
203
    }
 
204
 
 
205
    /* Save the module. */
 
206
    endpt->modules[i] = mod;
 
207
 
 
208
    /* Put in the module list, sorted by priority. */
 
209
    m = endpt->module_list.next;
 
210
    while (m != &endpt->module_list) {
 
211
        if (m->priority > mod->priority)
 
212
            break;
 
213
        m = m->next;
 
214
    }
 
215
    pj_list_insert_before(m, mod);
 
216
 
 
217
    /* Done. */
 
218
 
 
219
    PJ_LOG(4,(THIS_FILE, "Module \"%.*s\" registered", 
 
220
              (int)mod->name.slen, mod->name.ptr));
 
221
 
 
222
on_return:
 
223
    pj_rwmutex_unlock_write(endpt->mod_mutex);
 
224
    return status;
 
225
}
 
226
 
 
227
/*
 
228
 * Unregister a module from the endpoint.
 
229
 * The endpoint will then call the stop and unload function in the module to 
 
230
 * properly shutdown the module.
 
231
 */
 
232
PJ_DEF(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt,
 
233
                                                   pjsip_module *mod )
 
234
{
 
235
    pj_status_t status;
 
236
 
 
237
    pj_rwmutex_lock_write(endpt->mod_mutex);
 
238
 
 
239
    /* Make sure the module exists in the list. */
 
240
    PJ_ASSERT_ON_FAIL(  pj_list_find_node(&endpt->module_list, mod) == mod,
 
241
                        {status = PJ_ENOTFOUND;goto on_return;} );
 
242
 
 
243
    /* Make sure the module exists in the array. */
 
244
    PJ_ASSERT_ON_FAIL(  mod->id>=0 && 
 
245
                        mod->id<(int)PJ_ARRAY_SIZE(endpt->modules) &&
 
246
                        endpt->modules[mod->id] == mod,
 
247
                        {status = PJ_ENOTFOUND; goto on_return;});
 
248
 
 
249
    /* Try to stop the module. */
 
250
    if (mod->stop) {
 
251
        status = (*mod->stop)();
 
252
        if (status != PJ_SUCCESS) goto on_return;
 
253
    }
 
254
 
 
255
    /* Unload module */
 
256
    status = unload_module(endpt, mod);
 
257
 
 
258
on_return:
 
259
    pj_rwmutex_unlock_write(endpt->mod_mutex);
 
260
 
 
261
    if (status != PJ_SUCCESS) {
 
262
        char errmsg[PJ_ERR_MSG_SIZE];
 
263
 
 
264
        pj_strerror(status, errmsg, sizeof(errmsg));
 
265
        PJ_LOG(3,(THIS_FILE, "Module \"%.*s\" can not be unregistered: %s",
 
266
                  (int)mod->name.slen, mod->name.ptr, errmsg));
 
267
    }
 
268
 
 
269
    return status;
 
270
}
 
271
 
 
272
static pj_status_t unload_module(pjsip_endpoint *endpt,
 
273
                                 pjsip_module *mod)
 
274
{
 
275
    pj_status_t status;
 
276
 
 
277
    /* Try to unload the module. */
 
278
    if (mod->unload) {
 
279
        status = (*mod->unload)();
 
280
        if (status != PJ_SUCCESS) 
 
281
            return status;
 
282
    }
 
283
 
 
284
    /* Module MUST NOT set module ID to -1. */
 
285
    pj_assert(mod->id >= 0);
 
286
 
 
287
    /* Remove module from array. */
 
288
    endpt->modules[mod->id] = NULL;
 
289
 
 
290
    /* Remove module from list. */
 
291
    pj_list_erase(mod);
 
292
 
 
293
    /* Set module Id to -1. */
 
294
    mod->id = -1;
 
295
 
 
296
    /* Done. */
 
297
    status = PJ_SUCCESS;
 
298
 
 
299
    PJ_LOG(4,(THIS_FILE, "Module \"%.*s\" unregistered", 
 
300
              (int)mod->name.slen, mod->name.ptr));
 
301
 
 
302
    return status;
 
303
}
 
304
 
 
305
 
 
306
/*
 
307
 * Get the value of the specified capability header field.
 
308
 */
 
309
PJ_DEF(const pjsip_hdr*) pjsip_endpt_get_capability( pjsip_endpoint *endpt,
 
310
                                                     int htype,
 
311
                                                     const pj_str_t *hname)
 
312
{
 
313
    pjsip_hdr *hdr = endpt->cap_hdr.next;
 
314
 
 
315
    /* Check arguments. */
 
316
    PJ_ASSERT_RETURN(endpt != NULL, NULL);
 
317
    PJ_ASSERT_RETURN(htype != PJSIP_H_OTHER || hname, NULL);
 
318
 
 
319
    if (htype != PJSIP_H_OTHER) {
 
320
        while (hdr != &endpt->cap_hdr) {
 
321
            if (hdr->type == htype)
 
322
                return hdr;
 
323
            hdr = hdr->next;
 
324
        }
 
325
    }
 
326
    return NULL;
 
327
}
 
328
 
 
329
 
 
330
/*
 
331
 * Check if the specified capability is supported.
 
332
 */
 
333
PJ_DEF(pj_bool_t) pjsip_endpt_has_capability( pjsip_endpoint *endpt,
 
334
                                              int htype,
 
335
                                              const pj_str_t *hname,
 
336
                                              const pj_str_t *token)
 
337
{
 
338
    const pjsip_generic_array_hdr *hdr;
 
339
    unsigned i;
 
340
 
 
341
    hdr = (const pjsip_generic_array_hdr*) 
 
342
           pjsip_endpt_get_capability(endpt, htype, hname);
 
343
    if (!hdr)
 
344
        return PJ_FALSE;
 
345
 
 
346
    PJ_ASSERT_RETURN(token != NULL, PJ_FALSE);
 
347
 
 
348
    for (i=0; i<hdr->count; ++i) {
 
349
        if (!pj_stricmp(&hdr->values[i], token))
 
350
            return PJ_TRUE;
 
351
    }
 
352
 
 
353
    return PJ_FALSE;
 
354
}
 
355
 
 
356
/*
 
357
 * Add or register new capabilities as indicated by the tags to the
 
358
 * appropriate header fields in the endpoint.
 
359
 */
 
360
PJ_DEF(pj_status_t) pjsip_endpt_add_capability( pjsip_endpoint *endpt,
 
361
                                                pjsip_module *mod,
 
362
                                                int htype,
 
363
                                                const pj_str_t *hname,
 
364
                                                unsigned count,
 
365
                                                const pj_str_t tags[])
 
366
{
 
367
    pjsip_generic_array_hdr *hdr;
 
368
    unsigned i;
 
369
 
 
370
    PJ_UNUSED_ARG(mod);
 
371
 
 
372
    /* Check arguments. */
 
373
    PJ_ASSERT_RETURN(endpt!=NULL && count>0 && tags, PJ_EINVAL);
 
374
    PJ_ASSERT_RETURN(htype==PJSIP_H_ACCEPT || 
 
375
                     htype==PJSIP_H_ALLOW ||
 
376
                     htype==PJSIP_H_SUPPORTED,
 
377
                     PJ_EINVAL);
 
378
 
 
379
    /* Find the header. */
 
380
    hdr = (pjsip_generic_array_hdr*) pjsip_endpt_get_capability(endpt, 
 
381
                                                                htype, hname);
 
382
 
 
383
    /* Create the header when it's not present */
 
384
    if (hdr == NULL) {
 
385
        switch (htype) {
 
386
        case PJSIP_H_ACCEPT:
 
387
            hdr = pjsip_accept_hdr_create(endpt->pool);
 
388
            break;
 
389
        case PJSIP_H_ALLOW:
 
390
            hdr = pjsip_allow_hdr_create(endpt->pool);
 
391
            break;
 
392
        case PJSIP_H_SUPPORTED:
 
393
            hdr = pjsip_supported_hdr_create(endpt->pool);
 
394
            break;
 
395
        default:
 
396
            return PJ_EINVAL;
 
397
        }
 
398
 
 
399
        if (hdr) {
 
400
            pj_list_push_back(&endpt->cap_hdr, hdr);
 
401
        }
 
402
    }
 
403
 
 
404
    /* Add the tags to the header. */
 
405
    for (i=0; i<count; ++i) {
 
406
        pj_strdup(endpt->pool, &hdr->values[hdr->count], &tags[i]);
 
407
        ++hdr->count;
 
408
    }
 
409
 
 
410
    /* Done. */
 
411
    return PJ_SUCCESS;
 
412
}
 
413
 
 
414
/*
 
415
 * Get additional headers to be put in outgoing request message.
 
416
 */
 
417
PJ_DEF(const pjsip_hdr*) pjsip_endpt_get_request_headers(pjsip_endpoint *endpt)
 
418
{
 
419
    return &endpt->req_hdr;
 
420
}
 
421
 
 
422
 
 
423
/*
 
424
 * Initialize endpoint.
 
425
 */
 
426
PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
 
427
                                       const char *name,
 
428
                                       pjsip_endpoint **p_endpt)
 
429
{
 
430
    pj_status_t status;
 
431
    pj_pool_t *pool;
 
432
    pjsip_endpoint *endpt;
 
433
    pjsip_max_fwd_hdr *mf_hdr;
 
434
    pj_lock_t *lock = NULL;
 
435
 
 
436
 
 
437
    status = pj_register_strerror(PJSIP_ERRNO_START, PJ_ERRNO_SPACE_SIZE,
 
438
                                  &pjsip_strerror);
 
439
    pj_assert(status == PJ_SUCCESS);
 
440
 
 
441
    PJ_LOG(5, (THIS_FILE, "Creating endpoint instance..."));
 
442
 
 
443
    *p_endpt = NULL;
 
444
 
 
445
    /* Create pool */
 
446
    pool = pj_pool_create(pf, "pept%p", 
 
447
                          PJSIP_POOL_LEN_ENDPT, PJSIP_POOL_INC_ENDPT,
 
448
                          &pool_callback);
 
449
    if (!pool)
 
450
        return PJ_ENOMEM;
 
451
 
 
452
    /* Create endpoint. */
 
453
    endpt = PJ_POOL_ZALLOC_T(pool, pjsip_endpoint);
 
454
    endpt->pool = pool;
 
455
    endpt->pf = pf;
 
456
 
 
457
    /* Init modules list. */
 
458
    pj_list_init(&endpt->module_list);
 
459
 
 
460
    /* Initialize exit callback list. */
 
461
    pj_list_init(&endpt->exit_cb_list);
 
462
 
 
463
    /* Create R/W mutex for module manipulation. */
 
464
    status = pj_rwmutex_create(endpt->pool, "ept%p", &endpt->mod_mutex);
 
465
    if (status != PJ_SUCCESS)
 
466
        goto on_error;
 
467
 
 
468
    /* Init parser. */
 
469
    init_sip_parser();
 
470
 
 
471
    /* Init tel: uri */
 
472
    pjsip_tel_uri_subsys_init();
 
473
 
 
474
    /* Get name. */
 
475
    if (name != NULL) {
 
476
        pj_str_t temp;
 
477
        pj_strdup_with_null(endpt->pool, &endpt->name, pj_cstr(&temp, name));
 
478
    } else {
 
479
        pj_strdup_with_null(endpt->pool, &endpt->name, pj_gethostname());
 
480
    }
 
481
 
 
482
    /* Create mutex for the events, etc. */
 
483
    status = pj_mutex_create_recursive( endpt->pool, "ept%p", &endpt->mutex );
 
484
    if (status != PJ_SUCCESS) {
 
485
        goto on_error;
 
486
    }
 
487
 
 
488
    /* Create timer heap to manage all timers within this endpoint. */
 
489
    status = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT, 
 
490
                                   &endpt->timer_heap);
 
491
    if (status != PJ_SUCCESS) {
 
492
        goto on_error;
 
493
    }
 
494
 
 
495
    /* Set recursive lock for the timer heap. */
 
496
    status = pj_lock_create_recursive_mutex( endpt->pool, "edpt%p", &lock);
 
497
    if (status != PJ_SUCCESS) {
 
498
        goto on_error;
 
499
    }
 
500
    pj_timer_heap_set_lock(endpt->timer_heap, lock, PJ_TRUE);
 
501
 
 
502
    /* Set maximum timed out entries to process in a single poll. */
 
503
    pj_timer_heap_set_max_timed_out_per_poll(endpt->timer_heap, 
 
504
                                             PJSIP_MAX_TIMED_OUT_ENTRIES);
 
505
 
 
506
    /* Create ioqueue. */
 
507
    status = pj_ioqueue_create( endpt->pool, PJSIP_MAX_TRANSPORTS, &endpt->ioqueue);
 
508
    if (status != PJ_SUCCESS) {
 
509
        goto on_error;
 
510
    }
 
511
 
 
512
    /* Create transport manager. */
 
513
    status = pjsip_tpmgr_create( endpt->pool, endpt,
 
514
                                 &endpt_on_rx_msg,
 
515
                                 &endpt_on_tx_msg,
 
516
                                 &endpt->transport_mgr);
 
517
    if (status != PJ_SUCCESS) {
 
518
        goto on_error;
 
519
    }
 
520
 
 
521
    /* Create asynchronous DNS resolver. */
 
522
    status = pjsip_resolver_create(endpt->pool, &endpt->resolver);
 
523
    if (status != PJ_SUCCESS) {
 
524
        PJ_LOG(4, (THIS_FILE, "Error creating resolver instance"));
 
525
        goto on_error;
 
526
    }
 
527
 
 
528
    /* Initialize request headers. */
 
529
    pj_list_init(&endpt->req_hdr);
 
530
 
 
531
    /* Add "Max-Forwards" for request header. */
 
532
    mf_hdr = pjsip_max_fwd_hdr_create(endpt->pool,
 
533
                                      PJSIP_MAX_FORWARDS_VALUE);
 
534
    pj_list_insert_before( &endpt->req_hdr, mf_hdr);
 
535
 
 
536
    /* Initialize capability header list. */
 
537
    pj_list_init(&endpt->cap_hdr);
 
538
 
 
539
 
 
540
    /* Done. */
 
541
    *p_endpt = endpt;
 
542
    return status;
 
543
 
 
544
on_error:
 
545
    if (endpt->transport_mgr) {
 
546
        pjsip_tpmgr_destroy(endpt->transport_mgr);
 
547
        endpt->transport_mgr = NULL;
 
548
    }
 
549
    if (endpt->ioqueue) {
 
550
        pj_ioqueue_destroy(endpt->ioqueue);
 
551
        endpt->ioqueue = NULL;
 
552
    }
 
553
    if (endpt->timer_heap) {
 
554
        pj_timer_heap_destroy(endpt->timer_heap);
 
555
        endpt->timer_heap = NULL;
 
556
    }
 
557
    if (endpt->mutex) {
 
558
        pj_mutex_destroy(endpt->mutex);
 
559
        endpt->mutex = NULL;
 
560
    }
 
561
    if (endpt->mod_mutex) {
 
562
        pj_rwmutex_destroy(endpt->mod_mutex);
 
563
        endpt->mod_mutex = NULL;
 
564
    }
 
565
    pj_pool_release( endpt->pool );
 
566
 
 
567
    PJ_LOG(4, (THIS_FILE, "Error creating endpoint"));
 
568
    return status;
 
569
}
 
570
 
 
571
/*
 
572
 * Destroy endpoint.
 
573
 */
 
574
PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt)
 
575
{
 
576
    pjsip_module *mod;
 
577
    exit_cb *ecb;
 
578
 
 
579
    PJ_LOG(5, (THIS_FILE, "Destroying endpoing instance.."));
 
580
 
 
581
    /* Phase 1: stop all modules */
 
582
    mod = endpt->module_list.prev;
 
583
    while (mod != &endpt->module_list) {
 
584
        pjsip_module *prev = mod->prev;
 
585
        if (mod->stop) {
 
586
            (*mod->stop)();
 
587
        }
 
588
        mod = prev;
 
589
    }
 
590
 
 
591
    /* Phase 2: unload modules. */
 
592
    mod = endpt->module_list.prev;
 
593
    while (mod != &endpt->module_list) {
 
594
        pjsip_module *prev = mod->prev;
 
595
        unload_module(endpt, mod);
 
596
        mod = prev;
 
597
    }
 
598
 
 
599
    /* Destroy resolver */
 
600
    pjsip_resolver_destroy(endpt->resolver);
 
601
 
 
602
    /* Shutdown and destroy all transports. */
 
603
    pjsip_tpmgr_destroy(endpt->transport_mgr);
 
604
 
 
605
    /* Destroy ioqueue */
 
606
    pj_ioqueue_destroy(endpt->ioqueue);
 
607
 
 
608
    /* Destroy timer heap */
 
609
#if PJ_TIMER_DEBUG
 
610
    pj_timer_heap_dump(endpt->timer_heap);
 
611
#endif
 
612
    pj_timer_heap_destroy(endpt->timer_heap);
 
613
 
 
614
    /* Call all registered exit callbacks */
 
615
    ecb = endpt->exit_cb_list.next;
 
616
    while (ecb != &endpt->exit_cb_list) {
 
617
        (*ecb->func)(endpt);
 
618
        ecb = ecb->next;
 
619
    }
 
620
 
 
621
    /* Delete endpoint mutex. */
 
622
    pj_mutex_destroy(endpt->mutex);
 
623
 
 
624
    /* Deinit parser */
 
625
    deinit_sip_parser();
 
626
 
 
627
    /* Delete module's mutex */
 
628
    pj_rwmutex_destroy(endpt->mod_mutex);
 
629
 
 
630
    /* Finally destroy pool. */
 
631
    pj_pool_release(endpt->pool);
 
632
 
 
633
    PJ_LOG(4, (THIS_FILE, "Endpoint %p destroyed", endpt));
 
634
}
 
635
 
 
636
/*
 
637
 * Get endpoint name.
 
638
 */
 
639
PJ_DEF(const pj_str_t*) pjsip_endpt_name(const pjsip_endpoint *endpt)
 
640
{
 
641
    return &endpt->name;
 
642
}
 
643
 
 
644
 
 
645
/*
 
646
 * Create new pool.
 
647
 */
 
648
PJ_DEF(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt,
 
649
                                               const char *pool_name,
 
650
                                               pj_size_t initial,
 
651
                                               pj_size_t increment )
 
652
{
 
653
    pj_pool_t *pool;
 
654
 
 
655
    /* Lock endpoint mutex. */
 
656
    /* No need to lock mutex. Factory is thread safe.
 
657
    pj_mutex_lock(endpt->mutex);
 
658
     */
 
659
 
 
660
    /* Create pool */
 
661
    pool = pj_pool_create( endpt->pf, pool_name,
 
662
                           initial, increment, &pool_callback);
 
663
 
 
664
    /* Unlock mutex. */
 
665
    /* No need to lock mutex. Factory is thread safe.
 
666
    pj_mutex_unlock(endpt->mutex);
 
667
     */
 
668
 
 
669
    if (!pool) {
 
670
        PJ_LOG(4, (THIS_FILE, "Unable to create pool %s!", pool_name));
 
671
    }
 
672
 
 
673
    return pool;
 
674
}
 
675
 
 
676
/*
 
677
 * Return back pool to endpoint's pool manager to be either destroyed or
 
678
 * recycled.
 
679
 */
 
680
PJ_DEF(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt, pj_pool_t *pool )
 
681
{
 
682
    PJ_LOG(6, (THIS_FILE, "Releasing pool %s", pj_pool_getobjname(pool)));
 
683
 
 
684
    /* Don't need to acquire mutex since pool factory is thread safe
 
685
       pj_mutex_lock(endpt->mutex);
 
686
     */
 
687
    pj_pool_release( pool );
 
688
 
 
689
    PJ_UNUSED_ARG(endpt);
 
690
    /*
 
691
    pj_mutex_unlock(endpt->mutex);
 
692
     */
 
693
}
 
694
 
 
695
 
 
696
PJ_DEF(pj_status_t) pjsip_endpt_handle_events2(pjsip_endpoint *endpt,
 
697
                                               const pj_time_val *max_timeout,
 
698
                                               unsigned *p_count)
 
699
{
 
700
    /* timeout is 'out' var. This just to make compiler happy. */
 
701
    pj_time_val timeout = { 0, 0};
 
702
    unsigned count = 0, net_event_count = 0;
 
703
    int c;
 
704
 
 
705
    PJ_LOG(6, (THIS_FILE, "pjsip_endpt_handle_events()"));
 
706
 
 
707
    /* Poll the timer. The timer heap has its own mutex for better 
 
708
     * granularity, so we don't need to lock end endpoint. 
 
709
     */
 
710
    timeout.sec = timeout.msec = 0;
 
711
    c = pj_timer_heap_poll( endpt->timer_heap, &timeout );
 
712
    if (c > 0)
 
713
        count += c;
 
714
 
 
715
    /* timer_heap_poll should never ever returns negative value, or otherwise
 
716
     * ioqueue_poll() will block forever!
 
717
     */
 
718
    pj_assert(timeout.sec >= 0 && timeout.msec >= 0);
 
719
    if (timeout.msec >= 1000) timeout.msec = 999;
 
720
 
 
721
    /* If caller specifies maximum time to wait, then compare the value with
 
722
     * the timeout to wait from timer, and use the minimum value.
 
723
     */
 
724
    if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) {
 
725
        timeout = *max_timeout;
 
726
    }
 
727
 
 
728
    /* Poll ioqueue. 
 
729
     * Repeat polling the ioqueue while we have immediate events, because
 
730
     * timer heap may process more than one events, so if we only process
 
731
     * one network events at a time (such as when IOCP backend is used),
 
732
     * the ioqueue may have trouble keeping up with the request rate.
 
733
     *
 
734
     * For example, for each send() request, one network event will be
 
735
     *   reported by ioqueue for the send() completion. If we don't poll
 
736
     *   the ioqueue often enough, the send() completion will not be
 
737
     *   reported in timely manner.
 
738
     */
 
739
    do {
 
740
        c = pj_ioqueue_poll( endpt->ioqueue, &timeout);
 
741
        if (c < 0) {
 
742
            pj_status_t err = pj_get_netos_error();
 
743
            pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout));
 
744
            if (p_count)
 
745
                *p_count = count;
 
746
            return err;
 
747
        } else if (c == 0) {
 
748
            break;
 
749
        } else {
 
750
            net_event_count += c;
 
751
            timeout.sec = timeout.msec = 0;
 
752
        }
 
753
    } while (c > 0 && net_event_count < PJSIP_MAX_NET_EVENTS);
 
754
 
 
755
    count += net_event_count;
 
756
    if (p_count)
 
757
        *p_count = count;
 
758
 
 
759
    return PJ_SUCCESS;
 
760
}
 
761
 
 
762
/*
 
763
 * Handle events.
 
764
 */
 
765
PJ_DEF(pj_status_t) pjsip_endpt_handle_events(pjsip_endpoint *endpt,
 
766
                                              const pj_time_val *max_timeout)
 
767
{
 
768
    return pjsip_endpt_handle_events2(endpt, max_timeout, NULL);
 
769
}
 
770
 
 
771
/*
 
772
 * Schedule timer.
 
773
 */
 
774
#if PJ_TIMER_DEBUG
 
775
PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer_dbg(pjsip_endpoint *endpt,
 
776
                                                    pj_timer_entry *entry,
 
777
                                                    const pj_time_val *delay,
 
778
                                                    const char *src_file,
 
779
                                                    int src_line)
 
780
{
 
781
    PJ_LOG(6, (THIS_FILE, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)",
 
782
                         entry, delay->sec, delay->msec));
 
783
    return pj_timer_heap_schedule_dbg(endpt->timer_heap, entry, delay,
 
784
                                      src_file, src_line);
 
785
}
 
786
#else
 
787
PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt,
 
788
                                                pj_timer_entry *entry,
 
789
                                                const pj_time_val *delay )
 
790
{
 
791
    PJ_LOG(6, (THIS_FILE, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)",
 
792
                         entry, delay->sec, delay->msec));
 
793
    return pj_timer_heap_schedule( endpt->timer_heap, entry, delay );
 
794
}
 
795
#endif
 
796
 
 
797
/*
 
798
 * Cancel the previously registered timer.
 
799
 */
 
800
PJ_DEF(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt, 
 
801
                                       pj_timer_entry *entry )
 
802
{
 
803
    PJ_LOG(6, (THIS_FILE, "pjsip_endpt_cancel_timer(entry=%p)", entry));
 
804
    pj_timer_heap_cancel( endpt->timer_heap, entry );
 
805
}
 
806
 
 
807
/*
 
808
 * Get the timer heap instance of the SIP endpoint.
 
809
 */
 
810
PJ_DEF(pj_timer_heap_t*) pjsip_endpt_get_timer_heap(pjsip_endpoint *endpt)
 
811
{
 
812
    return endpt->timer_heap;
 
813
}
 
814
 
 
815
/* Init with default */
 
816
PJ_DEF(void) pjsip_process_rdata_param_default(pjsip_process_rdata_param *p)
 
817
{
 
818
    pj_bzero(p, sizeof(*p));
 
819
}
 
820
 
 
821
/* Distribute rdata */
 
822
PJ_DEF(pj_status_t) pjsip_endpt_process_rx_data( pjsip_endpoint *endpt,
 
823
                                                 pjsip_rx_data *rdata,
 
824
                                                 pjsip_process_rdata_param *p,
 
825
                                                 pj_bool_t *p_handled)
 
826
{
 
827
    pjsip_msg *msg;
 
828
    pjsip_process_rdata_param def_prm;
 
829
    pjsip_module *mod;
 
830
    pj_bool_t handled = PJ_FALSE;
 
831
    unsigned i;
 
832
    pj_status_t status;
 
833
 
 
834
    PJ_ASSERT_RETURN(endpt && rdata, PJ_EINVAL);
 
835
 
 
836
    if (p==NULL) {
 
837
        p = &def_prm;
 
838
        pjsip_process_rdata_param_default(p);
 
839
    }
 
840
 
 
841
    msg = rdata->msg_info.msg;
 
842
 
 
843
    if (p_handled)
 
844
        *p_handled = PJ_FALSE;
 
845
 
 
846
    if (!p->silent) {
 
847
        PJ_LOG(5, (THIS_FILE, "Distributing rdata to modules: %s",
 
848
                   pjsip_rx_data_get_info(rdata)));
 
849
        pj_log_push_indent();
 
850
    }
 
851
 
 
852
    LOCK_MODULE_ACCESS(endpt);
 
853
 
 
854
    /* Find start module */
 
855
    if (p->start_mod) {
 
856
        mod = (pjsip_module*)
 
857
              pj_list_find_node(&endpt->module_list, p->start_mod);
 
858
        if (!mod) {
 
859
            status = PJ_ENOTFOUND;
 
860
            goto on_return;
 
861
        }
 
862
    } else {
 
863
        mod = endpt->module_list.next;
 
864
    }
 
865
 
 
866
    /* Start after the specified index */
 
867
    for (i=0; i < p->idx_after_start && mod != &endpt->module_list; ++i) {
 
868
        mod = mod->next;
 
869
    }
 
870
 
 
871
    /* Start with the specified priority */
 
872
    while (mod != &endpt->module_list && mod->priority < (int)p->start_prio) {
 
873
        mod = mod->next;
 
874
    }
 
875
 
 
876
    if (mod == &endpt->module_list) {
 
877
        status = PJ_ENOTFOUND;
 
878
        goto on_return;
 
879
    }
 
880
 
 
881
    /* Distribute */
 
882
    if (msg->type == PJSIP_REQUEST_MSG) {
 
883
        do {
 
884
            if (mod->on_rx_request)
 
885
                handled = (*mod->on_rx_request)(rdata);
 
886
            if (handled)
 
887
                break;
 
888
            mod = mod->next;
 
889
        } while (mod != &endpt->module_list);
 
890
    } else {
 
891
        do {
 
892
            if (mod->on_rx_response)
 
893
                handled = (*mod->on_rx_response)(rdata);
 
894
            if (handled)
 
895
                break;
 
896
            mod = mod->next;
 
897
        } while (mod != &endpt->module_list);
 
898
    }
 
899
 
 
900
    status = PJ_SUCCESS;
 
901
 
 
902
on_return:
 
903
    if (p_handled)
 
904
        *p_handled = handled;
 
905
 
 
906
    UNLOCK_MODULE_ACCESS(endpt);
 
907
    if (!p->silent) {
 
908
        pj_log_pop_indent();
 
909
    }
 
910
    return status;
 
911
}
 
912
 
 
913
/*
 
914
 * This is the callback that is called by the transport manager when it 
 
915
 * receives a message from the network.
 
916
 */
 
917
static void endpt_on_rx_msg( pjsip_endpoint *endpt,
 
918
                                      pj_status_t status,
 
919
                                      pjsip_rx_data *rdata )
 
920
{
 
921
    pjsip_process_rdata_param proc_prm;
 
922
    pj_bool_t handled = PJ_FALSE;
 
923
 
 
924
    if (status != PJ_SUCCESS) {
 
925
        char info[30];
 
926
        char errmsg[PJ_ERR_MSG_SIZE];
 
927
 
 
928
        info[0] = '\0';
 
929
 
 
930
        if (status == PJSIP_EMISSINGHDR) {
 
931
            pj_str_t p;
 
932
 
 
933
            p.ptr = info; p.slen = 0;
 
934
 
 
935
            if (rdata->msg_info.cid == NULL || rdata->msg_info.cid->id.slen)
 
936
                pj_strcpy2(&p, "Call-ID");
 
937
            if (rdata->msg_info.from == NULL)
 
938
                pj_strcpy2(&p, " From");
 
939
            if (rdata->msg_info.to == NULL)
 
940
                pj_strcpy2(&p, " To");
 
941
            if (rdata->msg_info.via == NULL)
 
942
                pj_strcpy2(&p, " Via");
 
943
            if (rdata->msg_info.cseq == NULL) 
 
944
                pj_strcpy2(&p, " CSeq");
 
945
 
 
946
            p.ptr[p.slen] = '\0';
 
947
        }
 
948
 
 
949
        pj_strerror(status, errmsg, sizeof(errmsg));
 
950
 
 
951
        PJ_LOG(1, (THIS_FILE, 
 
952
                  "Error processing packet from %s:%d: %s %s [code %d]:\n"
 
953
                  "%.*s\n"
 
954
                  "-- end of packet.",
 
955
                  rdata->pkt_info.src_name, 
 
956
                  rdata->pkt_info.src_port,
 
957
                  errmsg,
 
958
                  info,
 
959
                  status,
 
960
                  (int)rdata->msg_info.len,     
 
961
                  rdata->msg_info.msg_buf));
 
962
        return;
 
963
    }
 
964
 
 
965
    PJ_LOG(5, (THIS_FILE, "Processing incoming message: %s", 
 
966
               pjsip_rx_data_get_info(rdata)));
 
967
    pj_log_push_indent();
 
968
 
 
969
#if defined(PJSIP_CHECK_VIA_SENT_BY) && PJSIP_CHECK_VIA_SENT_BY != 0
 
970
    /* For response, check that the value in Via sent-by match the transport.
 
971
     * If not matched, silently drop the response.
 
972
     * Ref: RFC3261 Section 18.1.2 Receiving Response
 
973
     */
 
974
    if (msg->type == PJSIP_RESPONSE_MSG) {
 
975
        const pj_str_t *local_addr;
 
976
        int port = rdata->msg_info.via->sent_by.port;
 
977
        pj_bool_t mismatch = PJ_FALSE;
 
978
        if (port == 0) {
 
979
            pjsip_transport_type_e type;
 
980
            type = (pjsip_transport_type_e)rdata->tp_info.transport->key.type;
 
981
            port = pjsip_transport_get_default_port_for_type(type);
 
982
        }
 
983
        local_addr = &rdata->tp_info.transport->local_name.host;
 
984
 
 
985
        if (pj_strcmp(&rdata->msg_info.via->sent_by.host, local_addr) != 0) {
 
986
 
 
987
            /* The RFC says that we should drop response when sent-by
 
988
             * address mismatch. But it could happen (e.g. with SER) when
 
989
             * endpoint with private IP is sending request to public
 
990
             * server.
 
991
 
 
992
            mismatch = PJ_TRUE;
 
993
 
 
994
             */
 
995
 
 
996
        } else if (port != rdata->tp_info.transport->local_name.port) {
 
997
            /* Port or address mismatch, we should discard response */
 
998
            /* But we saw one implementation (we don't want to name it to 
 
999
             * protect the innocence) which put wrong sent-by port although
 
1000
             * the "rport" parameter is correct.
 
1001
             * So we discard the response only if the port doesn't match
 
1002
             * both the port in sent-by and rport. We try to be lenient here!
 
1003
             */
 
1004
            if (rdata->msg_info.via->rport_param != 
 
1005
                rdata->tp_info.transport->local_name.port)
 
1006
                mismatch = PJ_TRUE;
 
1007
            else {
 
1008
                PJ_LOG(4,(THIS_FILE, "Message %s from %s has mismatch port in "
 
1009
                                     "sent-by but the rport parameter is "
 
1010
                                     "correct",
 
1011
                                     pjsip_rx_data_get_info(rdata), 
 
1012
                                     rdata->pkt_info.src_name));
 
1013
            }
 
1014
        }
 
1015
 
 
1016
        if (mismatch) {
 
1017
            PJ_TODO(ENDPT_REPORT_WHEN_DROPPING_MESSAGE);
 
1018
            PJ_LOG(4,(THIS_FILE, "Dropping response %s from %s:%d because "
 
1019
                                 "sent-by is mismatch", 
 
1020
                                 pjsip_rx_data_get_info(rdata),
 
1021
                                 rdata->pkt_info.src_name, 
 
1022
                                 rdata->pkt_info.src_port));
 
1023
            pj_log_pop_indent();
 
1024
            return;
 
1025
        }
 
1026
    }
 
1027
#endif
 
1028
 
 
1029
    pjsip_process_rdata_param_default(&proc_prm);
 
1030
    proc_prm.silent = PJ_TRUE;
 
1031
 
 
1032
    pjsip_endpt_process_rx_data(endpt, rdata, &proc_prm, &handled);
 
1033
 
 
1034
    /* No module is able to handle the message */
 
1035
    if (!handled) {
 
1036
        PJ_LOG(4,(THIS_FILE, "%s from %s:%d was dropped/unhandled by"
 
1037
                             " any modules",
 
1038
                             pjsip_rx_data_get_info(rdata),
 
1039
                             rdata->pkt_info.src_name,
 
1040
                             rdata->pkt_info.src_port));
 
1041
    }
 
1042
 
 
1043
    /* Must clear mod_data before returning rdata to transport, since
 
1044
     * rdata may be reused.
 
1045
     */
 
1046
    pj_bzero(&rdata->endpt_info, sizeof(rdata->endpt_info));
 
1047
 
 
1048
    pj_log_pop_indent();
 
1049
}
 
1050
 
 
1051
/*
 
1052
 * This callback is called by transport manager before message is sent.
 
1053
 * Modules may inspect the message before it's actually sent.
 
1054
 */
 
1055
static pj_status_t endpt_on_tx_msg( pjsip_endpoint *endpt,
 
1056
                                    pjsip_tx_data *tdata )
 
1057
{
 
1058
    pj_status_t status = PJ_SUCCESS;
 
1059
    pjsip_module *mod;
 
1060
 
 
1061
    /* Distribute to modules, starting from modules with LOWEST priority */
 
1062
    LOCK_MODULE_ACCESS(endpt);
 
1063
 
 
1064
    mod = endpt->module_list.prev;
 
1065
    if (tdata->msg->type == PJSIP_REQUEST_MSG) {
 
1066
        while (mod != &endpt->module_list) {
 
1067
            if (mod->on_tx_request)
 
1068
                status = (*mod->on_tx_request)(tdata);
 
1069
            if (status != PJ_SUCCESS)
 
1070
                break;
 
1071
            mod = mod->prev;
 
1072
        }
 
1073
 
 
1074
    } else {
 
1075
        while (mod != &endpt->module_list) {
 
1076
            if (mod->on_tx_response)
 
1077
                status = (*mod->on_tx_response)(tdata);
 
1078
            if (status != PJ_SUCCESS)
 
1079
                break;
 
1080
            mod = mod->prev;
 
1081
        }
 
1082
    }
 
1083
 
 
1084
    UNLOCK_MODULE_ACCESS(endpt);
 
1085
 
 
1086
    return status;
 
1087
}
 
1088
 
 
1089
 
 
1090
/*
 
1091
 * Create transmit data buffer.
 
1092
 */
 
1093
PJ_DEF(pj_status_t) pjsip_endpt_create_tdata(  pjsip_endpoint *endpt,
 
1094
                                               pjsip_tx_data **p_tdata)
 
1095
{
 
1096
    return pjsip_tx_data_create(endpt->transport_mgr, p_tdata);
 
1097
}
 
1098
 
 
1099
/*
 
1100
 * Create the DNS resolver instance. 
 
1101
 */
 
1102
PJ_DEF(pj_status_t) pjsip_endpt_create_resolver(pjsip_endpoint *endpt,
 
1103
                                                pj_dns_resolver **p_resv)
 
1104
{
 
1105
#if PJSIP_HAS_RESOLVER
 
1106
    PJ_ASSERT_RETURN(endpt && p_resv, PJ_EINVAL);
 
1107
    return pj_dns_resolver_create( endpt->pf, NULL, 0, endpt->timer_heap,
 
1108
                                   endpt->ioqueue, p_resv);
 
1109
#else
 
1110
    PJ_UNUSED_ARG(endpt);
 
1111
    PJ_UNUSED_ARG(p_resv);
 
1112
    pj_assert(!"Resolver is disabled (PJSIP_HAS_RESOLVER==0)");
 
1113
    return PJ_EINVALIDOP;
 
1114
#endif
 
1115
}
 
1116
 
 
1117
/*
 
1118
 * Set DNS resolver to be used by the SIP resolver.
 
1119
 */
 
1120
PJ_DEF(pj_status_t) pjsip_endpt_set_resolver( pjsip_endpoint *endpt,
 
1121
                                              pj_dns_resolver *resv)
 
1122
{
 
1123
    return pjsip_resolver_set_resolver(endpt->resolver, resv);
 
1124
}
 
1125
 
 
1126
/*
 
1127
 * Get the DNS resolver being used by the SIP resolver.
 
1128
 */
 
1129
PJ_DEF(pj_dns_resolver*) pjsip_endpt_get_resolver(pjsip_endpoint *endpt)
 
1130
{
 
1131
    PJ_ASSERT_RETURN(endpt, NULL);
 
1132
    return pjsip_resolver_get_resolver(endpt->resolver);
 
1133
}
 
1134
 
 
1135
/*
 
1136
 * Resolve
 
1137
 */
 
1138
PJ_DEF(void) pjsip_endpt_resolve( pjsip_endpoint *endpt,
 
1139
                                  pj_pool_t *pool,
 
1140
                                  pjsip_host_info *target,
 
1141
                                  void *token,
 
1142
                                  pjsip_resolver_callback *cb)
 
1143
{
 
1144
    pjsip_resolve( endpt->resolver, pool, target, token, cb);
 
1145
}
 
1146
 
 
1147
/*
 
1148
 * Get transport manager.
 
1149
 */
 
1150
PJ_DEF(pjsip_tpmgr*) pjsip_endpt_get_tpmgr(pjsip_endpoint *endpt)
 
1151
{
 
1152
    return endpt->transport_mgr;
 
1153
}
 
1154
 
 
1155
/*
 
1156
 * Get ioqueue instance.
 
1157
 */
 
1158
PJ_DEF(pj_ioqueue_t*) pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt)
 
1159
{
 
1160
    return endpt->ioqueue;
 
1161
}
 
1162
 
 
1163
/*
 
1164
 * Find/create transport.
 
1165
 */
 
1166
PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport(pjsip_endpoint *endpt,
 
1167
                                                  pjsip_transport_type_e type,
 
1168
                                                  const pj_sockaddr_t *remote,
 
1169
                                                  int addr_len,
 
1170
                                                  const pjsip_tpselector *sel,
 
1171
                                                  pjsip_transport **transport)
 
1172
{
 
1173
    return pjsip_tpmgr_acquire_transport(endpt->transport_mgr, type, 
 
1174
                                         remote, addr_len, sel, transport);
 
1175
}
 
1176
 
 
1177
 
 
1178
/*
 
1179
 * Find/create transport.
 
1180
 */
 
1181
PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport2(pjsip_endpoint *endpt,
 
1182
                                                   pjsip_transport_type_e type,
 
1183
                                                   const pj_sockaddr_t *remote,
 
1184
                                                   int addr_len,
 
1185
                                                   const pjsip_tpselector *sel,
 
1186
                                                   pjsip_tx_data *tdata,
 
1187
                                                   pjsip_transport **transport)
 
1188
{
 
1189
    return pjsip_tpmgr_acquire_transport2(endpt->transport_mgr, type, remote, 
 
1190
                                          addr_len, sel, tdata, transport);
 
1191
}
 
1192
 
 
1193
 
 
1194
/*
 
1195
 * Report error.
 
1196
 */
 
1197
PJ_DEF(void) pjsip_endpt_log_error(  pjsip_endpoint *endpt,
 
1198
                                     const char *sender,
 
1199
                                     pj_status_t error_code,
 
1200
                                     const char *format,
 
1201
                                     ... )
 
1202
{
 
1203
#if PJ_LOG_MAX_LEVEL > 0
 
1204
    char newformat[256];
 
1205
    int len;
 
1206
    va_list marker;
 
1207
 
 
1208
    va_start(marker, format);
 
1209
 
 
1210
    PJ_UNUSED_ARG(endpt);
 
1211
 
 
1212
    len = pj_ansi_strlen(format);
 
1213
    if (len < (int)sizeof(newformat)-30) {
 
1214
        pj_str_t errstr;
 
1215
 
 
1216
        pj_ansi_strcpy(newformat, format);
 
1217
        pj_ansi_snprintf(newformat+len, sizeof(newformat)-len-1,
 
1218
                         ": [err %d] ", error_code);
 
1219
        len += pj_ansi_strlen(newformat+len);
 
1220
 
 
1221
        errstr = pj_strerror( error_code, newformat+len, 
 
1222
                              sizeof(newformat)-len-1);
 
1223
 
 
1224
        len += errstr.slen;
 
1225
        newformat[len] = '\0';
 
1226
 
 
1227
        pj_log(sender, 1, newformat, marker);
 
1228
    } else {
 
1229
        pj_log(sender, 1, format, marker);
 
1230
    }
 
1231
 
 
1232
    va_end(marker);
 
1233
#else
 
1234
    PJ_UNUSED_ARG(format);
 
1235
    PJ_UNUSED_ARG(error_code);
 
1236
    PJ_UNUSED_ARG(sender);
 
1237
    PJ_UNUSED_ARG(endpt);
 
1238
#endif
 
1239
}
 
1240
 
 
1241
 
 
1242
/*
 
1243
 * Dump endpoint.
 
1244
 */
 
1245
PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
 
1246
{
 
1247
#if PJ_LOG_MAX_LEVEL >= 3
 
1248
    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()"));
 
1249
 
 
1250
    /* Lock mutex. */
 
1251
    pj_mutex_lock(endpt->mutex);
 
1252
 
 
1253
    PJ_LOG(3, (THIS_FILE, "Dumping endpoint %p:", endpt));
 
1254
    
 
1255
    /* Dumping pool factory. */
 
1256
    pj_pool_factory_dump(endpt->pf, detail);
 
1257
 
 
1258
    /* Pool health. */
 
1259
    PJ_LOG(3, (THIS_FILE," Endpoint pool capacity=%u, used_size=%u",
 
1260
               pj_pool_get_capacity(endpt->pool),
 
1261
               pj_pool_get_used_size(endpt->pool)));
 
1262
 
 
1263
    /* Resolver */
 
1264
#if PJSIP_HAS_RESOLVER
 
1265
    if (pjsip_endpt_get_resolver(endpt)) {
 
1266
        pj_dns_resolver_dump(pjsip_endpt_get_resolver(endpt), detail);
 
1267
    }
 
1268
#endif
 
1269
 
 
1270
    /* Transports. 
 
1271
     */
 
1272
    pjsip_tpmgr_dump_transports( endpt->transport_mgr );
 
1273
 
 
1274
    /* Timer. */
 
1275
#if PJ_TIMER_DEBUG
 
1276
    pj_timer_heap_dump(endpt->timer_heap);
 
1277
#else
 
1278
    PJ_LOG(3,(THIS_FILE, " Timer heap has %u entries", 
 
1279
                        pj_timer_heap_count(endpt->timer_heap)));
 
1280
#endif
 
1281
 
 
1282
    /* Unlock mutex. */
 
1283
    pj_mutex_unlock(endpt->mutex);
 
1284
#else
 
1285
    PJ_UNUSED_ARG(endpt);
 
1286
    PJ_UNUSED_ARG(detail);
 
1287
    PJ_LOG(3,(THIS_FILE, "pjsip_end_dump: can't dump because it's disabled."));
 
1288
#endif
 
1289
}
 
1290
 
 
1291
 
 
1292
PJ_DEF(pj_status_t) pjsip_endpt_atexit( pjsip_endpoint *endpt,
 
1293
                                        pjsip_endpt_exit_callback func)
 
1294
{
 
1295
    exit_cb *new_cb;
 
1296
 
 
1297
    PJ_ASSERT_RETURN(endpt && func, PJ_EINVAL);
 
1298
 
 
1299
    new_cb = PJ_POOL_ZALLOC_T(endpt->pool, exit_cb);
 
1300
    new_cb->func = func;
 
1301
 
 
1302
    pj_mutex_lock(endpt->mutex);
 
1303
    pj_list_push_back(&endpt->exit_cb_list, new_cb);
 
1304
    pj_mutex_unlock(endpt->mutex);
 
1305
 
 
1306
    return PJ_SUCCESS;
 
1307
}