blob: 5fdb233e01f96a56d7c859b1a9489019f7a4f003 [file] [log] [blame]
Benny Prijono14c2b862007-02-21 00:40:05 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
4 *
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 Prijono7cd16222007-03-05 00:58:24 +000086 status = pj_stun_endpoint_create(srv->si.pf, 0, srv->si.ioqueue,
87 srv->si.timer_heap, &srv->si.endpt);
Benny Prijono14c2b862007-02-21 00:40:05 +000088 if (status != PJ_SUCCESS)
Benny Prijono7cd16222007-03-05 00:58:24 +000089 goto on_error;
Benny Prijono14c2b862007-02-21 00:40:05 +000090
Benny Prijono7cd16222007-03-05 00:58:24 +000091 srv->si.thread_cnt = thread_cnt;
92 srv->threads = pj_pool_calloc(pool, thread_cnt, sizeof(pj_thread_t*));
93 for (i=0; i<thread_cnt; ++i) {
94 status = pj_thread_create(pool, "worker%p", &worker_thread,
95 srv, 0, 0, &srv->threads[i]);
96 if (status != PJ_SUCCESS)
97 goto on_error;
98 }
Benny Prijonoc5ee0912007-03-01 00:08:27 +000099
Benny Prijono7cd16222007-03-05 00:58:24 +0000100 *p_srv = srv;
Benny Prijono14c2b862007-02-21 00:40:05 +0000101 return PJ_SUCCESS;
Benny Prijono7cd16222007-03-05 00:58:24 +0000102
103on_error:
104 pj_stun_server_destroy(srv);
105 return status;
Benny Prijono14c2b862007-02-21 00:40:05 +0000106}
107
108
Benny Prijono7cd16222007-03-05 00:58:24 +0000109PJ_DEF(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv)
Benny Prijono14c2b862007-02-21 00:40:05 +0000110{
Benny Prijono7cd16222007-03-05 00:58:24 +0000111 return &srv->si;
Benny Prijono14c2b862007-02-21 00:40:05 +0000112}
113
114
Benny Prijonoe6315582007-03-08 18:58:04 +0000115pj_status_t pj_stun_server_register_usage(pj_stun_server *srv,
116 pj_stun_usage *usage)
117{
118 unsigned i;
119
120 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
121 if (srv->usage[i] == usage)
122 return PJ_SUCCESS;
123 }
124
125 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
126 if (srv->usage[i] == NULL)
127 break;
128 }
129
130 if (i == PJ_ARRAY_SIZE(srv->usage))
131 return PJ_ETOOMANY;
132
133 srv->usage[i] = usage;
134 ++srv->usage_cnt;
135
136 return PJ_SUCCESS;
137}
138
139pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv,
140 pj_stun_usage *usage)
141{
142 unsigned i;
143
144 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
145 if (srv->usage[i] == usage)
146 break;
147 }
148
149 if (i != PJ_ARRAY_SIZE(srv->usage)) {
150 srv->usage[i] = NULL;
151 --srv->usage_cnt;
152 return PJ_SUCCESS;
153 }
154
155 return PJ_ENOTFOUND;
156}
157
158
Benny Prijono7cd16222007-03-05 00:58:24 +0000159PJ_DEF(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv)
Benny Prijono14c2b862007-02-21 00:40:05 +0000160{
161 unsigned i;
162
Benny Prijonoe6315582007-03-08 18:58:04 +0000163 for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
164 if (!srv->usage[i])
165 continue;
166
167 pj_stun_usage_destroy(srv->usage[i]);
168 pj_stun_server_unregister_usage(srv, srv->usage[i]);
169 }
170
Benny Prijono7cd16222007-03-05 00:58:24 +0000171 srv->thread_quit_flag = PJ_TRUE;
172 for (i=0; i<srv->si.thread_cnt; ++i) {
173 pj_thread_join(srv->threads[i]);
174 srv->threads[i] = NULL;
Benny Prijono14c2b862007-02-21 00:40:05 +0000175 }
176
Benny Prijono7cd16222007-03-05 00:58:24 +0000177 pj_stun_endpoint_destroy(srv->si.endpt);
178 pj_timer_heap_destroy(srv->si.timer_heap);
179 pj_ioqueue_destroy(srv->si.ioqueue);
180 pj_pool_release(srv->pool);
Benny Prijono14c2b862007-02-21 00:40:05 +0000181
182 return PJ_SUCCESS;
183}
184
185