SafeDispatch/MotoRepeaterCore/SMSReceiveThread.cs
2024-02-22 18:43:59 +02:00

213 lines
8.0 KiB
C#

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 SafeMobileLib.MessageDecoders;
namespace MotoRepeater
{
class SMSReceiveThread
{
public UInt16 smsPort;
private byte[] data = new byte[1024];
private UdpClient udpClient;
public SMSReceiveThread(UInt16 port, UdpClient _udpClient)
{
smsPort = port;
SMSConfirm.fillList();
SMSConfirm.initializeTimer(); ;
udpClient = _udpClient;
}
public void handleConnection()
{
Utils.WriteLine("♥♥♥ SMS Receive Thread Started on port " + smsPort);
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
while (MotoRepeater_GW.isRunning)
{
try
{
//Utils.WriteLine("SMS Receive Thread waiting...");
// Blocks until a message returns on this socket from a remote host.
Byte[] receivedBytes = udpClient.Receive(ref remoteIpEndPoint);
//Console.WriteLine("=======================================================");
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();
Utils.WriteLine("SMS Thread received data from radio " + radioID);
header_T hret = DecodePacket(receivedBytes);
if (hret.ack)
{
//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);
}
//Console.WriteLine("SMSReceiveThread ACK sent: " + Utils.Byte2String(sendBytes, 0, sendBytes[1] + 2));
// schedule ack sending after 1 second
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Thread.Sleep(1000);
/* run your code here */
udpClient.Send(sendBytes, sendBytes[1] + 2, remoteIpEndPoint);
}).Start();
}
if (hret.header != 0x0BF) //regular message received
{
Utils.WriteLine(String.Format("»»» SMS from radio {0} [{1}]", radioID, hret.message));
//put information on message bus
//Byte[] toSendMulticast = Utils.createMulticastMessage(132, suid, receivedBytes);
//OnSMSBytesReceived(Int64.Parse(suid), receivedBytes);
OnSMSReceived(Int64.Parse(suid), hret.message);
//udpMulticast.Send(toSendMulticast, toSendMulticast.Length);
}
else //ack received
{
string seq_no = SMSConfirm.getFromConfirmationQueue(hret.seq_no);
#if DEBUG
Utils.WriteLine("Received ACK with header:" + hret.header + " with seq_id :" + hret.seq_no);
Utils.WriteLine("SMSConfirm.getFromConfirmationQueue(hret.seq_no)=" + seq_no);
#endif
Utils.WriteLine(String.Format("»»» SMS ACK from radio {0}", radioID));
byte[] buf = SafeMobileLib.Utils.Convert_text_For_multicast("#" + seq_no + "#242#1#");
OnSMSAckReceived(buf, seq_no.Equals("0.0") ? hret.seq_no+"" : seq_no);
//udpMulticast.Send(buf, buf.Length);
}
Thread.Sleep(100);
}
catch (Exception e)
{
if(MotoRepeater_GW.isRunning)
Utils.WriteLine("••• SMS Received Thread is restarting...");
}
}
}
header_T DecodePacket(Byte[] data)
{
header_T hret = new header_T();
hret.message = "";
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);
// 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++;
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++;
}
}
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];
}
}
Console.WriteLine();
// save message in inbox ht
string s = new string(cs, 0, k);
s.Replace("\r\n", "");
s = s.Replace(System.Environment.NewLine, string.Empty);
hret.message = s;
//Console.WriteLine("Message [" + s + "]");
}
return hret;
}
public delegate void SMSReceived(Int64 radioID, String message);
public event SMSReceived OnSMSReceived;
public delegate void SMSReceivedBytes(Int64 radioID, byte[] received);
public event SMSReceivedBytes OnSMSBytesReceived;
public delegate void SMSAckReceived(byte[] received, string seq_no);
public event SMSAckReceived OnSMSAckReceived;
}
}