blob: 3c1825f9b07be230274c8bd5da12e3bc67fab283 [file] [log] [blame]
Benny Prijono7cd16222007-03-05 00:58:24 +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 */
19#include "server.h"
20
21#define THIS_FILE "bind_usage.c"
22
23static void usage_on_rx_data(pj_stun_usage *usage,
24 void *pkt,
25 pj_size_t pkt_size,
26 const pj_sockaddr_t *src_addr,
27 unsigned src_addr_len);
Benny Prijonoe6315582007-03-08 18:58:04 +000028static void usage_on_destroy(pj_stun_usage *usage);
Benny Prijono7cd16222007-03-05 00:58:24 +000029static pj_status_t sess_on_send_msg(pj_stun_session *sess,
30 const void *pkt,
31 pj_size_t pkt_size,
32 const pj_sockaddr_t *dst_addr,
33 unsigned addr_len);
34static pj_status_t sess_on_rx_request(pj_stun_session *sess,
35 const pj_uint8_t *pkt,
36 unsigned pkt_len,
37 const pj_stun_msg *msg,
38 const pj_sockaddr_t *src_addr,
39 unsigned src_addr_len);
40
Benny Prijonoe6315582007-03-08 18:58:04 +000041struct bind_usage
42{
43 pj_pool_t *pool;
44 pj_stun_usage *usage;
45 pj_stun_session *session;
46};
47
48
Benny Prijono7cd16222007-03-05 00:58:24 +000049PJ_DEF(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv,
50 const pj_str_t *ip_addr,
51 unsigned port,
52 pj_stun_usage **p_bu)
53{
Benny Prijonoe6315582007-03-08 18:58:04 +000054 pj_pool_t *pool;
55 struct bind_usage *bu;
Benny Prijono7cd16222007-03-05 00:58:24 +000056 pj_stun_server_info *si;
Benny Prijono7cd16222007-03-05 00:58:24 +000057 pj_stun_usage_cb usage_cb;
58 pj_stun_session_cb sess_cb;
59 pj_sockaddr_in local_addr;
60 pj_status_t status;
61
62 si = pj_stun_server_get_info(srv);
63
Benny Prijonoe6315582007-03-08 18:58:04 +000064 pool = pj_pool_create(si->pf, "bind%p", 128, 128, NULL);
65 bu = PJ_POOL_ZALLOC_T(pool, struct bind_usage);
66 bu->pool = pool;
67
Benny Prijono7cd16222007-03-05 00:58:24 +000068 status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port);
69 if (status != PJ_SUCCESS)
70 return status;
71
72 pj_bzero(&usage_cb, sizeof(usage_cb));
73 usage_cb.on_rx_data = &usage_on_rx_data;
Benny Prijonoe6315582007-03-08 18:58:04 +000074 usage_cb.on_destroy = &usage_on_destroy;
Benny Prijono7cd16222007-03-05 00:58:24 +000075
76 status = pj_stun_usage_create(srv, "bind%p", &usage_cb,
77 PJ_AF_INET, PJ_SOCK_DGRAM, 0,
78 &local_addr, sizeof(local_addr),
Benny Prijonoe6315582007-03-08 18:58:04 +000079 &bu->usage);
80 if (status != PJ_SUCCESS) {
81 pj_pool_release(pool);
Benny Prijono7cd16222007-03-05 00:58:24 +000082 return status;
Benny Prijonoe6315582007-03-08 18:58:04 +000083 }
Benny Prijono7cd16222007-03-05 00:58:24 +000084
85 pj_bzero(&sess_cb, sizeof(sess_cb));
86 sess_cb.on_send_msg = &sess_on_send_msg;
87 sess_cb.on_rx_request = &sess_on_rx_request;
Benny Prijonob01897b2007-03-18 17:39:27 +000088 status = pj_stun_session_create(si->cfg, "bind%p", &sess_cb, PJ_FALSE,
Benny Prijonoe6315582007-03-08 18:58:04 +000089 &bu->session);
Benny Prijono7cd16222007-03-05 00:58:24 +000090 if (status != PJ_SUCCESS) {
Benny Prijonoe6315582007-03-08 18:58:04 +000091 pj_stun_usage_destroy(bu->usage);
Benny Prijono7cd16222007-03-05 00:58:24 +000092 return status;
93 }
94
Benny Prijonoe6315582007-03-08 18:58:04 +000095 pj_stun_usage_set_user_data(bu->usage, bu);
96 pj_stun_session_set_user_data(bu->session, bu);
Benny Prijono7cd16222007-03-05 00:58:24 +000097
Benny Prijonoe6315582007-03-08 18:58:04 +000098 if (p_bu)
99 *p_bu = bu->usage;
Benny Prijono7cd16222007-03-05 00:58:24 +0000100
101 return PJ_SUCCESS;
102}
103
104
105static void usage_on_rx_data(pj_stun_usage *usage,
106 void *pkt,
107 pj_size_t pkt_size,
108 const pj_sockaddr_t *src_addr,
109 unsigned src_addr_len)
110{
Benny Prijonoe6315582007-03-08 18:58:04 +0000111 struct bind_usage *bu;
Benny Prijono7cd16222007-03-05 00:58:24 +0000112 pj_stun_session *session;
113 pj_status_t status;
114
Benny Prijonoe6315582007-03-08 18:58:04 +0000115 bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage);
116 session = bu->session;
Benny Prijono7cd16222007-03-05 00:58:24 +0000117
118 /* Handle packet to session */
119 status = pj_stun_session_on_rx_pkt(session, (pj_uint8_t*)pkt, pkt_size,
120 PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET,
121 NULL, src_addr, src_addr_len);
122 if (status != PJ_SUCCESS) {
123 pj_stun_perror(THIS_FILE, "Error handling incoming packet", status);
124 return;
125 }
126}
127
128
129static pj_status_t sess_on_send_msg(pj_stun_session *sess,
130 const void *pkt,
131 pj_size_t pkt_size,
132 const pj_sockaddr_t *dst_addr,
133 unsigned addr_len)
134{
Benny Prijonoe6315582007-03-08 18:58:04 +0000135 struct bind_usage *bu;
Benny Prijono7cd16222007-03-05 00:58:24 +0000136 pj_stun_usage *usage;
137
Benny Prijonoe6315582007-03-08 18:58:04 +0000138 bu = (struct bind_usage*) pj_stun_session_get_user_data(sess);
139 usage = bu->usage;
Benny Prijono7cd16222007-03-05 00:58:24 +0000140
141 return pj_stun_usage_sendto(usage, pkt, pkt_size, 0,
142 dst_addr, addr_len);
143}
144
145
146static pj_status_t sess_on_rx_request(pj_stun_session *sess,
147 const pj_uint8_t *pkt,
148 unsigned pkt_len,
149 const pj_stun_msg *msg,
150 const pj_sockaddr_t *src_addr,
151 unsigned src_addr_len)
152{
153 pj_stun_tx_data *tdata;
154 pj_status_t status;
155
156 PJ_UNUSED_ARG(pkt);
157 PJ_UNUSED_ARG(pkt_len);
158
159 /* Create response */
160 status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata);
161 if (status != PJ_SUCCESS)
162 return status;
163
164 /* Create MAPPED-ADDRESS attribute */
Benny Prijonod5971742007-03-10 23:15:36 +0000165 status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
166 PJ_STUN_ATTR_MAPPED_ADDR,
167 PJ_FALSE,
168 src_addr, src_addr_len);
Benny Prijono7cd16222007-03-05 00:58:24 +0000169 if (status != PJ_SUCCESS) {
170 pj_stun_perror(THIS_FILE, "Error creating response", status);
171 pj_stun_msg_destroy_tdata(sess, tdata);
172 return status;
173 }
174
175 /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */
176 if (msg->hdr.magic == PJ_STUN_MAGIC) {
177 status =
Benny Prijonod5971742007-03-10 23:15:36 +0000178 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
179 PJ_STUN_ATTR_XOR_MAPPED_ADDR,
180 PJ_TRUE,
181 src_addr, src_addr_len);
Benny Prijono7cd16222007-03-05 00:58:24 +0000182 if (status != PJ_SUCCESS) {
183 pj_stun_perror(THIS_FILE, "Error creating response", status);
184 pj_stun_msg_destroy_tdata(sess, tdata);
185 return status;
186 }
187 }
188
189 /* Send */
190 status = pj_stun_session_send_msg(sess, PJ_TRUE,
191 src_addr, src_addr_len, tdata);
192 return status;
193
194}
195
Benny Prijonoe6315582007-03-08 18:58:04 +0000196static void usage_on_destroy(pj_stun_usage *usage)
197{
198 struct bind_usage *bu;
199
200 bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage);
201 if (bu==NULL)
202 return;
203
204 pj_stun_session_destroy(bu->session);
205 pj_pool_release(bu->pool);
206}