/* $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);
}
