Ejemplo n.º 1
0
        /// <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());
        }
Ejemplo n.º 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);
        }
Ejemplo n.º 3
0
        /// <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();
        }
Ejemplo n.º 4
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;
        }