summaryrefslogtreecommitdiff
path: root/pjnath
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-04-09 13:38:35 +0000
committerBenny Prijono <bennylp@teluu.com>2008-04-09 13:38:35 +0000
commitdf25592dcb2fccb8180fb9e4a10a6989e97c5dd1 (patch)
treee198dbed3329447a7061a9ee65bddd28b1130c03 /pjnath
parentc033e56749db3c724861c41ba3206e256a967777 (diff)
More ticket #485: now really remove pjstun-srv-test
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1917 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjnath')
-rw-r--r--pjnath/src/pjstun-srv-test/bind_usage.c206
-rw-r--r--pjnath/src/pjstun-srv-test/main.c160
-rw-r--r--pjnath/src/pjstun-srv-test/server.c183
-rw-r--r--pjnath/src/pjstun-srv-test/server.h139
-rw-r--r--pjnath/src/pjstun-srv-test/turn_usage.c1434
-rw-r--r--pjnath/src/pjstun-srv-test/usage.c274
6 files changed, 0 insertions, 2396 deletions
diff --git a/pjnath/src/pjstun-srv-test/bind_usage.c b/pjnath/src/pjstun-srv-test/bind_usage.c
deleted file mode 100644
index 84928af8..00000000
--- a/pjnath/src/pjstun-srv-test/bind_usage.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "server.h"
-
-#define THIS_FILE "bind_usage.c"
-
-static void usage_on_rx_data(pj_stun_usage *usage,
- void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len);
-static void usage_on_destroy(pj_stun_usage *usage);
-static pj_status_t sess_on_send_msg(pj_stun_session *sess,
- const void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *dst_addr,
- unsigned addr_len);
-static pj_status_t sess_on_rx_request(pj_stun_session *sess,
- const pj_uint8_t *pkt,
- unsigned pkt_len,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len);
-
-struct bind_usage
-{
- pj_pool_t *pool;
- pj_stun_usage *usage;
- pj_stun_session *session;
-};
-
-
-PJ_DEF(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv,
- const pj_str_t *ip_addr,
- unsigned port,
- pj_stun_usage **p_bu)
-{
- pj_pool_t *pool;
- struct bind_usage *bu;
- pj_stun_server_info *si;
- pj_stun_usage_cb usage_cb;
- pj_stun_session_cb sess_cb;
- pj_sockaddr_in local_addr;
- pj_status_t status;
-
- si = pj_stun_server_get_info(srv);
-
- pool = pj_pool_create(si->pf, "bind%p", 128, 128, NULL);
- bu = PJ_POOL_ZALLOC_T(pool, struct bind_usage);
- bu->pool = pool;
-
- status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port);
- if (status != PJ_SUCCESS)
- return status;
-
- pj_bzero(&usage_cb, sizeof(usage_cb));
- usage_cb.on_rx_data = &usage_on_rx_data;
- usage_cb.on_destroy = &usage_on_destroy;
-
- status = pj_stun_usage_create(srv, "bind%p", &usage_cb,
- pj_AF_INET(), pj_SOCK_DGRAM(), 0,
- &local_addr, sizeof(local_addr),
- &bu->usage);
- if (status != PJ_SUCCESS) {
- pj_pool_release(pool);
- return status;
- }
-
- pj_bzero(&sess_cb, sizeof(sess_cb));
- sess_cb.on_send_msg = &sess_on_send_msg;
- sess_cb.on_rx_request = &sess_on_rx_request;
- status = pj_stun_session_create(&si->stun_cfg, "bind%p", &sess_cb,
- PJ_FALSE, &bu->session);
- if (status != PJ_SUCCESS) {
- pj_stun_usage_destroy(bu->usage);
- return status;
- }
-
- pj_stun_usage_set_user_data(bu->usage, bu);
- pj_stun_session_set_user_data(bu->session, bu);
-
- if (p_bu)
- *p_bu = bu->usage;
-
- return PJ_SUCCESS;
-}
-
-
-static void usage_on_rx_data(pj_stun_usage *usage,
- void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- struct bind_usage *bu;
- pj_stun_session *session;
- pj_status_t status;
-
- bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage);
- session = bu->session;
-
- /* Handle packet to session */
- status = pj_stun_session_on_rx_pkt(session, (pj_uint8_t*)pkt, pkt_size,
- PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET,
- NULL, src_addr, src_addr_len);
- if (status != PJ_SUCCESS) {
- pj_stun_perror(THIS_FILE, "Error handling incoming packet", status);
- return;
- }
-}
-
-
-static pj_status_t sess_on_send_msg(pj_stun_session *sess,
- const void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *dst_addr,
- unsigned addr_len)
-{
- struct bind_usage *bu;
- pj_stun_usage *usage;
-
- bu = (struct bind_usage*) pj_stun_session_get_user_data(sess);
- usage = bu->usage;
-
- return pj_stun_usage_sendto(usage, pkt, pkt_size, 0,
- dst_addr, addr_len);
-}
-
-
-static pj_status_t sess_on_rx_request(pj_stun_session *sess,
- const pj_uint8_t *pkt,
- unsigned pkt_len,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- pj_stun_tx_data *tdata;
- pj_status_t status;
-
- PJ_UNUSED_ARG(pkt);
- PJ_UNUSED_ARG(pkt_len);
-
- /* Create response */
- status = pj_stun_session_create_res(sess, msg, 0, NULL, &tdata);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Create MAPPED-ADDRESS attribute */
- status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
- PJ_STUN_ATTR_MAPPED_ADDR,
- PJ_FALSE,
- src_addr, src_addr_len);
- if (status != PJ_SUCCESS) {
- pj_stun_perror(THIS_FILE, "Error creating response", status);
- pj_stun_msg_destroy_tdata(sess, tdata);
- return status;
- }
-
- /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */
- if (msg->hdr.magic == PJ_STUN_MAGIC) {
- status =
- pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
- PJ_STUN_ATTR_XOR_MAPPED_ADDR,
- PJ_TRUE,
- src_addr, src_addr_len);
- if (status != PJ_SUCCESS) {
- pj_stun_perror(THIS_FILE, "Error creating response", status);
- pj_stun_msg_destroy_tdata(sess, tdata);
- return status;
- }
- }
-
- /* Send */
- status = pj_stun_session_send_msg(sess, PJ_TRUE,
- src_addr, src_addr_len, tdata);
- return status;
-
-}
-
-static void usage_on_destroy(pj_stun_usage *usage)
-{
- struct bind_usage *bu;
-
- bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage);
- if (bu==NULL)
- return;
-
- pj_stun_session_destroy(bu->session);
- pj_pool_release(bu->pool);
-}
diff --git a/pjnath/src/pjstun-srv-test/main.c b/pjnath/src/pjstun-srv-test/main.c
deleted file mode 100644
index b7bb3b67..00000000
--- a/pjnath/src/pjstun-srv-test/main.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "server.h"
-
-#define THIS_FILE "main.c"
-
-struct options
-{
- char *realm;
- char *user_name;
- char *password;
- char *nonce;
- pj_bool_t use_fingerprint;
-} o;
-
-static void usage(void)
-{
- puts("Usage: pjstun_srv_test [OPTIONS]");
- puts("");
- puts("where OPTIONS:");
- puts(" --realm, -r Set realm of the credential");
- puts(" --username, -u Set username of the credential");
- puts(" --password, -p Set password of the credential");
- puts(" --nonce, -N Set NONCE");
- puts(" --fingerprint, -F Use fingerprint for outgoing requests");
- puts(" --help, -h");
-}
-
-
-static void server_main(pj_stun_server *srv)
-{
- int quit = 0;
-
- while (!quit) {
- char line[10];
-
- printf("Menu:\n"
- " d Dump status\n"
- " q Quit\n"
- "Choice:");
-
- fgets(line, sizeof(line), stdin);
- if (line[0] == 'q') {
- quit = 1;
- } else if (line[0] == 'd') {
- pj_stun_server_info *si = pj_stun_server_get_info(srv);
- pj_pool_factory_dump(si->pf, PJ_TRUE);
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- struct pj_getopt_option long_options[] = {
- { "realm", 1, 0, 'r'},
- { "username", 1, 0, 'u'},
- { "password", 1, 0, 'p'},
- { "nonce", 1, 0, 'N'},
- { "fingerprint",0, 0, 'F'},
- { "help", 0, 0, 'h'}
- };
- int c, opt_id;
- pj_caching_pool cp;
- pj_stun_server *srv;
- pj_stun_usage *turn;
- pj_status_t status;
-
- while((c=pj_getopt_long(argc,argv, "r:u:p:N:hF", long_options, &opt_id))!=-1) {
- switch (c) {
- case 'r':
- o.realm = pj_optarg;
- break;
- case 'u':
- o.user_name = pj_optarg;
- break;
- case 'p':
- o.password = pj_optarg;
- break;
- case 'N':
- o.nonce = pj_optarg;
- break;
- case 'h':
- usage();
- return 0;
- case 'F':
- o.use_fingerprint = PJ_TRUE;
- break;
- default:
- printf("Argument \"%s\" is not valid. Use -h to see help",
- argv[pj_optind]);
- return 1;
- }
- }
-
- if (pj_optind != argc) {
- puts("Error: invalid arguments");
- return 1;
- }
-
- pj_init();
- pjlib_util_init();
- pjnath_init();
- pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
-
- status = pj_stun_server_create(&cp.factory, 1, &srv);
- if (status != PJ_SUCCESS) {
- pj_stun_perror(THIS_FILE, "Unable to create server", status);
- return 1;
- }
-
- /*
- status = pj_stun_bind_usage_create(srv, NULL, 3478, NULL);
- if (status != PJ_SUCCESS) {
- pj_stun_perror(THIS_FILE, "Unable to create bind usage", status);
- return 1;
- }
- */
-
- status = pj_stun_turn_usage_create(srv, pj_SOCK_DGRAM(), NULL,
- 3478, o.use_fingerprint, &turn);
- if (status != PJ_SUCCESS) {
- pj_stun_perror(THIS_FILE, "Unable to create bind usage", status);
- return 1;
- }
-
- if (o.user_name && o.password) {
- pj_stun_auth_cred cred;
- pj_bzero(&cred, sizeof(cred));
- cred.type = PJ_STUN_AUTH_CRED_STATIC;
- cred.data.static_cred.realm = pj_str(o.realm);
- cred.data.static_cred.username = pj_str(o.user_name);
- cred.data.static_cred.data_type = 0;
- cred.data.static_cred.data = pj_str(o.password);
- cred.data.static_cred.nonce = pj_str(o.nonce);
- pj_stun_turn_usage_set_credential(turn, &cred);
- }
-
- server_main(srv);
-
- pj_stun_server_destroy(srv);
- pj_pool_factory_dump(&cp.factory, PJ_TRUE);
- pj_shutdown();
- return 0;
-}
diff --git a/pjnath/src/pjstun-srv-test/server.c b/pjnath/src/pjstun-srv-test/server.c
deleted file mode 100644
index e526c84d..00000000
--- a/pjnath/src/pjstun-srv-test/server.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "server.h"
-
-#define THIS_FILE "server.c"
-
-struct pj_stun_server
-{
- pj_stun_server_info si;
-
- pj_pool_t *pool;
-
- pj_bool_t thread_quit_flag;
- pj_thread_t **threads;
-
- unsigned usage_cnt;
- pj_stun_usage *usage[32];
-};
-
-PJ_DEF(pj_status_t) pj_stun_perror( const char *sender,
- const char *title,
- pj_status_t status)
-{
- char errmsg[PJ_ERR_MSG_SIZE];
- pj_strerror(status, errmsg, sizeof(errmsg));
-
- PJ_LOG(3,(sender, "%s: %s", title, errmsg));
- return status;
-}
-
-static int worker_thread(void *p)
-{
- pj_stun_server *srv = (pj_stun_server*)p;
-
- while (!srv->thread_quit_flag) {
- pj_time_val timeout = { 0, 50 };
- pj_timer_heap_poll(srv->si.timer_heap, NULL);
- pj_ioqueue_poll(srv->si.ioqueue, &timeout);
- }
-
- return 0;
-}
-
-
-PJ_DEF(pj_status_t) pj_stun_server_create(pj_pool_factory *pf,
- unsigned thread_cnt,
- pj_stun_server **p_srv)
-{
- pj_pool_t *pool;
- pj_stun_server *srv;
- unsigned i;
- pj_status_t status;
-
- pool = pj_pool_create(pf, "server%p", 4000, 4000, NULL);
-
- srv = PJ_POOL_ZALLOC_T(pool, pj_stun_server);
- srv->pool = pool;
- srv->si.pf = pf;
-
- status = pj_ioqueue_create(srv->pool, PJ_IOQUEUE_MAX_HANDLES,
- &srv->si.ioqueue);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- status = pj_timer_heap_create(srv->pool, 1024, &srv->si.timer_heap);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- pj_stun_config_init(&srv->si.stun_cfg, srv->si.pf, 0, srv->si.ioqueue,
- srv->si.timer_heap);
-
- srv->si.thread_cnt = thread_cnt;
- srv->threads = (pj_thread_t**)
- pj_pool_calloc(pool, thread_cnt, sizeof(pj_thread_t*));
- for (i=0; i<thread_cnt; ++i) {
- status = pj_thread_create(pool, "worker%p", &worker_thread,
- srv, 0, 0, &srv->threads[i]);
- if (status != PJ_SUCCESS)
- goto on_error;
- }
-
- *p_srv = srv;
- return PJ_SUCCESS;
-
-on_error:
- pj_stun_server_destroy(srv);
- return status;
-}
-
-
-PJ_DEF(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv)
-{
- return &srv->si;
-}
-
-
-pj_status_t pj_stun_server_register_usage(pj_stun_server *srv,
- pj_stun_usage *usage)
-{
- unsigned i;
-
- for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
- if (srv->usage[i] == usage)
- return PJ_SUCCESS;
- }
-
- for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
- if (srv->usage[i] == NULL)
- break;
- }
-
- if (i == PJ_ARRAY_SIZE(srv->usage))
- return PJ_ETOOMANY;
-
- srv->usage[i] = usage;
- ++srv->usage_cnt;
-
- return PJ_SUCCESS;
-}
-
-pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv,
- pj_stun_usage *usage)
-{
- unsigned i;
-
- for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
- if (srv->usage[i] == usage)
- break;
- }
-
- if (i != PJ_ARRAY_SIZE(srv->usage)) {
- srv->usage[i] = NULL;
- --srv->usage_cnt;
- return PJ_SUCCESS;
- }
-
- return PJ_ENOTFOUND;
-}
-
-
-PJ_DEF(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv)
-{
- unsigned i;
-
- for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
- if (!srv->usage[i])
- continue;
-
- pj_stun_usage_destroy(srv->usage[i]);
- pj_stun_server_unregister_usage(srv, srv->usage[i]);
- }
-
- srv->thread_quit_flag = PJ_TRUE;
- for (i=0; i<srv->si.thread_cnt; ++i) {
- pj_thread_join(srv->threads[i]);
- srv->threads[i] = NULL;
- }
-
- pj_timer_heap_destroy(srv->si.timer_heap);
- pj_ioqueue_destroy(srv->si.ioqueue);
- pj_pool_release(srv->pool);
-
- return PJ_SUCCESS;
-}
-
-
diff --git a/pjnath/src/pjstun-srv-test/server.h b/pjnath/src/pjstun-srv-test/server.h
deleted file mode 100644
index ada48069..00000000
--- a/pjnath/src/pjstun-srv-test/server.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __STUN_SERVER_H__
-#define __STUN_SERVER_H__
-
-#include <pjnath.h>
-#include <pjlib-util.h>
-#include <pjlib.h>
-
-
-/** Opaque declaration for STUN server instance */
-typedef struct pj_stun_server pj_stun_server;
-
-/** STUN server info */
-typedef struct pj_stun_server_info
-{
- pj_pool_factory *pf;
- pj_stun_config stun_cfg;
- pj_ioqueue_t *ioqueue;
- pj_timer_heap_t *timer_heap;
- unsigned thread_cnt;
-} pj_stun_server_info;
-
-/** STUN usage */
-typedef struct pj_stun_usage pj_stun_usage;
-
-/** STUN usage callback */
-typedef struct pj_stun_usage_cb
-{
- void (*on_rx_data)(pj_stun_usage *usage,
- void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len);
- void (*on_destroy)(pj_stun_usage *usage);
-} pj_stun_usage_cb;
-
-
-PJ_DECL(pj_status_t) pj_stun_perror(const char *sender,
- const char *title,
- pj_status_t status);
-
-/**
- * Create instance of STUN server.
- */
-PJ_DECL(pj_status_t) pj_stun_server_create(pj_pool_factory *pf,
- unsigned thread_cnt,
- pj_stun_server **p_srv);
-
-/**
- * Get STUN server info.
- */
-PJ_DECL(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv);
-
-
-/**
- * Destroy STUN server.
- */
-PJ_DECL(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv);
-
-
-/**
- * Create STUN usage.
- */
-PJ_DECL(pj_status_t) pj_stun_usage_create(pj_stun_server *srv,
- const char *name,
- const pj_stun_usage_cb *cb,
- int family,
- int type,
- int protocol,
- const pj_sockaddr_t *local_addr,
- int addr_len,
- pj_stun_usage **p_usage);
-
-/**
- * Destroy usage.
- */
-PJ_DECL(pj_status_t) pj_stun_usage_destroy(pj_stun_usage *usage);
-
-/**
- * Set user data.
- */
-PJ_DECL(pj_status_t) pj_stun_usage_set_user_data(pj_stun_usage *usage,
- void *user_data);
-/**
- * Get user data.
- */
-PJ_DECL(void*) pj_stun_usage_get_user_data(pj_stun_usage *usage);
-
-/**
- * Send with the usage.
- */
-PJ_DECL(pj_status_t) pj_stun_usage_sendto(pj_stun_usage *usage,
- const void *pkt,
- pj_size_t pkt_size,
- unsigned flags,
- const pj_sockaddr_t *dst_addr,
- unsigned addr_len);
-
-PJ_DECL(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv,
- const pj_str_t *ip_addr,
- unsigned port,
- pj_stun_usage **p_bu);
-
-PJ_DECL(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv,
- int type,
- const pj_str_t *ip_addr,
- unsigned port,
- pj_bool_t use_fingerprint,
- pj_stun_usage **p_bu);
-
-PJ_DECL(pj_status_t) pj_stun_turn_usage_set_credential(pj_stun_usage *turn,
- const pj_stun_auth_cred *cred);
-
-pj_status_t pj_stun_server_register_usage(pj_stun_server *srv,
- pj_stun_usage *usage);
-pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv,
- pj_stun_usage *usage);
-
-
-#endif /* __STUN_SERVER_H__ */
-
-
diff --git a/pjnath/src/pjstun-srv-test/turn_usage.c b/pjnath/src/pjstun-srv-test/turn_usage.c
deleted file mode 100644
index 4eb326b7..00000000
--- a/pjnath/src/pjstun-srv-test/turn_usage.c
+++ /dev/null
@@ -1,1434 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "server.h"
-
-#define THIS_FILE "turn_usage.c"
-
-#define MAX_CLIENTS 8000
-#define MAX_PEER_PER_CLIENT 16
-#define START_PORT 2000
-#define END_PORT 65530
-
-/*
- * Forward declarations.
- */
-struct turn_usage;
-struct turn_client;
-
-static void tu_on_rx_data(pj_stun_usage *usage,
- void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len);
-static void tu_on_destroy(pj_stun_usage *usage);
-static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess,
- const void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *dst_addr,
- unsigned addr_len);
-static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess,
- const pj_uint8_t *pkt,
- unsigned pkt_len,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len);
-
-static pj_status_t handle_binding_req(pj_stun_session *session,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len);
-
-static pj_status_t client_create(struct turn_usage *tu,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len,
- struct turn_client **p_client);
-static pj_status_t client_destroy(struct turn_client *client,
- pj_status_t reason);
-static pj_status_t client_handle_stun_msg(struct turn_client *client,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len);
-
-
-struct turn_usage
-{
- pj_pool_factory *pf;
- pj_stun_config *cfg;
- pj_ioqueue_t *ioqueue;
- pj_timer_heap_t *timer_heap;
- pj_pool_t *pool;
- pj_mutex_t *mutex;
- pj_stun_usage *usage;
- int type;
- pj_stun_session *default_session;
- pj_hash_table_t *client_htable;
- pj_stun_auth_cred *cred;
- pj_bool_t use_fingerprint;
-
- unsigned max_bw_kbps;
- unsigned max_lifetime;
-
- unsigned next_port;
-};
-
-struct peer;
-
-struct turn_client
-{
- char obj_name[PJ_MAX_OBJ_NAME];
- struct turn_usage *tu;
- pj_pool_t *pool;
- pj_stun_session *session;
- pj_mutex_t *mutex;
-
- pj_sockaddr_in client_src_addr;
-
- /* Socket and socket address of the allocated port */
- int sock_type;
- pj_sock_t sock;
- pj_ioqueue_key_t *key;
- pj_sockaddr_in alloc_addr;
-
- /* Allocation properties */
- unsigned bw_kbps;
- unsigned lifetime;
- pj_timer_entry expiry_timer;
-
-
- /* Hash table to keep all peers, key-ed by their address */
- pj_hash_table_t *peer_htable;
-
- /* Active destination, or sin_addr.s_addr will be zero if
- * no active destination is set.
- */
- struct peer *active_peer;
-
- /* Current packet received/sent from/to the allocated port */
- pj_uint8_t pkt[4000];
- pj_sockaddr_in pkt_src_addr;
- int pkt_src_addr_len;
- pj_ioqueue_op_key_t pkt_read_key;
- pj_ioqueue_op_key_t pkt_write_key;
-};
-
-struct peer
-{
- struct turn_client *client;
- pj_sockaddr_in addr;
-};
-
-struct session_data
-{
- struct turn_usage *tu;
- struct turn_client *client;
-};
-
-
-/*
- * This is the only public API, to create and start the TURN usage.
- */
-PJ_DEF(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv,
- int type,
- const pj_str_t *ip_addr,
- unsigned port,
- pj_bool_t use_fingerprint,
- pj_stun_usage **p_bu)
-{
- pj_pool_t *pool;
- struct turn_usage *tu;
- pj_stun_server_info *si;
- pj_stun_usage_cb usage_cb;
- pj_stun_session_cb sess_cb;
- struct session_data *sd;
- pj_sockaddr_in local_addr;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(srv && (type==pj_SOCK_DGRAM()||type==pj_SOCK_STREAM()),
- PJ_EINVAL);
- si = pj_stun_server_get_info(srv);
-
- pool = pj_pool_create(si->pf, "turn%p", 4000, 4000, NULL);
- tu = PJ_POOL_ZALLOC_T(pool, struct turn_usage);
- tu->pool = pool;
- tu->type = type;
- tu->pf = si->pf;
- tu->cfg = &si->stun_cfg;
- tu->ioqueue = si->ioqueue;
- tu->timer_heap = si->timer_heap;
- tu->next_port = START_PORT;
- tu->max_bw_kbps = 64;
- tu->max_lifetime = 10 * 60;
- tu->use_fingerprint = use_fingerprint;
-
- status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Create usage */
- pj_bzero(&usage_cb, sizeof(usage_cb));
- usage_cb.on_rx_data = &tu_on_rx_data;
- usage_cb.on_destroy = &tu_on_destroy;
- status = pj_stun_usage_create(srv, "turn%p", &usage_cb,
- pj_AF_INET(), tu->type, 0,
- &local_addr, sizeof(local_addr),
- &tu->usage);
- if (status != PJ_SUCCESS) {
- pj_pool_release(pool);
- return status;
- }
- pj_stun_usage_set_user_data(tu->usage, tu);
-
- /* Init hash tables */
- tu->client_htable = pj_hash_create(tu->pool, MAX_CLIENTS);
-
- /* Create default session */
- pj_bzero(&sess_cb, sizeof(sess_cb));
- sess_cb.on_send_msg = &tu_sess_on_send_msg;
- sess_cb.on_rx_request = &tu_sess_on_rx_request;
- status = pj_stun_session_create(&si->stun_cfg, "turns%p", &sess_cb,
- use_fingerprint, &tu->default_session);
- if (status != PJ_SUCCESS) {
- pj_stun_usage_destroy(tu->usage);
- return status;
- }
-
- sd = PJ_POOL_ZALLOC_T(pool, struct session_data);
- sd->tu = tu;
- pj_stun_session_set_user_data(tu->default_session, sd);
-
- pj_stun_session_set_server_name(tu->default_session, NULL);
-
- /* Create mutex */
- status = pj_mutex_create_recursive(pool, "turn%p", &tu->mutex);
- if (status != PJ_SUCCESS) {
- pj_stun_usage_destroy(tu->usage);
- return status;
- }
-
- if (p_bu) {
- *p_bu = tu->usage;
- }
-
- return PJ_SUCCESS;
-}
-
-
-PJ_DEF(pj_status_t) pj_stun_turn_usage_set_credential(pj_stun_usage *turn,
- const pj_stun_auth_cred *c)
-{
- struct turn_usage *tu;
- tu = (struct turn_usage*) pj_stun_usage_get_user_data(turn);
-
- tu->cred = PJ_POOL_ZALLOC_T(tu->pool, pj_stun_auth_cred);
- pj_stun_auth_cred_dup(tu->pool, tu->cred, c);
- pj_stun_session_set_credential(tu->default_session, tu->cred);
- return PJ_SUCCESS;
-}
-
-
-/*
- * This is a callback called by usage.c when the particular STUN usage
- * is to be destroyed.
- */
-static void tu_on_destroy(pj_stun_usage *usage)
-{
- struct turn_usage *tu;
- pj_hash_iterator_t hit, *it;
-
- tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage);
-
- /* Destroy all clients */
- if (tu->client_htable) {
- it = pj_hash_first(tu->client_htable, &hit);
- while (it) {
- struct turn_client *client;
-
- client = (struct turn_client *)pj_hash_this(tu->client_htable, it);
- client_destroy(client, PJ_SUCCESS);
-
- it = pj_hash_first(tu->client_htable, &hit);
- }
- }
-
- pj_stun_session_destroy(tu->default_session);
- pj_mutex_destroy(tu->mutex);
- pj_pool_release(tu->pool);
-}
-
-
-/*
- * This is a callback called by the usage.c to notify the TURN usage,
- * that incoming packet (may or may not be a STUN packet) is received
- * on the port where the TURN usage is listening.
- */
-static void tu_on_rx_data(pj_stun_usage *usage,
- void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- struct turn_usage *tu;
- struct turn_client *client;
- unsigned flags;
- pj_status_t status;
-
- /* Which usage instance is this */
- tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage);
-
- /* Lookup client structure based on source address */
- client = (struct turn_client*) pj_hash_get(tu->client_htable, src_addr,
- src_addr_len, NULL);
-
- /* STUN message decoding flag */
- flags = 0;
- if (tu->type == pj_SOCK_DGRAM())
- flags |= PJ_STUN_IS_DATAGRAM;
-
-
- if (client) {
- status = pj_stun_msg_check((const pj_uint8_t*)pkt, pkt_size, flags);
-
- if (status == PJ_SUCCESS) {
- if (client->session) {
- /* Received STUN message */
- status = pj_stun_session_on_rx_pkt(client->session,
- (pj_uint8_t*)pkt, pkt_size,
- flags, NULL,
- src_addr, src_addr_len);
- } else {
- client_destroy(client, PJ_SUCCESS);
- }
- } else if (client->active_peer) {
- /* Received non-STUN message and client has active destination */
- pj_ssize_t sz = pkt_size;
- pj_ioqueue_sendto(client->key, &client->pkt_write_key,
- pkt, &sz, 0,
- &client->active_peer->addr,
- sizeof(client->active_peer->addr));
- } else {
- /* Received non-STUN message and client doesn't have active
- * destination.
- */
- /* Ignore */
- }
-
- } else {
- /* Received packet (could be STUN or no) from new source */
- flags |= PJ_STUN_CHECK_PACKET;
- pj_stun_session_on_rx_pkt(tu->default_session, (pj_uint8_t*)pkt,
- pkt_size, flags, NULL,
- src_addr, src_addr_len);
- }
-}
-
-
-/*
- * This is a utility function provided by TU (Turn Usage) to reserve
- * or allocate internal port/socket. The allocation needs to be
- * coordinated to minimize bind() collissions.
- */
-static pj_status_t tu_alloc_port(struct turn_usage *tu,
- int type,
- unsigned rpp_bits,
- const pj_sockaddr_in *req_addr,
- pj_sock_t *p_sock,
- int *err_code)
-{
- enum { RETRY = 100 };
- pj_sockaddr_in addr;
- pj_sock_t sock = PJ_INVALID_SOCKET;
- unsigned retry;
- pj_status_t status;
-
- if (req_addr && req_addr->sin_port != 0) {
-
- *err_code = PJ_STUN_SC_INVALID_PORT;
-
- /* Allocate specific port */
- status = pj_sock_socket(pj_AF_INET(), type, 0, &sock);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Bind */
- status = pj_sock_bind(sock, req_addr, sizeof(pj_sockaddr_in));
- if (status != PJ_SUCCESS) {
- pj_sock_close(sock);
- return status;
- }
-
- /* Success */
- *p_sock = sock;
- return PJ_SUCCESS;
-
- } else {
- status = -1;
- *err_code = PJ_STUN_SC_INSUFFICIENT_CAPACITY;
-
- if (req_addr && req_addr->sin_addr.s_addr) {
- *err_code = PJ_STUN_SC_INVALID_IP_ADDR;
- pj_memcpy(&addr, req_addr, sizeof(pj_sockaddr_in));
- } else {
- pj_sockaddr_in_init(&addr, NULL, 0);
- }
-
- for (retry=0; retry<RETRY && sock == PJ_INVALID_SOCKET; ++retry) {
- switch (rpp_bits) {
- case 1:
- if ((tu->next_port & 0x01)==0)
- tu->next_port++;
- break;
- case 2:
- case 3:
- if ((tu->next_port & 0x01)==1)
- tu->next_port++;
- break;
- }
-
- status = pj_sock_socket(pj_AF_INET(), type, 0, &sock);
- if (status != PJ_SUCCESS)
- return status;
-
- addr.sin_port = pj_htons((pj_uint16_t)tu->next_port);
-
- if (++tu->next_port > END_PORT)
- tu->next_port = START_PORT;
-
- status = pj_sock_bind(sock, &addr, sizeof(addr));
- if (status != PJ_SUCCESS) {
- pj_sock_close(sock);
- sock = PJ_INVALID_SOCKET;
-
- /* If client requested specific IP address, assume that
- * bind failed because the IP address is not valid. We
- * don't want to retry that since it will exhaust our
- * port space.
- */
- if (req_addr && req_addr->sin_addr.s_addr)
- break;
- }
- }
-
- if (sock == PJ_INVALID_SOCKET) {
- return status;
- }
-
- *p_sock = sock;
- return PJ_SUCCESS;
- }
-}
-
-
-/*
- * This callback is called by the TU's STUN session when it receives
- * a valid STUN message. This is called from tu_on_rx_data above.
- */
-static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess,
- const pj_uint8_t *pkt,
- unsigned pkt_len,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- struct session_data *sd;
- struct turn_client *client;
- pj_stun_tx_data *tdata;
- pj_status_t status;
-
- PJ_UNUSED_ARG(pkt);
- PJ_UNUSED_ARG(pkt_len);
-
- sd = (struct session_data*) pj_stun_session_get_user_data(sess);
-
- pj_assert(sd->client == NULL);
-
- if (msg->hdr.type == PJ_STUN_BINDING_REQUEST) {
- return handle_binding_req(sess, msg, src_addr, src_addr_len);
-
- } else if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) {
- if (PJ_STUN_IS_REQUEST(msg->hdr.type)) {
- status = pj_stun_session_create_res(sess, msg,
- PJ_STUN_SC_NO_BINDING,
- NULL, &tdata);
- if (status==PJ_SUCCESS) {
- status = pj_stun_session_send_msg(sess, PJ_FALSE,
- src_addr, src_addr_len,
- tdata);
- }
- } else {
- PJ_LOG(4,(THIS_FILE,
- "Received %s %s without matching Allocation, "
- "ignored", pj_stun_get_method_name(msg->hdr.type),
- pj_stun_get_class_name(msg->hdr.type)));
- }
- return PJ_SUCCESS;
- }
-
- status = client_create(sd->tu, src_addr, src_addr_len, &client);
- if (status != PJ_SUCCESS) {
- pj_stun_perror(THIS_FILE, "Error creating new TURN client",
- status);
- return status;
- }
-
-
- /* Hand over message to client */
- pj_mutex_lock(client->mutex);
- status = client_handle_stun_msg(client, msg, src_addr, src_addr_len);
- pj_mutex_unlock(client->mutex);
-
- return status;
-}
-
-
-/*
- * This callback is called by STUN session when it needs to send packet
- * to the network.
- */
-static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess,
- const void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *dst_addr,
- unsigned addr_len)
-{
- struct session_data *sd;
-
- sd = (struct session_data*) pj_stun_session_get_user_data(sess);
-
- if (sd->tu->type == pj_SOCK_DGRAM()) {
- return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0,
- dst_addr, addr_len);
- } else {
- return PJ_ENOTSUP;
- }
-}
-
-
-/****************************************************************************/
-/*
- * TURN client operations.
- */
-
-/* Function prototypes */
-static pj_status_t client_create_relay(struct turn_client *client);
-static pj_status_t client_destroy_relay(struct turn_client *client);
-static void client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e);
-static void client_on_read_complete(pj_ioqueue_key_t *key,
- pj_ioqueue_op_key_t *op_key,
- pj_ssize_t bytes_read);
-static pj_status_t client_respond(struct turn_client *client,
- const pj_stun_msg *msg,
- int err_code,
- const char *err_msg,
- const pj_sockaddr_t *dst_addr,
- int dst_addr_len);
-static struct peer* client_get_peer(struct turn_client *client,
- const pj_sockaddr_in *peer_addr,
- pj_uint32_t *hval);
-static struct peer* client_add_peer(struct turn_client *client,
- const pj_sockaddr_in *peer_addr,
- pj_uint32_t hval);
-
-static const char *get_tp_type(int type)
-{
- if (type==pj_SOCK_DGRAM())
- return "udp";
- else if (type==pj_SOCK_STREAM())
- return "tcp";
- else
- return "???";
-}
-
-
-/*
- * This callback is called when incoming STUN message is received
- * in the TURN usage. This is called from by tu_on_rx_data() when
- * the packet is handed over to the client.
- */
-static pj_status_t client_sess_on_rx_msg(pj_stun_session *sess,
- const pj_uint8_t *pkt,
- unsigned pkt_len,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- struct session_data *sd;
-
- PJ_UNUSED_ARG(pkt);
- PJ_UNUSED_ARG(pkt_len);
-
- sd = (struct session_data*) pj_stun_session_get_user_data(sess);
- pj_assert(sd->client != PJ_SUCCESS);
-
- return client_handle_stun_msg(sd->client, msg, src_addr, src_addr_len);
-}
-
-
-/*
- * This callback is called by client's STUN session to send outgoing
- * STUN packet. It's called when client calls pj_stun_session_send_msg()
- * function.
- */
-static pj_status_t client_sess_on_send_msg(pj_stun_session *sess,
- const void *pkt,
- pj_size_t pkt_size,
- const pj_sockaddr_t *dst_addr,
- unsigned addr_len)
-{
- struct session_data *sd;
-
- sd = (struct session_data*) pj_stun_session_get_user_data(sess);
-
- if (sd->tu->type == pj_SOCK_DGRAM()) {
- return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0,
- dst_addr, addr_len);
- } else {
- return PJ_ENOTSUP;
- }
-}
-
-
-/*
- * Create a new TURN client for the specified source address.
- */
-static pj_status_t client_create(struct turn_usage *tu,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len,
- struct turn_client **p_client)
-{
- pj_pool_t *pool;
- struct turn_client *client;
- pj_stun_session_cb sess_cb;
- struct session_data *sd;
- pj_status_t status;
-
- PJ_ASSERT_RETURN(src_addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL);
-
- pool = pj_pool_create(tu->pf, "turnc%p", 4000, 4000, NULL);
- client = PJ_POOL_ZALLOC_T(pool, struct turn_client);
- client->pool = pool;
- client->tu = tu;
- client->sock = PJ_INVALID_SOCKET;
-
- pj_memcpy(&client->client_src_addr, src_addr,
- sizeof(client->client_src_addr));
-
- if (src_addr) {
- const pj_sockaddr_in *a4 = (const pj_sockaddr_in *)src_addr;
- pj_ansi_snprintf(client->obj_name, sizeof(client->obj_name),
- "%s:%s:%d",
- get_tp_type(tu->type),
- pj_inet_ntoa(a4->sin_addr),
- (int)pj_ntohs(a4->sin_port));
- client->obj_name[sizeof(client->obj_name)-1] = '\0';
- }
-
- /* Create session */
- pj_bzero(&sess_cb, sizeof(sess_cb));
- sess_cb.on_send_msg = &client_sess_on_send_msg;
- sess_cb.on_rx_request = &client_sess_on_rx_msg;
- sess_cb.on_rx_indication = &client_sess_on_rx_msg;
- status = pj_stun_session_create(tu->cfg, client->obj_name,
- &sess_cb, tu->use_fingerprint,
- &client->session);
- if (status != PJ_SUCCESS) {
- pj_pool_release(pool);
- return status;
- }
-
- if (tu->cred)
- pj_stun_session_set_credential(client->session, tu->cred);
-
- sd = PJ_POOL_ZALLOC_T(pool, struct session_data);
- sd->tu = tu;
- sd->client = client;
- pj_stun_session_set_user_data(client->session, sd);
-
- /* Mutex */
- status = pj_mutex_create_recursive(client->pool, pool->obj_name,
- &client->mutex);
- if (status != PJ_SUCCESS) {
- client_destroy(client, status);
- return status;
- }
-
- /* Create hash table */
- client->peer_htable = pj_hash_create(client->pool, MAX_PEER_PER_CLIENT);
- if (client->peer_htable == NULL) {
- client_destroy(client, status);
- return PJ_ENOMEM;
- }
-
- /* Init timer entry */
- client->expiry_timer.user_data = client;
- client->expiry_timer.cb = &client_on_expired;
- client->expiry_timer.id = 0;
-
- /* Register to hash table */
- pj_mutex_lock(tu->mutex);
- pj_hash_set(pool, tu->client_htable, src_addr, src_addr_len, 0, client);
- pj_mutex_unlock(tu->mutex);
-
- /* Done */
- *p_client = client;
-
- PJ_LOG(4,(THIS_FILE, "TURN client %s created", client->obj_name));
-
- return PJ_SUCCESS;
-}
-
-
-/*
- * Destroy TURN client.
- */
-static pj_status_t client_destroy(struct turn_client *client,
- pj_status_t reason)
-{
- struct turn_usage *tu = client->tu;
- char name[PJ_MAX_OBJ_NAME];
-
- pj_assert(sizeof(name)==sizeof(client->obj_name));
- pj_memcpy(name, client->obj_name, sizeof(name));
-
- /* Kill timer if it's active */
- if (client->expiry_timer.id != 0) {
- pj_timer_heap_cancel(tu->timer_heap, &client->expiry_timer);
- client->expiry_timer.id = PJ_FALSE;
- }
-
- /* Destroy relay */
- client_destroy_relay(client);
-
- /* Unregister client from hash table */
- pj_mutex_lock(tu->mutex);
- pj_hash_set(NULL, tu->client_htable,
- &client->client_src_addr, sizeof(client->client_src_addr),
- 0, NULL);
- pj_mutex_unlock(tu->mutex);
-
- /* Destroy STUN session */
- if (client->session) {
- pj_stun_session_destroy(client->session);
- client->session = NULL;
- }
-
- /* Mutex */
- if (client->mutex) {
- pj_mutex_destroy(client->mutex);
- client->mutex = NULL;
- }
-
- /* Finally destroy pool */
- if (client->pool) {
- pj_pool_t *pool = client->pool;
- client->pool = NULL;
- pj_pool_release(pool);
- }
-
- if (reason == PJ_SUCCESS) {
- PJ_LOG(4,(THIS_FILE, "TURN client %s destroyed", name));
- }
-
- return PJ_SUCCESS;
-}
-
-
-/*
- * This utility function is used to setup relay (with ioqueue) after
- * socket has been allocated for the TURN client.
- */
-static pj_status_t client_create_relay(struct turn_client *client)
-{
- pj_ioqueue_callback client_ioq_cb;
- int addrlen;
- pj_status_t status;
-
- /* Update address */
- addrlen = sizeof(pj_sockaddr_in);
- status = pj_sock_getsockname(client->sock, &client->alloc_addr,
- &addrlen);
- if (status != PJ_SUCCESS) {
- pj_sock_close(client->sock);
- client->sock = PJ_INVALID_SOCKET;
- return status;
- }
-
- if (client->alloc_addr.sin_addr.s_addr == 0) {
- status = pj_gethostip(pj_AF_INET(), (pj_sockaddr*)&client->alloc_addr.sin_addr);
- if (status != PJ_SUCCESS) {
- pj_sock_close(client->sock);
- client->sock = PJ_INVALID_SOCKET;
- return status;
- }
- }
-
- /* Register to ioqueue */
- pj_bzero(&client_ioq_cb, sizeof(client_ioq_cb));
- client_ioq_cb.on_read_complete = &client_on_read_complete;
- status = pj_ioqueue_register_sock(client->pool, client->tu->ioqueue,
- client->sock, client,
- &client_ioq_cb, &client->key);
- if (status != PJ_SUCCESS) {
- pj_sock_close(client->sock);
- client->sock = PJ_INVALID_SOCKET;
- return status;
- }
-
- pj_ioqueue_op_key_init(&client->pkt_read_key,
- sizeof(client->pkt_read_key));
- pj_ioqueue_op_key_init(&client->pkt_write_key,
- sizeof(client->pkt_write_key));
-
- /* Trigger the first read */
- client_on_read_complete(client->key, &client->pkt_read_key, 0);
-
- PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated on %s:%s:%d",
- client->obj_name,
- get_tp_type(client->sock_type),
- pj_inet_ntoa(client->alloc_addr.sin_addr),
- (int)pj_ntohs(client->alloc_addr.sin_port)));
-
- return PJ_SUCCESS;
-}
-
-
-/*
- * This utility function is used to destroy the port allocated for
- * the TURN client.
- */
-static pj_status_t client_destroy_relay(struct turn_client *client)
-{
- /* Close socket */
- if (client->key) {
- pj_ioqueue_unregister(client->key);
- client->key = NULL;
- client->sock = PJ_INVALID_SOCKET;
- } else if (client->sock && client->sock != PJ_INVALID_SOCKET) {
- pj_sock_close(client->sock);
- client->sock = PJ_INVALID_SOCKET;
- }
-
- PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocation %s:%s:%d destroyed",
- client->obj_name,
- get_tp_type(client->sock_type),
- pj_inet_ntoa(client->alloc_addr.sin_addr),
- (int)pj_ntohs(client->alloc_addr.sin_port)));
- return PJ_SUCCESS;
-}
-
-
-/*
- * From the source packet address, get the peer instance from hash table.
- */
-static struct peer* client_get_peer(struct turn_client *client,
- const pj_sockaddr_in *peer_addr,
- pj_uint32_t *hval)
-{
- return (struct peer*)
- pj_hash_get(client->peer_htable, peer_addr, sizeof(*peer_addr), hval);
-}
-
-
-/*
- * Add a peer instance to the peer hash table.
- */
-static struct peer* client_add_peer(struct turn_client *client,
- const pj_sockaddr_in *peer_addr,
- unsigned hval)
-{
- struct peer *peer;
-
- peer = PJ_POOL_ZALLOC_T(client->pool, struct peer);
- peer->client = client;
- pj_memcpy(&peer->addr, peer_addr, sizeof(peer->addr));
-
- pj_hash_set(client->pool, client->peer_htable,
- &peer->addr, sizeof(peer->addr), hval, peer);
-
- PJ_LOG(4,(THIS_FILE, "TURN client %s: peer %s:%s:%d added",
- client->obj_name, get_tp_type(client->sock_type),
- pj_inet_ntoa(peer->addr.sin_addr),
- (int)pj_ntohs(peer->addr.sin_port)));
-
- return peer;
-}
-
-
-/*
- * Utility to send STUN response message (normally to send error response).
- */
-static pj_status_t client_respond(struct turn_client *client,
- const pj_stun_msg *msg,
- int err_code,
- const char *custom_msg,
- const pj_sockaddr_t *dst_addr,
- int dst_addr_len)
-{
- pj_str_t err_msg;
- pj_str_t *p_err_msg = NULL;
- pj_stun_tx_data *response;
- pj_status_t status;
-
- if (custom_msg)
- pj_cstr(&err_msg, custom_msg), p_err_msg = &err_msg;
-
- status = pj_stun_session_create_res(client->session, msg,
- err_code, p_err_msg,
- &response);
- if (status == PJ_SUCCESS)
- status = pj_stun_session_send_msg(client->session, PJ_TRUE,
- dst_addr, dst_addr_len, response);
-
- return status;
-}
-
-
-/*
- * Handle incoming initial or subsequent Allocate Request.
- * This function is called by client_handle_stun_msg() below.
- */
-static pj_status_t client_handle_allocate_req(struct turn_client *client,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- const pj_stun_bandwidth_attr *a_bw;
- const pj_stun_lifetime_attr *a_lf;
- const pj_stun_req_port_props_attr *a_rpp;
- const pj_stun_req_transport_attr *a_rt;
- const pj_stun_req_ip_attr *a_rip;
- pj_stun_tx_data *response;
- pj_sockaddr_in req_addr;
- int addr_len;
- unsigned req_bw, rpp_bits;
- pj_time_val timeout;
- pj_status_t status;
-
- a_bw = (const pj_stun_bandwidth_attr *)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_BANDWIDTH, 0);
- a_lf = (const pj_stun_lifetime_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_LIFETIME, 0);
- a_rpp = (const pj_stun_req_port_props_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_PORT_PROPS, 0);
- a_rt = (const pj_stun_req_transport_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_TRANSPORT, 0);
- a_rip = (const pj_stun_req_ip_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_IP, 0);
-
- /* Init requested local address */
- pj_sockaddr_in_init(&req_addr, NULL, 0);
-
- /* Process BANDWIDTH attribute */
- if (a_bw && a_bw->value > client->tu->max_bw_kbps) {
- client_respond(client, msg, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL,
- src_addr, src_addr_len);
- return PJ_SUCCESS;
- } else if (a_bw) {
- client->bw_kbps = req_bw = a_bw->value;
- } else {
- req_bw = 0;
- client->bw_kbps = client->tu->max_bw_kbps;
- }
-
- /* Process REQUESTED-TRANSPORT attribute */
- if (a_rt && a_rt->value != 0) {
- client_respond(client, msg, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, NULL,
- src_addr, src_addr_len);
- return PJ_SUCCESS;
- } else if (a_rt) {
- client->sock_type = a_rt->value ? pj_SOCK_STREAM() : pj_SOCK_DGRAM();
- } else {
- client->sock_type = client->tu->type;;
- }
-
- /* Process REQUESTED-IP attribute */
- if (a_rip && a_rip->sockaddr.addr.sa_family != pj_AF_INET()) {
- client_respond(client, msg, PJ_STUN_SC_INVALID_IP_ADDR, NULL,
- src_addr, src_addr_len);
- return PJ_SUCCESS;
-
- } else if (a_rip) {
- req_addr.sin_addr.s_addr = a_rip->sockaddr.ipv4.sin_addr.s_addr;
- }
-
- /* Process REQUESTED-PORT-PROPS attribute */
- if (a_rpp) {
- unsigned port;
-
- rpp_bits = (a_rpp->value & 0x00030000) >> 16;
- port = (a_rpp->value & 0xFFFF);
- req_addr.sin_port = pj_htons((pj_uint8_t)port);
- } else {
- rpp_bits = 0;
- }
-
- /* Process LIFETIME attribute */
- if (a_lf && a_lf->value > client->tu->max_lifetime) {
- client->lifetime = client->tu->max_lifetime;
- } else if (a_lf) {
- client->lifetime = a_lf->value;
- } else {
- client->lifetime = client->tu->max_lifetime;
- }
-
- /* Allocate socket if we don't have one */
- if (client->key == NULL) {
- int err_code;
-
- PJ_LOG(4,(THIS_FILE, "TURN client %s: received initial Allocate "
- "request, requested type:addr:port=%s:%s:%d, rpp "
- "bits=%d, bw=%dkbps, lifetime=%d",
- client->obj_name, get_tp_type(client->sock_type),
- pj_inet_ntoa(req_addr.sin_addr), pj_ntohs(req_addr.sin_port),
- rpp_bits, client->bw_kbps, client->lifetime));
-
- status = tu_alloc_port(client->tu, client->sock_type, rpp_bits,
- &req_addr, &client->sock, &err_code);
- if (status != PJ_SUCCESS) {
- char errmsg[PJ_ERR_MSG_SIZE];
-
- pj_strerror(status, errmsg, sizeof(errmsg));
- PJ_LOG(4,(THIS_FILE, "TURN client %s: error allocating relay port"
- ": %s",
- client->obj_name, errmsg));
-
- client_respond(client, msg, err_code, NULL,
- src_addr, src_addr_len);
-
- return status;
- }
-
- status = client_create_relay(client);
- if (status != PJ_SUCCESS) {
- client_respond(client, msg, PJ_STUN_SC_SERVER_ERROR, NULL,
- src_addr, src_addr_len);
- return status;
- }
- } else {
- /* Otherwise check if the port parameter stays the same */
- /* TODO */
- PJ_LOG(4,(THIS_FILE, "TURN client %s: received Allocate refresh, "
- "lifetime=%d",
- client->obj_name, client->lifetime));
- }
-
- /* Refresh timer */
- if (client->expiry_timer.id != PJ_FALSE) {
- pj_timer_heap_cancel(client->tu->timer_heap, &client->expiry_timer);
- client->expiry_timer.id = PJ_FALSE;
- }
- timeout.sec = client->lifetime;
- timeout.msec = 0;
- pj_timer_heap_schedule(client->tu->timer_heap, &client->expiry_timer, &timeout);
- client->expiry_timer.id = PJ_TRUE;
-
- /* Done successfully, create and send success response */
- status = pj_stun_session_create_res(client->session, msg,
- 0, NULL, &response);
- if (status != PJ_SUCCESS) {
- return status;
- }
-
- pj_stun_msg_add_uint_attr(response->pool, response->msg,
- PJ_STUN_ATTR_BANDWIDTH, client->bw_kbps);
- pj_stun_msg_add_uint_attr(response->pool, response->msg,
- PJ_STUN_ATTR_LIFETIME, client->lifetime);
- pj_stun_msg_add_sockaddr_attr(response->pool, response->msg,
- PJ_STUN_ATTR_MAPPED_ADDR, PJ_FALSE,
- src_addr, src_addr_len);
- pj_stun_msg_add_sockaddr_attr(response->pool, response->msg,
- PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE,
- src_addr, src_addr_len);
-
- addr_len = sizeof(req_addr);
- pj_sock_getsockname(client->sock, &req_addr, &addr_len);
- pj_stun_msg_add_sockaddr_attr(response->pool, response->msg,
- PJ_STUN_ATTR_RELAY_ADDR, PJ_FALSE,
- &client->alloc_addr, addr_len);
-
- PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated or refreshed, "
- "internal address is %s:%s:%d",
- client->obj_name,
- get_tp_type(client->sock_type),
- pj_inet_ntoa(req_addr.sin_addr),
- (int)pj_ntohs(req_addr.sin_port)));
-
- return pj_stun_session_send_msg(client->session, PJ_TRUE,
- src_addr, src_addr_len, response);
-}
-
-
-/*
- * Handle incoming Binding request.
- * This function is called by client_handle_stun_msg() below.
- */
-static pj_status_t handle_binding_req(pj_stun_session *session,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- pj_stun_tx_data *tdata;
- pj_status_t status;
-
- /* Create response */
- status = pj_stun_session_create_res(session, msg, 0, NULL,
- &tdata);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Create MAPPED-ADDRESS attribute */
- pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
- PJ_STUN_ATTR_MAPPED_ADDR,
- PJ_FALSE,
- src_addr, src_addr_len);
-
- /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */
- if (msg->hdr.magic == PJ_STUN_MAGIC) {
- status =
- pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
- PJ_STUN_ATTR_XOR_MAPPED_ADDR,
- PJ_TRUE,
- src_addr, src_addr_len);
- }
-
- /* Send */
- status = pj_stun_session_send_msg(session, PJ_TRUE,
- src_addr, src_addr_len, tdata);
- return status;
-}
-
-
-/*
- * client handling incoming STUN Set Active Destination request
- * This function is called by client_handle_stun_msg() below.
- */
-static pj_status_t client_handle_sad(struct turn_client *client,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- pj_stun_remote_addr_attr *a_raddr;
-
- a_raddr = (pj_stun_remote_addr_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0);
- if (!a_raddr) {
- /* Remote active destination needs to be cleared */
- client->active_peer = NULL;
-
- } else if (a_raddr->sockaddr.addr.sa_family != pj_AF_INET()) {
- /* Bad request (not IPv4) */
- client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL,
- src_addr, src_addr_len);
- return PJ_SUCCESS;
-
- } else if (client->active_peer) {
- /* Client tries to set new active destination without clearing
- * it first. Reject with 439.
- */
- client_respond(client, msg, PJ_STUN_SC_TRANSITIONING, NULL,
- src_addr, src_addr_len);
- return PJ_SUCCESS;
-
- } else {
- struct peer *peer;
- pj_uint32_t hval = 0;
-
- /* Add a new peer/permission if we don't have one for this address */
- peer = client_get_peer(client, &a_raddr->sockaddr.ipv4, &hval);
- if (peer==NULL) {
- peer = client_add_peer(client, &a_raddr->sockaddr.ipv4, hval);
- }
-
- /* Set active destination */
- client->active_peer = peer;
- }
-
- if (client->active_peer) {
- PJ_LOG(4,(THIS_FILE,
- "TURN client %s: active destination set to %s:%d",
- client->obj_name,
- pj_inet_ntoa(client->active_peer->addr.sin_addr),
- (int)pj_ntohs(client->active_peer->addr.sin_port)));
- } else {
- PJ_LOG(4,(THIS_FILE, "TURN client %s: active destination cleared",
- client->obj_name));
- }
-
- /* Respond with successful response */
- client_respond(client, msg, 0, NULL, src_addr, src_addr_len);
-
- return PJ_SUCCESS;
-}
-
-
-/*
- * client handling incoming STUN Send Indication
- * This function is called by client_handle_stun_msg() below.
- */
-static pj_status_t client_handle_send_ind(struct turn_client *client,
- const pj_stun_msg *msg)
-{
- pj_stun_remote_addr_attr *a_raddr;
- pj_stun_data_attr *a_data;
- pj_uint32_t hval = 0;
- const pj_uint8_t *data;
- pj_ssize_t datalen;
-
- /* Get REMOTE-ADDRESS attribute */
- a_raddr = (pj_stun_remote_addr_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0);
- if (!a_raddr) {
- /* REMOTE-ADDRESS not present, discard packet */
- return PJ_SUCCESS;
-
- } else if (a_raddr->sockaddr.addr.sa_family != pj_AF_INET()) {
- /* REMOTE-ADDRESS present but not IPv4, discard packet */
- return PJ_SUCCESS;
-
- }
-
- /* Get the DATA attribute */
- a_data = (pj_stun_data_attr*)
- pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0);
- if (a_data) {
- data = (const pj_uint8_t *)a_data->data;
- datalen = a_data->length;
-
- } else if (client->sock_type == pj_SOCK_STREAM()) {
- /* Discard if no Data and Allocation type is TCP */
- return PJ_SUCCESS;
-
- } else {
- data = (const pj_uint8_t *)"";
- datalen = 0;
- }
-
- /* Add to peer table if necessary */
- if (client_get_peer(client, &a_raddr->sockaddr.ipv4, &hval)==NULL)
- client_add_peer(client, &a_raddr->sockaddr.ipv4, hval);
-
- /* Send the packet */
- pj_ioqueue_sendto(client->key, &client->pkt_write_key,
- data, &datalen, 0,
- &a_raddr->sockaddr.ipv4, sizeof(pj_sockaddr_in));
-
- return PJ_SUCCESS;
-}
-
-
-/*
- * client handling unknown incoming STUN message.
- * This function is called by client_handle_stun_msg() below.
- */
-static pj_status_t client_handle_unknown_msg(struct turn_client *client,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- PJ_LOG(4,(THIS_FILE, "TURN client %s: unhandled %s %s",
- client->obj_name, pj_stun_get_method_name(msg->hdr.type),
- pj_stun_get_class_name(msg->hdr.type)));
-
- if (PJ_STUN_IS_REQUEST(msg->hdr.type)) {
- return client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL,
- src_addr, src_addr_len);
- } else {
- /* Ignore */
- return PJ_SUCCESS;
- }
-}
-
-
-/*
- * Main entry for handling STUN messages arriving on the main TURN port,
- * for this client
- */
-static pj_status_t client_handle_stun_msg(struct turn_client *client,
- const pj_stun_msg *msg,
- const pj_sockaddr_t *src_addr,
- unsigned src_addr_len)
-{
- pj_status_t status;
-
- switch (msg->hdr.type) {
- case PJ_STUN_SEND_INDICATION:
- status = client_handle_send_ind(client, msg);
- break;
-
- case PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST:
- status = client_handle_sad(client, msg,
- src_addr, src_addr_len);
- break;
-
- case PJ_STUN_ALLOCATE_REQUEST:
- status = client_handle_allocate_req(client, msg,
- src_addr, src_addr_len);
- break;
-
- case PJ_STUN_BINDING_REQUEST:
- status = handle_binding_req(client->session, msg,
- src_addr, src_addr_len);
- break;
-
- default:
- status = client_handle_unknown_msg(client, msg,
- src_addr, src_addr_len);
- break;
- }
-
- return status;
-}
-
-
-PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos)
-{
- return (pdu[pos+0] << 24) +
- (pdu[pos+1] << 16) +
- (pdu[pos+2] << 8) +
- (pdu[pos+3]);
-}
-
-
-/*
- * Handle incoming data from peer
- * This function is called by client_on_read_complete() below.
- */
-static void client_handle_peer_data(struct turn_client *client,
- unsigned bytes_read)
-{
- struct peer *peer;
- pj_bool_t has_magic_cookie;
- pj_status_t status;
-
- /* Has the sender been registered as peer? */
- peer = client_get_peer(client, &client->pkt_src_addr, NULL);
- if (peer == NULL) {
- /* Nope. Discard packet */
- PJ_LOG(5,(THIS_FILE,
- "TURN client %s: discarded data from %s:%d",
- client->obj_name,
- pj_inet_ntoa(client->pkt_src_addr.sin_addr),
- (int)pj_ntohs(client->pkt_src_addr.sin_port)));
- return;
- }
-
- /* Check if packet has STUN magic cookie */
- has_magic_cookie = (GET_VAL32(client->pkt, 4) == PJ_STUN_MAGIC);
-
- /* If this is the Active Destination and the packet doesn't have
- * STUN magic cookie, send the packet to client as is.
- */
- if (peer == client->active_peer && !has_magic_cookie) {
- pj_stun_usage_sendto(client->tu->usage, client->pkt, bytes_read, 0,
- &client->client_src_addr, sizeof(pj_sockaddr_in));
- } else {
- /* Otherwise wrap in Data Indication */
- pj_stun_tx_data *data_ind;
-
- status = pj_stun_session_create_ind(client->session,
- PJ_STUN_DATA_INDICATION,
- &data_ind);
- if (status != PJ_SUCCESS)
- return;
-
- pj_stun_msg_add_sockaddr_attr(data_ind->pool, data_ind->msg,
- PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE,
- &client->pkt_src_addr,
- client->pkt_src_addr_len);
- pj_stun_msg_add_binary_attr(data_ind->pool, data_ind->msg,
- PJ_STUN_ATTR_DATA,
- client->pkt, bytes_read);
-
-
- pj_stun_session_send_msg(client->session, PJ_FALSE,
- &client->client_src_addr,
- sizeof(pj_sockaddr_in),
- data_ind);
- }
-}
-
-
-/*
- * This callback is called by the ioqueue when read operation has
- * completed on the allocated relay port.
- */
-static void client_on_read_complete(pj_ioqueue_key_t *key,
- pj_ioqueue_op_key_t *op_key,
- pj_ssize_t bytes_read)
-{
- enum { MAX_LOOP = 10 };
- struct turn_client *client;
- unsigned count;
- pj_status_t status;
-
- PJ_UNUSED_ARG(op_key);
-
- client = (struct turn_client*) pj_ioqueue_get_user_data(key);
-
- /* Lock client */
- pj_mutex_lock(client->mutex);
-
- for (count=0; ; ++count) {
- unsigned flags;
-
- if (bytes_read > 0) {
- /* Received data from peer! */
- client_handle_peer_data(client, bytes_read);
-
- } else if (bytes_read <= 0) {
- char errmsg[PJ_ERR_MSG_SIZE];
- pj_strerror(-bytes_read, errmsg, sizeof(errmsg));
- PJ_LOG(4,(THIS_FILE, "TURN client %s: error reading data "
- "from allocated relay port: %s",
- client->obj_name, errmsg));
- }
-
- bytes_read = sizeof(client->pkt);
- flags = (count >= MAX_LOOP) ? PJ_IOQUEUE_ALWAYS_ASYNC : 0;
- client->pkt_src_addr_len = sizeof(client->pkt_src_addr);
- status = pj_ioqueue_recvfrom(client->key,
- &client->pkt_read_key,
- client->pkt, &bytes_read, flags,
- &client->pkt_src_addr,
- &client->pkt_src_addr_len);
- if (status == PJ_EPENDING)
- break;
- }
-
- /* Unlock client */
- pj_mutex_unlock(client->mutex);
-}
-
-
-/* On Allocation timer timeout (i.e. we don't receive new Allocate request
- * to refresh the allocation in time)
- */
-static void client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e)
-{
- struct turn_client *client;
-
- PJ_UNUSED_ARG(th);
-
- client = (struct turn_client*) e->user_data;
-
- PJ_LOG(4,(THIS_FILE, "TURN client %s: allocation timer timeout, "
- "destroying client",
- client->obj_name));
- client_destroy(client, PJ_SUCCESS);
-}
-
diff --git a/pjnath/src/pjstun-srv-test/usage.c b/pjnath/src/pjstun-srv-test/usage.c
deleted file mode 100644
index 3ab08c18..00000000
--- a/pjnath/src/pjstun-srv-test/usage.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "server.h"
-
-struct worker
-{
- pj_ioqueue_op_key_t read_key;
- unsigned index;
- pj_uint8_t readbuf[4000];
- pj_sockaddr src_addr;
- int src_addr_len;
-};
-
-struct pj_stun_usage
-{
- pj_pool_t *pool;
- pj_stun_server *srv;
- pj_mutex_t *mutex;
- pj_stun_usage_cb cb;
- int type;
- pj_sock_t sock;
- pj_ioqueue_key_t *key;
- unsigned worker_cnt;
- struct worker *worker;
-
- pj_ioqueue_op_key_t *send_key;
- unsigned send_count, send_index;
-
- pj_bool_t quitting;
- void *user_data;
-};
-
-
-static void on_read_complete(pj_ioqueue_key_t *key,
- pj_ioqueue_op_key_t *op_key,
- pj_ssize_t bytes_read);
-
-/*
- * Create STUN usage.
- */
-PJ_DEF(pj_status_t) pj_stun_usage_create( pj_stun_server *srv,
- const char *name,
- const pj_stun_usage_cb *cb,
- int family,
- int type,
- int protocol,
- const pj_sockaddr_t *local_addr,
- int addr_len,
- pj_stun_usage **p_usage)
-{
- pj_stun_server_info *si;
- pj_pool_t *pool;
- pj_stun_usage *usage;
- pj_ioqueue_callback ioqueue_cb;
- unsigned i;
- pj_status_t status;
-
- si = pj_stun_server_get_info(srv);
-
- pool = pj_pool_create(si->pf, name, 4000, 4000, NULL);
- usage = PJ_POOL_ZALLOC_T(pool, pj_stun_usage);
- usage->pool = pool;
- usage->srv = srv;
-
- status = pj_mutex_create_simple(pool, name, &usage->mutex);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- usage->type = type;
- status = pj_sock_socket(family, type, protocol, &usage->sock);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- status = pj_sock_bind(usage->sock, local_addr, addr_len);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb));
- ioqueue_cb.on_read_complete = &on_read_complete;
- status = pj_ioqueue_register_sock(usage->pool, si->ioqueue, usage->sock,
- usage, &ioqueue_cb, &usage->key);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- usage->worker_cnt = si->thread_cnt;
- usage->worker = (struct worker*) pj_pool_calloc(pool, si->thread_cnt,
- sizeof(struct worker));
- for (i=0; i<si->thread_cnt; ++i) {
- pj_ioqueue_op_key_init(&usage->worker[i].read_key,
- sizeof(usage->worker[i].read_key));
- usage->worker[i].index = i;
- }
-
- usage->send_count = usage->worker_cnt * 2;
- usage->send_key = (pj_ioqueue_op_key_t*)
- pj_pool_calloc(pool, usage->send_count,
- sizeof(pj_ioqueue_op_key_t));
- for (i=0; i<usage->send_count; ++i) {
- pj_ioqueue_op_key_init(&usage->send_key[i],
- sizeof(usage->send_key[i]));
- }
-
- for (i=0; i<si->thread_cnt; ++i) {
- pj_ssize_t size;
-
- size = sizeof(usage->worker[i].readbuf);
- usage->worker[i].src_addr_len = sizeof(usage->worker[i].src_addr);
- status = pj_ioqueue_recvfrom(usage->key, &usage->worker[i].read_key,
- usage->worker[i].readbuf, &size,
- PJ_IOQUEUE_ALWAYS_ASYNC,
- &usage->worker[i].src_addr,
- &usage->worker[i].src_addr_len);
- if (status != PJ_EPENDING)
- goto on_error;
- }
-
- pj_stun_server_register_usage(srv, usage);
-
- /* Only after everything has been initialized we copy the callback,
- * to prevent callback from being called when we encounter error
- * during initialiation (decendant would not expect this).
- */
- pj_memcpy(&usage->cb, cb, sizeof(*cb));
-
- *p_usage = usage;
- return PJ_SUCCESS;
-
-on_error:
- pj_stun_usage_destroy(usage);
- return status;
-}
-
-
-/**
- * Destroy usage.
- */
-PJ_DEF(pj_status_t) pj_stun_usage_destroy(pj_stun_usage *usage)
-{
- pj_stun_server_unregister_usage(usage->srv, usage);
- if (usage->cb.on_destroy)
- (*usage->cb.on_destroy)(usage);
-
- if (usage->key) {
- pj_ioqueue_unregister(usage->key);
- usage->key = NULL;
- usage->sock = PJ_INVALID_SOCKET;
- } else if (usage->sock != 0 && usage->sock != PJ_INVALID_SOCKET) {
- pj_sock_close(usage->sock);
- usage->sock = PJ_INVALID_SOCKET;
- }
-
- if (usage->mutex) {
- pj_mutex_destroy(usage->mutex);
- usage->mutex = NULL;
- }
-
- if (usage->pool) {
- pj_pool_t *pool = usage->pool;
- usage->pool = NULL;
- pj_pool_release(pool);
- }
-
- return PJ_SUCCESS;
-}
-
-
-/**
- * Set user data.
- */
-PJ_DEF(pj_status_t) pj_stun_usage_set_user_data( pj_stun_usage *usage,
- void *user_data)
-{
- usage->user_data = user_data;
- return PJ_SUCCESS;
-}
-
-/**
- * Get user data.
- */
-PJ_DEF(void*) pj_stun_usage_get_user_data(pj_stun_usage *usage)
-{
- return usage->user_data;
-}
-
-
-/**
- * Send with the usage.
- */
-PJ_DEF(pj_status_t) pj_stun_usage_sendto( pj_stun_usage *usage,
- const void *pkt,
- pj_size_t pkt_size,
- unsigned flags,
- const pj_sockaddr_t *dst_addr,
- unsigned addr_len)
-{
- pj_ssize_t size = pkt_size;
- unsigned i, count = usage->send_count, index;
-
- pj_mutex_lock(usage->mutex);
- for (i=0, ++usage->send_index; i<count; ++i, ++usage->send_index) {
- if (usage->send_index >= usage->send_count)
- usage->send_index = 0;
-
- if (pj_ioqueue_is_pending(usage->key, &usage->send_key[usage->send_index])==0) {
- break;
- }
- }
-
- if (i==count) {
- pj_mutex_unlock(usage->mutex);
- return PJ_EBUSY;
- }
-
- index = usage->send_index;
- pj_mutex_unlock(usage->mutex);
-
- return pj_ioqueue_sendto(usage->key, &usage->send_key[index],
- pkt, &size, flags,
- dst_addr, addr_len);
-}
-
-
-static void on_read_complete(pj_ioqueue_key_t *key,
- pj_ioqueue_op_key_t *op_key,
- pj_ssize_t bytes_read)
-{
- enum { MAX_LOOP = 10 };
- pj_stun_usage *usage = (pj_stun_usage*) pj_ioqueue_get_user_data(key);
- struct worker *worker = (struct worker*) op_key;
- unsigned count;
- pj_status_t status;
-
- for (count=0; !usage->quitting; ++count) {
- unsigned flags;
-
- if (bytes_read > 0) {
- (*usage->cb.on_rx_data)(usage, worker->readbuf, bytes_read,
- &worker->src_addr, worker->src_addr_len);
- } else if (bytes_read < 0) {
- pj_stun_perror(usage->pool->obj_name, "recv() error", -bytes_read);
- }
-
- if (usage->quitting)
- break;
-
- bytes_read = sizeof(worker->readbuf);
- flags = (count >= MAX_LOOP) ? PJ_IOQUEUE_ALWAYS_ASYNC : 0;
- worker->src_addr_len = sizeof(worker->src_addr);
- status = pj_ioqueue_recvfrom(usage->key, &worker->read_key,
- worker->readbuf, &bytes_read, flags,
- &worker->src_addr, &worker->src_addr_len);
- if (status == PJ_EPENDING)
- break;
- else if (status != PJ_SUCCESS)
- bytes_read = -status;
- }
-}
-