/*
  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 OSIPUA_H
#define OSIPUA_H


#include <stdio.h>
#undef PACKAGE
#undef VERSION
#undef HAVE_CONFIG_H
#include <osipua-config.h>

#include <osip/osip.h>
#include <osip/port.h>
#include <osip/smsgtypes.h>
#include <osip/sdp.h>
#include <osip/dialog.h>

#define IP4_SIZE 20
#ifdef INET6
#define IP_SIZE 40
#endif

#ifdef __cplusplus
extern "C"{
#endif

#include "osipmanager.h"

/* used by the osip_trace macro*/
char *make_message (const char *fmt, ...);

#define osip_trace(loglevel,args)  do        \
{                       \
	char *__strmsg;  \
	__strmsg=make_message args ;    \
	OSIP_TRACE(osip_trace(__FILE__,__LINE__,(loglevel),NULL,"%s\n",__strmsg)); \
	sfree (__strmsg);        \
}while (0);

struct _OsipDialog
{
	from_t *from;
	int status;
	url_t *registrar;
	dialog_t *dialog;
	char *received;	/* ip address of the originator */
	char *localip;	/* local ip address to use for this dialog*/
	/* transactions associated with call-leg */
	transaction_t *inc_invite_tr;
	transaction_t *out_invite_tr;
	transaction_t *inc_bye_tr;
	transaction_t *out_bye_tr;
	transaction_t *inc_cancel_tr;
	transaction_t *out_cancel_tr;
	transaction_t *out_register_tr;

	/* list_t incoming_transactions; */
	/* list_t outgoing_transactions; */

	struct _RegistrationCtxt *reg_context;	/* the registration context if a registration is occuring */
	int inv_auth_count;
	int reg_auth_count;
	int resp180_count;
	unsigned int tag_set:1;
	unsigned int padding:31;

	struct _OsipUA *ua;	/* the ua object that manages the call */
	list_t body_contexts;	/* the active body contexts */
	void *data;
};

typedef struct _OsipDialog OsipDialog;


typedef int (*OsipUACallbackFunc) (OsipDialog *, transaction_t *, sip_t *,
				   void *);


	

/* the user agent class*/
struct _OsipUA
{
	osip_t *config;		/* the config structure driving the stack */
	struct _OsipManager *manager;	/* the manager object that manages the stack on which the ua is running */	
	contact_t *contact;	/* the user agent real identity, like machin@217.0.0.128 */
	list_t *alias;		/* list of alias like machin@www-db.research.bell-labs.com, including address of records */
	char *fromtag;		/* the from tag put in all from fields of the requests */
	char ua_ip4addr[IP4_SIZE];
#ifdef INET6
        int ua_family;
        char ua_ipaddr[IP_SIZE];
#endif
	int ua_port;
	list_t call_list;	/* the list of dialogs managed by the user agent */
	int max_dialogs;		/* the number of active dialogs of ua will process. If the limit is exceeded, it will answer BUSY HERE */
	int dialog_count;	/* number of active dialogs */
	url_t *registrar;	/* sip url of a registrar. This is also the address of the proxy if the OSIPUA_USE_PROXY flag is set */
	char *reg_passwd;	/* the password used for registration */
	unsigned int flags;
#define OSIP_UA_USE_PROXY (0x0001)
	//struct _MediaDesc *maudio;     /* a MediaDescriptor for audio*/
	//struct _MediaDesc *mvideo;     /* a MediaDescriptor for video*/
	/*signals */
	OsipUACallbackFunc invite;/*INVITE*/ 
	OsipUACallbackFunc invite_accepted;	/*INVITE_ACCEPTED *//* called to signal that media sessions can start */
	OsipUACallbackFunc bye;/*BYE*/ 
	OsipUACallbackFunc faillure;	/* FAILLURE */
	OsipUACallbackFunc informative;	/*various informations */
	FILE *dbg;

	/* presence management infos */
	int presence_mode;	/* 200-> accept calls
				 * 486-> answer automatic 486 Busy
				 * 600-> 600 Busy Evrywhere
				 * 480-> answar automatic 480 Temporirily unavailable
				 * 302-> Moved temporarily
				 * 380-> Alternative service */
	int presence_delay;	/* a value in seconds to ba added to Retry-After
				 * in 486 Busy or 480 Temporirily unavailable */
	char *presence_contact_url;	/* contain a sip-url for 302, 301, 380.
					 * TO BE DONE: Can also contain an email instead of url!
					 */
	list_t body_handlers;
	void *data;
};


typedef struct _OsipUA OsipUA;

#include "bodyhandler.h"
#include "bodycontext.h"

/* initialize the osipua library */
void osipua_init ();

/* stop the threads runned by osipua */
void osipua_exit ();

/* create new user agent with given parameters*/
OsipUA *osip_ua_new ();

/*set (or change) ua ip address*/
void osip_ua_set_ip4addr (OsipUA * ua, char *ip4addr, int port);
#ifdef INET6
void osip_ua_set_ipaddr (OsipUA * ua, char *ipaddr, int port, int ua_family);
#endif

void osip_ua_set_max_dialogs (OsipUA * ua, int max);

/* change identity of an existent user agent*/
int osip_ua_set_contact (OsipUA * ua, char *contact);

/* add an alias identity to which the ua is supposed to answser */
int osip_ua_add_alias (OsipUA * ua, char *contact);

/* remove an alias*/
int osip_ua_remove_alias (OsipUA * ua, char *contact);

/* remove all aliases */
void osip_ua_clean_alias (OsipUA * ua);

/* set a default registrar where REGISTER are sent. To unset, give registrar=NULL. */
int osip_ua_set_registrar (OsipUA * ua, char *registrar, char *passwd);

/* set a proxy to which all requests are sent. It does the same as osip_ua_set_registrar() but also indicate that the registrar
is also a proxy */
int osip_ua_set_outbound_proxy (OsipUA * ua, char *proxy, char *passwd);

/* set information about presence: this let the user agent to answer automatically
to incoming calls */
void osip_ua_set_presence_mode (OsipUA * ua, int mode);

/* set contact information used by presence modes 480, 301, 380.*/
void osip_ua_set_presence_contact_url (OsipUA * ua, char *url);

/* set the retry after */
void osip_ua_set_presence_delay (OsipUA * ua, int delay);

void osip_ua_add_body_handler (OsipUA * ua, BodyHandler * info);

/*register callbacks to be advertised when an invite arrives, a sent invite is accepted, or a bye is received, or a faillure occured*/
int osip_ua_signal_connect (OsipUA * ua, char *signal,OsipUACallbackFunc func);

OsipDialog * osip_ua_get_dialog(OsipUA *ua, int number);

/* destroy and free all ressources allocated by user_agent*/
int osip_ua_destroy (OsipUA * ua);



#include "osipdialog.h"

/**********************************************************************************************************************************************************************/
/*																				Private Functions: do not use them in an application																						*/
/***********************************************************************************************************************************************************************/

extern list_t ua_list;


/* find the user agent to which the message is destinated*/
OsipUA *osip_ua_find (sip_t * sipmsg);

BodyHandler *osip_ua_find_handler (OsipUA * ua, char *body_mime);

#ifdef __cplusplus
}
#endif

#endif
