Index: pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 51)
+++ pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 54)
@@ -33,5 +33,5 @@
 #include <pj/assert.h>
 #include <pj/errno.h>
-
+#include <pj/lock.h>
 
 #define PJSIP_EX_NO_MEMORY  PJ_NO_MEMORY_EXCEPTION
@@ -64,5 +64,8 @@
 
     /** Transport manager. */
-    pjsip_transport_mgr *transport_mgr;
+    pjsip_tpmgr		*transport_mgr;
+
+    /** Ioqueue. */
+    pj_ioqueue_t	*ioqueue;
 
     /** DNS Resolver. */
@@ -96,5 +99,6 @@
  * Prototypes.
  */
-static void endpt_transport_callback( pjsip_endpoint *, pjsip_rx_data *rdata );
+static void endpt_transport_callback(pjsip_endpoint*, 
+				     pj_status_t, pjsip_rx_data*);
 
 
@@ -355,4 +359,5 @@
     pjsip_endpoint *endpt;
     pjsip_max_forwards_hdr *mf_hdr;
+    pj_lock_t *lock = NULL;
 
     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create()"));
@@ -399,9 +404,26 @@
     }
 
+    /* Set recursive lock for the timer heap. */
+    status = pj_lock_create_recursive_mutex( endpt->pool, "edpt%p", &lock);
+    if (status != PJ_SUCCESS) {
+	goto on_error;
+    }
+    pj_timer_heap_set_lock(endpt->timer_heap, lock, PJ_TRUE);
+
+    /* Set maximum timed out entries to process in a single poll. */
+    pj_timer_heap_set_max_timed_out_per_poll(endpt->timer_heap, 
+					     PJSIP_MAX_TIMED_OUT_ENTRIES);
+
+    /* Create ioqueue. */
+    status = pj_ioqueue_create( endpt->pool, PJSIP_MAX_TRANSPORTS, &endpt->ioqueue);
+    if (status != PJ_SUCCESS) {
+	goto on_error;
+    }
+
     /* Create transport manager. */
-    status = pjsip_transport_mgr_create( endpt->pool,
-					 endpt,
-					 &endpt_transport_callback,
-					 &endpt->transport_mgr);
+    status = pjsip_tpmgr_create( endpt->pool, endpt,
+				 endpt->ioqueue, endpt->timer_heap,
+			         &endpt_transport_callback,
+				 &endpt->transport_mgr);
     if (status != PJ_SUCCESS) {
 	goto on_error;
@@ -446,5 +468,5 @@
 on_error:
     if (endpt->transport_mgr) {
-	pjsip_transport_mgr_destroy(endpt->transport_mgr);
+	pjsip_tpmgr_destroy(endpt->transport_mgr);
 	endpt->transport_mgr = NULL;
     }
@@ -471,5 +493,5 @@
 
     /* Shutdown and destroy all transports. */
-    pjsip_transport_mgr_destroy(endpt->transport_mgr);
+    pjsip_tpmgr_destroy(endpt->transport_mgr);
 
     /* Delete endpoint mutex. */
@@ -533,18 +555,14 @@
 					const pj_time_val *max_timeout)
 {
-    pj_time_val timeout;
-    int i;
+    /* timeout is 'out' var. This just to make compiler happy. */
+    pj_time_val timeout = { 0, 0};
 
     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_handle_events()"));
 
     /* Poll the timer. The timer heap has its own mutex for better 
-     * granularity, so we don't need to lock end endpoint. We also keep
-     * polling the timer while we have events.
+     * granularity, so we don't need to lock end endpoint. 
      */
-    timeout.sec = timeout.msec = 0; /* timeout is 'out' var. This just to make compiler happy. */
-    for (i=0; i<10; ++i) {
-	if (pj_timer_heap_poll( endpt->timer_heap, &timeout ) < 1)
-	    break;
-    }
+    timeout.sec = timeout.msec = 0;
+    pj_timer_heap_poll( endpt->timer_heap, &timeout );
 
     /* If caller specifies maximum time to wait, then compare the value with
@@ -555,6 +573,6 @@
     }
 
-    /* Poll events in the transport manager. */
-    pjsip_transport_mgr_handle_events( endpt->transport_mgr, &timeout);
+    /* Poll ioqueue. */
+    pj_ioqueue_poll( endpt->ioqueue, &timeout);
 }
 
@@ -659,11 +677,11 @@
 {
     pjsip_role_e role;
-    if (rdata->msg->type == PJSIP_REQUEST_MSG) {
+    if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
 	role = PJSIP_ROLE_UAS;
     } else {
 	role = PJSIP_ROLE_UAC;
     }
-    pjsip_tsx_create_key(rdata->pool, &rdata->key, role,
-			 &rdata->cseq->method, rdata);
+    pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role,
+			 &rdata->msg_info.cseq->method, rdata);
 }
 
@@ -673,11 +691,23 @@
  */
 static void endpt_transport_callback( pjsip_endpoint *endpt,
+				      pj_status_t status,
 				      pjsip_rx_data *rdata )
 {
-    pjsip_msg *msg = rdata->msg;
+    pjsip_msg *msg = rdata->msg_info.msg;
     pjsip_transaction *tsx;
     pj_bool_t a_new_transaction_just_been_created = PJ_FALSE;
 
     PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata));
+
+    if (status != PJ_SUCCESS) {
+	const char *src_addr = pj_inet_ntoa(rdata->pkt_info.addr.sin_addr);
+	int port = pj_ntohs(rdata->pkt_info.addr.sin_port);
+	PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status,
+			       "Src.addr=%s:%d, packet:--\n"
+			       "%s\n"
+			       "-- end of packet. Error",
+			       src_addr, port, rdata->msg_info.msg_buf));
+	return;
+    }
 
     /* For response, check that the value in Via sent-by match the transport.
@@ -688,14 +718,14 @@
 	const pj_sockaddr_in *addr;
 	const char *addr_addr;
-	int port = rdata->via->sent_by.port;
+	int port = rdata->msg_info.via->sent_by.port;
 	pj_bool_t mismatch = PJ_FALSE;
 	if (port == 0) {
 	    int type;
-	    type = pjsip_transport_get_type(rdata->transport);
+	    type = rdata->tp_info.transport->type;
 	    port = pjsip_transport_get_default_port_for_type(type);
 	}
-	addr = pjsip_transport_get_addr_name(rdata->transport);
+	addr = &rdata->tp_info.transport->public_addr;
 	addr_addr = pj_inet_ntoa(addr->sin_addr);
-	if (pj_strcmp2(&rdata->via->sent_by.host, addr_addr) != 0)
+	if (pj_strcmp2(&rdata->msg_info.via->sent_by.host, addr_addr) != 0)
 	    mismatch = PJ_TRUE;
 	else if (port != pj_ntohs(addr->sin_port)) {
@@ -707,5 +737,5 @@
 	     * both the port in sent-by and rport. We try to be lenient here!
 	     */
-	    if (rdata->via->rport_param != pj_sockaddr_in_get_port(addr))
+	    if (rdata->msg_info.via->rport_param != pj_sockaddr_in_get_port(addr))
 		mismatch = PJ_TRUE;
 	    else {
@@ -730,5 +760,5 @@
     /* Find the transaction for the received message. */
     PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s", 
-			 rdata->key.slen, rdata->key.ptr));
+			 rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr));
 
     /* Start lock mutex in the endpoint. */
@@ -736,5 +766,5 @@
 
     /* Find the transaction in the hash table. */
-    tsx = pj_hash_get( endpt->tsx_table, rdata->key.ptr, rdata->key.slen );
+    tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen );
 
     /* Unlock mutex. */
@@ -753,5 +783,5 @@
 	    /* Inform TU about the 200 message, only if it's INVITE. */
 	    if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) &&
-		rdata->cseq->method.id == PJSIP_INVITE_METHOD) 
+		rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) 
 	    {
 		pjsip_event e;
@@ -777,5 +807,5 @@
 	 * For non-ACK request message, create a new transaction.
 	 */
-	} else if (rdata->msg->line.req.method.id != PJSIP_ACK_METHOD) {
+	} else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
 
 	    pj_status_t status;
@@ -806,5 +836,5 @@
 	pjsip_tsx_on_rx_msg( tsx, rdata );
 
-    } else if (rdata->msg->line.req.method.id == PJSIP_ACK_METHOD) {
+    } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) {
 	/*
 	 * This is an ACK message, but the INVITE transaction could not
@@ -915,33 +945,14 @@
  * Find/create transport.
  */
-PJ_DEF(void) pjsip_endpt_get_transport( pjsip_endpoint *endpt,
-					pj_pool_t *pool,
-					pjsip_transport_type_e type,
-					const pj_sockaddr_in *remote,
-					void *token,
-					pjsip_transport_completion_callback *cb)
-{
-    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_get_transport()"));
-    pjsip_transport_get( endpt->transport_mgr, pool, type,
-			 remote, token, cb);
-}
-
-
-PJ_DEF(pj_status_t) pjsip_endpt_create_listener( pjsip_endpoint *endpt,
-						 pjsip_transport_type_e type,
-						 pj_sockaddr_in *addr,
-						 const pj_sockaddr_in *addr_name)
-{
-    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_listener()"));
-    return pjsip_create_listener( endpt->transport_mgr, type, addr, addr_name );
-}
-
-PJ_DEF(pj_status_t) pjsip_endpt_create_udp_listener( pjsip_endpoint *endpt,
-						     pj_sock_t sock,
-						     const pj_sockaddr_in *addr_name)
-{
-    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_udp_listener()"));
-    return pjsip_create_udp_listener( endpt->transport_mgr, sock, addr_name );
-}
+PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt,
+						  pjsip_transport_type_e type,
+						  const pj_sockaddr_in *remote,
+						  pjsip_transport **p_transport)
+{
+    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_alloc_transport()"));
+    return pjsip_tpmgr_alloc_transport( endpt->transport_mgr, type, remote,
+					p_transport);
+}
+
 
 PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
@@ -949,6 +960,4 @@
 #if PJ_LOG_MAX_LEVEL >= 3
     unsigned count;
-    pj_hash_iterator_t itr_val;
-    pj_hash_iterator_t *itr;
 
     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()"));
@@ -1015,36 +1024,6 @@
 
     /* Transports. 
-     * Note: transport is not properly locked in this function.
-     *       See pjsip_transport_first, pjsip_transport_next.
      */
-    itr = pjsip_transport_first( endpt->transport_mgr, &itr_val );
-    if (itr) {
-	PJ_LOG(3, (THIS_FILE, " Dumping transports:"));
-
-	do {
-	    char src_addr[128], dst_addr[128];
-	    int src_port, dst_port;
-	    const pj_sockaddr_in *addr;
-	    pjsip_transport_t *t;
-
-	    t = pjsip_transport_this(endpt->transport_mgr, itr);
-	    addr = pjsip_transport_get_local_addr(t);
-	    pj_native_strcpy(src_addr, pj_inet_ntoa(addr->sin_addr));
-	    src_port = pj_ntohs(addr->sin_port);
-
-	    addr = pjsip_transport_get_remote_addr(t);
-	    pj_native_strcpy(dst_addr, pj_inet_ntoa(addr->sin_addr));
-	    dst_port = pj_ntohs(addr->sin_port);
-
-	    PJ_LOG(3, (THIS_FILE, "  %s %s %s:%d --> %s:%d (refcnt=%d)", 
-		       pjsip_transport_get_type_name(t),
-		       pjsip_transport_get_obj_name(t),
-		       src_addr, src_port,
-		       dst_addr, dst_port,
-		       pjsip_transport_get_ref_cnt(t)));
-
-	    itr = pjsip_transport_next(endpt->transport_mgr, itr);
-	} while (itr);
-    }
+    pjsip_tpmgr_dump_transports( endpt->transport_mgr );
 
     /* Timer. */
