Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjlib / src / pj / pool_buf.c
1 /* $Id$ */
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 <pj/pool_buf.h>
21 #include <pj/assert.h>
22 #include <pj/os.h>
23
24 struct pj_pool_factory stack_based_factory;
25
26 struct creation_param
27 {
28     void        *stack_buf;
29     pj_size_t    size;
30 };
31
32 static int is_initialized;
33 static long tls = -1;
34 static void* stack_alloc(pj_pool_factory *factory, pj_size_t size);
35
36 static void pool_buf_cleanup(void)
37 {
38     if (tls != -1) {
39         pj_thread_local_free(tls);
40         tls = -1;
41     }
42     if (is_initialized)
43         is_initialized = 0;
44 }
45
46 static pj_status_t pool_buf_initialize()
47 {
48     pj_atexit(&pool_buf_cleanup);
49
50     stack_based_factory.policy.block_alloc = &stack_alloc;
51     return pj_thread_local_alloc(&tls);
52 }
53
54 static void* stack_alloc(pj_pool_factory *factory, pj_size_t size)
55 {
56     struct creation_param *param;
57     void *buf;
58
59     PJ_UNUSED_ARG(factory);
60
61     param = (struct creation_param*) pj_thread_local_get(tls);
62     if (param == NULL) {
63         /* Don't assert(), this is normal no-memory situation */
64         return NULL;
65     }
66
67     pj_thread_local_set(tls, NULL);
68
69     PJ_ASSERT_RETURN(size <= param->size, NULL);
70
71     buf = param->stack_buf;
72
73     /* Prevent the buffer from being reused */
74     param->stack_buf = NULL;
75
76     return buf;
77 }
78
79
80 PJ_DEF(pj_pool_t*) pj_pool_create_on_buf(const char *name,
81                                          void *buf,
82                                          pj_size_t size)
83 {
84 #if PJ_HAS_POOL_ALT_API == 0
85     struct creation_param param;
86     long align_diff;
87
88     PJ_ASSERT_RETURN(buf && size, NULL);
89
90     if (!is_initialized) {
91         if (pool_buf_initialize() != PJ_SUCCESS)
92             return NULL;
93         is_initialized = 1;
94     }
95
96     /* Check and align buffer */
97     align_diff = (long)buf;
98     if (align_diff & (PJ_POOL_ALIGNMENT-1)) {
99         align_diff &= (PJ_POOL_ALIGNMENT-1);
100         buf = (void*) (((char*)buf) + align_diff);
101         size -= align_diff;
102     }
103
104     param.stack_buf = buf;
105     param.size = size;
106     pj_thread_local_set(tls, &param);
107
108     return pj_pool_create_int(&stack_based_factory, name, size, 0, 
109                               pj_pool_factory_default_policy.callback);
110 #else
111     PJ_UNUSED_ARG(buf);
112     return pj_pool_create(NULL, name, size, size, NULL);
113 #endif
114 }
115