SMPP 3.4 Protocol for the Go programming language

Related tags

Network go-smpp
Overview

SMPP 3.4

GoDoc Go Report Card Build Status

This is an implementation of SMPP 3.4 for Go, based on the original smpp34 from Kevin Patel.

The API has been refactored to idiomatic Go code with more tests and documentation. There are also quite a few new features, such as a test server (see smpptest package) and support for text transformation for LATIN-1 and UCS-2.

It is not fully compliant, there are some TODOs in the code.

Usage

Following is an SMPP client transmitter wrapped by an HTTP server that can send Short Messages (SMS):

func main() {
    // make persistent connection
    tx := &smpp.Transmitter{
        Addr:   "localhost:2775",
        User:   "foobar",
        Passwd: "secret",
    }
    conn := tx.Bind()
    // check initial connection status
    var status smpp.ConnStatus
    if status = <-conn; status.Error() != nil {
        log.Fatalln("Unable to connect, aborting:", status.Error())
    }
    log.Println("Connection completed, status:", status.Status().String())
    // example of connection checker goroutine
    go func() {
        for c := range conn {
            log.Println("SMPP connection status:", c.Status())
        }
    }()
    // example of sender handler func
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        sm, err := tx.Submit(&smpp.ShortMessage{
            Src:      r.FormValue("src"),
            Dst:      r.FormValue("dst"),
            Text:     pdutext.Raw(r.FormValue("text")),
            Register: pdufield.NoDeliveryReceipt,
            TLVFields: pdutlv.Fields{
                pdutlv.TagReceiptedMessageID: pdutlv.CString(r.FormValue("msgId")),
            },
        })
        if err == smpp.ErrNotConnected {
            http.Error(w, "Oops.", http.StatusServiceUnavailable)
            return
        }
        if err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        io.WriteString(w, sm.RespID())
    })
    log.Fatal(http.ListenAndServe(":8080", nil))
}

You can test from the command line:

curl localhost:8080 -X GET -F src=bart -F dst=lisa -F text=hello

If you don't have an SMPP server to test, check out Selenium SMPPSim. It has been used for the development of this package.

Tools

See the tools under cmd/. There's a command line tool for sending SMS from the command line, and an HTTP server with WebSocket support.

Supported PDUs

  • bind_transmitter
  • bind_transmitter_resp
  • bind_receiver
  • bind_receiver_resp
  • bind_transceiver
  • bind_transceiver_resp
  • outbind
  • unbind
  • unbind_resp
  • submit_sm
  • submit_sm_resp
  • submit_sm_multi
  • submit_sm_multi_resp
  • data_sm
  • data_sm_resp
  • deliver_sm
  • deliver_sm_resp
  • query_sm
  • query_sm_resp
  • cancel_sm
  • cancel_sm_resp
  • replace_sm
  • replace_sm_resp
  • enquire_link
  • enquire_link_resp
  • alert_notification
  • generic_nack
  • tag-length-value (TLV)

Copyright

See LICENSE and AUTHORS files for details.

Comments
  • Receive message handler is not working

    Receive message handler is not working

    Hi,

    With the latest version sms receive event is not firing and status is changing continuously connected and disconnects. Message send successfully but received message event is not firing. When using Transmitter in place of Transceiver without handler then status connected for all time. Using below code .

       f := func(p pdu.Body) {
    	switch p.Header().ID {
    	case pdu.DeliverSMID:
    		f := p.Fields()
    		src := f[pdufield.SourceAddr]
    		dst := f[pdufield.DestinationAddr]
    		txt := f[pdufield.ShortMessage]
    		log.Printf("Short message from=%q to=%q: %q",
    			src, dst, txt)
    	}
    }
    
    tx := &smpp.Transceiver{
    	Addr:   "192.168.0.103:8802",
    	User:   "userid",
    	Passwd: "password",
    	Handler:     f,  // Handle incoming SM or delivery receipts.
    }
    // Create persistent connection, wait for the first status.
    conn := <-tx.Bind()
    if conn.Status() != smpp.Connected {
    	log.Fatal(conn.Error())
    }
    sm, err := tx.Submit(&smpp.ShortMessage{
    	Src:      "src",
    	Dst:      "des",
    	Text:     pdutext.Raw("sandeep"),
    	Register: pdufield.NoDeliveryReceipt,
    })
    if err != nil {
    	log.Fatal(err)
    }
    log.Println("Message ID:", sm.RespID())
    
    
    for{
    	
    	time.Sleep(time.Millisecond * 1600)
    }
    
    opened by sandeepkdpl 31
  • Windowed mode & automatic reconnection

    Windowed mode & automatic reconnection

    1. Does this library allows to send submit_sm messages with a window size greater than 1? For example, if the output window size is set to 10, I am allowed to send up to 10 submit_sm pdus before having the submit_sm_resp received. This mode can increase throughput to smsc substantially.
    2. What about automatic reconnection of dropped smpp connections to smsc?

    Many thanks!

    opened by robertmircea 26
  • features and fixes

    features and fixes

    1. RateLimiter from dev tree
    2. Fixed QuerySM "0" status according to SMPP 5.0 specs (props to @blind-oracle)
    3. Use BindInterval delay (if given) for retry in Bind() instead of exponential growth (props to @blind-oracle)
    4. Implemented EnquireLinkResp as time of the last response in enquireLink function:
    • if we don't get the response from server within the time window, unbind and close the connection (according to specs, enquirelink serves as "confidence-check of the communication path between an ESME and an SMSC", so if there's no response, we can't be confident that our connection is alive)
    1. Added src TON/NPI to QuerySM (props to @blind-oracle)
    2. Added EnquireLinkTimeout (props to @blind-oracle)
    3. Renamed conn to cl as it holds the client, not the connection
    4. Added sending of DeliverSMResp to receiver (props to @blind-oracle)
    • this fixes the problem when we're not responding to the receiver gate and it stops the connection from the server side
    1. Merged pull request https://github.com/fiorix/go-smpp/pull/28
    opened by nezorflame 18
  • Support messages larger than characters allowed per sms

    Support messages larger than characters allowed per sms

    I tried sending larger than one sms content UCS (60+) and Latin(160+) encoded data using ShortMessage struct but it failed on smpp service provided by cellular network. Sending large latin encoded messages work on smppsim. Smppsim fails to process any ucs encoded messages. I read up on it and came across these at http://www.activexperts.com/sms-component/smpp-specifications/smpp-parameter-definition/ :

    short_message

    The short_message parameter contains the user data. A maximum of 254 octets can be sent. ESME's should use the optional message_payload parameter in submit_sm, submit_multi, and deliver_sm to send larger user data sizes.

    sm_length

    The sm_length parameter specifies the length of the short_message parameter in octets. The sm_length should be set to 0 in the submit_sm, submit_multi, and deliver_sm PDUs if the message_payload parameter is being used to send user data larger than 254 octets.

    If above is right, can this library support sending larger than 160 chars messages? I couldn't find any logic to handle this in code.

    opened by haisum 15
  • Initial implementation of submit_multi PDU

    Initial implementation of submit_multi PDU

    Tested with SMPPSim simulator, tried to not change the API much to avoid more repetition, so SM can optionally hold submit multi parameters, but any improvement suggestions welcome. Once approach is validate I'll add more code to validate size of addresses and distribution lists as per SMPP spec.

    opened by VDVsx 10
  • Support 2 byte reference number in UDH header

    Support 2 byte reference number in UDH header

    Hey there,

    We're going to be running some services with this library that are going to be using a fairly large number of binds. With the current 1 byte reference number the chance of a collision would be relatively high and we'd like to use the alternative header with the 2 byte number. For now we've patched the library to add it in but was wanting to ask if you would accept a PR for it?

    Cheers, Lucian

    opened by lucianjon 7
  • short_message in DeliverSM scrambles when data_coding is 0x08

    short_message in DeliverSM scrambles when data_coding is 0x08

    When receiving DeliverSM of a UCS encoded message, short_message gets decoded using UCS2 and gets corrupt. A solution is, not to decode short_message when decoding PDU and let user decide what to do.

    Current output of short_message pdu field: selection_078

    After I removed automatic decoding: selection_079

    opened by haisum 6
  • Problems using test server

    Problems using test server

    Hi,

    I am trying to use (and expand) the server in smpptest. I ran a server and took the sample code for running a client. When I try to submit a ShortMessage with transmitter.Submit(), I get the error unexpected PDU ID: SubmitSM which makes sense since the server is only responding back with the same PDU in the EchoHandler.

    In the EchoHandler, I modified the ID of the PDU to be SubmitSMRespID by accessing the headers of the request PDU and when I send it back, the client times out. I pinpointed the problem to be in list.go:112 where it complains: not enough data for tag 0x0: want 29554, have 22.

    I would imagine that messing directly with the headers could be a bad idea, so I went ahead and used the function NewSubmitSMResp() from types.go to build a the appropriate response in the EchoHandler. When I sent it back, the client just times out again with no response and I can't pinpoint the cause.

    EchoHandler looks like this:

    func EchoHandler(conn Conn, m pdu.Body) {
        // Approach #1: Send it back as-is
    
        // Approach #2: Modify the ID directly
        // m.Header().ID = pdu.SubmitSMRespID
    
        // Approach #3: Send a new response
        // m = pdu.NewSubmitSMResp()
    
        err := conn.Write(m)
        if err != nil {
            fmt.Println(err)
        }
    }
    

    What am I doing wrong? Or am I missing to implement something? I am quite knew to SMPP so bare with me if there are obvious mistakes I didn't spot.

    Thanks!

    opened by cesarrodrig 6
  • Method for sending additional fields with SMS

    Method for sending additional fields with SMS

    Firstly, thanks for really awesome work. I have used and tested this package for simple sms and it works on smppsim simulator. My real smpp provided wants addrton,dest_addr_ton, source_addr_npi and addr_npi to be provided. If I send sms without these fields using Submit method it says invalid source address.

    Method func (t *Transmitter) Submit(sm *ShortMessage) (*ShortMessage, error) doesn't support a parmeter to send additional fields along with simple ones. May I suggest a new method with signature:

    func (t *Transmitter) SubmitWithFields(sm *ShortMessage, fields map[string]interface{}) (*ShortMessage, error)

    I tried implementing above using following code:

    
    // SubmitWithFields sends a short message along with extra pdu fields and returns and updates the given
    // sm with the response status. It returns the same sm object.
    func (t *Transmitter) SubmitWithFields(sm *ShortMessage, fields map[string]int) (*ShortMessage, error) {
        p := pdu.NewSubmitSM()
        f := p.Fields()
        f.Set(pdufield.SourceAddr, sm.Src)
        f.Set(pdufield.DestinationAddr, sm.Dst)
        f.Set(pdufield.ShortMessage, sm.Text)
        f.Set(pdufield.RegisteredDelivery, uint8(sm.Register))
        for k, v := range fields {
            err := f.Set(pdufield.Name(k), v)
            if err != nil {
                return sm, fmt.Errorf("Couldn't set field %s with value %s. Error: %s", k, v, err)
            }
        }
        // Check if the message has validity set.
        if sm.Validity != time.Duration(0) {
            f.Set(pdufield.ValidityPeriod, convertValidity(sm.Validity))
        }
        resp, err := t.do(p)
        if err != nil {
            return nil, err
        }
        sm.resp.Lock()
        sm.resp.p = resp.PDU
        sm.resp.Unlock()
        if id := resp.PDU.Header().ID; id != pdu.SubmitSMRespID {
            return sm, fmt.Errorf("unexpected PDU ID: %s", id)
        }
        if s := resp.PDU.Header().Status; s != 0 {
            return sm, s
        }
        return sm, resp.Err
    }
    

    but when I submit with this method, smppsim disconnects and times out. Is there any better way via which I can send additional fields?

    opened by haisum 6
  • ошибка подключения SMPP

    ошибка подключения SMPP

    Можете подсказать делаю пакет для API своего https://play.golang.org/p/ES7Fv1tuzJz . Но ошибка идетъ err con 2018/02/06 17:49:59 SMPP connection status: Connected err con 2018/02/06 17:50:33 SMPP connection status: Connected err con 2018/02/06 17:51:22 SMPP connection status: Connected

    в связи с чем такая ошибка может возникать

    opened by ghost 4
  • GSM7 encoding

    GSM7 encoding

    Hi all,

    Currently there is no support for GSM7 encoding or packing. Since most SMPP providers do not support receiving GSM7 packed (septet to octet conversion) requests, I suggest that we add two new codecs:

    GSM7 Packed

    Encode and pack messages. That means messages should be split after 140-7 bytes (UDH header), since there is the potential for splitting an escaped character (which consists of two bytes) like { across two parts, we should limit each part to 140-7-1 bytes.

    GSM7 Unpacked

    Only encode message, since many SMPP providers will not accept GSM7 packed. That means message should be split after 160-7 bytes (UDH header), since there is the potential for splitting an escaped character (which consists of two bytes) like { across two parts, we should limit each part to 160-7-1 bytes.

    opened by McSwitch 3
  • [BUG] - message encoding not working for long unicode message

    [BUG] - message encoding not working for long unicode message

    I'm trying to send unicode sms with more than 70 characters using SubmitLongMsg. But the message received has wrong encoding and showing chinese like text.

    opened by sujit-baniya 0
  • Easier way to manager delivery receipts - missing receipted_message_id and PDU Sequence Management

    Easier way to manager delivery receipts - missing receipted_message_id and PDU Sequence Management

    Thanks for the great work, is almost impossible to find content about SMPP implementations for the go language and other languages as well, in go, we can rely only in this and the linxGnu lib, I'm studying and even looking to contribute after understanding the implementation.

    I have a feature request tho, about the Delivery receipt (DeliverSM), using the melroselabs SMSC simulator on python or java client I'm receiving the receipted_message_id as it's stated on the smpp 3.4 specifications but with go-smpp is not implemented, I even thought it would be the MessageID Field but it always returns empty, is this field missing or is that a way to capture it? Another problem is to Manage the sequence between submitSM and DeliverSM, to correlate the ID some implementations leave the atomic integer id implementation to the developer, which usually using a message broker or a database is possible to control those sequences and correlate Receipts with the send Message is that a way that we can implement those features?

    opened by alexanderomnix 1
  • Using tx.Submit in thread

    Using tx.Submit in thread

    Can I use tx.Submit in thread ? I can see in the example_test it is used inside http Handler function

    Also if I use tx.Submit in 10 threads, the delivery receipts traffic would increase. Will the Handler function of Transceiver perform fast enough ?

    opened by tahseenjamal 2
  • use /v2 for local package imports

    use /v2 for local package imports

    This was changed in fe1b3c72362b03d9fd3afb7541a95e48218fe3e6.

    I don't know why it was called /v2, but if it is then the local imports should refer to the same version.

    opened by alicebob 0
Owner
Alexandre Fiori
Alexandre Fiori
wire protocol for multiplexing connections or streams into a single connection, based on a subset of the SSH Connection Protocol

qmux qmux is a wire protocol for multiplexing connections or streams into a single connection. It is based on the SSH Connection Protocol, which is th

Jeff Lindsay 191 Sep 25, 2022
A simple tool to convert socket5 proxy protocol to http proxy protocol

Socket5 to HTTP 这是一个超简单的 Socket5 代理转换成 HTTP 代理的小工具。 如何安装? Golang 用户 # Required Go 1.17+ go install github.com/mritd/[email protected] Docker 用户 docker pull m

mritd 7 Sep 7, 2022
A Language Server Protocol (LSP) server for Jsonnet

Jsonnet Language Server Warning: This project is in active development and is likely very buggy. A Language Server Protocol (LSP) server for Jsonnet.

Jack Baldry 17 Apr 29, 2022
Implementation of Pinocchio Protocol in Go language

pinocchio-protocol-zksnarks Implementation of Pinocchio Protocol in Go language 1 零知识证明和zksnarks 1.1 为什么需要可证明的计算? 随着技术的发展,计算能力表现出不对称的特性,例如云计算等拥有大量的算力,

null 0 Nov 3, 2021
language server protocol sdk implement for go

LSP(language server protocol) defines for golang lsp types is from vscode-languageserver-node. Project is working in progress. Example func main() {

Tobias Yin 38 Sep 14, 2022
Txt-lsp - A toy project with Language Server Protocol (LSP)

txt-lsp txt-lsp is a toy project where I play around with Language Server Protoc

Shi Han 0 Jan 22, 2022
BGP implemented in the Go Programming Language

GoBGP: BGP implementation in Go GoBGP is an open source BGP implementation designed from scratch for modern environment and implemented in a modern pr

null 3k Sep 26, 2022
A simple wrapper around libpcap for the Go programming language

PCAP This is a simple wrapper around libpcap for Go. Originally written by Andreas Krennmair [email protected] and only minorly touched up by Mark Smith

Andreas Krennmair 456 Sep 27, 2022
Basic LDAP v3 functionality for the GO programming language.

Basic LDAP v3 functionality for the GO programming language. Install For the latest version use: go get gopkg.in/ldap.v2 Import the latest version wi

null 137 May 24, 2022
Go-web-dev - Web Development With Google's Golang Programming Language Code Snippet and Exercises.

Web Development With Google's Golang Programming Language Code Snippet and Exercises This repository contains my code snippets, hands on exercises and

null 2 Jan 16, 2022
Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed.

arp Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed. Portions of this code are taken from the Go standard library. The

Matt Layher 296 Sep 27, 2022
Gmqtt is a flexible, high-performance MQTT broker library that fully implements the MQTT protocol V3.1.1 and V5 in golang

中文文档 Gmqtt News: MQTT V5 is now supported. But due to those new features in v5, there area lots of breaking changes. If you have any migration problem

null 742 Sep 27, 2022
A TCP Server Framework with graceful shutdown, custom protocol.

xtcp A TCP Server Framework with graceful shutdown,custom protocol. Usage Define your protocol format: Before create server and client, you need defin

xfx 136 Sep 11, 2022
Go library for writing standalone Map/Reduce jobs or for use with Hadoop's streaming protocol

dmrgo is a Go library for writing map/reduce jobs. It can be used with Hadoop's streaming protocol, but also includes a standalone map/reduce impleme

Damian Gryski 104 Aug 25, 2022
Implementation of the FTPS protocol for Golang.

FTPS Implementation for Go Information This implementation does not implement the full FTP/FTPS specification. Only a small subset. I have not done a

Marco Beierer 27 Mar 14, 2022
network multiplexing and framing protocol for RPC

TChannel Network multiplexing and framing protocol for RPC Read the Docs Languages: Node.js, Python, Go, Java Questions: Open a Github issue Uber's OS

Uber Open Source 1.2k Sep 4, 2022
Inspired by go-socks5,This package provides full functionality of socks5 protocol.

The protocol described here is designed to provide a framework for client-server applications in both the TCP and UDP domains to conveniently and securely use the services of a network firewall.

Zhangliu 69 Aug 15, 2022
A new way of working with Protocol Buffers.

Buf All documentation is hosted at https://buf.build. Please head over there for more details. Goal Buf’s long-term goal is to enable schema-driven de

null 5.4k Sep 26, 2022