{
    "content": [
        {
            "type": "text",
            "text": "# Net::SMPP (perldoc)\n\n## NAME\n\nNet::SMPP - pure Perl implementation of SMPP 3.4 over TCP\n\n## SYNOPSIS\n\nuse Net::SMPP;\n$smpp = Net::SMPP->newtransceiver($host, port=>$port,\nsystemid => 'yourusername',\npassword  => 'secret',\n) or die;\n\n## DESCRIPTION\n\nImplements Short Message Peer to Peer protocol, which is frequently used to pass short messages\nbetween mobile operators implementing short message service (SMS). This is applicable to both\neuropean GSM and american CDMA/TDMA systems.\n\n## Sections\n\n- **NAME**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **CONSTRUCTORS** (6 subsections)\n- **REQUEST PDU METHODS** (14 subsections)\n- **RESPONSE PDU METHODS** (13 subsections)\n- **MESSAGE ENCODING AND LENGTH**\n- **OTHER METHODS** (3 subsections)\n- **EXAMPLES**\n- **MULTIPART MESSAGE** (1 subsections)\n- **ERRORS**\n- **EXPORT**\n- **TESTS / WHAT IS KNOWN TO WORK**\n- **TO DO AND BUGS** (1 subsections)\n- **AUTHOR AND COPYRIGHT**\n- **PLUG**\n- **SEE ALSO** (1 subsections)\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "Net::SMPP",
        "section": "",
        "mode": "perldoc",
        "summary": "Net::SMPP - pure Perl implementation of SMPP 3.4 over TCP",
        "synopsis": "use Net::SMPP;\n$smpp = Net::SMPP->newtransceiver($host, port=>$port,\nsystemid => 'yourusername',\npassword  => 'secret',\n) or die;",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [
            "Typical client:",
            "use Net::SMPP;",
            "$smpp = Net::SMPP->newtransceiver('smsc.foo.net', port=>2552) or die;",
            "$resppdu = $smpp->submitsm(destinationaddr => '447799658372',",
            "data => 'test message') or die;",
            "Typical server, run from inetd:",
            "See test.pl for good templates with all official parameters, but beware that the actual",
            "parameter values are fictitious as is the flow of the dialog."
        ],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 6,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 85,
                "subsections": []
            },
            {
                "name": "CONSTRUCTORS",
                "lines": 1,
                "subsections": [
                    {
                        "name": "new",
                        "lines": 3
                    },
                    {
                        "name": "new_connect",
                        "lines": 15
                    },
                    {
                        "name": "new_transceiver",
                        "lines": 1
                    },
                    {
                        "name": "new_transmitter",
                        "lines": 1
                    },
                    {
                        "name": "new_receiver",
                        "lines": 4
                    },
                    {
                        "name": "new_listen",
                        "lines": 3
                    }
                ]
            },
            {
                "name": "REQUEST PDU METHODS",
                "lines": 76,
                "subsections": [
                    {
                        "name": "alert_notification",
                        "lines": 16
                    },
                    {
                        "name": "bind_transceiver",
                        "lines": 1
                    },
                    {
                        "name": "bind_transmitter",
                        "lines": 1
                    },
                    {
                        "name": "bind_receiver",
                        "lines": 32
                    },
                    {
                        "name": "cancel_sm",
                        "lines": 43
                    },
                    {
                        "name": "data_sm",
                        "lines": 30
                    },
                    {
                        "name": "deliver_sm",
                        "lines": 41
                    },
                    {
                        "name": "enquire_link",
                        "lines": 4
                    },
                    {
                        "name": "outbind",
                        "lines": 13
                    },
                    {
                        "name": "query_sm",
                        "lines": 11
                    },
                    {
                        "name": "replace_sm",
                        "lines": 17
                    },
                    {
                        "name": "submit_sm",
                        "lines": 46
                    },
                    {
                        "name": "submit_multi",
                        "lines": 49
                    },
                    {
                        "name": "unbind",
                        "lines": 4
                    }
                ]
            },
            {
                "name": "RESPONSE PDU METHODS",
                "lines": 5,
                "subsections": [
                    {
                        "name": "bind_receiver_resp",
                        "lines": 1
                    },
                    {
                        "name": "bind_transmitter_resp",
                        "lines": 1
                    },
                    {
                        "name": "bind_transceiver_resp",
                        "lines": 4
                    },
                    {
                        "name": "cancel_sm_resp",
                        "lines": 2
                    },
                    {
                        "name": "data_sm_resp",
                        "lines": 2
                    },
                    {
                        "name": "deliver_sm_resp",
                        "lines": 2
                    },
                    {
                        "name": "enquire_link_resp",
                        "lines": 2
                    },
                    {
                        "name": "generic_nack",
                        "lines": 2
                    },
                    {
                        "name": "query_sm_resp",
                        "lines": 7
                    },
                    {
                        "name": "replace_sm_resp",
                        "lines": 2
                    },
                    {
                        "name": "submit_sm_resp",
                        "lines": 2
                    },
                    {
                        "name": "submit_multi_resp",
                        "lines": 7
                    },
                    {
                        "name": "unbind_resp",
                        "lines": 2
                    }
                ]
            },
            {
                "name": "MESSAGE ENCODING AND LENGTH",
                "lines": 29,
                "subsections": []
            },
            {
                "name": "OTHER METHODS",
                "lines": 1,
                "subsections": [
                    {
                        "name": "read_pdu",
                        "lines": 10
                    },
                    {
                        "name": "wait_pdu",
                        "lines": 8
                    },
                    {
                        "name": "set_version",
                        "lines": 4
                    }
                ]
            },
            {
                "name": "EXAMPLES",
                "lines": 15,
                "subsections": []
            },
            {
                "name": "MULTIPART MESSAGE",
                "lines": 127,
                "subsections": [
                    {
                        "name": "wait_pdu",
                        "lines": 15
                    }
                ]
            },
            {
                "name": "ERRORS",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "EXPORT",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "TESTS / WHAT IS KNOWN TO WORK",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "TO DO AND BUGS",
                "lines": 1,
                "subsections": [
                    {
                        "name": "read_pdu",
                        "lines": 2
                    }
                ]
            },
            {
                "name": "AUTHOR AND COPYRIGHT",
                "lines": 8,
                "subsections": []
            },
            {
                "name": "PLUG",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SEE ALSO",
                "lines": 20,
                "subsections": [
                    {
                        "name": "perl",
                        "lines": 1
                    }
                ]
            }
        ],
        "sections": {
            "NAME": {
                "content": "Net::SMPP - pure Perl implementation of SMPP 3.4 over TCP\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "use Net::SMPP;\n$smpp = Net::SMPP->newtransceiver($host, port=>$port,\nsystemid => 'yourusername',\npassword  => 'secret',\n) or die;\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "Implements Short Message Peer to Peer protocol, which is frequently used to pass short messages\nbetween mobile operators implementing short message service (SMS). This is applicable to both\neuropean GSM and american CDMA/TDMA systems.\n\nThis documentation is not intended to be complete reference to SMPP protocol - use the SMPP\nspecification documents (see references section) to obtain exact operation and parameter names\nand their meaning. You may also need to obtain site specific documentation about the remote end\nand any protocol extensions that it supports or demands before you start a project. This\ndocument follows the convention of spelling parameter names exactly as they appear in the SMPP\nv3.4 documentation. SMPP v4.0 support also follows the respective documentation, except where\nv4.0 usage is in conflict with v3.4 usage, in which case the latter prevails (in practise I\nbelieve no such conflicts remain in the madule at present). For a complete list of error code\nand optional parameter enumerations, the reader is encouraged to consult the source code or SMPP\nspeciofications.\n\nDespite its name, SMPP protocol defines a client (ESME) and a server (often called SMSC in the\nmobile operator world). Client usually initiates the TCP connection and does *bind* to log in.\nAfter binding, a series of request response pairs, called PDUs (protocol data units) is\nexchanged. Request can be initiated by either end (hence \"peer-to-peer\"?) and the other end\nreponds. Requests are numbered with a sequence number and each response has corresponding\nsequence number. This allows several requests to be pending at the same time. Conceptually this\nis similar to IMAP or LDAP message IDs. Usually the $smpp object maintains the sequence numbers\nby itself and the programmer need not concern himself with their exact values, but should a need\nto override them arise, the seq argument can be supplied to any request or response method.\n\nNormally this module operates in synchronous mode, meaning that a method that sends a request\nwill also block until it gets the corresponding response. Internal command used for waiting for\nresponse is\n\n$resppdu = $smpp->waitpdu($cmdid, $seq);\n\nIf, while waiting for a particular response, other PDUs are received they are either handled by\nhandlers (set up by constructor) or discarded. Both command code and sequence number must match.\nTypically a handler for enquire command is set up while all other commands are silently dropped.\nThis practise may not be very suitable for transceiver mode of operation and certainly is not\nsuitable for implementing a SMSC.\n\nSynchronous operation makes it impossible to interleave SMPP operations, thus it should be\nregarded as a simplified programming model for simple tasks. Anyone requiring more advanced\ncontrol has to use the asynchronous mode and take up the burden of understanding and\nimplementing more of the message flow logic in his own application.\n\nIn synchronous mode request PDU methods return a Net::SMPP::PDU object representing the\nresponse, if all went well protocolwise, or undef if there was a protocol level error. If undef\nwas returned, the reason for the failure can be extracted from ${*$smpp}{smpperror} and\n${*$smpp}{smpperrorcode} (actual codes are undocumented at the moment, but are guaranteed not to\nchange) variables and the global variable $!. These variables are meaningless if anything else\nthan undef was returned. The response itself may be an error response if there was an\napplication level error in the remote end. In this case the application level error can be\ndetermined from $pdu->{status} field. Some responses also have optional parameters that further\nclarify the failure, see documentation for each operation.\n\nIf a protocol level error happens, probably the only safe action is to destroy the connection\nobject (e.g. undef $smpp). If an application level error happens, then depending on how the\nremote end has been implemented it may be possible to continue operation.\n\nModule can also be used asynchronously by specifying async=>1 to the constructor. In this mode\ncommand methods return immediately with the sequence number of the PDU and user should poll for\nany responses using\n\n$pdu = $smpp->waitpdu($cmdid, $seq);\n\nTypically waitpdu() is used to wait for a response, but if waitpdu() is used to wait for a\ncommand, the caller should generate appropriate response.\n\nIf caller wants to receive next available PDU, he can call\n\n$pdu = $smpp->readpdu();\n\nwhich will block until a PDU is received from the stream. The caller would then have to check if\nthe PDU is a response or a request and take appropriate action. The smsc.pl example program\nsupplied with this distribution demonstrates a possible framework for handling both requests and\nresponses.\n\nIf the caller does not want to block on waitpdu() or readpdu(), he must use select() to\ndetermine if the socket is readable (* what if SSL layer gets inserted?). Even if the socket\nselects for reading, there may not be enough data to complete the PDU, so the call may still\nblock. Currently there is no reliable mechanism for avoiding this. If this bothers you, you may\nconsider allocating a separate process for each connection so that blocking does not matter, or\nyou may set up some sort of timeout (see perlipc(1) man page) or you may rewrite this module and\ncontribute patches.\n\nResponse methods always return the sequence number, irrespective of synchronous or asynchronous\nmode, or undef if an error happened.\n",
                "subsections": []
            },
            "CONSTRUCTORS": {
                "content": "",
                "subsections": [
                    {
                        "name": "new",
                        "content": "Do not call. Has special internal meaning during accepting connections from listening\nsocket.\n"
                    },
                    {
                        "name": "new_connect",
                        "content": "Create a new SMPP client object and open conncetion to SMSC host\n\n$smpp = Net::SMPP->newconnect($host,\nsystemid => 'username',   # usually needed (default '')\npassword => 'secret',      # usually needed (default '')\nsystemtype => '',         # default ok, often not needed\ninterfaceversion => 0x34, # default ok, almost never needed\naddrton => 0x00,          # default ok, type of number unknwn\naddrnpi => 0x00,          # default ok, number plan indicator\naddressrange => '',       # default ok, regex matching nmbrs\n) or die;\n\nUsually this constructor is not called directly. Use newtransceiver(), newtransmitter(),\nand newreceiver() instead.\n"
                    },
                    {
                        "name": "new_transceiver",
                        "content": ""
                    },
                    {
                        "name": "new_transmitter",
                        "content": ""
                    },
                    {
                        "name": "new_receiver",
                        "content": "These constructors first construct the object using newconnect() and then bind using given\ntype of bind request. See bind family of methods, below. These constructors are usually used\nto implement ESME type functionality.\n"
                    },
                    {
                        "name": "new_listen",
                        "content": "Create new SMPP server object and open socket to listen on given port. This constructor is\nusually used to implement a SMSC.\n"
                    }
                ]
            },
            "REQUEST PDU METHODS": {
                "content": "Each request PDU method constructs a PDU from list of arguments supplied and sends it to the\nwire.\n\nIf async mode has been enabled (by specifying \"async=>1\" in the constructor or as an argument to\nthe method), the methods return sequence number of the PDU just sent. This number can be later\nused to match up the response, like this:\n\n$seq = $smpp->querysm(messageid => $msgid) or die;\n...\n$resppdu = $smpp->waitpdu(Net::SMPP::CMDquerysmresp, $seq)\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n\nIf async mode is not enabled (i.e. \"async=>1\" was not specified neither in constructor nor the\nmethod), the method will wait for the corresponding response and return Net::SMPP::PDU object\nrepresenting that response. The application should check the outcome of the operation from the\nstatus field of the response PDU, like this:\n\n$resppdu = $smpp->querysm(messageid => $msgid) or die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n\nAll request PDU methods optionally take \"seq=>123\" argument that allows explicit specification\nof the sequence number. The default is to increment internally stored sequence number by one and\nuse that.\n\nMost PDUs have mandatory parameters and optional parameters. If mandatory parameter is not\nsupplied, it is inherited from the smpp object. This means that the parameter can either be set\nas an argument to the constructor or it is inherited from built-in defaults in the innards of\nNet::SMPP (see \"Default\" table from line 217 onwards). Some mandatory parameters can not be\ndefaulted - if they are missing a die results. In descriptions below, defaultable mandatory\nparameters are show with the default value and comment indicating that its defaultable.\n\nOptional parameters can be supplied to all PDUs (although the SMPP spec does not allow optional\nparameters for some PDUs, the module does not check for this) by listing them in the order that\nthey should be appended to the end of the PDU. Optional parameters can not be defaulted - if the\nparameter is not supplied, it simply is not included in the PDU. Optional parameters are not\nsupported by previous versions of the SMPP protocol (up to and including 3.3). Applications\nwishing to be downwards compatible should not make use of optional parameters.\n\nStandard optional parameters can be supplied by their name (see \"paramtab\" in the Net::SMPP\nsource code, around line 345, for list of known optional parameters), but the programmer still\nneeds to supply the value of the parameter in the expected format (one often has to use pack to\nconstruct the value). Consult SMPP specifications for the correct format.\n\nIt is possible to supply arbitrary unsupported optional parameters by simply supplying the\nparameter tag as a decimal number. Consult your site dependent documentation to figure out the\ncorrect tags and to determine the correct format for the value.\n\nWhen optional parameters are returned in response PDUs, they are decoded and made available\nunder both numeric tag and symbolic tag, if known. For example the deliveryfailurereson of\ndatasmresp can be accessed both as $resp->{deliveryfailurereson} and $resp->{1061}. The\napplication needs to interpret the formatting of optional parameters itself. The module always\nassumes they are strings, while often they actually are interpretted as integers. Consult SMPP\nspecifications and site dependent documentation for correct format and use unpack to obtain the\nnumbers.\n\nIf an unknown nonnumeric parameter tags are supplied a warning is issued and parameter is\nskipped.\n\nIn general the Net::SMPP module does not enforce SMPP specifications. This means that it will\nhappily accept too long or too short values for manatory or optional parameters. Also the\ninternal formatting of the parameter values is not checked in any way. The programmer should\nconsult the SMPP specifications to learn the correct length and format of each mandatory and\noptional parameter.\n\nSimilarly, if the remote end returns incorrect PDUs and Net::SMPP is able to parse them (usually\nbecause length fields match), then Net::SMPP will not perform any further checks. This means\nthat some fields may be longer than allowed for in the specifications.\n\nI opted to leave the checks out at this stage because I needed a flexible module that allowed me\nto explore even nonconformant SMSC implementations. If the lack of sanity checks bothers you,\nformulate such checks and submit me a patch. Ideally one could at construction time supply an\nargument like \"strict=>1\" to enable the sanity checks.\n",
                "subsections": [
                    {
                        "name": "alert_notification",
                        "content": "Sent by SMSC to ESME when particular mobile subscriber has become available. sourceaddr\nspecifies which mobile subscriber. esmeaddr specifies which esme the message is destined\nto. Alert notifications can arise if delivery pending flag had been set for the subscriber\nfrom previous datasm operation.\n\nThere is no response PDU.\n\n$smpp->alertnotification(\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\nesmeaddrton => 0x00,   # default ok\nesmeaddrnpi => 0x00,   # default ok\nesmeaddr => $esmeaddr, # mandatory\n) or die;\n"
                    },
                    {
                        "name": "bind_transceiver",
                        "content": ""
                    },
                    {
                        "name": "bind_transmitter",
                        "content": ""
                    },
                    {
                        "name": "bind_receiver",
                        "content": "Bind family of methods is used to authenticate the client (ESME) to the server (SMSC).\nUsually bind happens as part of corresponding constructor \"newtransceiver()\",\n\"newtransmitter()\", or \"newreceiver()\" so these methods are rarely called directly. These\nmethods take a plethora of options, which are largely the same as the options taken by the\nconstructors and can safely be defaulted.\n\n$smpp->bindtransceiver(\nsystemid => 'username',   # usually needed (default '')\npassword => 'secret',      # usually needed (default '')\nsystemtype => '',         # default ok, often not needed\ninterfaceversion => 0x34, # default ok, almost never needed\naddrton => 0x00,          # default ok, type of number unkwn\naddrnpi => 0x00,          # default ok, number plan indic.\naddressrange => '',       # default ok, regex matching tels\n) or die;\n\nTypically it would be called like:\n\n$resppdu = $smpp->bindtransceiver(systemid => 'username',\npassword => 'secret') or die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n\nor to inform SMSC that you can handle all Spanish numbers:\n\n$resppdu = $smpp->bindtransceiver(systemid => 'username',\npassword => 'secret',\naddressrange => '^\\+?34')\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n"
                    },
                    {
                        "name": "cancel_sm",
                        "content": "Issued by ESME to cancel one or more short messages. Two principal modes of operation are:\n\n1. if messageid is supplied, other fields can be left at defaults. This mode deletes just\none message.\n\n2. if messageid is not supplied (or is empty string), then the other fields must be\nsupplied and all messages matching the criteria reflected by the other fields are deleted.\n\n$smpp->cancelsm(\nservicetype => '',      # default ok\nmessageid => '', # default ok, but often given\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\ndestaddrton => 0x00,   # default ok\ndestaddrnpi => 0x00,   # default ok\ndestinationaddr => '',  # default ok\n) or die;\n\nFor example\n\n$resppdu = $smpp->submitsm(destinationaddr => '+447799658372',\nshortmessage => 'test message')\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n$msgid = $resppdu->{messageid};\n\n$resppdu = $smpp->querysm(messageid => $msgid) or die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\nprint \"Message state is $resppdu->{messagestate}\\n\";\n\n$resppdu = $smpp->replacesm(messageid => $msgid,\nshortmessage => 'another test')\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n\n$resppdu = $smpp->cancelsm(messageid => $msgid) or die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n"
                    },
                    {
                        "name": "data_sm",
                        "content": "Newer alternative to submitsm and deliversm. In addition to that datasm can be used to\npass special messages such as SMSC Delivery Receipt, SME Delivery Acknowledgement, SME\nManual/User Acknowledgement, Intermediate notification.\n\nUnlike submitsm and deliversm, the shortmessage parameter is not mandatory.\nNever-the-less, the optional parameter messagepayload must be supplied for things to work\ncorrectly.\n\n$smpp->datasm(\nservicetype => '',      # default ok\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\ndestaddrton => 0x00,   # default ok\ndestaddrnpi => 0x00,   # default ok\ndestinationaddr => $tel,  # mandatory\nesmclass => 0x00,       # default ok\nregistereddelivery => 0x00, #default ok\ndatacoding => 0x00,     # default ok\nmessagepayload => 'test msg', # opt, but needed\n) or die;\n\nFor example\n\n$resppdu = $smpp->datasm(destinationaddr => '+447799658372',\nmessagepayload => 'test message')\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n"
                    },
                    {
                        "name": "deliver_sm",
                        "content": "Issued by SMSC to send message to an ESME. Further more SMSC can transfer following special\nmessages: 1. SMSC delivery receipt, 2. SME delivery acknowledgement, 3. SME Manual/User\nAcknowledgement, 4. Intermediate notification. These messages are sent in response to SMS\nmessage whose registereddelivery parameter requested them.\n\nIf message data is longer than 254 bytes, the optional parameter \"messagepayload\" should be\nused to store the message and \"shortmessage\" should be set to empty string. N.B. although\nprotocol has mechanism for sending fairly large messages, the underlying mobile network\nusually does not support very large messages. GSM supports only up to 160 characters, other\nsystems 128 or even just 100 characters.\n\n$smpp->deliversm(\nservicetype => '',      # default ok\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\ndestaddrton => 0x00,   # default ok\ndestaddrnpi => 0x00,   # default ok\ndestinationaddr => $t,  # mandatory\nesmclass => 0x00,       # default ok\nprotocolid => 0x00,     # default ok on CDMA,TDMA\n#   on GSM value needed\npriorityflag => 0x00,   # default ok\nscheduledeliverytime => '', # default ok\nvalidityperiod => '',        # default ok\nregistereddelivery => 0x00,  # default ok\nreplaceifpresentflag => 0x00, # default ok\ndatacoding => 0x00,     # default ok\nsmdefaultmsgid => 0x00,    # default ok\nshortmessage => '',     # default ok, but\n#   usually supplied\n) or die;\n\nFor example\n\n$resppdu = $smpp->deliversm(destinationaddr => '+447799658372',\nshortmessage => 'test message')\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n"
                    },
                    {
                        "name": "enquire_link",
                        "content": "Used by either ESME or SMSC to \"ping\" the other side. Takes no parameters.\n\n$smpp->enquirelink() or die;\n"
                    },
                    {
                        "name": "outbind",
                        "content": "Used by SMSC to signal ESME to originate a \"bindreceiver\" request to the SMSC. \"systemid\"\nand \"password\" authenticate the SMSC to the ESME. The \"outbind\" is used when SMSC initiates\nthe TCP session and needs to trigger ESME to perform a \"bindreceiver\". It is not needed if\nthe ESME initiates the TCP connection (e.g. sec 2.7.1, p.27).\n\nThere is not response PDU for \"outbind\", instead the ESME is expected to issue\n\"bindreceiver\".\n\n$smpp->outbind(\nsystemid => '',  # default ok, but usually given\npassword => '',   # default ok, but usually given\n) or die;\n"
                    },
                    {
                        "name": "query_sm",
                        "content": "Used by ESME to query status of a submitted short message. Both messageid and sourceaddr\nmust match (if sourceaddr was defaulted to NULL during submit, it must be NULL here, too).\nSee example near \"cancelsm\".\n\n$smpp->querysm(\nmessageid => $msgid,   # mandatory\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\n) or die;\n"
                    },
                    {
                        "name": "replace_sm",
                        "content": "Used by ESME to replace a previously submitted short message, provided it is still pending\ndelivery. Both messageid and sourceaddr must match (if sourceaddr was defaulted to NULL\nduring submit, it must be NULL here, too). See example near \"cancelsm\".\n\n$smpp->replacesm(\nmessageid => $msgid,   # mandatory\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\nscheduledeliverytime => '', # default ok\nvalidityperiod => '',        # default ok\nregistereddelivery => 0x00,  # default ok\nsmdefaultmsgid => 0x00,    # default ok\nshortmessage => '',     # default ok, but\n#   usually supplied\n) or die;\n"
                    },
                    {
                        "name": "submit_sm",
                        "content": "Used by ESME to submit short message to the SMSC for onward transmission to the specified\nshort message entity (SME). The submitsm does not support the transaction message mode.\n\nIf message data is longer than 254 bytes, the optional parameter \"messagepayload\" should be\nused to store the message and \"shortmessage\" should be set to empty string. N.B. although\nprotocol has mechanism for sending fairly large messages, the underlying mobile network\nusually does not support very large messages. GSM supports only up to 160 characters.\n\n$smpp->submitsm(\nservicetype => '',      # default ok\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\ndestaddrton => 0x00,   # default ok\ndestaddrnpi => 0x00,   # default ok\ndestinationaddr => $t,  # mandatory\nesmclass => 0x00,       # default ok\nprotocolid => 0x00,     # default ok on CDMA,TDMA\n#   on GSM value needed\npriorityflag => 0x00,   # default ok\nscheduledeliverytime => '', # default ok\nvalidityperiod => '',        # default ok\nregistereddelivery => 0x00,  # default ok\nreplaceifpresentflag => 0x00, # default ok\ndatacoding => 0x00,     # default ok\nsmdefaultmsgid => 0x00,    # default ok\nshortmessage => '',     # default ok, but\n#   usually supplied\n) or die;\n\nFor example\n\n$resppdu = $smpp->submitsm(destinationaddr => '+447799658372',\nshortmessage => 'test message')\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n\nOr\n\n$resppdu = $smpp->submitsm(destinationaddr => '+447799658372',\nshortmessage => '',\nmessagepayload => 'a'x500) or die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n"
                    },
                    {
                        "name": "submit_multi",
                        "content": "Used by ESME to submit short message to the SMSC for onward transmission to the specified\nshort message entities (SMEs). This command is especially destined for multiple recipients.\n\nIf message data is longer than 254 bytes, the optional parameter \"messagepayload\" should be\nused to store the message and \"shortmessage\" should be set to empty string. N.B. although\nprotocol has mechanism for sending fairly large messages, the underlying mobile network\nusually does not support very large messages. GSM supports only up to 160 characters.\n\n$smpp->submitmulti(\nservicetype => '',      # default ok\nsourceaddrton => 0x00, # default ok\nsourceaddrnpi => 0x00, # default ok\nsourceaddr => '',       # default ok\ndestflag =>             # default ok\n[ MULTIDESTFLAGSMEAddress,\nMULTIDESTFLAGdistlist, ... ],\ndestaddrton =>         # default ok\n[ 0x00, 0x00, ... ],\ndestaddrnpi =>         # default ok\n[ 0x00, 0x00, ... ],\ndestinationaddr =>      # mandatory\n[ $t1, $t2, ... ],\nesmclass => 0x00,       # default ok\nprotocolid => 0x00,     # default ok on CDMA,TDMA\n#   on GSM value needed\npriorityflag => 0x00,   # default ok\nscheduledeliverytime => '', # default ok\nvalidityperiod => '',        # default ok\nregistereddelivery => 0x00,  # default ok\nreplaceifpresentflag => 0x00, # default ok\ndatacoding => 0x00,     # default ok\nsmdefaultmsgid => 0x00,    # default ok\nshortmessage => '',     # default ok, but\n#   usually supplied\n) or die;\n\nFor example\n\n$resppdu = $smpp->submitmulti(destinationaddr =>\n[ '+447799658372', '+447799658373' ],\nshortmessage => 'test message')\nor die;\ndie \"Response indicated error: \" . $resppdu->explainstatus()\nif $resppdu->status;\n\nThe destinations are specified as an array reference. destflag, destaddrton, and\ndestaddrnpi must have same cardinality as destinationaddr if they are present. Default\nfor destflag is MULTIDESTFLAGSMEAddress, i.e. normal phone number.\n"
                    },
                    {
                        "name": "unbind",
                        "content": "Used by ESME to unregisters ESME from SMSC. Does not take any parameters.\n\n$smpp->unbind() or die;\n"
                    }
                ]
            },
            "RESPONSE PDU METHODS": {
                "content": "Response PDU methods are used to indicate outcome of requested commands. Typically these methods\nwould be used by someone implementing a server (SMSC).\n\nResponse PDUs do not have separate asynchronous behaviour pattern.\n",
                "subsections": [
                    {
                        "name": "bind_receiver_resp",
                        "content": ""
                    },
                    {
                        "name": "bind_transmitter_resp",
                        "content": ""
                    },
                    {
                        "name": "bind_transceiver_resp",
                        "content": "$smpp->bindtransceiverresp(\nsystemid => '', # default ok\n) or die;\n"
                    },
                    {
                        "name": "cancel_sm_resp",
                        "content": "$smpp->cancelsmresp() or die;\n"
                    },
                    {
                        "name": "data_sm_resp",
                        "content": "$smpp->datasmresp(messageid => $msgid) or die;\n"
                    },
                    {
                        "name": "deliver_sm_resp",
                        "content": "$smpp->deliversmresp(messageid => $msgid) or die;\n"
                    },
                    {
                        "name": "enquire_link_resp",
                        "content": "$smpp->enquirelinkresp() or die;\n"
                    },
                    {
                        "name": "generic_nack",
                        "content": "$smpp->genericnack() or die;\n"
                    },
                    {
                        "name": "query_sm_resp",
                        "content": "$smpp->querysmresp(\nmessageid => $msgid,   # mandatory\nfinaldate => '',        # default ok\nmessagestate => $state, # mandatory\nerrorcode => 0x00,      # default ok\n) or die;\n"
                    },
                    {
                        "name": "replace_sm_resp",
                        "content": "$smpp->replacesmresp() or die;\n"
                    },
                    {
                        "name": "submit_sm_resp",
                        "content": "$smpp->submitsmresp(messageid => $msgid) or die;\n"
                    },
                    {
                        "name": "submit_multi_resp",
                        "content": "$smpp->submitmultiresp(messageid => $msgid\ndestaddrton => [], # default ok\ndestaddrnpi => [], # default ok\ndestinationaddr => [],  # mandatory\nerrorstatuscode => [], # mandatory\n) or die;\n"
                    },
                    {
                        "name": "unbind_resp",
                        "content": "$smpp->unbindresp() or die;\n"
                    }
                ]
            },
            "MESSAGE ENCODING AND LENGTH": {
                "content": "Many SMS technologies have inherent message length limits. For example GSM specifies length\nto be 140 bytes. Using 7 bit encoding, this holds the 160 characters that people are\nfamiliar with. Net::SMPP does not enforce this limit in any way, i.e. if you create too long\nmessage, then it is your problem. You should at application layer make sure you stay within\nlimits.\n\nNet::SMPP also does not automatically perform the encoding, not even if you set\ndataencoding parameter. Application layer is responsible for performing the encoding and\nsetting the dataencoding parameter accordingly.\n\nTo assist in performing the usual 7 bit encoding, following functions are provided (but you\nhave to call them explicitly):\n\npack7bit()\nunpack7bit()\nExample\n\n$resppdu = $smpp->submitsm(destinationaddr => '+447799658372',\ndataencoding => 0x00,\nshortmessage => pack7bit('test message'))\nor die;\n\nThe rationale for leaving encoding and length issues at application layer is two fold: 1.\noften the data is just copied through to another message or protocol, thus we do not really\ncare how it is encoded or how long it is. Presumably it was valid at origin. 2. This policy\navoids underlying technology dependencies in the module. Often local deployments have all\nthe manner of hacks that make this area very difficult to chart. So I leave it to local\napplication developer to find out what is locally needed.\n",
                "subsections": []
            },
            "OTHER METHODS": {
                "content": "",
                "subsections": [
                    {
                        "name": "read_pdu",
                        "content": "Reads a PDU from stream and analyzes it into Net::SMPP::PDU object (if PDU is of known\ntype). Blocks until PDU is available. If you do not want it to block, do select on the\nsocket to make sure some data is available (unfortunately some data may be available, but\nnot enough, so it can still block).\n\nreadpdu() is very useful for implementing main loop of SMSC where unknown PDUs must be\nreceived in random order and processed.\n\n$pdu = $smpp->readpdu() or die;\n"
                    },
                    {
                        "name": "wait_pdu",
                        "content": "Reads PDUs from stream and handles or discards them until matching PDU is found. Blocks\nuntil success. Typically waitpdu() is used internally by request methods when operating in\nsynchronous mode. The PDUs to handle are specified by \"${*$me}{handlers}-\"{$commandid}>.\nThe handlers table is initially populated to handle enquirelink PDUs automatically, but\nthis can be altered using \"handlers\" argument to constructor.\n\n$pdu = $smpp->waitpdu($cmdidtowait, $seqtowait) or die;\n"
                    },
                    {
                        "name": "set_version",
                        "content": "Sets the protocol version of the object either to 0x40 or 0x34. Its important to use this\nmethod instead of altering $smpp->{smppversion} field directly because there are several\nother fields that have to be set in tandem.\n"
                    }
                ]
            },
            "EXAMPLES": {
                "content": "Typical client:\n\nuse Net::SMPP;\n$smpp = Net::SMPP->newtransceiver('smsc.foo.net', port=>2552) or die;\n$resppdu = $smpp->submitsm(destinationaddr => '447799658372',\ndata => 'test message') or die;\n*\n\nTypical server, run from inetd:\n\n*\n\nSee test.pl for good templates with all official parameters, but beware that the actual\nparameter values are fictitious as is the flow of the dialog.\n",
                "subsections": []
            },
            "MULTIPART MESSAGE": {
                "content": "Reportedly (Zeus Panchenko) multipart messages can be gotten to work with\n\nwhile (length ($msgtext)) {\nif ($multimsgmaxparts) {\n@udhar = map { sprintf \"%x\", $ } $origref, $multimsgmaxparts, $multimsgcurpart;\n$udh = pack(\"hhhhhh\",0x05, 0x00, 0x03 , @udhar);\n$resppdu = $smpp->submitsm(destinationaddr => $phone,\n...\nshortmessage => $udh . $msgtext,\n);\n...\n}\n}\n\n#4#cut =head1 VERSION 4.0 SUPPORT\n\nNet::SMPP was originally written for version 3.4 of SMPP protocol. I have since then gotten\nspecifications for an earlier protocol, the version 4.0 (Logical, eh? (pun intended)). In my\nunderstanding the relevant differences are as follows (n.b. (ok) marks difference that has\nalready been implemented):\n\n1. A reserved (always 0x00000000) field in message header (v4 p. 21) (ok)\n\n2. Connection can not be opened in transceiver mode (this module will not enforce this\nrestriction) (ok)\n\n3. Command versioning. Version 0x01 == V4 (v4 p. 22) (ok)\n\n4. Support for extended facilities has to be requested during bind (ok)\n\n5. bind* PDUs have facilitiesmask field (v4 p. 25) (ok)\n\n6. bind*resp PDUs have facilitiesmask field (v4 p. 27) (ok)\n\n7. outbind lacks system ID field (v4 p.30, v3.4 p. 54) (ok)\n\n8. submitsm lacks servicetype and adds messageclass (v4 p. 34, v3.4 p. 59) (ok)\n\n9. submitsm: telematicinterworking == protocolid (ok)\n\n10. submitsm: starting from number of destinations and destination address the message format\nis substantially different. Actually the message format is somewhat similar to v3.4\nsubmitmulti. (ok)\n\n11. submitsm: validity period encoded as an integer relative offset (was absolute time as C\nstring) (ok)\n\n12. submitsm: replaceifpresent flag missing (ok)\n\n13. submitsm: smlength field is 2 octets (was one) (ok)\n\n14. submitsmresp is completely different, but actually equal to v3.4 submitmultiresp (v4 p.\n37, v3.4 pp. 67,75) (ok)\n\n15. submitsm vs submitmulti: lacks servicetype, adds messageclass (ok)\n\n16. submitsm vs submitmulti: numberofdests increased from 1 byte to 4 (ok)\n\n17. submitsm vs submitmulti: esmclass lacking, adds messagingmode and msgreference (ok)\n\n18. submitsm vs submitmulti: telematicinterworking == protocolid (ok)\n\n19. submitsm vs submitmulti: replaceifpresent missing (ok)\n\n20. submitsm vs submitmulti: smlength is 2 bytes (was one) (ok)\n\n21. submitsm vs submitmulti: lacks destflag and distributionlistname (ok)\n\n22. deliversm: lacks servicetype (ok)\n\n23. deliversm: lacks esmclass, adds msgreference and messageclass (ok)\n\n24. deliversm: telematicinterworking == protocolid (ok)\n\n25. deliversm: prioritylevel == priorityflag (ok)\n\n26. deliversm: submittimestamp == scheduledeliverytime (ok)\n\n27. deliversm: lacks validityperiod, registereddelivery, and replaceifpresentflag (ok)\n\n28. deliversm: lacks smdefaultmsgid (ok)\n\n29. deliversm: smlength is now 2 bytes (was one) (ok)\n\n30. deliversmresp: lacks messageid (v3.4 has the field, but its unused) (ok)\n\n31. New command: deliveryreceipt (ok)\n\n32. New response: deliveryreceiptresp (ok)\n\n33. querysm: destaddr* fields added (v4 p. 46, v3.4 p. 95) (ok)\n\n34. querysmresp: errorcode renamed to networkerrorcode and increased in size from one to 4\nbytes (ok)\n\n35. cancelsm: servicetype renamed to messageclass, also type changed (ok)\n\n36. replacesm: added destaddr* fields (ok)\n\n37. replacesm: data type of validityperiod changed (ok)\n\n38. replacesm: added datacoding field (ok)\n\n39. replacesm: smlength field increased from one to two bytes (ok)\n\n40. In v3.4 command code 0x0009 means bindtransceiver, in v4.0 this very same code means\ndeliveryreceipt (bummer) (ok)\n\n41. In v3.4 enquirelink is 0x0015 where as in v4 it is 0x000a (ok)\n\nTo create version 4 connection, you must specify smppversion => 0x40 and you should not bind as\ntransceiver as that is not supported by the specification.\n\nAs v3.4 specification seems more mature, I recommend that where attributes have been renamed\nbetween v4 and v3.4 you stick to using v3.4 names. I have tried to provide compatibility code\nwhenever possible.\n\n#4#end\n\nMISC. NOTES\nUnless you wrote your program to be multithreaded or multiprocess, everything will happen in one\nthread of execution. Thus if you get unbind while doing something else (e.g. checking your spool\ndirectory), it stays in operating system level buffers until you actually call readpdu().\nKnowing about unbind or not is of little use. You can write your program to assume the network\ntraffic arrives only exactly when you call readpdu().\n\nRegarding the unbind, it is normally handled by a dispatch table automatically if you use",
                "subsections": [
                    {
                        "name": "wait_pdu",
                        "content": "add it there yourself. If you are calling readpdu() then you have to handle it yourslef. Even\nif you are using the supplied table, you may want to double check - there could be a bug.\n\nOne more thing: if your problem is knowing whether waitpdu() or readpdu() would block, then\nyou have two possible solutions:\n\n1. use select(2) systemcall to determine for the socket\nis ready for reading\n2. structure your program as several processes (e.g. one\nfor sending and one for receiving) so that you\ncan afford to block\n\nThe above two tricks are not specific to this module. Consult any standard text book on TCP/IP\nnetwork programming.\n"
                    }
                ]
            },
            "ERRORS": {
                "content": "Please consult \"statuscode\" table in the beginning of the source code or SMPP specification\nsection 5.1.3, table 5-2, pp.112-114.\n",
                "subsections": []
            },
            "EXPORT": {
                "content": "None by default.\n",
                "subsections": []
            },
            "TESTS / WHAT IS KNOWN TO WORK": {
                "content": "Interoperates with itself.\n",
                "subsections": []
            },
            "TO DO AND BUGS": {
                "content": "",
                "subsections": [
                    {
                        "name": "read_pdu",
                        "content": "The submitmulti command has not been implemented.\n"
                    }
                ]
            },
            "AUTHOR AND COPYRIGHT": {
                "content": "Sampo Kellomaki <sampo@symlabs.com>\n\nNet::SMPP is copyright (c) 2001-2010 by Sampo Kellomaki, All rights reserved. Portions copyright\n(c) 2001-2005 by Symlabs, All rights reserved. You may use and distribute Net::SMPP under same\nterms as perl itself.\n\nNET::SMPP COMES WITH ABSOLUTELY NO WARRANTY.\n",
                "subsections": []
            },
            "PLUG": {
                "content": "This work was sponsored by Symlabs, the LDAP and directory experts (www.symlabs.com).\n",
                "subsections": []
            },
            "SEE ALSO": {
                "content": "test.pl from this package\nShort Message Peer to Peer Protocol Specification v3.4, 12-Oct-1999, Issue 1.2\nwww.etsi.fr\nGSM 03.40, v5.7.1\nwww.wapforum.org\nShort Message Peer to Peer (SMPP) V4 Protocol Specification, 29-Apr-1997, Version 1.1 (from\nAldiscon/Logica) #4\nhttp://www.hsl.uk.com/documents/advserv-sms-smpp.pdf\nhttp://www.mobilesms.com/developers.asp\nhttp://opensmpp.logica.com\nwww.smpp.org (it appears as of July 2007 domain squatters have taken over the site and it is no\nlonger useful)\nhttp://www.smsforum.net/ -- New place for info (as of 20081214). However, this page announces\nthe death of itself as of July 27, 2007. Great. The SMS folks really do not want anyone to\nimplement their protocols from specifications.\n\"Short Message Peer to Peer Protocol Specification v5.0 19-February-2003\",\nhttp://www.csoft.co.uk/documents/smppv50.pdf (good as of 20081214)\nhttp://freshmeat.net/projects/netsmpp/ (announcements about Net::SMPP)\nhttp://zxid.org/smpp/net-smpp.html (home page)\nhttp://cpan.org/modules/by-module/Net/Net-SMPP-1.12.tar.gz (download from CPAN)",
                "subsections": [
                    {
                        "name": "perl",
                        "content": ""
                    }
                ]
            }
        }
    }
}