using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using System.Collections; using SafeNetLib; /* < rsp sid="SID" id="100111" mode="MOD" HW_Type="Hw_type" subscriber="Phone_nr" RFID="RFID" time="TIME" Latitude="" Longitude="" Speed="" ai1="" ai2="" ai3="" ai4="" ai5="" ai6="" ai7="" ai8="" di="" ao1="" ao2="" do=""> */ namespace MotoTRBO_SOC { public class ReceiveSMSThread { public static readonly int READ_TIMEOUT = 8640; public UInt16 port; //public MotoTRBOGW parent; string gwID; string connStr; DBhandle DB; public ReceiveSMSThread(ushort p_port, string p_connStr, string p_gwID) { port = p_port; gwID = p_gwID; connStr = p_connStr; DB = new DBhandle(p_connStr, p_gwID); } // ------------------------------------------------------------------- // Main // ------------------------------------------------------------------- public void HandleConnection() { while (MotoTRBO_GW.running) { while (MotoTRBO_GW.smsUDPclient != null) { try { // update that the Thread is still running MotoTRBO_GW.lastSMSThreadUpdate = DateTime.Now; //IPEndPoint object will allow us to read datagrams sent from any source. IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); //Utils.ConsWrite(DebugMSG_Type.SMS, "Init SMS Thread on port " + port +" ..waiting for SMS:"); // Blocks until a message returns on this socket from a remote host. Byte[] receiveBytes = MotoTRBO_GW.smsUDPclient.Receive(ref RemoteIpEndPoint); string returnData = Encoding.ASCII.GetString(receiveBytes); // Uses the IPEndPoint object to determine which of these two hosts responded. // Utils.ConsWrite(DebugMSG_Type.SMS, "\n--------------------"); //Utils.ConsWrite(DebugMSG_Type.SMS, "SMS Recv: " + LocationThread.Byte2String(receiveBytes, 0, receiveBytes[1] + 2)); //Utils.ConsWrite(DebugMSG_Type.SMS, "From " + RemoteIpEndPoint.Address.ToString() + ":" + RemoteIpEndPoint.Port.ToString()); header_T hret = DecodePacket(receiveBytes, RemoteIpEndPoint); //we got ACK for message add it to DB if ((hret.header == 0xBF) || (hret.header == 0x9F)) { Utils.ConsWrite(DebugMSG_Type.SMS, "»»» SMS ACK with header " + hret.header + " [" + hret.seq_no + "]"); lock (SN_Queues.waitConfSMSList.SyncRoot) { int index = -1; int count = 0; foreach (SMSmsg msg in SN_Queues.waitConfSMSList) { if (msg.seq_no == hret.seq_no) { index = count; SN_Queues.confSMSQueue.PostItem(msg); } count++; } if (index > -1)//we've found the message SN_Queues.waitConfSMSList.RemoveAt(index); } } else { Utils.ConsWrite(DebugMSG_Type.SMS, "»»» SMS [" + hret.message + "] from " + hret.suid); // fire event if (OnSMSReceived != null) OnSMSReceived(hret.message, hret.suid); } } catch (Exception e) { if (e.ToString().Contains("A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond")) { // read timeout has expired. This is a normal behaviour in my case when the udp socket is supposed to have a timout of 5 seconds } else { Utils.ConsWrite(DebugMSG_Type.DB, "##### LocationThread Exception #########\n" + e.ToString()); MotoTRBO_GW.smsUDPclient = null; } // set udp client to null if I want to recreate the udp client //udpClient = null; } Thread.Sleep(1); } if (OnUDPConnectionChanged != null) OnUDPConnectionChanged(false); int c = 0; while (MotoTRBO_GW.running && c < 6) { Thread.Sleep(500); c++; } try { // here the udpClient should be null so I have to recreate it MotoTRBO_GW.smsUDPclient = new UdpClient(port); MotoTRBO_GW.smsUDPclient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); //udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port)); MotoTRBO_GW.smsUDPclient.Client.ReceiveTimeout = 1000 * READ_TIMEOUT; if (OnUDPConnectionChanged != null) OnUDPConnectionChanged(true); } catch (Exception ex) { } } // end while } // ------------------------------------------------------------------- // Aux functions // ------------------------------------------------------------------- struct header_T { public string address; public bool ext, ext2, ack, cntl; public byte pdu_type; public byte seq_no; public byte encoding; public byte header; public string message; public string suid; } header_T DecodePacket(Byte[] data, IPEndPoint RemoteIpEndPoint) { header_T hret = new header_T(); int i, j, pdata; 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]); string suid = radioID.ToString(); pdata = (int)data[0]; pdata <<= 8; pdata |= (int)data[1]; /* Console.ForegroundColor = ConsoleColor.Cyan; //Utils.ConsWrite(DebugMSG_Type.SMS,"Length =" + pdata + "(0x" + data[0].ToString("X") + "," + data[1].ToString("X") + ")"); Console.Write("Data: "); for (i = 2; i < pdata + 2; i++) Console.Write(" 0x" + data[i].ToString("X")); Console.ForegroundColor = ConsoleColor.Gray; */ // parse header int header = data[2]; hret.header = data[2]; //Utils.ConsWrite(DebugMSG_Type.SMS,"Header: " + header.ToString("X")); 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); // parse address int addrsize = data[3]; i = 4; //Utils.ConsWrite(DebugMSG_Type.DB, "Address: "); for (j = 0; j < addrsize; j++) { //Console.Write(data[i + j].ToString("X")); } i += j; if (addrsize == 0) { //Utils.ConsWrite(DebugMSG_Type.SMS, "no len"); } else { //Utils.ConsWrite(DebugMSG_Type.SMS, ""); } // 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++; //Utils.ConsWrite(DebugMSG_Type.SMS,"Seq no: " + hret.seq_no); if (hret.ext2) { // parse third header hret.encoding = (byte)(data[i] & 0x0f); //Utils.ConsWrite(DebugMSG_Type.SMS,"Encoding: " + hret.encoding); i++; } } if (hret.ack) { Thread.Sleep(500); // The client needs an ACK Byte[] sendBytes = new Byte[10]; sendBytes[0] = 0x00; // len (2B) sendBytes[1] = 0x03; sendBytes[2] = 0xBF; // first header (req) sendBytes[3] = 0x00; // addr len sendBytes[4] = hret.seq_no; // 2nd header (opt) MotoTRBO_GW.smsUDPclient.Send(sendBytes, sendBytes[1] + 2, RemoteIpEndPoint.Address.ToString(), RemoteIpEndPoint.Port); //Utils.ConsWrite(DebugMSG_Type.SMS,"SMS ACK sent"); } int crc = 0; if ((!hret.cntl) && (hret.pdu_type == 0)) { // the rest is the txt message //Console.Write("SMS 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]; } } // save message in inbox ht string s = new string(cs, 0, k); s.Replace("\r\n", ""); s = s.Replace(System.Environment.NewLine, string.Empty); // safe message for hret hret.message = s; hret.suid = suid; //Utils.ConsWrite(DebugMSG_Type.SMS,"Message [" + s + "]"); if (s.StartsWith("Rfid")) { string rfid_string = new string(cs, 4, s.Length - 4); //Utils.ConsWrite(DebugMSG_Type.SMS,"RFID detected:" + rfid_string); OC4Jrfid rfid = new OC4Jrfid(); rfid.suid = suid; rfid.rfid = rfid_string; //MotoTRBOGW.DBQueueRFID.PostItem(rfid); } else { //insert message into database if (!DB.insertSMSinDB("" + suid, s)) { SMSmsg sms = new SMSmsg(); sms.suid = suid; sms.msg = "Unit not assigned to this SafeNet Gateway"; sms.req_conf = false; SN_Queues.sendSMSQueue.PostItem(sms); } /* else { LOGS.LOG(MotoTRBO_GW.cfg.gw_id + suid + " " + s); try { string email_addr = ""; string email_body = ""; if (s.Contains("@") && s.Contains(":") && s.Contains(".")) { // this may be an email so analyze further char[] sep = { ':' }; string[] all_msg = s.Split(sep); email_addr = all_msg[0]; email_body = all_msg[1]; if (email_addr.Contains("@") && email_addr.Contains(".")) { // this is email EmailHandler.sendMail(email_addr, email_body, suid); } } } catch (Exception ex) { Utils.ConsWrite(DebugMSG_Type.always, ex.ToString()); } } */ } } //Utils.ConsWrite(DebugMSG_Type.SMS,"i=" + i); return hret; } public delegate void SMSReceivedDEl(String sms, String radioID); public event SMSReceivedDEl OnSMSReceived; public delegate void UDPConnectionChangedDelegate(bool isConnected); public event UDPConnectionChangedDelegate OnUDPConnectionChanged; } }