summaryrefslogtreecommitdiff
path: root/pjnath/src/pjturn-srv/server.c
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-03-08 00:54:04 +0000
committerBenny Prijono <bennylp@teluu.com>2008-03-08 00:54:04 +0000
commite30de41312b8f3552dea56db5eb73d99889f6941 (patch)
tree94af9773e03bffd53f58620a87c26da737db62df /pjnath/src/pjturn-srv/server.c
parent2eeebb98f8e4fc3f84fe8d16548035b605ff0929 (diff)
More work on ticket #485: more TURN-07 work
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1850 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjnath/src/pjturn-srv/server.c')
-rw-r--r--pjnath/src/pjturn-srv/server.c154
1 files changed, 130 insertions, 24 deletions
diff --git a/pjnath/src/pjturn-srv/server.c b/pjnath/src/pjturn-srv/server.c
index 15268348..c9fc40cf 100644
--- a/pjnath/src/pjturn-srv/server.c
+++ b/pjnath/src/pjturn-srv/server.c
@@ -35,11 +35,6 @@
#define DEF_LIFETIME 300
-/* Globals */
-PJ_DEF_DATA(int) PJTURN_TP_UDP = 1;
-PJ_DEF_DATA(int) PJTURN_TP_TCP = 2;
-PJ_DEF_DATA(int) PJTURN_TP_TLS = 3;
-
/* Prototypes */
static pj_status_t on_tx_stun_msg( pj_stun_session *sess,
const void *pkt,
@@ -53,6 +48,19 @@ static pj_status_t on_rx_stun_request(pj_stun_session *sess,
const pj_sockaddr_t *src_addr,
unsigned src_addr_len);
+/*
+ * Get transport type name.
+ */
+PJ_DEF(const char*) pjturn_tp_type_name(int tp_type)
+{
+ /* Must be 3 characters long! */
+ if (tp_type == PJTURN_TP_UDP)
+ return "UDP";
+ else if (tp_type == PJTURN_TP_TCP)
+ return "TCP";
+ else
+ return "???";
+}
/*
* Create server.
@@ -97,7 +105,6 @@ PJ_DEF(pj_status_t) pjturn_srv_create( pj_pool_factory *pf,
/* Create hash tables */
srv->tables.alloc = pj_hash_create(pool, MAX_CLIENTS);
srv->tables.res = pj_hash_create(pool, MAX_CLIENTS);
- srv->tables.peer = pj_hash_create(pool, MAX_CLIENTS*MAX_PEERS_PER_CLIENT);
/* Init ports settings */
srv->ports.min_udp = srv->ports.next_udp = MIN_PORT;
@@ -165,6 +172,41 @@ PJ_DEF(pj_status_t) pjturn_srv_add_listener(pjturn_srv *srv,
return PJ_SUCCESS;
}
+/**
+ * Register an allocation.
+ */
+PJ_DEF(pj_status_t) pjturn_srv_register_allocation(pjturn_srv *srv,
+ pjturn_allocation *alloc)
+{
+ /* Add to hash tables */
+ pj_lock_acquire(srv->core.lock);
+ pj_hash_set(alloc->pool, srv->tables.alloc,
+ &alloc->hkey, sizeof(alloc->hkey), 0, alloc);
+ pj_hash_set(alloc->pool, srv->tables.res,
+ &alloc->relay.hkey, sizeof(alloc->relay.hkey), 0,
+ &alloc->relay);
+ pj_lock_release(srv->core.lock);
+
+ return PJ_SUCCESS;
+}
+
+/**
+ * Unregister an allocation.
+ */
+PJ_DEF(pj_status_t) pjturn_srv_unregister_allocation(pjturn_srv *srv,
+ pjturn_allocation *alloc)
+{
+ /* Unregister from hash tables */
+ pj_lock_acquire(srv->core.lock);
+ pj_hash_set(alloc->pool, srv->tables.alloc,
+ &alloc->hkey, sizeof(alloc->hkey), 0, NULL);
+ pj_hash_set(alloc->pool, srv->tables.res,
+ &alloc->relay.hkey, sizeof(alloc->relay.hkey), 0, NULL);
+ pj_lock_release(srv->core.lock);
+
+ return PJ_SUCCESS;
+}
+
/* Callback from our own STUN session to send packet */
static pj_status_t on_tx_stun_msg( pj_stun_session *sess,
@@ -184,19 +226,20 @@ static pj_status_t on_tx_stun_msg( pj_stun_session *sess,
}
/* Create and send error response */
-static pj_status_t respond_error(pj_stun_sess *sess, const pj_stun_msg *req,
- pj_bool_t cache, int code, const char *err_msg,
- const pj_sockaddr_t *addr, unsigned addr_len)
+static pj_status_t respond_error(pj_stun_session *sess, const pj_stun_msg *req,
+ pj_bool_t cache, int code, const char *errmsg,
+ const pj_sockaddr_t *dst_addr,
+ unsigned addr_len)
{
pj_status_t status;
pj_str_t reason;
pj_stun_tx_data *tdata;
status = pj_stun_session_create_res(sess, req,
- code, (err_msg?pj_cstr(&reason,err_msg):NULL),
+ code, (errmsg?pj_cstr(&reason,errmsg):NULL),
&tdata);
if (status != PJ_SUCCESS)
- return statys;
+ return status;
status = pj_stun_session_send_msg(sess, cache, dst_addr, addr_len, tdata);
return status;
@@ -220,7 +263,8 @@ static pj_status_t parse_allocate_req(pjturn_allocation_req *cfg,
pj_bzero(cfg, sizeof(*cfg));
/* Get BANDWIDTH attribute, if any. */
- attr_bw = pj_stun_msg_find_attr(msg, PJ_STUN_BANDWIDTH_ATTR, 0);
+ attr_bw = (pj_stun_uint_attr*)
+ pj_stun_msg_find_attr(req, PJ_STUN_ATTR_BANDWIDTH, 0);
if (attr_bw) {
cfg->bandwidth = attr_bw->value;
} else {
@@ -229,14 +273,15 @@ static pj_status_t parse_allocate_req(pjturn_allocation_req *cfg,
/* Check if we can satisfy the bandwidth */
if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) {
- respond_error(sess, msg, PJ_FALSE,
+ respond_error(sess, req, PJ_FALSE,
PJ_STUN_SC_ALLOCATION_QUOTA_REACHED,
"Invalid bandwidth", src_addr, src_addr_len);
return -1;
}
/* Get REQUESTED-TRANSPORT attribute, is any */
- attr_req_tp = pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_TRANSPORT, 0);
+ attr_req_tp = (pj_stun_uint_attr*)
+ pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0);
if (attr_req_tp) {
cfg->tp_type = PJ_STUN_GET_RT_PROTO(attr_req_tp->value);
} else {
@@ -245,21 +290,23 @@ static pj_status_t parse_allocate_req(pjturn_allocation_req *cfg,
/* Can only support UDP for now */
if (cfg->tp_type != PJTURN_TP_UDP) {
- respond_error(sess, msg, PJ_FALSE,
+ respond_error(sess, req, PJ_FALSE,
PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO,
NULL, src_addr, src_addr_len);
return -1;
}
/* Get REQUESTED-IP attribute, if any */
- attr_req_ip = pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_IP, 0);
+ attr_req_ip = (pj_stun_sockaddr_attr*)
+ pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_IP, 0);
if (attr_req_ip) {
- pj_memcpy(&cfg->addr, &attr_req_ip->sockaddr,
- sizeof(attr_req_ip->sockaddr));
+ pj_sockaddr_print(&attr_req_ip->sockaddr, cfg->addr,
+ sizeof(cfg->addr), 0);
}
/* Get REQUESTED-PORT-PROPS attribute, if any */
- attr_rpp = pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_PORT_PROPS, 0);
+ attr_rpp = (pj_stun_uint_attr*)
+ pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_PORT_PROPS, 0);
if (attr_rpp) {
cfg->rpp_bits = PJ_STUN_GET_RPP_BITS(attr_rpp->value);
cfg->rpp_port = PJ_STUN_GET_RPP_PORT(attr_rpp->value);
@@ -269,11 +316,12 @@ static pj_status_t parse_allocate_req(pjturn_allocation_req *cfg,
}
/* Get LIFETIME attribute */
- attr_lifetime = pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_LIFETIME, 0);
+ attr_lifetime = (pj_stun_uint_attr*)
+ pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0);
if (attr_lifetime) {
cfg->lifetime = attr_lifetime->value;
if (cfg->lifetime < MIN_LIFETIME || cfg->lifetime > MAX_LIFETIME) {
- respond_error(sess, msg, PJ_FALSE,
+ respond_error(sess, req, PJ_FALSE,
PJ_STUN_SC_BAD_REQUEST,
"Invalid LIFETIME value", src_addr,
src_addr_len);
@@ -295,10 +343,14 @@ static pj_status_t on_rx_stun_request(pj_stun_session *sess,
unsigned src_addr_len)
{
pjturn_listener *listener;
+ pjturn_srv *srv;
pjturn_allocation_req req;
+ pjturn_allocation *alloc;
+ pj_stun_tx_data *tdata;
pj_status_t status;
listener = (pjturn_listener*) pj_stun_session_get_user_data(sess);
+ srv = listener->server;
/* Handle strayed REFRESH request */
if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) {
@@ -321,8 +373,63 @@ static pj_status_t on_rx_stun_request(pj_stun_session *sess,
if (status != PJ_SUCCESS)
return status;
- /* Ready to allocate now */
+ /* Create new allocation. The relay resource will be allocated
+ * in this function.
+ */
+ status = pjturn_allocation_create(listener, src_addr, src_addr_len,
+ msg, &req, &alloc);
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR,
+ errmsg, src_addr, src_addr_len);
+ }
+
+ /* Respond the original ALLOCATE request */
+ status = pj_stun_session_create_res(srv->core.stun_sess[listener->id],
+ msg, 0, NULL, &tdata);
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pjturn_allocation_destroy(alloc);
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR,
+ errmsg, src_addr, src_addr_len);
+ }
+ /* Add RELAYED-ADDRESS attribute */
+ pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE,
+ &alloc->relay.hkey.addr,
+ pj_sockaddr_get_len(&alloc->relay.hkey.addr));
+
+ /* Add LIFETIME. */
+ pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_LIFETIME,
+ (unsigned)alloc->relay.lifetime);
+
+ /* Add BANDWIDTH */
+ pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_BANDWIDTH,
+ alloc->bandwidth);
+
+ /* Add RESERVATION-TOKEN */
+ PJ_TODO(ADD_RESERVATION_TOKEN);
+
+ /* Add XOR-MAPPED-ADDRESS */
+ pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
+ PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE,
+ &alloc->hkey.clt_addr,
+ pj_sockaddr_get_len(&alloc->hkey.clt_addr));
+
+ /* Send the response */
+ pj_stun_session_send_msg(srv->core.stun_sess[listener->id], PJ_TRUE,
+ src_addr, src_addr_len, tdata);
+
+ /* Done. */
+ return PJ_SUCCESS;
}
@@ -330,7 +437,6 @@ static pj_status_t on_rx_stun_request(pj_stun_session *sess,
static void handle_new_client( pjturn_srv *srv,
pjturn_pkt *pkt)
{
- pj_stun_msg *req, *res;
unsigned options, lis_id;
pj_status_t status;
@@ -391,7 +497,7 @@ PJ_DEF(void) pjturn_srv_on_rx_pkt( pjturn_srv *srv,
* allocation.
*/
if (alloc) {
- pjturn_allocation_on_rx_pkt(alloc, pkt);
+ pjturn_allocation_on_rx_client_pkt(alloc, pkt);
} else {
/* Otherwise this is a new client */
handle_new_client(srv, pkt);