summaryrefslogtreecommitdiff
path: root/pjnath/src
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/src
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/src')
-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
11 files changed, 232 insertions, 50 deletions
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.