#ifndef __GDB_KDP_UDP_H__
#define __GDB_KDP_UDP_H__

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include "kdp-protocol.h"

struct kdp_connection {

  /* connection information */

  kdp_log_function *logger;

  kdp_pkt_t *request;
  kdp_pkt_t *response;

  kdp_pkt_t *exc_request;
  kdp_pkt_t *exc_response;

  kdp_pkt_t *saved_exception;
  int saved_exception_pending;

  unsigned int receive_timeout; 
  unsigned int retries;

  int port;
  int bigendian;

  unsigned int session_key;	 /* obtained from target */

  int reqfd;			 /* socket for normal target */
  unsigned short reqport;	 /* udp port in req_reply_fd */
  int excfd;			 /* socket for target exceptions */
  unsigned short excport;	 /* udp port in excep_fd */

  unsigned int seqno;		 /* next request seq # */
  unsigned int exc_seqno;

  struct sockaddr_in target_sin; /* target communication addrs */

  int connected;
  int bound;
  int timed_out;
};

typedef struct kdp_connection kdp_connection;

kdp_return_t kdp_transmit_fd
  (kdp_connection *c, kdp_pkt_t *packet, int fd);

kdp_return_t kdp_receive_fd
  (kdp_connection *c, kdp_pkt_t *packet, int fd, int timeout);

kdp_return_t kdp_transmit_debug
  (kdp_connection *c, kdp_pkt_t *packet);

kdp_return_t kdp_transmit_exception
  (kdp_connection *c, kdp_pkt_t *packet);

kdp_return_t kdp_receive_debug
   (kdp_connection *c, kdp_pkt_t *packet, int timeout);

kdp_return_t kdp_receive_exception
  (kdp_connection *c, kdp_pkt_t *packet, int timeout);

kdp_return_t kdp_receive
  (kdp_connection *c, kdp_pkt_t *packet, int timeout);

const char *kdp_return_string
  (kdp_return_t error);

kdp_return_t kdp_create
  (kdp_connection *c, kdp_log_function *logger, 
   const char *target, unsigned int port, 
   int timeout, int retries);

kdp_return_t kdp_destroy 
  (kdp_connection *c);

void kdp_set_timeouts
  (kdp_connection *c, int timeout, int retries);

void kdp_set_big_endian (kdp_connection *c);
void kdp_set_little_endian (kdp_connection *c);

void kdp_reset (kdp_connection *c);

int kdp_is_bound (kdp_connection *c);
int kdp_is_connected (kdp_connection *c);

#endif /* __GDB_KDP_UDP_H__ */
