#include "TCPConnection.h"
#include <ant.h>
#include <IPAddress.h>
#include <OPENR/OSyslog.h>
#include <EndpointTypes.h>
#include <TCPEndpointMsg.h>

/*--- TCPRecvConnection ---*/
TCPRecvConnection::TCPRecvConnection(antStackRef ipStack, int bs) : TCPConnection(ipStack){
  recvSize = bs;                 ;
}

TCPRecvConnection::~TCPRecvConnection(){
  if(state != CONNECTION_INVALID)
    {
      recvBuffer.UnMap();
      antEnvDestroySharedBufferMsg destroyRecvBufferMsg(recvBuffer);
      destroyRecvBufferMsg.Call(ipstackRef, sizeof(destroyRecvBufferMsg));
    }
}

OStatus TCPRecvConnection::initConnection(){
  OStatus retVal=oSUCCESS;
  
  if(state != CONNECTION_INVALID)
    {
      if(initBuffer() != oSUCCESS) 
	retVal=oFAIL;
      if(initTcpEndpoint() != oSUCCESS) 
	retVal=oFAIL;
    }
  
  return retVal;
}

OStatus TCPRecvConnection::stop(){
  if (state != CONNECTION_CLOSED && state != CONNECTION_CLOSING && state != CONNECTION_INVALID) 
      {
	state = CONNECTION_CLOSING;
	TCPEndpointCloseMsg closeMsg(endpoint);
	closeMsg.Call(ipstackRef, sizeof(closeMsg));
	state = CONNECTION_CLOSED;
	return oSUCCESS;
      }
  return oFAIL;
}

OStatus TCPRecvConnection::initBuffer(){
  antEnvCreateSharedBufferMsg recvBufferMsg(recvSize);
  
  recvBufferMsg.Call(ipstackRef, sizeof(recvBufferMsg));
  if (recvBufferMsg.error != ANT_SUCCESS) 
    {
      OSYSLOG1((osyslogERROR, "%s : %s antError %d", "TelepatiTcp::initRecvBuffer()", "Can't allocate receive buffer", recvBufferMsg.error));
      return oFAIL;
    }
  
  recvBuffer=recvBufferMsg.buffer;
  recvBuffer.Map();
  recvData=(byte*)(recvBuffer.GetAddress());
  
  return oSUCCESS;
}

OStatus TCPRecvConnection::initTcpEndpoint(){
  if (state != CONNECTION_CLOSED) return oFAIL;

  antEnvCreateEndpointMsg udpCreateMsg(EndpointType_TCP, recvSize * 3);
  udpCreateMsg.Call(ipstackRef, sizeof(udpCreateMsg));
  
  if (udpCreateMsg.error != ANT_SUCCESS) 
    {
      OSYSLOG1((osyslogERROR, "%s : %s antError %d", "TelepatiTcp::initRecvUdpEndpoint()","Can't create endpoint", udpCreateMsg.error));
      return oFAIL;
    }
  endpoint = udpCreateMsg.moduleRef;

  return oSUCCESS;
}


/*--- TCPSendConnection ---*/
TCPSendConnection::TCPSendConnection(antStackRef ipStack, int bs) : TCPConnection(ipStack){
  bufferSize=bs;
  sendSize=0;
}

TCPSendConnection::~TCPSendConnection(){
  if(state != CONNECTION_INVALID)
    {
      sendBuffer.UnMap();
      antEnvDestroySharedBufferMsg destroySendBufferMsg(sendBuffer);
      destroySendBufferMsg.Call(ipstackRef, sizeof(destroySendBufferMsg));
    }
}
OStatus TCPSendConnection::initConnection(){
  OStatus retVal=oSUCCESS;
  bool someFail=false;
  if(state != CONNECTION_INVALID)
    {
      if(initBuffer() != oSUCCESS)
	retVal=oFAIL;
      if(initTcpEndpoint() != oSUCCESS) 
	retVal=oFAIL;
    }

  return retVal;
}

OStatus TCPSendConnection::stop(){
  if (state != CONNECTION_CLOSED && state != CONNECTION_CLOSING && state != CONNECTION_INVALID)
    {
      state = CONNECTION_CLOSING;
      TCPEndpointCloseMsg closeMsg(endpoint);
      closeMsg.Call(ipstackRef, sizeof(closeMsg));
      state = CONNECTION_CLOSED;
      return oSUCCESS;
    }
  
  return oFAIL;
}

OStatus TCPSendConnection::initBuffer(){
  antEnvCreateSharedBufferMsg sendBufferMsg(bufferSize);
  
  sendBufferMsg.Call(ipstackRef, sizeof(sendBufferMsg));
  if (sendBufferMsg.error != ANT_SUCCESS) 
    {
      OSYSLOG1((osyslogERROR, "%s : %s antError %d", "TelepatiTcp::initSendBuffer()", "Can't allocate send buffer", sendBufferMsg.error));
      return oFAIL;
    }
  
  sendBuffer=sendBufferMsg.buffer;
  sendBuffer.Map();
  sendData=(byte*)(sendBuffer.GetAddress());

  return oSUCCESS;
}
OStatus TCPSendConnection::initTcpEndpoint(){
  if (state != CONNECTION_CLOSED) return oFAIL;

  antEnvCreateEndpointMsg udpCreateMsg(EndpointType_TCP, bufferSize * 3);
  udpCreateMsg.Call(ipstackRef, sizeof(udpCreateMsg));
  
  if (udpCreateMsg.error != ANT_SUCCESS) 
    {
      OSYSLOG1((osyslogERROR, "%s : %s antError %d", "TelepatiTcp::initSendUdpEndpoint()","Can't create endpoint", udpCreateMsg.error));
      return oFAIL;
    }
  endpoint = udpCreateMsg.moduleRef;

  return oSUCCESS;
}
