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 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 if (OnNewDataRecv != null) OnNewDataRecv(decByte, decByte.Length); // trigger event if (OnNewDataReceived != null) 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); 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 (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; } /// /// Starts the thread that listens for mbus packets on a network interface /// /// The IP of the network interface. If null, the network interface with the smallest metric is chosed /// True if the thread was succesfully started, otherwise false 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"); } } }