370 lines
13 KiB
C#
370 lines
13 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Text;
|
|||
|
using System.Net.Sockets;
|
|||
|
using System.Net;
|
|||
|
using System.Threading;
|
|||
|
using System.Net.NetworkInformation;
|
|||
|
using System.Linq;
|
|||
|
|
|||
|
namespace SafeMobileLib
|
|||
|
{
|
|||
|
public class UdpMulticast
|
|||
|
{
|
|||
|
private Socket s;
|
|||
|
private Thread listenThread;
|
|||
|
public string mcastGroup { get; private set; }
|
|||
|
private int port;
|
|||
|
private volatile bool working = false;
|
|||
|
private bool useThreadPool = false;
|
|||
|
public bool Encrypted = true;
|
|||
|
public UdpMulticast(string mcastGroup, int port)
|
|||
|
{
|
|||
|
this.mcastGroup = mcastGroup;
|
|||
|
this.port = port;
|
|||
|
}
|
|||
|
|
|||
|
private void Listen_pool(object a)
|
|||
|
{
|
|||
|
Listen();
|
|||
|
}
|
|||
|
|
|||
|
private void Listen()
|
|||
|
{
|
|||
|
while (working)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
int recv = 0; ;
|
|||
|
byte[] b = new byte[65507];
|
|||
|
Thread.Sleep(1);
|
|||
|
if (s != null)
|
|||
|
recv = s.Receive(b);
|
|||
|
else
|
|||
|
break;//break if socket == null
|
|||
|
if (recv == 0)
|
|||
|
continue;//continue if return nr bytes == 0
|
|||
|
|
|||
|
if (OnNewDataRecv != null)
|
|||
|
{
|
|||
|
byte[] tmp = new byte[recv];
|
|||
|
for (int i = 0; i < recv; i++)
|
|||
|
{
|
|||
|
tmp[i] = b[i];
|
|||
|
}
|
|||
|
|
|||
|
byte[] decByte = Encrypted ? Encryption.Decrypt(tmp, EncryptionAlgorithm.Des64) : tmp;
|
|||
|
|
|||
|
// trigger event
|
|||
|
OnNewDataRecv(decByte, decByte.Length);
|
|||
|
}
|
|||
|
|
|||
|
if (OnNewDataReceived != null)
|
|||
|
{
|
|||
|
byte[] tmp = new byte[recv];
|
|||
|
for (int i = 0; i < recv; i++)
|
|||
|
{
|
|||
|
tmp[i] = b[i];
|
|||
|
}
|
|||
|
|
|||
|
byte[] decByte = Encrypted ? Encryption.Decrypt(tmp, EncryptionAlgorithm.Des64) : tmp;
|
|||
|
|
|||
|
// trigger event
|
|||
|
OnNewDataReceived(mcastGroup, decByte, decByte.Length);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (s == null)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (SocketException ex)
|
|||
|
{
|
|||
|
if (working)
|
|||
|
Utils.WriteLine("UdpMulticast Listen SOCKET EXCEPTION " + ex.ToString());
|
|||
|
break;
|
|||
|
}
|
|||
|
catch (ThreadAbortException ex)
|
|||
|
{
|
|||
|
if (working)
|
|||
|
Utils.WriteLine("UdpMulticast Listen Thread Abort EXCEPTION " + ex.ToString());
|
|||
|
break;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("UdpMulticast Listen Exception" + ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
Utils.WriteLine("Closing UDPMultiCast " + this.mcastGroup + ":" + this.port);
|
|||
|
}
|
|||
|
|
|||
|
private void Listen_Decoded()
|
|||
|
{
|
|||
|
while (true)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
byte[] b = new byte[65507];
|
|||
|
Thread.Sleep(1);
|
|||
|
int recv = s.Receive(b);
|
|||
|
if (OnNewDataRecv != null)
|
|||
|
{
|
|||
|
byte[] tmp = new byte[recv];
|
|||
|
for (int i = 0; i < recv; i++)
|
|||
|
{
|
|||
|
tmp[i] = b[i];
|
|||
|
}
|
|||
|
if (this.OnNewDataRecv != null)
|
|||
|
this.OnNewDataRecv(tmp, tmp.Length);
|
|||
|
}
|
|||
|
|
|||
|
if (OnNewDataReceived != null)
|
|||
|
{
|
|||
|
byte[] tmp = new byte[recv];
|
|||
|
for (int i = 0; i < recv; i++)
|
|||
|
{
|
|||
|
tmp[i] = b[i];
|
|||
|
}
|
|||
|
if (this.OnNewDataReceived != null)
|
|||
|
this.OnNewDataReceived(mcastGroup, tmp, tmp.Length);
|
|||
|
}
|
|||
|
|
|||
|
if (s == null)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (ThreadAbortException)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("UdpMulticast.cs->Listen" + ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public delegate void newData4Send(byte[] data, int dataLen);
|
|||
|
public event newData4Send OnNewDataRecv;
|
|||
|
|
|||
|
|
|||
|
public delegate void newDataReceivedDel(String broadcastAddress, byte[] data, int dataLen);
|
|||
|
public event newDataReceivedDel OnNewDataReceived;
|
|||
|
|
|||
|
private IPAddress getLocalIPAddress()
|
|||
|
{
|
|||
|
if (!NetworkInterface.GetIsNetworkAvailable())
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
|
|||
|
|
|||
|
return host
|
|||
|
.AddressList
|
|||
|
.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
|
|||
|
}
|
|||
|
|
|||
|
public static IPAddress getPreferedIPAdress()
|
|||
|
{
|
|||
|
IPAddress localIP = IPAddress.Parse("127.0.0.1");
|
|||
|
Socket socket = null;
|
|||
|
try
|
|||
|
{
|
|||
|
using (socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
|
|||
|
{
|
|||
|
socket.Connect("10.0.2.4", 65530);
|
|||
|
IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
|
|||
|
localIP = endPoint.Address;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine(ex.ToString(), ConsoleColor.DarkRed);
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
if (socket != null)
|
|||
|
socket.Dispose();
|
|||
|
}
|
|||
|
return localIP;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Starts the thread that listens for mbus packets on a network interface
|
|||
|
/// </summary>
|
|||
|
/// <param name="localIP">The IP of the network interface. If null, the network interface with the smallest metric is chosed</param>
|
|||
|
/// <returns>True if the thread was succesfully started, otherwise false</returns>
|
|||
|
public bool StartListen(string localIP = null)
|
|||
|
{
|
|||
|
bool ret = false;
|
|||
|
working = true;
|
|||
|
IPAddress myIP = !string.IsNullOrWhiteSpace(localIP) ? IPAddress.Parse(localIP) : getPreferedIPAdress();
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
if (s == null)
|
|||
|
{
|
|||
|
s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|||
|
}
|
|||
|
|
|||
|
if (s != null)
|
|||
|
{
|
|||
|
|
|||
|
|
|||
|
IPEndPoint ipep = new IPEndPoint(myIP, port);
|
|||
|
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
|
|||
|
s.Bind(ipep);
|
|||
|
IPAddress ip = IPAddress.Parse(mcastGroup);
|
|||
|
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, myIP));
|
|||
|
s.SetSocketOption(SocketOptionLevel.IP,
|
|||
|
SocketOptionName.MulticastTimeToLive, int.Parse("1"));
|
|||
|
listenThread = new Thread(new ThreadStart(Listen));
|
|||
|
listenThread.IsBackground = true;
|
|||
|
}
|
|||
|
|
|||
|
if (listenThread != null)
|
|||
|
listenThread.Start();
|
|||
|
ret = true;
|
|||
|
|
|||
|
Utils.WriteLine($"++++++++++++++++++++++++++++++++++++++++++\nUdpMulticast bind on {mcastGroup}:{port} Ethernet: {myIP}\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("UdpMulticast StartListen exception: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
public bool StartListen_ThreadPool()
|
|||
|
{
|
|||
|
bool ret = false;
|
|||
|
working = true;
|
|||
|
useThreadPool = true;
|
|||
|
try
|
|||
|
{
|
|||
|
if (s == null)
|
|||
|
{
|
|||
|
s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|||
|
}
|
|||
|
if (s != null)
|
|||
|
{
|
|||
|
Utils.WriteLine(String.Format("[### {0:H:mm:ss} ###] Port multi cast {1}", DateTime.Now, port));
|
|||
|
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
|
|||
|
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
|
|||
|
s.Bind(ipep);
|
|||
|
IPAddress ip = IPAddress.Parse(mcastGroup);
|
|||
|
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));
|
|||
|
s.SetSocketOption(SocketOptionLevel.IP,
|
|||
|
SocketOptionName.MulticastTimeToLive, int.Parse("1"));
|
|||
|
|
|||
|
ThreadPool.QueueUserWorkItem(new WaitCallback(Listen_pool));
|
|||
|
|
|||
|
}
|
|||
|
ret = true;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Ex:" + ex.ToString());
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
public bool StartListen_Decoded()
|
|||
|
{
|
|||
|
bool ret = false;
|
|||
|
working = true;
|
|||
|
try
|
|||
|
{
|
|||
|
if (s == null)
|
|||
|
{
|
|||
|
s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|||
|
}
|
|||
|
if (s != null)
|
|||
|
{
|
|||
|
Utils.WriteLine(String.Format("[### {0:H:mm:ss} ###] Port multi cast {1}", DateTime.Now, port));
|
|||
|
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
|
|||
|
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
|
|||
|
s.Bind(ipep);
|
|||
|
IPAddress ip = IPAddress.Parse(mcastGroup);
|
|||
|
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));
|
|||
|
s.SetSocketOption(SocketOptionLevel.IP,
|
|||
|
SocketOptionName.MulticastTimeToLive, int.Parse("1"));
|
|||
|
listenThread = new Thread(new ThreadStart(Listen_Decoded));
|
|||
|
listenThread.IsBackground = true;
|
|||
|
}
|
|||
|
if (listenThread != null)
|
|||
|
listenThread.Start();
|
|||
|
ret = true;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Ex:" + ex.ToString());
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
public void StopListen()
|
|||
|
{
|
|||
|
Utils.WriteLine("Stoping multicast listener:" + mcastGroup);
|
|||
|
working = false;
|
|||
|
if (!useThreadPool)
|
|||
|
if (listenThread != null)
|
|||
|
{
|
|||
|
if (listenThread.IsAlive)
|
|||
|
{
|
|||
|
listenThread.Abort();
|
|||
|
listenThread = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (s != null)
|
|||
|
{
|
|||
|
s.Close();
|
|||
|
s = null;
|
|||
|
}
|
|||
|
|
|||
|
GC.Collect();
|
|||
|
}
|
|||
|
|
|||
|
public void Send(byte[] data, int len)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (s == null)
|
|||
|
{
|
|||
|
s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|||
|
}
|
|||
|
|
|||
|
if (s != null && mcastGroup != null)
|
|||
|
{
|
|||
|
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(mcastGroup), port);
|
|||
|
byte[] encByte = Encryption.Encrypt(data, EncryptionAlgorithm.Des64);
|
|||
|
s.SendTo(encByte, encByte.Length, SocketFlags.None, ipep);
|
|||
|
}
|
|||
|
else Utils.WriteLine("s is NULL");
|
|||
|
}
|
|||
|
catch(Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("UdpMulticast send error : " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Send_decoded(byte[] data, int len)
|
|||
|
{
|
|||
|
if (s == null)
|
|||
|
{
|
|||
|
s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|||
|
}
|
|||
|
|
|||
|
if (s != null && mcastGroup != null)
|
|||
|
{
|
|||
|
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(mcastGroup), port);
|
|||
|
s.SendTo(data, data.Length, SocketFlags.None, ipep);
|
|||
|
}
|
|||
|
else Utils.WriteLine("s is NULL");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|