From a1ab8c17ac61fb1b09ad41cfb527208697340ace Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Sep 2013 22:59:33 +0400 Subject: First commit --- SmppServerLib/Properties/AssemblyInfo.cs | 36 +++ SmppServerLib/SmppClient.cs | 245 ++++++++++++++++++++ SmppServerLib/SmppLib.csproj | 84 +++++++ SmppServerLib/SmppOptionalParameter.cs | 77 +++++++ SmppServerLib/SmppPduAlertNotification.cs | 83 +++++++ SmppServerLib/SmppPduBindReceiver.cs | 29 +++ SmppServerLib/SmppPduBindReceiverResp.cs | 26 +++ SmppServerLib/SmppPduBindTransceiver.cs | 29 +++ SmppServerLib/SmppPduBindTransceiverResp.cs | 26 +++ SmppServerLib/SmppPduBindTransmitter.cs | 29 +++ SmppServerLib/SmppPduBindTransmitterResp.cs | 26 +++ SmppServerLib/SmppPduCancelSm.cs | 94 ++++++++ SmppServerLib/SmppPduCancelSmResp.cs | 22 ++ SmppServerLib/SmppPduDataSm.cs | 118 ++++++++++ SmppServerLib/SmppPduDataSmResp.cs | 36 +++ SmppServerLib/SmppPduDeliverSm.cs | 28 +++ SmppServerLib/SmppPduDeliverSmResp.cs | 26 +++ SmppServerLib/SmppPduEnquireLink.cs | 22 ++ SmppServerLib/SmppPduEnquireLinkResp.cs | 22 ++ SmppServerLib/SmppPduGenericNack.cs | 19 ++ SmppServerLib/SmppPduOutbind.cs | 44 ++++ SmppServerLib/SmppPduQuerySm.cs | 58 +++++ SmppServerLib/SmppPduQuerySmResp.cs | 58 +++++ SmppServerLib/SmppPduReplaceSm.cs | 110 +++++++++ SmppServerLib/SmppPduReplaceSmResp.cs | 22 ++ SmppServerLib/SmppPduSubmitSm.cs | 30 +++ SmppServerLib/SmppPduSubmitSmResp.cs | 26 +++ SmppServerLib/SmppPduUnbind.cs | 18 ++ SmppServerLib/SmppPduUnbindResp.cs | 19 ++ SmppServerLib/SmppUdhiParameter.cs | 29 +++ SmppServerLib/_SmppPdu.cs | 338 ++++++++++++++++++++++++++++ SmppServerLib/_SmppPduBindBase.cs | 90 ++++++++ SmppServerLib/_SmppPduBindRespBase.cs | 46 ++++ SmppServerLib/_SmppPduSmBase.cs | 243 ++++++++++++++++++++ SmppServerLib/_SmppPduSmRespBase.cs | 37 +++ SmppServerLib/bin/Release/SmppLib.dll | Bin 0 -> 48640 bytes 36 files changed, 2245 insertions(+) create mode 100644 SmppServerLib/Properties/AssemblyInfo.cs create mode 100644 SmppServerLib/SmppClient.cs create mode 100644 SmppServerLib/SmppLib.csproj create mode 100644 SmppServerLib/SmppOptionalParameter.cs create mode 100644 SmppServerLib/SmppPduAlertNotification.cs create mode 100644 SmppServerLib/SmppPduBindReceiver.cs create mode 100644 SmppServerLib/SmppPduBindReceiverResp.cs create mode 100644 SmppServerLib/SmppPduBindTransceiver.cs create mode 100644 SmppServerLib/SmppPduBindTransceiverResp.cs create mode 100644 SmppServerLib/SmppPduBindTransmitter.cs create mode 100644 SmppServerLib/SmppPduBindTransmitterResp.cs create mode 100644 SmppServerLib/SmppPduCancelSm.cs create mode 100644 SmppServerLib/SmppPduCancelSmResp.cs create mode 100644 SmppServerLib/SmppPduDataSm.cs create mode 100644 SmppServerLib/SmppPduDataSmResp.cs create mode 100644 SmppServerLib/SmppPduDeliverSm.cs create mode 100644 SmppServerLib/SmppPduDeliverSmResp.cs create mode 100644 SmppServerLib/SmppPduEnquireLink.cs create mode 100644 SmppServerLib/SmppPduEnquireLinkResp.cs create mode 100644 SmppServerLib/SmppPduGenericNack.cs create mode 100644 SmppServerLib/SmppPduOutbind.cs create mode 100644 SmppServerLib/SmppPduQuerySm.cs create mode 100644 SmppServerLib/SmppPduQuerySmResp.cs create mode 100644 SmppServerLib/SmppPduReplaceSm.cs create mode 100644 SmppServerLib/SmppPduReplaceSmResp.cs create mode 100644 SmppServerLib/SmppPduSubmitSm.cs create mode 100644 SmppServerLib/SmppPduSubmitSmResp.cs create mode 100644 SmppServerLib/SmppPduUnbind.cs create mode 100644 SmppServerLib/SmppPduUnbindResp.cs create mode 100644 SmppServerLib/SmppUdhiParameter.cs create mode 100644 SmppServerLib/_SmppPdu.cs create mode 100644 SmppServerLib/_SmppPduBindBase.cs create mode 100644 SmppServerLib/_SmppPduBindRespBase.cs create mode 100644 SmppServerLib/_SmppPduSmBase.cs create mode 100644 SmppServerLib/_SmppPduSmRespBase.cs create mode 100644 SmppServerLib/bin/Release/SmppLib.dll diff --git a/SmppServerLib/Properties/AssemblyInfo.cs b/SmppServerLib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b36762a --- /dev/null +++ b/SmppServerLib/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("SmppServerLib")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SmppServerLib")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("6325e4aa-0915-4195-8f39-8d9046b6feff")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер построения +// Редакция +// +// Можно задать все значения или принять номер построения и номер редакции по умолчанию, +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SmppServerLib/SmppClient.cs b/SmppServerLib/SmppClient.cs new file mode 100644 index 0000000..e90fb6d --- /dev/null +++ b/SmppServerLib/SmppClient.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace Flex.Cluster.Smpp +{ + public class SmppClient : IDisposable + { + TcpClient tcpClient; + Thread receiveThread; + MemoryStream data; + uint length = 0; + + public bool Connected + { + get { return tcpClient != null && tcpClient.Connected; } + } + public delegate void OnConnectedDelegate(SmppClient sender); + public event OnConnectedDelegate OnConnected = delegate { }; + public delegate void OnDisconnectedDelegate(SmppClient sender); + public event OnDisconnectedDelegate OnDisconnected = delegate { }; + public delegate void OnSmppPduReceivedDelegate(SmppClient sender, SmppPdu pdu); + public event OnSmppPduReceivedDelegate OnSmppPduReceived = delegate { }; + public delegate void OnBindTransmitterReceivedDelegate(SmppClient sender, SmppPduBindTransmitter pdu); + public event OnBindTransmitterReceivedDelegate OnBindTransmitterReceived = delegate { }; + public delegate void OnBindTransmitterRespReceivedDelegate(SmppClient sender, SmppPduBindTransmitterResp pdu); + public event OnBindTransmitterRespReceivedDelegate OnBindTransmitterRespReceived = delegate { }; + public delegate void OnBindReceiverReceivedDelegate(SmppClient sender, SmppPduBindReceiver pdu); + public event OnBindReceiverReceivedDelegate OnBindReceiverReceived = delegate { }; + public delegate void OnBindReceiverRespReceivedDelegate(SmppClient sender, SmppPduBindReceiverResp pdu); + public event OnBindReceiverRespReceivedDelegate OnBindReceiverRespReceived = delegate { }; + public delegate void OnBindTransceiverReceivedDelegate(SmppClient sender, SmppPduBindTransceiver pdu); + public event OnBindTransceiverReceivedDelegate OnBindTransceiverReceived = delegate { }; + public delegate void OnBindTransceiverRespReceivedDelegate(SmppClient sender, SmppPduBindTransceiverResp pdu); + public event OnBindTransceiverRespReceivedDelegate OnBindTransceiverRespReceived = delegate { }; + public delegate void OnUnbindReceivedDelegate(SmppClient sender, SmppPduUnbind pdu); + public event OnUnbindReceivedDelegate OnUnbindReceived = delegate { }; + public delegate void OnUnbindRespReceivedDelegate(SmppClient sender, SmppPduUnbindResp pdu); + public event OnUnbindRespReceivedDelegate OnUnbindRespReceived = delegate { }; + public delegate void OnGenerickNackReceivedDelegate(SmppClient sender, SmppPduGenerickNack pdu); + public event OnGenerickNackReceivedDelegate OnGenerickNackReceived = delegate { }; + public delegate void OnSubmitSmReceivedDelegate(SmppClient sender, SmppPduSubmitSm pdu); + public event OnSubmitSmReceivedDelegate OnSubmitSmReceived = delegate { }; + public delegate void OnSubmitSmRespReceivedDelegate(SmppClient sender, SmppPduSubmitSmResp pdu); + public event OnSubmitSmRespReceivedDelegate OnSubmitSmRespReceived = delegate { }; + //public delegate void OnSubmitMultiReceivedDelegate(SmppClient sender, SmppPduSubmitMulti pdu); + //public delegate void OnSubmitMultiRespReceivedDelegate(SmppClient sender, SmppPduSubmitMultiResp pdu); + public delegate void OnDeliverSmReceivedDelegate(SmppClient sender, SmppPduDeliverSm pdu); + public event OnDeliverSmReceivedDelegate OnDeliverSmReceived = delegate { }; + public delegate void OnDeliverSmRespReceivedDelegate(SmppClient sender, SmppPduDeliverSmResp pdu); + public event OnDeliverSmRespReceivedDelegate OnDeliverSmRespReceived = delegate { }; + public delegate void OnDataSmReceivedDelegate(SmppClient sender, SmppPduDataSm pdu); + public event OnDataSmReceivedDelegate OnDataSmReceived = delegate { }; + public delegate void OnDataSmRespReceivedDelegate(SmppClient sender, SmppPduDataSmResp pdu); + public event OnDataSmRespReceivedDelegate OnDataSmRespReceived = delegate { }; + public delegate void OnQuerySmReceivedDelegate(SmppClient sender, SmppPduQuerySm pdu); + public event OnQuerySmReceivedDelegate OnQuerySmReceived = delegate { }; + public delegate void OnQuerySmRespReceivedDelegate(SmppClient sender, SmppPduQuerySmResp pdu); + public event OnQuerySmRespReceivedDelegate OnQuerySmRespReceived = delegate { }; + public delegate void OnCancelSmReceivedDelegate(SmppClient sender, SmppPduCancelSm pdu); + public event OnCancelSmReceivedDelegate OnCancelSmReceived = delegate { }; + public delegate void OnCancelSmRespReceivedDelegate(SmppClient sender, SmppPduCancelSmResp pdu); + public event OnCancelSmRespReceivedDelegate OnCancelSmRespReceived = delegate { }; + public delegate void OnReplaceSmReceivedDelegate(SmppClient sender, SmppPduReplaceSm pdu); + public event OnReplaceSmReceivedDelegate OnReplaceSmReceived = delegate { }; + public delegate void OnReplaceSmRespReceivedDelegate(SmppClient sender, SmppPduReplaceSmResp pdu); + public event OnReplaceSmRespReceivedDelegate OnReplaceSmRespReceived = delegate { }; + public delegate void OnEnquireLinkReceivedDelegate(SmppClient sender, SmppPduEnquireLink pdu); + public event OnEnquireLinkReceivedDelegate OnEnquireLinkReceived = delegate { }; + public delegate void OnEnquireLinkRespReceivedDelegate(SmppClient sender, SmppPduEnquireLinkResp pdu); + public event OnEnquireLinkRespReceivedDelegate OnEnquireLinkRespReceived = delegate { }; + public delegate void OnAlertNotificationReceivedDelegate(SmppClient sender, SmppPduAlertNotification pdu); + public event OnAlertNotificationReceivedDelegate OnAlertNotificationReceived = delegate { }; + + public SmppClient() + { + OnSmppPduReceived += SmppConnection_OnSmppPduReceived; + } + + public void Connect(string host, int port, IPEndPoint localEndPoint = null) + { + Close(); + tcpClient = new TcpClient(localEndPoint ?? new IPEndPoint(IPAddress.Any, 0)); + tcpClient.ReceiveTimeout = 180000; + tcpClient.Connect(host, port); + data = new MemoryStream(); + length = 0; + receiveThread = new Thread(ReceivingThread); + receiveThread.Start(); + //enquireThread = new Thread(EnquireThread); + //enquireThread.Start(); + OnConnected(this); + } + + public void Close() + { + if (Connected) + tcpClient.Client.Disconnect(false); + } + + private void ReceivingThread() + { + try + { + int b; + do + { + b = tcpClient.GetStream().ReadByte(); + if (b >= 0) + { + data.WriteByte((byte)b); + if (data.Length == 4) + { + var buf = data.GetBuffer(); + length = (uint)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); + } + if (data.Length == length) + { + OnSmppPduReceived(this, SmppPdu.CreateFromBytes(data.GetBuffer(), length)); + data = new MemoryStream(); + length = 0; + } + } + } while (tcpClient != null && tcpClient.Connected && b >= 0); + } + catch { } + finally + { + if (tcpClient != null) + { + tcpClient.Close(); + tcpClient = null; + } + receiveThread = null; + OnDisconnected(this); + } + } + + private void EnquireThread() + { + while (tcpClient != null && tcpClient.Connected) + { + Thread.Sleep(55000); + try + { + SendPdu(new SmppPduEnquireLink()); + } + catch { } + } + } + + public void SendPdu(SmppPdu pdu) + { + if (tcpClient == null || !tcpClient.Connected) throw new Exception("Not connected"); + tcpClient.GetStream().Write(pdu.GetData(), 0, (int)pdu.Length); +#if DEBUG + Console.WriteLine("Sending: " + pdu); + Console.WriteLine(); +#endif + } + + void SmppConnection_OnSmppPduReceived(SmppClient sender, SmppPdu pdu) + { + switch (pdu.CommandId) + { + case SmppPdu.SmppCommandType.bind_transmitter: + OnBindTransmitterReceived(this, (SmppPduBindTransmitter)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.bind_transmitter_resp: + OnBindTransmitterRespReceived(this, (SmppPduBindTransmitterResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.bind_receiver: + OnBindReceiverReceived(this, (SmppPduBindReceiver)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.bind_receiver_resp: + OnBindReceiverRespReceived(this, (SmppPduBindReceiverResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.bind_transceiver: + OnBindTransceiverReceived(this, (SmppPduBindTransceiver)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.bind_transceiver_resp: + OnBindTransceiverRespReceived(this, (SmppPduBindTransceiverResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.unbind: + OnUnbindReceived(this, (SmppPduUnbind)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.unbind_resp: + OnUnbindRespReceived(this, (SmppPduUnbindResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.generic_nack: + OnGenerickNackReceived(this, (SmppPduGenerickNack)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.submit_sm: + OnSubmitSmReceived(this, (SmppPduSubmitSm)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.submit_sm_resp: + OnSubmitSmRespReceived(this, (SmppPduSubmitSmResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.deliver_sm: + OnDeliverSmReceived(this, (SmppPduDeliverSm)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.deliver_sm_resp: + OnDeliverSmRespReceived(this, (SmppPduDeliverSmResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.data_sm: + OnDataSmReceived(this, (SmppPduDataSm)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.data_sm_resp: + OnDataSmRespReceived(this, (SmppPduDataSmResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.query_sm: + OnQuerySmReceived(this, (SmppPduQuerySm)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.query_sm_resp: + OnQuerySmRespReceived(this, (SmppPduQuerySmResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.cancel_sm: + OnCancelSmReceived(this, (SmppPduCancelSm)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.cancel_sm_resp: + OnCancelSmRespReceived(this, (SmppPduCancelSmResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.enquire_link: + OnEnquireLinkReceived(this, (SmppPduEnquireLink)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.enquire_link_resp: + OnEnquireLinkRespReceived(this, (SmppPduEnquireLinkResp)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + case SmppPdu.SmppCommandType.alert_notification: + OnAlertNotificationReceived(this, (SmppPduAlertNotification)SmppPdu.CreateFromBytes(pdu.GetData())); + break; + } + } + + public void Dispose() + { + if (Connected) Close(); + } + } +} diff --git a/SmppServerLib/SmppLib.csproj b/SmppServerLib/SmppLib.csproj new file mode 100644 index 0000000..d15c229 --- /dev/null +++ b/SmppServerLib/SmppLib.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {E869C250-AA19-4EEB-8713-FFD3FF012017} + Library + Properties + Flex.Cluster.Smpp + SmppLib + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SmppServerLib/SmppOptionalParameter.cs b/SmppServerLib/SmppOptionalParameter.cs new file mode 100644 index 0000000..31662d0 --- /dev/null +++ b/SmppServerLib/SmppOptionalParameter.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppOptionalParameter + { + public enum ParameterTag : ushort + { + dest_addr_subunit = 0x0005, // GSM + dest_network_type = 0x0006, // Generic + dest_bearer_type = 0x0007, // Generic + dest_telematics_id = 0x0008, // GSM + source_addr_subunit = 0x000D, // GSM + source_network_type = 0x000E, // Generic + source_bearer_type = 0x000F, // Generic + source_telematics_id = 0x0010, // GSM + qos_time_to_live = 0x0017, // Generic + payload_type = 0x0019, // Generic + additional_status_info_text = 0x001D, // Generic + receipted_message_id = 0x001E, // Generic + ms_msg_wait_facilities = 0x0030, // GSM + privacy_indicator = 0x0201, // CDMA, TDMA + source_subaddress = 0x0202, // CDMA, TDMA + dest_subaddress = 0x0203, // CDMA, TDMA + user_message_reference = 0x0204, // 0x0204 Generic + user_response_code = 0x0205, // CDMA, TDMA + source_port = 0x020A, // Generic + destination_port = 0x020B, // Generic + sar_msg_ref_num = 0x020C, // Generic + language_indicator = 0x020D, // CDMA, TDMA + sar_total_segments = 0x020E, // Generic + sar_segment_seqnum = 0x020F, // Generic + SC_interface_version = 0x0210, // Generic + callback_num_pres_ind = 0x0302, // TDMA + callback_num_atag = 0x0303, // TDMA + number_of_messages = 0x0304, // CDMA + callback_num = 0x0381, // CDMA, TDMA, GSM, iDEN + dpf_result = 0x0420, // Generic + set_dpf = 0x0421, // Generic + ms_availability_status = 0x0422, // Generic + network_error_code = 0x0423, // Generic + message_payload = 0x0424, // Generic + delivery_failure_reason = 0x0425, // Generic + more_messages_to_send = 0x0426, // GSM + message_state = 0x0427, // Generic + ussd_service_op = 0x0501, // GSM (USSD) + display_time = 0x1201, // CDMA, TDMA + sms_signal = 0x1203, // TDMA + ms_validity = 0x1204, // CDMA, TDMA + alert_on_message_delivery = 0x130C, // CDMA + its_reply_type = 0x1380, // CDMA + its_session_info = 0x1383 // CDMA + } + + public readonly ParameterTag Tag; + public readonly ushort Length; + public readonly byte[] Value; + + public SmppOptionalParameter(ParameterTag tag, ushort length, byte[] value) + { + Tag = tag; + Length = length; + Value = value; + } + + public override string ToString() + { + var data = new StringBuilder(); + foreach(var b in Value) + data.AppendFormat("{0:X2} ",b); + return string.Format("Option: {0} = {1}", Tag, data.ToString()); + } + } +} diff --git a/SmppServerLib/SmppPduAlertNotification.cs b/SmppServerLib/SmppPduAlertNotification.cs new file mode 100644 index 0000000..d32b090 --- /dev/null +++ b/SmppServerLib/SmppPduAlertNotification.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduAlertNotification : SmppPdu + { + uint offsetSourceAddrTon, offsetSourceAddrNpi, offsetSourceAddr, offsetEsmeAddrTon, offsetEsmeAddrNpi, offsetEsmeAddr, offsetOptionalParameters; + + public byte SourceAddrTon + { + get { return ReadByte(offsetSourceAddrTon); } + } + public byte SourceAddrNpi + { + get { return ReadByte(offsetSourceAddrNpi); } + } + public string SourceAddr + { + get { return ReadCString(offsetSourceAddr); } + } + public byte EsmeAddrTon + { + get { return ReadByte(offsetEsmeAddrTon); } + } + public byte EsmeAddrNpi + { + get { return ReadByte(offsetEsmeAddrNpi); } + } + public string EsmeAddr + { + get { return ReadCString(offsetEsmeAddr); } + } + public SmppOptionalParameter[] OptionalParameters + { + get { return ReadOptionalParameters(offsetOptionalParameters); } + } + + public SmppPduAlertNotification(byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr, byte esmeAddrTon, byte esmeAddrNpi, string esmeAddr, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.alert_notification) + { + offsetSourceAddrTon = CurrentOffset; + WriteByte(sourceAddrTon); + + offsetSourceAddrNpi = CurrentOffset; + WriteByte(sourceAddrNpi); + + if (sourceAddr.Length > 64) throw new ArgumentOutOfRangeException("sourceAddr"); + offsetSourceAddr = CurrentOffset; + WriteCString(sourceAddr); + + offsetEsmeAddrTon = CurrentOffset; + WriteByte(sourceAddrTon); + + offsetEsmeAddrNpi = CurrentOffset; + WriteByte(sourceAddrNpi); + + if (esmeAddr.Length > 64) throw new ArgumentOutOfRangeException("esmeAddr"); + offsetEsmeAddr = CurrentOffset; + WriteCString(esmeAddr); + + offsetOptionalParameters = CurrentOffset; + if (optionalParameters != null) + WriteOptionalParameters(optionalParameters); + } + + public SmppPduAlertNotification(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduAlertNotification(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.alert_notification) throw new Exception("Invaid command ID"); + offsetSourceAddrTon = 12; + offsetSourceAddrNpi = offsetSourceAddrTon + 1; + offsetSourceAddr = offsetSourceAddrNpi + 1; + offsetEsmeAddrTon = FindCStringEnd(offsetSourceAddr); + offsetEsmeAddrNpi = offsetEsmeAddrTon + 1; + offsetEsmeAddr = offsetEsmeAddrNpi + 1; + offsetOptionalParameters = FindCStringEnd(offsetEsmeAddr); + } + } +} diff --git a/SmppServerLib/SmppPduBindReceiver.cs b/SmppServerLib/SmppPduBindReceiver.cs new file mode 100644 index 0000000..22430d0 --- /dev/null +++ b/SmppServerLib/SmppPduBindReceiver.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduBindReceiver : SmppPduBindBase + { + protected override SmppPdu.SmppCommandType GetCommandType() + { + return SmppCommandType.bind_receiver; + } + + public SmppPduBindReceiver(string systemId, string password, string systemType, byte interfaceVersion, byte addrTon, byte addrNpi, string addrRange) + : base(SmppCommandType.bind_receiver, systemId, password, systemType, interfaceVersion, addrTon, addrNpi, addrRange) + { + } + + public SmppPduBindReceiver(byte[] bytes) + : this(bytes, (uint)bytes.Length) + { + } + public SmppPduBindReceiver(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduBindReceiverResp.cs b/SmppServerLib/SmppPduBindReceiverResp.cs new file mode 100644 index 0000000..e51504f --- /dev/null +++ b/SmppServerLib/SmppPduBindReceiverResp.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduBindReceiverResp : SmppPduBindRespBase + { + protected override SmppPdu.SmppCommandType GetCommandType() + { + return SmppCommandType.bind_receiver_resp; + } + + public SmppPduBindReceiverResp(uint sequenceId, SmppCommandStatus status, string systemId, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.bind_receiver_resp, sequenceId, status, systemId, optionalParameters) + { + } + + public SmppPduBindReceiverResp(byte[] bytes) : this(bytes, (uint)bytes.Length) {} + public SmppPduBindReceiverResp(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduBindTransceiver.cs b/SmppServerLib/SmppPduBindTransceiver.cs new file mode 100644 index 0000000..324f0b3 --- /dev/null +++ b/SmppServerLib/SmppPduBindTransceiver.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduBindTransceiver : SmppPduBindBase + { + protected override SmppPdu.SmppCommandType GetCommandType() + { + return SmppCommandType.bind_transceiver; + } + + public SmppPduBindTransceiver(string systemId, string password, string systemType, byte interfaceVersion, byte addrTon, byte addrNpi, string addrRange) + : base(SmppCommandType.bind_transceiver, systemId, password, systemType, interfaceVersion, addrTon, addrNpi, addrRange) + { + } + + public SmppPduBindTransceiver(byte[] bytes) + : this(bytes, (uint)bytes.Length) + { + } + public SmppPduBindTransceiver(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduBindTransceiverResp.cs b/SmppServerLib/SmppPduBindTransceiverResp.cs new file mode 100644 index 0000000..ca03bc2 --- /dev/null +++ b/SmppServerLib/SmppPduBindTransceiverResp.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduBindTransceiverResp : SmppPduBindRespBase + { + protected override SmppPdu.SmppCommandType GetCommandType() + { + return SmppCommandType.bind_transceiver_resp; + } + + public SmppPduBindTransceiverResp(uint sequenceId, SmppCommandStatus status, string systemId, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.bind_transceiver_resp, sequenceId, status, systemId, optionalParameters) + { + } + + public SmppPduBindTransceiverResp(byte[] bytes) : this(bytes, (uint)bytes.Length) {} + public SmppPduBindTransceiverResp(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduBindTransmitter.cs b/SmppServerLib/SmppPduBindTransmitter.cs new file mode 100644 index 0000000..c10a4b2 --- /dev/null +++ b/SmppServerLib/SmppPduBindTransmitter.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduBindTransmitter : SmppPduBindBase + { + protected override SmppPdu.SmppCommandType GetCommandType() + { + return SmppCommandType.bind_transmitter; + } + + public SmppPduBindTransmitter(string systemId, string password, string systemType, byte interfaceVersion, byte addrTon, byte addrNpi, string addrRange) + : base(SmppCommandType.bind_transmitter, systemId, password, systemType, interfaceVersion, addrTon, addrNpi, addrRange) + { + } + + public SmppPduBindTransmitter(byte[] bytes) + : this(bytes, (uint)bytes.Length) + { + } + public SmppPduBindTransmitter(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduBindTransmitterResp.cs b/SmppServerLib/SmppPduBindTransmitterResp.cs new file mode 100644 index 0000000..934222d --- /dev/null +++ b/SmppServerLib/SmppPduBindTransmitterResp.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduBindTransmitterResp : SmppPduBindRespBase + { + protected override SmppPdu.SmppCommandType GetCommandType() + { + return SmppCommandType.bind_transmitter_resp; + } + + public SmppPduBindTransmitterResp(uint sequenceId, SmppCommandStatus status, string systemId, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.bind_transmitter_resp, sequenceId, status, systemId, optionalParameters) + { + } + + public SmppPduBindTransmitterResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduBindTransmitterResp(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduCancelSm.cs b/SmppServerLib/SmppPduCancelSm.cs new file mode 100644 index 0000000..a43ba72 --- /dev/null +++ b/SmppServerLib/SmppPduCancelSm.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduCancelSm : SmppPdu + { + uint offsetServiceType, offsetMessageId, offsetSourceAddrTon, offsetSourceAddrNpi, offsetSourceAddr, + offsetDestAddrTon, offsetDestAddrNpi, offsetDestAddr; + + public string ServiceType + { + get { return ReadCString(offsetServiceType); } + } + public string MessageId + { + get { return ReadCString(offsetMessageId); } + } + public byte SourceAddrTon + { + get { return ReadByte(offsetSourceAddrTon); } + } + public byte SourceAddrNpi + { + get { return ReadByte(offsetSourceAddrNpi); } + } + public string SourceAddr + { + get { return ReadCString(offsetSourceAddr); } + } + public byte DestAddrTon + { + get { return ReadByte(offsetDestAddrTon); } + } + public byte DestAddrNpi + { + get { return ReadByte(offsetDestAddrNpi); } + } + public string DestAddr + { + get { return ReadCString(offsetDestAddr); } + } + + public SmppPduCancelSm(string serviceType, string messageId, byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr, + byte destAddrTon, byte destAddrNpi, string destAddr) + : base(SmppCommandType.cancel_sm) + { + if (serviceType.Length > 5) throw new ArgumentOutOfRangeException("serviceType"); + offsetServiceType = CurrentOffset; + WriteCString(serviceType); + + if (messageId.Length > 64) throw new ArgumentOutOfRangeException("messageId"); + offsetMessageId = CurrentOffset; + WriteCString(messageId); + + offsetSourceAddrTon = CurrentOffset; + WriteByte(sourceAddrTon); + + offsetSourceAddrNpi = CurrentOffset; + WriteByte(sourceAddrNpi); + + if (sourceAddr.Length > 20) throw new ArgumentOutOfRangeException("sourceAddr"); + offsetSourceAddr = CurrentOffset; + WriteCString(sourceAddr); + + offsetDestAddrTon = CurrentOffset; + WriteByte(destAddrTon); + + offsetDestAddrNpi = CurrentOffset; + WriteByte(destAddrTon); + + if (destAddr.Length > 20) throw new ArgumentOutOfRangeException("destAddr"); + offsetDestAddr = CurrentOffset; + WriteCString(destAddr); + } + + public SmppPduCancelSm(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduCancelSm(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.cancel_sm) throw new Exception("Invaid command ID"); + offsetServiceType = 12; + offsetMessageId = FindCStringEnd(offsetServiceType); + offsetSourceAddrTon = FindCStringEnd(offsetMessageId); + offsetSourceAddrNpi = offsetSourceAddrTon + 1; + offsetSourceAddr = offsetSourceAddrNpi + 1; + offsetDestAddrTon = FindCStringEnd(offsetSourceAddr); + offsetDestAddrNpi = offsetDestAddrTon + 1; + offsetDestAddr = offsetDestAddrNpi + 1; + } + } +} diff --git a/SmppServerLib/SmppPduCancelSmResp.cs b/SmppServerLib/SmppPduCancelSmResp.cs new file mode 100644 index 0000000..9f77dd8 --- /dev/null +++ b/SmppServerLib/SmppPduCancelSmResp.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduCancelSmResp : SmppPdu + { + public SmppPduCancelSmResp(uint sequenceId, SmppCommandStatus status) + : base(SmppCommandType.cancel_sm_resp, status, sequenceId) + { + } + + public SmppPduCancelSmResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduCancelSmResp(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.cancel_sm_resp) throw new Exception("Invaid command ID"); + } + } +} diff --git a/SmppServerLib/SmppPduDataSm.cs b/SmppServerLib/SmppPduDataSm.cs new file mode 100644 index 0000000..33c91ff --- /dev/null +++ b/SmppServerLib/SmppPduDataSm.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduDataSm : SmppPdu + { + uint offsetServiceType, offsetSourceAddrTon, offsetSourceAddrNpi, offsetSourceAddr, offsetDestAddrTon, offsetDestAddrNpi, offsetDestAddr, + offsetEsmClass, offsetRegisteredDelivery, offsetDataCoding, offsetOptionalParameters; + + public string ServiceType + { + get { return ReadCString(offsetServiceType); } + } + public byte SourceAddrTon + { + get { return ReadByte(offsetSourceAddrTon); } + } + public byte SourceAddrNpi + { + get { return ReadByte(offsetSourceAddrNpi); } + } + public string SourceAddr + { + get { return ReadCString(offsetSourceAddr); } + } + public byte DestAddrTon + { + get { return ReadByte(offsetDestAddrTon); } + } + public byte DestAddrNpi + { + get { return ReadByte(offsetDestAddrNpi); } + } + public string DestAddr + { + get { return ReadCString(offsetDestAddr); } + } + public byte EsmClass + { + get { return ReadByte(offsetEsmClass); } + } + public byte RegisteredDelivery + { + get { return ReadByte(offsetRegisteredDelivery); } + } + public byte DataCoding + { + get { return ReadByte(offsetDataCoding); } + } + public SmppOptionalParameter[] OptionalParameters + { + get { return ReadOptionalParameters(offsetOptionalParameters); } + } + + public SmppPduDataSm(string serviceType, byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr, byte destAddrTon, byte destAddrNpi, string destAddr, + byte esmClass, byte registeredDelivery, byte dataCoding, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.data_sm) + { + if (serviceType.Length > 5) throw new ArgumentOutOfRangeException("systemType"); + offsetServiceType = CurrentOffset; + WriteCString(serviceType); + + offsetSourceAddrTon = CurrentOffset; + WriteByte(sourceAddrTon); + + offsetSourceAddrNpi = CurrentOffset; + WriteByte(sourceAddrNpi); + + if (sourceAddr.Length > 20) throw new ArgumentOutOfRangeException("sourceAddr"); + offsetSourceAddr = CurrentOffset; + WriteCString(sourceAddr); + + offsetDestAddrTon = CurrentOffset; + WriteByte(destAddrTon); + + offsetDestAddrNpi = CurrentOffset; + WriteByte(destAddrNpi); + + if (destAddr.Length > 20) throw new ArgumentOutOfRangeException("destAddr"); + offsetDestAddr = CurrentOffset; + WriteCString(destAddr); + + offsetEsmClass = CurrentOffset; + WriteByte(esmClass); + + offsetRegisteredDelivery = CurrentOffset; + WriteByte(registeredDelivery); + + offsetDataCoding = CurrentOffset; + WriteByte(dataCoding); + + offsetOptionalParameters = CurrentOffset; + if (optionalParameters != null) + WriteOptionalParameters(optionalParameters); + } + + public SmppPduDataSm(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduDataSm(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.data_sm) throw new Exception("Invaid command ID"); + offsetServiceType = 12; + offsetSourceAddrTon = FindCStringEnd(offsetServiceType); + offsetSourceAddrNpi = offsetSourceAddrTon + 1; + offsetSourceAddr = offsetSourceAddrNpi + 1; + offsetDestAddrTon = FindCStringEnd(offsetSourceAddr); + offsetDestAddrNpi = offsetDestAddrTon + 1; + offsetDestAddr = offsetDestAddrNpi + 1; + offsetEsmClass = FindCStringEnd(offsetDestAddr); + offsetRegisteredDelivery = offsetEsmClass + 1; + offsetDataCoding = offsetRegisteredDelivery + 1; + offsetOptionalParameters = offsetDataCoding + 1; + } + } +} diff --git a/SmppServerLib/SmppPduDataSmResp.cs b/SmppServerLib/SmppPduDataSmResp.cs new file mode 100644 index 0000000..9c5c505 --- /dev/null +++ b/SmppServerLib/SmppPduDataSmResp.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduDataSmResp : SmppPduSmRespBase + { + uint offsetOptionalParameters; + + override protected SmppCommandType GetCommandType() + { + return SmppCommandType.data_sm_resp; + } + public SmppOptionalParameter[] OptionalParameters + { + get { return ReadOptionalParameters(offsetOptionalParameters); } + } + + public SmppPduDataSmResp(uint sequenceId, SmppCommandStatus status, string messageId, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.data_sm_resp, sequenceId, status, messageId) + { + offsetOptionalParameters = CurrentOffset; + if (optionalParameters != null) + WriteOptionalParameters(optionalParameters); + } + + public SmppPduDataSmResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduDataSmResp(byte[] bytes, uint length) + : base(bytes, length) + { + offsetOptionalParameters = FindCStringEnd(offsetMessageId); + } + } +} diff --git a/SmppServerLib/SmppPduDeliverSm.cs b/SmppServerLib/SmppPduDeliverSm.cs new file mode 100644 index 0000000..2592cbc --- /dev/null +++ b/SmppServerLib/SmppPduDeliverSm.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduDeliverSm : SmppPduSmBase + { + override protected SmppCommandType GetCommandType() + { + return SmppCommandType.deliver_sm; + } + + public SmppPduDeliverSm(string serviceType, byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr, byte destAddrTon, byte destAddrNpi, string destAddr, + byte esmClass, byte protocolId, byte priorityFlag, byte registeredDelivery, byte dataCoding, /*byte smLength,*/ string shortMessage, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.deliver_sm, serviceType, sourceAddrTon, sourceAddrNpi, sourceAddr, destAddrTon, destAddrNpi, destAddr, esmClass, protocolId, + priorityFlag, "", "", registeredDelivery, 0, dataCoding, 0, /*smLength,*/ shortMessage, optionalParameters) + { + } + + public SmppPduDeliverSm(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduDeliverSm(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduDeliverSmResp.cs b/SmppServerLib/SmppPduDeliverSmResp.cs new file mode 100644 index 0000000..e541711 --- /dev/null +++ b/SmppServerLib/SmppPduDeliverSmResp.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduDeliverSmResp : SmppPduSmRespBase + { + override protected SmppCommandType GetCommandType() + { + return SmppCommandType.deliver_sm_resp; + } + + public SmppPduDeliverSmResp(uint sequenceId, SmppCommandStatus status = SmppCommandStatus.ESME_ROK) + : base(SmppCommandType.deliver_sm_resp, sequenceId, status, "") + { + } + + public SmppPduDeliverSmResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduDeliverSmResp(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduEnquireLink.cs b/SmppServerLib/SmppPduEnquireLink.cs new file mode 100644 index 0000000..2be1d70 --- /dev/null +++ b/SmppServerLib/SmppPduEnquireLink.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduEnquireLink : SmppPdu + { + public SmppPduEnquireLink() + : base(SmppCommandType.enquire_link) + { + } + + public SmppPduEnquireLink(byte[] bytes) : this(bytes, (uint)bytes.Length) {} + public SmppPduEnquireLink(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.enquire_link) throw new Exception("Invaid command ID"); + } + } +} diff --git a/SmppServerLib/SmppPduEnquireLinkResp.cs b/SmppServerLib/SmppPduEnquireLinkResp.cs new file mode 100644 index 0000000..9c5c596 --- /dev/null +++ b/SmppServerLib/SmppPduEnquireLinkResp.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduEnquireLinkResp : SmppPdu + { + public SmppPduEnquireLinkResp(uint sequenceId, SmppCommandStatus status = SmppCommandStatus.ESME_ROK) + : base(SmppCommandType.enquire_link_resp, status, sequenceId) + { + } + + public SmppPduEnquireLinkResp(byte[] bytes) : this(bytes, (uint)bytes.Length) {} + public SmppPduEnquireLinkResp(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.enquire_link_resp) throw new Exception("Invaid command ID"); + } + } +} diff --git a/SmppServerLib/SmppPduGenericNack.cs b/SmppServerLib/SmppPduGenericNack.cs new file mode 100644 index 0000000..7b277a7 --- /dev/null +++ b/SmppServerLib/SmppPduGenericNack.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduGenerickNack : SmppPdu + { + public SmppPduGenerickNack(uint sequenceId, SmppCommandStatus status) + : base(SmppCommandType.generic_nack, status, sequenceId) { } + public SmppPduGenerickNack(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduGenerickNack(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.generic_nack) throw new Exception("Invaid command ID"); + } + } +} diff --git a/SmppServerLib/SmppPduOutbind.cs b/SmppServerLib/SmppPduOutbind.cs new file mode 100644 index 0000000..f9961b3 --- /dev/null +++ b/SmppServerLib/SmppPduOutbind.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduOutbind : SmppPdu + { + uint offsetSystemId, offsetPassword; + + public string SystemId + { + get { return ReadCString(offsetSystemId); } + } + public string Password + { + get { return ReadCString(offsetPassword); } + } + + public SmppPduOutbind(string systemId, string password) + : base(SmppCommandType.outbind) + { + if (systemId.Length > 15) throw new ArgumentOutOfRangeException("systemId"); + offsetSystemId = CurrentOffset; + WriteCString(systemId); + + if (password.Length > 8) throw new ArgumentOutOfRangeException("password"); + offsetPassword = CurrentOffset; + WriteCString(password); + } + + public SmppPduOutbind(byte[] bytes) : this(bytes, (uint)bytes.Length) + { + } + public SmppPduOutbind(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.outbind) throw new Exception("Invaid command ID"); + offsetSystemId = 12; + offsetPassword = FindCStringEnd(offsetSystemId); + } + } +} diff --git a/SmppServerLib/SmppPduQuerySm.cs b/SmppServerLib/SmppPduQuerySm.cs new file mode 100644 index 0000000..aee5b73 --- /dev/null +++ b/SmppServerLib/SmppPduQuerySm.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduQuerySm : SmppPdu + { + uint offsetMessageId, offsetSourceAddrTon, offsetSourceAddrNpi, offsetSourceAddr; + + public string MessageId + { + get { return ReadCString(offsetMessageId); } + } + public byte SourceAddrTon + { + get { return ReadByte(offsetSourceAddrTon); } + } + public byte SourceAddrNpi + { + get { return ReadByte(offsetSourceAddrNpi); } + } + public string SourceAddr + { + get { return ReadCString(offsetSourceAddr); } + } + + public SmppPduQuerySm(string messageId, byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr) + : base(SmppCommandType.query_sm) + { + if (messageId.Length > 64) throw new ArgumentOutOfRangeException("messageId"); + offsetMessageId = CurrentOffset; + WriteCString(messageId); + + offsetSourceAddrTon = CurrentOffset; + WriteByte(sourceAddrTon); + + offsetSourceAddrNpi = CurrentOffset; + WriteByte(sourceAddrNpi); + + if (sourceAddr.Length > 20) throw new ArgumentOutOfRangeException("sourceAddr"); + offsetSourceAddr = CurrentOffset; + WriteCString(sourceAddr); + } + + public SmppPduQuerySm(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduQuerySm(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.query_sm) throw new Exception("Invaid command ID"); + offsetMessageId = 12; + offsetSourceAddrTon = FindCStringEnd(offsetMessageId); + offsetSourceAddrNpi = offsetSourceAddrTon + 1; + offsetSourceAddr = offsetSourceAddrNpi + 1; + } + } +} diff --git a/SmppServerLib/SmppPduQuerySmResp.cs b/SmppServerLib/SmppPduQuerySmResp.cs new file mode 100644 index 0000000..416131e --- /dev/null +++ b/SmppServerLib/SmppPduQuerySmResp.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduQuerySmResp : SmppPdu + { + uint offsetMessageId, offsetFinalDate, offsetMessageState, offsetErrorCode; + + public string MessageId + { + get { return ReadCString(offsetMessageId); } + } + public string FinalDate + { + get { return ReadCString(offsetFinalDate); } + } + public byte MessageState + { + get { return ReadByte(offsetMessageState); } + } + public byte ErrorCode + { + get { return ReadByte(offsetErrorCode); } + } + + public SmppPduQuerySmResp(uint sequenceId, SmppCommandStatus status, string messageId, string finalDate, byte messageState, byte errorCode) + : base(SmppCommandType.query_sm_resp, status, sequenceId) + { + if (messageId.Length > 64) throw new ArgumentOutOfRangeException("messageId"); + offsetMessageId = CurrentOffset; + WriteCString(messageId); + + if (finalDate.Length != 0 && finalDate.Length != 16) throw new ArgumentOutOfRangeException("finalDate"); + offsetFinalDate = CurrentOffset; + WriteCString(finalDate); + + offsetMessageState = CurrentOffset; + WriteByte(messageState); + + offsetErrorCode = CurrentOffset; + WriteByte(errorCode); + } + + public SmppPduQuerySmResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduQuerySmResp(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.query_sm_resp) throw new Exception("Invaid command ID"); + offsetMessageId = 12; + offsetFinalDate = FindCStringEnd(offsetMessageId); + offsetMessageState = FindCStringEnd(offsetFinalDate); + offsetErrorCode = offsetMessageState+1; + } + } +} diff --git a/SmppServerLib/SmppPduReplaceSm.cs b/SmppServerLib/SmppPduReplaceSm.cs new file mode 100644 index 0000000..48d4361 --- /dev/null +++ b/SmppServerLib/SmppPduReplaceSm.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduReplaceSm : SmppPdu + { + uint offsetMessageId, offsetSourceAddrTon, offsetSourceAddrNpi, offsetSourceAddr, offsetScheduleDeliveryTime, + offsetRegisteredDelivery, offsetValidityPeriod, offsetSmDefaultMsgId, offsetSmLength, offsetShortMessage; + + public string MessageId + { + get { return ReadCString(offsetMessageId); } + } + public byte SourceAddrTon + { + get { return ReadByte(offsetSourceAddrTon); } + } + public byte SourceAddrNpi + { + get { return ReadByte(offsetSourceAddrNpi); } + } + public string SourceAddr + { + get { return ReadCString(offsetSourceAddr); } + } + public string ScheduleDeliveryTime + { + get { return ReadCString(offsetScheduleDeliveryTime); } + } + public string ValidityPeriod + { + get { return ReadCString(offsetValidityPeriod); } + } + public byte RegisteredDelivery + { + get { return ReadByte(offsetRegisteredDelivery); } + } + public byte SmDefaultMsgId + { + get { return ReadByte(offsetSmDefaultMsgId); } + } + public byte SmLength + { + get { return ReadByte(offsetSmLength); } + } + public string ShortMessage + { + get { return ReadString(offsetShortMessage, SmLength ); } + } + + public SmppPduReplaceSm(string messageId, byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr, string scheduleDeliveryTime, string validityPeriod, byte registeredDelivery, byte smDefaultMsgId, byte smLength, string shortMessage) + : base(SmppCommandType.replace_sm) + { + if (messageId.Length > 64) throw new ArgumentOutOfRangeException("messageId"); + offsetMessageId = CurrentOffset; + WriteCString(messageId); + + offsetSourceAddrTon = CurrentOffset; + WriteByte(sourceAddrTon); + + offsetSourceAddrNpi = CurrentOffset; + WriteByte(sourceAddrNpi); + + if (sourceAddr.Length > 20) throw new ArgumentOutOfRangeException("sourceAddr"); + offsetSourceAddr = CurrentOffset; + WriteCString(sourceAddr); + + if (scheduleDeliveryTime.Length != 0 && scheduleDeliveryTime.Length != 16) throw new ArgumentOutOfRangeException("scheduleDeliveryTime"); + offsetScheduleDeliveryTime = CurrentOffset; + WriteCString(scheduleDeliveryTime); + + if (validityPeriod.Length != 0 && validityPeriod.Length != 16) throw new ArgumentOutOfRangeException("validityPeriod"); + offsetValidityPeriod = CurrentOffset; + WriteCString(validityPeriod); + + offsetRegisteredDelivery = CurrentOffset; + WriteByte(registeredDelivery); + + offsetSmDefaultMsgId = CurrentOffset; + WriteByte(smDefaultMsgId); + + // TODO: Codepage? + offsetSmLength = CurrentOffset; + WriteByte(smLength); + + offsetShortMessage = CurrentOffset; + WriteString(shortMessage, smLength); + } + + public SmppPduReplaceSm(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduReplaceSm(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.replace_sm) throw new Exception("Invaid command ID"); + offsetMessageId = 12; + offsetSourceAddrTon = FindCStringEnd(offsetMessageId); + offsetSourceAddrNpi = offsetSourceAddrTon + 1; + offsetSourceAddr = offsetSourceAddrNpi + 1; + offsetScheduleDeliveryTime = FindCStringEnd(offsetSourceAddr); + offsetValidityPeriod = FindCStringEnd(offsetScheduleDeliveryTime); + offsetRegisteredDelivery = FindCStringEnd(offsetValidityPeriod); + offsetSmDefaultMsgId = offsetRegisteredDelivery + 1; + offsetSmLength = offsetSmDefaultMsgId + 1; + offsetShortMessage = offsetSmLength + 1; + } + } +} diff --git a/SmppServerLib/SmppPduReplaceSmResp.cs b/SmppServerLib/SmppPduReplaceSmResp.cs new file mode 100644 index 0000000..8d93c91 --- /dev/null +++ b/SmppServerLib/SmppPduReplaceSmResp.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduReplaceSmResp : SmppPdu + { + public SmppPduReplaceSmResp(uint sequenceId, SmppCommandStatus status) + : base(SmppCommandType.replace_sm_resp, status, sequenceId) + { + } + + public SmppPduReplaceSmResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduReplaceSmResp(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.replace_sm_resp) throw new Exception("Invaid command ID"); + } + } +} diff --git a/SmppServerLib/SmppPduSubmitSm.cs b/SmppServerLib/SmppPduSubmitSm.cs new file mode 100644 index 0000000..533bbba --- /dev/null +++ b/SmppServerLib/SmppPduSubmitSm.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduSubmitSm : SmppPduSmBase + { + override protected SmppCommandType GetCommandType() + { + return SmppCommandType.submit_sm; + } + + public SmppPduSubmitSm(string serviceType, byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr, byte destAddrTon, byte destAddrNpi, string destAddr, + byte esmClass, byte protocolId, byte priorityFlag, string scheduleDeliveryTime, string validityPeriod, byte registeredDelivery, byte replaceIfPresentFlag, + byte dataCoding, byte smDefaultMsgId, /*byte smLength,*/ string shortMessage, SmppOptionalParameter[] optionalParameters = null) + : base(SmppCommandType.submit_sm, serviceType, sourceAddrTon, sourceAddrNpi, sourceAddr, destAddrTon, destAddrNpi, destAddr, esmClass, protocolId, + priorityFlag, scheduleDeliveryTime, validityPeriod, registeredDelivery, replaceIfPresentFlag, dataCoding, smDefaultMsgId, /*smLength,*/ shortMessage, + optionalParameters) + { + } + + public SmppPduSubmitSm(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduSubmitSm(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduSubmitSmResp.cs b/SmppServerLib/SmppPduSubmitSmResp.cs new file mode 100644 index 0000000..ea26a64 --- /dev/null +++ b/SmppServerLib/SmppPduSubmitSmResp.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduSubmitSmResp : SmppPduSmRespBase + { + override protected SmppCommandType GetCommandType() + { + return SmppCommandType.submit_sm_resp; + } + + public SmppPduSubmitSmResp(uint sequenceId, SmppCommandStatus status, string messageId) + : base(SmppCommandType.submit_sm_resp, sequenceId, status, messageId) + { + } + + public SmppPduSubmitSmResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduSubmitSmResp(byte[] bytes, uint length) + : base(bytes, length) + { + } + } +} diff --git a/SmppServerLib/SmppPduUnbind.cs b/SmppServerLib/SmppPduUnbind.cs new file mode 100644 index 0000000..98f61c6 --- /dev/null +++ b/SmppServerLib/SmppPduUnbind.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduUnbind : SmppPdu + { + public SmppPduUnbind() : base(SmppCommandType.unbind) { } + public SmppPduUnbind(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduUnbind(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.unbind) throw new Exception("Invaid command ID"); + } + } +} diff --git a/SmppServerLib/SmppPduUnbindResp.cs b/SmppServerLib/SmppPduUnbindResp.cs new file mode 100644 index 0000000..db2c157 --- /dev/null +++ b/SmppServerLib/SmppPduUnbindResp.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPduUnbindResp : SmppPdu + { + public SmppPduUnbindResp(uint sequenceId, SmppCommandStatus status) + : base(SmppCommandType.unbind_resp, status, sequenceId) { } + public SmppPduUnbindResp(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduUnbindResp(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != SmppCommandType.unbind_resp) throw new Exception("Invaid command ID"); + } + } +} diff --git a/SmppServerLib/SmppUdhiParameter.cs b/SmppServerLib/SmppUdhiParameter.cs new file mode 100644 index 0000000..83a9122 --- /dev/null +++ b/SmppServerLib/SmppUdhiParameter.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppUdhiParameter + { + public readonly byte Tag; + public readonly byte Length; + public readonly byte[] Value; + + public SmppUdhiParameter(byte tag, byte length, byte[] value) + { + Tag = tag; + Length = length; + Value = value; + } + + public override string ToString() + { + var data = new StringBuilder(); + foreach(var b in Value) + data.AppendFormat("{0:X2} ",b); + return string.Format("UDHI: {0} = {1}", Tag, data.ToString()); + } + } +} diff --git a/SmppServerLib/_SmppPdu.cs b/SmppServerLib/_SmppPdu.cs new file mode 100644 index 0000000..11519a0 --- /dev/null +++ b/SmppServerLib/_SmppPdu.cs @@ -0,0 +1,338 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public class SmppPdu + { + static uint currentSeqNumber = 1; + const uint offsetCommandId = 0; + const uint offsetStatus = 4; + const uint offsetSequenceNumber = 8; + + public uint Length + { + get { return (uint)(data.Length + 4); } + } + protected uint CurrentOffset + { + get { return (uint)(data.Length); } + } + public SmppCommandType CommandId + { + get { return (SmppCommandType)ReadInteger(offsetCommandId); } + } + public SmppCommandStatus Status + { + get { return (SmppCommandStatus)ReadInteger(offsetStatus); } + } + public uint SequenceNumber + { + get { return ReadInteger(offsetSequenceNumber); } + } + MemoryStream data; + + public enum SmppCommandType : uint + { + generic_nack = 0x80000000, + bind_receiver = 0x00000001, + bind_receiver_resp = 0x80000001, + bind_transmitter = 0x00000002, + bind_transmitter_resp = 0x80000002, + query_sm = 0x00000003, + query_sm_resp = 0x80000003, + submit_sm = 0x00000004, + submit_sm_resp = 0x80000004, + deliver_sm = 0x00000005, + deliver_sm_resp = 0x80000005, + unbind = 0x00000006, + unbind_resp = 0x80000006, + replace_sm = 0x00000007, + replace_sm_resp = 0x80000007, + cancel_sm = 0x00000008, + cancel_sm_resp = 0x80000008, + bind_transceiver = 0x00000009, + bind_transceiver_resp = 0x80000009, + outbind = 0x0000000B, + enquire_link = 0x00000015, + enquire_link_resp = 0x80000015, + submit_multi = 0x00000021, + submit_multi_resp = 0x80000021, + alert_notification = 0x00000102, + data_sm = 0x00000103, + data_sm_resp = 0x80000103 + }; + public enum SmppCommandStatus : uint + { + ESME_ROK = 0x00000000, // No Error + ESME_RINVMSGLEN = 0x00000001, // Message Length is invalid + ESME_RINVCMDLEN = 0x00000002, // Command Length is invalid + ESME_RINVCMDID = 0x00000003, // Invalid Command ID + ESME_RINVBNDSTS = 0x00000004, // Incorrect BIND Status for given command + ESME_RALYBND = 0x00000005, // ESME Already in Bound State + ESME_RINVPRTFLG = 0x00000006, // Invalid Priority Flag + ESME_RINVREGDLVFLG = 0x00000007, // Invalid Registered Delivery Flag + ESME_RSYSERR = 0x00000008, // System Error + ESME_RINVSRCADR = 0x0000000A, // Invalid Source Address + ESME_RINVDSTADR = 0x0000000B, // Invalid Dest Addr + ESME_RINVMSGID = 0x0000000C, // Message ID is invalid + ESME_RBINDFAIL = 0x0000000D, // Bind Failed + ESME_RINVPASWD = 0x0000000E, // Invalid Password + ESME_RINVSYSID = 0x0000000F, // Invalid System ID + ESME_RCANCELFAIL = 0x00000011, // 0x00000011 Cancel SM Failed + ESME_RREPLACEFAIL = 0x00000013, // Replace SM Failed + ESME_RMSGQFUL = 0x00000014, // Message Queue Full + ESME_RINVSERTYP = 0x00000015, // Invalid Service Type + ESME_RINVNUMDESTS = 0x00000033, // Invalid number of destinations + ESME_RINVDLNAME = 0x00000034, // Invalid Distribution List name + ESME_RINVDESTFLAG = 0x00000040, // Destination flag is invalid + ESME_RINVSUBREP = 0x00000042, // Invalid ‘submit with replace’ request + ESME_RINVESMCLASS = 0x00000043, // Invalid esm_classfield data + ESME_RCNTSUBDL = 0x00000044, // Cannot Submit to Distribution List + ESME_RSUBMITFAIL = 0x00000045, // submit_smor submit_multi failed + ESME_RINVSRCTON = 0x00000048, // Invalid Source address TON + ESME_RINVSRCNPI = 0x00000049, // Invalid Source address NPI + ESME_RINVDSTTON = 0x00000050, // Invalid Destination address TON + ESME_RINVDSTNPI = 0x00000051, // Invalid Destination address NPI + ESME_RINVSYSTYP = 0x00000053, // Invalid system_typefield + ESME_RINVREPFLAG = 0x00000054, // Invalid replace_if_present flag + ESME_RINVNUMMSGS = 0x00000055, // Invalid number of messages + ESME_RTHROTTLED = 0x00000058, // Throttling error (ESME has exceeded allowed message limits) + ESME_RINVSCHED = 0x00000061, // Invalid Scheduled Delivery Time + ESME_RINVEXPIRY = 0x00000062, // Invalid message validity period (Expiry time) + ESME_RINVDFTMSGID = 0x00000063, // Predefined Message Invalid or Not Found + ESME_RX_T_APPN = 0x00000064, // ESME Receiver Temporary App Error Code + ESME_RX_P_APPN = 0x00000065, // ESME Receiver Permanent App Error Code + ESME_RX_R_APPN = 0x00000066, // ESME Receiver Reject Message Error Code + ESME_RQUERYFAIL = 0x00000067, // query_smrequest failed + ESME_RINVOPTPARSTREAM = 0x000000C0, // Error in the optional part of the PDU Body. + ESME_ROPTPARNOTALLWD = 0x000000C1, // Optional Parameter not allowed + ESME_RINVPARLEN = 0x000000C2, // Invalid Parameter Length. + ESME_RMISSINGOPTPARAM = 0x000000C3, // Expected Optional Parameter missing + ESME_RINVOPTPARAMVAL = 0x000000C4, // Invalid Optional Parameter Value + ESME_RDELIVERYFAILURE = 0x000000FE, // Delivery Failure (used for data_sm_resp) + ESME_RUNKNOWNERR = 0x000000FF // Unknown Error + } + + public byte[] GetData() + { + var result = new byte[Length]; + result[0] = (byte)((Length >> 24) & 0xFF); + result[1] = (byte)((Length >> 16) & 0xFF); + result[2] = (byte)((Length >> 8) & 0xFF); + result[3] = (byte)(Length & 0xFF); + var buffer = data.GetBuffer(); + Array.Copy(buffer, 0, result, 4, Length - 4); + return result; + } + + protected void WriteInteger(uint v) + { + data.Seek(0, SeekOrigin.End); + data.WriteByte((byte)((v >> 24) & 0xFF)); + data.WriteByte((byte)((v >> 16) & 0xFF)); + data.WriteByte((byte)((v >> 8) & 0xFF)); + data.WriteByte((byte)(v & 0xFF)); + } + protected uint ReadInteger(uint offset) + { + uint result = 0; + var buffer = data.GetBuffer(); + for (int c = 0; c < 4; c++) + { + var b = buffer[offset + c]; + result <<= 8; + result |= (byte)b; + } + return result; + } + protected void WriteShort(ushort v) + { + data.Seek(0, SeekOrigin.End); + data.WriteByte((byte)((v >> 8) & 0xFF)); + data.WriteByte((byte)(v & 0xFF)); + } + protected ushort ReadShort(uint offset) + { + ushort result = 0; + var buffer = data.GetBuffer(); + for (int c = 0; c < 2; c++) + { + var b = buffer[offset + c]; + result <<= 8; + result |= (byte)b; + } + return result; + } + protected void WriteByte(byte v) + { + data.Seek(0, SeekOrigin.End); + data.WriteByte(v); + } + protected byte ReadByte(uint offset) + { + var buffer = data.GetBuffer(); + return buffer[offset]; + } + protected byte[] ReadBytes(uint offset, int len) + { + var buffer = data.GetBuffer(); + var result = new byte[len]; + Array.Copy(buffer, offset, result, 0, len); + return result; + } + protected void WriteCString(string v, Encoding encoding = null) + { + encoding = encoding ?? Encoding.ASCII; + var bytes = encoding.GetBytes(v); + data.Seek(0, SeekOrigin.End); + data.Write(bytes, 0, bytes.Length); + data.WriteByte(0); + } + protected string ReadCString(uint offset, Encoding encoding = null) + { + encoding = encoding ?? Encoding.ASCII; + var buffer = data.GetBuffer(); + int len = 0; + while (buffer[offset + len] != 0) len++; + return encoding.GetString(buffer, (int)offset, len); + } + protected uint FindCStringEnd(uint offset) + { + var buffer = data.GetBuffer(); + uint result = offset; + while (buffer[result] != 0) result++; + return result + 1; + } + protected void WriteString(string v, uint length, Encoding encoding = null) + { + encoding = encoding ?? Encoding.ASCII; + var bytes = encoding.GetBytes(v); + data.Seek(0, SeekOrigin.End); + data.Write(bytes, 0, (int)length); + } + protected string ReadString(uint offset, uint length, Encoding encoding = null) + { + encoding = encoding ?? Encoding.ASCII; + var buffer = data.GetBuffer(); + return encoding.GetString(buffer, (int)offset, (int)length); + } + protected void WriteOptionalParameters(SmppOptionalParameter[] parameters) + { + foreach (var parameter in parameters) + { + WriteShort((ushort)parameter.Tag); + WriteShort((ushort)parameter.Length); + data.Write(parameter.Value, 0, parameter.Length); + } + } + protected SmppOptionalParameter[] ReadOptionalParameters(uint offset) + { + var parameters = new List(); + uint pos = offset; + var buffer = data.GetBuffer(); + while (pos + 3 < data.Length) + { + ushort tag = ReadShort(pos); + pos += 2; + ushort valueLength = ReadShort(pos); + pos += 2; + var value = new byte[valueLength]; + Array.Copy(buffer, pos, value, 0, valueLength); + pos += valueLength; + parameters.Add(new SmppOptionalParameter((SmppOptionalParameter.ParameterTag)tag, valueLength, value)); + } + return parameters.ToArray(); + } + + protected SmppPdu(SmppCommandType commandType, SmppCommandStatus commandStatus = 0, uint seqNumber = 0) + { + data = new MemoryStream(); + WriteInteger((uint)commandType); + WriteInteger((uint)commandStatus); + WriteInteger(seqNumber == 0 ? currentSeqNumber++ : seqNumber); + if (currentSeqNumber > int.MaxValue) currentSeqNumber = 1; + } + public SmppPdu(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPdu(byte[] bytes, uint length) + { + data = new MemoryStream(); + data.Write(bytes, 4, (int)length - 4); + } + + public static SmppPdu CreateFromBytes(byte[] bytes) + { + return CreateFromBytes(bytes, (uint)bytes.Length); + } + public static SmppPdu CreateFromBytes(byte[] bytes, uint length) + { + var pdu = new SmppPdu(bytes, length); + switch (pdu.CommandId) + { + case SmppCommandType.bind_receiver: + return new SmppPduBindReceiver(bytes, length); + case SmppCommandType.bind_receiver_resp: + return new SmppPduBindReceiverResp(bytes, length); + case SmppCommandType.bind_transceiver: + return new SmppPduBindTransceiver(bytes, length); + case SmppCommandType.bind_transceiver_resp: + return new SmppPduBindTransceiverResp(bytes, length); + case SmppCommandType.bind_transmitter: + return new SmppPduBindTransmitter(bytes, length); + case SmppCommandType.bind_transmitter_resp: + return new SmppPduBindTransmitterResp(bytes, length); + case SmppCommandType.outbind: + return new SmppPduOutbind(bytes, length); + case SmppCommandType.unbind: + return new SmppPduUnbind(bytes, length); + case SmppCommandType.unbind_resp: + return new SmppPduUnbindResp(bytes, length); + case SmppCommandType.enquire_link: + return new SmppPduEnquireLink(bytes, length); + case SmppCommandType.enquire_link_resp: + return new SmppPduEnquireLinkResp(bytes, length); + case SmppCommandType.generic_nack: + return new SmppPduGenerickNack(bytes, length); + case SmppCommandType.deliver_sm: + return new SmppPduDeliverSm(bytes, length); + case SmppCommandType.submit_sm: + return new SmppPduSubmitSm(bytes, length); + case SmppCommandType.deliver_sm_resp: + return new SmppPduDeliverSmResp(bytes, length); + case SmppCommandType.submit_sm_resp: + return new SmppPduSubmitSmResp(bytes, length); + case SmppCommandType.data_sm: + return new SmppPduDataSm(bytes, length); + case SmppCommandType.data_sm_resp: + return new SmppPduDataSmResp(bytes, length); + case SmppCommandType.query_sm: + return new SmppPduQuerySm(bytes, length); + case SmppCommandType.query_sm_resp: + return new SmppPduQuerySmResp(bytes, length); + case SmppCommandType.cancel_sm: + return new SmppPduCancelSm(bytes, length); + case SmppCommandType.cancel_sm_resp: + return new SmppPduCancelSmResp(bytes, length); + case SmppCommandType.replace_sm: + return new SmppPduReplaceSm(bytes, length); + case SmppCommandType.replace_sm_resp: + return new SmppPduReplaceSmResp(bytes, length); + case SmppCommandType.alert_notification: + return new SmppPduAlertNotification(bytes, length); + } + throw new NotSupportedException(string.Format("Command {0} is not supported", pdu.CommandId)); + } + + public override string ToString() + { + var d = GetData(); + var dStr = new StringBuilder(); + foreach (var b in d) + dStr.AppendFormat("{0:X2} ", b); + return string.Format("Command: {0}, status: {1}, seq: {2}, length: {3}, data: {4}", CommandId, Status, SequenceNumber, Length, dStr.ToString()); + } + } +} diff --git a/SmppServerLib/_SmppPduBindBase.cs b/SmppServerLib/_SmppPduBindBase.cs new file mode 100644 index 0000000..9d64c79 --- /dev/null +++ b/SmppServerLib/_SmppPduBindBase.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public abstract class SmppPduBindBase : SmppPdu + { + abstract protected SmppCommandType GetCommandType(); + + uint offsetSystemId, offsetPassword, offsetSystemType, offsetInterfaceVersion, offsetAddrTon, offsetAddrNpi, offsetAddrRange; + + public string SystemId + { + get { return ReadCString(offsetSystemId); } + } + public string Password + { + get { return ReadCString(offsetPassword); } + } + public string SystemType + { + get { return ReadCString(offsetSystemType); } + } + public byte InterfaceVersion + { + get { return ReadByte(offsetInterfaceVersion);} + } + public byte AddrTon + { + get { return ReadByte(offsetAddrTon); } + } + public byte AddrNpi + { + get { return ReadByte(offsetAddrNpi); } + } + public string AddrRange + { + get { return ReadCString(offsetAddrRange); } + } + + public SmppPduBindBase(SmppCommandType commandType, string systemId, string password, string systemType, byte interfaceVersion, byte addrTon, byte addrNpi, string addrRange) + : base(commandType) + { + if (commandType != GetCommandType()) throw new Exception("Invaid command ID"); + + if (systemId.Length > 15) throw new ArgumentOutOfRangeException("systemId"); + offsetSystemId = CurrentOffset; + WriteCString(systemId); + + if (password.Length > 8) throw new ArgumentOutOfRangeException("password"); + offsetPassword = CurrentOffset; + WriteCString(password); + + if (systemType.Length > 12) throw new ArgumentOutOfRangeException("systemType"); + offsetSystemType = CurrentOffset; + WriteCString(systemType); + + offsetInterfaceVersion = CurrentOffset; + WriteByte(interfaceVersion); + + offsetAddrTon = CurrentOffset; + WriteByte(addrTon); + + offsetAddrNpi = CurrentOffset; + WriteByte(addrNpi); + + if (addrRange.Length > 40) throw new ArgumentOutOfRangeException("addressRange"); + offsetAddrRange = CurrentOffset; + WriteCString(addrRange); + } + + public SmppPduBindBase(byte[] bytes) : this(bytes, (uint)bytes.Length) + { + } + public SmppPduBindBase(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != GetCommandType()) throw new Exception("Invaid command ID"); + offsetSystemId = 12; + offsetPassword = FindCStringEnd(offsetSystemId); + offsetSystemType = FindCStringEnd(offsetPassword); + offsetInterfaceVersion = FindCStringEnd(offsetSystemType); + offsetAddrTon = offsetInterfaceVersion + 1; + offsetAddrNpi = offsetAddrTon + 1; + offsetAddrRange = offsetAddrNpi + 1; + } + } +} diff --git a/SmppServerLib/_SmppPduBindRespBase.cs b/SmppServerLib/_SmppPduBindRespBase.cs new file mode 100644 index 0000000..fd38139 --- /dev/null +++ b/SmppServerLib/_SmppPduBindRespBase.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public abstract class SmppPduBindRespBase : SmppPdu + { + abstract protected SmppCommandType GetCommandType(); + + uint offsetSystemId, offsetOptionalParameters; + + public string SystemId + { + get { return ReadCString(offsetSystemId); } + } + public SmppOptionalParameter[] OptionalParameters + { + get { return ReadOptionalParameters(offsetOptionalParameters); } + } + + public SmppPduBindRespBase(SmppCommandType commandType, uint sequenceId, SmppCommandStatus status, string systemId, SmppOptionalParameter[] optionalParameters = null) + : base(commandType, status, sequenceId) + { + if (commandType != GetCommandType()) throw new Exception("Invaid command ID"); + + if (systemId.Length > 15) throw new ArgumentOutOfRangeException("systemId"); + offsetSystemId = CurrentOffset; + WriteCString(systemId); + + offsetOptionalParameters = CurrentOffset; + if (optionalParameters != null) + WriteOptionalParameters(optionalParameters); + } + + public SmppPduBindRespBase(byte[] bytes) : this(bytes, (uint)bytes.Length) {} + public SmppPduBindRespBase(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != GetCommandType()) throw new Exception("Invaid command ID"); + offsetSystemId = 12; + offsetOptionalParameters = FindCStringEnd(offsetSystemId); + } + } +} diff --git a/SmppServerLib/_SmppPduSmBase.cs b/SmppServerLib/_SmppPduSmBase.cs new file mode 100644 index 0000000..279e106 --- /dev/null +++ b/SmppServerLib/_SmppPduSmBase.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public abstract class SmppPduSmBase : SmppPdu + { + abstract protected SmppCommandType GetCommandType(); + + uint offsetServiceType, offsetSourceAddrTon, offsetSourceAddrNpi, offsetSourceAddr, offsetDestAddrTon, offsetDestAddrNpi, offsetDestAddr, + offsetEsmClass, offsetProtocolId, offsetPriorityFlag, offsetScheduleDeliveryTime, offsetRegisteredDelivery, offsetValidityPeriod, offsetReplaceIfPresentFlag, offsetDataCoding, + offsetSmDefaultMsgId, offsetSmLength, offsetShortMessage, offsetOptionalParameters; + + public string ServiceType + { + get { return ReadCString(offsetServiceType); } + } + public byte SourceAddrTon + { + get { return ReadByte(offsetSourceAddrTon); } + } + public byte SourceAddrNpi + { + get { return ReadByte(offsetSourceAddrNpi); } + } + public string SourceAddr + { + get { return ReadCString(offsetSourceAddr); } + } + public byte DestAddrTon + { + get { return ReadByte(offsetDestAddrTon); } + } + public byte DestAddrNpi + { + get { return ReadByte(offsetDestAddrNpi); } + } + public string DestAddr + { + get { return ReadCString(offsetDestAddr); } + } + public byte EsmClass + { + get { return ReadByte(offsetEsmClass); } + } + public byte ProtocolId + { + get { return ReadByte(offsetProtocolId); } + } + public byte PriorityFlag + { + get { return ReadByte(offsetPriorityFlag); } + } + public string ScheduleDeliveryTime + { + get { return ReadCString(offsetScheduleDeliveryTime); } + } + public string ValidityPeriod + { + get { return ReadCString(offsetValidityPeriod); } + } + public byte RegisteredDelivery + { + get { return ReadByte(offsetRegisteredDelivery); } + } + public byte ReplaceIfPresentFlag + { + get { return ReadByte(offsetReplaceIfPresentFlag); } + } + public byte DataCoding + { + get { return ReadByte(offsetDataCoding); } + } + public Encoding DataEncoder + { + get + { + switch (DataCoding) + { + case 0: + return Encoding.ASCII; + case 8: + return Encoding.BigEndianUnicode; + default: + throw new NotSupportedException(string.Format("Codepage {0} is not supported yet", DataCoding)); + } + } + } + public byte SmDefaultMsgId + { + get { return ReadByte(offsetSmDefaultMsgId); } + } + public byte SmLength + { + get { return ReadByte(offsetSmLength); } + } + public string ShortMessage + { + get + { + if ((EsmClass & 64) == 0) + return ReadString(offsetShortMessage, SmLength, DataEncoder); + byte udhiLength = ReadByte(offsetShortMessage); + return ReadString(offsetShortMessage + udhiLength + 1, (uint)(SmLength - udhiLength - 1), DataEncoder); // UDHI + } + } + public SmppOptionalParameter[] OptionalParameters + { + get { return ReadOptionalParameters(offsetOptionalParameters); } + } + public SmppUdhiParameter[] UdhiParameters + { + get + { + if ((EsmClass & 64) == 0) return new SmppUdhiParameter[0]; + byte udhiLength = ReadByte(offsetShortMessage); + var result = new List(); + byte pos = 0; + while (pos < udhiLength) + { + byte tag = ReadByte(offsetShortMessage + 1 + pos); + byte len = ReadByte(offsetShortMessage + 1 + pos + 1); + var data = ReadBytes(offsetShortMessage + 1 + pos + 2, len); + result.Add(new SmppUdhiParameter(tag, len, data)); + pos += (byte)(len + 2); + } + return result.ToArray(); + } + } + + public SmppPduSmBase(SmppCommandType commandType, string serviceType, byte sourceAddrTon, byte sourceAddrNpi, string sourceAddr, byte destAddrTon, byte destAddrNpi, string destAddr, + byte esmClass, byte protocolId, byte priorityFlag, string scheduleDeliveryTime, string validityPeriod, byte registeredDelivery, byte replaceIfPresentFlag, + byte dataCoding, byte smDefaultMsgId, /*byte smLength,*/ string shortMessage, SmppOptionalParameter[] optionalParameters = null) + : base(commandType) + { + if (commandType != GetCommandType()) throw new Exception("Invaid command ID"); + + if (serviceType.Length > 5) throw new ArgumentOutOfRangeException("systemType"); + offsetServiceType = CurrentOffset; + WriteCString(serviceType); + + offsetSourceAddrTon = CurrentOffset; + WriteByte(sourceAddrTon); + + offsetSourceAddrNpi = CurrentOffset; + WriteByte(sourceAddrNpi); + + if (sourceAddr.Length > 20) throw new ArgumentOutOfRangeException("sourceAddr"); + offsetSourceAddr = CurrentOffset; + WriteCString(sourceAddr); + + offsetDestAddrTon = CurrentOffset; + WriteByte(destAddrTon); + + offsetDestAddrNpi = CurrentOffset; + WriteByte(destAddrNpi); + + if (destAddr.Length > 20) throw new ArgumentOutOfRangeException("destAddr"); + offsetDestAddr = CurrentOffset; + WriteCString(destAddr); + + offsetEsmClass = CurrentOffset; + WriteByte(esmClass); + + offsetProtocolId = CurrentOffset; + WriteByte(protocolId); + + offsetPriorityFlag = CurrentOffset; + WriteByte(priorityFlag); + + if (scheduleDeliveryTime.Length != 0 && scheduleDeliveryTime.Length != 16) throw new ArgumentOutOfRangeException("scheduleDeliveryTime"); + offsetScheduleDeliveryTime = CurrentOffset; + WriteCString(scheduleDeliveryTime); + + if (validityPeriod.Length != 0 && validityPeriod.Length != 16) throw new ArgumentOutOfRangeException("validityPeriod"); + offsetValidityPeriod = CurrentOffset; + WriteCString(validityPeriod); + + offsetRegisteredDelivery = CurrentOffset; + WriteByte(registeredDelivery); + + offsetReplaceIfPresentFlag = CurrentOffset; + WriteByte(replaceIfPresentFlag); + + offsetDataCoding = CurrentOffset; + WriteByte(dataCoding); + + offsetSmDefaultMsgId = CurrentOffset; + WriteByte(smDefaultMsgId); + + if (DataEncoder.GetByteCount(shortMessage) > 254) throw new ArgumentOutOfRangeException("smLength"); + offsetSmLength = CurrentOffset; + WriteByte((byte)DataEncoder.GetByteCount(shortMessage)); + + offsetShortMessage = CurrentOffset; + WriteString(shortMessage, (byte)DataEncoder.GetByteCount(shortMessage), DataEncoder); + + offsetOptionalParameters = CurrentOffset; + if (optionalParameters != null) + WriteOptionalParameters(optionalParameters); + } + + public SmppPduSmBase(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduSmBase(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != GetCommandType()) throw new Exception("Invaid command ID"); + offsetServiceType = 12; + offsetSourceAddrTon = FindCStringEnd(offsetServiceType); + offsetSourceAddrNpi = offsetSourceAddrTon + 1; + offsetSourceAddr = offsetSourceAddrNpi + 1; + offsetDestAddrTon = FindCStringEnd(offsetSourceAddr); + offsetDestAddrNpi = offsetDestAddrTon + 1; + offsetDestAddr = offsetDestAddrNpi + 1; + offsetEsmClass = FindCStringEnd(offsetDestAddr); + offsetProtocolId = offsetEsmClass + 1; + offsetPriorityFlag = offsetProtocolId + 1; + offsetScheduleDeliveryTime = offsetPriorityFlag + 1; + offsetValidityPeriod = FindCStringEnd(offsetScheduleDeliveryTime); + offsetRegisteredDelivery = FindCStringEnd(offsetValidityPeriod); + offsetReplaceIfPresentFlag = offsetRegisteredDelivery + 1; + offsetDataCoding = offsetReplaceIfPresentFlag + 1; + offsetSmDefaultMsgId = offsetDataCoding + 1; + offsetSmLength = offsetSmDefaultMsgId + 1; + offsetShortMessage = offsetSmLength + 1; + offsetOptionalParameters = offsetShortMessage + SmLength; + } + + public override string ToString() + { + var options = new StringBuilder(); + foreach (var option in OptionalParameters) + options.AppendFormat("\r\n{0}", option.ToString()); + foreach (var udhi in UdhiParameters) + options.AppendFormat("\r\n{0}", udhi.ToString()); + return base.ToString() + string.Format("\r\nservice type: {0}, source_addr_ton: {1}, source_addr_npi: {2}, sounce_addr: {3}, dest_addr_ton: {4}, dest_addr_npi: {5}, destination_addr: {6}, length: {8}, message: {7}", + ServiceType, SourceAddrTon, SourceAddrNpi, SourceAddr, DestAddrTon, DestAddrNpi, DestAddr, ShortMessage, SmLength) + + options.ToString(); + } + } +} diff --git a/SmppServerLib/_SmppPduSmRespBase.cs b/SmppServerLib/_SmppPduSmRespBase.cs new file mode 100644 index 0000000..d1b3309 --- /dev/null +++ b/SmppServerLib/_SmppPduSmRespBase.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Flex.Cluster.Smpp +{ + public abstract class SmppPduSmRespBase : SmppPdu + { + abstract protected SmppCommandType GetCommandType(); + + protected uint offsetMessageId; + + public string MessageId + { + get { return ReadCString(offsetMessageId); } + } + + public SmppPduSmRespBase(SmppCommandType commandType, uint sequenceId, SmppCommandStatus status, string messageId) + : base(commandType, status, sequenceId) + { + if (commandType != GetCommandType()) throw new Exception("Invaid command ID"); + + if (messageId.Length > 64) throw new ArgumentOutOfRangeException("messageId"); + offsetMessageId = CurrentOffset; + WriteCString(messageId); + } + + public SmppPduSmRespBase(byte[] bytes) : this(bytes, (uint)bytes.Length) { } + public SmppPduSmRespBase(byte[] bytes, uint length) + : base(bytes, length) + { + if (CommandId != GetCommandType()) throw new Exception("Invaid command ID"); + offsetMessageId = 12; + } + } +} diff --git a/SmppServerLib/bin/Release/SmppLib.dll b/SmppServerLib/bin/Release/SmppLib.dll new file mode 100644 index 0000000..9c49fe1 Binary files /dev/null and b/SmppServerLib/bin/Release/SmppLib.dll differ -- cgit v1.2.3