/*
  The osipua library is a library based on oSIP that implements CallLeg and User Agent
  level.
  Copyright (C) 2001  Simon MORLAT simon.morlat@free.fr
  											Aymeric MOIZARD jack@atosc.org
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef OSIPMANAGER_H
#define OSIPMANAGER_H

#undef HAVE_CONFIG_H
#include <osipua-config.h>
#include <osip/osip.h>
#include <osip/port.h>
#include <osip/thread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <sys/time.h>
#include <sys/types.h>

#define OSIP_MAX_UDP_PORTS 5



typedef struct _OsipManager
{
	osip_t *config;
	int send_sock;											/* the socket used to send requests and responses */
	int send_port;												/* the port from which requests and responses are sent*/
	int udpports[OSIP_MAX_UDP_PORTS];  /* table of listening ports*/
	int udpfds[ OSIP_MAX_UDP_PORTS];  /* the corresponding table of file descripor */
	fd_set udpfdset;                           /* set of scanned file descripors */
	int max_udpfd;											/* highest file descriptor */
	int udp_control_fd;									  /* a control file descriptor to interrupt select() when needed*/
	int udp_unblock_fd;
	int udp_run_cond;										/* the running condition for the sipd thread*/
	int resolv_run_cond;									/* the running condition for the resolution thread */
	char *udp_buf;													/* the buffer used for receiving udp messages*/
	sthread_t udp_thread;  					/* the udp thread control structure*/
	int thread_pid;
	sthread_t resolv_thread;							/*the name resolution thread */
	struct timeval recv_tout;                     /* the select timeout in udp_receive */
	fifo_t *resolv_fifo;
	smutex_t *mutex;
	fifo_t garbage_trn;
} OsipManager;

OsipManager* osip_manager_new();

int osip_manager_add_udpport(OsipManager *manager, int port);

int osip_manager_remove_udpport(OsipManager *manager, int port);

void osip_manager_start_udp_daemon(OsipManager *manager);

void osip_manager_stop_udp_daemon(OsipManager *manager);

void osip_manager_start_resolver(OsipManager *manager);

void osip_manager_stop_resolver(OsipManager *manager);

int osip_manager_set_send_port(OsipManager *manager,int port);

void osip_manager_destroy(OsipManager *manager);


/* osip callbacks */
void ict_kill_transaction(transaction_t* trn);
void ict_1xx_received(transaction_t* trn, sip_t* msg);
void ict_2xx_received(transaction_t* trn, sip_t* sipmsg);
void ict_3xx_received(transaction_t* trn, sip_t* sipmsg);
void ict_4xx_received(transaction_t* trn, sip_t* sipmsg);
void ict_5xx_received(transaction_t* trn, sip_t* sipmsg);
void ict_6xx_received(transaction_t* trn, sip_t* sipmsg);

void nict_kill_transaction(transaction_t* trn);
void nict_1xx_received(transaction_t* trn, sip_t* sipmsg);
void nict_2xx_received(transaction_t* trn, sip_t* sipmsg);
void nict_3xx_received(transaction_t* trn, sip_t* sipmsg);
void nict_4xx_received(transaction_t* trn, sip_t* sipmsg);
void nict_5xx_received(transaction_t* trn, sip_t* sipmsg);
void nict_6xx_received(transaction_t* trn, sip_t* sipmsg);

void ist_kill_transaction(transaction_t * trn);
void ist_invite_received(transaction_t * trn, sip_t *sipmsg);
void ist_ack_received(transaction_t * trn, sip_t *sipmsg);

void nist_kill_transaction(transaction_t * trn);
void nist_register_received(transaction_t * trn, sip_t *sipmsg);
void nist_bye_received(transaction_t * trn, sip_t *sipmsg);
void nist_cancel_received(transaction_t * trn, sip_t *sipmsg);
void nist_options_received(transaction_t * trn, sip_t *sipmsg);

extern OsipManager *def_manager;

/* send a sip response from a transaction */
void osip_send_response(OsipManager *mgr,transaction_t *transaction,sip_t *response);

int udp_send(transaction_t *trn, sip_t *sipmsg,char *host,int port,int sock);

#define osip_manager_wake_up(manager) write((manager)->udp_control_fd,"n",1);

#endif
