Index: pjproject/trunk/pjnath/src/pjturn-srv/server.c
===================================================================
--- pjproject/trunk/pjnath/src/pjturn-srv/server.c	(revision 1812)
+++ pjproject/trunk/pjnath/src/pjturn-srv/server.c	(revision 1850)
@@ -36,9 +36,4 @@
 
 
-/* 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,
@@ -54,4 +49,17 @@
 				      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 "???";
+}
 
 /*
@@ -98,5 +106,4 @@
     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 */
@@ -162,4 +169,39 @@
     lis->id = index;
     srv->core.lis_cnt++;
+
+    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;
@@ -185,7 +227,8 @@
 
 /* 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;
@@ -194,8 +237,8 @@
 
     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);
@@ -221,5 +264,6 @@
 
     /* 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;
@@ -230,5 +274,5 @@
     /* 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);
@@ -237,5 +281,6 @@
 
     /* 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);
@@ -246,5 +291,5 @@
     /* 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);
@@ -253,12 +298,14 @@
 
     /* 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);
@@ -270,9 +317,10 @@
 
     /* 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, 
@@ -296,8 +344,12 @@
 {
     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 */
@@ -322,6 +374,61 @@
 	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;
 }
 
@@ -331,5 +438,4 @@
 			       pjturn_pkt *pkt)
 {
-    pj_stun_msg *req, *res;
     unsigned options, lis_id;
     pj_status_t status;
@@ -392,5 +498,5 @@
      */
     if (alloc) {
-	pjturn_allocation_on_rx_pkt(alloc, pkt);
+	pjturn_allocation_on_rx_client_pkt(alloc, pkt);
     } else {
 	/* Otherwise this is a new client */
