blob: d69d38c69e4990d459c81db50faeb98da95379b8 [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);
28static pj_status_t sess_on_send_msg(pj_stun_session *sess,
29 const void *pkt,
30 pj_size_t pkt_size,
31 const pj_sockaddr_t *dst_addr,
32 unsigned addr_len);
33static pj_status_t sess_on_rx_request(pj_stun_session *sess,
34 const pj_uint8_t *pkt,
35 unsigned pkt_len,
36 const pj_stun_msg *msg,
37 const pj_sockaddr_t *src_addr,
38 unsigned src_addr_len);
39
40PJ_DEF(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv,
41 const pj_str_t *ip_addr,
42 unsigned port,
43 pj_stun_usage **p_bu)
44{
45 pj_stun_server_info *si;
46 pj_stun_session *session;
47 pj_stun_usage *usage;
48 pj_stun_usage_cb usage_cb;
49 pj_stun_session_cb sess_cb;
50 pj_sockaddr_in local_addr;
51 pj_status_t status;
52
53 si = pj_stun_server_get_info(srv);
54
55 status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port);
56 if (status != PJ_SUCCESS)
57 return status;
58
59 pj_bzero(&usage_cb, sizeof(usage_cb));
60 usage_cb.on_rx_data = &usage_on_rx_data;
61
62 status = pj_stun_usage_create(srv, "bind%p", &usage_cb,
63 PJ_AF_INET, PJ_SOCK_DGRAM, 0,
64 &local_addr, sizeof(local_addr),
65 &usage);
66 if (status != PJ_SUCCESS)
67 return status;
68
69 pj_bzero(&sess_cb, sizeof(sess_cb));
70 sess_cb.on_send_msg = &sess_on_send_msg;
71 sess_cb.on_rx_request = &sess_on_rx_request;
72 status = pj_stun_session_create(si->endpt, "bind%p", &sess_cb, PJ_FALSE,
73 &session);
74 if (status != PJ_SUCCESS) {
75 pj_stun_usage_destroy(usage);
76 return status;
77 }
78
79 pj_stun_usage_set_user_data(usage, session);
80 pj_stun_session_set_user_data(session, usage);
81
82 *p_bu = usage;
83
84 return PJ_SUCCESS;
85}
86
87
88static void usage_on_rx_data(pj_stun_usage *usage,
89 void *pkt,
90 pj_size_t pkt_size,
91 const pj_sockaddr_t *src_addr,
92 unsigned src_addr_len)
93{
94 pj_stun_session *session;
95 pj_status_t status;
96
97 session = (pj_stun_session*) pj_stun_usage_get_user_data(usage);
98
99 /* Handle packet to session */
100 status = pj_stun_session_on_rx_pkt(session, (pj_uint8_t*)pkt, pkt_size,
101 PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET,
102 NULL, src_addr, src_addr_len);
103 if (status != PJ_SUCCESS) {
104 pj_stun_perror(THIS_FILE, "Error handling incoming packet", status);
105 return;
106 }
107}
108
109
110static pj_status_t sess_on_send_msg(pj_stun_session *sess,
111 const void *pkt,
112 pj_size_t pkt_size,
113 const pj_sockaddr_t *dst_addr,
114 unsigned addr_len)
115{
116 pj_stun_usage *usage;
117
118 usage = pj_stun_session_get_user_data(sess);
119
120 return pj_stun_usage_sendto(usage, pkt, pkt_size, 0,
121 dst_addr, addr_len);
122}
123
124
125static pj_status_t sess_on_rx_request(pj_stun_session *sess,
126 const pj_uint8_t *pkt,
127 unsigned pkt_len,
128 const pj_stun_msg *msg,
129 const pj_sockaddr_t *src_addr,
130 unsigned src_addr_len)
131{
132 pj_stun_tx_data *tdata;
133 pj_status_t status;
134
135 PJ_UNUSED_ARG(pkt);
136 PJ_UNUSED_ARG(pkt_len);
137
138 /* Create response */
139 status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata);
140 if (status != PJ_SUCCESS)
141 return status;
142
143 /* Create MAPPED-ADDRESS attribute */
144 status = pj_stun_msg_add_ip_addr_attr(tdata->pool, tdata->msg,
145 PJ_STUN_ATTR_MAPPED_ADDR,
146 PJ_FALSE,
147 src_addr, src_addr_len);
148 if (status != PJ_SUCCESS) {
149 pj_stun_perror(THIS_FILE, "Error creating response", status);
150 pj_stun_msg_destroy_tdata(sess, tdata);
151 return status;
152 }
153
154 /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */
155 if (msg->hdr.magic == PJ_STUN_MAGIC) {
156 status =
157 pj_stun_msg_add_ip_addr_attr(tdata->pool, tdata->msg,
158 PJ_STUN_ATTR_XOR_MAPPED_ADDRESS,
159 PJ_TRUE,
160 src_addr, src_addr_len);
161 if (status != PJ_SUCCESS) {
162 pj_stun_perror(THIS_FILE, "Error creating response", status);
163 pj_stun_msg_destroy_tdata(sess, tdata);
164 return status;
165 }
166 }
167
168 /* Send */
169 status = pj_stun_session_send_msg(sess, PJ_TRUE,
170 src_addr, src_addr_len, tdata);
171 return status;
172
173}
174