From f5c4ac3cbadd515c83b71618e7ff2b1683c2aca2 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 20 Mar 2008 16:32:06 +0000 Subject: More ticket #485: client and server self tested git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1879 74dad513-b988-da41-8d7b-12977e46ad98 --- pjnath/src/pjturn-srv/allocation.c | 79 ++++++++++++++++++++---------- pjnath/src/pjturn-srv/auth.c | 12 ++--- pjnath/src/pjturn-srv/auth.h | 10 ++-- pjnath/src/pjturn-srv/main.c | 98 ++++++++++++++++++++++++++++++++++---- pjnath/src/pjturn-srv/server.c | 26 +++++----- pjnath/src/pjturn-srv/turn.h | 2 +- 6 files changed, 168 insertions(+), 59 deletions(-) (limited to 'pjnath/src/pjturn-srv') diff --git a/pjnath/src/pjturn-srv/allocation.c b/pjnath/src/pjturn-srv/allocation.c index 14ed228b..339b2924 100644 --- a/pjnath/src/pjturn-srv/allocation.c +++ b/pjnath/src/pjturn-srv/allocation.c @@ -668,7 +668,7 @@ static pj_status_t create_relay(pj_turn_srv *srv, if (status != PJ_SUCCESS) { /* Unable to allocate port */ - PJ_LOG(4,(THIS_FILE, "bind() failed: err %d", + PJ_LOG(4,(THIS_FILE, "Unable to allocate relay, giving up: err %d", status)); pj_sock_close(relay->tp.sock); relay->tp.sock = PJ_INVALID_SOCKET; @@ -688,6 +688,11 @@ static pj_status_t create_relay(pj_turn_srv *srv, if (!pj_sockaddr_has_addr(&relay->hkey.addr)) { pj_sockaddr_copy_addr(&relay->hkey.addr, &alloc->listener->addr); } + if (!pj_sockaddr_has_addr(&relay->hkey.addr)) { + pj_sockaddr tmp_addr; + pj_gethostip(af, &tmp_addr); + pj_sockaddr_copy_addr(&relay->hkey.addr, &tmp_addr); + } /* Init ioqueue */ pj_bzero(&icb, sizeof(icb)); @@ -751,14 +756,18 @@ static void send_reply_ok(pj_turn_allocation *alloc, interval = 0; } - /* Add LIFETIME. */ - pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_LIFETIME, interval); + /* Add LIFETIME if this is not ChannelBind. */ + if (PJ_STUN_GET_METHOD(tdata->msg->hdr.type)!=PJ_STUN_CHANNEL_BIND_METHOD){ + pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_LIFETIME, interval); - /* Add BANDWIDTH */ - pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_BANDWIDTH, - alloc->bandwidth); + /* Add BANDWIDTH if lifetime is not zero */ + if (interval != 0) { + pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_BANDWIDTH, + alloc->bandwidth); + } + } status = pj_stun_session_send_msg(alloc->sess, PJ_TRUE, &alloc->hkey.clt_addr, @@ -773,8 +782,8 @@ static void send_reply_ok(pj_turn_allocation *alloc, /* Create new permission */ static pj_turn_permission *create_permission(pj_turn_allocation *alloc, - const pj_sockaddr_t *peer_addr, - unsigned addr_len) + const pj_sockaddr_t *peer_addr, + unsigned addr_len) { pj_turn_permission *perm; @@ -794,6 +803,10 @@ static pj_turn_permission *create_permission(pj_turn_allocation *alloc, pj_gettimeofday(&perm->expiry); perm->expiry.sec += PJ_TURN_PERM_TIMEOUT; + /* Register to hash table */ + pj_hash_set(alloc->pool, alloc->peer_table, &perm->hkey.peer_addr, + pj_sockaddr_get_len(&perm->hkey.peer_addr), 0, perm); + return perm; } @@ -804,14 +817,14 @@ static pj_turn_permission *check_permission_expiry(pj_turn_permission *perm) pj_time_val now; pj_gettimeofday(&now); - if (PJ_TIME_VAL_LT(perm->expiry, now)) { + if (PJ_TIME_VAL_GT(perm->expiry, now)) { /* Permission has not expired */ return perm; } /* Remove from permission hash table */ - pj_hash_set(NULL, alloc->peer_table, &perm->hkey, sizeof(perm->hkey), - 0, NULL); + pj_hash_set(NULL, alloc->peer_table, &perm->hkey.peer_addr, + pj_sockaddr_get_len(&perm->hkey.peer_addr), 0, NULL); /* Remove from channel hash table, if assigned a channel number */ if (perm->channel != PJ_TURN_INVALID_CHANNEL) { @@ -828,16 +841,12 @@ lookup_permission_by_addr(pj_turn_allocation *alloc, const pj_sockaddr_t *peer_addr, unsigned addr_len) { - pj_turn_permission_key key; pj_turn_permission *perm; - pj_bzero(&key, sizeof(key)); - pj_memcpy(&key, peer_addr, addr_len); - /* Lookup in peer hash table */ - perm = (pj_turn_permission*) pj_hash_get(alloc->peer_table, &key, - sizeof(key), NULL); - return check_permission_expiry(perm); + perm = (pj_turn_permission*) pj_hash_get(alloc->peer_table, peer_addr, + addr_len, NULL); + return perm ? check_permission_expiry(perm) : NULL; } /* Lookup permission in hash table by the channel number */ @@ -849,9 +858,9 @@ lookup_permission_by_chnum(pj_turn_allocation *alloc, pj_turn_permission *perm; /* Lookup in peer hash table */ - perm = (pj_turn_permission*) pj_hash_get(alloc->peer_table, &chnum16, + perm = (pj_turn_permission*) pj_hash_get(alloc->ch_table, &chnum16, sizeof(chnum16), NULL); - return check_permission_expiry(perm); + return perm ? check_permission_expiry(perm) : NULL; } /* Update permission because of data from client to peer. @@ -930,8 +939,8 @@ PJ_DEF(void) pj_turn_allocation_on_rx_client_pkt(pj_turn_allocation *alloc, if (!perm) { /* Discard */ PJ_LOG(4,(alloc->obj_name, - "ChannelData from %s discarded: not found", - alloc->info)); + "ChannelData from %s discarded: ch#0x%x not found", + alloc->info, pj_ntohs(cd->ch_number))); goto on_return; } @@ -991,7 +1000,7 @@ static void handle_peer_pkt(pj_turn_allocation *alloc, cd->length = pj_htons((pj_uint16_t)len); /* Copy data */ - pj_memcpy(rel->tp.rx_pkt+sizeof(pj_turn_channel_data), pkt, len); + pj_memcpy(rel->tp.tx_pkt+sizeof(pj_turn_channel_data), pkt, len); /* Send to client */ pj_turn_listener_sendto(alloc->listener, rel->tp.tx_pkt, @@ -1009,6 +1018,18 @@ static void handle_peer_pkt(pj_turn_allocation *alloc, alloc_err(alloc, "Error creating Data indication", status); return; } + + pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_PEER_ADDR, PJ_TRUE, + src_addr, pj_sockaddr_get_len(src_addr)); + pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_DATA, + (const pj_uint8_t*)pkt, len); + + pj_stun_session_send_msg(alloc->sess, PJ_FALSE, + &alloc->hkey.clt_addr, + pj_sockaddr_get_len(&alloc->hkey.clt_addr), + tdata); } } @@ -1186,6 +1207,9 @@ static pj_status_t stun_on_rx_request(pj_stun_session *sess, /* Refresh permission */ refresh_permission(p1); + /* Send response */ + send_reply_ok(alloc, rdata); + /* Done */ return PJ_SUCCESS; } @@ -1212,6 +1236,11 @@ static pj_status_t stun_on_rx_request(pj_stun_session *sess, /* Assign channel number to permission */ p2->channel = PJ_STUN_GET_CH_NB(ch_attr->value); + /* Register to hash table */ + pj_assert(sizeof(p2->channel==2)); + pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel, + sizeof(p2->channel), 0, p2); + /* Update */ refresh_permission(p2); diff --git a/pjnath/src/pjturn-srv/auth.c b/pjnath/src/pjturn-srv/auth.c index 3071221c..8e6c9c59 100644 --- a/pjnath/src/pjturn-srv/auth.c +++ b/pjnath/src/pjturn-srv/auth.c @@ -113,11 +113,11 @@ PJ_DEF(pj_status_t) pj_turn_get_password(const pj_stun_msg *msg, * in the message can be accepted. If this callback returns * PJ_FALSE, 438 (Stale Nonce) response will be created. */ -PJ_DEF(pj_status_t) pj_turn_verify_nonce(const pj_stun_msg *msg, - void *user_data, - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *nonce) +PJ_DEF(pj_bool_t) pj_turn_verify_nonce(const pj_stun_msg *msg, + void *user_data, + const pj_str_t *realm, + const pj_str_t *username, + const pj_str_t *nonce) { PJ_UNUSED_ARG(msg); PJ_UNUSED_ARG(user_data); @@ -127,6 +127,6 @@ PJ_DEF(pj_status_t) pj_turn_verify_nonce(const pj_stun_msg *msg, if (pj_stricmp2(nonce, THE_NONCE)) return PJ_FALSE; - return PJ_SUCCESS; + return PJ_TRUE; } diff --git a/pjnath/src/pjturn-srv/auth.h b/pjnath/src/pjturn-srv/auth.h index db928051..2e342a73 100644 --- a/pjnath/src/pjturn-srv/auth.h +++ b/pjnath/src/pjturn-srv/auth.h @@ -105,11 +105,11 @@ PJ_DECL(pj_status_t) pj_turn_get_password(const pj_stun_msg *msg, * @return The callback MUST return non-zero if the * NONCE can be accepted. */ -PJ_DECL(pj_status_t) pj_turn_verify_nonce(const pj_stun_msg *msg, - void *user_data, - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *nonce); +PJ_DECL(pj_bool_t) pj_turn_verify_nonce(const pj_stun_msg *msg, + void *user_data, + const pj_str_t *realm, + const pj_str_t *username, + const pj_str_t *nonce); #endif /* __PJ_TURN_SRV_AUTH_H__ */ diff --git a/pjnath/src/pjturn-srv/main.c b/pjnath/src/pjturn-srv/main.c index 60c420b2..164b3c25 100644 --- a/pjnath/src/pjturn-srv/main.c +++ b/pjnath/src/pjturn-srv/main.c @@ -21,6 +21,8 @@ #define REALM "pjsip.org" +static pj_caching_pool g_cp; + int err(const char *title, pj_status_t status) { char errmsg[PJ_ERR_MSG_SIZE]; @@ -30,9 +32,91 @@ int err(const char *title, pj_status_t status) return 1; } +static void dump_status(pj_turn_srv *srv) +{ + char addr[80]; + pj_hash_iterator_t itbuf, *it; + pj_time_val now; + unsigned i; + + for (i=0; icore.lis_cnt; ++i) { + pj_turn_listener *lis = srv->core.listener[i]; + printf("Server address : %s\n", lis->info); + } + + printf("Worker threads : %d\n", srv->core.thread_cnt); + printf("Total mem usage: %d.%03dMB\n", g_cp.used_size / 1000000, + (g_cp.used_size % 1000000)/1000); + printf("UDP port range : %u %u %u (next/min/max)\n", srv->ports.next_udp, + srv->ports.min_udp, srv->ports.max_udp); + printf("TCP port range : %u %u %u (next/min/max)\n", srv->ports.next_tcp, + srv->ports.min_tcp, srv->ports.max_tcp); + printf("Clients # : %u\n", pj_hash_count(srv->tables.alloc)); + + puts(""); + + if (pj_hash_count(srv->tables.alloc)==0) { + return; + } + + puts("# Client addr. Alloc addr. Username Lftm Expy #prm #chl"); + puts("------------------------------------------------------------------------------"); + + pj_gettimeofday(&now); + + it = pj_hash_first(srv->tables.alloc, &itbuf); + i=1; + while (it) { + pj_turn_allocation *alloc = (pj_turn_allocation*) + pj_hash_this(srv->tables.alloc, it); + printf("%-3d %-22s %-22s %-8.*s %-4d %-4d %-4d %-4d\n", + i, + alloc->info, + pj_sockaddr_print(&alloc->relay.hkey.addr, addr, sizeof(addr), 3), + (int)alloc->cred.data.static_cred.username.slen, + (int)alloc->cred.data.static_cred.username.ptr, + alloc->relay.lifetime, + alloc->relay.expiry.sec - now.sec, + pj_hash_count(alloc->peer_table), + pj_hash_count(alloc->ch_table)); + it = pj_hash_next(srv->tables.alloc, it); + ++i; + } +} + +static void menu(void) +{ + puts(""); + puts("Menu:"); + puts(" d Dump status"); + puts(" q Quit"); + printf(">> "); +} + +static void console_main(pj_turn_srv *srv) +{ + pj_bool_t quit = PJ_FALSE; + + while (!quit) { + char line[10]; + + menu(); + + fgets(line, sizeof(line), stdin); + + switch (line[0]) { + case 'd': + dump_status(srv); + break; + case 'q': + quit = PJ_TRUE; + break; + } + } +} + int main() { - pj_caching_pool cp; pj_turn_srv *srv; pj_turn_listener *listener; pj_status_t status; @@ -44,11 +128,11 @@ int main() pjlib_util_init(); pjnath_init(); - pj_caching_pool_init(&cp, NULL, 0); + pj_caching_pool_init(&g_cp, NULL, 0); pj_turn_auth_init(REALM); - status = pj_turn_srv_create(&cp.factory, &srv); + status = pj_turn_srv_create(&g_cp.factory, &srv); if (status != PJ_SUCCESS) return err("Error creating server", status); @@ -62,15 +146,11 @@ int main() return err("Error adding listener", status); puts("Server is running"); - puts("Press to quit"); - { - char line[10]; - fgets(line, sizeof(line), stdin); - } + console_main(srv); pj_turn_srv_destroy(srv); - pj_caching_pool_destroy(&cp); + pj_caching_pool_destroy(&g_cp); pj_shutdown(); return 0; diff --git a/pjnath/src/pjturn-srv/server.c b/pjnath/src/pjturn-srv/server.c index b22cc53b..66f1c6a7 100644 --- a/pjnath/src/pjturn-srv/server.c +++ b/pjnath/src/pjturn-srv/server.c @@ -135,7 +135,7 @@ PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, /* Init ports settings */ srv->ports.min_udp = srv->ports.next_udp = MIN_PORT; - srv->ports.max_tcp = MAX_PORT; + srv->ports.max_udp = MAX_PORT; srv->ports.min_tcp = srv->ports.next_tcp = MIN_PORT; srv->ports.max_tcp = MAX_PORT; @@ -265,6 +265,18 @@ PJ_DEF(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv) } } + /* Destroy all allocations FIRST */ + if (srv->tables.alloc) { + it = pj_hash_first(srv->tables.alloc, &itbuf); + while (it != NULL) { + pj_turn_allocation *alloc = (pj_turn_allocation*) + pj_hash_this(srv->tables.alloc, it); + pj_hash_iterator_t *next = pj_hash_next(srv->tables.alloc, it); + pj_turn_allocation_destroy(alloc); + it = next; + } + } + /* Destroy all listeners and STUN sessions associated with them. */ for (i=0; icore.lis_cnt; ++i) { if (srv->core.listener[i]) { @@ -277,18 +289,6 @@ PJ_DEF(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv) } } - /* Destroy all allocations */ - if (srv->tables.alloc) { - it = pj_hash_first(srv->tables.alloc, &itbuf); - while (it != NULL) { - pj_turn_allocation *alloc = (pj_turn_allocation*) - pj_hash_this(srv->tables.alloc, it); - pj_turn_allocation_destroy(alloc); - it = pj_hash_next(srv->tables.alloc, it); - } - } - - /* Destroy hash tables (well, sort of) */ if (srv->tables.alloc) { srv->tables.alloc = NULL; diff --git a/pjnath/src/pjturn-srv/turn.h b/pjnath/src/pjturn-srv/turn.h index 2eb99254..337e8746 100644 --- a/pjnath/src/pjturn-srv/turn.h +++ b/pjnath/src/pjturn-srv/turn.h @@ -190,7 +190,7 @@ struct pj_turn_permission pj_turn_allocation *allocation; /** Optional channel number, or PJ_TURN_INVALID_CHANNEL if channel number - * is not requested for this permission. + * is not requested for this permission. */ pj_uint16_t channel; -- cgit v1.2.3