diff --git a/ASyncSocketClient.cs b/ASyncSocketClient.cs new file mode 100644 index 0000000..9a4962d --- /dev/null +++ b/ASyncSocketClient.cs @@ -0,0 +1,382 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; +using System.Net.Sockets; + +namespace RoaminSMPP +{ + /// + /// Socket class for asynchronous connection. + /// + internal class AsyncSocketClient : IDisposable + { + #region delegates + + /// + /// Called when a message is received. + /// + /// + /// The AsyncSocketClient to receive messages from. + /// + public delegate void MessageHandler(AsyncSocketClient asyncSocketClient); + + /// + /// Called when a connection is closed. + /// + /// + /// The AsyncSocketClient to receive messages from. + /// + public delegate void SocketClosingHandler( + AsyncSocketClient asyncSocketClient); + + /// + /// Called when a socket error occurs. + /// + /// + /// The AsyncSocketClient to receive messages from. + /// + /// + /// The exception that generated the error. + /// + public delegate void ErrorHandler( + AsyncSocketClient asyncSocketClient, Exception exception); + + #endregion delegates + //one MB + private const int BUFFER_SIZE = 1048576; + + #region private fields + + private NetworkStream _NetworkStream; + private TcpClient _TcpClient; + private AsyncCallback _CallbackReadMethod; + private AsyncCallback _CallbackWriteMethod; + private MessageHandler _MessageHandler; + private SocketClosingHandler _SocketCloseHandler; + private ErrorHandler _ErrorHandler; + private bool _IsDisposed; + private string _ServerIPAddress; + private Int16 _ServerPort; + private object _StateObject; + private byte[] _Buffer; + //private int clientBufferSize; + + #endregion private fields + + #region properties + + /// + /// The server IP address to connect to. + /// + public string ServerIPAddress + { + get + { + return _ServerIPAddress; + } + } + + /// + /// The server port to connect to. + /// + public Int16 ServerPort + { + get + { + return _ServerPort; + } + } + + /// + /// A user set state object to associate some state with a connection. + /// + public object StateObject + { + get + { + return _StateObject; + } + set + { + _StateObject = value; + } + } + + /// + /// Buffer to hold data coming in from the socket. + /// + public byte[] Buffer + { + get + { + return _Buffer; + } + } + + #endregion properties + + /// + /// Constructs an AsyncSocketClient. + /// + /// The size of the receive buffer. + /// The object to use for sending state + /// information. + /// The user-defined message handling method. + /// + /// The user-defined socket closing + /// handling method. + /// The user defined error handling method. + /// + public AsyncSocketClient(Int32 bufferSize, object stateObject, + MessageHandler msgHandler, SocketClosingHandler closingHandler, + ErrorHandler errHandler) + { + //allocate buffer +// clientBufferSize = bufferSize; +// _Buffer = new byte[clientBufferSize]; + + _Buffer = new byte[BUFFER_SIZE]; + _StateObject = stateObject; + + //set handlers + _MessageHandler = msgHandler; + _SocketCloseHandler = closingHandler; + _ErrorHandler = errHandler; + + //set the asynchronous method handlers + _CallbackReadMethod = new AsyncCallback(ReceiveComplete); + _CallbackWriteMethod = new AsyncCallback(SendComplete); + + //haven't been disposed yet + _IsDisposed = false; + } + + /// + /// Finalizer method. If Dispose() is called correctly, there is nothing + /// for this to do. + /// + ~AsyncSocketClient() + { + if (!_IsDisposed) + { + Dispose(); + } + } + + #region public methods + + /// + /// Sets the disposed flag to true and disconnects the socket. + /// + public void Dispose() + { + try + { + _IsDisposed = true; + Disconnect(); + } + catch + {} + } + + /// + /// Connects the socket to the given IP address and port. + /// This also calls Receive(). + /// + /// The IP address of the server. + /// The port to connect to. + public void Connect(String IPAddress, Int16 port) + { + try + { + //do we already have an open connection? + if (_NetworkStream == null) + { + _ServerIPAddress = IPAddress; + _ServerPort = port; + + //attempt to establish the connection + _TcpClient = new TcpClient(_ServerIPAddress, _ServerPort); + _NetworkStream = _TcpClient.GetStream(); + + //set some socket options + _TcpClient.ReceiveBufferSize = BUFFER_SIZE; + _TcpClient.SendBufferSize = BUFFER_SIZE; + _TcpClient.NoDelay = true; + //if the connection is dropped, drop all associated data + _TcpClient.LingerState = new LingerOption(false, 0); + + //start receiving messages + Receive(); + } + } + catch (SocketException exc) + { + //the connect failed..pass the word on + throw new Exception(exc.Message, exc.InnerException); + } + } + + /// + /// Disconnects from the server. + /// + public void Disconnect() + { + //close down the connection, making sure it exists first + if (_NetworkStream != null) + { + _NetworkStream.Close(); + } + if (_TcpClient != null) + { + _TcpClient.Close(); + } + + //prep for garbage collection-we may want to use this instance again + _NetworkStream = null; + _TcpClient = null; + + } + + /// + /// Asynchronously sends data across the socket. + /// + /// + /// The buffer of data to send. + /// + public void Send(byte[] buffer) + { + //send the data; don't worry about receiving any state information + //back; + try + { + if (_NetworkStream != null && _NetworkStream.CanWrite) + { + _NetworkStream.BeginWrite( + buffer, 0, buffer.Length, _CallbackWriteMethod, null); + } + else + { + throw new Exception("Socket is closed, cannot Send()."); + } + } + catch + { + throw; + } + } + + /// + /// Asynchronously receives data from the socket. + /// + public void Receive() + { + try + { + if (_NetworkStream != null && _NetworkStream.CanRead) + { + //_Buffer = new byte[clientBufferSize]; + _Buffer = new byte[BUFFER_SIZE]; + + _NetworkStream.BeginRead( + _Buffer, 0, _Buffer.Length, _CallbackReadMethod, null); + } + else + { + throw new Exception("Socket is closed, cannot Receive()."); + } + } + catch + { + throw; + } + } + + #endregion public methods + + #region private methods + + /// + /// Callback method called by the NetworkStream's thread when a message + /// is sent. + /// + /// The state object holding information about + /// the connection. + private void SendComplete(IAsyncResult state) + { + try + { + //check to be sure the network stream is valid before writing + if (_NetworkStream.CanWrite) + { + _NetworkStream.EndWrite(state); + } + } + catch + {} + } + + /// + /// Callback method called by the NetworkStream's thread when a message + /// arrives. + /// + /// The state object holding information about + /// the connection. + private void ReceiveComplete(IAsyncResult state) + { + try + { + //check the stream to be sure it is valid + if (_NetworkStream.CanRead) + { + int bytesReceived = _NetworkStream.EndRead(state); + + //if there are bytes to process, do so. Otherwise, the + //connection has been lost, so clean it up + if (bytesReceived > 0) + { + try + { + //send the incoming message to the message handler + _MessageHandler(this); + } + finally + { + //start listening again + Receive(); + } + } + } + } + catch + { + //the connection has been dropped so call the CloseHandler + try + { + _SocketCloseHandler(this); + } + finally + { + Dispose(); + } + } + } + #endregion private methods + } +} diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs new file mode 100644 index 0000000..0fc3ec0 --- /dev/null +++ b/AssemblyInfo.cs @@ -0,0 +1,57 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.4")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*)If no key is specified, the assembly is not signed. +// (*)KeyName refers to a key that has been installed in the Crypto Service +// Provider(CSP)on your machine. KeyFile refers to a file which contains +// a key. +// (*)If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1)If the KeyName can be found in the CSP, that key is used. +// (2)If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*)In order to create a KeyFile, you can use the sn.exe(Strong Name)utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*)Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..08e8652 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,22 @@ +10/11/2008 : License changed to GNU Lesser General Public License, V3. This should make combination with other (older) open source licenses such as the original BSD license possible. + +11/13/2006 : Added the remainder of the code to the project; I will no longer be working on this app. + +08/13/2005 : I've replaced much of the older code with new (hopefully more useful) code. This +new set of namespaces includes both incoming and outgoing functionality for all the PDUs. Note also +that this release is GPL only-I have dropped the QPL portion of the license from here on out. I +also fixed the dates on this changelog-for some reason I had them a year off. + +08/20/2004 : Host of changes. The PDUFactory and several incoming PDUs were changed +for compatibility after some testing. Added some documentation tags. Fixed TLVTable +so that null tags are simply dropped (i.e. trying to set an optional param to null +does nothing). Also added the debug file and xml file to the binary release. Also +changed the zip files so that they store relative path info rather than full path info +(to those of you who downloaded the early release-sorry about that). + +08/15/2004 : Changed the PDUFactory so that it allows multiple responses to come in on +a PDU. Also fixed the TrimResponsePDU() so that it didn't break if the command length +was too large (the null SMSC I was testing with today sent some out like that. Also +included a build script. + +08/14/2004 : Initial release. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..10926e8 --- /dev/null +++ b/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/COPYING.LESSER b/COPYING.LESSER new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/COPYING.LESSER @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/EventObject/AlertEventArgs.cs b/EventObject/AlertEventArgs.cs new file mode 100644 index 0000000..5c24768 --- /dev/null +++ b/EventObject/AlertEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + +namespace RoaminSMPP.EventObjects +{ + + /// + /// Class that defines the bind event. Includes all the available + /// mandatory and optional parameters in a bind_response. + /// + public class AlertEventArgs : SmppEventArgs + { + private SmppAlertNotification _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppAlertNotification AlertPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the AlertEventArgs. + /// + /// The SmppAlertNotification. + internal AlertEventArgs(SmppAlertNotification response): base(response) + { + _response = response; + } + } +} diff --git a/EventObject/BindEventArgs.cs b/EventObject/BindEventArgs.cs new file mode 100644 index 0000000..1035bfc --- /dev/null +++ b/EventObject/BindEventArgs.cs @@ -0,0 +1,52 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + + +using System; +using RoaminSMPP.Packet.Request; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines the bind_sm event. + /// + public class BindEventArgs : SmppEventArgs + { + private SmppBind _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppBind BindPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the BindEventArgs. + /// + /// The SmppBindResp. + internal BindEventArgs(SmppBind response): base(response) + { + _response = response; + } + } +} diff --git a/EventObject/BindRespEventArgs.cs b/EventObject/BindRespEventArgs.cs new file mode 100644 index 0000000..c721360 --- /dev/null +++ b/EventObject/BindRespEventArgs.cs @@ -0,0 +1,52 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + + /// + /// Class that defines the bind_sm_resp event. + /// + public class BindRespEventArgs : SmppEventArgs + { + private SmppBindResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppBindResp BindRespPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the BindEventArgs. + /// + /// The SmppBindResp. + internal BindRespEventArgs(SmppBindResp response): base(response) + { + _response = response; + } + } +} diff --git a/EventObject/CancelEventArgs.cs b/EventObject/CancelEventArgs.cs new file mode 100644 index 0000000..ab76f93 --- /dev/null +++ b/EventObject/CancelEventArgs.cs @@ -0,0 +1,53 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + + +using System; +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + + /// + /// Class that defines a cancel_sm_resp event. + /// + public class CancelEventArgs : SmppEventArgs + { + private SmppCancelSmResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppCancelSmResp CancelPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the CancelEventArgs. + /// + /// The SmppCancelSmResp. + internal CancelEventArgs(SmppCancelSmResp response): base(response) + { + _response = response; + } + } +} diff --git a/EventObject/CancelSmEventArgs.cs b/EventObject/CancelSmEventArgs.cs new file mode 100644 index 0000000..ee7de73 --- /dev/null +++ b/EventObject/CancelSmEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a cancel_sm event. + /// + public class CancelSmEventArgs : SmppEventArgs + { + private SmppCancelSm _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppCancelSm CancelSmPdu + { + get + { + return _response; + } + } + + /// + /// Creates a CancelSmEventArgs. + /// + /// The PDU that was received. + internal CancelSmEventArgs(SmppCancelSm packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/CancelSmRespEventArgs.cs b/EventObject/CancelSmRespEventArgs.cs new file mode 100644 index 0000000..0b0fb98 --- /dev/null +++ b/EventObject/CancelSmRespEventArgs.cs @@ -0,0 +1,55 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; +using RoaminSMPP.Packet.Response; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a cancel_sm_resp event. + /// + public class CancelSmRespEventArgs : SmppEventArgs + { + private SmppCancelSmResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppCancelSmResp CancelSmRespPdu + { + get + { + return _response; + } + } + + /// + /// Creates a CancelSmRespEventArgs. + /// + /// The PDU that was received. + internal CancelSmRespEventArgs(SmppCancelSmResp packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/CommonErrorEventArgs.cs b/EventObject/CommonErrorEventArgs.cs new file mode 100644 index 0000000..c72be81 --- /dev/null +++ b/EventObject/CommonErrorEventArgs.cs @@ -0,0 +1,51 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + + +using System; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Event args class. Holds the internal exception generated. + /// + public class CommonErrorEventArgs : System.EventArgs + { + private Exception _exc; + + /// + /// The thrown exception. + /// + public Exception ThrownException + { + get + { + return _exc; + } + } + + /// + /// Creates an CommErrorEventArgs. + /// + /// The exception that was generated. + public CommonErrorEventArgs(Exception exc) + { + _exc = exc; + } + } +} diff --git a/EventObject/DataSmEventArgs.cs b/EventObject/DataSmEventArgs.cs new file mode 100644 index 0000000..54ea598 --- /dev/null +++ b/EventObject/DataSmEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a data_sm event. + /// + public class DataSmEventArgs : SmppEventArgs + { + private SmppDataSm _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppDataSm DataSmPdu + { + get + { + return _response; + } + } + + /// + /// Creates a DataSmEventArgs. + /// + /// The PDU that was received. + internal DataSmEventArgs(SmppDataSm packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/DataSmRespEventArgs.cs b/EventObject/DataSmRespEventArgs.cs new file mode 100644 index 0000000..cbaa9d2 --- /dev/null +++ b/EventObject/DataSmRespEventArgs.cs @@ -0,0 +1,55 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a data_sm_resp event. + /// + public class DataSmRespEventArgs : SmppEventArgs + { + private SmppDataSmResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppDataSmResp DataSmRespPdu + { + get + { + return _response; + } + } + + /// + /// Creates a DataSmRespEventArgs. + /// + /// The PDU that was received. + internal DataSmRespEventArgs(SmppDataSmResp packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/DeliverSmEventArgs.cs b/EventObject/DeliverSmEventArgs.cs new file mode 100644 index 0000000..e5ba47d --- /dev/null +++ b/EventObject/DeliverSmEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a deliver_sm event. + /// + public class DeliverSmEventArgs : SmppEventArgs + { + private SmppDeliverSm _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppDeliverSm DeliverSmPdu + { + get + { + return _response; + } + } + + /// + /// Creates a DeliverSmEventArgs. + /// + /// The PDU that was received. + internal DeliverSmEventArgs(SmppDeliverSm packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/DeliverSmRespEventArgs.cs b/EventObject/DeliverSmRespEventArgs.cs new file mode 100644 index 0000000..f06a4ac --- /dev/null +++ b/EventObject/DeliverSmRespEventArgs.cs @@ -0,0 +1,55 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a deliver_sm_resp event. + /// + public class DeliverSmRespEventArgs : SmppEventArgs + { + private SmppDeliverSmResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppDeliverSmResp DeliverSmRespPdu + { + get + { + return _response; + } + } + + /// + /// Creates a DeliverSmRespEventArgs. + /// + /// The PDU that was received. + internal DeliverSmRespEventArgs(SmppDeliverSmResp packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/EnquireLinkEventArgs.cs b/EventObject/EnquireLinkEventArgs.cs new file mode 100644 index 0000000..dc26012 --- /dev/null +++ b/EventObject/EnquireLinkEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines the enquire_link event. + /// + public class EnquireLinkEventArgs : SmppEventArgs + { + private SmppEnquireLink _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppEnquireLink EnquireLinkPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the EnquireLinkEventArgs. + /// + /// The PDU from the ESME. + internal EnquireLinkEventArgs(SmppEnquireLink response): base(response) + { + _response = response; + } + } +} diff --git a/EventObject/EnquireLinkRespEventArgs.cs b/EventObject/EnquireLinkRespEventArgs.cs new file mode 100644 index 0000000..f3932e0 --- /dev/null +++ b/EventObject/EnquireLinkRespEventArgs.cs @@ -0,0 +1,52 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + + +using System; +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines the enquire_link_resp event. + /// + public class EnquireLinkRespEventArgs : SmppEventArgs + { + private SmppEnquireLinkResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppEnquireLinkResp EnquireLinkRespPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the EnquireLinkEventArgs. + /// + /// The SmppEnquireLinkResp. + internal EnquireLinkRespEventArgs(SmppEnquireLinkResp response): base(response) + { + _response = response; + } + } +} diff --git a/EventObject/GenericNackEventArgs.cs b/EventObject/GenericNackEventArgs.cs new file mode 100644 index 0000000..10bd05a --- /dev/null +++ b/EventObject/GenericNackEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a generic_nack event. + /// + public class GenericNackEventArgs : SmppEventArgs + { + private SmppGenericNack _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppGenericNack GenericNackPdu + { + get + { + return _response; + } + } + + /// + /// Creates a GenericNackEventArgs. + /// + /// The PDU that was received. + internal GenericNackEventArgs(SmppGenericNack packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/QuerySmEventArgs.cs b/EventObject/QuerySmEventArgs.cs new file mode 100644 index 0000000..5d82202 --- /dev/null +++ b/EventObject/QuerySmEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a query_sm event. + /// + public class QuerySmEventArgs : SmppEventArgs + { + private SmppQuerySm _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppQuerySm QuerySmPdu + { + get + { + return _response; + } + } + + /// + /// Creates a QuerySmEventArgs. + /// + /// The PDU that was received. + internal QuerySmEventArgs(SmppQuerySm packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/QuerySmRespEventArgs.cs b/EventObject/QuerySmRespEventArgs.cs new file mode 100644 index 0000000..fe211a5 --- /dev/null +++ b/EventObject/QuerySmRespEventArgs.cs @@ -0,0 +1,55 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a query_sm_resp event. + /// + public class QuerySmRespEventArgs : SmppEventArgs + { + private SmppQuerySmResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppQuerySmResp QuerySmRespPdu + { + get + { + return _response; + } + } + + /// + /// Creates a QuerySmRespEventArgs. + /// + /// The PDU that was received. + internal QuerySmRespEventArgs(SmppQuerySmResp packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/ReplaceSmEventArgs.cs b/EventObject/ReplaceSmEventArgs.cs new file mode 100644 index 0000000..70214ef --- /dev/null +++ b/EventObject/ReplaceSmEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a replace_sm event. + /// + public class ReplaceSmEventArgs : SmppEventArgs + { + private SmppReplaceSm _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppReplaceSm ReplaceSmPdu + { + get + { + return _response; + } + } + + /// + /// Creates a ReplaceSmEventArgs. + /// + /// The PDU that was received. + internal ReplaceSmEventArgs(SmppReplaceSm packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/ReplaceSmRespEventArgs.cs b/EventObject/ReplaceSmRespEventArgs.cs new file mode 100644 index 0000000..8d6ae42 --- /dev/null +++ b/EventObject/ReplaceSmRespEventArgs.cs @@ -0,0 +1,55 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a replace_sm_resp event. + /// + public class ReplaceSmRespEventArgs : SmppEventArgs + { + private SmppReplaceSmResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppReplaceSmResp ReplaceSmRespPdu + { + get + { + return _response; + } + } + + /// + /// Creates a ReplaceSmRespEventArgs. + /// + /// The PDU that was received. + internal ReplaceSmRespEventArgs(SmppReplaceSmResp packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/SmppEventArgs.cs b/EventObject/SmppEventArgs.cs new file mode 100644 index 0000000..2faffef --- /dev/null +++ b/EventObject/SmppEventArgs.cs @@ -0,0 +1,53 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + + +using System; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.EventObjects +{ + + /// + /// Base class to provide some functionality for all events. + /// + public abstract class SmppEventArgs : System.EventArgs + { + private Pdu _response; + + /// + /// Allows access to the underlying Pdu. + /// + public Pdu ResponsePdu + { + get + { + return _response; + } + } + + /// + /// Sets up the SmppEventArgs. + /// + /// The SMPPResponse. + public SmppEventArgs(Pdu response) + { + _response = response; + } + } +} diff --git a/EventObject/SubmitMultiEventArgs.cs b/EventObject/SubmitMultiEventArgs.cs new file mode 100644 index 0000000..c03698d --- /dev/null +++ b/EventObject/SubmitMultiEventArgs.cs @@ -0,0 +1,54 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a submit_multi event. + /// + public class SubmitMultiEventArgs : SmppEventArgs + { + private SmppSubmitMulti _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppSubmitMulti SubmitMultiPdu + { + get + { + return _response; + } + } + + /// + /// Creates a SubmitMultiEventArgs. + /// + /// The PDU that was received. + internal SubmitMultiEventArgs(SmppSubmitMulti packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/SubmitMultiRespEventArgs.cs b/EventObject/SubmitMultiRespEventArgs.cs new file mode 100644 index 0000000..846f397 --- /dev/null +++ b/EventObject/SubmitMultiRespEventArgs.cs @@ -0,0 +1,55 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a submit_multi_resp event. + /// + public class SubmitMultiRespEventArgs : SmppEventArgs + { + private SmppSubmitMultiResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppSubmitMultiResp SubmitMultiRespPdu + { + get + { + return _response; + } + } + + /// + /// Creates a SubmitMultiRespEventArgs. + /// + /// The PDU that was received. + internal SubmitMultiRespEventArgs(SmppSubmitMultiResp packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/SubmitSmEventArgs.cs b/EventObject/SubmitSmEventArgs.cs new file mode 100644 index 0000000..72a856c --- /dev/null +++ b/EventObject/SubmitSmEventArgs.cs @@ -0,0 +1,53 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; + +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; + +namespace RoaminSMPP.EventObjects +{ + /// + /// Class that defines a submit_sm event. + /// + public class SubmitSmEventArgs : SmppEventArgs + { + private SmppSubmitSm _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppSubmitSm SubmitSmPdu + { + get + { + return _response; + } + } + + /// + /// Creates a SubmitSmEventArgs. + /// + /// The PDU that was received. + internal SubmitSmEventArgs(SmppSubmitSm packet): base(packet) + { + _response = packet; + } + } +} diff --git a/EventObject/SubmitSmRespEventArgs.cs b/EventObject/SubmitSmRespEventArgs.cs new file mode 100644 index 0000000..f1c65fb --- /dev/null +++ b/EventObject/SubmitSmRespEventArgs.cs @@ -0,0 +1,53 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + + +using System; +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + + /// + /// Class that defines the submit_sm_resp event. + /// + public class SubmitSmRespEventArgs : SmppEventArgs + { + private SmppSubmitSmResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppSubmitSmResp SubmitSmPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the SubmitSmRespEventArgs. + /// + /// The SmppSubmitSmResp. + internal SubmitSmRespEventArgs(SmppSubmitSmResp response): base(response) + { + _response = response; + } + } +} diff --git a/EventObject/UnbindEventArgs.cs b/EventObject/UnbindEventArgs.cs new file mode 100644 index 0000000..d50ac73 --- /dev/null +++ b/EventObject/UnbindEventArgs.cs @@ -0,0 +1,55 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + + +using System; +using RoaminSMPP.Packet.Response; +using RoaminSMPP.Packet.Request; + +namespace RoaminSMPP.EventObjects +{ + + /// + /// Class that defines the unbind event. + /// + public class UnbindEventArgs : SmppEventArgs + { + SmppUnbind _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppUnbind UnbindPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the UnbindEventArgs. + /// + /// The SmppUnbind. + internal UnbindEventArgs(SmppUnbind response): base(response) + { + _response = response; + } + } +} + diff --git a/EventObject/UnbindRespEventArgs.cs b/EventObject/UnbindRespEventArgs.cs new file mode 100644 index 0000000..b0b4672 --- /dev/null +++ b/EventObject/UnbindRespEventArgs.cs @@ -0,0 +1,53 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.EventObjects +{ + + /// + /// Class that defines the unbind_resp event. + /// + public class UnbindRespEventArgs : SmppEventArgs + { + SmppUnbindResp _response; + + /// + /// Allows access to the underlying Pdu. + /// + public SmppUnbindResp UnbindRespPdu + { + get + { + return _response; + } + } + + /// + /// Sets up the UnbindEventArgs. + /// + /// The SmppUnbindResp. + internal UnbindRespEventArgs(SmppUnbindResp response): base(response) + { + _response = response; + } + } +} + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..b860267 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Packet/Pdu.cs b/Packet/Pdu.cs new file mode 100644 index 0000000..8f1934e --- /dev/null +++ b/Packet/Pdu.cs @@ -0,0 +1,1399 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using System.Diagnostics; +using RoaminSMPP.Utility; +using System.Text; + +namespace RoaminSMPP.Packet +{ + /// + /// Represents a protocol data unit. This class holds type enumerations and common + /// functionality for request and response Pdus. + /// + public abstract class Pdu : IDisposable + { + #region constants + + /// + /// Standard length of Pdu header. + /// + protected const int HEADER_LENGTH = 16; + /// + /// Delivery time length + /// + protected const int DATE_TIME_LENGTH = 16; + + #endregion constants + + #region private fields + + private static uint _StaticSequenceNumber = 0; + private uint _CommandStatus; + private CommandIdType _CommandID; + private TlvTable _tlvTable = new TlvTable(); + private uint _CustomSequenceNumber = 0; + private uint _SequenceNumber = 0; + + private byte[] _PacketBytes = new byte[0]; + private uint _CommandLength; + + #endregion private fields + + #region properties + + /// + /// Gets or sets the byte response from the SMSC. This will return a clone of the + /// byte array upon a "get" request. + /// + public byte[] PacketBytes + { + get + { + return(byte[])_PacketBytes.Clone(); + } + + set + { + _PacketBytes = value; + } + } + + /// + /// Defines the overall length of the Pdu in octets(i.e. bytes). + /// + public uint CommandLength + { + get + { + return _CommandLength; + } + } + + /// + /// The sequence number of the message. Only call this after you call + /// GetMSBHexEncoding; it will be incorrect otherwise. If you are setting the + /// sequence number(such as for a deliver_sm_resp), set this before you call + /// GetMSBHexEncoding. Note that setting the custom sequence number will + /// disable the automatic updating of the sequence number for this instance. + /// You can restore the automatic updating by setting this property to 0. + /// + public uint SequenceNumber + { + get + { + return _SequenceNumber; + } + set + { + _CustomSequenceNumber = value; + } + } + + /// + /// Indicates outcome of request. + /// + public uint CommandStatus + { + get + { + return _CommandStatus; + } + set + { + _CommandStatus = value; + } + } + + /// + /// The command ID of this Pdu. + /// + protected CommandIdType CommandID + { + get + { + return _CommandID; + } + set + { + _CommandID = value; + } + } + + #endregion properties + + #region constructors + + /// + /// Constructor for sent Pdus. + /// + protected Pdu() + { + InitPdu(); + } + + /// + /// Constructor for received Pdus. + /// + /// The incoming bytes to translate to a Pdu. + protected Pdu(byte[] incomingBytes) + { + #if DEBUG + Console.WriteLine("In Pdu byte[] constructor"); + #endif + _PacketBytes = incomingBytes; + _CommandLength = DecodeCommandLength(_PacketBytes); + _CommandID = DecodeCommandId(_PacketBytes); + _CommandStatus = UnsignedNumConverter.SwapByteOrdering(BitConverter.ToUInt32(_PacketBytes, 8)); + _SequenceNumber = UnsignedNumConverter.SwapByteOrdering(BitConverter.ToUInt32(_PacketBytes, 12)); + _PacketBytes = TrimResponsePdu(_PacketBytes); + + //set the other Pdu-specific fields + DecodeSmscResponse(); + } + + #endregion constructors + + #region overridable methods + + /// + /// Initializes this Pdu. Override to add more functionality, but don't forget to + /// call this one. + /// + protected virtual void InitPdu() + { + CommandStatus = 0; + CommandID = Pdu.CommandIdType.generic_nack; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public virtual void ToMsbHexEncoding() + { + throw new NotImplementedException("GetMSBHexEncoding is not implemented in Pdu."); + } + + /// + /// Decodes the bind response from the SMSC. This version throws a NotImplementedException. + /// + protected virtual void DecodeSmscResponse() + { + throw new NotImplementedException("DecodeSmscResponse is not implemented in Pdu."); + } + + #endregion overridable methods + + /// + /// Calculates the length of the given ArrayList representation of the Pdu and + /// inserts this length into the appropriate spot in the Pdu. This will call + /// TrimToSize()on the ArrayList-the caller need not do it. + /// + /// The protocol data unit to calculate the + /// length for. + /// The Pdu with the length inserted, trimmed to size. + protected static ArrayList InsertLengthIntoPdu(ArrayList pdu) + { + pdu.TrimToSize(); + uint commandLength =(uint)(4 + pdu.Count); + uint reqLenH2N = UnsignedNumConverter.SwapByteOrdering(commandLength); + byte[] reqLenArray = BitConverter.GetBytes(reqLenH2N); + //insert into the Pdu + pdu.InsertRange(0, reqLenArray); + pdu.TrimToSize(); + + return pdu; + } + + /// + /// Takes the given Pdu, calculates its length(trimming it beforehand), inserting + /// its length, and copying it to a byte array. + /// + /// The Pdu to encode. + /// The byte array representation of the Pdu. + protected byte[] EncodePduForTransmission(ArrayList pdu) + { + AddTlvBytes(ref pdu); + pdu = InsertLengthIntoPdu(pdu); + byte[] result = new byte[pdu.Count]; + pdu.CopyTo(result); + + return result; + } + + /// + /// Retrieves the given bytes from the TLV table and converts them into a + /// host order UInt16. + /// + /// The TLV tag to use for retrieval + /// The host order result. + protected UInt16 GetHostOrderUInt16FromTlv(ushort tag) + { + return UnsignedNumConverter.SwapByteOrdering( + BitConverter.ToUInt16(GetOptionalParamBytes(tag), 0)); + } + + /// + /// Retrieves the given bytes from the TLV table and converts them into a + /// host order UInt32. + /// + /// The TLV tag to use for retrieval + /// The host order result. + protected UInt32 GetHostOrderUInt32FromTlv(ushort tag) + { + return UnsignedNumConverter.SwapByteOrdering( + BitConverter.ToUInt32(GetOptionalParamBytes(tag), 0)); + } + + /// + /// Takes the given value and puts it into the TLV table, accounting for + /// network byte ordering. + /// + /// The TLV tag to use for retrieval + /// The value to put into the table + protected void SetHostOrderValueIntoTlv(UInt16 tag, UInt16 val) + { + SetOptionalParamBytes( + tag, + BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering(val))); + } + + /// + /// Takes the given value and puts it into the TLV table, accounting for + /// network byte ordering. + /// + /// The TLV tag to use for retrieval + /// The value to put into the table + protected void SetHostOrderValueIntoTlv(UInt16 tag, UInt32 val) + { + SetOptionalParamBytes( + tag, + BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering(val))); + } + + /// + /// What remains after the header is stripped off the Pdu. Subclasses + /// don't need the header as its information is stored here. In + /// addition, this allows them to manipulate the response data + /// all they want without destroying the original. The copying is + /// done every time this property is accessed, so use caution in a + /// high-performance setting. + /// + protected byte[] BytesAfterHeader + { + get + { + long length = _PacketBytes.Length - HEADER_LENGTH; + byte[] remainder = new byte[length]; + Array.Copy(_PacketBytes, HEADER_LENGTH, remainder, 0, length); + return remainder; + } + } + + /// + /// Creates an ArrayList consisting of the Pdu header. Command ID and status + /// need to be set before calling this. + /// + /// The Pdu as a trimmed ArrayList. + protected ArrayList GetPduHeader() + { + ArrayList pdu = new ArrayList(); + pdu.AddRange(BitConverter.GetBytes(UnsignedNumConverter.SwapByteOrdering((uint)_CommandID))); + pdu.AddRange(BitConverter.GetBytes(UnsignedNumConverter.SwapByteOrdering(_CommandStatus))); + + //increase the sequence number + GenerateSequenceNumber(); + pdu.AddRange(BitConverter.GetBytes(UnsignedNumConverter.SwapByteOrdering(_SequenceNumber))); + pdu.TrimToSize(); + return pdu; + } + + /// + /// Generates a monotonically increasing sequence number for each Pdu. When it + /// hits the the 32 bit unsigned int maximum, it starts over. + /// + private void GenerateSequenceNumber() + { + if(_CustomSequenceNumber == 0) + { + _StaticSequenceNumber++; + if(_StaticSequenceNumber >= UInt32.MaxValue) + { + _StaticSequenceNumber = 1; + } + _SequenceNumber = _StaticSequenceNumber; + } + else + { + _SequenceNumber = _CustomSequenceNumber; + } + } + + #region TLV table methods + + /// + /// Gets the optional parameter string associated with + /// the given tag. + /// + /// The tag in TLV. + /// The optional parameter string, the empty + /// string if not found. + public string GetOptionalParamString(UInt16 tag) + { + return _tlvTable.GetOptionalParamString(UnsignedNumConverter.SwapByteOrdering(tag)); + } + + /// + /// Gets the optional parameter bytes associated with + /// the given tag. + /// + /// The tag in TLV. + /// The optional parameter bytes, null if + /// not found. + public byte[] GetOptionalParamBytes(UInt16 tag) + { + return _tlvTable.GetOptionalParamBytes(UnsignedNumConverter.SwapByteOrdering(tag)); + } + + /// + /// Sets the given TLV(as a string)into the table. This ignores + /// null values. This will reverse the byte order in the tag for you + ///(necessary for encoding). + /// + /// The tag for this TLV. + /// The value of this TLV. + public void SetOptionalParamString(UInt16 tag, string val) + { + _tlvTable.SetOptionalParamString(UnsignedNumConverter.SwapByteOrdering(tag), val); + } + + /// + /// Sets the given TLV(as a byte array)into the table. This will not take + /// care of big-endian/little-endian issues, although it will reverse the byte order + /// in the tag for you(necessary for encoding). This ignores null values. + /// + /// The tag for this TLV. + /// The value of this TLV. + public void SetOptionalParamBytes(UInt16 tag, byte[] val) + { + _tlvTable.SetOptionalParamBytes(UnsignedNumConverter.SwapByteOrdering(tag), val); + } + + /// + /// Allows the updating of TLV values. This will not take care of + /// big-endian/little-endian issues, although it will reverse the byte order + /// in the tag for you(necessary for encoding). + /// + /// The tag for this TLV. + /// The value of this TLV. + public void UpdateOptionalParamBytes(UInt16 tag, byte[] val) + { + _tlvTable.UpdateOptionalParamBytes(UnsignedNumConverter.SwapByteOrdering(tag), val); + } + + /// + /// Allows the updating of TLV values. This will reverse the byte order in the tag for you + ///(necessary for encoding). + /// + /// The tag for this TLV. + /// The value of this TLV. + public void UpdateOptionalParamString(UInt16 tag, string val) + { + _tlvTable.UpdateOptionalParamString(UnsignedNumConverter.SwapByteOrdering(tag), val); + } + + /// + /// Takes the given bytes and attempts to insert them into the TLV table. + /// + /// The bytes to convert for the TLVs. + protected void TranslateTlvDataIntoTable(byte[] tlvBytes) + { + _tlvTable.TranslateTlvDataIntoTable(tlvBytes); + } + + /// + /// Takes the given bytes and attempts to insert them into the TLV table. + /// + /// The bytes to convert for the TLVs. + /// The index of the byte array to start at. This is here + /// because in some instances you may not want to start at the + /// beginning. + protected void TranslateTlvDataIntoTable(byte[] tlvBytes, Int32 index) + { + #if DEBUG + Console.WriteLine("Calling TranslateTlvDataIntoTable(byte[], Int32)"); + #endif + _tlvTable.TranslateTlvDataIntoTable(tlvBytes, index); + } + + /// + /// Adds the TLV bytes to the given Pdu. + /// + /// The Pdu to add to. + protected void AddTlvBytes(ref ArrayList pdu) + { + ArrayList tlvs = _tlvTable.GenerateByteEncodedTlv(); + foreach(byte[] tlv in tlvs) + { + #if DEBUG + StringBuilder sb = new StringBuilder("\nAdding TLV bytes\n"); + for(int i = 0; i < tlv.Length; i++) + { + sb.Append(tlv[i].ToString("X").PadLeft(2, '0')); + sb.Append(" "); + } + sb.Append("\n"); + Console.WriteLine(sb); + + #endif + + pdu.AddRange(tlv); + } + } + + #endregion TLV table methods + + #region enumerations + + /// + /// Enumerates the bearer types for source and destination. + /// + public enum BearerType : byte + { + /// + /// Unknown + /// + Unknown = 0x00, + /// + /// SMS + /// + SMS = 0x01, + /// + /// CircuitSwitchedData + /// + CircuitSwitchedData = 0x02, + /// + /// PacketData + /// + PacketData = 0x03, + /// + /// USSD + /// + USSD = 0x04, + /// + /// CDPD + /// + CDPD = 0x05, + /// + /// DataTAC + /// + DataTAC = 0x06, + /// + /// FLEX_ReFLEX + /// + FLEX_ReFLEX = 0x07, + /// + /// CellBroadcast + /// + CellBroadcast = 0x08 + } + + /// + /// Enumerates the network types for the source and destination. + /// + public enum NetworkType : byte + { + /// + /// Unknown + /// + Unknown = 0x00, + /// + /// GSM + /// + GSM = 0x01, + /// + /// ANSI_136_TDMA + /// + ANSI_136_TDMA = 0x02, + /// + /// IS_95_CDMA + /// + IS_95_CDMA = 0x03, + /// + /// PDC + /// + PDC = 0x04, + /// + /// PHS + /// + PHS = 0x05, + /// + /// iDEN + /// + iDEN = 0x06, + /// + /// AMPS + /// + AMPS = 0x07, + /// + /// PagingNetwork + /// + PagingNetwork = 0x08 + } + + /// + /// Enumerates the different states a message can be in. + /// + public enum MessageStateType : byte + { + /// + /// Enroute + /// + Enroute = 1, + /// + /// Delivered + /// + Delivered = 2, + /// + /// Expired + /// + Expired = 3, + /// + /// Deleted + /// + Deleted = 4, + /// + /// Undeliverable + /// + Undeliverable = 5, + /// + /// Accepted + /// + Accepted = 6, + /// + /// Unknown + /// + Unknown = 7, + /// + /// Rejected + /// + Rejected = 8 + } + + /// + /// SMPP version type. + /// + public enum SmppVersionType : byte + { + /// + /// Version 3.3 of the SMPP spec. + /// + Version3_3 = 0x33, + /// + /// Version 3.4 of the SMPP spec. + /// + Version3_4 = 0x34 + } + + /// + /// Enumerates the source address subunit types. + /// + public enum AddressSubunitType : byte + { + /// + /// Unknown + /// + Unknown = 0x00, + /// + /// MSDisplay + /// + MSDisplay = 0x01, + /// + /// MobileEquipment + /// + MobileEquipment = 0x02, + /// + /// SmartCard1 + /// + SmartCard1 = 0x03, + /// + /// ExternalUnit1 + /// + ExternalUnit1 = 0x04 + } + + /// + /// Enumerates the display time type. + /// + public enum DisplayTimeType : byte + { + /// + /// Temporary + /// + Temporary = 0x00, + /// + /// Default + /// + Default = 0x01, + /// + /// Invoke + /// + Invoke = 0x02 + } + + /// + /// Enumerates the type of the ITS Reply Type + /// + public enum ItsReplyTypeType : byte + { + /// + /// Digit + /// + Digit = 0, + /// + /// Number + /// + Number = 1, + /// + /// TelephoneNum + /// + TelephoneNum = 2, + /// + /// Password + /// + Password = 3, + /// + /// CharacterLine + /// + CharacterLine = 4, + /// + /// Menu + /// + Menu = 5, + /// + /// Date + /// + Date = 6, + /// + /// Time + /// + Time = 7, + /// + /// Continue + /// + Continue = 8 + } + + /// + /// Enumerates the MS Display type. + /// + public enum MsValidityType : byte + { + /// + /// StoreIndefinitely + /// + StoreIndefinitely = 0x00, + /// + /// PowerDown + /// + PowerDown = 0x01, + /// + /// SIDBased + /// + SIDBased = 0x02, + /// + /// DisplayOnly + /// + DisplayOnly = 0x03 + } + + /// + /// Enumerates all of the "standard" optional codes. This is more for + /// convenience when writing/updating this library than for end programmers, + /// as the the TLV table methods take a ushort/UInt16 rather than an + /// OptionalParamCodes enumeration. + /// + public enum OptionalParamCodes : ushort + { + /// + /// Destination address subunit + /// + dest_addr_subunit = 0x0005, + /// + /// Destination address network type + /// + dest_network_type = 0x0006, + /// + /// Destination address bearer type + /// + dest_bearer_type = 0x0007, + /// + /// Destination address telematics ID + /// + dest_telematics_id = 0x0008, + /// + /// Source address subunit + /// + source_addr_subunit = 0x000D, + /// + /// Source address network type + /// + source_network_type = 0x000E, + /// + /// Source address bearer type + /// + source_bearer_type = 0x000F, + /// + /// Source address telematics ID + /// + source_telematics_id = 0x0010, + /// + /// Quality of service time to live + /// + qos_time_to_live = 0x0017, + /// + /// Payload type + /// + payload_type = 0x0019, + /// + /// Additional status info + /// + additional_status_info_text = 0x001D, + /// + /// Receipted message ID + /// + receipted_message_id = 0x001E, + /// + /// Message wait facilities + /// + ms_msg_wait_facilities = 0x0030, + /// + /// Privacy indicator + /// + privacy_indicator = 0x0201, + /// + /// Source subaddress + /// + source_subaddress = 0x0202, + /// + /// Destination subaddress + /// + dest_subaddress = 0x0203, + /// + /// User message reference + /// + user_message_reference = 0x0204, + /// + /// User response code + /// + user_response_code = 0x0205, + /// + /// Source port + /// + source_port = 0x020A, + /// + /// Destination port + /// + destination_port = 0x020B, + /// + /// Message reference number + /// + sar_msg_ref_num = 0x020C, + /// + /// Language indicator + /// + language_indicator = 0x020D, + /// + /// Total segments + /// + sar_total_segments = 0x020E, + /// + /// Segment sequence number + /// + sar_segment_seqnum = 0x020F, + /// + /// Interface version + /// + SC_interface_version = 0x0210, + /// + /// Callback number indicator + /// + callback_num_pres_ind = 0x0302, + /// + /// Callback number tag + /// + callback_num_atag = 0x0303, + /// + /// Total number of messages + /// + number_of_messages = 0x0304, + /// + /// Callback number + /// + callback_num = 0x0381, + /// + /// DPF result + /// + dpf_result = 0x0420, + /// + /// Set DPF + /// + set_dpf = 0x0421, + /// + /// Availability status + /// + ms_availability_status = 0x0422, + /// + /// Network error code + /// + network_error_code = 0x0423, + /// + /// Message payload + /// + message_payload = 0x0424, + /// + /// Reason for delivery failure + /// + delivery_failure_reason = 0x0425, + /// + /// More messages to send flag + /// + more_messages_to_send = 0x0426, + /// + /// Message state + /// + message_state = 0x0427, + /// + /// USSD service opcode + /// + ussd_service_op = 0x0501, + /// + /// Display time + /// + display_time = 0x1201, + /// + /// SMS signal + /// + sms_signal = 0x1203, + /// + /// Message validity + /// + ms_validity = 0x1204, + /// + /// Alert on message delivery + /// + alert_on_message_delivery = 0x130C, + /// + /// ITS reply type + /// + its_reply_type = 0x1380, + /// + /// ITS session info + /// + its_session_info = 0x1383 + } + + /// + /// Enumerates the type of number types that can be used for the SMSC + /// message + /// sending. + /// + public enum TonType : byte + { + /// + /// Unknown + /// + Unknown = 0x00, + /// + /// International + /// + International = 0x01, + /// + /// National + /// + National = 0x02, + /// + /// Network specific + /// + NetworkSpecific = 0x03, + /// + /// Subscriber number + /// + SubscriberNumber = 0x04, + /// + /// Alphanumeric + /// + Alphanumeric = 0x05, + /// + /// Abbreviated + /// + Abbreviated = 0x06 + } + + /// + /// Enumerates the number plan indicator types that can be used for the + /// SMSC + /// message sending. + /// + public enum NpiType : byte + { + /// + /// Unknown + /// + Unknown = 0x00, + /// + /// ISDN + /// + ISDN = 0x01, + /// + /// Data + /// + Data = 0x03, + /// + /// Telex + /// + Telex = 0x04, + /// + /// Land mobile + /// + LandMobile = 0x06, + /// + /// National + /// + National = 0x08, + /// + /// Private + /// + Private = 0x09, + /// + /// ERMES + /// + ERMES = 0x0A, + /// + /// Internet + /// + Internet = 0x0E + } + + /// + /// Enumerates the priority level of the message. + /// + public enum PriorityType : byte + { + /// + /// Lowest + /// + Lowest = 0x00, + /// + /// Level1 + /// + Level1 = 0x01, + /// + /// Level2 + /// + Level2 = 0x02, + /// + /// Highest + /// + Highest = 0x03 + } + + /// + /// Enumerates the types of registered delivery. Not all possible options + /// are present, just the common ones. + /// + public enum RegisteredDeliveryType : byte + { + /// + /// No registered delivery + /// + None = 0x00, + /// + /// Notification on success or failure + /// + OnSuccessOrFailure = 0x01, + /// + /// Notification on failure only + /// + OnFailure = 0x02 + } + + /// + /// Enumerates the data coding types. + /// + public enum DataCodingType : byte + { + /// + /// SMSCDefault + /// + SMSCDefault = 0x00, + /// + /// IA5_ASCII + /// + IA5_ASCII = 0x01, + /// + /// OctetUnspecifiedB + /// + OctetUnspecifiedB = 0x02, + /// + /// Latin1 + /// + Latin1 = 0x03, + /// + /// OctetUnspecifiedA + /// + OctetUnspecifiedA = 0x04, + /// + /// JIS + /// + JIS = 0x05, + /// + /// Cyrillic + /// + Cyrillic = 0x06, + /// + /// Latin_Hebrew + /// + Latin_Hebrew = 0x07, + /// + /// Pictogram + /// + Pictogram = 0x09, + /// + /// MusicCodes + /// + MusicCodes = 0x0A, + /// + /// ExtendedKanjiJIS + /// + ExtendedKanjiJIS = 0x0D, + /// + /// KS_C + /// + KS_C = 0x0E + } + + /// + /// Enumerates the privacy indicator types. + /// + public enum PrivacyType : byte + { + /// + /// Nonrestricted + /// + Nonrestricted = 0x00, + /// + /// Restricted + /// + Restricted = 0x01, + /// + /// Confidential + /// + Confidential = 0x03, + /// + /// Secret + /// + Secret = 0x03 + } + + /// + /// Enumerates the types of payload type. + /// + public enum PayloadTypeType : byte + { + /// + /// WDPMessage + /// + WDPMessage = 0x00, + /// + /// WCMPMessage + /// + WCMPMessage = 0x01 + } + + /// + /// Enumerates the language types. + /// + public enum LanguageType : byte + { + /// + /// Unspecified + /// + Unspecified = 0x00, + /// + /// English + /// + English = 0x01, + /// + /// French + /// + French = 0x02, + /// + /// Spanish + /// + Spanish = 0x03, + /// + /// German + /// + German = 0x04, + /// + /// Portuguese + /// + Portuguese = 0x05 + } + + /// + /// Enumerates the DPF result types. + /// + public enum DpfResultType : byte + { + /// + /// DPFNotSet + /// + DPFNotSet = 0, + /// + /// DPFSet + /// + DPFSet = 1 + } + + /// + /// Enumeration of all the Pdu command types. + /// + public enum CommandIdType : uint + { + /// + /// generic_nack + /// + generic_nack = 0x80000000, + /// + /// bind_receiver + /// + bind_receiver = 0x00000001, + /// + /// bind_receiver_resp + /// + bind_receiver_resp = 0x80000001, + /// + /// bind_transmitter + /// + bind_transmitter = 0x00000002, + /// + /// bind_transmitter_resp + /// + bind_transmitter_resp = 0x80000002, + /// + /// query_sm + /// + query_sm = 0x00000003, + /// + /// query_sm_resp + /// + query_sm_resp = 0x80000003, + /// + /// submit_sm + /// + submit_sm = 0x00000004, + /// + /// submit_sm_resp + /// + submit_sm_resp = 0x80000004, + /// + /// deliver_sm + /// + deliver_sm = 0x00000005, + /// + /// deliver_sm_resp + /// + deliver_sm_resp = 0x80000005, + /// + /// unbind + /// + unbind = 0x00000006, + /// + /// unbind_resp + /// + unbind_resp = 0x80000006, + /// + /// replace_sm + /// + replace_sm = 0x00000007, + /// + /// replace_sm_resp + /// + replace_sm_resp = 0x80000007, + /// + /// cancel_sm + /// + cancel_sm = 0x00000008, + /// + /// cancel_sm_resp + /// + cancel_sm_resp = 0x80000008, + /// + /// bind_transceiver + /// + bind_transceiver = 0x00000009, + /// + /// bind_transceiver_resp + /// + bind_transceiver_resp = 0x80000009, + /// + /// outbind + /// + outbind = 0x0000000B, + /// + /// enquire_link + /// + enquire_link = 0x00000015, + /// + /// enquire_link_resp + /// + enquire_link_resp = 0x80000015, + /// + /// submit_multi + /// + submit_multi = 0x00000021, + /// + /// submit_multi_resp + /// + submit_multi_resp = 0x80000021, + /// + /// alert_notification + /// + alert_notification = 0x00000102, + /// + /// data_sm + /// + data_sm = 0x00000103, + /// + /// data_sm_resp + /// + data_sm_resp = 0x80000103 + } + + #endregion enumerations + + #region utility methods + + /// + /// Trims the trailing zeroes off of the response Pdu. Useful for + /// tracing and other purposes. This uses the command length to + /// actually trim it down, so TLVs and strings are not lost. If the + /// response actually is the same length as the command length, this + /// method performs a pass-through. + /// + /// The trimmed Pdu(byte array). + public static byte[] TrimResponsePdu(byte[] response) + { + uint commLength = DecodeCommandLength(response); + if(commLength == response.Length) + { + return response; + } + //trap any weird data coming in + if(commLength >= Int32.MaxValue || commLength > response.Length) + { + return new Byte[0]; + } + + byte[] trimmed = new Byte[commLength]; + for(int i = 0; i < trimmed.Length; i++) + { + trimmed[i] = response[i]; + } + + return trimmed; + } + + /// + /// Utility method to allow the Pdu factory to decode the command + /// ID without knowing about packet structure. Some SMSCs combine + /// response packets(even though they shouldn't). + /// + /// The Pdu response packet. + /// The ID of the Pdu command(e.g. cancel_sm_resp). + public static CommandIdType DecodeCommandId(byte[] response) + { + uint id = 0; + try + { + id = UnsignedNumConverter.SwapByteOrdering(BitConverter.ToUInt32(response, 4)); + return(CommandIdType)id; + } + catch //possible that we are reading a bad command + { + return CommandIdType.generic_nack; + } + } + + /// + /// Utility method to allow the Pdu factory to decode the command + /// length without knowing about packet structure. Some SMSCs combine + /// response packets(even though they shouldn't). + /// + /// The Pdu response packet. + /// The length of the Pdu command. + public static UInt32 DecodeCommandLength(byte[] response) + { + return UnsignedNumConverter.SwapByteOrdering(BitConverter.ToUInt32(response, 0)); + } + + #endregion utility methods + + #region IDisposable methods + + /// + /// Implementation of IDisposable + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Method for derived classes to implement. + /// + /// Set to false if called from a finalizer. + protected virtual void Dispose(bool disposing) + { + if(disposing) + { + // Free other state(managed objects). + } + // Free your own state(unmanaged objects). + // Set large fields to null. + } + + /// + /// Finalizer. Base classes will inherit this-used when Dispose()is not automatically called. + /// + ~Pdu() + { + // Simply call Dispose(false). + Dispose(false); + } + + #endregion IDisposable methods + } +} diff --git a/Packet/Request/MessageLcd2.cs b/Packet/Request/MessageLcd2.cs new file mode 100644 index 0000000..6054d1b --- /dev/null +++ b/Packet/Request/MessageLcd2.cs @@ -0,0 +1,267 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP.Packet; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// This class encapsulates common attributes for submit_sm and submit_multi Pdus. + /// + public abstract class MessageLcd2 : MessageLcd3 + { + /// + /// Limit of short message. + /// + public const int SHORT_MESSAGE_LIMIT = 160; + + #region private fields + + private SmppVersionType _ProtocolId = Pdu.SmppVersionType.Version3_4; + private PriorityType _PriorityFlag = Pdu.PriorityType.Level1; + private string _ScheduleDeliveryTime = string.Empty; + private string _ValidityPeriod = string.Empty; + private bool _ReplaceIfPresentFlag = false; + private byte _SmDefaultMessageId = 0; + private object _ShortMessage = null; + + #endregion private fields + + #region protected fields + + /// + /// The length of the short message. + /// + protected byte _SmLength = 0; + + #endregion protected fields + + #region properties + + /// + /// Protocol Identifier; network specific field. + /// + public SmppVersionType ProtocolId + { + get + { + return _ProtocolId; + } + set + { + _ProtocolId = value; + } + } + + /// + /// The priority level of the message. + /// + public PriorityType PriorityFlag + { + get + { + return _PriorityFlag; + } + set + { + _PriorityFlag = value; + } + } + + /// + /// Scheduled delivery time for the message delivery. Set to null for immediate + /// delivery. Otherwise, use YYMMDDhhmmsstnn as the format. See section 7.1.1 of + /// the SMPP spec for more details. + /// + public string ScheduleDeliveryTime + { + get + { + return _ScheduleDeliveryTime; + } + set + { + if(value != null && value != string.Empty) + { + if(value.Length == DATE_TIME_LENGTH) + { + _ScheduleDeliveryTime = value; + } + else + { + throw new ArgumentException("Scheduled delivery time not in correct format."); + } + } + else + { + _ScheduleDeliveryTime = string.Empty; + } + } + } + + /// + /// The validity period of this message. Set to null to request the SMSC default + /// validity period. Otherwise, use YYMMDDhhmmsstnn as the format. See section 7.1.1 of + /// the SMPP spec for more details. + /// + public string ValidityPeriod + { + get + { + return _ValidityPeriod; + } + set + { + if(value != null && value != string.Empty) + { + if(value.Length == DATE_TIME_LENGTH) + { + _ValidityPeriod = value; + } + else + { + throw new ArgumentException("Validity period not in correct format."); + } + } + else + { + _ValidityPeriod = string.Empty; + } + } + } + + /// + /// Flag indicating if submitted message should replace an existing message. + /// + public bool ReplaceIfPresentFlag + { + get + { + return _ReplaceIfPresentFlag; + } + set + { + _ReplaceIfPresentFlag = value; + } + } + + /// + /// Allows use of a canned message from the SMSC. If not using an SMSC canned message, + /// set to 0. + /// + public byte SmDefaultMessageId + { + get + { + return _SmDefaultMessageId; + } + set + { + _SmDefaultMessageId = value; + } + } + + /// + /// The short message to send, up to 160 octets. If you need more length, use the + /// MessagePayload property. Do not use both at the same time! Setting this to null + /// will result in an empty string. This can be either a string or a byte array; anything + /// else will result in an exception. + /// + public object ShortMessage + { + get + { + return _ShortMessage; + } + set + { + _ShortMessage = value; + } + } + + /// + /// The length of the short message. + /// + public byte SmLength + { + get + { + return _SmLength; + } + } + + #endregion properties + + #region constructors + + /// + /// Groups construction tasks for subclasses. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", registered delivery type to none, + /// ESM class to 0, data coding to SMSC default, protocol ID to v3.4, priority to level 1, + /// validity period to default, replace if present to false, default message ID to 0, + /// and the short message to an empty string. + /// + protected MessageLcd2(): base() + {} + + /// + /// Creates a new MessageLcd2 for incoming PDUs. + /// + /// The incoming bytes to decode. + protected MessageLcd2(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Creates the bytes after the destination address bytes. This also inserts the TLV + /// table data. Common to both submit and submit multiple. + /// + /// The bytes in the Pdu before the destination address(es). + protected ArrayList GetBytesAfterDestination() + { + ArrayList pdu = new ArrayList(); + pdu.Add(EsmClass); + pdu.Add((byte)ProtocolId); + pdu.Add((byte)PriorityFlag); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ScheduleDeliveryTime))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ValidityPeriod))); + pdu.Add((byte)RegisteredDelivery); + + if(ReplaceIfPresentFlag == true) + { + pdu.Add((byte)0x01); + } + else + { + pdu.Add((byte)0x00); + } + + pdu.Add((byte)DataCoding); + pdu.Add(SmDefaultMessageId); + _SmLength = PduUtil.InsertShortMessage(pdu, ShortMessage); + + pdu.TrimToSize(); + + return pdu; + } + } +} diff --git a/Packet/Request/MessageLcd3.cs b/Packet/Request/MessageLcd3.cs new file mode 100644 index 0000000..31b15ca --- /dev/null +++ b/Packet/Request/MessageLcd3.cs @@ -0,0 +1,601 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using RoaminSMPP.Packet; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Provides some common attributes for data_sm, submit_sm, and submit_multi. + /// + public abstract class MessageLcd3 : MessageLcd4 + { + #region private fields + + private string _ServiceType = string.Empty; + private byte _EsmClass = 0; + private DataCodingType _DataCoding = Pdu.DataCodingType.SMSCDefault; + + #endregion private fields + + #region constants + + private const int SAR_MIN = 1; + private const int SAR_MAX = 255; + + #endregion constants + + #region mandatory parameters + + /// + /// The service type of the message. Null values are treated as empty strings. + /// + public string ServiceType + { + get + { + return _ServiceType; + } + + set + { + if(value != null) + { + if(value.Length <= SERVICE_TYPE_LENGTH) + { + _ServiceType = value; + } + else + { + throw new ArgumentOutOfRangeException("Service Type must be " + + SERVICE_TYPE_LENGTH + " 5 characters or less."); + } + } + else + { + _ServiceType = string.Empty; + } + } + } + + /// + /// Indicates Message Mode and Message Type. See the SMSC version 3.4 specification + /// for details on setting this. + /// + public byte EsmClass + { + get + { + return _EsmClass; + } + set + { + _EsmClass = value; + } + } + + /// + /// Defines the encoding scheme of the short message user data. + /// + public DataCodingType DataCoding + { + get + { + return _DataCoding; + } + set + { + _DataCoding = value; + } + } + + #endregion mandatory parameters + + #region optional params + + /// + /// The application port number associated with the source address of the message. + /// This parameter should be present for WAP applications. + /// + public UInt16 SourcePort + { + get + { + return GetHostOrderUInt16FromTlv((ushort)Pdu.OptionalParamCodes.source_port); + } + set + { + if(value < UInt16.MaxValue) + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.source_port, value); + } + else + { + throw new ArgumentException("source_port value too large."); + } + } + } + + /// + /// The subcomponent in the destination device which created the user data. + /// + public AddressSubunitType SourceAddressSubunit + { + get + { + return (AddressSubunitType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.source_addr_subunit)[0]; + } + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.source_addr_subunit, new Byte[] {(byte)value}); + } + } + + /// + /// The application port number associated with the destination address of the + /// message. This parameter should be present for WAP applications. + /// + public UInt16 DestinationPort + { + get + { + return GetHostOrderUInt16FromTlv((ushort)Pdu.OptionalParamCodes.destination_port); + } + set + { + if(value < UInt16.MaxValue) + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.destination_port, value); + } + else + { + throw new ArgumentException("destination_port value too large."); + } + } + } + + /// + /// The reference number for a particular concatenated short message. Both + /// SarTotalSegments and SarSegmentSeqnum need to be set in conjunction with this + /// property. In addition, this must be the same for each segment. + /// + public UInt16 SarMsgRefNumber + { + get + { + return GetHostOrderUInt16FromTlv((ushort)Pdu.OptionalParamCodes.sar_msg_ref_num); + } + set + { + if(value < UInt16.MaxValue) + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.sar_msg_ref_num, value); + } + else + { + throw new ArgumentException("sar_msg_ref_number value too large."); + } + } + } + + /// + /// Indicates the total number of short messages within the concatenated short + /// message. Both SarMsgRefNumber and SarSegmentSeqNum need to be set in + /// conjunction with this property. In addition, this must be the same for each + /// segment. + /// + public byte SarTotalSegments + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.sar_total_segments)[0]; + } + + set + { + if(value >= SAR_MIN && value <= SAR_MAX) + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.sar_total_segments, new Byte[] {(byte)value}); + } + else + { + throw new ArgumentException( + "sar_total_segments must be >= " + SAR_MIN + " and <= " + SAR_MAX); + } + } + } + + /// + /// The sequence number of a particular short message within the concatenated + /// short message. Both SarMsgRefNumber and SarTotalSegments need to be set in + /// conjunction with this property. + /// + public byte SarSegmentSeqnum + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.sar_segment_seqnum)[0]; + } + + set + { + if(value >= SAR_MIN && value <= SAR_MAX) + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.sar_segment_seqnum, new Byte[] {(byte)value}); + } + else + { + throw new ArgumentException( + "sar_segment_seqnum must be >= " + SAR_MIN + " and <= " + SAR_MAX); + } + } + } + + /// + /// Defines the type of payload. + /// + public PayloadTypeType PayloadType + { + get + { + return (PayloadTypeType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.payload_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.payload_type, new Byte[] {(byte)value}); + } + } + + /// + /// Contains the extended short message user data. Up to 64K octets can be + /// transmitted. The limit for this is network/SMSC dependent. + /// + public object MessagePayload + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.message_payload); + } + + set + { + PduUtil.SetMessagePayload(this, value); + } + } + + /// + /// The privacy level of the message. + /// + public PrivacyType PrivacyIndicator + { + get + { + return (PrivacyType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.privacy_indicator)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.privacy_indicator, new Byte[] {(byte)value}); + } + } + + /// + /// ESME assigned message reference number. + /// + public UInt16 UserMessageReference + { + get + { + return GetHostOrderUInt16FromTlv((ushort)Pdu.OptionalParamCodes.user_message_reference); + } + set + { + if(value < UInt16.MaxValue) + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.user_message_reference, value); + } + else + { + throw new ArgumentException("user_message_reference too large."); + } + } + } + + /// + /// Allows an indication to be provided to an MS that there are + /// messages waiting for the subscriber on systems on the PLMN. The indication + /// can be an icon on the MS screen or other MMI indication. + /// See section 5.3.2.13 for details on how to set this. + /// + public byte MsMsgWaitFacilities + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.ms_msg_wait_facilities)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.ms_msg_wait_facilities, new Byte[] {value}); + } + } + + /// + /// Provides a MS with validity information associated with the received + /// short message. + /// + public MsValidityType MsValidity + { + get + { + return (MsValidityType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.ms_validity)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.ms_validity, new Byte[] {(byte)value}); + } + } + + /// + /// Provides a TDMA MS station with alert tone information associated with the + /// received short message. + /// + public UInt16 SmsSignal + { + get + { + return GetHostOrderUInt16FromTlv((ushort)Pdu.OptionalParamCodes.sms_signal); + } + + set + { + if(value < UInt16.MaxValue) + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.sms_signal, value); + } + else + { + throw new ArgumentException("sms_signal value too large."); + } + } + } + + /// + /// The subcomponent in the destination device for which the user data is intended. + /// + public AddressSubunitType DestinationAddrSubunit + { + get + { + return (AddressSubunitType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.dest_addr_subunit)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.dest_addr_subunit, new Byte[] {(byte)value}); + } + } + + /// + /// Tells a mobile station to alert the user when the short message arrives at the MS. + /// + /// Note: there is no value part associated with this parameter. + /// Any value you pass in will be discarded. + /// + public byte AlertOnMsgDelivery + { + get + { + try + { + byte[] bytes = GetOptionalParamBytes( + (ushort)OptionalParamCodes.alert_on_message_delivery); + return 1; + } + catch(ApplicationException) + { + return 0; + } + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.alert_on_message_delivery, new Byte[0]); + } + } + + /// + /// The language of the short message. + /// + public LanguageType LanguageIndicator + { + get + { + return (LanguageType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.language_indicator)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.language_indicator, new Byte[] {(byte)value}); + } + } + + /// + /// Associates a display time with the short message on the MS. + /// + public DisplayTimeType DisplayTime + { + get + { + return (DisplayTimeType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.display_time)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.display_time, new Byte[] {(byte)value}); + } + } + + /// + /// Associates a call back number with the message. See section 5.3.2.36 of the + /// SMPP spec for details. This must be between 4 and 19 characters in length. + /// + public string CallbackNum + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.callback_num); + } + + set + { + PduUtil.SetCallbackNum(this, value); + } + } + + /// + /// Controls the presentation indication and screening of the CallBackNumber at the + /// mobile station. You must also use the callback_num parameter with this. + /// See section 5.3.2.37 of the SMPP spec for details in how to set this. + /// + public byte CallbackNumPresInd + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.callback_num_pres_ind)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.callback_num_pres_ind, new Byte[] {value}); + } + } + + /// + /// Alphanumeric display tag for call back number. This must be less than or + /// equal to 65 characters in length. + /// + public string CallbackNumAtag + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.callback_num_atag); + } + + set + { + const int CALLBACK_ATAG_MAX = 65; + + if(value.Length <= CALLBACK_ATAG_MAX) + { + SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.callback_num_atag, value); + } + else + { + throw new ArgumentException("Callback number atag must be <= " + CALLBACK_ATAG_MAX + "."); + } + } + } + + /// + /// Specifies a subaddress associated with the originator of the message. + /// See section 5.3.2.15 of the SMPP spec for details on + /// setting this parameter. + /// + public string SourceSubaddress + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.source_subaddress); + } + + set + { + PduUtil.SetSourceSubaddress(this, value); + } + } + + /// + /// Specifies a subaddress associated with the receiver of the message. + /// See section 5.3.2.15 of the SMPP spec for details on + /// setting this parameter. + /// + public string DestinationSubaddress + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.dest_subaddress); + } + + set + { + PduUtil.SetDestSubaddress(this, value); + } + } + + #endregion optional params + + #region constructors + + /// + /// Groups construction tasks for subclasses. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", registered delivery type to none, + /// ESM class to 0, and data coding to SMSC default. + /// + protected MessageLcd3(): base() + {} + + /// + /// Creates a new MessageLcd3 for incoming PDUs. + /// + /// The incoming bytes to decode. + protected MessageLcd3(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + } +} diff --git a/Packet/Request/MessageLcd4.cs b/Packet/Request/MessageLcd4.cs new file mode 100644 index 0000000..c3b28ab --- /dev/null +++ b/Packet/Request/MessageLcd4.cs @@ -0,0 +1,72 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Provides some common attributes for data_sm, submit_sm, submit_multi, + /// and replace_sm. + /// + public abstract class MessageLcd4 : MessageLcd6 + { + /// + /// The registered delivery type of the message. + /// + protected RegisteredDeliveryType _RegisteredDelivery = Pdu.RegisteredDeliveryType.None; + + #region properties + + /// + /// The registered delivery type of the message. + /// + public RegisteredDeliveryType RegisteredDelivery + { + get + { + return _RegisteredDelivery; + } + set + { + _RegisteredDelivery = value; + } + } + + #endregion properties + + #region constructors + + /// + /// Groups construction tasks for subclasses. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", and registered delivery type to + /// none. + /// + protected MessageLcd4(): base() + {} + + /// + /// Creates a new MessageLcd4 for incoming PDUs. + /// + /// The incoming bytes to decode. + protected MessageLcd4(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + } +} diff --git a/Packet/Request/MessageLcd6.cs b/Packet/Request/MessageLcd6.cs new file mode 100644 index 0000000..c1f9eea --- /dev/null +++ b/Packet/Request/MessageLcd6.cs @@ -0,0 +1,135 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Provides some common attributes for data_sm, query_sm, submit_sm, submit_multi, + /// cancel_sm, and replace_sm. + /// + public abstract class MessageLcd6 : Pdu + { + #region private fields + + private TonType _SourceAddressTon = Pdu.TonType.International; + private NpiType _SourceAddressNpi = Pdu.NpiType.ISDN; + private string _SourceAddress = string.Empty; + + #endregion private fields + + #region constants + /// + /// Address length for source and destination addresses + /// + protected const int ADDRESS_LENGTH = 20; + /// + /// Message length + /// + protected const int MSG_LENGTH = 64; + /// + /// Length of service type string + /// + protected const int SERVICE_TYPE_LENGTH = 50; + + #endregion constants + + #region properties + + /// + /// The type of number of the source address. + /// + public TonType SourceAddressTon + { + get + { + return _SourceAddressTon; + } + set + { + _SourceAddressTon = value; + } + } + + /// + /// The number plan indicator of the source address. + /// + public NpiType SourceAddressNpi + { + get + { + return _SourceAddressNpi; + } + set + { + _SourceAddressNpi = value; + } + } + + /// + /// The source address. Null values are treated as empty strings. + /// + public string SourceAddress + { + get + { + return _SourceAddress; + } + set + { + if(value != null) + { + if(value.Length <= ADDRESS_LENGTH) + { + _SourceAddress = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Source Address must be <= " + ADDRESS_LENGTH + " characters."); + } + } + else + { + _SourceAddress = string.Empty; + } + } + } + + #endregion properties + + #region constructors + + /// + /// Groups construction tasks for subclasses. Sets source address TON to + /// international, source address NPI to ISDN, and source address to "". + /// + protected MessageLcd6(): base() + {} + + /// + /// Creates a new MessageLcd6 for incoming PDUs. + /// + /// The incoming bytes to decode. + protected MessageLcd6(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + } +} diff --git a/Packet/Request/SmppAlertNotification.cs b/Packet/Request/SmppAlertNotification.cs new file mode 100644 index 0000000..9de4ccb --- /dev/null +++ b/Packet/Request/SmppAlertNotification.cs @@ -0,0 +1,248 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP.Packet; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Sent from the SMSC to the mobile device when the device is available and a + /// delivery pending flag has been set from a previous data_sm operation. + /// + public class SmppAlertNotification : Pdu + { + #region private fields + + private TonType _SourceAddressTon = TonType.International; + private NpiType _SourceAddressNpi = NpiType.ISDN; + private string _SourceAddress = string.Empty; + private TonType _EsmeAddressTon = TonType.International; + private NpiType _EsmeAddressNpi = NpiType.ISDN; + private string _EsmeAddress = string.Empty; + + #endregion private fields + + #region enumerations + + /// + /// Enumerates the availability states of the message. + /// + public enum AvailabilityStatusType : byte + { + /// + /// Available + /// + Available = 0x00, + /// + /// Denied + /// + Denied = 0x01, + /// + /// Unavailable + /// + Unavailable = 0x02 + } + + #endregion enumerations + + #region mandatory parameters + + /// + /// Enumerates the type of number. + /// + public TonType SourceAddressTon + { + get + { + return _SourceAddressTon; + } + + set + { + _SourceAddressTon = value; + } + } + + /// + /// Enumerates the numbering plan indicator. + /// + public NpiType SourceAddressNpi + { + get + { + return _SourceAddressNpi; + } + + set + { + _SourceAddressNpi = value; + } + } + + /// + /// Address of sending entity. + /// + public string SourceAddress + { + get + { + return _SourceAddress; + } + + set + { + _SourceAddress = (value == null) ? string.Empty : value; + } + } + + /// + /// The type of number for the destination address that requested an alert. + /// + public TonType EsmeAddressTon + { + get + { + return _EsmeAddressTon; + } + + set + { + _EsmeAddressTon = value; + } + } + + /// + /// The numbering plan indicator for the destination address that requested an alert. + /// + public NpiType EsmeAddressNpi + { + get + { + return _EsmeAddressNpi; + } + + set + { + _EsmeAddressNpi = value; + } + } + + /// + /// The source address of the device that requested an alert. + /// + public string EsmeAddress + { + get + { + return _EsmeAddress; + } + + set + { + _EsmeAddress = (value == null) ? string.Empty : value; + } + } + + #endregion mandatory parameters + + #region optional parameters + + /// + /// The status of the mobile station. + /// + public AvailabilityStatusType MSAvailabilityStatus + { + get + { + return(AvailabilityStatusType)GetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.ms_availability_status)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.ms_availability_status, new Byte[] {(byte)value}); + } + } + + #endregion optional parameters + + #region constructors + + /// + /// Creates an SMPP Alert Notification Pdu. + /// + /// The bytes received from an ESME. + public SmppAlertNotification(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates an SMPP Alert Notification Pdu. + /// + public SmppAlertNotification(): base() + {} + + #endregion constructors + + /// + /// Decodes the alert_notification from the SMSC. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + SourceAddressTon =(TonType)remainder[0]; + SourceAddressNpi =(NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + EsmeAddressTon =(TonType)remainder[0]; + EsmeAddressNpi =(NpiType)remainder[1]; + EsmeAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + //fill the TLV table if applicable + TranslateTlvDataIntoTable(remainder); + } + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.alert_notification; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + pdu.Add((byte)EsmeAddressTon); + pdu.Add((byte)EsmeAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(EsmeAddress))); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Request/SmppBind.cs b/Packet/Request/SmppBind.cs new file mode 100644 index 0000000..c4889aa --- /dev/null +++ b/Packet/Request/SmppBind.cs @@ -0,0 +1,343 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Class for a bind request Pdu. + /// + public class SmppBind : Pdu + { + #region private fields + + private string _SystemId = string.Empty; + private string _Password = string.Empty; + private string _SystemType = string.Empty; + private string _AddressRange = string.Empty; + private SmppVersionType _InterfaceVersion = Pdu.SmppVersionType.Version3_4; + private TonType _AddressTon = Pdu.TonType.International; + private NpiType _AddressNpi = Pdu.NpiType.ISDN; + private BindingType _BindType = BindingType.BindAsTransceiver; + + #endregion private fields + + #region constants + + private const int ID_LENGTH = 15; + private const int PASS_LENGTH = 8; + private const int TYPE_LENGTH = 12; + private const int RANGE_LENGTH = 40; + + #endregion constants + + #region mandatory parameters + + /// + /// The binding type: transmitter, receiver, or transceiver. + /// + public BindingType BindType + { + get + { + return _BindType; + } + set + { + switch(value) + { + case BindingType.BindAsReceiver: + { + CommandID = CommandIdType.bind_receiver; + break; + } + case BindingType.BindAsTransceiver: + { + CommandID = CommandIdType.bind_transceiver; + break; + } + case BindingType.BindAsTransmitter: + { + CommandID = CommandIdType.bind_transmitter; + break; + } + default: + { + CommandID = CommandIdType.bind_transmitter; + break; + } + } + + _BindType = value; + } + } + + /// + /// The ESME system requesting to bind with the SMSC. Set to null for default value. + /// + public string SystemId + { + get + { + return _SystemId; + } + set + { + if(value != null) + { + if(value.Length <= ID_LENGTH) + _SystemId = value; + else + throw new ArgumentOutOfRangeException("System ID must be <= "+ + ID_LENGTH + " characters)."); + } + else + _SystemId = ""; + } + } + + /// + /// Used by the SMSC to authenticate the ESME requesting to bind. + /// Set to null for default value. + /// + public string Password + { + get + { + return _Password; + } + set + { + if(value != null) + { + if(value.Length <= PASS_LENGTH) + { + _Password = value; + } + else + { + throw new ArgumentOutOfRangeException("Password must be <= "+ PASS_LENGTH + " characters)."); + } + } + else + { + _Password = string.Empty; + } + } + } + + /// + /// The type of ESME system requesting to bind with the SMSC. + /// Set to null for default value. + /// + public string SystemType + { + get + { + return _SystemType; + } + set + { + if(value != null) + { + if(value.Length <= TYPE_LENGTH) + { + _SystemType = value; + } + else + { + throw new ArgumentOutOfRangeException("System type must be <= "+ TYPE_LENGTH + " characters)."); + } + } + else + { + _SystemType = string.Empty; + } + } + } + + /// + /// The ESME address range. If not known, set to null. + /// + public string AddressRange + { + get + { + return _AddressRange; + } + set + { + if(value != null) + { + if(value.Length <= RANGE_LENGTH) + { + _AddressRange = value; + } + else + { + throw new ArgumentOutOfRangeException("Address range must be <= "+ RANGE_LENGTH + " characters)."); + } + } + else + { + _AddressRange = string.Empty; + } + } + } + + /// + /// The version of the SMPP protocol supported by the ESME. + /// + public SmppVersionType InterfaceVersion + { + get + { + return _InterfaceVersion; + } + set + { + _InterfaceVersion = value; + } + } + + /// + /// Indicates type of number of ESME address. + /// + public TonType AddressTon + { + get + { + return _AddressTon; + } + set + { + _AddressTon = value; + } + } + + /// + /// Numbering plan indicator for ESME address. + /// + public NpiType AddressNpi + { + get + { + return _AddressNpi; + } + set + { + _AddressNpi = value; + } + } + + #endregion mandatory parameters + + #region enumerations + + /// + /// Binding types for the SMPP bind request. + /// + public enum BindingType : uint + { + /// + /// BindAsReceiver + /// + BindAsReceiver = 1, + /// + /// BindAsTransmitter + /// + BindAsTransmitter = 2, + /// + /// BindAsTransceiver + /// + BindAsTransceiver = 9 + } + + #endregion enumerations + + #region constructors + + /// + /// Constructs a bind request. Sets system ID, password, system type, and address + /// range to empty strings. Sets interface version to v3.4, address TON to + /// international, address NPI to ISDN, and sets to bind as a transceiver. + /// + public SmppBind(): base() + {} + + /// + /// Constructs a bind request. Sets system ID, password, system type, and address + /// range to empty strings. Sets interface version to v3.4, address TON to + /// international, address NPI to ISDN, and sets to bind as a transceiver. + /// + /// The incoming bytes from an ESME. + public SmppBind(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + BindType = BindingType.BindAsTransceiver; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SystemId))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(Password))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SystemType))); + pdu.Add((byte)InterfaceVersion); + pdu.Add((byte)AddressTon); + pdu.Add((byte)AddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(AddressRange))); + + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the submit_sm Pdu. The Pdu has basically the same format as + /// the submit_sm Pdu, but in this case it is a response. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + BindType = (SmppBind.BindingType)CommandID; + SystemId = SmppStringUtil.GetCStringFromBody(ref remainder); + Password = SmppStringUtil.GetCStringFromBody(ref remainder); + SystemType = SmppStringUtil.GetCStringFromBody(ref remainder); + InterfaceVersion =(SmppVersionType)remainder[0]; + AddressTon =(TonType)remainder[1]; + AddressNpi =(NpiType)remainder[2]; + AddressRange = SmppStringUtil.GetCStringFromBody(ref remainder, 3); + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppCancelSm.cs b/Packet/Request/SmppCancelSm.cs new file mode 100644 index 0000000..28f6a62 --- /dev/null +++ b/Packet/Request/SmppCancelSm.cs @@ -0,0 +1,253 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Cancels one or more previous short messages. A particular message or all messages + /// for a particular source, destination and service_type can be cancelled. + /// + /// From the SMPP spec: + /// If the message_id is set to the ID of a previously submitted message, then + /// provided the source address supplied by the ESME matches that of the stored + /// message, that message will be cancelled. + /// If the message_id is null, all outstanding undelivered messages with matching + /// source and destination addresses given in the Pdu are cancelled. If provided, + /// service_type is included in this matching. + /// Where the original submit_sm, data_sm or submit_multi source address was + /// defaulted to null, then the source address in the cancel_sm command should also + /// be null. + /// + public class SmppCancelSm : MessageLcd6 + { + #region private fields + + private string _MessageId = string.Empty; + private string _ServiceType = string.Empty; + private TonType _DestinationAddressTon = Pdu.TonType.International; + private NpiType _DestinationAddressNpi = Pdu.NpiType.ISDN; + private string _DestinationAddress = string.Empty; + + #endregion private fields + + #region properties + + /// + /// Message ID of the message to be cancelled. This must be the SMSC assigned Message + /// ID of the original message. Set to null if cancelling a group of messages. + /// + public string MessageId + { + get + { + return _MessageId; + } + set + { + if(value != null) + { + if(value.Length <= MSG_LENGTH) + { + _MessageId = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Message ID must be <= " + MSG_LENGTH + " characters."); + } + } + else + { + _MessageId = string.Empty; + } + } + } + + /// + /// Set to indicate SMS Application service, if cancellation of a group of application + /// service messages is desired. Otherwise set to null. + /// + public string ServiceType + { + get + { + return _ServiceType; + } + set + { + if(value != null) + { + if(value.Length <= SERVICE_TYPE_LENGTH) + { + _ServiceType = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Service Type must be <= " + SERVICE_TYPE_LENGTH + " characters."); + } + } + else + { + _ServiceType = string.Empty; + } + } + } + + /// + /// Type of number of destination SME address of the message(s)to be cancelled. + /// This must match that supplied in the original message submission request. + /// This can be set to null if the message ID is provided. + /// + public TonType DestinationAddressTon + { + get + { + return _DestinationAddressTon; + } + set + { + _DestinationAddressTon = value; + } + } + + /// + /// Numbering Plan Indicator of destination SME address of the message(s))to be + /// cancelled. This must match that supplied in the original message submission request. + /// This can be set to null when the message ID is provided. + /// + public NpiType DestinationAddressNpi + { + get + { + return _DestinationAddressNpi; + } + set + { + _DestinationAddressNpi = value; + } + } + + /// + /// Destination address of message(s)to be cancelled. This must match that supplied in + /// the original message submission request. This can be set to null when the message ID + /// is provided. + /// + public string DestinationAddress + { + get + { + return _DestinationAddress; + } + set + { + if(value != null) + { + if(value.Length <= ADDRESS_LENGTH) + { + _DestinationAddress = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Destination Address must be <= " + ADDRESS_LENGTH + " characters."); + } + } + else + { + _DestinationAddress = string.Empty; + } + } + } + + #endregion properties + + #region constructors + + /// + /// Creates an SMPP Cancel SM Pdu. Sets message ID and service type to empty strings + ///(null), sets the destination TON to international and the destination NPI to ISDN, + /// and sets the command status to 0. + /// + public SmppCancelSm(): base() + {} + + /// + /// Creates an SMPP Cancel SM Pdu. Sets message ID and service type to empty strings + ///(null), sets the destination TON to international and the destination NPI to ISDN, + /// and sets the command status to 0. + /// + /// The bytes received from an ESME. + public SmppCancelSm(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.cancel_sm; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ServiceType))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(MessageId))); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + pdu.Add((byte)DestinationAddressTon); + pdu.Add((byte)DestinationAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(DestinationAddress))); + + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the cancel_sm Pdu. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + ServiceType = SmppStringUtil.GetCStringFromBody(ref remainder); + MessageId = SmppStringUtil.GetCStringFromBody(ref remainder); + SourceAddressTon =(TonType)remainder[0]; + SourceAddressNpi =(NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + DestinationAddressTon =(TonType)remainder[0]; + DestinationAddressNpi =(NpiType)remainder[1]; + DestinationAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppDataSm.cs b/Packet/Request/SmppDataSm.cs new file mode 100644 index 0000000..579bfb3 --- /dev/null +++ b/Packet/Request/SmppDataSm.cs @@ -0,0 +1,516 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using RoaminSMPP.Utility; +using System.Collections; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// This command is used to transfer data between the SMSC and the ESME(and can be + /// used by both). This is an alternative to the submit_sm and deliver_sm commands. + /// + public class SmppDataSm : MessageLcd3 + { + private TonType _DestinationAddressTon = Pdu.TonType.International; + private NpiType _DestinationAddressNpi = Pdu.NpiType.ISDN; + private string _DestinationAddress = string.Empty; + + #region mandatory parameters + + /// + /// Type of number of destination SME address of the message(s)to be cancelled. + /// This must match that supplied in the original message submission request. + /// This can be set to null if the message ID is provided. + /// + public TonType DestinationAddressTon + { + get + { + return _DestinationAddressTon; + } + set + { + _DestinationAddressTon = value; + } + } + + /// + /// Numbering Plan Indicator of destination SME address of the message(s))to be + /// cancelled. This must match that supplied in the original message submission request. + /// This can be set to null when the message ID is provided. + /// + public NpiType DestinationAddressNpi + { + get + { + return _DestinationAddressNpi; + } + set + { + _DestinationAddressNpi = value; + } + } + + /// + /// Destination address of message(s)to be cancelled. This must match that supplied in + /// the original message submission request. This can be set to null when the message ID + /// is provided. + /// + public string DestinationAddress + { + get + { + return _DestinationAddress; + } + set + { + if(value != null) + { + if(value.Length <= ADDRESS_LENGTH) + { + _DestinationAddress = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Destination Address must be <= " + ADDRESS_LENGTH + " characters."); + } + } + else + { + _DestinationAddress = string.Empty; + } + } + } + + #endregion mandatory parameters + + #region optional params + + /// + /// The correct network associated with the originating device. + /// + public NetworkType SourceNetworkType + { + get + { + return(NetworkType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.source_network_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.source_network_type, new Byte[] {(byte)value}); + } + } + + /// + /// The correct bearer type for the delivering the user data to the destination. + /// + public BearerType SourceBearerType + { + get + { + return(BearerType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.source_bearer_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.source_bearer_type, new Byte[] {(byte)value}); + } + } + + /// + /// The telematics identifier associated with the source. The value part + /// has yet to be defined in the specs as of 07/20/2004. + /// + public UInt16 SourceTelematicsId + { + get + { + return GetHostOrderUInt16FromTlv((ushort)Pdu.OptionalParamCodes.source_telematics_id); + } + + set + { + if(value < UInt16.MaxValue) + { + SetOptionalParamBytes( + (UInt16)Pdu.OptionalParamCodes.source_telematics_id, + BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering(value))); + } + else + { + throw new ArgumentException("source_telematics_id value too large."); + } + } + } + + /// + /// The correct network for the destination device. + /// + public NetworkType DestNetworkType + { + get + { + return(NetworkType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.dest_network_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.dest_network_type, new Byte[] {(byte)value}); + } + } + + /// + /// The correct bearer type for the delivering the user data to the destination. + /// + public BearerType DestBearerType + { + get + { + return(BearerType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.dest_bearer_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.dest_bearer_type, new Byte[] {(byte)value}); + } + } + + /// + /// The telematics identifier associated with the destination. The value part + /// has yet to be defined in the specs as of 07/20/2004. + /// + public UInt16 DestTelematicsId + { + get + { + return GetHostOrderUInt16FromTlv((ushort)Pdu.OptionalParamCodes.dest_telematics_id); + } + + set + { + if(value < UInt16.MaxValue) + { + SetOptionalParamBytes( + (UInt16)Pdu.OptionalParamCodes.dest_telematics_id, + BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering(value))); + } + else + { + throw new ArgumentException("dest_telematics_id value too large."); + } + } + } + + /// + /// If true, this indicates that there are more messages to follow for the + /// destination SME. + /// + public bool MoreMessagesToSend + { + get + { + byte sendMore = GetOptionalParamBytes( + (ushort)OptionalParamCodes.more_messages_to_send)[0]; + + return (sendMore == 0) ? false : true; + } + + set + { + byte sendMore; + if(value == false) + { + sendMore =(byte)0x00; + } + else + { + sendMore =(byte)0x01; + } + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.more_messages_to_send, new Byte[] {sendMore}); + } + } + + /// + /// Time to live as a relative time in seconds from submission. + /// + public UInt32 QosTimeToLive + { + get + { + return GetHostOrderUInt32FromTlv((ushort)Pdu.OptionalParamCodes.qos_time_to_live); + } + + set + { + if(value < UInt32.MaxValue) + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.qos_time_to_live, + BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering(value))); + } + else + { + throw new ArgumentException("qos_time_to_live value too large."); + } + } + } + + /// + /// Sets the Delivery Pending Flag on delivery failure. + /// + public DpfResultType SetDpf + { + get + { + return(DpfResultType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.set_dpf)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.set_dpf, new Byte[] {(byte)value}); + } + } + + /// + /// SMSC message ID of message being receipted. Should be present for SMSC + /// Delivery Receipts and Intermediate Notifications. + /// + public string ReceiptedMessageId + { + get + { + return GetOptionalParamString((ushort)Pdu.OptionalParamCodes.receipted_message_id); + } + + set + { + PduUtil.SetReceiptedMessageId(this, value); + } + } + + /// + /// Message State. Should be present for SMSC Delivery Receipts and Intermediate + /// Notifications. + /// + public MessageStateType MessageState + { + get + { + return (MessageStateType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.message_state)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.message_state, new Byte[] {(byte)value}); + } + } + + /// + /// Network error code. May be present for SMSC Delivery Receipts and + /// Intermediate Notifications. See section 5.3.2.31 for more information. + /// + public string NetworkErrorCode + { + get + { + return GetOptionalParamString((ushort)Pdu.OptionalParamCodes.network_error_code); + } + + set + { + PduUtil.SetNetworkErrorCode(this, value); + } + } + + /// + /// A user response code. The actual response codes are implementation specific. + /// + public byte UserResponseCode + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.user_response_code)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.user_response_code,new Byte[] {value}); + } + } + + /// + /// Indicates the number of messages stored in a mail box. + /// + public byte NumberOfMessages + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.number_of_messages)[0]; + } + + set + { + if(value <= 99) + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.number_of_messages, new Byte[] {value}); + } + else + { + throw new ArgumentException("number_of_messages must be between 0 and 99."); + } + } + } + + /// + /// Indicates and controls the MS users reply method to an SMS delivery message + /// received from the network. + /// + public ItsReplyTypeType ItsReplyType + { + get + { + return (ItsReplyTypeType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.its_reply_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.its_reply_type, new Byte[] {(byte)value}); + } + } + + /// + /// Session control information for Interactive Teleservice. + /// + /// See section 5.3.2.43 of the SMPP spec for how to set this. + /// + public string ItsSessionInfo + { + get + { + return GetOptionalParamString((ushort)Pdu.OptionalParamCodes.its_session_info); + } + + set + { + PduUtil.SetItsSessionInfo(this, value); + } + } + + #endregion optional params + + #region constructors + + /// + /// Creates a data_sm Pdu. Sets the destination TON to international, the destination + /// NPI to ISDN, and the command status to 0. + /// + public SmppDataSm(): base() + {} + + /// + /// Creates a data_sm Pdu. Sets the destination TON to international, the destination + /// NPI to ISDN, and the command status to 0. + /// + /// The bytes received from an ESME. + public SmppDataSm(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.data_sm; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ServiceType))); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + pdu.Add((byte)DestinationAddressTon); + pdu.Add((byte)DestinationAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(DestinationAddress))); + pdu.Add(EsmClass); + pdu.Add((byte)RegisteredDelivery); + pdu.Add((byte)DataCoding); + + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the cancel_sm Pdu. + /// + protected override void DecodeSmscResponse() + { + #if DEBUG + Console.WriteLine("In DecodeSmscResponse of EsmppDataSm"); + #endif + byte[] remainder = BytesAfterHeader; + ServiceType = SmppStringUtil.GetCStringFromBody(ref remainder); + SourceAddressTon = (TonType)remainder[0]; + SourceAddressNpi = (NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + DestinationAddressTon = (TonType)remainder[0]; + DestinationAddressNpi = (NpiType)remainder[1]; + DestinationAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + EsmClass = remainder[0]; + RegisteredDelivery = (RegisteredDeliveryType)remainder[1]; + DataCoding = (DataCodingType)remainder[2]; + + TranslateTlvDataIntoTable(remainder, 3); + } + } +} diff --git a/Packet/Request/SmppDeliverSm.cs b/Packet/Request/SmppDeliverSm.cs new file mode 100644 index 0000000..83c1f79 --- /dev/null +++ b/Packet/Request/SmppDeliverSm.cs @@ -0,0 +1,678 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using RoaminSMPP.Utility; +using RoaminSMPP.Packet; +using System.Collections; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// This class defines a deliver_sm that is SMSC generated. This does + /// NOT handle anything other than strings in the short message. + /// + public class SmppDeliverSm : Pdu + { + #region private fields + + private string _ServiceType = string.Empty; + private TonType _SourceAddressTon = TonType.International; + private NpiType _SourceAddressNpi = NpiType.ISDN; + private string _SourceAddress = string.Empty; + private TonType _DestinationAddressTon = TonType.International; + private NpiType _DestinationAddressNpi = NpiType.ISDN; + private string _DestinationAddress = string.Empty; + private byte _EsmClass = 0; + private SmppVersionType _ProtocolId = SmppVersionType.Version3_4; + private PriorityType _PriorityFlag = PriorityType.Lowest; + private RegisteredDeliveryType _RegisteredDelivery = RegisteredDeliveryType.None; + private DataCodingType _DataCoding = DataCodingType.SMSCDefault; + private byte _SmLength = 0; + private string _ShortMessage = null; + + #endregion private fields + + /// + /// Used to indicate the SMS Application service associated with the message. + /// If this is unknown, null is returned. + /// + public string ServiceType + { + get + { + return _ServiceType; + } + + set + { + _ServiceType = (value == null) ? string.Empty : value; + } + } + + /// + /// Type of Number for source address. + /// + public TonType SourceAddressTon + { + get + { + return _SourceAddressTon; + } + + set + { + _SourceAddressTon = value; + } + } + + /// + /// Numbering Plan Indicator for source address. + /// + public NpiType SourceAddressNpi + { + get + { + return _SourceAddressNpi; + } + + set + { + _SourceAddressNpi = value; + } + } + + /// + /// Address of origination entity. + /// + public string SourceAddress + { + get + { + return _SourceAddress; + } + + set + { + _SourceAddress = (value == null) ? string.Empty : value; + } + } + + /// + /// Type of number of destination entity. + /// + public TonType DestinationAddressTon + { + get + { + return _DestinationAddressTon; + } + + set + { + _DestinationAddressTon = value; + } + } + + /// + /// Numbering Plan Indicator of destination entity. + /// + public NpiType DestinationAddressNpi + { + get + { + return _DestinationAddressNpi; + } + + set + { + _DestinationAddressNpi = value; + } + } + + /// + /// Destination address of entity. + /// + public string DestinationAddress + { + get + { + return _DestinationAddress; + } + + set + { + _DestinationAddress = (value == null) ? string.Empty : value; + } + } + + /// + /// Indicates Message Mode and Message Type. See the SMSC + /// version 3.4 specification for details on this. + /// + public byte EsmClass + { + get + { + return _EsmClass; + } + + set + { + _EsmClass = value; + } + } + + /// + /// Protocol Identifier; network specific. + /// + public SmppVersionType ProtocolId + { + get + { + return _ProtocolId; + } + + set + { + _ProtocolId = value; + } + } + + /// + /// Designates the priority level of the message. + /// + public PriorityType PriorityFlag + { + get + { + return _PriorityFlag; + } + + set + { + _PriorityFlag = value; + } + } + + /// + /// Use this to indicate if you want delivery confirmation. + /// + public RegisteredDeliveryType RegisteredDelivery + { + get + { + return _RegisteredDelivery; + } + + set + { + _RegisteredDelivery = value; + } + } + + /// + /// Indicates the encoding scheme of the short message. + /// + public DataCodingType DataCoding + { + get + { + return _DataCoding; + } + + set + { + _DataCoding = value; + } + } + + /// + /// Short message length in octets(bytes for x86). + /// + public byte SmLength + { + get + { + return _SmLength; + } + } + + /// + /// The short message for this Pdu. This holds up to 160 characters. + /// If the message is longer, the MessagePayload property will be used. + /// If this is the case, the short message length will be zero. Note + /// that both the ShortMessage and MessagePayload cannot be used + /// simultaneously. + /// + public string ShortMessage + { + get + { + return _ShortMessage; + } + + set + { + _ShortMessage = value; + } + } + + #region optional parameters + + /// + /// The message reference number assigned by the ESME. + /// + public UInt16 UserMessageReference + { + get + { + return GetHostOrderUInt16FromTlv((ushort)OptionalParamCodes.user_message_reference); + } + + set + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.user_message_reference, value); + } + } + + /// + /// The port number associated with the source address of the message. This + /// parameter will be present for WAP applications. + /// + public UInt16 SourcePort + { + get + { + return GetHostOrderUInt16FromTlv((ushort)OptionalParamCodes.source_port); + } + + set + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.source_port, value); + } + } + + /// + /// The port number associated with the destination address of the message. This + /// parameter will be present for WAP applications. + /// + public UInt16 DestinationPort + { + get + { + return GetHostOrderUInt16FromTlv((ushort)OptionalParamCodes.destination_port); + } + + set + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.destination_port, value); + } + } + + /// + /// The reference number for a particular concatenated short message. + /// + public UInt16 SarMsgRefNumber + { + get + { + return GetHostOrderUInt16FromTlv((ushort)OptionalParamCodes.sar_msg_ref_num); + } + + set + { + SetHostOrderValueIntoTlv((UInt16)Pdu.OptionalParamCodes.sar_msg_ref_num, value); + } + } + + /// + /// Total number of short message fragments within the concatenated short message. + /// + public byte SarTotalSegments + { + get + { + return GetOptionalParamBytes((ushort)OptionalParamCodes.sar_total_segments)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.sar_total_segments, new Byte[] {value}); + } + } + + /// + /// The sequence number of a particular short message fragment within the + /// concatenated short message. + /// + public byte SarSegmentSeqnum + { + get + { + return GetOptionalParamBytes((ushort)OptionalParamCodes.sar_segment_seqnum)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.sar_segment_seqnum, new Byte[] {value}); + } + } + + /// + /// A user response code. The actual response codes are SMS application specific. + /// + public byte UserResponseCode + { + get + { + return GetOptionalParamBytes((ushort)OptionalParamCodes.user_response_code)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.user_response_code, new Byte[] {value}); + } + } + + /// + /// Indicates a level of privacy associated with the message. + /// + public PrivacyType PrivacyIndicator + { + get + { + return(PrivacyType) + GetOptionalParamBytes((ushort)OptionalParamCodes.privacy_indicator)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.privacy_indicator, new Byte[] {(byte)value}); + } + } + + /// + /// Defines the type of payload(e.g. WDP, WCMP, etc.) + /// + public PayloadTypeType PayloadType + { + get + { + return(PayloadTypeType) + GetOptionalParamBytes((ushort)OptionalParamCodes.payload_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.payload_type, new Byte[] {(byte)value}); + } + } + + /// + /// This can hold up to 64K octets of short message data. + /// The actual limit is network/SMSC dependent. + /// + public string MessagePayload + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.message_payload); + } + + set + { + PduUtil.SetMessagePayload(this, value); + } + } + + /// + /// Associates a callback number with a message. See section 5.3.2.36 of the + /// SMPP spec for details. This must be between 4 and 19 characters in length. + /// + public string CallbackNum + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.callback_num); + } + + set + { + PduUtil.SetCallbackNum(this, value); + } + } + + /// + /// Specifies a source subaddress associated with the originating entity. + /// See section 5.3.2.15 of the SMPP spec for details on setting this parameter. + /// + public string SourceSubaddress + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.source_subaddress); + } + + set + { + PduUtil.SetSourceSubaddress(this, value); + } + } + + /// + /// Specifies a source subaddress associated with the receiving entity. + /// See section 5.3.2.15 of the SMPP spec for details on setting this parameter. + /// + public string DestinationSubaddress + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.dest_subaddress); + } + + set + { + PduUtil.SetDestSubaddress(this, value); + } + } + + /// + /// The language of the short message. + /// + public LanguageType LanguageIndicator + { + get + { + return(LanguageType) + GetOptionalParamBytes((ushort)OptionalParamCodes.language_indicator)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.language_indicator, new Byte[] {(byte)value}); + } + } + + /// + /// From the SMPP spec: + /// The its_session_info parameter is a required parameter for the CDMA Interactive + /// Teleservice as defined by the Korean PCS carriers [KORITS]. It contains control + /// information for the interactive session between an MS and an ESME. + /// + /// See section 5.3.2.43 of the SMPP spec for how to set this. + /// + public string ItsSessionInfo + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.its_session_info); + } + + set + { + PduUtil.SetItsSessionInfo(this, value); + } + } + + /// + /// Network Error Code. May be present for Intermediate Notifications + /// and SMSC Delivery Receipts. See SMPP spec 5.3.2.31 for details. + /// + public string NetworkErrorCode + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.network_error_code); + } + + set + { + PduUtil.SetNetworkErrorCode(this, value); + } + } + + /// + /// Indicates to the ESME the final message state for an SMSC Delivery Receipt. + /// + public MessageStateType MessageState + { + get + { + return(MessageStateType) + GetOptionalParamBytes((ushort)OptionalParamCodes.message_state)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.message_state, new Byte[] {(byte)value}); + } + } + + /// + /// Indicates the ID of the message being receipted in an SMSC Delivery Receipt. + /// + public string ReceiptedMessageId + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.receipted_message_id); + } + + set + { + PduUtil.SetReceiptedMessageId(this, value); + } + } + + #endregion optional parameters + + #region constructors + + /// + /// Creates a deliver_sm Pdu. + /// + /// The bytes received from an ESME. + public SmppDeliverSm(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a deliver_sm Pdu. + /// + public SmppDeliverSm(): base() + {} + + #endregion constructors + + /// + /// This decodes the deliver_sm Pdu. The Pdu has basically the same format as + /// the submit_sm Pdu, but in this case it is a response. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + ServiceType = SmppStringUtil.GetCStringFromBody(ref remainder); + SourceAddressTon = (TonType)remainder[0]; + SourceAddressNpi = (NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + DestinationAddressTon = (TonType)remainder[0]; + DestinationAddressNpi = (NpiType)remainder[1]; + DestinationAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + EsmClass = remainder[0]; + ProtocolId = (SmppVersionType)remainder[1]; + PriorityFlag = (PriorityType)remainder[2]; + //schedule_delivery_time and validity_period are null, so don't bother + //reading them + RegisteredDelivery = (RegisteredDeliveryType)remainder[5]; + //replace_if_present is always null, so don't bother reading it + DataCoding = (DataCodingType)remainder[7]; + //sm_default_msg_id is always null, so don't bother reading it + _SmLength = remainder[9]; + ShortMessage = SmppStringUtil.GetStringFromBody(ref remainder, 10, 10 + _SmLength); + TranslateTlvDataIntoTable(remainder); + } + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.deliver_sm; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ServiceType))); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + pdu.Add((byte)DestinationAddressTon); + pdu.Add((byte)DestinationAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(DestinationAddress))); + pdu.Add(EsmClass); + pdu.Add((byte)ProtocolId); + pdu.Add((byte)PriorityFlag); + //schedule_delivery_time and validity_period are null, so set them to zero + pdu.Add((byte)0); + pdu.Add((byte)0); + pdu.Add((byte)RegisteredDelivery); + //replace_if_present is always null, so set it to zero + pdu.Add((byte)0); + pdu.Add((byte)DataCoding); + //sm_default_msg_id is always null, so set it to zero + pdu.Add((byte)0); + _SmLength = PduUtil.InsertShortMessage(pdu, ShortMessage); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Request/SmppEnquireLink.cs b/Packet/Request/SmppEnquireLink.cs new file mode 100644 index 0000000..f3f30ff --- /dev/null +++ b/Packet/Request/SmppEnquireLink.cs @@ -0,0 +1,76 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using RoaminSMPP.Packet; +using System.Collections; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Defines the SMPP enquire_link Pdu. This is basically just the header. + /// + public class SmppEnquireLink : Pdu + { + #region constructors + + /// + /// Creates an enquire_link Pdu. Sets command status and command ID. + /// + public SmppEnquireLink(): base() + {} + + /// + /// Creates an enquire_link Pdu. Sets command status and command ID. + /// + /// The bytes received from an ESME. + public SmppEnquireLink(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.enquire_link; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the query_sm Pdu. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppGenericNack.cs b/Packet/Request/SmppGenericNack.cs new file mode 100644 index 0000000..8f270d5 --- /dev/null +++ b/Packet/Request/SmppGenericNack.cs @@ -0,0 +1,76 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using RoaminSMPP.Utility; +using System.Collections; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Class to represent a generic negative acknowledgment. + /// + public class SmppGenericNack : Pdu + { + #region constructors + + /// + /// Creates a new generic NACK. Sets the error code to 0. + /// + public SmppGenericNack(): base() + {} + + /// + /// Creates a new generic NACK. + /// + /// The incoming bytes from the ESME. + public SmppGenericNack(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.generic_nack; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the query_sm Pdu. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppOutbind.cs b/Packet/Request/SmppOutbind.cs new file mode 100644 index 0000000..f9f8ab1 --- /dev/null +++ b/Packet/Request/SmppOutbind.cs @@ -0,0 +1,116 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using System.Text; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Defines an outbind response(really a request TO us)from the SMSC. + /// + public class SmppOutbind : Pdu + { + private string _SystemId = string.Empty; + private string _Password = string.Empty; + + /// + /// The ID of the SMSC. + /// + public string SystemId + { + get + { + return _SystemId; + } + + set + { + _SystemId = (value == null) ? string.Empty : value; + } + } + + /// + /// Password that the ESME can use for authentication. + /// + public string Password + { + get + { + return _Password; + } + + set + { + _Password = (value == null) ? string.Empty : value; + } + } + + #region constructors + + /// + /// Creates an outbind response Pdu. + /// + /// The bytes received from an ESME. + public SmppOutbind(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates an outbind response Pdu. + /// + public SmppOutbind(): base() + {} + + #endregion constructors + + /// + /// Decodes the outbind response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + SystemId = SmppStringUtil.GetCStringFromBody(ref remainder); + Password = SmppStringUtil.GetCStringFromBody(ref remainder); + //fill the TLV table if applicable + TranslateTlvDataIntoTable(remainder); + } + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.outbind; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SystemId))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(Password))); + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Request/SmppQuerySm.cs b/Packet/Request/SmppQuerySm.cs new file mode 100644 index 0000000..06c20ad --- /dev/null +++ b/Packet/Request/SmppQuerySm.cs @@ -0,0 +1,119 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using RoaminSMPP.Packet; +using System.Collections; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// This class defines a query_sm ESME originated Pdu. + /// + public class SmppQuerySm : MessageLcd6 + { + private string _MessageId = string.Empty; + + /// + /// The ID of the message. + /// + public string MessageId + { + get + { + return _MessageId; + } + set + { + if(value != null) + { + if(value.Length <= MSG_LENGTH) + { + _MessageId = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Message ID must be <= " + MSG_LENGTH + " characters."); + } + } + else + { + _MessageId = string.Empty; + } + } + } + + #region constructors + + /// + /// Creates a query_sm Pdu. Sets source address TON to international, source address + /// NPI to ISDN, source address to "", and message ID to an empty string. + /// + public SmppQuerySm(): base() + {} + + /// + /// Creates a new SmppQuerySm for incoming PDUs. + /// + /// The incoming bytes to decode. + public SmppQuerySm(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.query_sm; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(MessageId))); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the query_sm Pdu. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + MessageId = SmppStringUtil.GetCStringFromBody(ref remainder); + SourceAddressTon =(TonType)remainder[0]; + SourceAddressNpi =(NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppReplaceSm.cs b/Packet/Request/SmppReplaceSm.cs new file mode 100644 index 0000000..82030ad --- /dev/null +++ b/Packet/Request/SmppReplaceSm.cs @@ -0,0 +1,253 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP.Packet; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Pdu to replace a previously submitted short message that hasn't been delivered. + /// The match is based on the message_id and source addresses of the original message. + /// + public class SmppReplaceSm : MessageLcd4 + { + #region private fields + + private string _MessageId = string.Empty; + private string _ScheduleDeliveryTime = string.Empty; + private string _ValidityPeriod = string.Empty; + private byte _SmDefaultMessageId = 0; + private object _ShortMessage = null; + private byte _SmLength = 0; + + #endregion private fields + + #region mandatory parameters + + /// + /// SMSC message ID of the message to be replaced. This must be the message ID of the + /// original message. + /// + public string MessageId + { + get + { + return _MessageId; + } + set + { + if(value != null) + { + if(value.Length <= MSG_LENGTH) + { + _MessageId = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Message ID must be <= " + MSG_LENGTH + " characters."); + } + } + else + { + _MessageId = string.Empty; + } + } + } + + /// + /// New scheduled delivery time for the short message. Set to null, if updating of the + /// original scheduled delivery time is not desired. + /// + public string ScheduleDeliveryTime + { + get + { + return _ScheduleDeliveryTime; + } + set + { + if(value != null && value != string.Empty) + { + if(value.Length == DATE_TIME_LENGTH) + { + _ScheduleDeliveryTime = value; + } + else + { + throw new ArgumentException("Scheduled delivery time not in correct format."); + } + } + else + { + _ScheduleDeliveryTime = string.Empty; + } + } + } + + /// + /// New expiration time for the short message. Set to null, if updating of the original + /// expiration time is not required. + /// + public string ValidityPeriod + { + get + { + return _ValidityPeriod; + } + set + { + if(value != null && value != string.Empty) + { + if(value.Length == DATE_TIME_LENGTH) + { + _ValidityPeriod = value; + } + else + { + throw new ArgumentException("Validity period not in correct format."); + } + } + else + { + _ValidityPeriod = string.Empty; + } + } + } + + /// + /// New pre-defined(canned)message identifier. Set to 0 if not using. + /// + public byte SmDefaultMessageId + { + get + { + return _SmDefaultMessageId; + } + set + { + _SmDefaultMessageId = value; + } + } + + /// + /// New short message to replace existing message. + /// + public object ShortMessage + { + get + { + return _ShortMessage; + } + set + { + _ShortMessage = value; + } + } + + /// + /// The length of the short message. + /// + public byte SmLength + { + get + { + return _SmLength; + } + } + + #endregion mandatory parameters + + #region constructors + + /// + /// Creates a replace_sm Pdu. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", registered delivery type to none, + /// message ID, scheduled delivery time, validity period, and short message to + /// empty strings(NULL SMSC value). Sets the default message ID to 0. + /// + public SmppReplaceSm(): base() + {} + + /// + /// Creates a replace_sm Pdu. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", registered delivery type to none, + /// message ID, scheduled delivery time, validity period, and short message to + /// empty strings(NULL SMSC value). Sets the default message ID to 0. + /// + /// The incoming bytes from an ESME. + public SmppReplaceSm(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.replace_sm; + } + + /// + /// Generates the hex encoded bytes for a replace_sm Pdu. + /// + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(MessageId))); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ScheduleDeliveryTime))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ValidityPeriod))); + pdu.Add((byte)RegisteredDelivery); + pdu.Add(_SmDefaultMessageId); + + _SmLength = PduUtil.InsertShortMessage(pdu, ShortMessage); + + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the submit_sm Pdu. The Pdu has basically the same format as + /// the submit_sm Pdu, but in this case it is a response. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + MessageId = SmppStringUtil.GetCStringFromBody(ref remainder); + SourceAddressTon =(TonType)remainder[0]; + SourceAddressNpi =(NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + ScheduleDeliveryTime = SmppStringUtil.GetCStringFromBody(ref remainder); + ValidityPeriod = SmppStringUtil.GetCStringFromBody(ref remainder); + RegisteredDelivery =(RegisteredDeliveryType)remainder[0]; + SmDefaultMessageId = remainder[1]; + _SmLength = remainder[2]; + ShortMessage = SmppStringUtil.GetStringFromBody(ref remainder, 3, 3 + _SmLength); + + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppSubmitMulti.cs b/Packet/Request/SmppSubmitMulti.cs new file mode 100644 index 0000000..d5cd7c8 --- /dev/null +++ b/Packet/Request/SmppSubmitMulti.cs @@ -0,0 +1,196 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Defines a submit_multi Pdu. + /// + public class SmppSubmitMulti : MessageLcd2 + { + //note that all of the optional parameters are in the base class. + private byte _NumberOfDests = 0; + private DestinationAddress[] _DestinationAddresses = new DestinationAddress[0]; + private const int MAX_DESTS = 254; + + #region properties + + /// + /// The number of destinations to send to. + /// + public byte NumberOfDestinations + { + get + { + return _NumberOfDests; + } + } + + /// + /// The destination addresses that will be sent to. This will set the number of + /// destination addresses as well. Passing null in will set them to zero. Calling the + /// accessor will get you a cloned array. You must use the mutator to modify the values. + /// + public DestinationAddress[] DestinationAddresses + { + get + { + return(DestinationAddress[])_DestinationAddresses.Clone(); + } + set + { + _DestinationAddresses = (value == null) ? new DestinationAddress[0] : value; + _NumberOfDests = (byte)_DestinationAddresses.Length; + } + } + + #endregion properties + + #region constructors + + /// + /// Creates a submit_multi Pdu. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", registered delivery type to none, + /// ESM class to 0, data coding to SMSC default, protocol ID to v3.4, priority to level 1, + /// validity period to default, replace if present to false, default message ID to 0, + /// the short message to an empty string, the number of destinations to 0 and the + /// destination addresses to null. Use the DestAddrFactory class to create + /// destination addresses. + /// + public SmppSubmitMulti(): base() + {} + + /// + /// Creates a submit_multi Pdu. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", registered delivery type to none, + /// ESM class to 0, data coding to SMSC default, protocol ID to v3.4, priority to level 1, + /// validity period to default, replace if present to false, default message ID to 0, + /// the short message to an empty string, the number of destinations to 0 and the + /// destination addresses to null. Use the DestAddrFactory class to create + /// destination addresses. + /// + /// The incoming bytes from an ESME + public SmppSubmitMulti(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.submit_multi; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ServiceType))); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + //number of destinations. + pdu.Add(NumberOfDestinations); + + //and their addresses + foreach(DestinationAddress address in _DestinationAddresses) + { + if(!address.IsDistributionList) + { + //pack up the byte array for this address + ArrayList sme = new ArrayList(); + pdu.Add((byte)0x01); + pdu.Add((byte)address.DestinationAddressTon); + pdu.Add((byte)address.DestinationAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull( + Encoding.ASCII.GetBytes(address.DestAddress))); + } + else + { + ArrayList dln = new ArrayList(); + pdu.Add((byte)0x02); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull( + Encoding.ASCII.GetBytes(address.DistributionList))); + } + } + + pdu.AddRange(base.GetBytesAfterDestination()); + + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// Decodes the submit_multi response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + + ServiceType = SmppStringUtil.GetCStringFromBody(ref remainder); + SourceAddressTon =(TonType)remainder[0]; + SourceAddressNpi =(NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + + //the SMSC might not send back the number of destinations, + //so check if it did + if(remainder.Length > 0) + { + _NumberOfDests = remainder[0]; + DestinationAddresses = new DestinationAddress[NumberOfDestinations]; + + //trim off the number of destinations + long length = remainder.Length - 1; + byte[] newRemainder = new byte[length]; + Array.Copy(remainder, 1, newRemainder, 0, length); + remainder = newRemainder; + newRemainder = null; + + for(int i = 0; i < _DestinationAddresses.Length; i++) + { + _DestinationAddresses[i] = new DestinationAddress(ref remainder); + } + } + + EsmClass = remainder[0]; + ProtocolId =(SmppVersionType)remainder[1]; + PriorityFlag =(PriorityType)remainder[2]; + ScheduleDeliveryTime = SmppStringUtil.GetCStringFromBody(ref remainder, 3); + ValidityPeriod = SmppStringUtil.GetCStringFromBody(ref remainder); + RegisteredDelivery =(RegisteredDeliveryType)remainder[0]; + ReplaceIfPresentFlag =(remainder[1] == 0)? false : true; + DataCoding =(DataCodingType)remainder[2]; + SmDefaultMessageId = remainder[3]; + _SmLength = remainder[4]; + ShortMessage = SmppStringUtil.GetStringFromBody(ref remainder, 5, 5 + _SmLength); + + //fill the TLV table if applicable + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppSubmitSm.cs b/Packet/Request/SmppSubmitSm.cs new file mode 100644 index 0000000..f2cc333 --- /dev/null +++ b/Packet/Request/SmppSubmitSm.cs @@ -0,0 +1,346 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Defines an SMPP submit request. + /// + public class SmppSubmitSm : MessageLcd2 + { + #region private fields + + private TonType _DestinationAddressTon; + private NpiType _DestinationAddressNpi; + private string _DestinationAddress; + + #endregion private fields + + #region mandatory parameters + + /// + /// Type of Number for destination. + /// + public TonType DestinationAddressTon + { + get + { + return _DestinationAddressTon; + } + set + { + _DestinationAddressTon = value; + } + } + + /// + /// Numbering Plan Indicator for destination. + /// + public NpiType DestinationAddressNpi + { + get + { + return _DestinationAddressNpi; + } + set + { + _DestinationAddressNpi = value; + } + } + + /// + /// Destination address of this short message. Null values will be converted to an + /// empty string. + /// + public string DestinationAddress + { + get + { + return _DestinationAddress; + } + set + { + if(value != null) + { + if(value.ToString().Length <= ADDRESS_LENGTH) + { + _DestinationAddress = value; + } + else + { + throw new ArgumentOutOfRangeException( + "Destination Address too long(must be <= "+ ADDRESS_LENGTH + " 20 characters)."); + } + } + else + { + _DestinationAddress = string.Empty; + } + } + } + + #endregion mandatory parameters + + #region optional params + + /// + /// Indicates to the SMSC that there are further messages for the same destination. + /// + public bool MoreMessagesToSend + { + get + { + byte[] bytes = GetOptionalParamBytes((ushort)OptionalParamCodes.more_messages_to_send); + + return(bytes[0] == 0)? false : true; + } + + set + { + byte sendMore; + if(value == false) + { + sendMore =(byte)0x00; + } + else + { + sendMore =(byte)0x01; + } + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.more_messages_to_send, new Byte[] {sendMore}); + } + } + + /// + /// A response code set by the user in a User Acknowledgement/Reply message. The + /// response codes are application specific. From the SMPP spec: + /// + /// 0 to 255(IS-95 CDMA) + /// 0 to 15(CMT-136 TDMA) + /// + public byte UserResponseCode + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.user_response_code)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.user_response_code, new Byte[] {value}); + } + } + + /// + /// Used to indicate the number of messages stored in a mailbox. + /// + public byte NumberOfMessages + { + get + { + return GetOptionalParamBytes( + (ushort)OptionalParamCodes.number_of_messages)[0]; + } + + set + { + const int MAX_NUM_MSGS = 99; + + if(value <= MAX_NUM_MSGS) + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.number_of_messages, new Byte[] {value}); + } + else + { + throw new ArgumentException( + "number_of_messages must be between 0 and " + MAX_NUM_MSGS + "."); + } + } + } + + /// + /// From the SMPP spec: + /// The its_reply_type parameter is a required parameter for the CDMA Interactive + /// Teleservice as defined by the Korean PCS carriers [KORITS]. It indicates and + /// controls the MS users reply method to an SMS delivery message received from + /// the ESME. + /// + public ItsReplyTypeType ItsReplyType + { + get + { + return (ItsReplyTypeType)GetOptionalParamBytes( + (ushort)OptionalParamCodes.its_reply_type)[0]; + } + + set + { + SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.its_reply_type, new Byte[] {(byte)value}); + } + } + + /// + /// From the SMPP spec: + /// The its_session_info parameter is a required parameter for the CDMA Interactive + /// Teleservice as defined by the Korean PCS carriers [KORITS]. It contains control + /// information for the interactive session between an MS and an ESME. + /// + /// See section 5.3.2.43 of the SMPP spec for how to set this. + /// + public string ItsSessionInfo + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.its_session_info); + } + + set + { + PduUtil.SetItsSessionInfo(this, value); + } + } + + /// + /// From the SMPP spec: + /// The ussd_service_op parameter is required to define the USSD service operation + /// when SMPP is being used as an interface to a(GSM)USSD system. + /// + /// See 5.3.2.44 of the SMPP spec for how to set this. + /// + public string UssdServiceOp + { + get + { + return GetOptionalParamString((ushort)OptionalParamCodes.ussd_service_op); + } + + set + { + if(value == null) + { + SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.ussd_service_op, string.Empty); + } + else if(value.Length == 1) + { + SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.ussd_service_op, value); + } + else + { + throw new ArgumentException("ussd_service_op must have length 1"); + } + } + } + + #endregion optional params + + #region constructors + + /// + /// Creates a submit Pdu. Sets source address TON to international, + /// source address NPI to ISDN, source address to "", registered delivery type to none, + /// ESM class to 0, data coding to SMSC default, protocol ID to v3.4, priority to level 1, + /// validity period to default, replace if present to false, default message ID to 0, + /// the short message to an empty string, the destination address TON to international, + /// destination address NPI to ISDN, the destination address to "", the command status + /// to 0, and the Command ID to submit_sm. + /// + public SmppSubmitSm(): base() + { + } + + /// + /// Creates a new SmppSubmitSm for incoming PDUs. + /// + /// The incoming bytes to decode. + public SmppSubmitSm(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + DestinationAddressTon = Pdu.TonType.International; + DestinationAddressNpi = Pdu.NpiType.ISDN; + DestinationAddress = null; + CommandStatus = 0; + CommandID = CommandIdType.submit_sm; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(ServiceType))); + pdu.Add((byte)SourceAddressTon); + pdu.Add((byte)SourceAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SourceAddress))); + pdu.Add((byte)DestinationAddressTon); + pdu.Add((byte)DestinationAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(DestinationAddress))); + pdu.AddRange(GetBytesAfterDestination()); + + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the submit_sm Pdu. The Pdu has basically the same format as + /// the submit_sm Pdu, but in this case it is a response. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + ServiceType = SmppStringUtil.GetCStringFromBody(ref remainder); + SourceAddressTon =(TonType)remainder[0]; + SourceAddressNpi =(NpiType)remainder[1]; + SourceAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + DestinationAddressTon =(TonType)remainder[0]; + DestinationAddressNpi =(NpiType)remainder[1]; + DestinationAddress = SmppStringUtil.GetCStringFromBody(ref remainder, 2); + EsmClass = remainder[0]; + ProtocolId =(SmppVersionType)remainder[1]; + PriorityFlag =(PriorityType)remainder[2]; + ScheduleDeliveryTime = SmppStringUtil.GetCStringFromBody(ref remainder, 3); + ValidityPeriod = SmppStringUtil.GetCStringFromBody(ref remainder); + RegisteredDelivery =(RegisteredDeliveryType)remainder[0]; + ReplaceIfPresentFlag =(remainder[1] == 0)? false : true; + DataCoding =(DataCodingType)remainder[2]; + SmDefaultMessageId = remainder[3]; + _SmLength = remainder[4]; + ShortMessage = SmppStringUtil.GetStringFromBody(ref remainder, 5, 5 + _SmLength); + + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Request/SmppUnbind.cs b/Packet/Request/SmppUnbind.cs new file mode 100644 index 0000000..633bdd3 --- /dev/null +++ b/Packet/Request/SmppUnbind.cs @@ -0,0 +1,76 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Request +{ + /// + /// Class to issue an unbind request to the SMSC. + /// + public class SmppUnbind : Pdu + { + #region constructors + + /// + /// Creates an unbind PDU. + /// + public SmppUnbind(): base() + {} + + /// + /// Creates an unbind PDU. + /// + /// The bytes received from an ESME. + public SmppUnbind(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.unbind; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// This decodes the query_sm Pdu. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + + TranslateTlvDataIntoTable(remainder); + } + } +} diff --git a/Packet/Response/SmppBindResp.cs b/Packet/Response/SmppBindResp.cs new file mode 100644 index 0000000..753e758 --- /dev/null +++ b/Packet/Response/SmppBindResp.cs @@ -0,0 +1,124 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Text; +using System.Collections; +using RoaminSMPP; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Class to define an SMSC bind response. + /// + public class SmppBindResp : Pdu + { + private string _SystemId = string.Empty; + + /// + /// The ID of the SMSC. + /// + public string SystemId + { + get + { + return _SystemId; + } + + set + { + _SystemId = (value == null) ? string.Empty : value; + } + } + + /// + /// The SMPP version supported by SMSC. + /// + public string ScInterfaceVersion + { + get + { + return GetOptionalParamString((ushort) + Pdu.OptionalParamCodes.SC_interface_version); + } + + set + { + string version = value; + if(value == null) + { + version = string.Empty; + } + SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.SC_interface_version, version); + } + } + + #region constructors + + /// + /// Creates a bind response Pdu. + /// + /// The bytes received from an ESME. + public SmppBindResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a bind_resp. + /// + public SmppBindResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the bind response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + SystemId = SmppStringUtil.GetCStringFromBody(ref remainder); + //fill the TLV table if applicable + TranslateTlvDataIntoTable(remainder); + } + + /// + /// Initializes this Pdu for sending purposes. Note that this sets the bind type to + /// transceiver so you will want to change this if you are not dealing with a + /// transceiver. This also sets system type to an empty string. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.bind_transceiver_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(SystemId))); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppCancelSmResp.cs b/Packet/Response/SmppCancelSmResp.cs new file mode 100644 index 0000000..a1ab132 --- /dev/null +++ b/Packet/Response/SmppCancelSmResp.cs @@ -0,0 +1,75 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Response Pdu for the cancel_sm command. + /// + public class SmppCancelSmResp : Pdu + { + #region constructors + + /// + /// Creates a cancel_sm Pdu. + /// + /// The bytes received from an ESME. + public SmppCancelSmResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a cancel_sm Pdu. + /// + public SmppCancelSmResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the cancel_sm response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + TranslateTlvDataIntoTable(BytesAfterHeader); + } + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.cancel_sm_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppDataSmResp.cs b/Packet/Response/SmppDataSmResp.cs new file mode 100644 index 0000000..6365674 --- /dev/null +++ b/Packet/Response/SmppDataSmResp.cs @@ -0,0 +1,189 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using System.Text; +using RoaminSMPP.Utility; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Response Pdu for the data_sm command. + /// + public class SmppDataSmResp : SmppSubmitSmResp + { + /// + /// Enumerates the delivery failure types. + /// + public enum DeliveryFailureType : byte + { + /// + /// DestinationUnavailable + /// + DestinationUnavailable = 0x00, + /// + /// DestinationAddressInvalid + /// + DestinationAddressInvalid = 0x01, + /// + /// PermanentNetworkError + /// + PermanentNetworkError = 0x02, + /// + /// TemporaryNetworkError + /// + TemporaryNetworkError = 0x03 + } + + #region optional parameters + + /// + /// Indicates the reason for delivery failure. + /// + public DeliveryFailureType DeliveryFailureReason + { + get + { + return(DeliveryFailureType) + GetOptionalParamBytes((ushort) + Pdu.OptionalParamCodes.delivery_failure_reason)[0]; + } + + set + { + SetOptionalParamBytes( + (UInt16)Pdu.OptionalParamCodes.delivery_failure_reason, + BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering((byte)value))); + } + } + + /// + /// Error code specific to a wireless network. See SMPP spec section + /// 5.3.2.31 for details. + /// + public string NetworkErrorCode + { + get + { + return GetOptionalParamString((ushort) + Pdu.OptionalParamCodes.network_error_code); + } + + set + { + PduUtil.SetNetworkErrorCode(this, value); + } + } + + /// + /// Text(ASCII)giving additional info on the meaning of the response. + /// + public string AdditionalStatusInfoText + { + get + { + return GetOptionalParamString((ushort) + Pdu.OptionalParamCodes.additional_status_info_text); + } + + set + { + const int MAX_STATUS_LEN = 264; + if(value == null) + { + SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.additional_status_info_text, string.Empty); + } + else if(value.Length <= MAX_STATUS_LEN) + { + SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.additional_status_info_text, value); + } + else + { + throw new ArgumentException( + "additional_status_info_text must have length <= " + MAX_STATUS_LEN); + } + } + } + + /// + /// Indicates whether the Delivery Pending Flag was set. + /// + public DpfResultType DpfResult + { + get + { + return(DpfResultType) + GetOptionalParamBytes((ushort) + Pdu.OptionalParamCodes.dpf_result)[0]; + } + + set + { + SetOptionalParamBytes( + (UInt16)Pdu.OptionalParamCodes.dpf_result, + BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering((byte)value))); + } + } + + #endregion optional parameters + + #region constructors + + /// + /// Creates a data_sm_resp Pdu. + /// + public SmppDataSmResp(): base() + {} + + /// + /// Creates a data_sm_resp Pdu. + /// + /// The bytes received from an ESME. + public SmppDataSmResp(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.data_sm_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(MessageId))); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppDeliverSmResp.cs b/Packet/Response/SmppDeliverSmResp.cs new file mode 100644 index 0000000..3854c36 --- /dev/null +++ b/Packet/Response/SmppDeliverSmResp.cs @@ -0,0 +1,78 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// This class defines an ESME originated deliver_sm_resp. + /// + public class SmppDeliverSmResp : Pdu + { + #region constructors + + /// + /// Creates a deliver_sm_resp Pdu. Sets command status and command ID. + /// + public SmppDeliverSmResp(): base() + {} + + /// + /// Creates a deliver_sm_resp Pdu. Sets command status and command ID. + /// + /// The incoming bytes from the ESME. + public SmppDeliverSmResp(byte[] incomingBytes): base(incomingBytes) + {} + + #endregion constructors + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.deliver_sm_resp; + } + + /// + /// Creates the byte encoding for this Pdu. + /// + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + //the message_id is unused and is always set to null + pdu.Add((byte)0x00); + PacketBytes = EncodePduForTransmission(pdu); + } + + /// + /// Decodes the deliver_sm response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + + //fill the TLV table if applicable + TranslateTlvDataIntoTable(remainder, 1); + } + } +} diff --git a/Packet/Response/SmppEnquireLinkResp.cs b/Packet/Response/SmppEnquireLinkResp.cs new file mode 100644 index 0000000..77ddbaa --- /dev/null +++ b/Packet/Response/SmppEnquireLinkResp.cs @@ -0,0 +1,75 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Defines the response Pdu from an enquire_link. + /// + public class SmppEnquireLinkResp : Pdu + { + #region constructors + + /// + /// Creates an enquire_link Pdu. + /// + /// The bytes received from an ESME. + public SmppEnquireLinkResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates an enquire_link Pdu. + /// + public SmppEnquireLinkResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the enquire_link response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + TranslateTlvDataIntoTable(BytesAfterHeader); + } + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.enquire_link_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppGenericNackResp.cs b/Packet/Response/SmppGenericNackResp.cs new file mode 100644 index 0000000..22236c8 --- /dev/null +++ b/Packet/Response/SmppGenericNackResp.cs @@ -0,0 +1,78 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Represents a generic NACK sent by the SMSC. + /// + public class SmppGenericNackResp : Pdu + { + #region constructors + + /// + /// Creates a generic_nack response Pdu. + /// + /// The bytes received from an ESME. + public SmppGenericNackResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a generic_nack response Pdu. + /// + public SmppGenericNackResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the generic NACK response from the SMSC. Since a generic + /// NACK response contains essentially nothing other than the header, + /// this method does nothing special. It will grab any TLVs that are in + /// the Pdu, however. + /// + protected override void DecodeSmscResponse() + { + TranslateTlvDataIntoTable(BytesAfterHeader); + } + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.generic_nack; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppQuerySmResp.cs b/Packet/Response/SmppQuerySmResp.cs new file mode 100644 index 0000000..00a401d --- /dev/null +++ b/Packet/Response/SmppQuerySmResp.cs @@ -0,0 +1,175 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using System.Text; +using RoaminSMPP.Packet; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// This class defines the response to a query_sm Pdu. + /// + public class SmppQuerySmResp : Pdu + { + private string _MessageId = string.Empty; + private string _FinalDate = string.Empty; + private MessageStateType _MessageStatus = MessageStateType.Enroute; + private byte _ErrorCode = 0; + + #region mandatory parameters + + /// + /// SMSC Message ID of the message whose state is being queried. + /// + public string MessageId + { + get + { + return _MessageId; + } + + set + { + _MessageId = (value == null) ? string.Empty : value; + } + } + + /// + /// Date and time when the queried message reached a final state. For messages + /// which have not yet reached a final state this field will be null. + /// + public string FinalDate + { + get + { + return _FinalDate; + } + + set + { + if(value != null && value != string.Empty) + { + if(value.Length == DATE_TIME_LENGTH) + { + _FinalDate = value; + } + else + { + throw new ArgumentException("Final date is not in the correct format."); + } + } + else + { + _FinalDate = string.Empty; + } + } + } + + /// + /// Specifies the status of the queried short message. + /// + public MessageStateType MessageStatus + { + get + { + return _MessageStatus; + } + + set + { + _MessageStatus = value; + } + } + + /// + /// Holds a network error code defining the reason for failure of message delivery. + /// + public byte ErrorCode + { + get + { + return _ErrorCode; + } + + set + { + _ErrorCode = value; + } + } + + #endregion mandatory parameters + + #region constructors + + /// + /// Creates a query_sm response. + /// + /// The bytes received from an ESME. + public SmppQuerySmResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a query_sm response. + /// + public SmppQuerySmResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the query_sm response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + byte[] remainder = BytesAfterHeader; + MessageId = SmppStringUtil.GetCStringFromBody(ref remainder); + FinalDate = SmppStringUtil.GetCStringFromBody(ref remainder); + MessageStatus = (MessageStateType)remainder[0]; + ErrorCode = remainder[1]; + //fill the TLV table if applicable + TranslateTlvDataIntoTable(remainder, 2); + } + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.query_sm_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(MessageId))); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(FinalDate))); + pdu.Add((byte)MessageStatus); + pdu.Add(ErrorCode); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppReplaceSmResp.cs b/Packet/Response/SmppReplaceSmResp.cs new file mode 100644 index 0000000..4290b03 --- /dev/null +++ b/Packet/Response/SmppReplaceSmResp.cs @@ -0,0 +1,75 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Defines the replace_sm_resp Pdu. + /// + public class SmppReplaceSmResp : Pdu + { + #region constructors + + /// + /// Creates a replace_sm response Pdu. + /// + /// The bytes received from an ESME. + public SmppReplaceSmResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a replace_sm response Pdu. + /// + public SmppReplaceSmResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the replace_sm response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + TranslateTlvDataIntoTable(BytesAfterHeader); + } + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.replace_sm_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppSubmitMultiResp.cs b/Packet/Response/SmppSubmitMultiResp.cs new file mode 100644 index 0000000..9b4331e --- /dev/null +++ b/Packet/Response/SmppSubmitMultiResp.cs @@ -0,0 +1,145 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using System.Text; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Description of SmppSubmitMultiResp. + /// + public class SmppSubmitMultiResp : SmppSubmitSmResp + { + private byte _NumberUnsuccessful = 0; + private UnsuccessAddress[] _UnsuccessfulAddresses = new UnsuccessAddress[0]; + + /// + /// The number of messages that could not be delivered. The mutator is not + /// provided as setting the unsucess addresses will set it. + /// + public byte NumberUnsuccessful + { + get + { + return _NumberUnsuccessful; + } + } + + /// + /// The array of unsuccessful addresses. This will set the number of addresses as well. + /// Passing in null will set them to zero. Calling the accessor will get you a cloned array. + /// You must use the set accessor to modify the values. + /// + public UnsuccessAddress[] UnsuccessfulAddresses + { + get + { + return(UnsuccessAddress[])_UnsuccessfulAddresses.Clone(); + } + + set + { + _UnsuccessfulAddresses = (value == null) ? new UnsuccessAddress[0] : value; + _NumberUnsuccessful = (byte)_UnsuccessfulAddresses.Length; + } + } + + #region constructors + + /// + /// Creates a submit_multi response Pdu. + /// + /// The bytes received from an ESME. + public SmppSubmitMultiResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a submit_multi response Pdu. + /// + public SmppSubmitMultiResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the submit_multi response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + DecodeNonTlv(); + + byte[] remainder = base.ResponseAfterMsgId; + //the SMSC might not send back the number of unsuccessful messages, + //so check if it did + if(remainder.Length > 0) + { + _NumberUnsuccessful = remainder[0]; + UnsuccessfulAddresses = new UnsuccessAddress[NumberUnsuccessful]; + long length = remainder.Length - 1; + byte[] newRemainder = new byte[length]; + Array.Copy(remainder, 1, newRemainder, 0, length); + remainder = newRemainder; + newRemainder = null; + //unsuccessful + for(int i = 0; i < UnsuccessfulAddresses.Length; i++) + { + _UnsuccessfulAddresses[i] = new UnsuccessAddress(ref remainder); + } + } + + //fill the TLV table if applicable + TranslateTlvDataIntoTable(remainder); + } + + /// + /// Initializes this Pdu. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.submit_multi_resp; + } + + /// + /// Creates the byte encoding for this Pdu. + /// + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(MessageId))); + pdu.Add(NumberUnsuccessful); + //add the unsuccess addresses + UnsuccessAddress[] unsuccessfulAddresses = UnsuccessfulAddresses; + + for(int i = 0; i < NumberUnsuccessful; i++) + { + pdu.Add((byte)unsuccessfulAddresses[i].DestinationAddressTon); + pdu.Add((byte)unsuccessfulAddresses[i].DestinationAddressNpi); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull( + Encoding.ASCII.GetBytes(unsuccessfulAddresses[i].DestinationAddress))); + pdu.AddRange(BitConverter.GetBytes( + UnsignedNumConverter.SwapByteOrdering(unsuccessfulAddresses[i].ErrorStatusCode))); + } +// + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppSubmitSmResp.cs b/Packet/Response/SmppSubmitSmResp.cs new file mode 100644 index 0000000..4ce4db6 --- /dev/null +++ b/Packet/Response/SmppSubmitSmResp.cs @@ -0,0 +1,123 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using System.Text; +using RoaminSMPP.Utility; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Defines the submit_sm response from the SMSC. + /// + public class SmppSubmitSmResp : Pdu + { + private string _MessageId = string.Empty; + private byte[] _ResponseAfterMsgId; + + /// + /// The message ID(SMSC-assigned)of the submitted message. + /// + public string MessageId + { + get + { + return _MessageId; + } + + set + { + _MessageId = (value == null) ? string.Empty : value; + } + } + + /// + /// Accessor for the submit_multi to get at the response after the message ID. + /// This is, in essence, set only after DecodeSmscResponse()in this base class + /// is called. + /// + protected byte[] ResponseAfterMsgId + { + get + { + return _ResponseAfterMsgId; + } + } + + #region constructors + + /// + /// Creates a submit_sm response Pdu. + /// + /// The bytes received from an ESME. + public SmppSubmitSmResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates a submit_sm_resp + /// + public SmppSubmitSmResp(): base() + { + } + + #endregion constructors + + /// + /// Decodes the submit response from the SMSC. + /// + protected override void DecodeSmscResponse() + { + DecodeNonTlv(); + //fill the TLV table if applicable + TranslateTlvDataIntoTable(_ResponseAfterMsgId); + } + + /// + /// Decodes the non-TLV bytes. Needed for the submit_multi_resp. + /// + protected void DecodeNonTlv() + { + //header + byte[] remainder = BytesAfterHeader; + MessageId = SmppStringUtil.GetCStringFromBody(ref remainder); + _ResponseAfterMsgId = remainder; + } + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.submit_sm_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + pdu.AddRange(SmppStringUtil.ArrayCopyWithNull(Encoding.ASCII.GetBytes(MessageId))); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/Packet/Response/SmppUnbindResp.cs b/Packet/Response/SmppUnbindResp.cs new file mode 100644 index 0000000..4a6015d --- /dev/null +++ b/Packet/Response/SmppUnbindResp.cs @@ -0,0 +1,77 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; + +namespace RoaminSMPP.Packet.Response +{ + /// + /// Defines the unbind response from the SMSC. + /// + public class SmppUnbindResp : Pdu + { + #region constructors + + /// + /// Creates an unbind response Pdu. + /// + /// The bytes received from an ESME. + public SmppUnbindResp(byte[] incomingBytes): base(incomingBytes) + {} + + /// + /// Creates an unbind response Pdu. + /// + public SmppUnbindResp(): base() + {} + + #endregion constructors + + /// + /// Decodes the unbind response from the SMSC. Since an unbind response contains + /// essentially nothing other than the header, this method does nothing special. + /// It will grab any TLVs that are in the Pdu, however. + /// + protected override void DecodeSmscResponse() + { + //fill the TLV table if applicable + TranslateTlvDataIntoTable(BytesAfterHeader); + } + + /// + /// Initializes this Pdu for sending purposes. + /// + protected override void InitPdu() + { + base.InitPdu(); + CommandStatus = 0; + CommandID = CommandIdType.unbind_resp; + } + + /// + /// Gets the hex encoding(big-endian)of this Pdu. + /// + ///The hex-encoded version of the Pdu + public override void ToMsbHexEncoding() + { + ArrayList pdu = GetPduHeader(); + + PacketBytes = EncodePduForTransmission(pdu); + } + } +} diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..5217f78 --- /dev/null +++ b/README.TXT @@ -0,0 +1,12 @@ +This software is meant to provide an open source edition of the basic +SMPP v3.4 functionality. It includes PDU definitions for all of the +PDUs in the spec. + +I will no longer be adding functionality to this app; I may or may not fix bugs. If you find a +bug and want it fixed, BE NICE! I don't like people who make demands on my (not so free) time. + +Please read the enclosed license files, COPYING (GNU GPL) and COPYING.LESSER (GNU LGPL) for more details. + +Thanks! + +-Chris Bouzek diff --git a/RoaminSMPP.cmbx b/RoaminSMPP.cmbx new file mode 100644 index 0000000..d4c6284 --- /dev/null +++ b/RoaminSMPP.cmbx @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RoaminSMPP.mdsx b/RoaminSMPP.mdsx new file mode 100644 index 0000000..0bb9bbf --- /dev/null +++ b/RoaminSMPP.mdsx @@ -0,0 +1,3 @@ + + ./build/bin + \ No newline at end of file diff --git a/RoaminSMPP.pidb b/RoaminSMPP.pidb new file mode 100644 index 0000000..bf53c53 Binary files /dev/null and b/RoaminSMPP.pidb differ diff --git a/RoaminSMPP.prjx b/RoaminSMPP.prjx new file mode 100644 index 0000000..2ba3426 --- /dev/null +++ b/RoaminSMPP.prjx @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SMPPCommunicator.cs b/SMPPCommunicator.cs new file mode 100644 index 0000000..56ca12e --- /dev/null +++ b/SMPPCommunicator.cs @@ -0,0 +1,1052 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Net.Sockets; +using System.Collections; +using System.Threading; +using RoaminSMPP.Packet.Request; +using RoaminSMPP.Utility; +using RoaminSMPP.Packet.Response; +using RoaminSMPP.Packet; +using RoaminSMPP.EventObjects; +using System.Timers; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace RoaminSMPP +{ + /// + /// Wrapper class to provide asynchronous I/O for the RoaminSMPP library. Note that most + /// SMPP events have default handlers. If the events are overridden by the caller by adding + /// event handlers, it is the caller's responsibility to ensure that the proper response is + /// sent. For example: there is a default deliver_sm_resp implemented. If you "listen" to + /// the deliver_sm event, it is your responsibility to then send the deliver_sm_resp packet. + /// + public class SMPPCommunicator : Component + { + private AsyncSocketClient asClient; + private Int16 _Port; + private SmppBind.BindingType _BindType; + private string _Host; + private Pdu.NpiType _NpiType; + private Pdu.TonType _TonType; + private SmppBind.SmppVersionType _Version; + private string _AddressRange; + private string _Password; + private string _SystemId; + private string _SystemType; + private System.Timers.Timer timer; + private int _EnquireLinkInterval; + private int _SleepTimeAfterSocketFailure; + private bool _SentUnbindPacket = true; //default to true since we start out unbound + private string username; + + /// + /// Required designer variable. + /// + protected Container components = null; + + #region properties + + /// + /// The username to use for software validation. + /// + public string Username + { + set + { + username = value; + } + } + + /// + /// Accessor to determine if we have sent the unbind packet out. Once the packet is + /// sent, you can consider this object to be unbound. + /// + public bool SentUnbindPacket + { + get + { + return _SentUnbindPacket; + } + } + + /// + /// The port on the SMSC to connect to. + /// + public Int16 Port + { + get + { + return _Port; + } + set + { + _Port = value; + } + } + + /// + /// The binding type(receiver, transmitter, or transceiver)to use + /// when connecting to the SMSC. + /// + public SmppBind.BindingType BindType + { + get + { + return _BindType; + } + set + { + _BindType = value; + } + + } + /// + /// The system type to use when connecting to the SMSC. + /// + public string SystemType + { + get + { + return _SystemType; + } + set + { + _SystemType = value; + } + } + /// + /// The system ID to use when connecting to the SMSC. This is, + /// in essence, a user name. + /// + public string SystemId + { + get + { + return _SystemId; + } + set + { + _SystemId = value; + } + } + /// + /// The password to use when connecting to an SMSC. + /// + public string Password + { + get + { + return _Password; + } + set + { + _Password = value; + } + } + + /// + /// The host to bind this SMPPCommunicator to. + /// + public string Host + { + get + { + return _Host; + } + set + { + _Host = value; + } + } + /// + /// The number plan indicator that this SMPPCommunicator should use. + /// + public Pdu.NpiType NpiType + { + get + { + return _NpiType; + } + set + { + _NpiType = value; + } + } + + /// + /// The type of number that this SMPPCommunicator should use. + /// + public Pdu.TonType TonType + { + get + { + return _TonType; + } + set + { + _TonType = value; + } + } + + /// + /// The SMPP specification version to use. + /// + public SmppBind.SmppVersionType Version + { + get + { + return _Version; + } + set + { + _Version = value; + } + } + + /// + /// The address range of this SMPPCommunicator. + /// + public string AddressRange + { + get + { + return _AddressRange; + } + set + { + _AddressRange = value; + } + } + + /// + /// Set to the number of seconds that should elapse in between enquire_link + /// packets. Setting this to anything other than 0 will enable the timer, setting + /// it to 0 will disable the timer. Note that the timer is only started/stopped + /// during a bind/unbind. Negative values are ignored. + /// + public int EnquireLinkInterval + { + get + { + return _EnquireLinkInterval; + } + + set + { + if(value >= 0) + _EnquireLinkInterval = value; + } + } + + /// + /// Sets the number of seconds that the system will wait before trying to rebind + /// after a total network failure(due to cable problems, etc). Negative values are + /// ignored. + /// + public int SleepTimeAfterSocketFailure + { + get + { + return _SleepTimeAfterSocketFailure; + } + + set + { + if(value >= 0) + _SleepTimeAfterSocketFailure = value; + } + } + #endregion properties + + #region events + /// + /// Event called when the communicator receives a bind response. + /// + public event BindRespEventHandler OnBindResp; + /// + /// Event called when an error occurs. + /// + public event ErrorEventHandler OnError; + /// + /// Event called when the communicator is unbound. + /// + public event UnbindRespEventHandler OnUnboundResp; + /// + /// Event called when the connection is closed. + /// + public event ClosingEventHandler OnClose; + /// + /// Event called when an alert_notification comes in. + /// + public event AlertEventHandler OnAlert; + /// + /// Event called when a submit_sm_resp is received. + /// + public event SubmitSmRespEventHandler OnSubmitSmResp; + /// + /// Event called when a response to an enquire_link_resp is received. + /// + public event EnquireLinkRespEventHandler OnEnquireLinkResp; + /// + /// Event called when a submit_sm is received. + /// + public event SubmitSmEventHandler OnSubmitSm; + /// + /// Event called when a query_sm is received. + /// + public event QuerySmEventHandler OnQuerySm; + /// + /// Event called when a generic_nack is received. + /// + public event GenericNackEventHandler OnGenericNack; + /// + /// Event called when an enquire_link is received. + /// + public event EnquireLinkEventHandler OnEnquireLink; + /// + /// Event called when an unbind is received. + /// + public event UnbindEventHandler OnUnbind; + /// + /// Event called when the communicator receives a request for a bind. + /// + public event BindEventHandler OnBind; + /// + /// Event called when the communicator receives a cancel_sm. + /// + public event CancelSmEventHandler OnCancelSm; + /// + /// Event called when the communicator receives a cancel_sm_resp. + /// + public event CancelSmRespEventHandler OnCancelSmResp; + /// + /// Event called when the communicator receives a query_sm_resp. + /// + public event QuerySmRespEventHandler OnQuerySmResp; + /// + /// Event called when the communicator receives a data_sm. + /// + public event DataSmEventHandler OnDataSm; + /// + /// Event called when the communicator receives a data_sm_resp. + /// + public event DataSmRespEventHandler OnDataSmResp; + /// + /// Event called when the communicator receives a deliver_sm. + /// + public event DeliverSmEventHandler OnDeliverSm; + /// + /// Event called when the communicator receives a deliver_sm_resp. + /// + public event DeliverSmRespEventHandler OnDeliverSmResp; + /// + /// Event called when the communicator receives a replace_sm. + /// + public event ReplaceSmEventHandler OnReplaceSm; + /// + /// Event called when the communicator receives a replace_sm_resp. + /// + public event ReplaceSmRespEventHandler OnReplaceSmResp; + /// + /// Event called when the communicator receives a submit_multi. + /// + public event SubmitMultiEventHandler OnSubmitMulti; + /// + /// Event called when the communicator receives a submit_multi_resp. + /// + public event SubmitMultiRespEventHandler OnSubmitMultiResp; + #endregion events + + #region delegates + + /// + /// Delegate to handle binding responses of the communicator. + /// + public delegate void BindRespEventHandler(object source, BindRespEventArgs e); + /// + /// Delegate to handle any errors that come up. + /// + public delegate void ErrorEventHandler(object source, CommonErrorEventArgs e); + /// + /// Delegate to handle the unbind_resp. + /// + public delegate void UnbindRespEventHandler(object source, UnbindRespEventArgs e); + /// + /// Delegate to handle closing of the connection. + /// + public delegate void ClosingEventHandler(object source, EventArgs e); + /// + /// Delegate to handle alert_notification events. + /// + public delegate void AlertEventHandler(object source, AlertEventArgs e); + /// + /// Delegate to handle a submit_sm_resp + /// + public delegate void SubmitSmRespEventHandler(object source, SubmitSmRespEventArgs e); + /// + /// Delegate to handle the enquire_link response. + /// + public delegate void EnquireLinkRespEventHandler(object source, EnquireLinkRespEventArgs e); + /// + /// Delegate to handle the submit_sm. + /// + public delegate void SubmitSmEventHandler(object source, SubmitSmEventArgs e); + /// + /// Delegate to handle the query_sm. + /// + public delegate void QuerySmEventHandler(object source, QuerySmEventArgs e); + /// + /// Delegate to handle generic_nack. + /// + public delegate void GenericNackEventHandler(object source, GenericNackEventArgs e); + /// + /// Delegate to handle the enquire_link. + /// + public delegate void EnquireLinkEventHandler(object source, EnquireLinkEventArgs e); + /// + /// Delegate to handle the unbind message. + /// + public delegate void UnbindEventHandler(object source, UnbindEventArgs e); + /// + /// Delegate to handle requests for binding of the communicator. + /// + public delegate void BindEventHandler(object source, BindEventArgs e); + /// + /// Delegate to handle cancel_sm. + /// + public delegate void CancelSmEventHandler(object source, CancelSmEventArgs e); + /// + /// Delegate to handle cancel_sm_resp. + /// + public delegate void CancelSmRespEventHandler(object source, CancelSmRespEventArgs e); + /// + /// Delegate to handle query_sm_resp. + /// + public delegate void QuerySmRespEventHandler(object source, QuerySmRespEventArgs e); + /// + /// Delegate to handle data_sm. + /// + public delegate void DataSmEventHandler(object source, DataSmEventArgs e); + /// + /// Delegate to handle data_sm_resp. + /// + public delegate void DataSmRespEventHandler(object source, DataSmRespEventArgs e); + /// + /// Delegate to handle deliver_sm. + /// + public delegate void DeliverSmEventHandler(object source, DeliverSmEventArgs e); + /// + /// Delegate to handle deliver_sm_resp. + /// + public delegate void DeliverSmRespEventHandler(object source, DeliverSmRespEventArgs e); + /// + /// Delegate to handle replace_sm. + /// + public delegate void ReplaceSmEventHandler(object source, ReplaceSmEventArgs e); + /// + /// Delegate to handle replace_sm_resp. + /// + public delegate void ReplaceSmRespEventHandler(object source, ReplaceSmRespEventArgs e); + /// + /// Delegate to handle submit_multi. + /// + public delegate void SubmitMultiEventHandler(object source, SubmitMultiEventArgs e); + /// + /// Delegate to handle submit_multi_resp. + /// + public delegate void SubmitMultiRespEventHandler(object source, SubmitMultiRespEventArgs e); + + #endregion delegates + + #region constructors + + /// + /// Creates a default SMPPCommunicator, with port 9999, bindtype set to + /// transceiver, host set to localhost, NPI type set to ISDN, TON type + /// set to International, version set to 3.4, enquire link interval set + /// to 0(disabled), sleep time after socket failure set to 10 seconds, + /// and address range, password, system type and system ID set to null + ///(no value). + /// + /// The container that will hold this + /// component. + public SMPPCommunicator(IContainer container) + { + // Required for Windows.Forms Class Composition Designer support + InitCommunicator(); + container.Add(this); + InitializeComponent(); + } + + /// + /// Creates a default SMPPCommunicator, with port 9999, bindtype set to + /// transceiver, host set to localhost, NPI type set to ISDN, TON type + /// set to International, version set to 3.4, enquire link interval set + /// to 0(disabled), sleep time after socket failure set to 10 seconds, + /// and address range, password, system type and system ID set to null + ///(no value). + /// + public SMPPCommunicator() + { + InitCommunicator(); + + InitializeComponent(); + } + + #endregion constructors + + + private void delTest() { + + } + /// + /// Sends a user-specified Pdu(see the RoaminSMPP base library for + /// Pdu types). This allows complete flexibility for sending Pdus. + /// + /// The Pdu to send. + public void SendPdu(Pdu packet) + { + bool sendFailed = true; + + while(sendFailed) + { + try + { + packet.ToMsbHexEncoding(); + asClient.Send(packet.PacketBytes); + sendFailed = false; + } + catch(Exception exc) + { + if(OnError != null) + { + OnError(this, new CommonErrorEventArgs(exc)); + } + + //try to stay alive + if((exc.Message.ToLower().IndexOf("socket is closed")>= 0 || + exc.Message.ToLower().IndexOf("unable to write data to the transport connection")>= 0)) + { + System.Threading.Thread.Sleep(SleepTimeAfterSocketFailure * 1000); + Bind(); + } + else + { + //don't know what happened, but kick out + sendFailed = false; + } + } + } + } + + /// + /// Connects and binds the SMPPCommunicator to the SMSC, using the + /// values that have been set in the constructor and through the + /// properties. This will also start the timer that sends enquire_link packets + /// at regular intervals, if it has been enabled. + /// + public void Bind() + { + try + { + if(asClient != null) + asClient.Disconnect(); + } + catch + { + //drop it on the floor + } + + //connect + try + { + asClient = new AsyncSocketClient(10240, null, + new AsyncSocketClient.MessageHandler(ClientMessageHandler), + new AsyncSocketClient.SocketClosingHandler(ClientCloseHandler), + new AsyncSocketClient.ErrorHandler(ClientErrorHandler)); + + asClient.Connect(Host, Port); + + SmppBind request = new SmppBind(); + request.SystemId = SystemId; + request.Password = Password; + request.SystemType = SystemType; + request.InterfaceVersion = Version; + request.AddressTon = TonType; + request.AddressNpi = NpiType; + request.AddressRange = AddressRange; + request.BindType = BindType; + + SendPdu(request); + _SentUnbindPacket = false; + + if(_EnquireLinkInterval > 0) + { + if(timer == null) + { + timer = new System.Timers.Timer(); + timer.Elapsed += new ElapsedEventHandler(TimerElapsed); + } + + if(timer != null) //reset the old timer + { + timer.Stop(); + + timer.Interval = EnquireLinkInterval * 1000; + timer.Start(); + } + } + } + catch(Exception exc) + { + if(OnError != null) + { + OnError(this, new CommonErrorEventArgs(exc)); + } + } + } + + /// + /// Unbinds the SMPPCommunicator from the SMSC then disconnects the socket + /// when it receives the unbind response from the SMSC. This will also stop the + /// timer that sends out the enquire_link packets if it has been enabled. You need to + /// explicitly call this to unbind.; it will not be done for you. + /// + public void Unbind() + { + if(timer != null) + timer.Stop(); + + if(!_SentUnbindPacket) + { + SmppUnbind request = new SmppUnbind(); + SendPdu(request); + _SentUnbindPacket = true; + } + } + + #region internal methods + /// + /// Callback method to handle received messages. The AsyncSocketClient + /// library calls this; don't call it yourself. + /// + /// The client to receive messages from. + internal void ClientMessageHandler(AsyncSocketClient client) + { + try + { + Queue responseQueue = new PduFactory().GetPduQueue(client.Buffer); + ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessPduQueue), responseQueue); + } + catch(Exception exception) + { + if(OnError != null) + { + CommonErrorEventArgs e = new CommonErrorEventArgs(exception); + OnError(this, e); + } + } + } + + /// + /// Callback method to handle socket closing. + /// + /// The client to receive messages from. + internal void ClientCloseHandler(AsyncSocketClient client) + { + //fire off a closing event + if(OnClose != null) + { + System.EventArgs e = new System.EventArgs(); + OnClose(this, e); + } + } + + /// + /// Callback method to handle errors. + /// + /// The client to receive messages from. + /// The generated exception. + internal void ClientErrorHandler(AsyncSocketClient client, + Exception exception) + { + //fire off an error handler + if(OnError != null) + { + CommonErrorEventArgs e = new CommonErrorEventArgs(exception); + OnError(this, e); + } + } + #endregion internal methods + + #region private methods + + /// + /// Goes through the packets in the queue and fires events for them. Called by the + /// threads in the ThreadPool. + /// + /// The queue of byte packets. + private void ProcessPduQueue(object queueStateObj) + { + Queue responseQueue = queueStateObj as Queue; + + foreach(Pdu response in responseQueue) + { + //based on each Pdu, fire off an event + if(response != null) + FireEvents(response); + } + } + + /// + /// Sends out an enquire_link packet. + /// + /// + /// + private void TimerElapsed(object sender, ElapsedEventArgs ea) + { + SendPdu(new SmppEnquireLink()); + } + + /// + /// Fires an event off based on what Pdu is sent in. + /// + /// The response to fire an event for. + private void FireEvents(Pdu response) + { + //here we go... + if(response is SmppBindResp) + { + if(OnBindResp != null) + { + OnBindResp(this, new BindRespEventArgs((SmppBindResp)response)); + } + } + else if(response is SmppUnbindResp) + { + //disconnect + asClient.Disconnect(); + if(OnUnboundResp != null) + { + OnUnboundResp(this, new UnbindRespEventArgs((SmppUnbindResp)response)); + } + } + else if(response is SmppAlertNotification) + { + if(OnAlert != null) + { + OnAlert(this, new AlertEventArgs((SmppAlertNotification)response)); + } + } + else if(response is SmppSubmitSmResp) + { + if(OnSubmitSmResp != null) + { + OnSubmitSmResp(this, + new SubmitSmRespEventArgs((SmppSubmitSmResp)response)); + } + } + else if(response is SmppEnquireLinkResp) + { + if(OnEnquireLinkResp != null) + { + OnEnquireLinkResp(this, new EnquireLinkRespEventArgs((SmppEnquireLinkResp)response)); + } + } + else if(response is SmppSubmitSm) + { + if(OnSubmitSm != null) + { + OnSubmitSm(this, new SubmitSmEventArgs((SmppSubmitSm)response)); + } + else + { + //default a response + SmppSubmitSmResp pdu = new SmppSubmitSmResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.MessageId = System.Guid.NewGuid().ToString().Substring(0, 10); + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + } + else if(response is SmppQuerySm) + { + if(OnQuerySm != null) + { + OnQuerySm(this, new QuerySmEventArgs((SmppQuerySm)response)); + } + else + { + //default a response + SmppQuerySmResp pdu = new SmppQuerySmResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + } + else if(response is SmppGenericNack) + { + if(OnGenericNack != null) + { + OnGenericNack(this, new GenericNackEventArgs((SmppGenericNack)response)); + } + } + else if(response is SmppEnquireLink) + { + if(OnEnquireLink != null) + { + OnEnquireLink(this, new EnquireLinkEventArgs((SmppEnquireLink)response)); + } + + //send a response back + SmppEnquireLinkResp pdu = new SmppEnquireLinkResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + else if(response is SmppUnbind) + { + if(OnUnbind != null) + { + OnUnbind(this, new UnbindEventArgs((SmppUnbind)response)); + } + else + { + //default a response + SmppUnbindResp pdu = new SmppUnbindResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + } + else if(response is SmppBind) + { + if(OnBind != null) + { + OnBind(this, new BindEventArgs((SmppBind)response)); + } + else + { + //default a response + SmppBindResp pdu = new SmppBindResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + pdu.SystemId = "Generic"; + + SendPdu(pdu); + } + } + else if(response is SmppCancelSm) + { + if(OnCancelSm != null) + { + OnCancelSm(this, new CancelSmEventArgs((SmppCancelSm)response)); + } + else + { + //default a response + SmppCancelSmResp pdu = new SmppCancelSmResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + } + else if(response is SmppCancelSmResp) + { + if(OnCancelSmResp != null) + { + OnCancelSmResp(this, new CancelSmRespEventArgs((SmppCancelSmResp)response)); + } + } + else if(response is SmppCancelSmResp) + { + if(OnCancelSmResp != null) + { + OnCancelSmResp(this, new CancelSmRespEventArgs((SmppCancelSmResp)response)); + } + } + else if(response is SmppQuerySmResp) + { + if(OnQuerySmResp != null) + { + OnQuerySmResp(this, new QuerySmRespEventArgs((SmppQuerySmResp)response)); + } + } + else if(response is SmppDataSm) + { + if(OnDataSm != null) + { + OnDataSm(this, new DataSmEventArgs((SmppDataSm)response)); + } + else + { + //default a response + SmppDataSmResp pdu = new SmppDataSmResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + pdu.MessageId = "Generic"; + + SendPdu(pdu); + } + } + else if(response is SmppDataSmResp) + { + if(OnDataSmResp != null) + { + OnDataSmResp(this, new DataSmRespEventArgs((SmppDataSmResp)response)); + } + } + else if(response is SmppDeliverSm) + { + if(OnDeliverSm != null) + { + OnDeliverSm(this, new DeliverSmEventArgs((SmppDeliverSm)response)); + } + else + { + //default a response + SmppDeliverSmResp pdu = new SmppDeliverSmResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + } + else if(response is SmppDeliverSmResp) + { + if(OnDeliverSmResp != null) + { + OnDeliverSmResp(this, new DeliverSmRespEventArgs((SmppDeliverSmResp)response)); + } + } + else if(response is SmppReplaceSm) + { + if(OnReplaceSm != null) + { + OnReplaceSm(this, new ReplaceSmEventArgs((SmppReplaceSm)response)); + } + else + { + //default a response + SmppReplaceSmResp pdu = new SmppReplaceSmResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + } + else if(response is SmppReplaceSmResp) + { + if(OnReplaceSmResp != null) + { + OnReplaceSmResp(this, new ReplaceSmRespEventArgs((SmppReplaceSmResp)response)); + } + } + else if(response is SmppSubmitMulti) + { + if(OnSubmitMulti != null) + { + OnSubmitMulti(this, new SubmitMultiEventArgs((SmppSubmitMulti)response)); + } + else + { + //default a response + SmppSubmitMultiResp pdu = new SmppSubmitMultiResp(); + pdu.SequenceNumber = response.SequenceNumber; + pdu.CommandStatus = 0; + + SendPdu(pdu); + } + } + else if(response is SmppSubmitMultiResp) + { + if(OnSubmitMultiResp != null) + { + OnSubmitMultiResp(this, new SubmitMultiRespEventArgs((SmppSubmitMultiResp)response)); + } + } + } + + /// + /// Initializes the SMPPCommunicator with some default values. + /// + private void InitCommunicator() + { + Port = 9999; + BindType = SmppBind.BindingType.BindAsTransceiver; + Host = "localhost"; + NpiType = Pdu.NpiType.ISDN; + TonType = Pdu.TonType.International; + Version = SmppBind.SmppVersionType.Version3_4; + AddressRange = null; + Password = null; + SystemId = null; + SystemType = null; + EnquireLinkInterval = 0; + SleepTimeAfterSocketFailure = 10; + } + #endregion private methods + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + protected void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + #endregion + + /// + /// Disposes of this component. Called by the framework; do not call it + /// directly. + /// + /// This is set to false during garbage collection but + /// true during a disposal. + protected override void Dispose(bool disposing) + { + if(disposing) + { + if(components != null) + { + components.Dispose(); + } + } + + try + { + if(!_SentUnbindPacket) + Unbind(); + } + catch + { + //drop it on the floor + } + base.Dispose(disposing); + } + } +} diff --git a/Utility/DestinationAddress.cs b/Utility/DestinationAddress.cs new file mode 100644 index 0000000..1956c28 --- /dev/null +++ b/Utility/DestinationAddress.cs @@ -0,0 +1,258 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Utility +{ + /// + /// Marker/utility class to define destination addresses for the submit_multi. + /// + public sealed class DestinationAddress + { + private Pdu.TonType _DestinationAddressTon = Pdu.TonType.International; + private Pdu.NpiType _DestinationAddressNpi = Pdu.NpiType.ISDN; + private string _DestinationAddress = string.Empty; + private string _DistributionList = string.Empty; + private bool _IsDistributionList = false; + + #region properties + + /// + /// Type of number for destination SME. + /// + public Pdu.TonType DestinationAddressTon + { + get + { + return _DestinationAddressTon; + } + } + + /// + /// Numbering Plan Indicator for destination SME + /// + public Pdu.NpiType DestinationAddressNpi + { + get + { + return _DestinationAddressNpi; + } + } + + /// + /// Destination Address of destination SME + /// + public string DestAddress + { + get + { + return _DestinationAddress; + } + } + + /// + /// Distribution list of destination address + /// + public string DistributionList + { + get + { + return _DistributionList; + } + } + + /// + /// Set to true if this DestinationAddress is a DistributionList. + /// + public bool IsDistributionList + { + get + { + return _IsDistributionList; + } + } + + #endregion properties + + /// + /// Creates an DestinationAddress address. This will trim down the address given to + /// it for use in future operations. + /// + /// The bytes of the response. + public DestinationAddress(ref byte[] address) + { + if(address[0] == 0x01) + { + _IsDistributionList = false; + } + else if(address[0] == 0x02) + { + _IsDistributionList = true; + } + else + { + throw new ApplicationException("Unable to determine type of destination address"); + } + + if(!IsDistributionList) + { + _DestinationAddressTon = (Pdu.TonType)address[1]; + _DestinationAddressNpi = (Pdu.NpiType)address[2]; + _DestinationAddress = SmppStringUtil.GetCStringFromBody(ref address, 3); +// +// long length = address.Length - 4; +// byte[] newRemainder = new byte[length]; +// Array.Copy(address, 4, newRemainder, 0, length); +// //and change the reference +// address = newRemainder; +// newRemainder = null; + } + else + { + _DistributionList = SmppStringUtil.GetCStringFromBody(ref address, 1); +// +// long length = address.Length - 4; +// byte[] newRemainder = new byte[length]; +// Array.Copy(address, 4, newRemainder, 0, length); +// //and change the reference +// address = newRemainder; +// newRemainder = null; + } + } + + /// + /// Creates a new DestinationAddress. + /// + /// Type of number for destination SME. + /// Numbering Plan Indicator for destination SME + /// Destination Address of destination SME + public DestinationAddress( + Pdu.TonType destinationAddressTon, + Pdu.NpiType destinationAddressNpi, + string destinationAdress) + { + if(destinationAdress == null || destinationAdress.Length > 20) + { + throw new ArgumentException( + "Destination Adress must be 20 characters or less."); + } + + _IsDistributionList = false; + + this._DestinationAddressTon = destinationAddressTon; + this._DestinationAddressNpi = destinationAddressNpi; + this._DestinationAddress = destinationAdress; + } + + /// + /// Creates a new DestinationAddress. + /// + /// Distribution list of destination address + public DestinationAddress(string distributionList) + { + if(distributionList == null || distributionList.Length > 20) + { + throw new ArgumentException( + "distribution list must be 20 characters or less."); + } + + _IsDistributionList = true; + + this._DistributionList = distributionList; + } + + /// + /// Clones this DestinationAddress. + /// + /// The cloned object. + public object Clone() + { + DestinationAddress temp = null; + + if(!this.IsDistributionList) + { + temp = new DestinationAddress( + _DestinationAddressTon, _DestinationAddressNpi, _DestinationAddress); + } + else + { + temp = new DestinationAddress(_DistributionList); + } + + temp._IsDistributionList = this.IsDistributionList; + + return temp; + } + + /// + /// Checks to see if two UnsuccessAddresses are equal. + /// + /// The UnsuccessAddresses to check + /// true if obj and this are equal + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + DestinationAddress da = (DestinationAddress) obj; + + if(!da.IsDistributionList) + { + // value member check + return + _DestinationAddressTon.Equals(da._DestinationAddressTon) && + _DestinationAddressNpi.Equals(da._DestinationAddressNpi) && + _DestinationAddress.Equals(da._DestinationAddress); + } + else + { + return _DistributionList.Equals(da._DistributionList); + } + } + + /// + /// Gets the hash code for this object. + /// + /// + public override int GetHashCode() + { + int hashCode = 0; + + if(!this.IsDistributionList) + { + hashCode ^= this.DestAddress.GetHashCode(); + hashCode ^= this.DestinationAddressNpi.GetHashCode(); + hashCode ^= this.DestinationAddressTon.GetHashCode(); + } + else + { + hashCode ^= this.DistributionList.GetHashCode(); + } + + return hashCode; + } + } +} diff --git a/Utility/PduFactory.cs b/Utility/PduFactory.cs new file mode 100644 index 0000000..fbd5478 --- /dev/null +++ b/Utility/PduFactory.cs @@ -0,0 +1,152 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using RoaminSMPP; +using RoaminSMPP.Packet; +using RoaminSMPP.Packet.Request; +using RoaminSMPP.Packet.Response; + +namespace RoaminSMPP.Utility +{ + /// + /// Takes incoming packets from an input stream and generates + /// PDUs based on the command field. + /// + public class PduFactory + { + /// + /// Constructor. + /// + public PduFactory() + { + } + + /// + /// Factory method to generate the PDU. + /// + /// The SMSC response. + /// The PDU. + public Queue GetPduQueue(byte[] incomingPDUs) + { + Queue packetQueue = new Queue(); + //get the first packet + byte[] response = null; + Pdu packet = null; + int newLength = 0; + //this needs to start at zero + uint CommandLength = 0; + + //look for multiple PDUs in the response + while(incomingPDUs.Length > 0) + { + //determine if we have another response PDU after this one + newLength =(int)(incomingPDUs.Length - CommandLength); + //could be empty data or it could be a PDU + if(newLength > 0) + { + //get the next PDU + response = Pdu.TrimResponsePdu(incomingPDUs); + //there could be none... + if(response.Length > 0) + { + //get the command length and command ID + CommandLength = Pdu.DecodeCommandLength(response); + //trim the packet down so we can look for more PDUs + long length = incomingPDUs.Length - CommandLength; + byte[] newRemainder = new byte[length]; + Array.Copy(incomingPDUs, CommandLength, newRemainder, 0, length); + incomingPDUs = newRemainder; + newRemainder = null; + if(CommandLength > 0) + { + //process + packet = GetPDU(response); + if(packet != null) + packetQueue.Enqueue(packet); + } + } + else + { + //kill it off and return + incomingPDUs = new Byte[0]; + } + } + } + + return packetQueue; + } + + /// + /// Gets a single PDU based on the response bytes. + /// + /// The SMSC response. + /// The PDU corresponding to the bytes. + private Pdu GetPDU(byte[] response) + { + Pdu.CommandIdType commandID = Pdu.DecodeCommandId(response); + Pdu packet; + switch(commandID) + { + case Pdu.CommandIdType.alert_notification: + packet = new SmppAlertNotification(response); + break; + case Pdu.CommandIdType.bind_receiver_resp: + case Pdu.CommandIdType.bind_transceiver_resp: + case Pdu.CommandIdType.bind_transmitter_resp: + packet = new SmppBindResp(response); + break; + case Pdu.CommandIdType.cancel_sm_resp: + packet = new SmppCancelSmResp(response); + break; + case Pdu.CommandIdType.data_sm_resp: + packet = new SmppDataSmResp(response); + break; + case Pdu.CommandIdType.deliver_sm: + packet = new SmppDeliverSm(response); + break; + case Pdu.CommandIdType.enquire_link_resp: + packet = new SmppEnquireLinkResp(response); + break; + case Pdu.CommandIdType.outbind: + packet = new SmppOutbind(response); + break; + case Pdu.CommandIdType.query_sm_resp: + packet = new SmppQuerySmResp(response); + break; + case Pdu.CommandIdType.replace_sm_resp: + packet = new SmppReplaceSmResp(response); + break; + case Pdu.CommandIdType.submit_multi_resp: + packet = new SmppSubmitMultiResp(response); + break; + case Pdu.CommandIdType.submit_sm_resp: + packet = new SmppSubmitSmResp(response); + break; + case Pdu.CommandIdType.unbind_resp: + packet = new SmppUnbindResp(response); + break; + default: + packet = null; + break; + } + + return packet; + } + } +} diff --git a/Utility/PduUtil.cs b/Utility/PduUtil.cs new file mode 100644 index 0000000..398f18e --- /dev/null +++ b/Utility/PduUtil.cs @@ -0,0 +1,255 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; +using System.Collections; +using System.Text; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Utility +{ + /// + /// Holds common functionality for requests. + /// + public class PduUtil + { + #region constants + + private const int SUBADDRESS_MIN = 2; + private const int SUBADDRESS_MAX = 23; + + #endregion constants + /// + /// Do not instantiate + /// + private PduUtil() + { + } + + /// + /// Inserts the short message into the PDU ArrayList. + /// + /// The PDU to put the short message into. + /// The short message to insert. + /// The length of the short message. + public static byte InsertShortMessage(ArrayList pdu, object ShortMessage) + { + byte[] msg; + + if(ShortMessage == null) + { + msg = new Byte[]{0x00}; + } + else if(ShortMessage is string) + { + msg = Encoding.ASCII.GetBytes((string)ShortMessage); + } + else if(ShortMessage is byte[]) + { + msg =(byte[])ShortMessage; + } + else + { + throw new ArgumentException("Short Message must be a string or byte array."); + } + // if(msg.Length >= MessageLcd2.SHORT_MESSAGE_LIMIT) + // throw new ArgumentException( + // "Short message cannot be longer than " + + // MessageLcd2.SHORT_MESSAGE_LIMIT + " octets."); + + byte SmLength = (byte)msg.Length; + pdu.Add(SmLength); + pdu.AddRange(msg); + + return SmLength; + } + + /// + /// Takes the given PDU and inserts a receipted message ID into the TLV table. + /// + /// The PDU to operate on. + /// The value to insert. + public static void SetReceiptedMessageId(Pdu pdu, string val) + { + const int MAX_RECEIPTED_ID_LEN = 65; + if(val == null) + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.receipted_message_id, string.Empty); + } + else if(val.Length <= MAX_RECEIPTED_ID_LEN) + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.receipted_message_id, val); + } + else + { + throw new ArgumentException( + "receipted_message_id must have length 1-" + MAX_RECEIPTED_ID_LEN); + } + } + + /// + /// Takes the given PDU and inserts a network error code into the TLV table. + /// + /// The PDU to operate on. + /// The value to insert. + public static void SetNetworkErrorCode(Pdu pdu, string val) + { + const int ERR_CODE_LEN = 3; + if(val == null || val.Length != ERR_CODE_LEN) + { + throw new ArgumentException("network_error_code must have length " + ERR_CODE_LEN); + } + else + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.network_error_code,val); + } + } + + /// + /// Takes the given PDU and inserts ITS session info into the TLV table. + /// + /// The PDU to operate on. + /// The value to insert. + public static void SetItsSessionInfo(Pdu pdu, string val) + { + const int MAX_ITS = 16; + + if(val == null) + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.its_session_info, string.Empty); + } + else if(val.Length == MAX_ITS) + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.its_session_info, val); + } + else + { + throw new ArgumentException("its_session_info must have length " + MAX_ITS); + } + } + + /// + /// Takes the given PDU and inserts a destination subaddress into the TLV table. + /// + /// The PDU to operate on. + /// The value to insert. + public static void SetDestSubaddress(Pdu pdu, string val) + { + if(val.Length >= SUBADDRESS_MIN && val.Length <= SUBADDRESS_MAX) + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.dest_subaddress, val); + } + else + { + throw new ArgumentException( + "Destination subaddress must be between " + SUBADDRESS_MIN + + " and " + SUBADDRESS_MAX + " characters."); + } + } + + /// + /// Takes the given PDU and inserts a source subaddress into the TLV table. + /// + /// The PDU to operate on. + /// The value to insert. + public static void SetSourceSubaddress(Pdu pdu, string val) + { + if(val.Length >= SUBADDRESS_MIN && val.Length <= SUBADDRESS_MAX) + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.source_subaddress, val); + } + else + { + throw new ArgumentException( + "Source subaddress must be between " + SUBADDRESS_MIN + + " and " + SUBADDRESS_MAX + " characters."); + } + } + + /// + /// Takes the given PDU and inserts a callback number into the TLV table. + /// + /// The PDU to operate on. + /// The value to insert. + public static void SetCallbackNum(Pdu pdu, string val) + { + const int CALLBACK_NUM_MIN = 4; + const int CALLBACK_NUM_MAX = 19; + if(val.Length >= CALLBACK_NUM_MIN && val.Length <= CALLBACK_NUM_MAX) + { + pdu.SetOptionalParamString( + (ushort)Pdu.OptionalParamCodes.callback_num, val); + } + else + { + throw new ArgumentException( + "callback_num size must be between " + CALLBACK_NUM_MIN + + " and " + CALLBACK_NUM_MAX + " characters."); + } + } + + /// + /// Takes the given PDU and inserts a message payload into its TLV table. + /// + /// The PDU to operate on. + /// The value to insert. + public static void SetMessagePayload(Pdu pdu, object val) + { + if(val != null) + { + byte[] encodedValue; + if(val is string) + { + encodedValue = Encoding.ASCII.GetBytes((string)val); + } + else if(val is byte[]) + { + encodedValue =(byte[])val; + } + else + { + throw new ArgumentException("Message Payload must be a string or byte array."); + } + + const int MAX_PAYLOAD_LENGTH = 64000; + if(encodedValue.Length < MAX_PAYLOAD_LENGTH) + { + pdu.SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.message_payload, encodedValue); + } + else + { + throw new ArgumentException( + "Message Payload must be " + MAX_PAYLOAD_LENGTH + " characters or less in size."); + } + } + else + { + pdu.SetOptionalParamBytes( + (ushort)Pdu.OptionalParamCodes.message_payload, new byte[]{0}); + } + } + } +} diff --git a/Utility/SmppStringUtil.cs b/Utility/SmppStringUtil.cs new file mode 100644 index 0000000..322ee48 --- /dev/null +++ b/Utility/SmppStringUtil.cs @@ -0,0 +1,178 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ + +using System; +using System.Text; + +namespace RoaminSMPP.Utility +{ + /// + /// Catchall utility class for dealing with strings in SMPP packets. + /// + public class SmppStringUtil + { + /// + /// Do not instantiate. + /// + private SmppStringUtil() + { + } + + /// + /// Gets the next string from the given byte array. Note: this + /// method also trims off the string from the byte array, so that it can be easily + /// used in subsequent operations. You have to know the string length; this will not + /// look for a null character(as it is meant to be used with non-null terminated + /// strings). + /// + /// The byte array to pull the string from. + /// This should not contain extraneous data. + /// The index to start getting the string from. + /// Usually zero. + /// The index to end at. The character at + /// this index will not be included. + /// The string retrieved. + public static string GetStringFromBody(ref byte[] remainder, int startIndex, int endIndex) + { + string result; + + //make sure we aren't trying to read non-command + //data + if(endIndex <= remainder.Length) + { + result = System.Text.Encoding.ASCII.GetString(remainder, startIndex, endIndex - startIndex); + } + else + { + result = string.Empty; + } + + //now trim down the remainder-no null character + long length = remainder.Length - endIndex; + if(length >= 0) + { + byte[] newRemainder = new byte[length]; + Array.Copy(remainder, endIndex, newRemainder, 0, length); + remainder = newRemainder; + newRemainder = null; + } + + return result; + } + + /// + /// Gets the next null-terminated string from the given byte array. Note: this + /// method also trims off the string(including the null character)from the + /// byte array, so that it can be easily used in subsequent operations. + /// This is equivalent to GetCStringFromBody(ref remainder, 0). + /// + /// The byte array to + /// pull the string from. This should not + /// contain extraneous data. + /// The string retrieved. + public static string GetCStringFromBody(ref byte[] remainder) + { + return GetCStringFromBody(ref remainder, 0); + } + + /// + /// Gets the next null-terminated string from the given byte array. Note: this + /// method also trims off the string(including the null character)from the + /// byte array, so that it can be easily used in subsequent operations. + /// + /// The byte array to + /// pull the string from. This should not + /// contain extraneous data. + /// The index to start getting the string from. + /// Usually zero. + /// The string retrieved. + public static string GetCStringFromBody(ref byte[] remainder, int startIndex) + { + int i; + + //find where the null character(end of string)is + //this stops ON the null character + for(i = startIndex; i < remainder.Length && remainder[i] != 0x00; i++) + { + ; + } + + return GetCStringFromBody(ref remainder, startIndex, i); + } + + /// + /// Gets the next null-terminated string from the given byte array. Note: this + /// method also trims off the string from the byte array, so that it can be easily used + /// in subsequent operations. + /// + /// The byte array to pull the string from. + /// This should not contain extraneous data. + /// The index to start getting the string from. + /// Usually zero. + /// The index to end at. The character at + /// this index will not be included. + /// The string retrieved. + public static string GetCStringFromBody(ref byte[] remainder, int startIndex, int endIndex) + { + string result; + + //make sure we aren't trying to read non-command + //data + if(endIndex <= remainder.Length) + { + result = Encoding.ASCII.GetString(remainder, startIndex, endIndex - startIndex); + } + else + { + result = string.Empty; + } + + //now trim down the remainder-chop off the null character as well + long length = remainder.Length - endIndex - 1; + if(length >= 0) + { + byte[] newRemainder = new byte[length]; + Array.Copy(remainder, endIndex + 1, newRemainder, 0, length); + remainder = newRemainder; + newRemainder = null; + } + + return result; + } + + /// + /// Copies the data from the source array, appending a null character to the end. + /// This really only has a use for creating null terminated arrays that represent + /// strings. + /// + /// The source array to copy from. + /// + public static byte[] ArrayCopyWithNull(byte[] source) + { + byte[] temp = new byte[source.Length + 1]; + for(int i = 0; i < source.Length; i++) + { + temp[i] = source[i]; + } + //append the null + temp[temp.Length - 1] =(byte)0x00; + + return temp; + } + } +} diff --git a/Utility/TlvTable.cs b/Utility/TlvTable.cs new file mode 100644 index 0000000..6a04b08 --- /dev/null +++ b/Utility/TlvTable.cs @@ -0,0 +1,288 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using System.Collections; +using System.Net; +using System.Text; +using System.Diagnostics; + +namespace RoaminSMPP.Utility +{ + /// + /// Tag, length, value table for SMPP PDUs. The methods in this class assume + /// that the tag passed in is already in network byte order. + /// + public class TlvTable + { + private Hashtable tlvTable; + + /// + /// Creates a TLV table. + /// + public TlvTable() + { + tlvTable = new Hashtable(); + tlvTable = Hashtable.Synchronized(tlvTable); + } + + /// + /// Converts the TLV byte array data into the Hashtable. This will check if + /// the passed in data is null or is an empty array so you don't need to + /// check it before calling this method. This is equivalent to + /// TranslateTlvDataIntoTable(tlvData, 0). + /// + /// The bytes of TLVs. + public void TranslateTlvDataIntoTable(byte[] tlvData) + { + TranslateTlvDataIntoTable(tlvData, 0); + } + + /// + /// Converts the TLV byte array data into the Hashtable. This will check if + /// the passed in data is null or is an empty array so you don't need to check + /// it before calling this method. + /// + /// The bytes of TLVs. + /// The index of the byte array to start at. This is here + /// because in some instances you may not want to start at the + /// beginning. + public void TranslateTlvDataIntoTable(byte[] tlvData, Int32 index) + { + if(tlvData == null || tlvData.Length <= 0) + { + return; + } + + //go through and decode the TLVs + while(index < tlvData.Length) + { + InjectTlv(tlvData, ref index); + } + } + + /// + /// Using the given tlvData byte array and the given starting index, inserts + /// the tag and value(as a byte array)into the hashtable. Note that the + /// tlvData needs to be in the SMPP v3.4 format(tag, length, value). This + /// assumes that the tag and length (from the tlvData array) are in network byte order. + /// + /// Note also that this will advance the index by the TLV data length so that + /// it may be used for consecutive reads from the same array. + /// + /// The TLV data as a byte array. + /// The index of the array to start reading from. + private void InjectTlv(byte[] tlvData, ref Int32 index) + { + byte[] temp = new byte[2]; + temp[0] = tlvData[index]; + temp[1] = tlvData[index + 1]; + + #if DEBUG + Console.WriteLine("tag bytes " + temp[0].ToString("X").PadLeft(2, '0') + + temp[1].ToString("X").PadLeft(2, '0')); + #endif + + UInt16 tag = BitConverter.ToUInt16(temp, 0); + index += 2; + temp[0] = tlvData[index]; + temp[1] = tlvData[index + 1]; + UInt16 length = UnsignedNumConverter.SwapByteOrdering(BitConverter.ToUInt16(temp, 0)); + index += 2; + //decode the value + + #if DEBUG + Console.WriteLine("TLV Length " + length); + #endif + + ArrayList data = new ArrayList(length); + + int total = index + length; + for(int k = index;(k < index + length)&& k < tlvData.Length; k++) + { + data.Add(tlvData[k]); + } + + data.TrimToSize(); + //add the values to the hashtable + tlvTable.Add(tag, data.ToArray(typeof(byte))); + //set it up for the next run + index += length; + } + + /// + /// Gets the optional parameter bytes associated with the given tag. + /// + /// The tag in TLV. + /// The optional parameter bytes, null if not found. + /// Thrown if the tag cannot be found. + public byte[] GetOptionalParamBytes(UInt16 tag) + { + object val = tlvTable[tag]; + if(val == null) + { + throw new ApplicationException("TLV tag " + tag + " not found."); + } + else + { + byte[] bVal = (byte[])val; + #if DEBUG + StringBuilder sb = new StringBuilder(); + sb.Append("Getting tag " + UnsignedNumConverter.SwapByteOrdering(tag)); + sb.Append("\nValue: "); + + for(int i = 0; i < bVal.Length; i++) + { + sb.Append(bVal[i]); + sb.Append(" "); + } + + Console.WriteLine(sb); + + #endif + return bVal; + } + } + + /// + /// Gets the optional parameter string associated with the given tag. + /// + /// The tag in TLV. + /// The optional parameter string, the empty string if not found. + /// + /// Thrown if the tag cannot be found. + public string GetOptionalParamString(UInt16 tag) + { + byte[] val = GetOptionalParamBytes(tag); + + return Encoding.ASCII.GetString(val); + } + + /// + /// Sets the given TLV(as a byte array)into the table. This ignores null values. + /// + /// The tag in TLV. + /// The value of this TLV. + public void SetOptionalParamBytes(UInt16 tag, byte[] val) + { + #if DEBUG + StringBuilder sb = new StringBuilder(); + sb.Append("Setting tag " + UnsignedNumConverter.SwapByteOrdering(tag)); + sb.Append("\nValue: "); + + for(int i = 0; i < val.Length; i++) + { + sb.Append(val[i]); + sb.Append(" "); + } + + Console.WriteLine(sb); + + #endif + if(val != null) + { + if(val.Length > UInt16.MaxValue) + { + throw new Exception("Optional parameter value for " + tag + " is too large."); + } + tlvTable.Add(tag, val); + } + } + + /// + /// Sets the given TLV(as a string)into the table. This ignores + /// null values. + /// + /// The tag in TLV. + /// The value of this TLV. + public void SetOptionalParamString(UInt16 tag, string val) + { + if(val != null) + { + SetOptionalParamBytes(tag, Encoding.ASCII.GetBytes(val)); + } + } + + /// + /// Allows the updating of TLV values. + /// + /// The tag in TLV. + /// The value of this TLV. + /// Thrown if the tag cannot be found. + public void UpdateOptionalParamBytes(UInt16 tag, byte[] val) + { + object obj = tlvTable[tag]; + + if(obj != null) + { + tlvTable[tag] = val; + } + else + { + throw new ApplicationException("TLV tag " + tag + " not found"); + } + } + + /// + /// Allows the updating of TLV values. + /// + /// The tag in TLV. + /// The value of this TLV. + public void UpdateOptionalParamString(UInt16 tag, string val) + { + UpdateOptionalParamBytes(tag, Encoding.ASCII.GetBytes(val)); + } + + /// + /// Iterates through the hashtable, gathering the tag, length, and + /// value as it goes. For each entry, it encodes the TLV into a byte + /// array. It is assumed that the tags and length are already in network + /// byte order. + /// + /// An ArrayList consisting of byte array entries, each of which + /// is a TLV. Returns an empty ArrayList if the TLV table is empty. + public ArrayList GenerateByteEncodedTlv() + { + if(tlvTable == null || tlvTable.Count <= 0) + { + return new ArrayList(0); + } + + ArrayList tlvs = new ArrayList(); + IDictionaryEnumerator iterator = tlvTable.GetEnumerator(); + ArrayList elem = new ArrayList(); + while(iterator.MoveNext()) + { + elem.Clear(); + //tag-2 bytes + elem.AddRange(BitConverter.GetBytes(((UInt16)iterator.Key))); + //length-2 bytes + byte[] nextVal = (byte[])iterator.Value; + UInt16 tlvLength = UnsignedNumConverter.SwapByteOrdering(((UInt16)(nextVal).Length)); + elem.AddRange(BitConverter.GetBytes(tlvLength)); + //value + elem.AddRange(nextVal); + elem.TrimToSize(); + //copy it over to a byte array + tlvs.Add(elem.ToArray(typeof(byte))); + } + tlvs.TrimToSize(); + + return tlvs; + } + } +} diff --git a/Utility/UnsignedNumConverter.cs b/Utility/UnsignedNumConverter.cs new file mode 100644 index 0000000..31e7f1c --- /dev/null +++ b/Utility/UnsignedNumConverter.cs @@ -0,0 +1,66 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; + +namespace RoaminSMPP.Utility +{ + /// + /// Utility class to do big-endian to little endian conversions and the like. + /// This is for unsigned numbers only; use the IPAddress class for signed values. + /// + public sealed class UnsignedNumConverter + { + /// + /// Do not instantiate. + /// + private UnsignedNumConverter() + { + } + + /// + /// Converts from big-endian to little endian and vice versa. + /// + /// The value to swap. + /// The byte-swapped value, 0 if val < 0 + public static UInt32 SwapByteOrdering(UInt32 val) + { + if(val < 0) + return 0; + return((val << 24)& 0xFF000000)+((val << 8)& 0x00FF0000)+ + ((val >> 8)& 0x0000FF00)+((val >> 24)& 0x000000FF); + } + + /// + /// Converts from big-endian to little endian and vice versa. Don't use + /// for negative integers; it has not been tested for that. + /// + /// The value to swap. + /// The byte-swapped value, 0 if val < 0 + public static UInt16 SwapByteOrdering(UInt16 val) + { + if(val < 0) + { + return 0; + } + + UInt16 newVal = (UInt16)(((val << 8)& 0xFF00)+((val >> 8)& 0x00FF)); + + return newVal; + } + } +} diff --git a/Utility/UnsuccessAddress.cs b/Utility/UnsuccessAddress.cs new file mode 100644 index 0000000..1fa349d --- /dev/null +++ b/Utility/UnsuccessAddress.cs @@ -0,0 +1,181 @@ +/* RoaminSMPP: SMPP communication library + * Copyright (C) 2004, 2005 Christopher M. Bouzek + * + * This file is part of RoaminSMPP. + * + * RoaminSMPP is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * RoaminSMPP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lessert General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with RoaminSMPP. If not, see . + */ +using System; +using RoaminSMPP.Packet; + +namespace RoaminSMPP.Utility +{ + /// + /// Defines an Unsuccess address, used with the response to submit_multi. + /// The spec states that both SME addresses and distribution lists can be + /// used here, but it only defines for the SME address, so that is all that + /// this will handle. + /// + public class UnsuccessAddress + { + private Pdu.TonType _DestinationAddressTon; + private Pdu.NpiType _DestinationAddressNpi; + private string _DestinationAddress; + private uint _ErrorStatusCode; + + #region properties + + /// + /// Type of number for destination SME. + /// + public Pdu.TonType DestinationAddressTon + { + get + { + return _DestinationAddressTon; + } + } + + /// + /// Numbering Plan Indicator for destination SME + /// + public Pdu.NpiType DestinationAddressNpi + { + get + { + return _DestinationAddressNpi; + } + } + + /// + /// Destination Address of destination SME + /// + public string DestinationAddress + { + get + { + return _DestinationAddress; + } + } + + /// + /// Indicates the success or failure of the submit_multi request to this + /// SME address. + /// + public UInt32 ErrorStatusCode + { + get + { + return _ErrorStatusCode; + } + } + + #endregion properties + + /// + /// Creates an Unsuccess address. This will trim down the address given to + /// it for use in future operations. + /// + /// The bytes of the response. + public UnsuccessAddress(ref byte[] address) + { + _DestinationAddressTon = (Pdu.TonType)address[0]; + _DestinationAddressNpi = (Pdu.NpiType)address[1]; + _DestinationAddress = SmppStringUtil.GetCStringFromBody(ref address, 2); + //convert error status to host order + _ErrorStatusCode = UnsignedNumConverter.SwapByteOrdering( + BitConverter.ToUInt32(address, 0)); + //now we have to trim off four octets to account for the status code + long length = address.Length - 4; + byte[] newRemainder = new byte[length]; + Array.Copy(address, 4, newRemainder, 0, length); + //and change the reference + address = newRemainder; + newRemainder = null; + } + + /// + /// Creates a new UnsuccessAdress. + /// + /// Type of number for destination SME. + /// Numbering Plan Indicator for destination SME + /// Destination Address of destination SME + /// Indicates the success or failure of the submit_multi request + /// to this SME address. + public UnsuccessAddress( + Pdu.TonType destinationAddressTon, + Pdu.NpiType destinationAddressNpi, + string destinationAdress, + UInt32 ErrorStatusCode) + { + this._DestinationAddressTon = destinationAddressTon; + this._DestinationAddressNpi = destinationAddressNpi; + this._DestinationAddress = destinationAdress; + this._ErrorStatusCode = ErrorStatusCode; + } + + /// + /// Clones this UnsuccessAddress. + /// + /// The cloned object. + public object Clone() + { + UnsuccessAddress temp = new UnsuccessAddress( + _DestinationAddressTon, _DestinationAddressNpi, _DestinationAddress, _ErrorStatusCode); + return temp; + } + + /// + /// Checks to see if two UnsuccessAddresses are equal. + /// + /// The UnsuccessAddresses to check + /// true if obj and this are equal + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + // safe because of the GetType check + UnsuccessAddress us = (UnsuccessAddress) obj; + + // value member check + return + _DestinationAddressTon.Equals(us._DestinationAddressTon) && + _DestinationAddressNpi.Equals(us._DestinationAddressNpi) && + _DestinationAddress.Equals(us._DestinationAddress) && + _ErrorStatusCode.Equals(us._ErrorStatusCode); + } + + /// + /// Gets the hash code for this object. + /// + /// + public override int GetHashCode() + { + int hashCode = 0; + hashCode ^= this.DestinationAddress.GetHashCode(); + hashCode ^= this.DestinationAddressNpi.GetHashCode(); + hashCode ^= this.DestinationAddressTon.GetHashCode(); + hashCode ^= this.ErrorStatusCode.GetHashCode(); + + return hashCode; + } + } +} diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..1d4c65c --- /dev/null +++ b/version.txt @@ -0,0 +1,3 @@ +major=1 +minor=0 +name=flux