diff --git a/contrib/src/pjproject/fetch_and_patch.bat b/contrib/src/pjproject/fetch_and_patch.bat
index 5cb61f566533a237f3befcb7a531d02eb8130260..dc3aa889f03bb8eaaf416ae376d778469a384a23 100644
--- a/contrib/src/pjproject/fetch_and_patch.bat
+++ b/contrib/src/pjproject/fetch_and_patch.bat
@@ -35,6 +35,7 @@ bash -c "%PATCH_CMD% %UNIXPATH%pjproject/fix_ioqueue_ipv6_sendto.patch"
 bash -c "%PATCH_CMD% %UNIXPATH%pjproject/add_dtls_transport.patch"
 bash -c "%PATCH_CMD% %UNIXPATH%pjproject/rfc6544.patch"
 bash -c "%PATCH_CMD% %UNIXPATH%pjproject/ice_config.patch"
+bash -c "%PATCH_CMD% %UNIXPATH%pjproject/fix_first_packet_turn_tcp.patch"
 
 %APPLY_CMD% %SRC%\pjproject\win32_vs_gnutls.patch
 %APPLY_CMD% %SRC%\pjproject\win_config.patch
diff --git a/contrib/src/pjproject/fix_first_packet_turn_tcp.patch b/contrib/src/pjproject/fix_first_packet_turn_tcp.patch
new file mode 100644
index 0000000000000000000000000000000000000000..dbedf6a1512025699c52962cc3421fd6f0f1835a
--- /dev/null
+++ b/contrib/src/pjproject/fix_first_packet_turn_tcp.patch
@@ -0,0 +1,79 @@
+ pjnath/src/pjnath/turn_sock.c | 64 +++++++++++++++++++++++++++++++++-------------------------------
+ 1 file changed, 33 insertions(+), 31 deletions(-)
+
+diff --git a/pjnath/src/pjnath/turn_sock.c b/pjnath/src/pjnath/turn_sock.c
+index 7033fd93..6a3a3e31 100644
+--- a/pjnath/src/pjnath/turn_sock.c
++++ b/pjnath/src/pjnath/turn_sock.c
+@@ -1052,38 +1052,40 @@ static pj_bool_t dataconn_on_data_read(pj_activesock_t *asock,
+ 	return PJ_FALSE;
+     }
+ 
+-    if (conn->state == DATACONN_STATE_READY) {
+-	/* Application data */
+-	if (turn_sock->cb.on_rx_data) {
+-	    (*turn_sock->cb.on_rx_data)(turn_sock, data, size,
+-					&conn->peer_addr,
+-					conn->peer_addr_len);
++	*remainder = size;
++	while (*remainder > 0) {
++		if (conn->state == DATACONN_STATE_READY) {
++			/* Application data */
++			if (turn_sock->cb.on_rx_data) {
++				(*turn_sock->cb.on_rx_data)(turn_sock, data, *remainder,
++							&conn->peer_addr,
++							conn->peer_addr_len);
++			}
++			*remainder = 0;
++		} else if (conn->state == DATACONN_STATE_CONN_BINDING) {
++			/* Waiting for ConnectionBind response */
++			pj_bool_t is_stun;
++			pj_turn_session_on_rx_pkt_param prm;
++				
++			/* Ignore if this is not a STUN message */
++			is_stun = ((((pj_uint8_t*)data)[0] & 0xC0) == 0);
++			if (!is_stun)
++				goto on_return;
++
++			pj_bzero(&prm, sizeof(prm));
++			prm.pkt = data;
++			prm.pkt_len = *remainder;
++			prm.src_addr = &conn->peer_addr;
++			prm.src_addr_len = conn->peer_addr_len;
++			pj_turn_session_on_rx_pkt2(conn->turn_sock->sess, &prm);
++			/* Got remainder? */
++			if (prm.parsed_len < *remainder && prm.parsed_len > 0) {
++				pj_memmove(data, (pj_uint8_t*)data+prm.parsed_len, *remainder);
++			}
++			*remainder -= prm.parsed_len;
++		} else
++			goto on_return;
+ 	}
+-    } else if (conn->state == DATACONN_STATE_CONN_BINDING) {
+-	/* Waiting for ConnectionBind response */
+-	pj_bool_t is_stun;
+-	pj_turn_session_on_rx_pkt_param prm;
+-        
+-	/* Ignore if this is not a STUN message */
+-	is_stun = ((((pj_uint8_t*)data)[0] & 0xC0) == 0);
+-	if (!is_stun)
+-	    goto on_return;
+-
+-	pj_bzero(&prm, sizeof(prm));
+-	prm.pkt = data;
+-	prm.pkt_len = size;
+-	prm.src_addr = &conn->peer_addr;
+-	prm.src_addr_len = conn->peer_addr_len;
+-	pj_turn_session_on_rx_pkt2(conn->turn_sock->sess, &prm);
+-	/* Got remainder? */
+-	if (prm.parsed_len < size) {
+-	    *remainder = size - prm.parsed_len;
+-	    if (prm.parsed_len) {
+-		pj_memmove(data, (pj_uint8_t*)data+prm.parsed_len,
+-			   *remainder);
+-	    }
+-	}
+-    }
+ 
+ on_return:
+     pj_grp_lock_release(turn_sock->grp_lock);
diff --git a/contrib/src/pjproject/rules.mak b/contrib/src/pjproject/rules.mak
index 4f65de345c5dbc81aa4f9165f856ed67dbfa04f3..b37cc90a7a08e1ef1001fdef7535b5fa762e11e2 100644
--- a/contrib/src/pjproject/rules.mak
+++ b/contrib/src/pjproject/rules.mak
@@ -64,6 +64,7 @@ endif
 	$(APPLY) $(SRC)/pjproject/rfc6544.patch
 	$(APPLY) $(SRC)/pjproject/ice_config.patch
 	$(APPLY) $(SRC)/pjproject/sip_config.patch
+	$(APPLY) $(SRC)/pjproject/fix_first_packet_turn_tcp.patch
 	$(UPDATE_AUTOCONFIG)
 	$(MOVE)
 
diff --git a/src/turn_transport.cpp b/src/turn_transport.cpp
index 024141e8f1f26c6762ffe6dce6ca2572b4b50858..7546bf3d754d8c7dcd17a38a672557cd958e7a23 100644
--- a/src/turn_transport.cpp
+++ b/src/turn_transport.cpp
@@ -162,7 +162,7 @@ public:
 
     void onTurnState(pj_turn_state_t old_state, pj_turn_state_t new_state);
     void onRxData(const uint8_t* pkt, unsigned pkt_len, const pj_sockaddr_t* peer_addr, unsigned addr_len);
-    pj_status_t onPeerConnection(pj_uint32_t conn_id, const pj_sockaddr_t* peer_addr, unsigned addr_len);
+    void onPeerConnection(pj_uint32_t conn_id, const pj_sockaddr_t* peer_addr, unsigned addr_len, pj_status_t status);
     void ioJob();
 
     std::mutex apiMutex_;
@@ -238,22 +238,24 @@ TurnTransportPimpl::onRxData(const uint8_t* pkt, unsigned pkt_len,
         (channel_it->second) << std::string(reinterpret_cast<const char*>(pkt), pkt_len);
 }
 
-pj_status_t
+void
 TurnTransportPimpl::onPeerConnection(pj_uint32_t conn_id,
-                                     const pj_sockaddr_t* addr, unsigned addr_len)
+                                     const pj_sockaddr_t* addr, unsigned addr_len,
+                                     pj_status_t status)
 {
     IpAddr peer_addr (*static_cast<const pj_sockaddr*>(addr), addr_len);
-    JAMI_DBG() << "Received connection attempt from "
-                << peer_addr.toString(true, true) << ", id=" << std::hex
-                << conn_id;
-    {
-        MutexGuard lk {apiMutex_};
-        peerChannels_.emplace(peer_addr, PeerChannel {});
+    if (status == PJ_SUCCESS) {
+        JAMI_DBG() << "Received connection attempt from "
+                    << peer_addr.toString(true, true) << ", id=" << std::hex
+                    << conn_id;
+        {
+            MutexGuard lk {apiMutex_};
+            peerChannels_.emplace(peer_addr, PeerChannel {});
+        }
     }
 
     if (settings.onPeerConnection)
-        settings.onPeerConnection(conn_id, peer_addr, true);
-    return PJ_SUCCESS;
+        settings.onPeerConnection(conn_id, peer_addr, status == PJ_SUCCESS);
 }
 
 void
@@ -314,12 +316,13 @@ TurnTransport::TurnTransport(const TurnTransportParams& params)
         auto pimpl = static_cast<TurnTransportPimpl*>(pj_turn_sock_get_user_data(relay));
         pimpl->onTurnState(old_state, new_state);
     };
-    relay_cb.on_connection_attempt = [](pj_turn_sock *relay,
+    relay_cb.on_connection_status = [](pj_turn_sock *relay,
+                                        pj_status_t status,
                                         pj_uint32_t conn_id,
                                         const pj_sockaddr_t *peer_addr,
                                         unsigned addr_len) {
       auto pimpl = static_cast<TurnTransportPimpl *>(pj_turn_sock_get_user_data(relay));
-      return pimpl->onPeerConnection(conn_id, peer_addr, addr_len);
+      pimpl->onPeerConnection(conn_id, peer_addr, addr_len, status);
     };
 
     // TURN socket config