summaryrefslogtreecommitdiff
path: root/pjsip/include/pjsip/sip_endpoint.h
blob: 63c65d7543ad5009df8f04b27df282aa180d4f53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
/* $Id: sip_endpoint.h 4275 2012-10-04 06:11:58Z bennylp $ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJSIP_SIP_ENDPOINT_H__
#define __PJSIP_SIP_ENDPOINT_H__

/**
 * @file sip_endpoint.h
 * @brief SIP Endpoint.
 */

#include <pjsip/sip_transport.h>
#include <pjsip/sip_resolve.h>

/**
 * @defgroup PJSIP_CORE_CORE At the Very Core
 * @ingroup PJSIP_CORE
 * @brief The very core of PJSIP.
 */

PJ_BEGIN_DECL

/**
 * @defgroup PJSIP_ENDPT Endpoint
 * @ingroup PJSIP_CORE_CORE
 * @brief The master, owner of all objects
 *
 * SIP Endpoint instance (pjsip_endpoint) can be viewed as the master/owner of
 * all SIP objects in an application. It performs the following roles:
 *  - it manages the allocation/deallocation of memory pools for all objects.
 *  - it manages listeners and transports, and how they are used by 
 *    transactions.
 *  - it receives incoming messages from transport layer and automatically
 *    dispatches them to the correct transaction (or create a new one).
 *  - it has a single instance of timer management (timer heap).
 *  - it manages modules, which is the primary means of extending the library.
 *  - it provides single polling function for all objects and distributes 
 *    events.
 *  - it automatically handles incoming requests which can not be handled by
 *    existing modules (such as when incoming request has unsupported method).
 *  - and so on..
 *
 * Application should only instantiate one SIP endpoint instance for every
 * process.
 *
 * @{
 */


/**
 * Type of callback to register to pjsip_endpt_atexit().
 */
typedef void (*pjsip_endpt_exit_callback)(pjsip_endpoint *endpt);


/**
 * Create an instance of SIP endpoint from the specified pool factory.
 * The pool factory reference then will be kept by the endpoint, so that 
 * future memory allocations by SIP components will be taken from the same
 * pool factory.
 *
 * @param pf	        Pool factory that will be used for the lifetime of 
 *                      endpoint.
 * @param name          Optional name to be specified for the endpoint.
 *                      If this parameter is NULL, then the name will use
 *                      local host name.
 * @param endpt         Pointer to receive endpoint instance.
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
					const char *name,
                                        pjsip_endpoint **endpt);

/**
 * Destroy endpoint instance. Application must make sure that all pending
 * transactions have been terminated properly, because this function does not
 * check for the presence of pending transactions.
 *
 * @param endpt		The SIP endpoint to be destroyed.
 */
PJ_DECL(void) pjsip_endpt_destroy(pjsip_endpoint *endpt);

/**
 * Get endpoint name.
 *
 * @param endpt         The SIP endpoint instance.
 *
 * @return              Endpoint name, as was registered during endpoint
 *                      creation. The string is NULL terminated.
 */
PJ_DECL(const pj_str_t*) pjsip_endpt_name(const pjsip_endpoint *endpt);

/**
 * Poll for events. Application must call this function periodically to ensure
 * that all events from both transports and timer heap are handled in timely
 * manner.  This function, like all other endpoint functions, is thread safe, 
 * and application may have more than one thread concurrently calling this function.
 *
 * @param endpt		The endpoint.
 * @param max_timeout	Maximum time to wait for events, or NULL to wait forever
 *			until event is received.
 *
 * @return		PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_handle_events( pjsip_endpoint *endpt, 
					        const pj_time_val *max_timeout);


/**
 * Handle events with additional info about number of events that
 * have been handled.
 *
 * @param endpt		The endpoint.
 * @param max_timeout	Maximum time to wait for events, or NULL to wait forever
 *			until event is received.
 * @param count		Optional argument to receive the number of events that
 *			have been handled by the function.
 *
 * @return		PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_handle_events2(pjsip_endpoint *endpt,
					        const pj_time_val *max_timeout,
					        unsigned *count);
/**
 * Schedule timer to endpoint's timer heap. Application must poll the endpoint
 * periodically (by calling #pjsip_endpt_handle_events) to ensure that the
 * timer events are handled in timely manner. When the timeout for the timer
 * has elapsed, the callback specified in the entry argument will be called.
 * This function, like all other endpoint functions, is thread safe.
 *
 * @param endpt	    The endpoint.
 * @param entry	    The timer entry.
 * @param delay	    The relative delay of the timer.
 * @return	    PJ_OK (zero) if successfull.
 */
#if PJ_TIMER_DEBUG
#define pjsip_endpt_schedule_timer(ept,ent,d) \
			pjsip_endpt_schedule_timer_dbg(ept, ent, d, \
			                               __FILE__, __LINE__)

PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer_dbg(pjsip_endpoint *endpt,
						    pj_timer_entry *entry,
						    const pj_time_val *delay,
						    const char *src_file,
						    int src_line);
#else
PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt,
						 pj_timer_entry *entry,
						 const pj_time_val *delay );
#endif

/**
 * Cancel the previously registered timer.
 * This function, like all other endpoint functions, is thread safe.
 *
 * @param endpt	    The endpoint.
 * @param entry	    The timer entry previously registered.
 */
PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt, 
					pj_timer_entry *entry );

/**
 * Get the timer heap instance of the SIP endpoint.
 *
 * @param endpt	    The endpoint.
 *
 * @return	    The timer heap instance.
 */
PJ_DECL(pj_timer_heap_t*) pjsip_endpt_get_timer_heap(pjsip_endpoint *endpt);


/**
 * Register new module to the endpoint.
 * The endpoint will then call the load and start function in the module to 
 * properly initialize the module, and assign a unique module ID for the 
 * module.
 *
 * @param endpt		The endpoint.
 * @param module	The module to be registered.
 *
 * @return		PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt,
						  pjsip_module *module );

/**
 * Unregister a module from the endpoint.
 * The endpoint will then call the stop and unload function in the module to 
 * properly shutdown the module.
 *
 * @param endpt		The endpoint.
 * @param module	The module to be registered.
 *
 * @return		PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt,
						    pjsip_module *module );

/**
 * This describes additional parameters to pjsip_endpt_process_rx_data()
 * function. Application MUST call pjsip_process_rdata_param_default() to
 * initialize this structure.
 */
typedef struct pjsip_process_rdata_param
{
    /**
     * Specify the minimum priority number of the modules that are allowed
     * to process the message. Default is zero to allow all modules to
     * process the message.
     */
    unsigned start_prio;

    /**
     * Specify the pointer of the module where processing will start.
     * The default is NULL, meaning processing will start from the start
     * of the module list.
     */
    void *start_mod;

    /**
     * Set to N, then processing will start at Nth module after start
     * module (where start module can be an explicit module as specified
     * by \a start_mod or the start of module list when \a start_mod is
     * NULL). For example, if set to 1, then processing will start from
     * the next module after start module. Default is zero.
     */
    unsigned idx_after_start;

    /**
     * Print nothing to log. Default is PJ_FALSE.
     */
    pj_bool_t silent;

} pjsip_process_rdata_param;

/**
 * Initialize with default.
 *
 * @param p	The param.
 */
PJ_DECL(void) pjsip_process_rdata_param_default(pjsip_process_rdata_param *p);

/**
 * Manually distribute the specified pjsip_rx_data to registered modules.
 * Normally application does not need to call this function because received
 * messages will be given to endpoint automatically by transports.
 *
 * Application can use this function when it has postponed the processing of
 * an incoming message, for example to perform long operations such as
 * database operation or to consult other servers to decide what to do with
 * the message. In this case, application clones the original rdata, return
 * from the callback, and perform the long operation. Upon completing the
 * long operation, it resumes pjsip's module processing by calling this
 * function, and then free the cloned rdata.
 *
 * @param endpt		The endpoint instance.
 * @param rdata		The rdata to be distributed.
 * @param p		Optional pointer to param to specify from which module
 * 			the processing should start.
 * @param p_handled	Optional pointer to receive last return value of
 * 			module's \a on_rx_request() or \a on_rx_response()
 * 			callback.
 *
 * @return		PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_process_rx_data(pjsip_endpoint *endpt,
                                                 pjsip_rx_data *rdata,
                                                 pjsip_process_rdata_param *p,
                                                 pj_bool_t *p_handled);

/**
 * Create pool from the endpoint. All SIP components should allocate their
 * memory pool by calling this function, to make sure that the pools are
 * allocated from the same pool factory. This function, like all other endpoint
 * functions, is thread safe.
 *
 * @param endpt		The SIP endpoint.
 * @param pool_name	Name to be assigned to the pool.
 * @param initial	The initial size of the pool.
 * @param increment	The resize size.
 * @return		Memory pool, or NULL on failure.
 *
 * @see pj_pool_create
 */
PJ_DECL(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt,
					     const char *pool_name,
					     pj_size_t initial,
					     pj_size_t increment );

/**
 * Return back pool to endpoint to be released back to the pool factory.
 * This function, like all other endpoint functions, is thread safe.
 *
 * @param endpt	    The endpoint.
 * @param pool	    The pool to be destroyed.
 */
PJ_DECL(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt,
					pj_pool_t *pool );

/**
 * Find transaction in endpoint's transaction table by the transaction's key.
 * This function normally is only used by modules. The key for a transaction
 * can be created by calling #pjsip_tsx_create_key.
 *
 * @param endpt	    The endpoint instance.
 * @param key	    Transaction key, as created with #pjsip_tsx_create_key.
 *
 * @return	    The transaction, or NULL if it's not found.
 */
PJ_DECL(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt,
					          const pj_str_t *key );

/**
 * Register the transaction to the endpoint's transaction table.
 * This function should only be used internally by the stack.
 *
 * @param endpt	    The SIP endpoint.
 * @param tsx	    The transaction.
 */
PJ_DECL(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt,
					pjsip_transaction *tsx);

/**
 * Forcefull destroy the transaction. This function should only be used
 * internally by the stack.
 *
 * @param endpt	    The endpoint.
 * @param tsx	    The transaction to destroy.
 */
PJ_DECL(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt,
				      pjsip_transaction *tsx);

/**
 * Create a new transmit data buffer.
 * This function, like all other endpoint functions, is thread safe.
 *
 * @param endpt	    The endpoint.
 * @param p_tdata    Pointer to receive transmit data buffer.
 *
 * @return	    PJ_SUCCESS or the appropriate error code.
 */
PJ_DECL(pj_status_t) pjsip_endpt_create_tdata( pjsip_endpoint *endpt,
					       pjsip_tx_data **p_tdata);

/**
 * Create the DNS resolver instance. Application creates the DNS
 * resolver instance, set the nameserver to be used by the DNS
 * resolver, then set the DNS resolver to be used by the endpoint
 * by calling #pjsip_endpt_set_resolver().
 *
 * @param endpt		The SIP endpoint instance.
 * @param p_resv	Pointer to receive the DNS resolver instance.
 *
 * @return		PJ_SUCCESS on success, or the appropriate error
 *			code.
 */
PJ_DECL(pj_status_t) pjsip_endpt_create_resolver(pjsip_endpoint *endpt,
						 pj_dns_resolver **p_resv);

/**
 * Set DNS resolver to be used by the SIP resolver. Application can set
 * the resolver instance to NULL to disable DNS resolution (perhaps
 * temporarily). When DNS resolver is disabled, the endpoint will resolve
 * hostnames with the normal pj_gethostbyname() function.
 *
 * @param endpt		The SIP endpoint instance.
 * @param resv		The resolver instance to be used by the SIP
 *			endpoint.
 *
 * @return		PJ_SUCCESS on success, or the appropriate error
 *			code.
 */
PJ_DECL(pj_status_t) pjsip_endpt_set_resolver(pjsip_endpoint *endpt,
					      pj_dns_resolver *resv);

/**
 * Get the DNS resolver being used by the SIP resolver.
 *
 * @param endpt		The SIP endpoint instance.
 *
 * @return		The DNS resolver instance currently being used
 *			by the SIP endpoint.
 */
PJ_DECL(pj_dns_resolver*) pjsip_endpt_get_resolver(pjsip_endpoint *endpt);

/**
 * Asynchronously resolve a SIP target host or domain according to rule 
 * specified in RFC 3263 (Locating SIP Servers). When the resolving operation
 * has completed, the callback will be called.
 *
 * @param endpt	    The endpoint instance.
 * @param pool	    The pool to allocate resolver job.
 * @param target    The target specification to be resolved.
 * @param token	    A user defined token to be passed back to callback function.
 * @param cb	    The callback function.
 */
PJ_DECL(void) pjsip_endpt_resolve( pjsip_endpoint *endpt,
				   pj_pool_t *pool,
				   pjsip_host_info *target,
				   void *token,
				   pjsip_resolver_callback *cb);

/**
 * Get transport manager instance.
 *
 * @param endpt	    The endpoint.
 *
 * @return	    Transport manager instance.
 */
PJ_DECL(pjsip_tpmgr*) pjsip_endpt_get_tpmgr(pjsip_endpoint *endpt);

/**
 * Get ioqueue instance.
 *
 * @param endpt	    The endpoint.
 *
 * @return	    The ioqueue.
 */
PJ_DECL(pj_ioqueue_t*) pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt);

/**
 * Find a SIP transport suitable for sending SIP message to the specified
 * address. If transport selector ("sel") is set, then the function will
 * check if the transport selected is suitable to send requests to the
 * specified address.
 *
 * @see pjsip_tpmgr_acquire_transport
 *
 * @param endpt	    The SIP endpoint instance.
 * @param type	    The type of transport to be acquired.
 * @param remote    The remote address to send message to.
 * @param addr_len  Length of the remote address.
 * @param sel	    Optional pointer to transport selector instance which is
 *		    used to find explicit transport, if required.
 * @param p_tp	    Pointer to receive the transport instance, if one is found.
 *
 * @return	    PJ_SUCCESS on success, or the appropriate error code.
 */
PJ_DECL(pj_status_t) 
pjsip_endpt_acquire_transport( pjsip_endpoint *endpt,
			       pjsip_transport_type_e type,
			       const pj_sockaddr_t *remote,
			       int addr_len,
			       const pjsip_tpselector *sel,
			       pjsip_transport **p_tp);


/**
 * Find a SIP transport suitable for sending SIP message to the specified
 * address by also considering the outgoing SIP message data. If transport 
 * selector ("sel") is set, then the function will check if the transport 
 * selected is suitable to send requests to the specified address.
 *
 * @see pjsip_tpmgr_acquire_transport
 *
 * @param endpt	    The SIP endpoint instance.
 * @param type	    The type of transport to be acquired.
 * @param remote    The remote address to send message to.
 * @param addr_len  Length of the remote address.
 * @param sel	    Optional pointer to transport selector instance which is
 *		    used to find explicit transport, if required.
 * @param tdata	    Optional pointer to SIP message data to be sent.
 * @param p_tp	    Pointer to receive the transport instance, if one is found.
 *
 * @return	    PJ_SUCCESS on success, or the appropriate error code.
 */
PJ_DECL(pj_status_t) 
pjsip_endpt_acquire_transport2(pjsip_endpoint *endpt,
			       pjsip_transport_type_e type,
			       const pj_sockaddr_t *remote,
			       int addr_len,
			       const pjsip_tpselector *sel,
			       pjsip_tx_data *tdata,
			       pjsip_transport **p_tp);


/*****************************************************************************
 *
 * Capabilities Management
 *
 * Modules may implement new capabilities to the stack. These capabilities
 * are indicated by the appropriate SIP header fields, such as Accept,
 * Accept-Encoding, Accept-Language, Allow, Supported, etc.
 *
 * When a module provides new capabilities to the stack, it registers these
 * capabilities to the endpoint by supplying new tags (strings) to the
 * appropriate header fields. Application (or other modules) can then query
 * these header fields to get the list of supported capabilities, and may
 * include these headers in the outgoing message.
 *****************************************************************************
 */

/**
 * Get the value of the specified capability header field.
 *
 * @param endpt	    The endpoint.
 * @param htype	    The header type to be retrieved, which value may be:
 *		    - PJSIP_H_ACCEPT
 *		    - PJSIP_H_ALLOW
 *		    - PJSIP_H_SUPPORTED
 * @param hname	    If htype specifies PJSIP_H_OTHER, then the header name
 *		    must be supplied in this argument. Otherwise the value
 *		    must be set to NULL.
 *
 * @return	    The appropriate header, or NULL if the header is not
 *		    available.
 */
PJ_DECL(const pjsip_hdr*) pjsip_endpt_get_capability( pjsip_endpoint *endpt,
						      int htype,
						      const pj_str_t *hname);


/**
 * Check if we have the specified capability.
 *
 * @param endpt	    The endpoint.
 * @param htype	    The header type to be retrieved, which value may be:
 *		    - PJSIP_H_ACCEPT
 *		    - PJSIP_H_ALLOW
 *		    - PJSIP_H_SUPPORTED
 * @param hname	    If htype specifies PJSIP_H_OTHER, then the header name
 *		    must be supplied in this argument. Otherwise the value
 *		    must be set to NULL.
 * @param token	    The capability token to check. For example, if \a htype
 *		    is PJSIP_H_ALLOW, then \a token specifies the method
 *		    names; if \a htype is PJSIP_H_SUPPORTED, then \a token
 *		    specifies the extension names such as "100rel".
 *
 * @return	    PJ_TRUE if the specified capability is supported,
 *		    otherwise PJ_FALSE..
 */
PJ_DECL(pj_bool_t) pjsip_endpt_has_capability( pjsip_endpoint *endpt,
					       int htype,
					       const pj_str_t *hname,
					       const pj_str_t *token);


/**
 * Add or register new capabilities as indicated by the tags to the
 * appropriate header fields in the endpoint.
 *
 * @param endpt	    The endpoint.
 * @param mod	    The module which registers the capability.
 * @param htype	    The header type to be set, which value may be:
 *		    - PJSIP_H_ACCEPT
 *		    - PJSIP_H_ALLOW
 *		    - PJSIP_H_SUPPORTED
 * @param hname	    If htype specifies PJSIP_H_OTHER, then the header name
 *		    must be supplied in this argument. Otherwise the value
 *		    must be set to NULL.
 * @param count	    The number of tags in the array.
 * @param tags	    Array of tags describing the capabilities or extensions
 *		    to be added to the appropriate header.
 *
 * @return	    PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_add_capability( pjsip_endpoint *endpt,
						 pjsip_module *mod,
						 int htype,
						 const pj_str_t *hname,
						 unsigned count,
						 const pj_str_t tags[]);

/**
 * Get list of additional headers to be put in outgoing request message.
 * Currently only Max-Forwards are defined.
 *
 * @param e	    The endpoint.
 *
 * @return	    List of headers.
 */
PJ_DECL(const pjsip_hdr*) pjsip_endpt_get_request_headers(pjsip_endpoint *e);


/**
 * Dump endpoint status to the log. This will print the status to the log
 * with log level 3.
 *
 * @param endpt		The endpoint.
 * @param detail	If non zero, then it will dump a detailed output.
 *			BEWARE that this option may crash the system because
 *			it tries to access all memory pools.
 */
PJ_DECL(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail );


/**
 * Register cleanup function to be called by SIP endpoint when 
 * #pjsip_endpt_destroy() is called.  Note that application should not
 * use or access any endpoint resource (such as pool, ioqueue, timer heap)
 * from within the callback as such resource may have been released when
 * the callback function is invoked.
 *
 * @param endpt		The SIP endpoint.
 * @param func		The function to be registered.
 *
 * @return		PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjsip_endpt_atexit(pjsip_endpoint *endpt,
					pjsip_endpt_exit_callback func);


/**
 * @}
 */


/**
 * Log an error.
 */
PJ_DECL(void) pjsip_endpt_log_error( pjsip_endpoint *endpt,
				     const char *sender,
                                     pj_status_t error_code,
                                     const char *format,
                                     ... );

#define PJSIP_ENDPT_LOG_ERROR(expr)   \
            pjsip_endpt_log_error expr

#define PJSIP_ENDPT_TRACE(tracing,expr) \
            do {                        \
                if ((tracing))          \
                    PJ_LOG(4,expr);     \
            } while (0)

/*
 * Internal functions.
 */
/*
 * Receive transaction events from transactions and put in the event queue
 * to be processed later.
 */
void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt );

PJ_END_DECL

#endif	/* __PJSIP_SIP_ENDPOINT_H__ */