/*
 * 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.
 */

#include "peer.h"
#include "cpuutil.h"

#ifndef _WENGO
#include "trace.h"
#include "genhash.h"
#endif

#ifdef _WENGO
#include "p2pp/common/trace.h"
#include "p2pp/utils/genhash.h"
#endif

extern CpuUtil* gCpuUtilization;

//this structure contains values for program
//and machine bw, cpuutil, and memory. if the
//appropriate values are set, then actual bandwidth/cpu/mem
//is not calculated. rather the set bw/cpuutil/mem is used.
struct nodeval g_stnodeval;

//for switch
enum PeerState Peer::m_eState=ePBOOTSTRAP;  
enum PeerSubState Peer::m_eSubState=eS_PNONE;

list<peerinfo> Peer::m_BSP;

char8 Peer::m_STUN_IP[IPADDRLEN];
uint16 Peer::m_STUN_PORT;

Peer::Peer() {

}//Peer


Peer::~Peer() {
  //delete pRoutingTable;
  //delete pNeighborTable;
}//~Peer


void Peer::Initialize() {

  //HACK FOR CMDCLIENT
  /*
  int32 flag=0;
  if(m_eState == ePCONNECTED) {
    flag=1;
  }
  */
  //HACK FOR CMDCLIENT ENDS

  if( ePEER == m_NODE_TYPE || eCLIENT == m_NODE_TYPE || eAUTO == m_NODE_TYPE) {
    /*
    m_eState = ePBOOTSTRAP;
    //Set the ID to zero
    for(int i=0; i<4; i++) {
      m_ID[i]=0;
    }
    //TEMP
    idlen = 4;
    */
  } else {
    m_eState = ePINITIAL;
    idlen = m_HASH_SIZE;
  }
  
  //HACK FOR CMDCLIENT
  /*
  if(1==flag) {
    m_eState = ePCONNECTED;

    //create self ID based on user-ID
    getHash((uchar*)m_USERID, strlen((char*)m_USERID), (uchar*)m_ID, m_HASH_SIZE, m_HASH_ALG);

    idlen = m_HASH_SIZE;

  }
  */
  //HACK FOR CMDCLIENT ENDS

  //m_uiTransId = 0;

  //Initialize node timers
  m_RMT=45;
  //m_KAT=30;
  m_KAT=5;
  m_TT=10;

  //set the peer pointer in the respective helper classes. 
  //1) resource manager 2) mainthelper 3) stun turn ice manager

  m_objRM.setParams(this);
  m_objMH.setParams(this, &m_objRM);
  m_objSTI.setParams(this);

  Node::Initialize();

}//Initialize


void Peer::OnTimer() {
  //
  /*
  if(onTimerCallback) {
    onTimerCallback(m_pApp);
  }*/
  Node::OnTimer();

}//OnTimer


  

int32 Peer::getSelfPeer(struct peerinfo& stP) {

  map<string, port_trans> addrmap;
  map<string, int> relaymap;
  map<string, port_trans>::iterator itr;
  map<string, int>::iterator itrrelay;

  //PeerInfo
  stP.stobj.objtype = ePEERINFO;
  stP.isPresent = 1;

  //Peer-Id
  memcpy(stP.stpeerid.id, m_ID, idlen);
  stP.stpeerid.stobj.length = idlen;
  stP.stpeerid.isPresent=1;

  //Get the addressinfo object from transport
  m_pobjTransport->getAddrPort(addrmap);

  //Fill the table
  int i=0;
  for(itr=addrmap.begin(); itr!=addrmap.end(); itr++, i++) {

    strncpy(stP.staddr.addr[i], (char*)itr->first.c_str(), 16);
    stP.staddr.port[i] = itr->second.port;
    stP.staddr.tt[i]   = itr->second.tt;
    stP.staddr.ht[i]   = itr->second.ht;
    stP.staddr.ipver[i]=4;

    stP.staddr.R[i] = 0;
    stP.staddr.foundation[i] = 0;
    stP.staddr.compid[i] = 0;
    stP.staddr.priority[i] = 0;
    
  }//end for

  //add relay address
  relaymap.clear();
  m_objSTI.GetRelayAddr(stP.staddr.port[0], relaymap);
  for(itrrelay=relaymap.begin(); itrrelay!=relaymap.end(); itrrelay++, i++) {

    strncpy(stP.staddr.addr[i], (char*)itrrelay->first.c_str(), 16);
    stP.staddr.port[i] = itrrelay->second;
    stP.staddr.tt[i]   = eUDP;
    stP.staddr.ht[i]   = eRELAYED;
    stP.staddr.ipver[i]=4;

    stP.staddr.R[i] = 0;
    stP.staddr.foundation[i] = 0;
    stP.staddr.compid[i] = 0;
    stP.staddr.priority[i] = 0;
    
  }//end for


  //The number of address info objects
  stP.staddr.num = i;
  stP.staddr.isPresent=1;

  return i;

}//getSelfPeer



int32 Peer::getSelfID() {

  map<string, port_trans> addrmap;
  map<string, port_trans>::iterator itr;
  list<peerinfo>::iterator litr;

  //check if this is the first node
  m_pobjTransport->getAddrPort(addrmap);
  
  for(litr=m_msg.stlpeerinfo.begin(); litr!=m_msg.stlpeerinfo.end(); litr++) {
    for(itr=addrmap.begin(); itr!=addrmap.end(); itr++) {
      
      for(int i=0; i<(*litr).staddr.num; i++) {

        if(0 == strcmp((*litr).staddr.addr[i], (char*)itr->first.c_str()) &&
           (*litr).staddr.port[i] == itr->second.port) {

          memcpy(m_ID, (*litr).stpeerid.id, (*litr).stpeerid.stobj.length);

          TRACE(2, "Peer::getSelfID...Found self ID\n", "");
          return 1;
        }
      }//end for

    }//end for    
  }//end for

  return 0;

}//getSelfID



int32 Peer::CreateBNList(list<peerinfo>& l_BSP) {

  map<string, port_trans> addrmap;
  map<string, port_trans>::iterator itr;
  list<peerinfo>::iterator litr;
  int32 flag=0;
  int32 found=0;

  //check if this is the first node
  m_pobjTransport->getAddrPort(addrmap);
  

  TRACE(3, "Peer::CreateBNList...addrmapsize: %d peerinfolistsize: %d\n", addrmap.size(), m_msg.stlpeerinfo.size() );
  
  //Get a list of bootstrap peers
  for(litr=m_msg.stlpeerinfo.begin(); litr!=m_msg.stlpeerinfo.end(); litr++) {

    flag = 0;
    for(itr=addrmap.begin(); itr!=addrmap.end(); itr++) {

      for(int i=0; i<(*litr).staddr.num; i++) {

        TRACE(3, "Peer::CreateBNList...rIP: %s rPort: %d mIP: %s mPort: %d\n", (*litr).staddr.addr[i], (*litr).staddr.port[i], (char*)itr->first.c_str(), itr->second.port);

        //Check if our own IP address and port were present
        if(0 == strcmp((*litr).staddr.addr[i], (char*)itr->first.c_str()) &&
           (*litr).staddr.port[i] == itr->second.port 
           /*(*litr).staddr.tt[i] == itr->second.tt*/) {
          flag=1;
        }

        //Check for bootstrap IP address and port
        if(0 == strcmp((*litr).staddr.addr[i], m_BOOT_IP) &&
           (*litr).staddr.port[i] == m_BOOT_PORT) {
          flag=1;
        }

      }//end for
    }//end for

    //this is bootstrap peer
    if(0 == flag) {
      l_BSP.push_back(*litr);
      found=1;
    }
    flag=0;

  }//end for

  return found;

}//isBNAddrPresent



/*
  private vitual function so that IL can call getNextHop independent
  of the DHT being used.
 */
uint32 Peer::getNextHop(uchar* peerid, uint32 len, struct peerinfo& stP) {

  return 1;
}


int32 Peer::OnReceive(uchar* buf, int len, char* pchIP, int32 port, transtype tt) {
  return Node::OnReceive(buf, len, pchIP, port, tt);


}//OnReceive



int32 Peer::PublishObject(char8* pchKey, uint32 kLen, char8* pchValue, uint32 vLen, transtype tt, void* (*insertcallback)(void*, int32), void* pApp) {

  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.strKey = pchKey;
  objLO.conttype = eSTRINGVAL;
  objLO.strVal = pchValue;
  objLO.ritype = ePUBLISHOBJECT;
  objLO.changeID = 0;
  objLO.callback = insertcallback;
  objLO.pApp = pApp;

  //transport type
  objLO.tt = tt;

  m_LO.push_back(objLO);

  return 1;

}//PublishObject



int32 Peer::LookupObject (char8* pchKey, uint32 kLen, transtype tt, void* (*lookupcallback)(void*, int32), void* pApp, void* Conference ) {
  
  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.strKey = pchKey;
  objLO.conttype = eSTRINGVAL;
  objLO.ritype = eLOOKUPOBJECT;
  objLO.callback = lookupcallback;
  objLO.pApp = pApp;

  //transport type
  objLO.tt = tt;

  m_LO.push_back(objLO);

  return 1;
}//LookupObject



int32 Peer::LookupUser (char8* pchKey, uint32 kLen, transtype tt, void* (*lookupcallback)(void*, int32), void* pApp, void* Conference ) {

  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.strKey = pchKey;
  objLO.conttype = eUSERINFO;
  objLO.ritype = eLOOKUPOBJECT;
  objLO.callback = lookupcallback;
  objLO.pApp = pApp;

  //transport type
  objLO.tt = tt;

  m_LO.push_back(objLO);

  return 1;
  
}//LookupUser

int32 Peer::LookupSIP (char8* pchKey, uint32 kLen, transtype tt, void* (*lookupcallback)(void*, int32), void* pApp, void* Conference ) {

  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.strKey = pchKey;
  objLO.conttype = eSIP;
  objLO.ritype = eLOOKUPOBJECT;
  objLO.callback = lookupcallback;
  objLO.pApp = pApp;

  //transport type
  objLO.tt = tt;

  m_LO.push_back(objLO);

  return 1;
  
}//LookupSIP

/*
int32 Peer::AllocateRelay(int* sock, void* (*lookupcallback)(void*, int32), void* pApp, void* Conference ) {

}//Peer::AllocateRelay
*/
int32 Peer::GetRT(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*callback)(void*, int32 respcode), void* pApp) {

  struct LObject objLO;  
  
  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.diagtype = eGET_RT;
  objLO.ritype = eGETDIAGNOSTICS;
  strcpy(objLO.pchIP, pchIP);
  objLO.port = port;
  objLO.tt = tt;  

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
  
}//GetRT


int32 Peer::GetNT(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*callback)(void*, int32 respcode), void* pApp) {

  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.diagtype = eGET_NT;
  objLO.ritype = eGETDIAGNOSTICS;
  strcpy(objLO.pchIP, pchIP);
  objLO.port = port;
  objLO.tt = tt;

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
  
}//GetNT



int32 Peer::GetRO(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*callback)(void*, int32 respcode), void* pApp) {

  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.diagtype = eGET_RO;
  objLO.ritype = eGETDIAGNOSTICS;
  strcpy(objLO.pchIP, pchIP);
  objLO.port = port;
  objLO.tt = tt;

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
  
}//GetRO

int32 Peer::GetTurnAlloc(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*callback)(void*, int32 respcode), void* pApp) {
  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.diagtype = eGET_TURNALLOC;
  objLO.ritype = eGETDIAGNOSTICS;
  strcpy(objLO.pchIP, pchIP);
  objLO.port = port;
  objLO.tt = tt;

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
}//GetTurnAlloc

int32 Peer::GetRelayList(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*callback)(void*, int32 respcode), void* pApp) {
  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.diagtype = eGET_RELAYLIST;
  objLO.ritype = eGETDIAGNOSTICS;
  strcpy(objLO.pchIP, pchIP);
  objLO.port = port;
  objLO.tt = tt;

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
}//GetRelayList


int32 Peer::ChangeUserID(char8* pchID, uint32 ilen, void* (*callback)(void*, int32 respcode), void* pApp) {

  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  objLO.strKey = pchID;
  objLO.ritype = ePUBLISHOBJECT;
  objLO.changeID = 1;

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
  
}//ChangeUserID



int32 Peer::Set(char8* pchIP, uint32 ilen, uint16 port, transtype tt, struct nodeval& stnv, int32 isSet, void* (*callback)(void*, int32 respcode), void* pApp) {

  struct LObject objLO;

  //If not connected return immediately
  if(ePCONNECTED != m_eState) {
    return 0;
  }

  if(1==isSet) {
    objLO.ritype = eSET;
  } else {
    objLO.ritype = eRESET;
  }
  strcpy(objLO.pchIP, pchIP);
  objLO.port = port;
  objLO.tt = tt;

  //nodevalue
  objLO.stnv = stnv;

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
  
}//Set


int32 Peer::Disconnect(void* (*callback)(void*, int32 respcode), void* pApp) {

  struct LObject objLO;
  
  objLO.ritype = eLEAVE;
  objLO.disconnect = 1;

  objLO.callback = callback;
  objLO.pApp = pApp;

  m_LO.push_back(objLO);

  return 1;
  
}//Disconnect



void Peer::ComposeJoin(struct peerinfo stP) {  

  int size;
  map<string, port_trans> addrmap;
  map<string, port_trans>::iterator itr;

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;
  m_msg.stcmn_hdr.reqoritype = eJOIN;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ttl = 255;
  m_msg.stcmn_hdr.rori = m_REC;
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.slen = idlen;

  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);
 
  size=m_msg.encode(m_buf, BUFSIZE);

  message s1;
  s1.parse(m_buf, size);

  //create a transaction and pass it the message
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_ID, idlen, eREQUEST, eJOIN, eUDP);
  pTrans->Send(m_buf, size, stP.staddr.addr[0], stP.staddr.port[0]);
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++;
  
}//ComposeJoin


void Peer::ComposeJoin(struct peerinfo stP, transtype tt, string& strtransid, struct message& msg) {

  int size;
  map<string, port_trans> addrmap;
  map<string, port_trans>::iterator itr;

  //decrement TTL
  msg.stcmn_hdr.ttl--;

  size=msg.encode(m_buf, BUFSIZE);

  message s1;
  s1.parse(m_buf, size);

  //create a transaction and pass it the message
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, msg.stcmn_hdr.transid, msg.stcmn_hdr.srcid, idlen, eREQUEST, eJOIN, tt);
  pTrans->Send(m_buf, size, stP.staddr.addr[0], stP.staddr.port[0]);
  m_TMap[pTrans->getTransId()] = pTrans;
  
  strtransid = msg.getTransId();

}//ComposeJoin



void Peer::ComposeExchangeTable(struct peerinfo stP) {

  int size;
  map<string, port_trans> addrmap;
  map<string, port_trans>::iterator itr;

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;
  m_msg.stcmn_hdr.reqoritype = eEXCHANGETABLE;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.ttl = 255;             //TTL
  m_msg.stcmn_hdr.rori = m_REC;          //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.slen = idlen;

  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);
 
  size=m_msg.encode(m_buf, BUFSIZE);

  message s1;
  s1.parse(m_buf, size);

  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_ID, idlen, eREQUEST, eEXCHANGETABLE, eUDP);
  pTrans->Send(m_buf, size, stP.staddr.addr[0], stP.staddr.port[0] );
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++;

}//ComposeExchangeTable



void Peer::ComposeExchangeTableWithLookupPeer(struct peerinfo stP,const struct LObject& objLO, string& strtransid) {

  int size;
  map<string, port_trans> addrmap;
  map<string, port_trans>::iterator itr;

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;
  m_msg.stcmn_hdr.reqoritype = eEXCHANGETABLE;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.ttl = 255;             //TTL
  m_msg.stcmn_hdr.rori = m_REC;          //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.slen = idlen;

  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);
 
  //plookup object
  m_msg.stpl.isPresent=1;
  m_msg.stpl.E=1;
  m_msg.stpl.R=0;
  m_msg.stpl.stida.isPresent=1;
  memcpy(m_msg.stpl.stida.id, objLO.stpl.stida.id, idlen); 
  m_msg.stpl.stida.stobj.length=idlen;
  m_msg.stpl.num=objLO.stpl.num;

  size=m_msg.encode(m_buf, BUFSIZE);

  message s1;
  s1.parse(m_buf, size);

  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_ID, idlen, eREQUEST, eEXCHANGETABLE, eUDP);
  pTrans->Send(m_buf, size, stP.staddr.addr[0], stP.staddr.port[0] );
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++;

}//ComposeExchangeTableWithLookupPeer



void Peer::ComposeBootstrap() {
  
  int size;
  map<string, port_trans> addrmap;
  map<string, port_trans>::iterator itr;

  //printf("composing bootstrap\n");

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;
  m_msg.stcmn_hdr.reqoritype = eBOOTSTRAP;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;     //peer or client
  m_msg.stcmn_hdr.ttl = 255;              //TTL
  m_msg.stcmn_hdr.rori = m_REC;           //recursive or iterative
  memset(m_msg.stcmn_hdr.srcid, 0, 4);
  m_msg.stcmn_hdr.slen=4;
 
  //peer-info object
  m_msg.stpeerinfo.isPresent=1;

  //peerid object
  m_msg.stpeerinfo.stpeerid.isPresent=1;
  memset(m_msg.stpeerinfo.stpeerid.id, 0, 4);
  m_msg.stpeerinfo.stpeerid.stobj.length=4;

  //address object
  m_msg.stpeerinfo.staddr.isPresent=1;  
  
  //Get the addressinfo object from transport
  m_pobjTransport->getAddrPort(addrmap);

  //Fill the address table
  int i=0;
  for(itr=addrmap.begin(); itr!=addrmap.end(); itr++, i++) {

    strncpy(m_msg.stpeerinfo.staddr.addr[i], (char*)itr->first.c_str(), 16);
    m_msg.stpeerinfo.staddr.port[i] = itr->second.port;
    m_msg.stpeerinfo.staddr.tt[i] = itr->second.tt;
    m_msg.stpeerinfo.staddr.ht[i] = itr->second.ht;
    m_msg.stpeerinfo.staddr.ipver[i] = 4;

    //added for windows
    m_msg.stpeerinfo.staddr.R[i] = 0;
    
  }//end for


  //Set the number of addressinfo objects
  m_msg.stpeerinfo.staddr.num = i;
  m_msg.stpeerinfo.stunhashed.isPresent = 1;
  strcpy((char*)m_msg.stpeerinfo.stunhashed.unhashed, (char*)m_USERID);
  m_msg.stpeerinfo.stunhashed.stobj.length = strlen((char*)m_msg.stpeerinfo.stunhashed.unhashed);

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction object, pass it the encoded msg to send, and
  //store it in a map  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_msg.stpeerinfo.stpeerid.id, m_msg.stpeerinfo.stpeerid.stobj.length, eREQUEST, eBOOTSTRAP, eUDP);
  pTrans->Send(m_buf, size, m_BOOT_IP, m_BOOT_PORT);
  m_TMap[pTrans->getTransId()] = pTrans;

  //printf("Transaction id is: %s\n", (char*)pTrans->getTransId().c_str() );

  m_uiTransId++;

  
}//ComposeBootstrap


void Peer::ComposeKeepAlive(struct peerinfo stP) {  

  int size;
  struct message tMsg;

  tMsg.Initialize();

  //common header
  tMsg.stcmn_hdr.msgtype = eREQUEST;
  tMsg.stcmn_hdr.reqoritype = eKEEPALIVE;
  tMsg.stcmn_hdr.transid = m_uiTransId;
  tMsg.stcmn_hdr.porc = m_NODE_TYPE;
  tMsg.stcmn_hdr.ack = 0;
  tMsg.stcmn_hdr.ttl = 255;                  //TTL
  tMsg.stcmn_hdr.rori = m_REC;               //recursive or iterative
  memcpy(tMsg.stcmn_hdr.srcid, m_ID, idlen); //srcid
  tMsg.stcmn_hdr.slen = idlen;

  //peer-info object
  getSelfPeer(tMsg.stpeerinfo);

  //if rtt
  if(stP.strtt.isPresent==1) {
    tMsg.stpeerinfo.strtt.isPresent=1;
    tMsg.stpeerinfo.strtt.utime=stP.strtt.utime;
  }//if

  size=tMsg.encode(m_buf, 65000);

  message s1;
  s1.parse(m_buf, size);		


  //create a transaction and pass it the message
  Transaction* pTrans = new Transaction();
  //TEMP CODE
  pTrans->setDestId(stP.stpeerid.id, idlen);
  //TEMP CODE ends

  pTrans->setParams(m_pobjTransport, m_uiTransId, m_ID, idlen, eREQUEST, eKEEPALIVE, eUDP);
  pTrans->Send(m_buf, size, stP.staddr.addr[0], stP.staddr.port[0]);
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++;


}//ComposeKeepALive


void Peer::ComposePublishObject(struct peerinfo lstP, const LObject& objLO, string& strtransid) {  
  int32 size;
  message s1;
  list <resourceobject>::iterator itr;
  list <resourceobject>  lstro;

  m_msg.Initialize();

  TRACE(2, "Peer::ComposePublishObject IP: %s port: %d\n", (char*)lstP.staddr.addr[0], lstP.staddr.port[0]);

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;
  m_msg.stcmn_hdr.reqoritype = ePUBLISHOBJECT;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.ttl = 255;                  //TTL
  m_msg.stcmn_hdr.rori = m_REC;               //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.slen = idlen;

  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //resource-object
  if(1==objLO.stro.isPresent){
    m_msg.lstro.push_back(objLO.stro);
  }
  lstro = objLO.lstro;
  itr= lstro.begin();
  for( ; itr != lstro.end(); itr++) {
    m_msg.lstro.push_back(*itr);
  }//end for

  //printf("lstro isPresent: %d resid: %d objLO isPresent: %d resid: %d\n", (*m_msg.lstro.begin()).isPresent, (*m_msg.lstro.begin()).stresid.isPresent, objLO.stro.isPresent, objLO.stro.stresid.isPresent);

  //encode the object
  size=m_msg.encode(m_buf, BUFSIZE);

  s1.parse(m_buf, size);


  strtransid = m_msg.getTransId();
  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_msg.stpeerinfo.stpeerid.id, m_msg.stpeerinfo.stpeerid.stobj.length, eREQUEST, ePUBLISHOBJECT, eUDP);  
  pTrans->Send(m_buf, size,  (char*)lstP.staddr.addr[0], lstP.staddr.port[0]);  
  m_TMap[pTrans->getTransId()] = pTrans;

  //printf("Trans-Id is: %s\n", (char*) (m_msg.getTransId().c_str()) );

  m_uiTransId++;
  
  TRACE(2, "Peer::ComposePublishObject...Trans-ID: %s\n", (char*)(pTrans->getTransId().c_str()) );
  

}//ComposePublishObject



void Peer::ComposePublishObject(struct peerinfo lstP, const LObject& objLO, string& strtransid, struct message& msg, transtype tt) {
  
  int32 size;
  struct message tMsg;
  list <resourceobject>::iterator itr;
  list <resourceobject>  lstro;

  tMsg.Initialize();

  TRACE(2, "Peer::ComposePublishObject (msg) IP: %s port: %d transport: %d\n", (char*)lstP.staddr.addr[0], lstP.staddr.port[0], tt);
  
  //common header
  tMsg.stcmn_hdr = msg.stcmn_hdr;
  tMsg.stcmn_hdr.ttl--;              //decrement TTL hops

  //peer-info object
  tMsg.stpeerinfo = msg.stpeerinfo;  //peer-info

  //resource-object
  tMsg.lstro.push_back(objLO.stro);
  lstro = objLO.lstro;
  itr= lstro.begin();
  for( ; itr != lstro.end(); itr++) {
    tMsg.lstro.push_back(*itr);
  }//end for

  //TODO: check for the presence of route log
  
  
  //encode the object
  size=tMsg.encode(m_buf, BUFSIZE);
  
  message s1;
  s1.parse(m_buf, size);
  
  
  //Transaction-Id
  strtransid = tMsg.getTransId();
  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, tMsg.stcmn_hdr.transid, tMsg.stpeerinfo.stpeerid.id, tMsg.stpeerinfo.stpeerid.stobj.length, eREQUEST, ePUBLISHOBJECT, tt);
  pTrans->Send(m_buf, size,  (char*)lstP.staddr.addr[0], lstP.staddr.port[0]);  
  m_TMap[pTrans->getTransId()] = pTrans;
  
  //printf("Trans-Id is: %s\n", (char*) (msg.getTransId().c_str()) );
  
  
  TRACE(2, "Peer::ComposePublishObject (msg)...Trans-ID: %s\n", (char*)(pTrans->getTransId().c_str()) );
  
  
}//ComposePublishObject




void Peer::ComposeLookupObject(struct peerinfo lstP, const LObject& objLO, string& strtransid) {
  
  int size;

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;		//request type of message.
  m_msg.stcmn_hdr.reqoritype = eLOOKUPOBJECT;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;           //peer or client
  m_msg.stcmn_hdr.ttl = 255;                    //TTL
  m_msg.stcmn_hdr.rori = m_REC;                 //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen);   //srcid
  m_msg.stcmn_hdr.slen = idlen;


  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //rlookup object
  m_msg.strl = objLO.strl;

  size=m_msg.encode(m_buf, 65000);

  message s1;
  s1.parse(m_buf, size);		


  //Create a transaction object, pass it the encoded msg to send, and
  //store it in a map  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_msg.stpeerinfo.stpeerid.id, m_msg.stpeerinfo.stpeerid.stobj.length, eREQUEST, eLOOKUPOBJECT, eUDP);
  pTrans->Send(m_buf, size,  (char*)lstP.staddr.addr[0], lstP.staddr.port[0]);
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++;

  
  //get the transaction id (source-id+transid)
  strtransid = pTrans->getTransId();

}//ComposeLookupObject



void Peer::ComposeLookupObject(struct peerinfo lstP, const LObject& objLO, string& strtransid, struct message& msg, transtype tt) {
  
  int size;

  //decrement ttl
  msg.stcmn_hdr.ttl--;
  
  size=msg.encode(m_buf, 65000);

  message s1;
  s1.parse(m_buf, size);		


  //Create a transaction object, pass it the encoded msg to send, and
  //store it in a map  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, msg.stcmn_hdr.transid, msg.stpeerinfo.stpeerid.id, msg.stpeerinfo.stpeerid.stobj.length, eREQUEST, eLOOKUPOBJECT, tt);
  pTrans->Send(m_buf, size,  (char*)lstP.staddr.addr[0], lstP.staddr.port[0]);
  m_TMap[pTrans->getTransId()] = pTrans;

  //get the transaction id (source-id+transid)
  strtransid = pTrans->getTransId();

}//ComposeLookupObject



void Peer::ComposeJoinResp(int32 respCode, struct peerinfo stPSelf, struct peerinfo stPNext, char* pchIP, int32 port, transtype tt) {

  int32 size;
  
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eRESPONSEACK;
  //m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.respcode = respCode;
  memcpy(m_msg.stcmn_hdr.respid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.rlen = idlen;


  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  if(302 == respCode) {
    m_msg.stlpeerinfo.clear();
    //stPNext.isPresent=1;
    m_msg.stlpeerinfo.push_back(stPNext);
  }  else if(200 == respCode)  {
    m_msg.stlpeerinfo.clear();
    //m_msg.stlpeerinfo.push_back(stPSelf);
  }

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eJOIN, eUDP);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;

}//ComposeJoinResp



void Peer::ComposeJoinResp(char* pchIP, int32 port, transtype tt, struct message& msg) {

  int32 size;
  
  //encode the message
  size=msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);

  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, msg.stcmn_hdr.transid, msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eJOIN, tt);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;

}//ComposeJoinResp



void Peer::ComposeACK(char* pchIP, uint16 port) {
  int32 size;
  struct message tMsg;
  
  //common header  
  tMsg.Initialize();
  tMsg.stcmn_hdr = m_msg.stcmn_hdr;
  tMsg.stcmn_hdr.ack = 1;
  
  //copy source id
  memcpy(tMsg.stcmn_hdr.srcid, m_msg.stcmn_hdr.srcid, m_msg.stcmn_hdr.slen);
  tMsg.stcmn_hdr.slen = m_msg.stcmn_hdr.slen;

  //If acking a request or an indication
  if(tMsg.stcmn_hdr.msgtype==eREQUEST || tMsg.stcmn_hdr.msgtype==eINDICATION) {
    memcpy(tMsg.stcmn_hdr.respid, m_ID, idlen);
    tMsg.stcmn_hdr.rlen = idlen;
  }

  //If acking a response or responseACK
  if(tMsg.stcmn_hdr.msgtype==eRESPONSE || tMsg.stcmn_hdr.msgtype==eRESPONSEACK) {
    memcpy(tMsg.stcmn_hdr.respid, m_msg.stcmn_hdr.respid, m_msg.stcmn_hdr.rlen);
    tMsg.stcmn_hdr.rlen = m_msg.stcmn_hdr.rlen;
  }//end if


  //peer-info object
  getSelfPeer(tMsg.stpeerinfo);

  if(tMsg.stcmn_hdr.reqoritype == eBOOTSTRAP || tMsg.stcmn_hdr.reqoritype == eGETDIAGNOSTICS) {
    memset(tMsg.stpeerinfo.stpeerid.id, 0, 4);
    tMsg.stpeerinfo.stpeerid.stobj.length = 4;
  }

  //encode the message
  size=tMsg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);

  //send the message
  m_pobjTransport->Send(m_buf, size, pchIP, port, eUDP);
  

}//Peer::ComposeACK



void Peer::ComposePublishObjectResp(int32 respCode, struct peerinfo stPSelf, struct peerinfo stPNext, char* pchIP, int32 port, transtype tt, struct timeval expt, struct message& msg) {

  int size;
  list< struct peerinfo > lstP;
  list< struct peerinfo >::iterator itr;

  msg.Initialize();

  //common header
  msg.stcmn_hdr.msgtype = eRESPONSEACK;
  //msg.stcmn_hdr.porc = m_NODE_TYPE;
  msg.stcmn_hdr.respcode = respCode;
  memcpy(msg.stcmn_hdr.respid, m_ID, idlen); //srcid
  msg.stcmn_hdr.rlen = idlen;

  //peer-info object
  getSelfPeer(msg.stpeerinfo);

  if(302 == respCode) {

    msg.stlpeerinfo.clear();
    //stPNext.isPresent=1;
    msg.stlpeerinfo.push_back(stPNext);

  }  else if(200 == respCode)  {

    msg.stexpires.isPresent = 1;
    msg.stexpires.utime = expt.tv_sec;

    /*
    //code added by gaurav. temp commented.
    m_pRT->getTable(lstP, eUDP);
    //routing-table
    for(itr=lstP.begin(); itr!=lstP.end(); itr++) {
      msg.strt.isPresent=1;
      msg.strt.table.push_back(*itr);
    } */

  }

  //encode the message
  size=msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);
  
  
  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, msg.stcmn_hdr.transid, msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, ePUBLISHOBJECT, tt);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;
  
  
}//ComposePublishObjectResp



void Peer::ComposePublishObjectResp(char* pchIP, int32 port, transtype tt, struct message& msg) {

  int size;
  list< struct peerinfo > lstP;
  list< struct peerinfo >::iterator itr;

  //encode the message
  size=msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);
  
  /*
  //code added by gaurav. temp commented.
  m_pRT->getTable(lstP, eUDP);
  //routing-table
  for(itr=lstP.begin(); itr!=lstP.end(); itr++) {
    msg.strt.isPresent=1;
    msg.strt.table.push_back(*itr);
  } 
  */
  
  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, msg.stcmn_hdr.transid, msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, ePUBLISHOBJECT, tt);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;
  
  
}//ComposePublishObjectResp




void Peer::ComposeLookupObjectResp(int32 respCode, struct peerinfo stPSelf, struct peerinfo stPNext, char* pchIP, int32 port, transtype tt, LObject& objLO) {

  int32 size;
  list<resourceobject>::iterator i1;
  
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eRESPONSEACK;
  //m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.respcode = respCode;
  memcpy(m_msg.stcmn_hdr.respid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.rlen = idlen;
  
  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //If 302, add a next hop
  if(302 == respCode) {
    m_msg.stlpeerinfo.clear();
    
    //stPNext.isPresent=1;
    m_msg.stlpeerinfo.push_back(stPNext);
  } else if(200 == respCode) {
    
    for(i1=objLO.lstro.begin(); i1 != objLO.lstro.end(); i1++) {
      m_msg.lstro.push_back(*i1);
    }//end for
  }

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eLOOKUPOBJECT, eUDP);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;
  
  
}//ComposeLookupObjectResp



void Peer::ComposeLookupObjectResp(char* pchIP, int32 port, transtype tt, struct message& msg) {

  int size;

  //encode the message
  size=msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);
  

  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, msg.stcmn_hdr.transid, msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eLOOKUPOBJECT, tt);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;
  
  
}//ComposeLookupObjectResp


void Peer::ComposeExchangeTableResp(list<peerinfo>& lstP, char* pchIP, int32 port, transtype tt) {
  int32 size;
  list<peerinfo>::iterator itr;
  plookup stpl;
  stpl.isPresent=0;

  if(m_msg.stpl.isPresent){
    stpl=m_msg.stpl;
  }
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eRESPONSEACK;
  //m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.respcode = 200;
  memcpy(m_msg.stcmn_hdr.respid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.rlen = idlen;
  if(stpl.isPresent){
    m_msg.stpl=stpl;
  }
  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //routing-table
  for(itr=lstP.begin(); itr!=lstP.end(); itr++) {
    m_msg.strt.isPresent=1;
    m_msg.strt.table.push_back(*itr);
  }  

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);



  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eEXCHANGETABLE, eUDP);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;  

}//ComposeExchangeTableResp


void Peer::ComposeKeepAliveResp(char* pchIP, int32 port, transtype tt) {
  int32 size;
  
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eRESPONSEACK;
  //m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.respcode = 200;
  memcpy(m_msg.stcmn_hdr.respid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.rlen = idlen;

  
  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eKEEPALIVE, eUDP);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;  

  
}//ComposeKeepAliveResp




void Peer::ComposeDiagnostics(const LObject& objLO, string& strtransid) {

  int32 size;

  TRACE(2, "Peer::ComposeDiagnostics... Begins\n", "" );  
  
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;
  m_msg.stcmn_hdr.reqoritype = eGETDIAGNOSTICS;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.ttl = 255;                  //TTL
  m_msg.stcmn_hdr.rori = m_REC;               //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.slen = idlen;


  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //always request bw
  m_msg.stdiagoptions.bwf = 1;

  
  //diagnostic header
  m_msg.stdiagoptions.isPresent=1;
  switch(objLO.diagtype) {
  case eGET_RT:
    m_msg.stdiagoptions.r=1;
    break;

  case eGET_NT:
    m_msg.stdiagoptions.n=1;
    break;

  case eGET_RO:
    m_msg.stdiagoptions.e=1;
    break;

  case eGET_RELAYLIST:
    m_msg.stdiagoptions.rl=1;
    break;

  case eGET_TURNALLOC:
    m_msg.stdiagoptions.ta=1;
    break;

  default:
    break;
  }

  //encode the message
  size=m_msg.encode(m_buf, 65000);

  
  message s1;
  s1.parse(m_buf, size);		


  //create a transaction and pass it the message
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_ID, idlen, eREQUEST, eGETDIAGNOSTICS, objLO.tt);
  pTrans->Send(m_buf, size, (char8*)objLO.pchIP, objLO.port);
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++; 

  strtransid = pTrans->getTransId();
  
  return;
}//ComposeDiagnostics


/*void Diagnostics::ComposeDiagnosticsToSites(int32 flag) {
  int size;
  list<struct message>::iterator itr;

  //send the message
  itr=m_DL.begin();
  while(itr!=m_DL.end()){



    size=m_msg.encode(m_buf, BUFSIZE);

}
*/

void Peer::ComposeDiagnosticsResp(list<peerinfo>& lstP, list<resourceobject>& lstRes, char* pchIP, int32 port, transtype tt) {
  int32 size;
  list<peerinfo>::iterator itr;
  list<resourceobject>::iterator i1;
  struct message tMsg;
  int32 f1=0;
  long rbw, sbw;
  list<struct turnalloc> lstta;

  tMsg.Initialize();

  tMsg.stcmn_hdr = m_msg.stcmn_hdr;

  //common header
  tMsg.stcmn_hdr.msgtype = (tt == eUDP)? eRESPONSEACK:eRESPONSE;
  tMsg.stcmn_hdr.ack = 0;
  tMsg.stcmn_hdr.respcode = 200;
  memcpy(tMsg.stcmn_hdr.respid, m_ID, idlen); //srcid
  tMsg.stcmn_hdr.rlen = idlen;
  TRACE(2, "ID len: %d\n", idlen);
  memcpy(tMsg.stcmn_hdr.respid, m_ID, idlen); //srcid
  tMsg.stcmn_hdr.rlen = idlen;

  //peer-info object
  getSelfPeer(tMsg.stpeerinfo);


  //printf("requesting: r %d e %d\n", m_msg.stdiagoptions.r, m_msg.stdiagoptions.e);

  //If routing table
  if(1 == m_msg.stdiagoptions.r) {

    //routing and /or neighbor table
    for(itr=lstP.begin(); itr!=lstP.end(); itr++) {
      tMsg.stdiagnostics.strt.isPresent=1;
      tMsg.stdiagnostics.strt.table.push_back(*itr);
      f1=1;
    } 
  }
  //If neighbor table
  if(1 == m_msg.stdiagoptions.n) {

    // neighbor table
    for(itr=lstP.begin(); itr!=lstP.end(); itr++) {
      tMsg.stdiagnostics.stnt.isPresent=1;
      tMsg.stdiagnostics.stnt.table.push_back(*itr);
      f1=1;
    } 
  }
  //If resource table
  if(1 == m_msg.stdiagoptions.e) {

    //resource-table
    for(i1=lstRes.begin(); i1!=lstRes.end(); i1++) {
      tMsg.stdiagnostics.lstro.push_back(*i1);
      f1=1;
    } 
  }

  //relay list
  if(1==m_msg.stdiagoptions.rl) {
    m_objSTI.GetRelayList(tMsg.stdiagnostics.stlrelaylist);
  }//relay list
  
  //TURN allocaitons
  if(1==m_msg.stdiagoptions.ta) {
    m_objSTI.GetTurnAllocations(tMsg.stdiagnostics.stlturnalloc);
  }//TURN allocations

  //Diagnostics is always present because we return the bandwidth
  tMsg.stdiagnostics.isPresent=1;


  //Send and receive bw from P2P and media
  tMsg.stdiagnostics.stbw.isPresent=1;
  sbw=rbw=0;
  m_pobjTransport->getSendRecvBW(tMsg.stdiagnostics.stbw.sbw, tMsg.stdiagnostics.stbw.rbw);
  //media bandwidth
  getsendrecvbw(&sbw,&rbw);
  tMsg.stdiagnostics.stbw.sbw+=sbw;
  tMsg.stdiagnostics.stbw.rbw+=rbw;

  //if bandwidth has been set, report this one
  if(g_stnodeval.stbw.isPresent && 0 == g_stnodeval.stbw.ismach) {    
    tMsg.stdiagnostics.stbw.sbw=g_stnodeval.stbw.sbw;
    tMsg.stdiagnostics.stbw.rbw=g_stnodeval.stbw.rbw;
    TRACE(3,"Peer::ComposeDiagnosticsResp...reporting bandwidth set by checker %d %d\n", 
      g_stnodeval.stbw.sbw, g_stnodeval.stbw.rbw);
  } 
  
  //send program cpu utilization
  tMsg.stdiagnostics.stcpuutil.isPresent=1;
  tMsg.stdiagnostics.sttcpuutil.ismach=0;
  tMsg.stdiagnostics.stcpuutil.cpuusage=(int16)gCpuUtilization->GetCpuUsage();

  //send machine cpu utilization
  tMsg.stdiagnostics.sttcpuutil.isPresent=1;
  tMsg.stdiagnostics.sttcpuutil.ismach=1;
  tMsg.stdiagnostics.sttcpuutil.cpuusage=(int16)gCpuUtilization->GetTCpuUsage();


  //if cpuutilization has been set, report this one
  if(g_stnodeval.stcpuutil.isPresent && 0 == g_stnodeval.stcpuutil.ismach) {
    tMsg.stdiagnostics.stcpuutil.cpuusage=g_stnodeval.stcpuutil.cpuusage;
    
    TRACE(3,"Peer::ComposeDiagnosticsResp...reporting cpuutil set by checker %d\n", g_stnodeval.stcpuutil.cpuusage);
  } 

  //encode the message
  size=tMsg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, tMsg.stcmn_hdr.transid, tMsg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eGETDIAGNOSTICS, tt);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;  

}//ComposeDiagnosticsResp



int32 Peer::SendACK(char* pchIP, uint16 port) {

  return 1;
}//SendACK



void Peer::ComposeLookupPeer(struct peerinfo lstP, const struct LObject& objLO, string& strtransid) {

  int size;

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;		//request type of message.
  m_msg.stcmn_hdr.reqoritype = eLOOKUPPEER;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;           //peer or client
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.ttl = 255;                  //TTL
  m_msg.stcmn_hdr.rori = m_REC;               //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.slen = idlen;


  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //plookup object
  m_msg.stpl.isPresent=1;
  m_msg.stpl.E=1;
  m_msg.stpl.R=0;
  m_msg.stpl.stida.isPresent=1;
  memcpy(m_msg.stpl.stida.id, lstP.stpeerid.id, idlen); 
  m_msg.stpl.stida.stobj.length=idlen;
  m_msg.stpl.num=objLO.stpl.num;

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eREQUEST, eLOOKUPPEER, eUDP);
  pTrans->Send(m_buf, size, lstP.staddr.addr[0], lstP.staddr.port[0]);
  m_TMap[pTrans->getTransId()] = pTrans;
  
  m_uiTransId++;

  //get the transaction id (source-id+transid) 
  strtransid = pTrans->getTransId();

}//ComposeLookupPeer



/*
 * This method is used during recursive forwarding of request
 */

void Peer::ComposeLookupPeer(struct peerinfo lstP, const struct LObject& objLO, string& strtransid, struct message& msg, transtype tt) {

  int size;
  struct message tMsg;

  //tMsg
  tMsg.Initialize();  
  tMsg.stcmn_hdr = msg.stcmn_hdr;
  tMsg.stcmn_hdr.ttl--;
  
  //peer-info object
  getSelfPeer(tMsg.stpeerinfo);

  //copy the plookup object
  tMsg.stpl = msg.stpl;
  
  //encode the message
  size=tMsg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);

  
  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, tMsg.stcmn_hdr.transid, tMsg.stcmn_hdr.srcid, idlen, eREQUEST, eLOOKUPPEER, tt);
  pTrans->Send(m_buf, size, lstP.staddr.addr[0], lstP.staddr.port[0]);
  m_TMap[pTrans->getTransId()] = pTrans;

  //get the transaction id (source-id+transid)
  strtransid = pTrans->getTransId();


  TRACE(2, "Peer::ComposePublishObject (msg)...Trans-ID: %s\n", (char*)(pTrans->getTransId().c_str()) );

}//ComposeLookupPeer



void Peer::ComposeLookupPeerResp(list<struct peerinfo> lstP, int num, char* pchIP, int32 port, transtype tt, int32 respCode) {

  int32 size;
  list<struct peerinfo>::iterator itr;
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eRESPONSEACK;	//request type of message.
  m_msg.stcmn_hdr.respcode = respCode;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;           //peer or client
  memcpy(m_msg.stcmn_hdr.respid, m_ID, idlen);  //srcid
  m_msg.stcmn_hdr.rlen = idlen;

  //remove the plookup method
  m_msg.stpl.isPresent=0;

  for(itr=lstP.begin();itr!=lstP.end(); ++itr) {
    m_msg.stlpeerinfo.push_back(*itr);
  }

  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eLOOKUPPEER, tt);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;

  
}//ComposeLookupPeerResp




void Peer::ComposeSet(struct LObject& objLO, struct nodeval& stnodeval, string& strtransid) {
  int size;

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;           //request type of message.
  m_msg.stcmn_hdr.reqoritype = eSET;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;           //peer or client
  m_msg.stcmn_hdr.ttl = 255;                    //TTL
  m_msg.stcmn_hdr.rori = m_REC;                 //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen);   //srcid
  m_msg.stcmn_hdr.slen = idlen;


  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //nodevalue
  m_msg.stnodeval=stnodeval;
  m_msg.stnodeval.isPresent=1;

  size=m_msg.encode(m_buf, 65000);

  message s1;
  s1.parse(m_buf, size);		


  //Create a transaction object, pass it the encoded msg to send, and
  //store it in a map  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_ID, idlen, eREQUEST, eSET, objLO.tt);
  pTrans->Send(m_buf, size, (char8*)objLO.pchIP, objLO.port);
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++;

  //get the transaction id (source-id+transid)
  strtransid = pTrans->getTransId();

}//ComposeSet


void Peer::ComposeSetResp(char* pchIP, int32 port, transtype tt) {
  int32 size;
  
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eRESPONSEACK;
  //m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.respcode = 200;
  memcpy(m_msg.stcmn_hdr.respid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.rlen = idlen;

  
  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eSET, eUDP);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;
  
}//ComposeSetResp



void Peer::ComposeReset(struct LObject& objLO, struct nodeval& stnodeval, string& strtransid) {
  
  int size;

  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eREQUEST;           //request type of message.
  m_msg.stcmn_hdr.reqoritype = eRESET;
  m_msg.stcmn_hdr.transid = m_uiTransId;
  m_msg.stcmn_hdr.porc = m_NODE_TYPE;           //peer or client
  m_msg.stcmn_hdr.ttl = 255;                    //TTL
  m_msg.stcmn_hdr.rori = m_REC;                 //recursive or iterative
  memcpy(m_msg.stcmn_hdr.srcid, m_ID, idlen);   //srcid
  m_msg.stcmn_hdr.slen = idlen;


  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //nodevalue
  m_msg.stnodeval=stnodeval;
  m_msg.stnodeval.isPresent=1;

  size=m_msg.encode(m_buf, 65000);

  message s1;
  s1.parse(m_buf, size);		


  //Create a transaction object, pass it the encoded msg to send, and
  //store it in a map  
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_uiTransId, m_ID, idlen, eREQUEST, eSET, objLO.tt);
  pTrans->Send(m_buf, size, (char8*)objLO.pchIP, objLO.port);
  m_TMap[pTrans->getTransId()] = pTrans;

  m_uiTransId++;
  
  //get the transaction id (source-id+transid)
  strtransid = pTrans->getTransId();

}//ComposeReset



void Peer::ComposeResetResp(char* pchIP, int32 port, transtype tt) {
  int32 size;
  
  m_msg.Initialize();

  //common header
  m_msg.stcmn_hdr.msgtype = eRESPONSEACK;
  //m_msg.stcmn_hdr.porc = m_NODE_TYPE;
  m_msg.stcmn_hdr.ack = 0;
  m_msg.stcmn_hdr.respcode = 200;
  memcpy(m_msg.stcmn_hdr.respid, m_ID, idlen); //srcid
  m_msg.stcmn_hdr.rlen = idlen;

  
  //peer-info object
  getSelfPeer(m_msg.stpeerinfo);

  //encode the message
  size=m_msg.encode(m_buf, BUFSIZE);

  //For debugging purposes, parse the message
  message s1;
  s1.parse(m_buf, size);


  //Create a transaction and pass it the response
  Transaction* pTrans = new Transaction();
  pTrans->setParams(m_pobjTransport, m_msg.stcmn_hdr.transid, m_msg.stcmn_hdr.srcid, idlen, eRESPONSEACK, eRESET, eUDP);
  pTrans->Send(m_buf, size, pchIP, port);
  m_TMap[pTrans->getTransId()] = pTrans;  

  
}//ComposeResetResp
