/* $Id$ */
/* 
 * Copyright (C) 2003-2005 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;

    status = pj_stun_config_create(srv->si.pf, 0, srv->si.ioqueue, 
				     srv->si.timer_heap, &srv->si.cfg);
    if (status != PJ_SUCCESS)
	goto on_error;

    srv->si.thread_cnt = thread_cnt;
    srv->threads = 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_stun_config_destroy(srv->si.cfg);
    pj_timer_heap_destroy(srv->si.timer_heap);
    pj_ioqueue_destroy(srv->si.ioqueue);
    pj_pool_release(srv->pool);

    return PJ_SUCCESS;
}


