blob: e526c84dc0c66faf594ae1a4567b372ebd057b1c [file] [log] [blame]
Benny Prijono14c2b862007-02-21 00:40:05 +00001/* $Id$ */
2/*
Benny Prijonof1428f32007-06-19 09:04:58 +00003 * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono14c2b862007-02-21 00:40:05 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
Benny Prijono14c2b862007-02-21 00:40:05 +000019
Benny Prijono7cd16222007-03-05 00:58:24 +000020#include "server.h"
Benny Prijono14c2b862007-02-21 00:40:05 +000021
Benny Prijono7cd16222007-03-05 00:58:24 +000022#define THIS_FILE "server.c"
Benny Prijono14c2b862007-02-21 00:40:05 +000023
Benny Prijono7cd16222007-03-05 00:58:24 +000024struct pj_stun_server
Benny Prijonoc5ee0912007-03-01 00:08:27 +000025{
Benny Prijono7cd16222007-03-05 00:58:24 +000026 pj_stun_server_info si;
Benny Prijonoc5ee0912007-03-01 00:08:27 +000027
Benny Prijonoc5ee0912007-03-01 00:08:27 +000028 pj_pool_t *pool;
Benny Prijonoc5ee0912007-03-01 00:08:27 +000029
30 pj_bool_t thread_quit_flag;
Benny Prijono7cd16222007-03-05 00:58:24 +000031 pj_thread_t **threads;
Benny Prijonoe6315582007-03-08 18:58:04 +000032
33 unsigned usage_cnt;
34 pj_stun_usage *usage[32];
Benny Prijono7cd16222007-03-05 00:58:24 +000035};
Benny Prijonoc5ee0912007-03-01 00:08:27 +000036
Benny Prijono7cd16222007-03-05 00:58:24 +000037PJ_DEF(pj_status_t) pj_stun_perror( const char *sender,
38 const char *title,
39 pj_status_t status)
Benny Prijono14c2b862007-02-21 00:40:05 +000040{
41 char errmsg[PJ_ERR_MSG_SIZE];
42 pj_strerror(status, errmsg, sizeof(errmsg));
43
44 PJ_LOG(3,(sender, "%s: %s", title, errmsg));
Benny Prijono14c2b862007-02-21 00:40:05 +000045 return status;
46}
47
Benny Prijono14c2b862007-02-21 00:40:05 +000048static int worker_thread(void *p)
49{
Benny Prijono7cd16222007-03-05 00:58:24 +000050 pj_stun_server *srv = (pj_stun_server*)p;
Benny Prijono14c2b862007-02-21 00:40:05 +000051
Benny Prijono7cd16222007-03-05 00:58:24 +000052 while (!srv->thread_quit_flag) {
Benny Prijono14c2b862007-02-21 00:40:05 +000053 pj_time_val timeout = { 0, 50 };
Benny Prijono7cd16222007-03-05 00:58:24 +000054 pj_timer_heap_poll(srv->si.timer_heap, NULL);
55 pj_ioqueue_poll(srv->si.ioqueue, &timeout);
Benny Prijono14c2b862007-02-21 00:40:05 +000056 }
57
58 return 0;
59}
60
61
Benny Prijono7cd16222007-03-05 00:58:24 +000062PJ_DEF(pj_status_t) pj_stun_server_create(pj_pool_factory *pf,
63 unsigned thread_cnt,
64 pj_stun_server **p_srv)
Benny Prijono14c2b862007-02-21 00:40:05 +000065{
Benny Prijono7cd16222007-03-05 00:58:24 +000066 pj_pool_t *pool;
67 pj_stun_server *srv;
68 unsigned i;
Benny Prijono14c2b862007-02-21 00:40:05 +000069 pj_status_t status;
70
Benny Prijono7cd16222007-03-05 00:58:24 +000071 pool = pj_pool_create(pf, "server%p", 4000, 4000, NULL);
72
73 srv = PJ_POOL_ZALLOC_T(pool, pj_stun_server);
74 srv->pool = pool;
75 srv->si.pf = pf;
76
77 status = pj_ioqueue_create(srv->pool, PJ_IOQUEUE_MAX_HANDLES,
78 &srv->si.ioqueue);
Benny Prijono14c2b862007-02-21 00:40:05 +000079 if (status != PJ_SUCCESS)
Benny Prijono7cd16222007-03-05 00:58:24 +000080 goto on_error;
Benny Prijono14c2b862007-02-21 00:40:05 +000081
Benny Prijono7cd16222007-03-05 00:58:24 +000082 status = pj_timer_heap_create(srv->pool, 1024, &srv->si.timer_heap);
Benny Prijono14c2b862007-02-21 00:40:05 +000083 if (status != PJ_SUCCESS)
Benny Prijono7cd16222007-03-05 00:58:24 +000084 goto on_error;
Benny Prijono14c2b862007-02-21 00:40:05 +000085
Benny Prijono48a49272007-03-21 09:31:01 +000086 pj_stun_config_init(&srv->si.stun_cfg, srv->si.pf, 0, srv->si.ioqueue,
87 srv->si.timer_heap);
Benny Prijono14c2b862007-02-21 00:40:05 +000088
Benny Prijono7cd16222007-03-05 00:58:24 +000089 srv->si.thread_cnt = thread_cnt;
Benny Prijonoa1e69682007-05-11 15:14:34 +000090 srv->threads = (pj_thread_t**)
91 pj_pool_calloc(pool, thread_cnt, sizeof(pj_thread_t*));
Benny Prijono7cd16222007-03-05 00:58:24 +000092 for (i=0; i<thread_cnt; ++i) {
93 status = pj_thread_create(pool, "worker%p", &worker_thread,
94 srv, 0, 0, &srv->threads[i]);
95 if (status != PJ_SUCCESS)
96 goto on_error;
97 }
Benny Prijonoc5ee0912007-03-01 00:08:27 +000098
Benny Prijono7cd16222007-03-05 00:58:24 +000099 *p_srv = srv;
Benny Prijono14c2b862007-02-21 00:40:05 +0000100 return PJ_SUCCESS;
Benny Prijono7cd16222007-03-05 00:58:24 +0000101
102on_error:
103 pj_stun_server_destroy(srv);
104 return status;
Benny Prijono14c2b862007-02-21 00:40:05 +0000105}
106
107
Benny Prijono7cd16222007-03-05 00:58:24 +0000108PJ_DEF(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv)
Benny Prijono14c2b862007-02-21 00:40:05 +0000109{
Benny Prijono7cd16222007-03-05 00:58:24 +0000110 return &srv->si;
Benny Prijono14c2b862007-02-21 00:40:05 +0000111}
112
113
Benny Prijonoe6315582007-03-08 18:58:04 +0000114pj_status_t pj_stun_server_register_usage(pj_stun_server *srv,
115 pj_stun_usage *usage)
116{
117 unsigned i;
118
119 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
120 if (srv->usage[i] == usage)
121 return PJ_SUCCESS;
122 }
123
124 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
125 if (srv->usage[i] == NULL)
126 break;
127 }
128
129 if (i == PJ_ARRAY_SIZE(srv->usage))
130 return PJ_ETOOMANY;
131
132 srv->usage[i] = usage;
133 ++srv->usage_cnt;
134
135 return PJ_SUCCESS;
136}
137
138pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv,
139 pj_stun_usage *usage)
140{
141 unsigned i;
142
143 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
144 if (srv->usage[i] == usage)
145 break;
146 }
147
148 if (i != PJ_ARRAY_SIZE(srv->usage)) {
149 srv->usage[i] = NULL;
150 --srv->usage_cnt;
151 return PJ_SUCCESS;
152 }
153
154 return PJ_ENOTFOUND;
155}
156
157
Benny Prijono7cd16222007-03-05 00:58:24 +0000158PJ_DEF(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv)
Benny Prijono14c2b862007-02-21 00:40:05 +0000159{
160 unsigned i;
161
Benny Prijonoe6315582007-03-08 18:58:04 +0000162 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
163 if (!srv->usage[i])
164 continue;
165
166 pj_stun_usage_destroy(srv->usage[i]);
167 pj_stun_server_unregister_usage(srv, srv->usage[i]);
168 }
169
Benny Prijono7cd16222007-03-05 00:58:24 +0000170 srv->thread_quit_flag = PJ_TRUE;
171 for (i=0; i<srv->si.thread_cnt; ++i) {
172 pj_thread_join(srv->threads[i]);
173 srv->threads[i] = NULL;
Benny Prijono14c2b862007-02-21 00:40:05 +0000174 }
175
Benny Prijono7cd16222007-03-05 00:58:24 +0000176 pj_timer_heap_destroy(srv->si.timer_heap);
177 pj_ioqueue_destroy(srv->si.ioqueue);
178 pj_pool_release(srv->pool);
Benny Prijono14c2b862007-02-21 00:40:05 +0000179
180 return PJ_SUCCESS;
181}
182
183