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

#ifndef _WENGO
#include "types.h"
#include "node.h"
#endif

#ifdef _WENGO
#include "p2pp/common/types.h"
#include "p2pp/node/node.h"
#include "p2pp/node/client.h"
#endif

#include <map>
using namespace std;

#ifdef _LINUX_
#include <sys/socket.h>
#endif

#ifdef WIN32
#include <winsock.h>
#endif

#define TIMEOUT 500000

class Node;
struct port_trans;

enum SOCK_OPTIONS {S_TCP_NODELAY=10, S_TCP_QUICKACK, S_TCP_INFO, S_SNDBUF, S_RCVBUF, S_WQ, S_RQ};

struct _tcp_info {
 uint32 tcpi_snd_cwnd;
  uint32 tcpi_snd_ssthresh;
  uint32 tcpi_snd_mss;
  uint32 tcpi_rcv_mss;
  uint32 tcpi_lost;
  uint32 tcpi_total_retrans;
  uint32 tcpi_rtt;
  uint32 tcpi_rcv_rtt;
  uchar  tcpi_ca_state;

public:
  _tcp_info()  {
    tcpi_snd_cwnd=1;
    tcpi_snd_ssthresh=1;
    tcpi_snd_mss=1;
    tcpi_rcv_mss=1;
    tcpi_lost=1;
    tcpi_total_retrans=1;
    tcpi_ca_state=1;
  }
};



class Transport {

private:
  Node* m_pobjNode;

  int32 m_uiTcpPort;
  int32 m_uiUdpPort;
  int32 m_iTcpSock;
  int32 m_iUdpSock;

  fd_set sockfds;
  int32 sockmax;

  //socket maps
  map<string, int32> m_SL;      //listener socket
  map<string, int32> m_nSL;
  map<string, int32> m_rSL;
  
  //buffer to receive data in
  uchar m_buf[65000];

  uint32 m_curS;
  uint32 m_prevS;

  uint32 m_curR;
  uint32 m_prevR;
  struct timeval m_timeSR;

  int32 isConnected;
  int32 m_Listen;

private:
  void build_select_list();
  void handle_new_connection();
  void read_socks();
  int32 sockcon(char* ip, int32 port);

public:

  Transport();
  ~Transport();
  void setNode(Node* pobjNode);

  int32 Send(uchar* buf, uint32 len, char* ip, int32 port, transtype eType);

  void Initialize(int32 iTcpPort, int32 iUdpPort);
  
  int32 getAddress(int32& num, char8 addr[][IPADDRLEN], uint16 port[], uchar ht[], uchar tt[]);

  int32 getAddrPort(map<string, port_trans>& addrmap);


  void getSendRecvBW(uint32& sbw, uint32& rbw);

  void Disconnect();

  static int32 gethostbyname(char* name, string& strIP);
  static int32 gethostbyaddr(char* ip, string& strHostName);  

  static int getsockopt_tcp(int sockid, enum SOCK_OPTIONS options, void* optval, int* optlen);

  void ListenLoop() ;

  void SuspendListen(){
    m_Listen=0;
  }

  int getUDPSocket() {
    return m_iUdpSock;
  }
};

#endif
