Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/smpp-sharp-lib.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'SmppServerLib/_SmppPdu.cs')
-rw-r--r--SmppServerLib/_SmppPdu.cs338
1 files changed, 338 insertions, 0 deletions
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<SmppOptionalParameter>();
+ 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());
+ }
+ }
+}