Index: pjproject/trunk/pjnath/src/pjnath/turn_sock.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/turn_sock.c	(revision 6039)
+++ pjproject/trunk/pjnath/src/pjnath/turn_sock.c	(revision 6071)
@@ -94,4 +94,7 @@
 
     pj_ioqueue_op_key_t	 send_key;
+    pj_ioqueue_op_key_t	 int_send_key;
+    unsigned 		 pkt_len;
+    unsigned 		 body_len;
 
     /* Data connection, when peer_conn_type==PJ_TURN_TP_TCP (RFC 6062) */
@@ -109,4 +112,9 @@
 				    const pj_sockaddr_t *dst_addr,
 				    unsigned dst_addr_len);
+static pj_status_t turn_on_stun_send_pkt(pj_turn_session *sess,
+				    	 const pj_uint8_t *pkt,
+				    	 unsigned pkt_len,
+				    	 const pj_sockaddr_t *dst_addr,
+				    	 unsigned dst_addr_len);
 static void turn_on_channel_bound(pj_turn_session *sess,
 				  const pj_sockaddr_t *peer_addr,
@@ -136,4 +144,7 @@
 			      pj_status_t status,
 			      pj_size_t *remainder);
+static pj_bool_t on_data_sent(pj_turn_sock *turn_sock,
+			      pj_ioqueue_op_key_t *send_key,
+			      pj_ssize_t sent);
 static pj_bool_t on_connect_complete(pj_turn_sock *turn_sock,
 				     pj_status_t status);
@@ -149,4 +160,7 @@
 				    pj_status_t status,
 				    pj_size_t *remainder);
+static pj_bool_t on_data_sent_asock(pj_activesock_t *asock,
+			      	     pj_ioqueue_op_key_t *send_key,
+			      	     pj_ssize_t sent);
 
 /*
@@ -168,4 +182,7 @@
 				       pj_status_t status,
 				       pj_size_t *remainder);
+static pj_bool_t dataconn_on_data_sent(pj_activesock_t *asock,
+			      	       pj_ioqueue_op_key_t *send_key,
+			      	       pj_ssize_t sent);
 static pj_bool_t dataconn_on_connect_complete(pj_activesock_t *asock,
 					      pj_status_t status);
@@ -328,4 +345,5 @@
     pj_bzero(&sess_cb, sizeof(sess_cb));
     sess_cb.on_send_pkt = &turn_on_send_pkt;
+    sess_cb.on_stun_send_pkt = &turn_on_stun_send_pkt;
     sess_cb.on_channel_bound = &turn_on_channel_bound;
     sess_cb.on_rx_data = &turn_on_rx_data;
@@ -628,4 +646,8 @@
 	return PJ_EINVALIDOP;
 
+    /* TURN session may add some headers to the packet, so we need
+     * to store our actual data length to be sent here.
+     */
+    turn_sock->body_len = pkt_len;
     return pj_turn_session_sendto(turn_sock->sess, pkt, pkt_len, 
 				  addr, addr_len);
@@ -694,4 +716,6 @@
     /* Init send_key */
     pj_ioqueue_op_key_init(&turn_sock->send_key, sizeof(turn_sock->send_key));
+    pj_ioqueue_op_key_init(&turn_sock->int_send_key,
+    			   sizeof(turn_sock->int_send_key));
 
     /* Send Allocate request */
@@ -861,4 +885,38 @@
 }
 
+static pj_bool_t on_data_sent(pj_turn_sock *turn_sock,
+			      pj_ioqueue_op_key_t *send_key,
+			      pj_ssize_t sent)
+{
+    unsigned header_len, sent_size;
+
+    /* Don't report to callback if this is internal message. */
+    if (send_key == &turn_sock->int_send_key) {
+	return PJ_TRUE;
+    }
+
+    if (turn_sock->cb.on_data_sent) {
+        /* Remove the length of packet header from sent size. */
+	header_len = turn_sock->pkt_len - turn_sock->body_len;
+	sent_size = (sent > header_len)? (sent - header_len) : 0;
+	(*turn_sock->cb.on_data_sent)(turn_sock, sent_size);
+    }
+
+    return PJ_TRUE;
+}
+
+
+static pj_bool_t on_data_sent_asock(pj_activesock_t *asock,
+			      	     pj_ioqueue_op_key_t *send_key,
+			      	     pj_ssize_t sent)
+{
+    pj_turn_sock *turn_sock;
+
+    turn_sock = (pj_turn_sock*)pj_activesock_get_user_data(asock);
+
+    return on_data_sent(turn_sock, send_key, sent);
+}
+
+
 #if PJ_HAS_SSL_SOCK
 static pj_bool_t on_data_read_ssl_sock(pj_ssl_sock_t *ssl_sock,
@@ -897,16 +955,15 @@
     }
 
-    return PJ_TRUE;
+    return on_data_sent(turn_sock, op_key, bytes_sent);
 }
 #endif
 
-/*
- * Callback from TURN session to send outgoing packet.
- */
-static pj_status_t turn_on_send_pkt(pj_turn_session *sess,
-				    const pj_uint8_t *pkt,
-				    unsigned pkt_len,
-				    const pj_sockaddr_t *dst_addr,
-				    unsigned dst_addr_len)
+
+static pj_status_t send_pkt(pj_turn_session *sess,
+			    pj_bool_t internal,
+			    const pj_uint8_t *pkt,
+			    unsigned pkt_len,
+			    const pj_sockaddr_t *dst_addr,
+			    unsigned dst_addr_len)
 {
     pj_turn_sock *turn_sock = (pj_turn_sock*) 
@@ -914,4 +971,5 @@
     pj_ssize_t len = pkt_len;
     pj_status_t status = PJ_SUCCESS;
+    pj_ioqueue_key_t *send_key = &turn_sock->send_key;
 
     if (turn_sock == NULL || turn_sock->is_destroying) {
@@ -922,7 +980,11 @@
     }
 
+    if (internal)
+    	send_key = &turn_sock->int_send_key;
+    turn_sock->pkt_len = pkt_len;
+
     if (turn_sock->conn_type == PJ_TURN_TP_UDP) {
 	status = pj_activesock_sendto(turn_sock->active_sock,
-				      &turn_sock->send_key, pkt, &len, 0,
+				      send_key, pkt, &len, 0,
 				      dst_addr, dst_addr_len);
     } else if (turn_sock->alloc_param.peer_conn_type == PJ_TURN_TP_TCP) {
@@ -932,5 +994,5 @@
 	    /* Destination address is TURN server */
 	    status = pj_activesock_send(turn_sock->active_sock,
-					&turn_sock->send_key, pkt, &len, 0);
+					send_key, pkt, &len, 0);
 	} else {
 	    /* Destination address is peer, lookup data connection */
@@ -952,10 +1014,10 @@
     } else  if (turn_sock->conn_type == PJ_TURN_TP_TCP) {
 	status = pj_activesock_send(turn_sock->active_sock,
-				    &turn_sock->send_key, pkt, &len, 0);
+				    send_key, pkt, &len, 0);
     }
 #if PJ_HAS_SSL_SOCK
     else if (turn_sock->conn_type == PJ_TURN_TP_TLS) {
 	status = pj_ssl_sock_send(turn_sock->ssl_sock,
-				  &turn_sock->send_key, pkt, &len, 0);
+				  send_key, pkt, &len, 0);
     }
 #endif
@@ -969,4 +1031,28 @@
 
     return status;
+}
+
+
+/*
+ * Callback from TURN session to send outgoing packet.
+ */
+static pj_status_t turn_on_send_pkt(pj_turn_session *sess,
+				    const pj_uint8_t *pkt,
+				    unsigned pkt_len,
+				    const pj_sockaddr_t *dst_addr,
+				    unsigned dst_addr_len)
+{
+    return send_pkt(sess, PJ_FALSE, pkt, pkt_len,
+    		    dst_addr, dst_addr_len);
+}
+
+static pj_status_t turn_on_stun_send_pkt(pj_turn_session *sess,
+				    	 const pj_uint8_t *pkt,
+				    	 unsigned pkt_len,
+				    	 const pj_sockaddr_t *dst_addr,
+				    	 unsigned dst_addr_len)
+{
+    return send_pkt(sess, PJ_TRUE, pkt, pkt_len,
+    		    dst_addr, dst_addr_len);
 }
 
@@ -1170,4 +1256,5 @@
 	    pj_bzero(&asock_cb, sizeof(asock_cb));
 	    asock_cb.on_data_read = &on_data_read_asock;
+	    asock_cb.on_data_sent = &on_data_sent_asock;
 	    asock_cb.on_connect_complete = &on_connect_complete_asock;
 	    status = pj_activesock_create(turn_sock->pool, sock,
@@ -1399,4 +1486,15 @@
 }
 
+static pj_bool_t dataconn_on_data_sent(pj_activesock_t *asock,
+			      	       pj_ioqueue_op_key_t *send_key,
+			      	       pj_ssize_t sent)
+{
+    tcp_data_conn_t *conn = (tcp_data_conn_t*)
+			    pj_activesock_get_user_data(asock);
+    pj_turn_sock *turn_sock = conn->turn_sock;
+
+    return on_data_sent(turn_sock, send_key, sent);
+}
+
 static pj_bool_t dataconn_on_connect_complete(pj_activesock_t *asock,
 					      pj_status_t status)
@@ -1577,4 +1675,5 @@
     pj_bzero(&asock_cb, sizeof(asock_cb));
     asock_cb.on_data_read = &dataconn_on_data_read;
+    asock_cb.on_data_sent = &dataconn_on_data_sent;
     asock_cb.on_connect_complete = &dataconn_on_connect_complete;
     status = pj_activesock_create(pool, sock,
