private void OnReceiveData(IAsyncResult asyncResult)
{
System.Net.Sockets.UdpClient conn = (System.Net.Sockets.UdpClient)asyncResult.AsyncState;
try
{
System.Net.IPEndPoint ep = new Net.IPEndPoint(System.Net.IPAddress.Any, 0);
byte[] local_buffer;
int rx = 0;
try
{
local_buffer = conn.EndReceive(asyncResult, ref ep);
rx = local_buffer.Length;
}
catch (Exception) // ICMP port unreachable
{
//restart data receive
conn.BeginReceive(OnReceiveData, conn);
return;
}
if (rx == 0) // Empty frame : port scanner maybe
{
//restart data receive
conn.BeginReceive(OnReceiveData, conn);
return;
}
try
{
//verify message
BacnetAddress remote_address;
Convert((System.Net.IPEndPoint)ep, out remote_address);
BacnetBvlcFunctions function;
int msg_length;
if (rx < BVLC.BVLC_HEADER_LENGTH)
{
Trace.TraceWarning("Some garbage data got in");
}
else
{
// Basic Header lenght
int HEADER_LENGTH = bvlc.Decode(local_buffer, 0, out function, out msg_length, ep);
if (HEADER_LENGTH == -1)
{
Trace.WriteLine("Unknow BVLC Header");
return;
}
// response to BVLC_REGISTER_FOREIGN_DEVICE (could be BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK ... but we are not a BBMD, don't care)
if (function == BacnetBvlcFunctions.BVLC_RESULT)
{
Trace.WriteLine("Receive Register as Foreign Device Response");
}
// a BVLC_FORWARDED_NPDU frame by a BBMD, change the remote_address to the original one (stored in the BVLC header)
// we don't care about the BBMD address
if (function == BacnetBvlcFunctions.BVLC_FORWARDED_NPDU)
{
long ip = ((long)local_buffer[7] << 24) + ((long)local_buffer[6] << 16) + ((long)local_buffer[5] << 8) + (long)local_buffer[4];
int port = (local_buffer[8] << 8) + local_buffer[9]; // 0xbac0 maybe
ep = new Net.IPEndPoint(ip, port);
Convert((System.Net.IPEndPoint)ep, out remote_address);
}
if ((function == BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU) || (function == BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU) || (function == BacnetBvlcFunctions.BVLC_FORWARDED_NPDU))
//send to upper layers
if ((MessageRecieved != null) &&(rx>HEADER_LENGTH)) MessageRecieved(this, local_buffer, HEADER_LENGTH, rx - HEADER_LENGTH, remote_address);
}
}
catch (Exception ex)
{
Trace.TraceError("Exception in udp recieve: " + ex.Message);
}
finally
{
//restart data receive
conn.BeginReceive(OnReceiveData, conn);
}
}
catch (Exception ex)
{
//restart data receive
if (conn.Client != null)
{
Trace.TraceError("Exception in Ip OnRecieveData: " + ex.Message);
conn.BeginReceive(OnReceiveData, conn);
}
}
}