/*@@includes:*/
includes
{
  #include "IPCommon.can"
}
/*@@end*/

/*@@var:*/
variables
{
}
/*@@end*/

/*@@caplFunc:SetupIp():*///function
void SetupIp()
{
  int   adapterIndex = 1;
  char  text[512] = "";
  char  info[512] = "";
  int   size = 512;
  long  result = 0;
  dword addresses[1];

  writeClear(0);

  if (1 > IpGetAdapterCount())
  {
    writelineex(0, 3, "Error: There is no network interface available!");
    
    stop();
  }

  if (0 != IpGetAdapterAddress(adapterIndex, addresses, 1))
  {
    writelineex(0, 3, "Error: Could not retrieve Ip address!");
    
    stop();
  }

  gIpAddress = addresses[0]; // the interface used

  if (INVALID_IP == gIpAddress)
  {
    writelineex(0, 3, "Error: Ip address to be used is invalid!");
    
    stop();
  }
 
  IpGetAdapterDescription(adapterIndex, text, size);
  snprintf(info, size, "Interface: %s", text);
  writelineex(0, 1, info);

  IpGetAdapterAddressAsString(adapterIndex, text, size);
  snprintf(info, size, "Ip address: %s", text);
  writelineex(0, 1, info);

  SysSetVariableString(sysvar::TCPIP::TcpServerIp, text);

  SysSetVariableString(sysvar::UDP::UdpServerIp, text);

  IpGetAdapterMaskAsString(adapterIndex, text, size);
  snprintf(info, size, "Subnet mask: %s", text);
  writelineex(0, 1, info);

  IpGetAdapterGatewayAsString(adapterIndex, text, size);
  snprintf(info, size, "Gateway address: %s", text);
  writelineex(0, 1, info);
 
  gStatus = gkSTATUS_INITIALISED;
}
/*@@end*/

/*@@startStart:Start:*/
on start
{
  SetupIp();  
}
/*@@end*/

/*@@stop:StopMeasurement:*/
on stopMeasurement
{
  ResetIp();
}
/*@@end*/

/*@@caplFunc:OnTcpListen(dword,long):*///function
void OnTcpListen( dword socket, long result)
{
  if (gTcpSocket != socket)
  {
    writelineex( 0, 2, "OnTcpListen called for unexpected socket (%d).", socket);
    
    return;
  }

  if ( 0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpListen error (%d, %s).", 
                 IpGetLastSocketError( socket), gIpLastErrStr);
    return;
  }

  if (gTcpDataSocket != INVALID_SOCKET)
  {
    TcpClose(gTcpDataSocket);
  }
  
  gTcpDataSocket = TcpAccept( socket);

  if ( INVALID_SOCKET == gTcpDataSocket)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "Error: TcpAccept (%d): %s", 
                 IpGetLastSocketError( socket), gIpLastErrStr);
    
    return;
  }

  TcpRecv( gTcpDataSocket);

  writelineex( 0, 1, "Status: Tcp connection established.");  
}
/*@@end*/

/*@@caplFunc:OnTcpReceive(dword,long,dword,dword,char[],dword):*///function
long OnTcpReceive( dword socket, long result, dword address, dword port, char buffer[], dword size)
{
  char  addressString[64] = "";

  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpReceive called for unknown socket 0x%X", socket);

    return 0;
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpReceive error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);

    return 0;
  }
 
  IpGetAddressAsString(address, addressString, elcount(addressString));

   SysSetVariableString(sysvar::TCPIP::TcpClientIp, addressString);

  @sysvar::TCPIP::TcpClientPort = port;

  SysSetVariableString(sysvar::TCPIP::TcpClientData, buffer);
 
  TcpRecv( socket);

  return 0;
}
/*@@end*/

/*@@caplFunc:OnTcpSend(dword,long,char[],dword):*///function
void OnTcpSend( dword socket, long result, char buffer[], dword size)
{
  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpSend called for unknown socket 0x%X", socket);
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpSend error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);
  }
  else
  {
    writelineex( 0, 1, "Tcp data sent successfully!");
  }
}
/*@@end*/

/*@@caplFunc:StartListenTcp():*///function
void StartListenTcp()
{ 
  gTcpPort = @sysvar::TCPIP::TcpServerPort;

  gTcpSocket = TcpOpen(gIpAddress, gTcpPort);

  if ( INVALID_SOCKET == gTcpSocket)
  {
    writelineex(0, 1, "Error: could not create Tcp socket!");

    return;
  }

  writelineex(0, 1, "Successfully created Tcp socket.");
  
  TcpListen(gTcpSocket);

  writelineex( 0, 1, "Listening for incoming Tcp connections on port %d", gTcpPort);
}
/*@@end*/

/*@@caplFunc:StopListenTcp():*///function
void StopListenTcp()
{
  if (INVALID_SOCKET != gTcpDataSocket)
  {
    TcpClose(gTcpDataSocket);
    
    gTcpDataSocket = INVALID_SOCKET;
  }

  if (INVALID_SOCKET != gTcpSocket)
  {
    TcpClose(gTcpSocket);
    
    gTcpSocket = INVALID_SOCKET;
  }

  writelineex(0, 1, "Tcp socket is closed.");
}
/*@@end*/

/*@@caplFunc:SendTcpData():*///function
void SendTcpData()
{
  char buffer[4096];
   
  SysGetVariableString(sysvar::TCPIP::TcpData, buffer, elcount(buffer));

  if (INVALID_SOCKET != gTcpDataSocket)

  if (0 != TcpSend( gTcpDataSocket, buffer, elcount(buffer)))
  {
    gIpLastErr = IpGetLastSocketError( gTcpDataSocket);

    if ( WSA_IO_PENDING != gIpLastErr)
    {
      IpGetLastSocketErrorAsString( gTcpDataSocket, gIpLastErrStr, elcount( gIpLastErrStr));

      writelineex( 0, 2, "TcpSend error (%d): %s", gIpLastErr, gIpLastErrStr);
    }
  }
  else
  {
    writelineex( 0, 1, "Tcp data sent successfully!");
  }
}
/*@@end*/

/*@@caplFunc:SendUdpData():*///function
void SendUdpData()
{
  char buffer[64]; // used for ip address

  char data[4096]; // user data

  dword clientIp;

  if ( INVALID_SOCKET == gUdpSocket)
  {
    writelineex(0, 1, "Error: Udp socket is not opened!");

    return;
  }

  SysGetVariableString(sysvar::UDP::UdpClientIp, buffer, elcount(buffer));

  clientIp = IpGetAddressAsNumber(buffer);

  if (INVALID_IP == clientIp)
  {
    writelineex(0, 1, "Error: invalid client Ip address!");
    
    return;
  }

  SysGetVariableString(sysvar::UDP::UdpData, data, elcount(data));

  UdpSendTo(gUdpSocket, clientIp, @sysvar::UDP::UdpClientPort, data, elcount(data));
}
/*@@end*/

/*@@caplFunc:OpenUdpPort():*///function
void OpenUdpPort()
{
  gUdpPort = @sysvar::UDP::UdpServerPort;
  
  gUdpSocket = UdpOpen( gIpAddress, gUdpPort);

  if ( INVALID_SOCKET == gUdpSocket)
  {
    writelineex(0, 1, "Error: could not create Udp socket!");
  }
  else
  {
    writelineex(0, 1, "Udp socket is opened successfully.");

    UdpRecv( gUdpSocket);
  }
}
/*@@end*/

/*@@caplFunc:CloseUdpPort():*///function
void CloseUdpPort()
{
  if (INVALID_SOCKET != gUdpSocket)
  {
    UdpClose(gUdpSocket);
    
    gUdpSocket = INVALID_SOCKET;

    writelineex(0, 1, "Udp port is closed.");
  }

  SysSetVariableString(sysvar::UDP::UdpClientIp, "");

  @sysvar::UDP::UdpClientPort = 0;
}
/*@@end*/

/*@@caplFunc:ResetIp():*///function
void ResetIp()
{
  if (INVALID_SOCKET != gTcpDataSocket)
  {
    TcpClose(gTcpDataSocket);
    
    gTcpDataSocket = INVALID_SOCKET;
  }

  if (INVALID_SOCKET != gTcpSocket)
  {
    TcpClose(gTcpSocket);
    
    gTcpSocket = INVALID_SOCKET;
  }

  if (INVALID_SOCKET != gUdpSocket)
  {
    UdpClose(gUdpSocket);
    
    gUdpSocket = INVALID_SOCKET;
  }

}
/*@@end*/

/*@@caplFunc:OnUdpReceiveFrom(dword,long,dword,dword,char[],dword):*///function
void OnUdpReceiveFrom( dword socket, long result, dword address, dword port, char buffer[], dword count)
{
  char  addressString[64] = "";

  if ( gUdpSocket != socket)
  {
    writelineex(0, 2, "OnUdpReceiveFrom called for unknown socket!");
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnUdpReceiveFrom error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);
  }
 
  IpGetAddressAsString(address, addressString, elcount(addressString));

  SysSetVariableString(sysvar::UDP::UdpClientIp, addressString);

  @sysvar::UDP::UdpClientPort = port;

  SysSetVariableString(sysvar::UDP::UdpClientData, buffer);
 
  UdpRecv( socket);
}
/*@@end*/

/*@@sysvarUpdate:TCPIP::TcpSend:*/
on sysvar_update sysvar::TCPIP::TcpSend
{
  if (@this)
  {
    SendTcpData();
  }
}
/*@@end*/

/*@@sysvarUpdate:TCPIP::TcpStartListen:*/
on sysvar_update sysvar::TCPIP::TcpStartListen
{
  if (@this)
  {
    StartListenTcp();
  }
}
/*@@end*/

/*@@sysvarUpdate:TCPIP::TcpStopListen:*/
on sysvar_update sysvar::TCPIP::TcpStopListen
{
  if (@this)
  {
    StopListenTcp();
  }
}
/*@@end*/

/*@@sysvarUpdate:UDP::UdpClose:*/
on sysvar_update sysvar::UDP::UdpClose
{
  if (@this)
  {
    CloseUdpPort();
  }
}
/*@@end*/

/*@@sysvarUpdate:UDP::UdpOpen:*/
on sysvar_update sysvar::UDP::UdpOpen
{
  if (@this)
  {
    OpenUdpPort();
  }
}
/*@@end*/

/*@@sysvarUpdate:UDP::UdpSend:*/
on sysvar_update sysvar::UDP::UdpSend
{
  if (@this)
  {
    SendUdpData();
  }
}
/*@@end*/

