/// <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(); }
/// <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; }
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; }