360 lines
14 KiB
Plaintext
360 lines
14 KiB
Plaintext
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=""> </rsp>
|
||
*/
|
||
|
||
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, "<22><><EFBFBD> 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, "<22><><EFBFBD> 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;
|
||
|
||
|
||
}
|
||
} |