/*@!Encoding:1252*/

variables
{
  UdpSocket gSocket;
  char      gRxBuffer[1500];
}

on sysvar_update sysvar::Receiver::Open
{
  long result;
  
  // on open button down...
  if (@this == 1)
  {
    // Open an UDP socket. As source address 0 is used, this means that
    // the configure address of the TCP/IP stack is used. See TCP/IP stack
    // configuration dialog in the simulation setup
    // On UDP port 40001 we want to receive UDP pacekts.
    gSocket = UdpSocket::Open( 0, 40001 );
    
    if (IpGetLastError() != 0)
    {
      // if UdpSocket::Open fails, we print a message to the write window
      write( "<%BASE_FILE_NAME%> UdpSocket::Open failed with reauls %d", IpGetLastError() );
      return;
    }
    
    // Optionally the receiver can join a multicast group. This triggers the sending
    // of an IGMP message, which notifies routers the the node wants to receive
    // specific multicasts. The router will forward this multicasts to the node
    //
    // The TCP/IP stack as configured 2 VLANs, every VLAN is represented
    // as an additional Ethernet adapter of the node. The first adapter,
    // without VLAN has the interface index 1.
    // Here we want to receive the multicassts in VLAN with ID 2, which
    // is represented by the interface index 3 and multicast address 239.0.2.1

    result = gSocket.JoinMulticastGroup( 3, IpGetAddressAsNumber( "239.0.2.1" ) );
    
    if (result != 0)
    {
      write( "<%BASE_FILE_NAME%> ERROR: JoinMulticastGroup failed with result %d", result);
    }
    
    // To receive data with the created socket, we have to call ReceiveFrom.
    gSocket.ReceiveFrom( gRxBuffer, elcount(gRxBuffer) );
    
    // if ReceiveFrom does not immediatelly copy to to gRxBuffer, it returns 997 to
    // indicate it will call the callback function OnUdpReceiveFrom later.
    if ((gSocket.GetLastSocketError() != 0) && (gSocket.GetLastSocketError()  != 997))
    {
      char errorString[100];
      // if ReceiveFrom fails, we print a message to the write window
      gSocket.GetLastSocketErrorAsString( errorString, elcount(errorString) );
      write( "<%BASE_FILE_NAME%> ReceiveFrom failed with result %d (%s)", IpGetLastError(), errorString );
    }
    
    // update panel controls state
    EnableControl( "Receiver", "OpenButton", 0 );
    EnableControl( "Receiver", "CloseButton", 1 );
  }
}

on sysvar_update sysvar::Receiver::Close
{
  long result;
  
  // on open button down...
  if (@this == 1)
  {
    // Here we leave the multicast group. This will trigger a IGMP packet.
    result = gSocket.LeaveMulticastGroup( 3, IpGetAddressAsNumber( "239.0.2.1" ) );
    
    if (result != 0)
    {
      write( "<%BASE_FILE_NAME%> ERROR: LeaveMulticastGroup failed with result %d", result);
    }

    // Close socket
    gSocket.Close();

    // update panel controls state
    EnableControl( "Receiver", "OpenButton", 1 );
    EnableControl( "Receiver", "CloseButton", 0 );
  }
}

on preStop
{
  // Close socket on measurement stop
  gSocket.Close();
}

// Callback function, which is called if a UDP packet is received
void OnUdpReceiveFrom( dword socket, long result, dword address, dword port, char buffer[], dword size)
{
  if (result == 0)
  {
    char addressString[20];
    
    ipGetAddressAsString( address, addressString, elcount(addressString) );
    
    // set sysvars to display receive data in panels
    sysSetVariableString( sysvar::Receiver::RxAddress, addressString );
    sysSetVariableString( sysvar::Receiver::RxText, buffer );
  }

  // To receive more data, we have to call ReceiveFrom again.
  gSocket.ReceiveFrom( gRxBuffer, elcount(gRxBuffer) );
}
