summaryrefslogtreecommitdiff
path: root/pjnath
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-08-22 17:46:33 +0000
committerBenny Prijono <bennylp@teluu.com>2008-08-22 17:46:33 +0000
commitbec19e0d3c8fd02ead56676fa540bba024e10113 (patch)
treed7e65d3245c9aa3bfaf7c9c9b9dcf12b961ac1e7 /pjnath
parent3329e6261fba0e1fb9e4e8b23805945683101122 (diff)
Ticket #598: Update to draft-ietf-behave-rfc3489bis-18 and draft-ietf-behave-turn-09, and fix other things as well. Please see the ticket for more info
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2234 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjnath')
-rw-r--r--pjnath/include/pjnath/stun_msg.h84
-rw-r--r--pjnath/include/pjnath/turn_session.h9
-rw-r--r--pjnath/include/pjnath/types.h8
-rw-r--r--pjnath/src/pjnath-test/server.c4
-rw-r--r--pjnath/src/pjnath-test/stun.c2
-rw-r--r--pjnath/src/pjnath/stun_msg.c87
-rw-r--r--pjnath/src/pjnath/stun_msg_dump.c6
-rw-r--r--pjnath/src/pjnath/stun_session.c4
-rw-r--r--pjnath/src/pjnath/stun_transaction.c41
-rw-r--r--pjnath/src/pjnath/turn_session.c75
-rw-r--r--pjnath/src/pjnath/turn_sock.c11
-rw-r--r--pjnath/src/pjturn-srv/allocation.c2
-rw-r--r--pjnath/src/pjturn-srv/listener_udp.c5
-rw-r--r--pjnath/src/pjturn-srv/server.c45
14 files changed, 292 insertions, 91 deletions
diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h
index a122ba87..895035c6 100644
--- a/pjnath/include/pjnath/stun_msg.h
+++ b/pjnath/include/pjnath/stun_msg.h
@@ -290,12 +290,12 @@ typedef enum pj_stun_attr_type
PJ_STUN_ATTR_CHANNEL_NUMBER = 0x000C,/**< TURN CHANNEL-NUMBER */
PJ_STUN_ATTR_LIFETIME = 0x000D,/**< TURN LIFETIME attr. */
PJ_STUN_ATTR_MAGIC_COOKIE = 0x000F,/**< MAGIC-COOKIE attr (deprec)*/
- PJ_STUN_ATTR_BANDWIDTH = 0x0010,/**< TURN BANDWIDTH attr. */
+ PJ_STUN_ATTR_BANDWIDTH = 0x0010,/**< TURN BANDWIDTH (deprec) */
PJ_STUN_ATTR_PEER_ADDR = 0x0012,/**< TURN PEER-ADDRESS attr. */
PJ_STUN_ATTR_DATA = 0x0013,/**< DATA attribute. */
PJ_STUN_ATTR_REALM = 0x0014,/**< REALM attribute. */
PJ_STUN_ATTR_NONCE = 0x0015,/**< NONCE attribute. */
- PJ_STUN_ATTR_RELAY_ADDR = 0x0016,/**< RELAY-ADDRESS attribute. */
+ PJ_STUN_ATTR_RELAYED_ADDR = 0x0016,/**< RELAYED-ADDRESS attribute.*/
PJ_STUN_ATTR_REQ_ADDR_TYPE = 0x0017,/**< REQUESTED-ADDRESS-TYPE */
PJ_STUN_ATTR_REQ_PROPS = 0x0018,/**< REQUESTED-PROPS */
PJ_STUN_ATTR_REQ_TRANSPORT = 0x0019,/**< REQUESTED-TRANSPORT */
@@ -305,13 +305,13 @@ typedef enum pj_stun_attr_type
PJ_STUN_ATTR_XOR_REFLECTED_FROM = 0x0023,/**< XOR-REFLECTED-FROM */
PJ_STUN_ATTR_PRIORITY = 0x0024,/**< PRIORITY */
PJ_STUN_ATTR_USE_CANDIDATE = 0x0025,/**< USE-CANDIDATE */
- PJ_STUN_ATTR_XOR_INTERNAL_ADDR = 0x0026,/**< XOR-INTERNAL-ADDRESS */
+ PJ_STUN_ATTR_ICMP = 0x0030,/**< ICMP (TURN) */
PJ_STUN_ATTR_END_MANDATORY_ATTR,
PJ_STUN_ATTR_START_EXTENDED_ATTR= 0x8021,
- PJ_STUN_ATTR_SERVER = 0x8022,/**< SERVER attribute. */
+ PJ_STUN_ATTR_SOFTWARE = 0x8022,/**< SOFTWARE attribute. */
PJ_STUN_ATTR_ALTERNATE_SERVER = 0x8023,/**< ALTERNATE-SERVER. */
PJ_STUN_ATTR_REFRESH_INTERVAL = 0x8024,/**< REFRESH-INTERVAL. */
PJ_STUN_ATTR_FINGERPRINT = 0x8028,/**< FINGERPRINT attribute. */
@@ -345,6 +345,7 @@ typedef enum pj_stun_status
PJ_STUN_SC_ALLOCATION_MISMATCH = 437, /**< TURN Alloc Mismatch */
PJ_STUN_SC_STALE_NONCE = 438, /**< Stale Nonce */
PJ_STUN_SC_TRANSITIONING = 439, /**< Transitioning. */
+ PJ_STUN_SC_WRONG_CREDENTIALS = 441, /**< TURN Wrong Credentials */
PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO = 442, /**< Unsupported Transport or
Protocol (TURN) */
PJ_STUN_SC_INVALID_IP_ADDR = 443, /**< Invalid IP Address(TURN)*/
@@ -514,8 +515,7 @@ typedef struct pj_stun_empty_attr
/**
* This structure represents generic STUN string attributes, such as STUN
- * USERNAME, PASSWORD, SERVER, REALM, and NONCE attributes. Note that for REALM and
- * NONCE attributes, the text MUST be quoted with.
+ * USERNAME, PASSWORD, SOFTWARE, REALM, and NONCE attributes.
*/
typedef struct pj_stun_string_attr
{
@@ -739,14 +739,12 @@ typedef struct pj_stun_sockaddr_attr pj_stun_xor_mapped_addr_attr;
/**
- * This describes STUN SERVER attribute.
- * The server attribute contains a textual description of the software
- * being used by the server, including manufacturer and version number.
- * The attribute has no impact on operation of the protocol, and serves
- * only as a tool for diagnostic and debugging purposes. The value of
- * SERVER is variable length.
- */
-typedef struct pj_stun_string_attr pj_stun_server_attr;
+ * This describes STUN SOFTWARE attribute.
+ * The SOFTWARE attribute contains a textual description of the software
+ * being used by the agent sending the message. It is used by clients
+ * and servers. Its value SHOULD include manufacturer and version
+ * number. */
+typedef struct pj_stun_string_attr pj_stun_software_attr;
/**
@@ -932,12 +930,12 @@ typedef struct pj_stun_binary_attr pj_stun_data_attr;
/**
- * This describes the STUN RELAY-ADDRESS attribute.
- * The RELAY-ADDRESS is present in Allocate responses. It specifies the
+ * This describes the STUN RELAYED-ADDRESS attribute.
+ * The RELAYED-ADDRESS is present in Allocate responses. It specifies the
* address and port that the server allocated to the client. It is
* encoded in the same way as XOR-MAPPED-ADDRESS.
*/
-typedef struct pj_stun_sockaddr_attr pj_stun_relay_addr_attr;
+typedef struct pj_stun_sockaddr_attr pj_stun_relayed_addr_attr;
/**
@@ -964,9 +962,9 @@ typedef struct pj_stun_uint_attr pj_stun_req_addr_type;
* the values in this attribute: #PJ_STUN_GET_PROP_TYPE(), and
* #PJ_STUN_SET_PROP_TYPE().
*
- * This attribute allows the client to request certain properties for
- * the relayed transport address that is allocated by the server. The
- * attribute is 32 bits long. Its format is:
+ * This attribute allows the client to request that the allocation have
+ * certain properties, and by the server to indicate which properties
+ * are supported. The attribute is 32 bits long. Its format is:
\verbatim
@@ -981,11 +979,32 @@ typedef struct pj_stun_uint_attr pj_stun_req_addr_type;
* The field labeled "Prop-type" is an 8-bit field specifying the
* desired property. The rest of the attribute is RFFU (Reserved For
* Future Use) and MUST be set to 0 on transmission and ignored on
- * reception. The values of the "Prop-type" field are:
- *
- * 0x00 (Reserved)
- * 0x01 Even port number
- * 0x02 Pair of ports
+ * reception.
+ *
+ * The "Prop-type" field is formatted as follows:
+
+ \verbatim
+
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |E|R|P| |
+ +-+-+-+-+-+-+-+-+
+
+ \endverbatim
+
+ The bits in "Prop-type" are:
+
+ E: If 1, the port number for the relayed-transport-address must be
+ even. If 0, the port number can be even or odd.
+
+ R: If 1, the server must reserve the next highest port for a
+ subsequent allocation. If 0, no such reservation is requested.
+ If the client sets the R bit to 1, it MUST also set the E bit to 1
+ (however, the E bit may be 1 when the R bit is 0).
+
+ P: If 1, the allocation must be a Preserving allocation. If 0, the
+ allocation can be either Preserving or Non-Preserving.
+
*/
typedef struct pj_stun_uint_attr pj_stun_req_props_attr;
@@ -1090,16 +1109,6 @@ typedef struct pj_stun_uint_attr pj_stun_priority_attr;
typedef struct pj_stun_empty_attr pj_stun_use_candidate_attr;
/**
- * This structure describes STUN XOR-INTERNAL-ADDRESS attribute from
- * draft-wing-behave-nat-control-stun-usage-00.
- * This attribute MUST be present in a Binding Response and may be used
- * in other responses as well. This attribute is necessary to allow a
- * STUN client to 'walk backwards' and communicate directly with all of
- * the STUN-aware NATs along the path.
- */
-typedef pj_stun_sockaddr_attr pj_stun_xor_internal_addr_attr;
-
-/**
* This describes the STUN TIMER-VAL attribute.
* The TIMER-VAL attribute is used only in conjunction with the Set
* Active Destination response. It conveys from the server, to the
@@ -1118,6 +1127,11 @@ typedef struct pj_stun_uint64_attr pj_stun_ice_controlling_attr;
typedef struct pj_stun_uint64_attr pj_stun_ice_controlled_attr;
/**
+ * This describes TURN ICMP attribute
+ */
+typedef struct pj_stun_uint_attr pj_stun_icmp_attr;
+
+/**
* This structure describes a parsed STUN message. All integral fields
* in this structure (including IP addresses) will be in the host
* byte order.
diff --git a/pjnath/include/pjnath/turn_session.h b/pjnath/include/pjnath/turn_session.h
index 73be679c..b577e02a 100644
--- a/pjnath/include/pjnath/turn_session.h
+++ b/pjnath/include/pjnath/turn_session.h
@@ -236,7 +236,9 @@ typedef struct pj_turn_alloc_param
{
/**
* The requested BANDWIDTH. Default is zero to not request any
- * specific bandwidth.
+ * specific bandwidth. Note that this attribute has been deprecated
+ * after TURN-08 draft, hence application should only use this
+ * attribute when talking to TURN-07 or older version.
*/
int bandwidth;
@@ -581,6 +583,8 @@ PJ_DECL(pj_status_t) pj_turn_session_bind_channel(pj_turn_session *sess,
* should contain either STUN encapsulated message or
* a ChannelData packet.
* @param pkt_len The length of the packet.
+ * @param parsed_len Optional argument to receive the number of parsed
+ * or processed data from the packet.
*
* @return The function may return non-PJ_SUCCESS if it receives
* non-STUN and non-ChannelData packet, or if the
@@ -588,7 +592,8 @@ PJ_DECL(pj_status_t) pj_turn_session_bind_channel(pj_turn_session *sess,
*/
PJ_DECL(pj_status_t) pj_turn_session_on_rx_pkt(pj_turn_session *sess,
void *pkt,
- unsigned pkt_len);
+ unsigned pkt_len,
+ unsigned *parsed_len);
/**
diff --git a/pjnath/include/pjnath/types.h b/pjnath/include/pjnath/types.h
index 66ab4cdd..b1012977 100644
--- a/pjnath/include/pjnath/types.h
+++ b/pjnath/include/pjnath/types.h
@@ -97,8 +97,8 @@ to determine the IP address and port allocated to them by a NAT and to
keep NAT bindings open.
This version of PJNATH implements the following STUN-bis draft:
-- <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-15.txt">
- <B>draft-ietf-behave-rfc3489bis-15</b></A>: Session Traversal
+- <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-18.txt">
+ <B>draft-ietf-behave-rfc3489bis-18</b></A>: Session Traversal
Utilities for (NAT) (STUN),
@@ -109,8 +109,8 @@ operation of the relay and to exchange packets with its peers using the relay.
This version of PJNATH implements both TCP and UDP client transport and it
complies with the following TURN draft:
- - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-07.txt">
- <B>draft-ietf-behave-turn-07</B></A>: Obtaining Relay Addresses
+ - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-09.txt">
+ <B>draft-ietf-behave-turn-09</B></A>: Obtaining Relay Addresses
from Simple Traversal Underneath NAT (STUN)
diff --git a/pjnath/src/pjnath-test/server.c b/pjnath/src/pjnath-test/server.c
index 466b3a3d..360e17ce 100644
--- a/pjnath/src/pjnath-test/server.c
+++ b/pjnath/src/pjnath-test/server.c
@@ -309,8 +309,8 @@ static pj_stun_msg* create_success_response(test_server *test_srv,
/* Add LIFETIME */
pj_stun_msg_add_uint_attr(pool, resp, PJ_STUN_ATTR_LIFETIME, lifetime);
if (lifetime != 0) {
- /* Add RELAY-ADDRESS */
- pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE, &alloc->alloc_addr,
+ /* Add RELAYED-ADDRESS */
+ pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_RELAYED_ADDR, PJ_TRUE, &alloc->alloc_addr,
pj_sockaddr_get_len(&alloc->alloc_addr));
/* Add XOR-MAPPED-ADDRESS */
pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, &alloc->client_addr,
diff --git a/pjnath/src/pjnath-test/stun.c b/pjnath/src/pjnath-test/stun.c
index 71775f6b..5d157053 100644
--- a/pjnath/src/pjnath-test/stun.c
+++ b/pjnath/src/pjnath-test/stun.c
@@ -694,7 +694,7 @@ static pj_stun_msg* create_msgint2(pj_pool_t *pool, test_vector *v)
pj_stun_msg_create(pool, v->msg_type, PJ_STUN_MAGIC,
(pj_uint8_t*)v->tsx_id, &msg);
- pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER,
+ pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE,
pj_cstr(&s1, "test vector"));
pj_sockaddr_in_init(&mapped_addr, pj_cstr(&s1, "127.0.0.1"), 32853);
diff --git a/pjnath/src/pjnath/stun_msg.c b/pjnath/src/pjnath/stun_msg.c
index 42df8c38..0d8c5c59 100644
--- a/pjnath/src/pjnath/stun_msg.c
+++ b/pjnath/src/pjnath/stun_msg.c
@@ -66,6 +66,7 @@ static struct
{ PJ_STUN_SC_ALLOCATION_MISMATCH, "Allocation Mismatch"},
{ PJ_STUN_SC_STALE_NONCE, "Stale Nonce"},
{ PJ_STUN_SC_TRANSITIONING, "Active Destination Already Set"},
+ { PJ_STUN_SC_WRONG_CREDENTIALS, "Wrong Credentials"},
{ PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, "Unsupported Transport Protocol"},
{ PJ_STUN_SC_INVALID_IP_ADDR, "Invalid IP Address"},
{ PJ_STUN_SC_INVALID_PORT, "Invalid Port"},
@@ -309,7 +310,7 @@ static struct attr_desc mandatory_attr_desc[] =
},
{
/* PJ_STUN_ATTR_RELAY_ADDRESS, */
- "RELAY-ADDRESS",
+ "RELAYED-ADDRESS",
&decode_xored_sockaddr_attr,
&encode_sockaddr_attr,
&clone_sockaddr_attr
@@ -420,11 +421,81 @@ static struct attr_desc mandatory_attr_desc[] =
&clone_empty_attr
},
{
- /* PJ_STUN_ATTR_XOR_INTERNAL_ADDR, */
- "XOR-INTERNAL-ADDRESS",
- &decode_xored_sockaddr_attr,
- &encode_sockaddr_attr,
- &clone_sockaddr_attr
+ /* ID 0x0026 is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x0027 is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x0028 is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x0029 is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x002a is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x002b is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x002c is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x002d is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x002e is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* ID 0x002f is not assigned */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ /* PJ_STUN_ATTR_ICMP, */
+ "ICMP",
+ &decode_uint_attr,
+ &encode_uint_attr,
+ &clone_uint_attr
},
/* Sentinel */
@@ -447,8 +518,8 @@ static struct attr_desc extended_attr_desc[] =
NULL
},
{
- /* PJ_STUN_ATTR_SERVER, */
- "SERVER",
+ /* PJ_STUN_ATTR_SOFTWARE, */
+ "SOFTWARE",
&decode_string_attr,
&encode_string_attr,
&clone_string_attr
diff --git a/pjnath/src/pjnath/stun_msg_dump.c b/pjnath/src/pjnath/stun_msg_dump.c
index a5556acc..8b6310a8 100644
--- a/pjnath/src/pjnath/stun_msg_dump.c
+++ b/pjnath/src/pjnath/stun_msg_dump.c
@@ -72,10 +72,9 @@ static int print_attr(char *buffer, unsigned length,
case PJ_STUN_ATTR_CHANGED_ADDR:
case PJ_STUN_ATTR_REFLECTED_FROM:
case PJ_STUN_ATTR_PEER_ADDR:
- case PJ_STUN_ATTR_RELAY_ADDR:
+ case PJ_STUN_ATTR_RELAYED_ADDR:
case PJ_STUN_ATTR_XOR_MAPPED_ADDR:
case PJ_STUN_ATTR_XOR_REFLECTED_FROM:
- case PJ_STUN_ATTR_XOR_INTERNAL_ADDR:
case PJ_STUN_ATTR_ALTERNATE_SERVER:
{
const pj_stun_sockaddr_attr *attr;
@@ -122,6 +121,7 @@ static int print_attr(char *buffer, unsigned length,
case PJ_STUN_ATTR_PRIORITY:
case PJ_STUN_ATTR_FINGERPRINT:
case PJ_STUN_ATTR_REFRESH_INTERVAL:
+ case PJ_STUN_ATTR_ICMP:
{
const pj_stun_uint_attr *attr;
@@ -138,7 +138,7 @@ static int print_attr(char *buffer, unsigned length,
case PJ_STUN_ATTR_PASSWORD:
case PJ_STUN_ATTR_REALM:
case PJ_STUN_ATTR_NONCE:
- case PJ_STUN_ATTR_SERVER:
+ case PJ_STUN_ATTR_SOFTWARE:
{
const pj_stun_string_attr *attr;
diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c
index bec02ca3..35c982f4 100644
--- a/pjnath/src/pjnath/stun_session.c
+++ b/pjnath/src/pjnath/stun_session.c
@@ -216,9 +216,9 @@ static pj_status_t apply_msg_options(pj_stun_session *sess,
pj_status_t status = 0;
pj_str_t realm, username, nonce, auth_key;
- /* The server SHOULD include a SERVER attribute in all responses */
+ /* The server SHOULD include a SOFTWARE attribute in all responses */
if (sess->srv_name.slen && PJ_STUN_IS_RESPONSE(msg->hdr.type)) {
- pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER,
+ pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE,
&sess->srv_name);
}
diff --git a/pjnath/src/pjnath/stun_transaction.c b/pjnath/src/pjnath/stun_transaction.c
index 1242dfe7..9942d83b 100644
--- a/pjnath/src/pjnath/stun_transaction.c
+++ b/pjnath/src/pjnath/stun_transaction.c
@@ -251,6 +251,8 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx,
void *pkt,
unsigned pkt_len)
{
+ pj_status_t status;
+
PJ_ASSERT_RETURN(tsx && pkt && pkt_len, PJ_EINVAL);
PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY);
@@ -261,8 +263,45 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx,
/* Update STUN retransmit flag */
tsx->require_retransmit = retransmit;
+ /* For TCP, schedule timeout timer after PJ_STUN_TIMEOUT_VALUE.
+ * Since we don't have timeout timer, simulate this by using
+ * retransmit timer.
+ */
+ if (!retransmit) {
+ unsigned timeout;
+
+ pj_assert(tsx->retransmit_timer.id == 0);
+ tsx->transmit_count = PJ_STUN_MAX_TRANSMIT_COUNT;
+
+ timeout = tsx->rto_msec * 16;
+ tsx->retransmit_time.sec = timeout / 1000;
+ tsx->retransmit_time.msec = timeout % 1000;
+
+ /* Schedule timer first because when send_msg() failed we can
+ * cancel it (as opposed to when schedule_timer() failed we cannot
+ * cancel transmission).
+ */;
+ status = pj_timer_heap_schedule(tsx->timer_heap,
+ &tsx->retransmit_timer,
+ &tsx->retransmit_time);
+ if (status != PJ_SUCCESS) {
+ tsx->retransmit_timer.id = 0;
+ return status;
+ }
+ }
+
/* Send the message */
- return tsx_transmit_msg(tsx);
+ status = tsx_transmit_msg(tsx);
+ if (status != PJ_SUCCESS) {
+ if (tsx->retransmit_timer.id != 0) {
+ pj_timer_heap_cancel(tsx->timer_heap,
+ &tsx->retransmit_timer);
+ tsx->retransmit_timer.id = 0;
+ }
+ return status;
+ }
+
+ return PJ_SUCCESS;
}
diff --git a/pjnath/src/pjnath/turn_session.c b/pjnath/src/pjnath/turn_session.c
index 8f50d820..ad3d99ab 100644
--- a/pjnath/src/pjnath/turn_session.c
+++ b/pjnath/src/pjnath/turn_session.c
@@ -914,7 +914,8 @@ on_return:
*/
PJ_DEF(pj_status_t) pj_turn_session_on_rx_pkt(pj_turn_session *sess,
void *pkt,
- unsigned pkt_len)
+ unsigned pkt_len,
+ unsigned *parsed_len)
{
pj_bool_t is_stun;
pj_status_t status;
@@ -940,47 +941,58 @@ PJ_DEF(pj_status_t) pj_turn_session_on_rx_pkt(pj_turn_session *sess,
if (is_datagram)
options |= PJ_STUN_IS_DATAGRAM;
status=pj_stun_session_on_rx_pkt(sess->stun, pkt, pkt_len,
- options, NULL, NULL,
+ options, NULL, parsed_len,
sess->srv_addr,
pj_sockaddr_get_len(sess->srv_addr));
- } else if (sess->cb.on_rx_data) {
-
- /* This must be ChannelData. Only makes sense when on_rx_data() is
- * implemented by application.
- */
+ } else {
+ /* This must be ChannelData. */
pj_turn_channel_data cd;
struct peer *peer;
- PJ_ASSERT_RETURN(pkt_len >= 4, PJ_ETOOSMALL);
+ if (pkt_len < 4) {
+ if (parsed_len) *parsed_len = 0;
+ return PJ_ETOOSMALL;
+ }
- /* Lookup peer */
+ /* Decode ChannelData packet */
pj_memcpy(&cd, pkt, sizeof(pj_turn_channel_data));
cd.ch_number = pj_ntohs(cd.ch_number);
cd.length = pj_ntohs(cd.length);
- peer = lookup_peer_by_chnum(sess, cd.ch_number);
- if (!peer || !peer->bound) {
- status = PJ_ENOTFOUND;
- goto on_return;
- }
- /* Check that size is correct, for UDP */
+ /* Check that size is sane */
if (pkt_len < cd.length+sizeof(cd)) {
+ if (parsed_len) {
+ if (is_datagram) {
+ /* Discard the datagram */
+ *parsed_len = pkt_len;
+ } else {
+ /* Insufficient fragment */
+ *parsed_len = 0;
+ }
+ }
status = PJ_ETOOSMALL;
goto on_return;
+ } else {
+ if (parsed_len) {
+ *parsed_len = cd.length + sizeof(cd);
+ }
+ }
+
+ /* Lookup peer */
+ peer = lookup_peer_by_chnum(sess, cd.ch_number);
+ if (!peer || !peer->bound) {
+ status = PJ_ENOTFOUND;
+ goto on_return;
}
/* Notify application */
- (*sess->cb.on_rx_data)(sess, ((pj_uint8_t*)pkt)+sizeof(cd),
- cd.length, &peer->addr,
- pj_sockaddr_get_len(&peer->addr));
-
- status = PJ_SUCCESS;
+ if (sess->cb.on_rx_data) {
+ (*sess->cb.on_rx_data)(sess, ((pj_uint8_t*)pkt)+sizeof(cd),
+ cd.length, &peer->addr,
+ pj_sockaddr_get_len(&peer->addr));
+ }
- } else {
- /* This is ChannelData and application doesn't implement
- * on_rx_data() callback. Just ignore the packet.
- */
status = PJ_SUCCESS;
}
@@ -1077,7 +1089,7 @@ static void on_allocate_success(pj_turn_session *sess,
const pj_stun_msg *msg)
{
const pj_stun_lifetime_attr *lf_attr;
- const pj_stun_relay_addr_attr *raddr_attr;
+ const pj_stun_relayed_addr_attr *raddr_attr;
const pj_stun_sockaddr_attr *mapped_attr;
pj_str_t s;
pj_time_val timeout;
@@ -1125,8 +1137,8 @@ static void on_allocate_success(pj_turn_session *sess,
/* Check that relayed transport address contains correct
* address family.
*/
- raddr_attr = (const pj_stun_relay_addr_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_RELAY_ADDR, 0);
+ raddr_attr = (const pj_stun_relayed_addr_attr*)
+ pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_RELAYED_ADDR, 0);
if (raddr_attr == NULL && method==PJ_STUN_ALLOCATE_METHOD) {
on_session_fail(sess, method, PJNATH_EINSTUNMSG,
pj_cstr(&s, "Error: Received ALLOCATE without "
@@ -1341,6 +1353,7 @@ static pj_status_t stun_on_rx_indication(pj_stun_session *stun,
{
pj_turn_session *sess;
pj_stun_peer_addr_attr *peer_attr;
+ pj_stun_icmp_attr *icmp;
pj_stun_data_attr *data_attr;
PJ_UNUSED_ARG(token);
@@ -1358,6 +1371,14 @@ static pj_status_t stun_on_rx_indication(pj_stun_session *stun,
return PJ_EINVALIDOP;
}
+ /* Check if there is ICMP attribute in the message */
+ icmp = (pj_stun_icmp_attr*)
+ pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ICMP, 0);
+ if (icmp != NULL) {
+ /* This is a forwarded ICMP packet. Ignore it for now */
+ return PJ_SUCCESS;
+ }
+
/* Get PEER-ADDRESS attribute */
peer_attr = (pj_stun_peer_addr_attr*)
pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PEER_ADDR, 0);
diff --git a/pjnath/src/pjnath/turn_sock.c b/pjnath/src/pjnath/turn_sock.c
index 94ff80ab..509efe22 100644
--- a/pjnath/src/pjnath/turn_sock.c
+++ b/pjnath/src/pjnath/turn_sock.c
@@ -463,6 +463,7 @@ static pj_bool_t on_data_read(pj_activesock_t *asock,
pj_size_t *remainder)
{
pj_turn_sock *turn_sock;
+ unsigned parsed_len;
pj_bool_t ret = PJ_TRUE;
turn_sock = (pj_turn_sock*) pj_activesock_get_user_data(asock);
@@ -470,8 +471,14 @@ static pj_bool_t on_data_read(pj_activesock_t *asock,
if (status == PJ_SUCCESS && turn_sock->sess) {
/* Report incoming packet to TURN session */
- PJ_TODO(REPORT_PARSED_LEN);
- pj_turn_session_on_rx_pkt(turn_sock->sess, data, size);
+ parsed_len = (unsigned)size;
+ pj_turn_session_on_rx_pkt(turn_sock->sess, data, size, &parsed_len);
+ if (parsed_len < (unsigned)size) {
+ *remainder = size - parsed_len;
+ pj_memmove(data, ((char*)data)+parsed_len, *remainder);
+ } else {
+ *remainder = 0;
+ }
} else if (status != PJ_SUCCESS &&
turn_sock->conn_type != PJ_TURN_TP_UDP)
{
diff --git a/pjnath/src/pjturn-srv/allocation.c b/pjnath/src/pjturn-srv/allocation.c
index b2215e0d..3e4b77f6 100644
--- a/pjnath/src/pjturn-srv/allocation.c
+++ b/pjnath/src/pjturn-srv/allocation.c
@@ -212,7 +212,7 @@ static pj_status_t send_allocate_response(pj_turn_allocation *alloc,
/* Add RELAYED-ADDRESS attribute */
pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
- PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE,
+ PJ_STUN_ATTR_RELAYED_ADDR, PJ_TRUE,
&alloc->relay.hkey.addr,
pj_sockaddr_get_len(&alloc->relay.hkey.addr));
diff --git a/pjnath/src/pjturn-srv/listener_udp.c b/pjnath/src/pjturn-srv/listener_udp.c
index 2c0eccdc..9d600589 100644
--- a/pjnath/src/pjturn-srv/listener_udp.c
+++ b/pjnath/src/pjturn-srv/listener_udp.c
@@ -125,10 +125,9 @@ PJ_DEF(pj_status_t) pj_turn_listener_create_udp( pj_turn_srv *srv,
/* Create each read_op and kick off read operation */
for (i=0; i<concurrency_cnt; ++i) {
pj_pool_t *rpool = pj_pool_create(srv->core.pf, "rop%p",
- sizeof(struct read_op)+1000,
- 1000, NULL);
+ 1000, 1000, NULL);
- udp->read_op[i] = PJ_POOL_ZALLOC_T(rpool, struct read_op);
+ udp->read_op[i] = PJ_POOL_ZALLOC_T(pool, struct read_op);
udp->read_op[i]->pkt.pool = rpool;
on_read_complete(udp->key, &udp->read_op[i]->op_key, 0);
diff --git a/pjnath/src/pjturn-srv/server.c b/pjnath/src/pjturn-srv/server.c
index 1089ec91..c277e11e 100644
--- a/pjnath/src/pjturn-srv/server.c
+++ b/pjnath/src/pjturn-srv/server.c
@@ -551,6 +551,43 @@ static pj_status_t on_rx_stun_request(pj_stun_session *sess,
return PJ_SUCCESS;
}
+/* Handle STUN Binding request */
+static void handle_binding_request(pj_turn_pkt *pkt,
+ unsigned options)
+{
+ pj_stun_msg *request, *response;
+ pj_uint8_t pdu[200];
+ pj_size_t len;
+ pj_status_t status;
+
+ /* Decode request */
+ status = pj_stun_msg_decode(pkt->pool, pkt->pkt, pkt->len, options,
+ &request, NULL, NULL);
+ if (status != PJ_SUCCESS)
+ return;
+
+ /* Create response */
+ status = pj_stun_msg_create_response(pkt->pool, request, 0, NULL,
+ &response);
+ if (status != PJ_SUCCESS)
+ return;
+
+ /* Add XOR-MAPPED-ADDRESS */
+ pj_stun_msg_add_sockaddr_attr(pkt->pool, response,
+ PJ_STUN_ATTR_XOR_MAPPED_ADDR,
+ PJ_TRUE,
+ &pkt->src.clt_addr,
+ pkt->src_addr_len);
+
+ /* Encode */
+ status = pj_stun_msg_encode(response, pdu, sizeof(pdu), 0, NULL, &len);
+ if (status != PJ_SUCCESS)
+ return;
+
+ /* Send response */
+ pkt->transport->sendto(pkt->transport, pdu, len, 0,
+ &pkt->src.clt_addr, pkt->src_addr_len);
+}
/*
* This callback is called by UDP listener on incoming packet. This is
@@ -615,6 +652,14 @@ PJ_DEF(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv,
return;
}
+ /* Special handling for Binding Request. We won't give it to the
+ * STUN session since this request is not authenticated.
+ */
+ if (pkt->pkt[1] == 1) {
+ handle_binding_request(pkt, options);
+ return;
+ }
+
/* Hand over processing to STUN session. This will trigger
* on_rx_stun_request() callback to be called if the STUN
* message is a request.