/// <summary>
        /// Sends an SMS message synchronouslly, possibly splitting it on multiple PDUs 
        /// using the specified segmentation & reassembly method.
        /// </summary>
        /// <param name="pdu">The pdu.</param>
        /// <param name="method">The method.</param>
        /// <returns>The list of messageIds assigned by remote party to each submitted PDU.</returns>
        public IEnumerable<string> Send(SmppSubmitSm pdu, SmppSarMethod method)
        {
            var requests = SmppUtil.SplitLongMessage(pdu, method, GetRandomByte()).Cast<SmppRequest>();
            var responses = SendRequests(requests);

            if (responses.Any(x => (x is SmppGenericNackResp)))
            {
                var nack = responses.First(x => x is SmppGenericNackResp);
                var idx = responses.IndexWhere(x => x == nack);
                var req = requests.ElementAt(idx);
                var msg = string.Format("SMPP PDU was rejected by remote party. (error: {0})", nack.CommandStatus);
                throw new SmppRemoteException(msg, req, nack);
            }

            if (responses.Any(x => x.CommandStatus != 0))
            {
                var res = responses.First(x => x.CommandStatus != 0);
                var idx = responses.IndexWhere(x => x == res);
                var req = requests.ElementAt(idx);
                var msg = string.Format("SMPP Request returned an error status. (code: {0})", res.CommandStatus);
                throw new SmppRemoteException(msg, req, res);
            }

            return responses.OfType<SmppSubmitSmResp>().Select(x => x.MessageId).ToArray();
        }
Example #2
0
        /// <summary>
        /// Apply segmentation over a message possibly splitting it on multiple SMPP PDUs.
        /// </summary>
        /// <remarks>
        /// Method may return the passed pdu (modified as needed) as result in case no splitting is required.
        /// </remarks>
        /// <param name="pdu">The base pdu to use.</param>
        /// <param name="method">The segmentation & reasembly method tu use when splitting the message.</param>
        /// <param name="correlationId">The correlation id to set to each message part.</param>
        /// <returns>The list of sequence numbers of PDUs sent</returns>
        public static IEnumerable<SmppSubmitSm> SplitLongMessage(SmppSubmitSm pdu, SmppSarMethod method, byte correlationId)
        {
            if (pdu == null) throw new ArgumentNullException("pdu");

            var result = new List<SmppSubmitSm>();
            var data = pdu.MessagePayload != null ? pdu.MessagePayload : pdu.ShortMessage;

            if (data != null && !(data is string || data is byte[]))
                throw new ArgumentException("Short Message must be a string or byte array.");

            var bytes = data is string ? PduUtil.GetEncodedText(pdu.DataCoding, data as string) : data as byte[];
            var maxSegmentLen = GetMaxSegmentLength(pdu.DataCoding, bytes.Length);

            // Remove/Reset data from PDU..
            pdu.ShortMessage = pdu.MessagePayload = null;
            // Remove sequenceNumber.
            pdu.SequenceNumber = 0;
            // Remove UDH header (if set).
            pdu.EsmClass &= ((byte)~NetworkFeatures.UDHI);
            // Remove SMPP segmentation properties..
            pdu.MoreMessagesToSend = null;
            pdu.NumberOfMessages = null;
            pdu.SarTotalSegments = null;
            pdu.SarMsgRefNumber = null;

            // Sending as payload means avoiding all the data splitting logic.. (which is great ;))
            if (method == SmppSarMethod.SendAsPayload)
            {
                pdu.MessagePayload = data;
                return new[] { pdu };
            }

            // Else.. let's do segmentation and the other crappy stuff..
            var udhref = method == SmppSarMethod.UserDataHeader ? new Nullable<byte>(correlationId) : null;
            var segments = SplitMessage(bytes, maxSegmentLen, udhref);
            var totalSegments = segments.Count();
            var segno = 0;

            // If just one segment, send it w/o SAR parameters..
            if (totalSegments < 2)
            {
                pdu.ShortMessage = data;
                return new[] { pdu };
            }

            // Ok, se we need segmentation, let's go ahead an use input PDU as template.
            var template = pdu.GetEncodedPdu();
            // Well save results here..
            var results = new List<SmppSubmitSm>();

            foreach (var segment in segments)
            {
                var packet = new SmppSubmitSm(template);

                segno++; // Increase sequence number.
                packet.SequenceNumber = 0; // Remove sequenceNumber.
                packet.ShortMessage = segment; // Set current segment bytes as short message..

                switch (method)
                {
                    case SmppSarMethod.UserDataHeader:
                        packet.EsmClass |= (byte)NetworkFeatures.UDHI; // Set UDH flag..
                        break;
                    case SmppSarMethod.UseSmppSegmentation:
                        packet.EsmClass &= ((byte)~NetworkFeatures.UDHI); // Remove UDH header (if set).
                        // Fill-in SMPP segmentation fields..
                        packet.MoreMessagesToSend = segno != totalSegments;
                        packet.NumberOfMessages = (byte)totalSegments;
                        packet.SarTotalSegments = (byte)totalSegments;
                        packet.SarMsgRefNumber = correlationId;
                        packet.SarSegmentSeqnum = (byte)segno;
                        break;
                }

                result.Add(packet);
            }

            return result;
        }
Example #3
0
        static void Main(string[] args)
        {
            var client = new SMPPCommunicator();
            client.Host = "127.0.0.1";
            client.Port = 2775;
            client.SystemId = "test1";
            client.Password = "******";
            client.EnquireLinkInterval = 25;
            client.BindType = AberrantSMPP.Packet.Request.SmppBind.BindingType.BindAsTransceiver;
            client.NpiType = AberrantSMPP.Packet.Pdu.NpiType.ISDN;
            client.TonType = AberrantSMPP.Packet.Pdu.TonType.International;
            client.Version = AberrantSMPP.Packet.Pdu.SmppVersionType.Version3_4;

            client.OnAlert += (s, e) => Console.WriteLine("Alert: " + e.ResponsePdu);
            client.OnBind += (s, e) => Console.WriteLine("OnBind: " + e.ResponsePdu);
            client.OnBindResp += (s, e) => Console.WriteLine("OnBindResp: " + e.ResponsePdu);
            client.OnCancelSm += (s, e) => Console.WriteLine("OnCancelSm: " + e.ResponsePdu);
            client.OnCancelSmResp += (s, e) => Console.WriteLine("OnCancelResp: " + e.ResponsePdu);
            client.OnClose += (s, e) => Console.WriteLine("OnClose: " + e.GetType());
            client.OnDataSm += (s, e) => Console.WriteLine("OnDataSm: " + e.ResponsePdu);
            client.OnDataSmResp += (s, e) => Console.WriteLine("OnDataResp: " + e.ResponsePdu);
            client.OnDeliverSm += (s, e) => Console.WriteLine("OnDeliverSm: " + e.ResponsePdu);
            client.OnDeliverSmResp += (s, e) => Console.WriteLine("OnDeliverSmResp: " + e.ResponsePdu);
            client.OnEnquireLink += (s, e) => Console.WriteLine("OnEnquireLink: " + e.ResponsePdu);
            client.OnEnquireLinkResp += (s, e) => Console.WriteLine("OnEnquireLinkResp: " + e.ResponsePdu);
            client.OnError += (s, e) => Console.WriteLine("OnError: " + e.ThrownException.Message);
            client.OnGenericNack += (s, e) => Console.WriteLine("OnGenericNack: " + e.ResponsePdu);
            client.OnQuerySm += (s, e) => Console.WriteLine("OnQuerySm: " + e.ResponsePdu);
            client.OnQuerySmResp += (s, e) => Console.WriteLine("OnQuerySmResp: " + e.ResponsePdu);
            client.OnReplaceSm += (s, e) => Console.WriteLine("OnReplaceSm: " + e.ResponsePdu);
            client.OnReplaceSmResp += (s, e) => Console.WriteLine("OnReplaceSmResp: " + e.ResponsePdu);
            client.OnSubmitMulti += (s, e) => Console.WriteLine("OnSubmitMulti: " + e.ResponsePdu);
            client.OnSubmitMultiResp += (s, e) => Console.WriteLine("OnSubmitMultiResp: " + e.ResponsePdu);
            client.OnSubmitSm += (s, e) => Console.WriteLine("OnSubmitSm: " + e.ResponsePdu);
            client.OnSubmitSmResp += new SMPPCommunicator.SubmitSmRespEventHandler(client_OnSubmitSmResp);
            client.OnUnbind += (s, e) => Console.WriteLine("OnUnbind: " + e.ResponsePdu);
            client.OnUnboundResp += (s, e) => Console.WriteLine("OnUnboundResp: " + e.ResponsePdu);

            client.Bind();

            //var txt = new String('a', 200);
            //var txt = "X de mas de 160 caractereñ.. @€34567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890ABCDEFGHIJKL987654321";
            var txt = @"X de mas de 160 caractereñ.. @€abcdefghijklmnopqrstxyz!!!0987654321-ABCDE";
            #if true
            var req = new SmppSubmitSm() {
            //var req = new SmppDataSm() {
                AlertOnMsgDelivery = 0x1,
                DataCoding = DataCoding.UCS2,
                SourceAddress = "WOP",
                DestinationAddress = "+34667484721",
                //DestinationAddress = "+34692471323",
                //DestinationAddress = "+34915550000",
                ValidityPeriod = "000000235959000R", // R == Time Relative to SMSC's time.
                //EsmClass = ...
                LanguageIndicator = LanguageIndicator.Unspecified,
                //PayloadType = Pdu.PayloadTypeType.WDPMessage,
                MessagePayload = new byte[] { 0x0A, 0x0A },
            #if true
                ShortMessage = txt,
            #else
                ShortMessage = new byte[] {
                    Encoding.ASCII.GetBytes("A")[0], Encoding.ASCII.GetBytes("U")[0], 0x20,			// A
                    0x20, 0x24,			// Currency
                    0x20, 0x1b, 0x65,	// Euro symbol
                    0x20, 0x2d,			// -
                    0x20, 0x1b, 0x3d,	// tilde (~)
                    0x20, 0x7d,			// ñ
                    0x20, 0x09			// Cedilla
                },
            #endif
                //MsValidity = Pdu.MsValidityType.StoreIndefinitely,
                //NumberOfMessages
                PriorityFlag = Pdu.PriorityType.Highest,
                //PrivacyIndicator = Pdu.PrivacyType.Nonrestricted
                RegisteredDelivery = //Pdu.RegisteredDeliveryType.OnSuccessOrFailure,
                    (Pdu.RegisteredDeliveryType)0x1e,
            };
            #else
            var req = new SmppDataSm()
            {
                //var req = new SmppDataSm() {
                AlertOnMsgDelivery = 0x1,
                DataCoding = Pdu.DataCodingType.Latin1,
                SourceAddress = "EVICERTIA",
                DestinationAddress = "+34667484721",
                //DestinationAddress = "+34915550000",
                //EsmClass = ...
                LanguageIndicator = Pdu.LanguageType.Spanish,
                //PayloadType = Pdu.PayloadTypeType.WDPMessage,
                MessagePayload = new byte[] { 0x0A, 0x0A },
                //MsValidity = Pdu.MsValidityType.StoreIndefinitely,
                //NumberOfMessages
                //PrivacyIndicator = Pdu.PrivacyType.Nonrestricted
                RegisteredDelivery = //Pdu.RegisteredDeliveryType.OnSuccessOrFailure,
                    (Pdu.RegisteredDeliveryType)0x1e,
                SetDpf = Pdu.DpfResultType.DPFSet,
            };
            #endif
            //AberrantSMPP.Utility.PduUtil.SetMessagePayload(req, req.MessagePayload);
            client.SendPdu(req);

            while (true)
            {
                foreach (var id in SentMessages)
                {
                    //var q = new SmppQuerySm() { MessageId = id };
                    //client.SendPdu(q);
                }

                System.Threading.Thread.Sleep(1000);
            }
        }
 /// <summary>
 /// Creates a SubmitSmEventArgs.
 /// </summary>
 /// <param name="packet">The PDU that was received.</param>
 internal SubmitSmEventArgs(SmppSubmitSm packet)
     : base(packet)
 {
     _response = packet;
 }