summaryrefslogtreecommitdiff
path: root/pjlib-util/src/pjstun-srv-test/turn_usage.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjlib-util/src/pjstun-srv-test/turn_usage.c')
-rw-r--r--pjlib-util/src/pjstun-srv-test/turn_usage.c181
1 files changed, 138 insertions, 43 deletions
diff --git a/pjlib-util/src/pjstun-srv-test/turn_usage.c b/pjlib-util/src/pjstun-srv-test/turn_usage.c
index f82d5149..e3d2e595 100644
--- a/pjlib-util/src/pjstun-srv-test/turn_usage.c
+++ b/pjlib-util/src/pjstun-srv-test/turn_usage.c
@@ -49,6 +49,11 @@ static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess,
const pj_sockaddr_t *src_addr,
unsigned src_addr_len);
+static pj_status_t handle_binding_req(pj_stun_session *session,
+ const pj_stun_msg *msg,
+ const pj_sockaddr_t *src_addr,
+ unsigned src_addr_len);
+
static pj_status_t client_create(struct turn_usage *tu,
const pj_sockaddr_t *src_addr,
unsigned src_addr_len,
@@ -90,11 +95,13 @@ struct turn_client
pj_stun_session *session;
pj_mutex_t *mutex;
+ pj_sockaddr_in client_src_addr;
+
/* Socket and socket address of the allocated port */
int sock_type;
pj_sock_t sock;
pj_ioqueue_key_t *key;
- pj_sockaddr_in client_addr;
+ pj_sockaddr_in alloc_addr;
/* Allocation properties */
unsigned bw_kbps;
@@ -149,8 +156,8 @@ PJ_DEF(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv,
pj_sockaddr_in local_addr;
pj_status_t status;
- PJ_ASSERT_RETURN(srv && (type==PJ_SOCK_DGRAM||type==PJ_SOCK_STREAM) &&
- p_bu, PJ_EINVAL);
+ PJ_ASSERT_RETURN(srv && (type==PJ_SOCK_DGRAM||type==PJ_SOCK_STREAM),
+ PJ_EINVAL);
si = pj_stun_server_get_info(srv);
pool = pj_pool_create(si->pf, "turn%p", 4000, 4000, NULL);
@@ -159,8 +166,11 @@ PJ_DEF(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv,
tu->type = type;
tu->pf = si->pf;
tu->endpt = si->endpt;
+ tu->ioqueue = si->ioqueue;
tu->timer_heap = si->timer_heap;
tu->next_port = START_PORT;
+ tu->max_bw_kbps = 64;
+ tu->max_lifetime = 10 * 60;
status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port);
if (status != PJ_SUCCESS)
@@ -205,7 +215,9 @@ PJ_DEF(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv,
return status;
}
- *p_bu = tu->usage;
+ if (p_bu) {
+ *p_bu = tu->usage;
+ }
return PJ_SUCCESS;
}
@@ -223,14 +235,16 @@ static void tu_on_destroy(pj_stun_usage *usage)
tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage);
/* Destroy all clients */
- it = pj_hash_first(tu->client_htable, &hit);
- while (it) {
- struct turn_client *client;
+ if (tu->client_htable) {
+ it = pj_hash_first(tu->client_htable, &hit);
+ while (it) {
+ struct turn_client *client;
- client = (struct turn_client *)pj_hash_this(tu->client_htable, it);
- client_destroy(client, PJ_SUCCESS);
+ client = (struct turn_client *)pj_hash_this(tu->client_htable, it);
+ client_destroy(client, PJ_SUCCESS);
- it = pj_hash_next(tu->client_htable, it);
+ it = pj_hash_first(tu->client_htable, &hit);
+ }
}
pj_stun_session_destroy(tu->default_session);
@@ -391,6 +405,7 @@ static pj_status_t tu_alloc_port(struct turn_usage *tu,
return status;
}
+ *p_sock = sock;
return PJ_SUCCESS;
}
}
@@ -419,7 +434,10 @@ static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess,
pj_assert(sd->client == NULL);
- if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) {
+ if (msg->hdr.type == PJ_STUN_BINDING_REQUEST) {
+ return handle_binding_req(sess, msg, src_addr, src_addr_len);
+
+ } else if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) {
if (PJ_STUN_IS_REQUEST(msg->hdr.type)) {
status = pj_stun_session_create_response(sess, msg,
PJ_STUN_SC_NO_BINDING,
@@ -505,9 +523,9 @@ static struct peer* client_add_peer(struct turn_client *client,
static const char *get_tp_type(int type)
{
- if (type==0)
+ if (type==PJ_SOCK_DGRAM)
return "udp";
- else if (type==1)
+ else if (type==PJ_SOCK_STREAM)
return "tcp";
else
return "???";
@@ -519,12 +537,12 @@ static const char *get_tp_type(int type)
* in the TURN usage. This is called from by tu_on_rx_data() when
* the packet is handed over to the client.
*/
-static pj_status_t client_sess_on_rx_request(pj_stun_session *sess,
- const pj_uint8_t *pkt,
- unsigned pkt_len,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
+static pj_status_t client_sess_on_rx_msg(pj_stun_session *sess,
+ const pj_uint8_t *pkt,
+ unsigned pkt_len,
+ const pj_stun_msg *msg,
+ const pj_sockaddr_t *src_addr,
+ unsigned src_addr_len)
{
struct session_data *sd;
@@ -576,12 +594,17 @@ static pj_status_t client_create(struct turn_usage *tu,
struct session_data *sd;
pj_status_t status;
+ PJ_ASSERT_RETURN(src_addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL);
+
pool = pj_pool_create(tu->pf, "turnc%p", 4000, 4000, NULL);
client = PJ_POOL_ZALLOC_T(pool, struct turn_client);
client->pool = pool;
client->tu = tu;
client->sock = PJ_INVALID_SOCKET;
+ pj_memcpy(&client->client_src_addr, src_addr,
+ sizeof(client->client_src_addr));
+
if (src_addr) {
const pj_sockaddr_in *a4 = (const pj_sockaddr_in *)src_addr;
pj_ansi_snprintf(client->obj_name, sizeof(client->obj_name),
@@ -595,7 +618,8 @@ static pj_status_t client_create(struct turn_usage *tu,
/* Create session */
pj_bzero(&sess_cb, sizeof(sess_cb));
sess_cb.on_send_msg = &client_sess_on_send_msg;
- sess_cb.on_rx_request = &client_sess_on_rx_request;
+ sess_cb.on_rx_request = &client_sess_on_rx_msg;
+ sess_cb.on_rx_indication = &client_sess_on_rx_msg;
status = pj_stun_session_create(tu->endpt, client->obj_name,
&sess_cb, PJ_FALSE,
&client->session);
@@ -667,7 +691,8 @@ static pj_status_t client_destroy(struct turn_client *client,
/* Unregister client from hash table */
pj_mutex_lock(tu->mutex);
pj_hash_set(NULL, tu->client_htable,
- &client->client_addr, sizeof(client->client_addr), 0, NULL);
+ &client->client_src_addr, sizeof(client->client_src_addr),
+ 0, NULL);
pj_mutex_unlock(tu->mutex);
/* Destroy STUN session */
@@ -709,7 +734,7 @@ static pj_status_t client_create_relay(struct turn_client *client)
/* Update address */
addrlen = sizeof(pj_sockaddr_in);
- status = pj_sock_getsockname(client->sock, &client->client_addr,
+ status = pj_sock_getsockname(client->sock, &client->alloc_addr,
&addrlen);
if (status != PJ_SUCCESS) {
pj_sock_close(client->sock);
@@ -717,6 +742,15 @@ static pj_status_t client_create_relay(struct turn_client *client)
return status;
}
+ if (client->alloc_addr.sin_addr.s_addr == 0) {
+ status = pj_gethostip(&client->alloc_addr.sin_addr);
+ if (status != PJ_SUCCESS) {
+ pj_sock_close(client->sock);
+ client->sock = PJ_INVALID_SOCKET;
+ return status;
+ }
+ }
+
/* Register to ioqueue */
pj_bzero(&client_ioq_cb, sizeof(client_ioq_cb));
client_ioq_cb.on_read_complete = &client_on_read_complete;
@@ -740,8 +774,8 @@ static pj_status_t client_create_relay(struct turn_client *client)
PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated on %s:%s:%d",
client->obj_name,
get_tp_type(client->sock_type),
- pj_inet_ntoa(client->client_addr.sin_addr),
- (int)pj_ntohs(client->client_addr.sin_port)));
+ pj_inet_ntoa(client->alloc_addr.sin_addr),
+ (int)pj_ntohs(client->alloc_addr.sin_port)));
return PJ_SUCCESS;
}
@@ -766,8 +800,8 @@ static pj_status_t client_destroy_relay(struct turn_client *client)
PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocation %s:%s:%d destroyed",
client->obj_name,
get_tp_type(client->sock_type),
- pj_inet_ntoa(client->client_addr.sin_addr),
- (int)pj_ntohs(client->client_addr.sin_port)));
+ pj_inet_ntoa(client->alloc_addr.sin_addr),
+ (int)pj_ntohs(client->alloc_addr.sin_port)));
return PJ_SUCCESS;
}
@@ -795,15 +829,15 @@ static struct peer* client_add_peer(struct turn_client *client,
peer = PJ_POOL_ZALLOC_T(client->pool, struct peer);
peer->client = client;
- pj_memcpy(&peer->addr, peer_addr, sizeof(*peer_addr));
+ pj_memcpy(&peer->addr, peer_addr, sizeof(peer->addr));
pj_hash_set(client->pool, client->peer_htable,
- peer_addr, sizeof(*peer_addr), hval, peer);
+ &peer->addr, sizeof(peer->addr), hval, peer);
PJ_LOG(4,(THIS_FILE, "TURN client %s: peer %s:%s:%d added",
client->obj_name, get_tp_type(client->sock_type),
- pj_inet_ntoa(peer_addr->sin_addr),
- (int)pj_ntohs(peer_addr->sin_port)));
+ pj_inet_ntoa(peer->addr.sin_addr),
+ (int)pj_ntohs(peer->addr.sin_port)));
return peer;
}
@@ -975,7 +1009,7 @@ static pj_status_t client_handle_allocate_req(struct turn_client *client,
timeout.sec = client->lifetime;
timeout.msec = 0;
pj_timer_heap_schedule(client->tu->timer_heap, &client->expiry_timer, &timeout);
-
+ client->expiry_timer.id = PJ_TRUE;
/* Done successfully, create and send success response */
status = pj_stun_session_create_response(client->session, msg,
@@ -988,18 +1022,18 @@ static pj_status_t client_handle_allocate_req(struct turn_client *client,
PJ_STUN_ATTR_BANDWIDTH, client->bw_kbps);
pj_stun_msg_add_uint_attr(response->pool, response->msg,
PJ_STUN_ATTR_LIFETIME, client->lifetime);
- pj_stun_msg_add_ip_addr_attr(response->pool, response->msg,
+ pj_stun_msg_add_sockaddr_attr(response->pool, response->msg,
PJ_STUN_ATTR_MAPPED_ADDR, PJ_FALSE,
src_addr, src_addr_len);
- pj_stun_msg_add_ip_addr_attr(response->pool, response->msg,
+ pj_stun_msg_add_sockaddr_attr(response->pool, response->msg,
PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE,
src_addr, src_addr_len);
addr_len = sizeof(req_addr);
pj_sock_getsockname(client->sock, &req_addr, &addr_len);
- pj_stun_msg_add_ip_addr_attr(response->pool, response->msg,
+ pj_stun_msg_add_sockaddr_attr(response->pool, response->msg,
PJ_STUN_ATTR_RELAY_ADDR, PJ_FALSE,
- &req_addr, addr_len);
+ &client->alloc_addr, addr_len);
PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated or refreshed, "
"internal address is %s:%s:%d",
@@ -1013,6 +1047,46 @@ static pj_status_t client_handle_allocate_req(struct turn_client *client,
}
+/*
+ * Handle incoming Binding request.
+ * This function is called by client_handle_stun_msg() below.
+ */
+static pj_status_t handle_binding_req(pj_stun_session *session,
+ const pj_stun_msg *msg,
+ const pj_sockaddr_t *src_addr,
+ unsigned src_addr_len)
+{
+ pj_stun_tx_data *tdata;
+ pj_status_t status;
+
+ /* Create response */
+ status = pj_stun_session_create_response(session, msg, 0, NULL,
+ &tdata);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Create MAPPED-ADDRESS attribute */
+ pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_MAPPED_ADDR,
+ PJ_FALSE,
+ src_addr, src_addr_len);
+
+ /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */
+ if (msg->hdr.magic == PJ_STUN_MAGIC) {
+ status =
+ pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_XOR_MAPPED_ADDR,
+ PJ_TRUE,
+ src_addr, src_addr_len);
+ }
+
+ /* Send */
+ status = pj_stun_session_send_msg(session, PJ_TRUE,
+ src_addr, src_addr_len, tdata);
+ return status;
+}
+
+
/*
* client handling incoming STUN Set Active Destination request
* This function is called by client_handle_stun_msg() below.
@@ -1058,10 +1132,16 @@ static pj_status_t client_handle_sad(struct turn_client *client,
client->active_peer = peer;
}
- PJ_LOG(4,(THIS_FILE, "TURN client %s: active destination set to %s:%d",
- client->obj_name,
- pj_inet_ntoa(client->active_peer->addr.sin_addr),
- (int)pj_ntohs(client->active_peer->addr.sin_port)));
+ if (client->active_peer) {
+ PJ_LOG(4,(THIS_FILE,
+ "TURN client %s: active destination set to %s:%d",
+ client->obj_name,
+ pj_inet_ntoa(client->active_peer->addr.sin_addr),
+ (int)pj_ntohs(client->active_peer->addr.sin_port)));
+ } else {
+ PJ_LOG(4,(THIS_FILE, "TURN client %s: active destination cleared",
+ client->obj_name));
+ }
/* Respond with successful response */
client_respond(client, msg, 0, NULL, src_addr, src_addr_len);
@@ -1162,17 +1242,27 @@ static pj_status_t client_handle_stun_msg(struct turn_client *client,
switch (msg->hdr.type) {
case PJ_STUN_SEND_INDICATION:
status = client_handle_send_ind(client, msg);
+ break;
case PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST:
status = client_handle_sad(client, msg,
src_addr, src_addr_len);
+ break;
+
case PJ_STUN_ALLOCATE_REQUEST:
status = client_handle_allocate_req(client, msg,
src_addr, src_addr_len);
+ break;
+
+ case PJ_STUN_BINDING_REQUEST:
+ status = handle_binding_req(client->session, msg,
+ src_addr, src_addr_len);
+ break;
default:
status = client_handle_unknown_msg(client, msg,
src_addr, src_addr_len);
+ break;
}
return status;
@@ -1203,6 +1293,11 @@ static void client_handle_peer_data(struct turn_client *client,
peer = client_get_peer(client, &client->pkt_src_addr, NULL);
if (peer == NULL) {
/* Nope. Discard packet */
+ PJ_LOG(5,(THIS_FILE,
+ "TURN client %s: discarded data from %s:%d",
+ client->obj_name,
+ pj_inet_ntoa(client->pkt_src_addr.sin_addr),
+ (int)pj_ntohs(client->pkt_src_addr.sin_port)));
return;
}
@@ -1225,10 +1320,10 @@ static void client_handle_peer_data(struct turn_client *client,
if (status != PJ_SUCCESS)
return;
- pj_stun_msg_add_ip_addr_attr(data_ind->pool, data_ind->msg,
- PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE,
- &client->pkt_src_addr,
- client->pkt_src_addr_len);
+ pj_stun_msg_add_sockaddr_attr(data_ind->pool, data_ind->msg,
+ PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE,
+ &client->pkt_src_addr,
+ client->pkt_src_addr_len);
pj_stun_msg_add_binary_attr(data_ind->pool, data_ind->msg,
PJ_STUN_ATTR_DATA,
client->pkt, bytes_read);