using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using SafeMobileLib; using System.Threading; using MotoTRBO_GW; namespace MotoTrbo_GW { class SMSReceiveThread { private string radioIP; public Int32 smsPort; private byte[] data = new byte[1024]; private UdpMulticast udpMulticast; private UdpClient udpClient; private String mIP; private Int32 mPort; public SMSReceiveThread(string radioIP, Int32 port, String multicastID, String multicastPort, UdpClient capPlusUDP = null) { this.radioIP = radioIP; smsPort = port; mIP = multicastID; mPort = Int32.Parse(multicastPort); //for cap plus udpClient = capPlusUDP; } public void handleConnection() { SafeMobileLib.Utils.WriteLine("SMSReceive Thread started on port " + smsPort, ConsoleColor.Cyan, ConsoleType.SMS); try { if (!Main.capacityPlus) { udpClient = null; udpClient = new UdpClient(); udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); string localIP = RadioStuff.GetInterface(radioIP); udpClient.Client.Bind(new IPEndPoint(IPAddress.Parse(localIP), smsPort)); } else { SafeMobileLib.Utils.WriteLine("SMS in cap+ MODE!!", ConsoleType.SMS); } } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("SMSReceiveThread handleConnection exception: " + ex.ToString(), ConsoleColor.Red, ConsoleType.SMS); } try { udpMulticast = new UdpMulticast(mIP, mPort); SafeMobileLib.Utils.WriteLine("SMSReceiveThread successfully registered to multicast group", ConsoleType.SMS); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("SMSReceiveThread exception while joining the multicast group: " + ex.ToString(), ConsoleColor.Red, ConsoleType.SMS); } IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); SafeMobileLib.Utils.WriteLine("Waiting for SMS on port " + smsPort, ConsoleType.SMS); while (Program.isRunning) { try { // Blocks until a message returns on this socket from a remote host. Byte[] receivedBytes = udpClient.Receive(ref remoteIpEndPoint); char[] separator = { '.' }; string[] su = remoteIpEndPoint.Address.ToString().Split(separator); uint radioID = (Convert.ToUInt32(su[1])) * 256 * 256 + (Convert.ToUInt32(su[2])) * 256 + Convert.ToUInt32(su[3]); //EndPoint p= udpClient.Client.LocalEndPoint; string suid = radioID.ToString(); SafeMobileLib.Utils.WriteLine("SMSReceiveThread received data from radio " + radioID + ": ", ConsoleType.SMS); Utils.printBytesArray(receivedBytes, ConsoleType.SMS); SafeMobileLib.Utils.WriteLine("\n\n", ConsoleType.SMS); //register route if (!Main.capacityPlus) { //SafeMobileLib.Utils.WriteLine("RadioGW received a sms from field unit with ID " + suid + " on gateway radio with IP " + radioIP + " \n\r Adding route to route table if route not present."); if (RouteManager.NetworkIDs_Hash.ContainsKey(radioIP)) { RoutingUtils.addRoute_withBuffer(suid.ToString(), radioIP, RouteManager.NetworkIDs_Hash[radioIP].ToString()); } else { //SafeMobileLib.Utils.WriteLine("RouteManager.NetworkIDs_Hash does not contain a key for " + radioIP, ConsoleColor.Red); } } header_T hret = DecodePacket(receivedBytes); if (hret.ack) { SafeMobileLib.Utils.WriteLine("ACK received", ConsoleType.SMS); Thread.Sleep(1000); // The client needs an ACK byte extension_header = 0; if (hret.seq_no > 0x1F) extension_header = 1; Byte[] sendBytes = new Byte[5 + extension_header]; sendBytes[0] = 0x00; // len (2B) sendBytes[1] = (byte)(3 + extension_header); sendBytes[2] = 0xBF; // first header (req) sendBytes[3] = 0x00; // addr len sendBytes[4] = (byte)(hret.seq_no & 0x1F); // 2nd header (opt) if (extension_header == 1) { sendBytes[4] += 0x80; //added the extension header info sendBytes[5] = (byte)(hret.seq_no & 0x60); } //SafeMobileLib.Utils.WriteLine("SMSReceiveThread ACK sent: " + Utils.Byte2String(sendBytes, 0, sendBytes[1] + 2)); udpClient.Send(sendBytes, sendBytes[1] + 2, remoteIpEndPoint); } SafeMobileLib.Utils.WriteLine("", ConsoleType.SMS); if (hret.header != 0x0BF) //regular message received { SafeMobileLib.Utils.WriteLine("REGULAR MESSAGE RECEIVED ", ConsoleType.SMS); // decode the message received SafeMobileLib.MessageDecoders.SMSdecoder dec2 = new SafeMobileLib.MessageDecoders.SMSdecoder(false); dec2.DecodePacket(receivedBytes); // check if the message has text if (dec2.messBody != "") { SafeMobileLib.Utils.WriteLine("msg body " + dec2.messBody, ConsoleType.SMS); // convert the string inyo byte array List bytes = new List(); foreach (char c in dec2.messBody.ToCharArray()) bytes.Add((byte)c); // add the hyt flag to the message to announce that is already parsed bytes.Add((byte)'#'); bytes.Add((byte)'h'); bytes.Add((byte)'y'); bytes.Add((byte)'t'); #if LINXB // Check if message is for a Linx (text msg of call request) // Text messages for LINX : LINX(linxID).(text) - ex: Linx100.Hello // Call request message for LINX: Linx(linxID).. - ex: Linx100.. string message = dec2.messBody; bool isMessageForLinx = false; int linxID = -1; string txtForLinx = ""; if (message.IndexOf("linx", 0, StringComparison.InvariantCultureIgnoreCase) == 0) { // message starts with linx int indexOfFirstPoint; if ((indexOfFirstPoint = message.IndexOf('.', 4)) != -1) { // There is a point in the text string linxIDstring = message.Substring(4, indexOfFirstPoint - 4); if (int.TryParse(linxIDstring, out linxID)) { // Message for a linx ID // Determine if is an sms or call request txtForLinx = message.Substring(indexOfFirstPoint + 1); if (txtForLinx == ".") { // Call request for LINX PrivateCallRequestForLinxReceived?.Invoke(int.Parse(suid), linxID); // Don't send cmd on mbus continue; } else { // text message for LINX isMessageForLinx = true; } } } } #endif //put information on message bus string sequenceID; Byte[] toSendMulticast = Utils.createMulticastMessage(132, suid, bytes.ToArray(), out sequenceID); udpMulticast.Send(toSendMulticast, toSendMulticast.Length); #if LINXB if (isMessageForLinx) SmsForLixReceived?.Invoke(sequenceID, int.Parse(suid), linxID, txtForLinx); #endif #if DEBUG SafeMobileLib.Utils.WriteLine("SMSReceiveThread Received SMS", ConsoleType.SMS); SafeMobileLib.Utils.WriteLine("SMSReceiveThread sent data to message bus", ConsoleType.SMS); #endif } } else //ack received { SafeMobileLib.Utils.WriteLine("ACK Received", ConsoleType.SMS); string seq_no = "0.0"; if (Main.smsConfirmForUnits.ContainsKey((Int32)radioID)) seq_no = Main.smsConfirmForUnits[(Int32)radioID].getFromConfirmationQueue(hret.seq_no); #if DEBUG SafeMobileLib.Utils.WriteLine("Received ACK with header:" + hret.header + " with seq_id :" + hret.seq_no, ConsoleColor.Cyan, ConsoleType.SMS); SafeMobileLib.Utils.WriteLine("SMSConfirm.getFromConfirmationQueue(hret.seq_no)=" + seq_no, ConsoleColor.Cyan, ConsoleType.SMS); #endif System.Text.Encoding enc = System.Text.Encoding.ASCII; byte[] buf = enc.GetBytes(GetAck4MessagebusForSequence(seq_no)); //send SMS ack to message bus udpMulticast.Send(buf, buf.Length); // add message to the acknowledged ones SMSSendThread.acknowledgedMessagesSeqNo.Add(seq_no); } Thread.Sleep(100); } catch (Exception e) { SafeMobileLib.Utils.WriteLine("##### SMSReceiveThread Exception #########\n" + e.ToString(), ConsoleColor.Red, ConsoleType.SMS); } } } /// /// Create a confirmation message that needs to be broadcasted over the message bus. /// The message requires the sequence number for which the ack is done /// /// Message sequence number that will be ack /// A string that will be sent over the message bus public static string GetAck4MessagebusForSequence(string seqNo) { string test = "#242#1#"; String cmdok = "#" + seqNo + test; Int32 tmp = cmdok.Length + 1; tmp += tmp.ToString().Length; cmdok = "#" + tmp.ToString() + cmdok; return cmdok; } header_T DecodePacket(Byte[] data) { SafeMobileLib.Utils.WriteLine("Decode Packet length " + data.Length, ConsoleType.SMS); header_T hret = new header_T(); int i, j, pdata; pdata = (int)data[0]; pdata <<= 8; pdata |= (int)data[1]; // parse header int header = data[2]; hret.header = data[2]; if ((header & 0x80) != 0) hret.ext = true; else hret.ext = false; if ((header & 0x40) != 0) hret.ack = true; else hret.ack = false; if ((header & 0x10) != 0) hret.cntl = true; else hret.cntl = false; // txt message hret.pdu_type = (byte)(header & 0x0f); SafeMobileLib.Utils.WriteLine("Decode 3 " + data[3], ConsoleType.SMS); // parse address int addrsize = data[3]; i = 4; //Console.Write("Address: "); for (j = 0; j < addrsize; j++) { //Console.Write(data[i + j].ToString("X")); } i += j; // parse rest of headers if (hret.ext) { byte h2 = data[i]; if ((h2 & 0x80) != 0) hret.ext2 = true; else hret.ext2 = false; hret.seq_no = (byte)(h2 & 0x1F); i++; SafeMobileLib.Utils.WriteLine("seq no " + hret.seq_no, ConsoleType.SMS); if (hret.ext2) { // parse third header byte seqNr_MSB = (byte)(data[i] & 0x60); hret.seq_no += seqNr_MSB; hret.encoding = (byte)(data[i] & 0x0f); i++; } } SafeMobileLib.Utils.WriteLine("crc" + data[3], ConsoleType.SMS); int crc = 0; if ((!hret.cntl) && (hret.pdu_type == 0)) { // the rest is the txt message Char[] cs = new Char[100]; int k; for (j = i, k = 0; j < pdata + 2; j++) { //Console.Write(" 0x" + data[j].ToString("X")); if (data[j] != 0) { cs[k++] = (Char)data[j]; crc |= (Char)data[j]; } } SafeMobileLib.Utils.WriteLine("after msg parsing", ConsoleType.SMS); // save message in inbox ht string s = new string(cs, 0, k); s.Replace("\r\n", ""); s = s.Replace(System.Environment.NewLine, string.Empty); SafeMobileLib.Utils.WriteLine("Message [" + s + "]", ConsoleType.SMS); } return hret; } #if LINXB #region Events fro LINX public delegate void SmsForLixReceivedDel(string seqID, int remoteRadioID, int linxRadioID, string text); public event SmsForLixReceivedDel SmsForLixReceived; public delegate void PrivateCallRequestForLinxReceivedDel(int remoteRadioID, int linxRadioID); public event PrivateCallRequestForLinxReceivedDel PrivateCallRequestForLinxReceived; #endregion #endif } }