From 685aef52bcf830cb591798cd0814dd4a10605497 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 14 Mar 2008 17:56:11 +0000 Subject: More ticket #485: initial test on TURN client/server git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1869 74dad513-b988-da41-8d7b-12977e46ad98 --- pjnath/include/pjnath/stun_auth.h | 4 ++++ pjnath/src/pjnath-test/stun.c | 2 +- pjnath/src/pjnath/stun_auth.c | 5 +++++ pjnath/src/pjnath/stun_session.c | 5 +++-- pjnath/src/pjnath/turn_session.c | 3 +++ pjnath/src/pjnath/turn_udp.c | 25 ++++++++++++++++++++++--- pjnath/src/pjturn-client/client_main.c | 13 ++++++++----- pjnath/src/pjturn-srv/auth.c | 23 +++++++++++++++++++++++ pjnath/src/pjturn-srv/auth.h | 12 ++++++++++++ pjnath/src/pjturn-srv/main.c | 11 ++++++++++- pjnath/src/pjturn-srv/server.c | 2 +- 11 files changed, 92 insertions(+), 13 deletions(-) (limited to 'pjnath') diff --git a/pjnath/include/pjnath/stun_auth.h b/pjnath/include/pjnath/stun_auth.h index 849d2e0a..840e473d 100644 --- a/pjnath/include/pjnath/stun_auth.h +++ b/pjnath/include/pjnath/stun_auth.h @@ -277,6 +277,9 @@ PJ_DECL(void) pj_stun_auth_cred_dup(pj_pool_t *pool, * the message. * @param pool If response is to be created, then memory will * be allocated from this pool. + * @param auth_key Optional pointer to receive authentication key to + * calculate MESSAGE-INTEGRITY of the response, if + * the response needs to be authenticated. * @param p_response Optional pointer to receive the response message * then the credential in the request fails to * authenticate. @@ -291,6 +294,7 @@ PJ_DECL(pj_status_t) pj_stun_authenticate_request(const pj_uint8_t *pkt, const pj_stun_msg *msg, pj_stun_auth_cred *cred, pj_pool_t *pool, + pj_str_t *auth_key, pj_stun_msg **p_response); diff --git a/pjnath/src/pjnath-test/stun.c b/pjnath/src/pjnath-test/stun.c index 32a31719..c0d74380 100644 --- a/pjnath/src/pjnath-test/stun.c +++ b/pjnath/src/pjnath-test/stun.c @@ -655,7 +655,7 @@ static int fingerprint_test_vector() cred.data.static_cred.data = pj_str(v->password); status = pj_stun_authenticate_request(buf, len, msg, - &cred, pool, NULL); + &cred, pool, NULL, NULL); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); diff --git a/pjnath/src/pjnath/stun_auth.c b/pjnath/src/pjnath/stun_auth.c index b809c072..4a6024f0 100644 --- a/pjnath/src/pjnath/stun_auth.c +++ b/pjnath/src/pjnath/stun_auth.c @@ -121,6 +121,7 @@ PJ_DEF(pj_status_t) pj_stun_authenticate_request(const pj_uint8_t *pkt, const pj_stun_msg *msg, pj_stun_auth_cred *cred, pj_pool_t *pool, + pj_str_t *auth_key, pj_stun_msg **p_response) { pj_str_t realm, nonce, password; @@ -332,6 +333,10 @@ PJ_DEF(pj_status_t) pj_stun_authenticate_request(const pj_uint8_t *pkt, create_challenge(pool, msg, PJ_STUN_SC_STALE_NONCE, NULL, &realm, &nonce, p_response); } + if (auth_key) { + pj_stun_create_key(pool, auth_key, &realm, + &auser->value, &password); + } return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_STALE_NONCE); } } diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c index d9ae3b75..29dc3e57 100644 --- a/pjnath/src/pjnath/stun_session.c +++ b/pjnath/src/pjnath/stun_session.c @@ -859,16 +859,17 @@ static pj_status_t authenticate_req(pj_stun_session *sess, unsigned src_addr_len) { pj_stun_msg *response; + pj_str_t auth_key; pj_status_t status; if (PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type) || sess->cred == NULL) return PJ_SUCCESS; status = pj_stun_authenticate_request(pkt, pkt_len, msg, sess->cred, - tmp_pool, &response); + tmp_pool, &auth_key, &response); if (status != PJ_SUCCESS && response != NULL) { PJ_LOG(5,(SNAME(sess), "Message authentication failed")); - send_response(sess, tmp_pool, response, NULL, PJ_FALSE, + send_response(sess, tmp_pool, response, &auth_key, PJ_FALSE, src_addr, src_addr_len); } diff --git a/pjnath/src/pjnath/turn_session.c b/pjnath/src/pjnath/turn_session.c index 05abc436..7b772dcf 100644 --- a/pjnath/src/pjnath/turn_session.c +++ b/pjnath/src/pjnath/turn_session.c @@ -218,6 +218,9 @@ PJ_DEF(pj_status_t) pj_turn_session_create( pj_stun_config *cfg, return status; } + /* Attach ourself to STUN session */ + pj_stun_session_set_user_data(sess->stun, sess); + /* Replace mutex in STUN session with a NULL mutex, since access to * STUN session is serialized. */ diff --git a/pjnath/src/pjnath/turn_udp.c b/pjnath/src/pjnath/turn_udp.c index a5d34b60..8d5ff9d4 100644 --- a/pjnath/src/pjnath/turn_udp.c +++ b/pjnath/src/pjnath/turn_udp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -112,6 +113,15 @@ PJ_DEF(pj_status_t) pj_turn_udp_create( pj_stun_config *cfg, return status; } + /* Bind to any */ + pj_sockaddr_init(af, &udp_rel->src_addr, NULL, 0); + status = pj_sock_bind(udp_rel->sock, &udp_rel->src_addr, + pj_sockaddr_get_len(&udp_rel->src_addr)); + if (status != PJ_SUCCESS) { + pj_turn_udp_destroy(udp_rel); + return status; + } + /* Register to ioqeuue */ pj_bzero(&ioq_cb, sizeof(ioq_cb)); ioq_cb.on_read_complete = &on_read_complete; @@ -255,7 +265,9 @@ static void on_read_complete(pj_ioqueue_key_t *key, pj_ioqueue_op_key_t *op_key, pj_ssize_t bytes_read) { + enum { MAX_RETRY = 10 }; pj_turn_udp *udp_rel; + int retry = 0; pj_status_t status; udp_rel = (pj_turn_udp*) pj_ioqueue_get_user_data(key); @@ -270,16 +282,23 @@ static void on_read_complete(pj_ioqueue_key_t *key, /* Read next packet */ bytes_read = sizeof(udp_rel->pkt); udp_rel->src_addr_len = sizeof(udp_rel->src_addr); - status = pj_ioqueue_recvfrom(udp_rel->key, op_key, udp_rel->pkt, &bytes_read, 0, &udp_rel->src_addr, &udp_rel->src_addr_len); - if (status != PJ_EPENDING && status != PJ_SUCCESS) + if (status != PJ_EPENDING && status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + + pj_strerror(status, errmsg, sizeof(errmsg)); + PJ_LOG(4,(udp_rel->pool->obj_name, + "ioqueue recvfrom error: %s", errmsg)); + bytes_read = -status; + } - } while (status != PJ_EPENDING && status != PJ_ECANCELLED); + } while (status != PJ_EPENDING && status != PJ_ECANCELLED && + ++retry < MAX_RETRY); } diff --git a/pjnath/src/pjturn-client/client_main.c b/pjnath/src/pjturn-client/client_main.c index a9123319..114f47c8 100644 --- a/pjnath/src/pjturn-client/client_main.c +++ b/pjnath/src/pjturn-client/client_main.c @@ -132,7 +132,7 @@ static int init() len = sizeof(addr); CHECK( pj_sock_getsockname(g.peer[i].sock, &addr, &len) ); - port = pj_sockaddr_get_port(&g.peer[i].addr); + port = pj_sockaddr_get_port(&addr); CHECK( pj_gethostip(pj_AF_INET(), &g.peer[i].addr) ); pj_sockaddr_set_port(&g.peer[0].addr, port); @@ -357,7 +357,10 @@ static void menu(void) if (g.udp_rel) { pj_turn_udp_get_info(g.udp_rel, &info); strcpy(client_state, pj_turn_state_name(info.state)); - pj_sockaddr_print(&info.relay_addr, relay_addr, sizeof(relay_addr), 3); + if (info.state >= PJ_TURN_STATE_READY) + pj_sockaddr_print(&info.relay_addr, relay_addr, sizeof(relay_addr), 3); + else + strcpy(relay_addr, "0.0.0.0:0"); } else { strcpy(client_state, "NULL"); strcpy(relay_addr, "0.0.0.0:0"); @@ -371,15 +374,15 @@ static void menu(void) puts("+====================================================================+"); puts("| CLIENT | PEER-0 |"); puts("| | |"); - printf("| State : %12s | Address: %21s |\n", + printf("| State : %-12s | Address: %-21s |\n", client_state, peer0_addr); - printf("| Relay addr: %21s | |\n", + printf("| Relay addr: %-21s | |\n", relay_addr); puts("| | 0 Send data to relay address |"); puts("| A Allocate relay +--------------------------------+ "); puts("| S[01] Send data to peer 0/1 | PEER-1 |"); puts("| B[01] BindChannel to peer 0/1 | |"); - printf("| X Delete allocation | Address: %21s |\n", + printf("| X Delete allocation | Address: %-21s |\n", peer1_addr); puts("+-----------------------------------+ |"); puts("| q Quit | 1 Send data to relay adderss |"); diff --git a/pjnath/src/pjturn-srv/auth.c b/pjnath/src/pjturn-srv/auth.c index 3071221c..ad930251 100644 --- a/pjnath/src/pjturn-srv/auth.c +++ b/pjnath/src/pjturn-srv/auth.c @@ -58,6 +58,29 @@ PJ_DEF(void) pj_turn_auth_dinit(void) } +PJ_DEF(pj_status_t) pj_turn_get_cred( const pj_stun_msg *msg, + void *user_data, + pj_pool_t *pool, + pj_str_t *realm, + pj_str_t *username, + pj_str_t *nonce, + int *data_type, + pj_str_t *data) +{ + PJ_UNUSED_ARG(msg); + PJ_UNUSED_ARG(pool); + PJ_UNUSED_ARG(user_data); + + *realm = pj_str(g_realm); + *username = pj_str(g_cred[0].username); + *nonce = pj_str(THE_NONCE); + *data_type = 0; + *data = pj_str(g_cred[0].passwd); + + return PJ_SUCCESS; +} + + /* * This function is called by pj_stun_verify_credential() when * server needs to challenge the request with 401 response. diff --git a/pjnath/src/pjturn-srv/auth.h b/pjnath/src/pjturn-srv/auth.h index db928051..d0b5a0ec 100644 --- a/pjnath/src/pjturn-srv/auth.h +++ b/pjnath/src/pjturn-srv/auth.h @@ -60,6 +60,18 @@ PJ_DECL(pj_status_t) pj_turn_get_auth(void *user_data, pj_str_t *realm, pj_str_t *nonce); +/** + * Get credential. + */ +PJ_DECL(pj_status_t) pj_turn_get_cred(const pj_stun_msg *msg, + void *user_data, + pj_pool_t *pool, + pj_str_t *realm, + pj_str_t *username, + pj_str_t *nonce, + int *data_type, + pj_str_t *data); + /** * This function is called to get the password for the specified username. * This function is also used to check whether the username is valid. diff --git a/pjnath/src/pjturn-srv/main.c b/pjnath/src/pjturn-srv/main.c index 3cddafc1..60c420b2 100644 --- a/pjnath/src/pjturn-srv/main.c +++ b/pjnath/src/pjturn-srv/main.c @@ -17,6 +17,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "turn.h" +#include "auth.h" + +#define REALM "pjsip.org" int err(const char *title, pj_status_t status) { @@ -38,13 +41,19 @@ int main() if (status != PJ_SUCCESS) return err("pj_init() error", status); + pjlib_util_init(); + pjnath_init(); + pj_caching_pool_init(&cp, NULL, 0); + pj_turn_auth_init(REALM); + status = pj_turn_srv_create(&cp.factory, &srv); if (status != PJ_SUCCESS) return err("Error creating server", status); - status = pj_turn_listener_create_udp(srv, pj_AF_INET(), NULL, 3478, 1, 0, &listener); + status = pj_turn_listener_create_udp(srv, pj_AF_INET(), NULL, + PJ_STUN_PORT, 1, 0, &listener); if (status != PJ_SUCCESS) return err("Error creating listener", status); diff --git a/pjnath/src/pjturn-srv/server.c b/pjnath/src/pjturn-srv/server.c index 6765b3ca..11180dbf 100644 --- a/pjnath/src/pjturn-srv/server.c +++ b/pjnath/src/pjturn-srv/server.c @@ -147,7 +147,7 @@ PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, srv->core.cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; srv->core.cred.data.dyn_cred.user_data = srv; srv->core.cred.data.dyn_cred.get_auth = &pj_turn_get_auth; - srv->core.cred.data.dyn_cred.get_cred = &pj_turn_srv_get_cred; + srv->core.cred.data.dyn_cred.get_cred = &pj_turn_get_cred; srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password; srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce; -- cgit v1.2.3