/*
 * Copyright (C) 2008 The Trustees of Columbia University in the City of New York. 
 * All rights reserved.
 *
 * See the file LICENSE included in this distribution for details.
 */

#ifndef __PJNATH_CLIENT__
#define __PJNATH_CLIENT__

#include <pjnath.h>
#include <pjlib-util.h>
#include <pjlib.h>
#define IPADDRLEN 16
#define PORTLEN 10
#define BUF_LEN_P2PP 1500

typedef struct client_options {

  pj_sock_t		 sock;
  pj_thread_t		*thread;

  //buffer used for receiving data. send buffer is pkt
  char		 data[BUF_LEN_P2PP];    
  //length of the packet received
  int			 datalen;               

  char    ch_srv_addr[IPADDRLEN];
  char    ch_srv_port[PORTLEN];
  char    *realm;
  char    *user_name;
  char    *password;
  char    *nonce;

  pj_bool_t         use_fingerprint;
  pj_stun_config	  stun_config;
  pj_pool_t		      *pool;
  pj_caching_pool	  cp;
  pj_timer_heap_t	  *th;
  pj_stun_session	  *sess;

  pj_bool_t		      quit;
  pj_sockaddr_in	  peer_addr;      //my own address, port is SIP, P2PP, media
  pj_sockaddr_in	  srv_addr;       //STUN server address
  pj_sockaddr_in	  response_addr;  //relay addr attr
  pj_sockaddr_in	  binding_addr;   //srflex addr attr
  
  pj_sockaddr_in    remote_addr;    

  pj_status_t		    detect_result;
  pj_stun_nat_type  nat_type;
  pj_stun_msg_type  response_type;
  size_t				pktlen;             //length of send buffer
  char			    pkt[BUF_LEN_P2PP];  //buffer used for sending data

  //for ice
  pj_ice_sess			    *ice;
  pj_ice_sess_cand    rcand[3];
  int                 rcand_cnt;
  //pj_ioqueue_key_t     *key; /**< ioqueue key.*/
  //pj_ioqueue_op_key_t  read_op;/**< ioqueue read operation key*/
  pj_sockaddr          src_addr;
  int                  src_addr_len;

} ClientOptions;
/*
void set_config(struct client_options *client_options);
*/

int init_pjnath();
int init_client(ClientOptions *g);
int shutdown_client(ClientOptions *g);


int change_stun_srv(ClientOptions *g, char* srv_ip, char* srv_port);


/*
 *sends a bind, allocate request to g->srv_addr. 
 *STUN/TURN server address discovered using LookupStunPort
 */
void send_bind_request(int sock, ClientOptions *g);
void send_allocate_request(int sock, pj_bool_t allocate, 
                           ClientOptions *g);
void send_raw_data_to_srv(int sock,  ClientOptions *g);

void create_send_ind(ClientOptions* g, char *buf, int *len);


pj_stun_nat_type perform_detection(ClientOptions *g);

int stun_msg_check(unsigned char* buffer, int len);

int parse_stun_msg(ClientOptions *g, 
		   unsigned char* buffer, int len, 
		   pj_sockaddr_in *addr, int addrlen,  
		   pj_stun_msg_type *msg_type, int *result,
		   pj_sockaddr_in *result_addr);


/*
*These functions are defined in pjnath_ice.c
*/
void init_ice(ClientOptions *g);

void set_ice_local_cand_host(ClientOptions *g, 
			     struct pj_sockaddr_in *addr);

void set_ice_local_cand_srflex(ClientOptions *g, 
			       struct pj_sockaddr_in *addr);

void set_ice_local_cand_relay(ClientOptions *g, 
			      struct pj_sockaddr_in *addr);

void set_ice_remote_cand_host(ClientOptions *g, 
			      struct pj_sockaddr_in *addr);

void set_ice_remote_cand_srflex(ClientOptions *g, 
				struct pj_sockaddr_in *addr);

void set_ice_remote_cand_relay(ClientOptions *g, 
			       struct pj_sockaddr_in *addr);

void create_ice_cand(pj_ice_sess_cand *rcand,
		     unsigned comp_id,
		     pj_ice_cand_type type,
		     pj_ice_sess *ice, 
		     const pj_sockaddr_t *addr,
		     const pj_sockaddr_t *base_addr,
		     int addr_len);

void start_check(ClientOptions *g,
		 pj_ice_sess_cand *rcand);

void destroy_ice_sess(ClientOptions *g,
					  pj_ice_sess *ice);

void get_valid_rcand(ClientOptions *g,
		     char *ipaddr, 
		     unsigned short *port,
         char *type);

void listen_for_ice(ClientOptions *g);

int is_ice_complete(ClientOptions *g);

/*
 *sends raw data to relay_address (IP:port)
 *used in testing
 */
void send_raw_data_to_relay(int sock, char *relay_address, 
                            ClientOptions *g);

/*
 *set active destination
 *used in testing
 */
void send_sad_request(int sock, pj_bool_t set, 
		      char *active_dest_addr, 
		      ClientOptions *g);

#endif //__PJNATH_CLIENT__
