Showing preview only (372K chars total). Download the full file or copy to clipboard to get everything.
Repository: linxGnu/gosmpp
Branch: master
Commit: 577c73e414d2
Files: 115
Total size: 344.5 KB
Directory structure:
gitextract_d637zljl/
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ └── go.yml
├── .gitignore
├── .golangci.yml
├── LICENSE
├── README.md
├── connect.go
├── connect_test.go
├── connection.go
├── connection_test.go
├── data/
│ ├── 7bit.go
│ ├── 7bit_test.go
│ ├── codings.go
│ ├── codings_test.go
│ ├── header_data.go
│ ├── header_data_string.go
│ ├── other_codings.go
│ ├── pkg.go
│ ├── pkg_test.go
│ ├── utils.go
│ └── utils_test.go
├── errors/
│ ├── pkg.go
│ └── pkg_test.go
├── example/
│ ├── smsc_simulator/
│ │ └── smsc.cpp
│ ├── transceiver_with_auto_response/
│ │ └── main.go
│ ├── transceiver_with_manual_response/
│ │ └── main.go
│ ├── transeiver_with_custom_store/
│ │ ├── CustomStore.go
│ │ └── main.go
│ └── transeiver_with_request_window_and_custom_submitSm/
│ ├── CustomSubmitSM.go
│ └── main.go
├── go.mod
├── go.sum
├── pdu/
│ ├── Address.go
│ ├── AddressRange.go
│ ├── AddressRange_test.go
│ ├── Address_test.go
│ ├── AlertNotification.go
│ ├── AlertNotification_test.go
│ ├── BindRequest.go
│ ├── BindRequest_test.go
│ ├── BindResponse.go
│ ├── BindResponse_test.go
│ ├── Buffer.go
│ ├── Buffer_test.go
│ ├── CancelSM.go
│ ├── CancelSMResp.go
│ ├── CancelSMResp_test.go
│ ├── CancelSM_test.go
│ ├── DataSM.go
│ ├── DataSMResp.go
│ ├── DataSMResp_test.go
│ ├── DataSM_test.go
│ ├── DeliverSM.go
│ ├── DeliverSMResp.go
│ ├── DeliverSMResp_test.go
│ ├── DeliverSM_test.go
│ ├── DestinationAddress.go
│ ├── DestinationAddress_test.go
│ ├── DistributionList.go
│ ├── DistributionList_test.go
│ ├── EnquireLink.go
│ ├── EnquireLinkResp.go
│ ├── EnquireLinkResp_test.go
│ ├── EnquireLink_test.go
│ ├── GenericNack.go
│ ├── GenericNack_test.go
│ ├── Outbind.go
│ ├── Outbind_test.go
│ ├── PDU.go
│ ├── PDUFactory.go
│ ├── PDUFactory_test.go
│ ├── PDUHeader.go
│ ├── PDUHeader_test.go
│ ├── PDU_test.go
│ ├── QuerySM.go
│ ├── QuerySMResp.go
│ ├── QuerySMResp_test.go
│ ├── QuerySM_test.go
│ ├── ReplaceSM.go
│ ├── ReplaceSMResp.go
│ ├── ReplaceSMResp_test.go
│ ├── ReplaceSM_test.go
│ ├── ShortMessage.go
│ ├── ShortMessage_test.go
│ ├── SubmitMulti.go
│ ├── SubmitMultiResp.go
│ ├── SubmitMultiResp_test.go
│ ├── SubmitMulti_test.go
│ ├── SubmitSM.go
│ ├── SubmitSMResp.go
│ ├── SubmitSMResp_test.go
│ ├── SubmitSM_test.go
│ ├── TLV.go
│ ├── UDH.go
│ ├── UDH_test.go
│ ├── Unbind.go
│ ├── UnbindResp.go
│ ├── UnbindResp_test.go
│ ├── Unbind_test.go
│ ├── UnsuccessSME.go
│ ├── UnsuccessSME_test.go
│ └── helper_test.go
├── pkg.go
├── receivable.go
├── receivable_test.go
├── request_store.go
├── session.go
├── session_test.go
├── state.go
├── state_test.go
├── transceivable.go
├── transceivable_test.go
├── transmittable.go
├── transmittable_test.go
└── types.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
================================================
FILE: .github/workflows/go.yml
================================================
name: Build
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Check out
uses: actions/checkout@v5
- name: Set up GCC
run: |
sudo apt install gcc g++ -y
shell: bash
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
# - name: Linter
# uses: golangci/golangci-lint-action@v8
# with:
# version: latest
- name: Start SMSC
run: |
g++ example/smsc_simulator/smsc.cpp -o smsc
./smsc &
shell: bash
- name: Test Coverage
run: go test -v -race -count=1 -coverprofile=coverage.out
- name: Convert coverage to lcov
uses: jandelgado/gcov2lcov-action@v1
with:
version: latest
infile: coverage.out
outfile: coverage.lcov
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
path-to-lcov: coverage.lcov
================================================
FILE: .gitignore
================================================
.idea/
vendor/
*DS_Store
*.out
smsc
================================================
FILE: .golangci.yml
================================================
version: "2"
linters:
# Default set of linters.
# The value can be:
# - `standard`: https://golangci-lint.run/docs/linters/#enabled-by-default
# - `all`: enables all linters by default.
# - `none`: disables all linters by default.
# - `fast`: enables only linters considered as "fast" (`golangci-lint help linters --json | jq '[ .[] | select(.fast==true) ] | map(.name)'`).
# Default: standard
default: all
# Enable specific linter.
enable:
- arangolint
- asasalint
- asciicheck
- bidichk
- bodyclose
- canonicalheader
- containedctx
- contextcheck
- copyloopvar
- cyclop
- decorder
- depguard
- dogsled
- dupl
- dupword
- durationcheck
- embeddedstructfieldcheck
- err113
- errcheck
- errchkjson
- errname
- errorlint
- exhaustive
- exhaustruct
- exptostd
- fatcontext
- forbidigo
- forcetypeassert
- funcorder
- funlen
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoglobals
- gochecknoinits
- gochecksumtype
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- goheader
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- gosmopolitan
- govet
- grouper
- iface
- importas
- inamedparam
- ineffassign
- interfacebloat
- intrange
- ireturn
- lll
- loggercheck
- maintidx
- makezero
- mirror
- misspell
- mnd
- musttag
- nakedret
- nestif
- nilerr
- nilnesserr
- nilnil
- nlreturn
- noctx
- noinlineerr
- nolintlint
- nonamedreturns
- nosprintfhostport
- paralleltest
- perfsprint
- prealloc
- predeclared
- promlinter
- protogetter
- reassign
- recvcheck
- revive
- rowserrcheck
- sloglint
- spancheck
- sqlclosecheck
- tagalign
- tagliatelle
- testableexamples
- testifylint
- testpackage
- thelper
- tparallel
- unconvert
- unparam
- unused
- usestdlibvars
- usetesting
- varnamelen
- wastedassign
- whitespace
- wrapcheck
- wsl
- wsl_v5
- zerologlint
# Disable specific linters.
disable:
- staticcheck
- arangolint
- asasalint
- asciicheck
- bidichk
- bodyclose
- canonicalheader
- containedctx
- contextcheck
- copyloopvar
- cyclop
- decorder
- depguard
- dogsled
- dupl
- dupword
- durationcheck
- embeddedstructfieldcheck
- err113
- errcheck
- errchkjson
- errname
- errorlint
- exhaustive
- exhaustruct
- exptostd
- fatcontext
- forbidigo
- forcetypeassert
- funcorder
- funlen
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoglobals
- gochecknoinits
- gochecksumtype
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- goheader
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- gosmopolitan
- govet
- grouper
- iface
- importas
- inamedparam
- ineffassign
- interfacebloat
- intrange
- ireturn
- lll
- loggercheck
- maintidx
- makezero
- mirror
- misspell
- mnd
- musttag
- nakedret
- nestif
- nilerr
- nilnesserr
- nilnil
- nlreturn
- noctx
- noinlineerr
- nolintlint
- nonamedreturns
- nosprintfhostport
- paralleltest
- perfsprint
- prealloc
- predeclared
- promlinter
- protogetter
- reassign
- recvcheck
- revive
- rowserrcheck
- sloglint
- spancheck
- sqlclosecheck
- staticcheck
- tagalign
- tagliatelle
- testableexamples
- testifylint
- testpackage
- thelper
- tparallel
- unconvert
- unparam
- unused
- usestdlibvars
- usetesting
- varnamelen
- wastedassign
- whitespace
- wrapcheck
- wsl
- wsl_v5
- zerologlint
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# gosmpp
[]()
[](https://goreportcard.com/report/github.com/linxGnu/gosmpp)
[](https://coveralls.io/github/linxGnu/gosmpp?branch=master)
[](https://godoc.org/github.com/linxGnu/gosmpp)
SMPP (3.4) Client Library in pure Go.
This library is well tested with SMSC simulators:
- [Melroselabs SMSC](https://melroselabs.com/services/smsc-simulator/#smsc-simulator-try)
## Installation
```
go get -u github.com/linxGnu/gosmpp
```
## Usage
### Highlight
- From `v0.1.4`, gosmpp is written in event-based style and fully-manage your smpp session, connection, error, rebinding, etc. You only need to implement some hooks:
```go
trans, err := gosmpp.NewSession(
gosmpp.TRXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
EnquireLink: 5 * time.Second,
ReadTimeout: 10 * time.Second,
OnSubmitError: func(_ pdu.PDU, err error) {
log.Fatal("SubmitPDU error:", err)
},
OnReceivingError: func(err error) {
fmt.Println("Receiving PDU/Network error:", err)
},
OnRebindingError: func(err error) {
fmt.Println("Rebinding but error:", err)
},
OnPDU: handlePDU(),
OnClosed: func(state gosmpp.State) {
fmt.Println(state)
},
}, 5*time.Second)
if err != nil {
log.Println(err)
}
defer func() {
_ = trans.Close()
}()
```
### Version (0.1.4.RC+)
- Full example could be found: [here](https://github.com/linxGnu/gosmpp/blob/master/example)
- In this example, you should run smsc first:
- Build and run SMSC Simulator:
```bash
g++ -std=c++11 example/smsc_simulator/smsc.cpp -o smsc
./smsc &
```
- Run smpp client in the example: https://github.com/linxGnu/gosmpp/blob/master/example/main.go
```bash
go run example/main.go
```
### Old version (0.1.3 and previous)
Full example could be found: [gist](https://gist.github.com/linxGnu/b488997a0e62b3f6a7060ba2af6391ea)
## Supported PDUs
- [x] bind_transmitter
- [x] bind_transmitter_resp
- [x] bind_receiver
- [x] bind_receiver_resp
- [x] bind_transceiver
- [x] bind_transceiver_resp
- [x] outbind
- [x] unbind
- [x] unbind_resp
- [x] submit_sm
- [x] submit_sm_resp
- [x] submit_sm_multi
- [x] submit_sm_multi_resp
- [x] data_sm
- [x] data_sm_resp
- [x] deliver_sm
- [x] deliver_sm_resp
- [x] query_sm
- [x] query_sm_resp
- [x] cancel_sm
- [x] cancel_sm_resp
- [x] replace_sm
- [x] replace_sm_resp
- [x] enquire_link
- [x] enquire_link_resp
- [x] alert_notification
- [x] generic_nack
================================================
FILE: connect.go
================================================
package gosmpp
import (
"fmt"
"net"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)
var (
// NonTLSDialer is non-tls connection dialer.
NonTLSDialer = func(addr string) (net.Conn, error) {
return net.Dial("tcp", addr)
}
)
// Dialer is connection dialer.
type Dialer func(addr string) (net.Conn, error)
// Auth represents basic authentication to SMSC.
type Auth struct {
// SMSC is SMSC address.
SMSC string
SystemID string
Password string
SystemType string
}
type BindError struct {
CommandStatus data.CommandStatusType
}
func (err BindError) Error() string {
return fmt.Sprintf("binding error (%s): %s", err.CommandStatus, err.CommandStatus.Desc())
}
func newBindRequest(s Auth, bindingType pdu.BindingType, addressRange pdu.AddressRange) (bindReq *pdu.BindRequest) {
bindReq = pdu.NewBindRequest(bindingType)
bindReq.SystemID = s.SystemID
bindReq.Password = s.Password
bindReq.SystemType = s.SystemType
bindReq.AddressRange = addressRange
return
}
// Connector is connection factory interface.
type Connector interface {
Connect() (conn *Connection, err error)
GetBindType() pdu.BindingType
}
type connector struct {
dialer Dialer
auth Auth
bindingType pdu.BindingType
addressRange pdu.AddressRange
}
func (c *connector) GetBindType() pdu.BindingType {
return c.bindingType
}
func (c *connector) Connect() (conn *Connection, err error) {
conn, err = connect(c.dialer, c.auth.SMSC, newBindRequest(c.auth, c.bindingType, c.addressRange))
return
}
func connect(dialer Dialer, addr string, bindReq *pdu.BindRequest) (c *Connection, err error) {
conn, err := dialer(addr)
if err != nil {
return
}
// create wrapped connection
c = NewConnection(conn)
// send binding request
_, err = c.WritePDU(bindReq)
if err != nil {
_ = conn.Close()
return
}
// catching response
var (
p pdu.PDU
resp *pdu.BindResp
)
for {
if p, err = pdu.Parse(c); err != nil {
_ = conn.Close()
return
}
if pd, ok := p.(*pdu.BindResp); ok {
resp = pd
break
}
}
if resp.CommandStatus != data.ESME_ROK {
err = BindError{CommandStatus: resp.CommandStatus}
_ = conn.Close()
} else {
c.systemID = resp.SystemID
}
return
}
// TXConnector returns a Transmitter (TX) connector.
func TXConnector(dialer Dialer, auth Auth) Connector {
return &connector{
dialer: dialer,
auth: auth,
bindingType: pdu.Transmitter,
}
}
// RXConnector returns a Receiver (RX) connector.
func RXConnector(dialer Dialer, auth Auth, opts ...connectorOption) Connector {
c := &connector{
dialer: dialer,
auth: auth,
bindingType: pdu.Receiver,
}
for _, opt := range opts {
opt(c)
}
return c
}
// TRXConnector returns a Transceiver (TRX) connector.
func TRXConnector(dialer Dialer, auth Auth, opts ...connectorOption) Connector {
c := &connector{
dialer: dialer,
auth: auth,
bindingType: pdu.Transceiver,
}
for _, opt := range opts {
opt(c)
}
return c
}
type connectorOption func(c *connector)
func WithAddressRange(addressRange pdu.AddressRange) connectorOption {
return func(c *connector) {
c.addressRange = addressRange
}
}
================================================
FILE: connect_test.go
================================================
package gosmpp
import (
"github.com/linxGnu/gosmpp/pdu"
"sync/atomic"
"testing"
"github.com/stretchr/testify/require"
)
var currentAuth int32
var auths = [][2]string{
{"689528", "1a97ae"},
}
const (
smscAddr = "127.0.0.1:2775"
mess = "Thử nghiệm: chuẩn bị nế mễ"
)
func nextAuth() Auth {
pair := int(atomic.AddInt32(¤tAuth, 1)) % len(auths)
return Auth{
SMSC: smscAddr,
SystemID: auths[pair][0],
Password: auths[pair][1],
SystemType: "",
}
}
func TestBindingSMSC(t *testing.T) {
checker := func(t *testing.T, c Connector) {
conn, err := c.Connect()
require.Nil(t, err)
require.NotNil(t, conn)
_ = conn.Close()
}
t.Run("TX", func(t *testing.T) {
checker(t, TXConnector(NonTLSDialer, nextAuth()))
})
t.Run("RX", func(t *testing.T) {
checker(t, RXConnector(NonTLSDialer, nextAuth()))
})
t.Run("RX", func(t *testing.T) {
addrRange := pdu.AddressRange{}
addrRange.AddressRange = "31218"
checker(t, RXConnector(NonTLSDialer, nextAuth(), WithAddressRange(addrRange)))
})
t.Run("TRX", func(t *testing.T) {
checker(t, TRXConnector(NonTLSDialer, nextAuth()))
})
t.Run("TRX", func(t *testing.T) {
addrRange := pdu.AddressRange{}
addrRange.AddressRange = "31218"
checker(t, TRXConnector(NonTLSDialer, nextAuth(), WithAddressRange(addrRange)))
})
}
func TestBindingSMSC_Error(t *testing.T) {
auth := Auth{SMSC: smscAddr, SystemID: "invalid"}
checker := func(t *testing.T, c Connector) {
conn, err := c.Connect()
require.ErrorContains(t, err, "Invalid System ID")
_ = conn.Close()
}
t.Run("TX", func(t *testing.T) {
checker(t, TXConnector(NonTLSDialer, auth))
})
t.Run("RX", func(t *testing.T) {
checker(t, RXConnector(NonTLSDialer, auth))
})
t.Run("TRX", func(t *testing.T) {
checker(t, TRXConnector(NonTLSDialer, auth))
})
}
func TestBindingType(t *testing.T) {
auth := Auth{SMSC: smscAddr, SystemID: "invalid"}
t.Run("TX", func(t *testing.T) {
c := TXConnector(NonTLSDialer, auth)
require.Equal(t, c.GetBindType(), pdu.Transmitter)
})
t.Run("RX", func(t *testing.T) {
c := RXConnector(NonTLSDialer, auth)
require.Equal(t, c.GetBindType(), pdu.Receiver)
})
t.Run("TRX", func(t *testing.T) {
c := TRXConnector(NonTLSDialer, auth)
require.Equal(t, c.GetBindType(), pdu.Transceiver)
})
}
================================================
FILE: connection.go
================================================
package gosmpp
import (
"bufio"
"net"
"time"
"github.com/linxGnu/gosmpp/pdu"
)
// Connection wraps over net.Conn with buffered data reader.
type Connection struct {
systemID string
conn net.Conn
reader *bufio.Reader
}
// NewConnection returns a Connection.
func NewConnection(conn net.Conn) (c *Connection) {
c = &Connection{
conn: conn,
reader: bufio.NewReaderSize(conn, 128<<10),
}
return
}
// Read reads data from the connection.
// Read can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *Connection) Read(b []byte) (n int, err error) {
n, err = c.reader.Read(b)
return
}
// Write writes data to the connection.
// Write can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
func (c *Connection) Write(b []byte) (n int, err error) {
n, err = c.conn.Write(b)
return
}
// WritePDU data to the connection.
func (c *Connection) WritePDU(p pdu.PDU) (n int, err error) {
buf := pdu.NewBuffer(make([]byte, 0, 64))
p.Marshal(buf)
n, err = c.conn.Write(buf.Bytes())
return
}
// Close closes the connection.
// Any blocked Read or Write operations will be unblocked and return errors.
func (c *Connection) Close() error {
return c.conn.Close()
}
// LocalAddr returns the local network address.
func (c *Connection) LocalAddr() net.Addr {
return c.conn.LocalAddr()
}
// RemoteAddr returns the remote network address.
func (c *Connection) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
}
// SetDeadline sets the read and write deadlines associated
// with the connection. It is equivalent to calling both
// SetReadDeadline and SetWriteDeadline.
//
// A deadline is an absolute time after which I/O operations
// fail with a timeout (see type Error) instead of
// blocking. The deadline applies to all future and pending
// I/O, not just the immediately following call to Read or
// Write. After a deadline has been exceeded, the connection
// can be refreshed by setting a deadline in the future.
//
// An idle timeout can be implemented by repeatedly extending
// the deadline after successful Read or Write calls.
//
// A zero value for t means I/O operations will not time out.
//
// Note that if a TCP connection has keep-alive turned on,
// which is the default unless overridden by Dialer.KeepAlive
// or ListenConfig.KeepAlive, then a keep-alive failure may
// also return a timeout error. On Unix systems a keep-alive
// failure on I/O can be detected using
// errors.Is(err, syscall.ETIMEDOUT).
func (c *Connection) SetDeadline(t time.Time) error {
return c.conn.SetDeadline(t)
}
// SetReadDeadline sets the deadline for future Read calls
// and any currently-blocked Read call.
// A zero value for t means Read will not time out.
func (c *Connection) SetReadDeadline(t time.Time) error {
return c.conn.SetReadDeadline(t)
}
// SetReadTimeout is equivalent to ReadDeadline(now + timeout)
func (c *Connection) SetReadTimeout(t time.Duration) error {
return c.conn.SetReadDeadline(time.Now().Add(t))
}
// SetWriteDeadline sets the deadline for future Write calls
// and any currently-blocked Write call.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
// A zero value for t means Write will not time out.
func (c *Connection) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
}
// SetWriteTimeout is equivalent to WriteDeadline(now + timeout)
func (c *Connection) SetWriteTimeout(t time.Duration) error {
return c.conn.SetWriteDeadline(time.Now().Add(t))
}
================================================
FILE: connection_test.go
================================================
package gosmpp
import (
"net"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestConnection(t *testing.T) {
conn, err := net.Dial("tcp", "smscsim.melroselabs.com:2775")
require.Nil(t, err)
c := NewConnection(conn)
defer func() {
_ = c.Close()
}()
t.Log(c.LocalAddr())
t.Log(c.RemoteAddr())
require.Nil(t, c.SetDeadline(time.Now().Add(5*time.Second)))
require.Nil(t, c.SetWriteDeadline(time.Now().Add(5*time.Second)))
require.Nil(t, c.SetReadDeadline(time.Now().Add(5*time.Second)))
}
================================================
FILE: data/7bit.go
================================================
package data
// Source code in this file is copied from: https://github.com/fiorix/go-smpp/master/smpp/encoding/gsm7.go
import (
"bytes"
"errors"
"math"
"golang.org/x/text/encoding"
"golang.org/x/text/transform"
)
// ErrInvalidCharacter means a given character can not be represented in GSM 7-bit encoding.
//
// This can only happen during encoding.
var ErrInvalidCharacter = errors.New("invalid gsm7 character")
// ErrInvalidByte means that a given byte is outside of the GSM 7-bit encoding range.
//
// This can only happen during decoding.
var ErrInvalidByte = errors.New("invalid gsm7 byte")
/*
GSM 7-bit default alphabet and extension table
Source: https://en.wikipedia.org/wiki/GSM_03.38#GSM_7-bit_default_alphabet_and_extension_table_of_3GPP_TS_23.038_/_GSM_03.38
*/
const escapeSequence = 0x1B
var forwardLookup = map[rune]byte{
'@': 0x00, '£': 0x01, '$': 0x02, '¥': 0x03, 'è': 0x04, 'é': 0x05, 'ù': 0x06, 'ì': 0x07,
'ò': 0x08, 'Ç': 0x09, '\n': 0x0a, 'Ø': 0x0b, 'ø': 0x0c, '\r': 0x0d, 'Å': 0x0e, 'å': 0x0f,
'Δ': 0x10, '_': 0x11, 'Φ': 0x12, 'Γ': 0x13, 'Λ': 0x14, 'Ω': 0x15, 'Π': 0x16, 'Ψ': 0x17,
'Σ': 0x18, 'Θ': 0x19, 'Ξ': 0x1a /* 0x1B */, 'Æ': 0x1c, 'æ': 0x1d, 'ß': 0x1e, 'É': 0x1f,
' ': 0x20, '!': 0x21, '"': 0x22, '#': 0x23, '¤': 0x24, '%': 0x25, '&': 0x26, '\'': 0x27,
'(': 0x28, ')': 0x29, '*': 0x2a, '+': 0x2b, ',': 0x2c, '-': 0x2d, '.': 0x2e, '/': 0x2f,
'0': 0x30, '1': 0x31, '2': 0x32, '3': 0x33, '4': 0x34, '5': 0x35, '6': 0x36, '7': 0x37,
'8': 0x38, '9': 0x39, ':': 0x3a, ';': 0x3b, '<': 0x3c, '=': 0x3d, '>': 0x3e, '?': 0x3f,
'¡': 0x40, 'A': 0x41, 'B': 0x42, 'C': 0x43, 'D': 0x44, 'E': 0x45, 'F': 0x46, 'G': 0x47,
'H': 0x48, 'I': 0x49, 'J': 0x4a, 'K': 0x4b, 'L': 0x4c, 'M': 0x4d, 'N': 0x4e, 'O': 0x4f,
'P': 0x50, 'Q': 0x51, 'R': 0x52, 'S': 0x53, 'T': 0x54, 'U': 0x55, 'V': 0x56, 'W': 0x57,
'X': 0x58, 'Y': 0x59, 'Z': 0x5a, 'Ä': 0x5b, 'Ö': 0x5c, 'Ñ': 0x5d, 'Ü': 0x5e, '§': 0x5f,
'¿': 0x60, 'a': 0x61, 'b': 0x62, 'c': 0x63, 'd': 0x64, 'e': 0x65, 'f': 0x66, 'g': 0x67,
'h': 0x68, 'i': 0x69, 'j': 0x6a, 'k': 0x6b, 'l': 0x6c, 'm': 0x6d, 'n': 0x6e, 'o': 0x6f,
'p': 0x70, 'q': 0x71, 'r': 0x72, 's': 0x73, 't': 0x74, 'u': 0x75, 'v': 0x76, 'w': 0x77,
'x': 0x78, 'y': 0x79, 'z': 0x7a, 'ä': 0x7b, 'ö': 0x7c, 'ñ': 0x7d, 'ü': 0x7e, 'à': 0x7f,
}
var forwardEscape = map[rune]byte{
'\f': 0x0A, '^': 0x14, '{': 0x28, '}': 0x29, '\\': 0x2F, '[': 0x3C, '~': 0x3D, ']': 0x3E, '|': 0x40, '€': 0x65,
}
var reverseLookup = map[byte]rune{
0x00: '@', 0x01: '£', 0x02: '$', 0x03: '¥', 0x04: 'è', 0x05: 'é', 0x06: 'ù', 0x07: 'ì',
0x08: 'ò', 0x09: 'Ç', 0x0a: '\n', 0x0b: 'Ø', 0x0c: 'ø', 0x0d: '\r', 0x0e: 'Å', 0x0f: 'å',
0x10: 'Δ', 0x11: '_', 0x12: 'Φ', 0x13: 'Γ', 0x14: 'Λ', 0x15: 'Ω', 0x16: 'Π', 0x17: 'Ψ',
0x18: 'Σ', 0x19: 'Θ', 0x1a: 'Ξ' /* 0x1B */, 0x1c: 'Æ', 0x1d: 'æ', 0x1e: 'ß', 0x1f: 'É',
0x20: ' ', 0x21: '!', 0x22: '"', 0x23: '#', 0x24: '¤', 0x25: '%', 0x26: '&', 0x27: '\'',
0x28: '(', 0x29: ')', 0x2a: '*', 0x2b: '+', 0x2c: ',', 0x2d: '-', 0x2e: '.', 0x2f: '/',
0x30: '0', 0x31: '1', 0x32: '2', 0x33: '3', 0x34: '4', 0x35: '5', 0x36: '6', 0x37: '7',
0x38: '8', 0x39: '9', 0x3a: ':', 0x3b: ';', 0x3c: '<', 0x3d: '=', 0x3e: '>', 0x3f: '?',
0x40: '¡', 0x41: 'A', 0x42: 'B', 0x43: 'C', 0x44: 'D', 0x45: 'E', 0x46: 'F', 0x47: 'G',
0x48: 'H', 0x49: 'I', 0x4a: 'J', 0x4b: 'K', 0x4c: 'L', 0x4d: 'M', 0x4e: 'N', 0x4f: 'O',
0x50: 'P', 0x51: 'Q', 0x52: 'R', 0x53: 'S', 0x54: 'T', 0x55: 'U', 0x56: 'V', 0x57: 'W',
0x58: 'X', 0x59: 'Y', 0x5a: 'Z', 0x5b: 'Ä', 0x5c: 'Ö', 0x5d: 'Ñ', 0x5e: 'Ü', 0x5f: '§',
0x60: '¿', 0x61: 'a', 0x62: 'b', 0x63: 'c', 0x64: 'd', 0x65: 'e', 0x66: 'f', 0x67: 'g',
0x68: 'h', 0x69: 'i', 0x6a: 'j', 0x6b: 'k', 0x6c: 'l', 0x6d: 'm', 0x6e: 'n', 0x6f: 'o',
0x70: 'p', 0x71: 'q', 0x72: 'r', 0x73: 's', 0x74: 't', 0x75: 'u', 0x76: 'v', 0x77: 'w',
0x78: 'x', 0x79: 'y', 0x7a: 'z', 0x7b: 'ä', 0x7c: 'ö', 0x7d: 'ñ', 0x7e: 'ü', 0x7f: 'à',
}
var reverseEscape = map[byte]rune{
0x0A: '\f', 0x14: '^', 0x28: '{', 0x29: '}', 0x2F: '\\', 0x3C: '[', 0x3D: '~', 0x3E: ']', 0x40: '|', 0x65: '€',
}
// ValidateGSM7String returns the characters, in the given text, that can not be represented in GSM 7-bit encoding.
func ValidateGSM7String(text string) []rune {
invalidChars := make([]rune, 0, 4)
for _, r := range text {
if _, ok := forwardLookup[r]; !ok {
if _, ok := forwardEscape[r]; !ok {
invalidChars = append(invalidChars, r)
}
}
}
return invalidChars
}
// ValidateGSM7Buffer returns the bytes, in the given buffer, that are outside of the GSM 7-bit encoding range.
func ValidateGSM7Buffer(buffer []byte) []byte {
invalidBytes := make([]byte, 0, 4)
count := 0
for count < len(buffer) {
b := buffer[count]
if b == escapeSequence {
count++
if count >= len(buffer) {
invalidBytes = append(invalidBytes, b)
break
}
e := buffer[count]
if _, ok := reverseEscape[e]; !ok {
invalidBytes = append(invalidBytes, b, e)
}
} else if _, ok := reverseLookup[b]; !ok {
invalidBytes = append(invalidBytes, b)
}
count++
}
return invalidBytes
}
// GetEscapeChars returns the escape characters in the given text, that doesn't exist in GSM 7-bit DEFAULT alphabet table
func GetEscapeChars(runeText []rune) []rune {
eChars := make([]rune, 0, 4)
for _, r := range runeText {
if _, ok := forwardEscape[r]; ok {
eChars = append(eChars, r)
}
}
return eChars
}
// IsEscapeChar checks if the given rune is an escape char
func IsEscapeChar(c rune) bool {
_, exists := forwardEscape[c]
return exists
}
// GSM7 returns a GSM 7-bit Bit Encoding.
//
// Set the packed flag to true if you wish to convert septets to octets,
// this should be false for most SMPP providers.
func GSM7(packed bool) encoding.Encoding {
return gsm7Encoding{packed: packed}
}
type gsm7Encoding struct {
packed bool
}
func (g gsm7Encoding) NewDecoder() *encoding.Decoder {
return &encoding.Decoder{Transformer: &gsm7Decoder{
packed: g.packed,
}}
}
func (g gsm7Encoding) NewEncoder() *encoding.Encoder {
return &encoding.Encoder{Transformer: &gsm7Encoder{
packed: g.packed,
}}
}
func (g gsm7Encoding) String() string {
if g.packed {
return "GSM 7-bit (Packed)"
}
return "GSM 7-bit (Unpacked)"
}
type gsm7Decoder struct {
packed bool
}
func (g *gsm7Decoder) Reset() { /* not needed */ }
func unpack(src []byte, packed bool) (septets []byte) {
septets = src
if packed {
septets = make([]byte, 0, len(src))
count := 0
for remain := len(src) - count; remain > 0; {
// Unpack by converting octets into septets.
switch {
case remain >= 7:
septets = append(septets, src[count+0]&0x7F<<0)
septets = append(septets, (src[count+1]&0x3F<<1)|(src[count+0]&0x80>>7))
septets = append(septets, (src[count+2]&0x1F<<2)|(src[count+1]&0xC0>>6))
septets = append(septets, (src[count+3]&0x0F<<3)|(src[count+2]&0xE0>>5))
septets = append(septets, (src[count+4]&0x07<<4)|(src[count+3]&0xF0>>4))
septets = append(septets, (src[count+5]&0x03<<5)|(src[count+4]&0xF8>>3))
septets = append(septets, (src[count+6]&0x01<<6)|(src[count+5]&0xFC>>2))
if src[count+6] > 0 {
septets = append(septets, src[count+6]&0xFE>>1)
}
count += 7
case remain >= 6:
septets = append(septets, src[count+0]&0x7F<<0)
septets = append(septets, (src[count+1]&0x3F<<1)|(src[count+0]&0x80>>7))
septets = append(septets, (src[count+2]&0x1F<<2)|(src[count+1]&0xC0>>6))
septets = append(septets, (src[count+3]&0x0F<<3)|(src[count+2]&0xE0>>5))
septets = append(septets, (src[count+4]&0x07<<4)|(src[count+3]&0xF0>>4))
septets = append(septets, (src[count+5]&0x03<<5)|(src[count+4]&0xF8>>3))
count += 6
case remain >= 5:
septets = append(septets, src[count+0]&0x7F<<0)
septets = append(septets, (src[count+1]&0x3F<<1)|(src[count+0]&0x80>>7))
septets = append(septets, (src[count+2]&0x1F<<2)|(src[count+1]&0xC0>>6))
septets = append(septets, (src[count+3]&0x0F<<3)|(src[count+2]&0xE0>>5))
septets = append(septets, (src[count+4]&0x07<<4)|(src[count+3]&0xF0>>4))
count += 5
case remain >= 4:
septets = append(septets, src[count+0]&0x7F<<0)
septets = append(septets, (src[count+1]&0x3F<<1)|(src[count+0]&0x80>>7))
septets = append(septets, (src[count+2]&0x1F<<2)|(src[count+1]&0xC0>>6))
septets = append(septets, (src[count+3]&0x0F<<3)|(src[count+2]&0xE0>>5))
count += 4
case remain >= 3:
septets = append(septets, src[count+0]&0x7F<<0)
septets = append(septets, (src[count+1]&0x3F<<1)|(src[count+0]&0x80>>7))
septets = append(septets, (src[count+2]&0x1F<<2)|(src[count+1]&0xC0>>6))
count += 3
case remain >= 2:
septets = append(septets, src[count+0]&0x7F<<0)
septets = append(septets, (src[count+1]&0x3F<<1)|(src[count+0]&0x80>>7))
count += 2
case remain >= 1:
septets = append(septets, src[count+0]&0x7F<<0)
count++
default:
return
}
remain = len(src) - count
}
}
return
}
func (g *gsm7Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
if len(src) == 0 {
return 0, 0, nil
}
septets := unpack(src, g.packed)
nSeptet := 0
builder := bytes.NewBufferString("")
for nSeptet < len(septets) {
b := septets[nSeptet]
if b == escapeSequence {
nSeptet++
if nSeptet >= len(septets) {
return 0, 0, ErrInvalidByte
}
e := septets[nSeptet]
if r, ok := reverseEscape[e]; ok {
builder.WriteRune(r)
} else {
return 0, 0, ErrInvalidByte
}
} else if r, ok := reverseLookup[b]; ok {
builder.WriteRune(r)
} else {
return 0, 0, ErrInvalidByte
}
nSeptet++
}
text := builder.Bytes()
nDst = len(text)
if len(dst) < nDst {
return 0, 0, transform.ErrShortDst
}
copy(dst, text)
return
}
type gsm7Encoder struct {
packed bool
}
func (g *gsm7Encoder) Reset() {
/* no needed */
}
func pack(dst []byte, septets []byte) (nDst int) {
nSeptet := 0
for remain := len(septets); remain > 0; {
// Pack by converting septets into octets.
switch {
case remain >= 8:
dst[nDst+0] = (septets[nSeptet+0] & 0x7F >> 0) | (septets[nSeptet+1] & 0x01 << 7)
dst[nDst+1] = (septets[nSeptet+1] & 0x7E >> 1) | (septets[nSeptet+2] & 0x03 << 6)
dst[nDst+2] = (septets[nSeptet+2] & 0x7C >> 2) | (septets[nSeptet+3] & 0x07 << 5)
dst[nDst+3] = (septets[nSeptet+3] & 0x78 >> 3) | (septets[nSeptet+4] & 0x0F << 4)
dst[nDst+4] = (septets[nSeptet+4] & 0x70 >> 4) | (septets[nSeptet+5] & 0x1F << 3)
dst[nDst+5] = (septets[nSeptet+5] & 0x60 >> 5) | (septets[nSeptet+6] & 0x3F << 2)
dst[nDst+6] = (septets[nSeptet+6] & 0x40 >> 6) | (septets[nSeptet+7] & 0x7F << 1)
nSeptet += 8
nDst += 7
case remain >= 7:
dst[nDst+0] = (septets[nSeptet+0] & 0x7F >> 0) | (septets[nSeptet+1] & 0x01 << 7)
dst[nDst+1] = (septets[nSeptet+1] & 0x7E >> 1) | (septets[nSeptet+2] & 0x03 << 6)
dst[nDst+2] = (septets[nSeptet+2] & 0x7C >> 2) | (septets[nSeptet+3] & 0x07 << 5)
dst[nDst+3] = (septets[nSeptet+3] & 0x78 >> 3) | (septets[nSeptet+4] & 0x0F << 4)
dst[nDst+4] = (septets[nSeptet+4] & 0x70 >> 4) | (septets[nSeptet+5] & 0x1F << 3)
dst[nDst+5] = (septets[nSeptet+5] & 0x60 >> 5) | (septets[nSeptet+6] & 0x3F << 2)
dst[nDst+6] = septets[nSeptet+6] & 0x40 >> 6
nSeptet += 7
nDst += 7
case remain >= 6:
dst[nDst+0] = (septets[nSeptet+0] & 0x7F >> 0) | (septets[nSeptet+1] & 0x01 << 7)
dst[nDst+1] = (septets[nSeptet+1] & 0x7E >> 1) | (septets[nSeptet+2] & 0x03 << 6)
dst[nDst+2] = (septets[nSeptet+2] & 0x7C >> 2) | (septets[nSeptet+3] & 0x07 << 5)
dst[nDst+3] = (septets[nSeptet+3] & 0x78 >> 3) | (septets[nSeptet+4] & 0x0F << 4)
dst[nDst+4] = (septets[nSeptet+4] & 0x70 >> 4) | (septets[nSeptet+5] & 0x1F << 3)
dst[nDst+5] = septets[nSeptet+5] & 0x60 >> 5
nSeptet += 6
nDst += 6
case remain >= 5:
dst[nDst+0] = (septets[nSeptet+0] & 0x7F >> 0) | (septets[nSeptet+1] & 0x01 << 7)
dst[nDst+1] = (septets[nSeptet+1] & 0x7E >> 1) | (septets[nSeptet+2] & 0x03 << 6)
dst[nDst+2] = (septets[nSeptet+2] & 0x7C >> 2) | (septets[nSeptet+3] & 0x07 << 5)
dst[nDst+3] = (septets[nSeptet+3] & 0x78 >> 3) | (septets[nSeptet+4] & 0x0F << 4)
dst[nDst+4] = septets[nSeptet+4] & 0x70 >> 4
nSeptet += 5
nDst += 5
case remain >= 4:
dst[nDst+0] = (septets[nSeptet+0] & 0x7F >> 0) | (septets[nSeptet+1] & 0x01 << 7)
dst[nDst+1] = (septets[nSeptet+1] & 0x7E >> 1) | (septets[nSeptet+2] & 0x03 << 6)
dst[nDst+2] = (septets[nSeptet+2] & 0x7C >> 2) | (septets[nSeptet+3] & 0x07 << 5)
dst[nDst+3] = septets[nSeptet+3] & 0x78 >> 3
nSeptet += 4
nDst += 4
case remain >= 3:
dst[nDst+0] = (septets[nSeptet+0] & 0x7F >> 0) | (septets[nSeptet+1] & 0x01 << 7)
dst[nDst+1] = (septets[nSeptet+1] & 0x7E >> 1) | (septets[nSeptet+2] & 0x03 << 6)
dst[nDst+2] = septets[nSeptet+2] & 0x7C >> 2
nSeptet += 3
nDst += 3
case remain >= 2:
dst[nDst+0] = (septets[nSeptet+0] & 0x7F >> 0) | (septets[nSeptet+1] & 0x01 << 7)
dst[nDst+1] = septets[nSeptet+1] & 0x7E >> 1
nSeptet += 2
nDst += 2
case remain >= 1:
dst[nDst+0] = septets[nSeptet+0] & 0x7F >> 0
nSeptet++
nDst++
default:
return
}
remain = len(septets) - nSeptet
}
return
}
func (g *gsm7Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
if len(src) == 0 {
return 0, 0, nil
}
text := string(src) // work with []rune (a.k.a string) instead of []byte
septets := make([]byte, 0, len(text))
for _, r := range text {
if v, ok := forwardLookup[r]; ok {
septets = append(septets, v)
} else if v, ok := forwardEscape[r]; ok {
septets = append(septets, escapeSequence, v)
} else {
return 0, 0, ErrInvalidCharacter
}
nSrc++
}
nDst = len(septets)
if g.packed {
nDst = int(math.Ceil(float64(len(septets)) * 7 / 8))
}
if len(dst) < nDst {
return 0, 0, transform.ErrShortDst
}
if !g.packed {
copy(dst, septets)
return nDst, nSrc, nil
}
nDst = pack(dst, septets)
return
}
================================================
FILE: data/7bit_test.go
================================================
package data
// Source code in this file is copied from: https://github.com/fiorix
import (
"encoding/hex"
"fmt"
"reflect"
"testing"
"golang.org/x/text/transform"
)
var validationStringTests = []struct {
Text string
Expected []rune
}{
{Text: "12345678", Expected: []rune{}},
{Text: "12345[6]", Expected: []rune{}},
{Text: "@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞ\f^{}\\[~]|€ÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà", Expected: []rune{}},
{Text: "你", Expected: []rune{'你'}},
}
var validationBufferTests = []struct {
Buffer []byte
Expected []byte
}{
{Buffer: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, Expected: []byte{}},
{Buffer: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x1B, 0x3C, 0x36, 0x1B, 0x3E}, Expected: []byte{}},
{Buffer: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x1B}, Expected: []byte{0x1B}},
{Buffer: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x1B, 0x00}, Expected: []byte{0x1B, 0x00}},
{Buffer: []byte{0x80, 0x81, 0x82, 0x83}, Expected: []byte{0x80, 0x81, 0x82, 0x83}},
}
var packedTests = []struct {
Text string
Buff []byte
}{
{Text: "", Buff: []byte{}},
{Text: "1", Buff: []byte{0x31}},
{Text: "12", Buff: []byte{0x31, 0x19}},
{Text: "123", Buff: []byte{0x31, 0xD9, 0x0C}},
{Text: "1234", Buff: []byte{0x31, 0xD9, 0x8C, 0x06}},
{Text: "12345", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0x03}},
{Text: "123456", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0x01}},
{Text: "1234567", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0xDD, 0x00}},
{Text: "12345678", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0xDD, 0x70}},
{Text: "123456789", Buff: []byte{0x31, 0xD9, 0x8C, 0x56, 0xB3, 0xDD, 0x70, 0x39}},
{Text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur nec nunc venenatis, ultricies ipsum id, volutpat ante. Sed pretium ac metus a interdum metus.", Buff: []byte("\xCC\xB7\xBC\xDC\x06\xA5\xE1\xF3\x7A\x1B\x44\x7E\xB3\xDF\x72\xD0\x3C\x4D\x07\x85\xDB\x65\x3A\x0B\x34\x7E\xBB\xE7\xE5\x31\xBD\x4C\xAF\xCB\x41\x61\x72\x1A\x9E\x9E\x8F\xD3\xEE\x33\xA8\xCC\x4E\xD3\x5D\xA0\x61\x5D\x1E\x16\xA7\xE9\x75\x39\xC8\x5D\x1E\x83\xDC\x75\xF7\x18\x64\x2F\xBB\xCB\xEE\x30\x3D\x3D\x67\x81\xEA\x6C\xBA\x3C\x3D\x4E\x97\xE7\xA0\x34\x7C\x5E\x6F\x83\xD2\x64\x16\xC8\xFE\x66\xD7\xE9\xF0\x30\x1D\x14\x76\xD3\xCB\x2E\xD0\xB4\x4C\x06\xC1\xE5\x65\x7A\xBA\xDE\x06\x85\xC7\xA0\x76\x99\x5E\x9F\x83\xC2\xA0\xB4\x9B\x5E\x96\x93\xEB\x6D\x50\xBB\x4C\xAF\xCF\x5D")},
{Text: "\n", Buff: []byte{0x0A}},
{Text: "\r", Buff: []byte{0x0D}},
{Text: "\f", Buff: []byte{0x1B, 0x05}},
{Text: "^{}\\[~]|€", Buff: []byte{0x1B, 0xCA, 0x06, 0xB5, 0x49, 0x6D, 0x5E, 0x1B, 0xDE, 0xA6, 0xB7, 0xF1, 0x6D, 0x80, 0x9B, 0x32}},
{Text: "@£$¥èéùìòÇØøÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà", Buff: []byte("\x80\x80\x60\x40\x28\x18\x0E\x88\xC4\x82\xE1\x78\x40\x22\x92\x09\xA5\x62\xB9\x60\x32\x1A\x4E\xC7\xF3\x01\x85\x44\x23\x52\xC9\x74\x42\xA5\x54\x2B\x56\xCB\xF5\x82\xC5\x64\x33\x5A\xCD\x76\xC3\xE5\x74\x3B\x5E\xCF\xF7\x03\x06\x85\x43\x62\xD1\x78\x44\x26\x95\x4B\x66\xD3\xF9\x84\x46\xA5\x53\x6A\xD5\x7A\xC5\x66\xB5\x5B\x6E\xD7\xFB\x05\x87\xC5\x63\x72\xD9\x7C\x46\xA7\xD5\x6B\x76\xDB\xFD\x86\xC7\xE5\x73\x7A\xDD\x7E\xC7\xE7\xF5\x7B\x7E\xDF\xFF\x07")},
}
var unpackedTests = []struct {
Text string
Buff []byte
}{
{Text: "", Buff: []byte{}},
{Text: "1", Buff: []byte{0x31}},
{Text: "12", Buff: []byte{0x31, 0x32}},
{Text: "123", Buff: []byte{0x31, 0x32, 0x33}},
{Text: "1234", Buff: []byte{0x31, 0x32, 0x33, 0x34}},
{Text: "12345", Buff: []byte{0x31, 0x32, 0x33, 0x34, 0x35}},
{Text: "123456", Buff: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36}},
{Text: "1234567", Buff: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37}},
{Text: "12345678", Buff: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}},
{Text: "123456789", Buff: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}},
{Text: "12345[6", Buff: []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x1B, 0x3C, 0x36}},
{Text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur nec nunc venenatis, ultricies ipsum id, volutpat ante. Sed pretium ac metus a interdum metus.", Buff: []byte("\x4C\x6F\x72\x65\x6D\x20\x69\x70\x73\x75\x6D\x20\x64\x6F\x6C\x6F\x72\x20\x73\x69\x74\x20\x61\x6D\x65\x74\x2C\x20\x63\x6F\x6E\x73\x65\x63\x74\x65\x74\x75\x72\x20\x61\x64\x69\x70\x69\x73\x63\x69\x6E\x67\x20\x65\x6C\x69\x74\x2E\x20\x43\x75\x72\x61\x62\x69\x74\x75\x72\x20\x6E\x65\x63\x20\x6E\x75\x6E\x63\x20\x76\x65\x6E\x65\x6E\x61\x74\x69\x73\x2C\x20\x75\x6C\x74\x72\x69\x63\x69\x65\x73\x20\x69\x70\x73\x75\x6D\x20\x69\x64\x2C\x20\x76\x6F\x6C\x75\x74\x70\x61\x74\x20\x61\x6E\x74\x65\x2E\x20\x53\x65\x64\x20\x70\x72\x65\x74\x69\x75\x6D\x20\x61\x63\x20\x6D\x65\x74\x75\x73\x20\x61\x20\x69\x6E\x74\x65\x72\x64\x75\x6D\x20\x6D\x65\x74\x75\x73\x2E")},
{Text: "\n", Buff: []byte{0x0A}},
{Text: "\r", Buff: []byte{0x0D}},
{Text: "\f", Buff: []byte{0x1B, 0x0A}},
{Text: "^{}\\[~]|€", Buff: []byte{0x1B, 0x14, 0x1B, 0x28, 0x1B, 0x29, 0x1B, 0x2F, 0x1B, 0x3C, 0x1B, 0x3D, 0x1B, 0x3E, 0x1B, 0x40, 0x1B, 0x65}},
{Text: "@£$¥èéùìòÇØøÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà", Buff: []byte("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F")},
}
var invalidCharacterTests = []struct {
Packed bool
Text string
}{
{Packed: true, Text: "你"},
{Packed: false, Text: "你"},
}
var invalidByteTests = []struct {
Packed bool
Buff []byte
}{
{Packed: false, Buff: []byte{0x80}},
{Packed: false, Buff: []byte{0x1B}},
{Packed: false, Buff: []byte{0x1B, 0x80}},
}
func TestGSM7EncodingString(t *testing.T) {
tests := []struct {
Packed bool
Expected string
}{
{Packed: true, Expected: "GSM 7-bit (Packed)"},
{Packed: false, Expected: "GSM 7-bit (Unpacked)"},
}
for index, row := range tests {
actual := fmt.Sprint(GSM7(row.Packed))
if actual != row.Expected {
t.Fatalf("%d: expected '%s' but got '%s'", index, row.Expected, actual)
}
}
}
func TestValidateGSM7String(t *testing.T) {
for index, row := range validationStringTests {
actual := ValidateGSM7String(row.Text)
if !reflect.DeepEqual(actual, row.Expected) {
t.Fatalf("%2d: actual did not equal expected.\nactual: %s\nexpect: %s", index, string(actual), string(row.Expected))
}
}
}
func TestValidateGSM7Buffer(t *testing.T) {
for index, row := range validationBufferTests {
actual := ValidateGSM7Buffer(row.Buffer)
if !reflect.DeepEqual(actual, row.Expected) {
t.Fatalf("%2d: actual did not equal expected.\nactual: %s\nexpect: %s", index, hex.EncodeToString(actual), hex.EncodeToString(row.Expected))
}
}
}
func TestPackedEncoder(t *testing.T) {
encoder := GSM7(true).NewEncoder()
for index, row := range packedTests {
es, _, err := transform.Bytes(encoder, []byte(row.Text))
if err != nil {
t.Fatalf("%2d: unexpected error: '%s'", index, err.Error())
}
if !reflect.DeepEqual(es, row.Buff) {
t.Fatalf("%2d: actual did not equal expected.\nactual: %s\nexpect: %s", index, hex.EncodeToString(es), hex.EncodeToString(row.Buff))
}
}
}
func TestUnpackedEncoder(t *testing.T) {
encoder := GSM7(false).NewEncoder()
for index, row := range unpackedTests {
es, _, err := transform.Bytes(encoder, []byte(row.Text))
if err != nil {
t.Fatalf("%2d: unexpected error: '%s'", index, err.Error())
}
if !reflect.DeepEqual(es, row.Buff) {
t.Fatalf("%2d: actual did not equal expected.\nactual: %s\nexpect: %s", index, hex.EncodeToString(es), hex.EncodeToString(row.Buff))
}
}
}
func TestPackedDecoder(t *testing.T) {
decoder := GSM7(true).NewDecoder()
for index, row := range packedTests {
es, _, err := transform.Bytes(decoder, row.Buff)
if err != nil {
t.Fatalf("%2d: unexpected error: '%s'", index, err.Error())
}
if string(es) != row.Text {
t.Fatalf("%2d: actual did not equal expected.\nactual: %s\nexpect: %s", index, string(es), row.Text)
}
}
}
func TestUnpackedDecoder(t *testing.T) {
encoder := GSM7(false).NewDecoder()
for index, row := range unpackedTests {
es, _, err := transform.Bytes(encoder, row.Buff)
if err != nil {
t.Fatalf("%2d: unexpected error: '%s'", index, err.Error())
}
if string(es) != row.Text {
t.Fatalf("%2d: actual did not equal expected.\nactual: %s\nexpect: %s", index, string(es), row.Text)
}
}
}
func TestInvalidCharacter(t *testing.T) {
for index, row := range invalidCharacterTests {
encoder := GSM7(row.Packed).NewEncoder()
_, _, err := transform.Bytes(encoder, []byte(row.Text))
if err == nil {
t.Fatalf("%2d: expected error but got no error", index)
}
if err != ErrInvalidCharacter {
t.Fatalf("%2d: expected '%s' but got '%s'", index, ErrInvalidCharacter, err.Error())
}
}
}
func TestInvalidByte(t *testing.T) {
for index, row := range invalidByteTests {
decoder := GSM7(row.Packed).NewDecoder()
_, _, err := transform.Bytes(decoder, row.Buff)
if err == nil {
t.Fatalf("%2d: expected error but got no error", index)
}
if err != ErrInvalidByte {
t.Fatalf("%2d: expected '%s' but got '%s'", index, ErrInvalidByte, err.Error())
}
}
}
================================================
FILE: data/codings.go
================================================
package data
import (
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/encoding/unicode"
)
const (
// GSM7BITCoding is gsm-7bit coding
GSM7BITCoding byte = 0x00
// ASCIICoding is ascii coding
ASCIICoding byte = 0x01
// BINARY8BIT1Coding is 8-bit binary coding
BINARY8BIT1Coding byte = 0x02
// LATIN1Coding is iso-8859-1 coding
LATIN1Coding byte = 0x03
// BINARY8BIT2Coding is 8-bit binary coding
BINARY8BIT2Coding byte = 0x04
// CYRILLICCoding is iso-8859-5 coding
CYRILLICCoding byte = 0x06
// HEBREWCoding is iso-8859-8 coding
HEBREWCoding byte = 0x07
// UCS2Coding is UCS2 coding
UCS2Coding byte = 0x08
)
// EncDec wraps encoder and decoder interface.
type EncDec interface {
Encode(str string) ([]byte, error)
Decode([]byte) (string, error)
}
// Encoding interface.
type Encoding interface {
EncDec
DataCoding() byte
}
func encode(str string, encoder *encoding.Encoder) ([]byte, error) {
return encoder.Bytes([]byte(str))
}
func decode(data []byte, decoder *encoding.Decoder) (st string, err error) {
tmp, err := decoder.Bytes(data)
if err == nil {
st = string(tmp)
}
return
}
// CustomEncoding is wrapper for user-defined data encoding.
type CustomEncoding struct {
encDec EncDec
coding byte
}
// NewCustomEncoding creates new custom encoding.
func NewCustomEncoding(coding byte, encDec EncDec) Encoding {
return &CustomEncoding{
coding: coding,
encDec: encDec,
}
}
// Encode string.
func (c *CustomEncoding) Encode(str string) ([]byte, error) {
return c.encDec.Encode(str)
}
// Decode data to string.
func (c *CustomEncoding) Decode(data []byte) (string, error) {
return c.encDec.Decode(data)
}
// DataCoding flag.
func (c *CustomEncoding) DataCoding() byte {
return c.coding
}
type gsm7bit struct {
packed bool
}
func (c *gsm7bit) Encode(str string) ([]byte, error) {
return encode(str, GSM7(c.packed).NewEncoder())
}
func (c *gsm7bit) Decode(data []byte) (string, error) {
return decode(data, GSM7(c.packed).NewDecoder())
}
func (c *gsm7bit) DataCoding() byte { return GSM7BITCoding }
func (c *gsm7bit) ShouldSplit(text string, octetLimit uint) (shouldSplit bool) {
if c.packed {
return uint((len(text)*7+7)/8) > octetLimit
} else {
return uint(len(text)) > octetLimit
}
}
func (c *gsm7bit) EncodeSplit(text string, octetLimit uint) (allSeg [][]byte, err error) {
if octetLimit < 64 {
octetLimit = 134
}
allSeg = [][]byte{}
runeSlice := []rune(text)
fr, to := 0, int(octetLimit)
for fr < len(runeSlice) {
if to > len(runeSlice) {
to = len(runeSlice)
}
seg, err := c.Encode(string(runeSlice[fr:to]))
if err != nil {
return nil, err
}
allSeg = append(allSeg, seg)
fr, to = to, to+int(octetLimit)
}
return
}
type gsm7bitPacked struct {
}
func (c *gsm7bitPacked) Encode(str string) ([]byte, error) {
return encode(str, GSM7(true).NewEncoder())
}
func (c *gsm7bitPacked) Decode(data []byte) (string, error) {
return decode(data, GSM7(true).NewDecoder())
}
func (c *gsm7bitPacked) DataCoding() byte { return GSM7BITCoding }
func (c *gsm7bitPacked) ShouldSplit(text string, octetLimit uint) (shouldSplit bool) {
runeSlice := []rune(text)
tLen := len(runeSlice)
escCharsLen := len(GetEscapeChars(runeSlice))
regCharsLen := tLen - escCharsLen
// Esacpe characters occupy 2 octets/septets
// https://en.wikipedia.org/wiki/GSM_03.38
// https://www.developershome.com/sms/gsmAlphabet.asp
return uint((regCharsLen*7+escCharsLen*2*7+7)/8) > octetLimit
}
func (c *gsm7bitPacked) GetSeptetCount(runeSlice []rune) int {
tLen := len(runeSlice)
escCharsLen := len(GetEscapeChars(runeSlice))
regCharsLen := tLen - escCharsLen
return escCharsLen*2 + regCharsLen
}
func (c *gsm7bitPacked) EncodeSplit(text string, octetLimit uint) (allSeg [][]byte, err error) {
if octetLimit < 64 {
octetLimit = 134
}
allSeg = [][]byte{}
runeSlice := []rune(text)
lim := int(octetLimit * 8 / 7)
fr, to := 0, lim
for fr < len(runeSlice) {
if to > len(runeSlice) {
to = len(runeSlice)
}
to = determineTo(fr, to, lim, runeSlice)
seg, err := c.Encode(string(runeSlice[fr:to]))
if err != nil {
return nil, err
}
includeLSB := false
nSeptet := c.GetSeptetCount(runeSlice[fr:to])
if nSeptet != lim && nSeptet%8 == 0 { // The last octet's LSB should be included during shift
includeLSB = true
}
seg = shiftBitsLeftOne(seg, includeLSB)
allSeg = append(allSeg, seg)
fr, to = to, to+lim
}
return
}
func determineTo(from int, to int, lim int, runeSlice []rune) int {
nSeptet := 0
for nSeptet < lim {
if IsEscapeChar(runeSlice[from]) { // esc chars counted as 2 septes
nSeptet += 2
} else {
nSeptet++
}
from++
if from == to {
break
}
}
to = from
if IsEscapeChar(runeSlice[to-1]) { // 9.2.3.24.1 Concatenated Short Messages "A character represented by an escape-sequence shall not be split in the middle."
if nSeptet > lim {
to--
}
}
return to
}
// Shifts the given byte stream one position left, in order to put a padding bit in between UDH and the beginning of the septets of an actual message
// Ref1: https://www.etsi.org/deliver/etsi_ts/123000_123099/123040/16.00.00_60/ts_123040v160000p.pdf Page 74
// Ref2: https://help.goacoustic.com/hc/en-us/articles/360043843154--How-character-encoding-affects-SMS-message-length Pls. ref. to the note "..It is added as padding so that the actual 7-bit encoding data begins on a septet boundary—the 50th bit."
// Ref3: https://en.wikipedia.org/wiki/Concatenated_SMS "..This means up to 6 bits of zeros need to be inserted at the start of the [message]."
func shiftBitsLeftOne(input []byte, includeLSB bool) []byte {
shifted := make([]byte, len(input))
for i, b := range input {
shifted[i] = b << 1
if i > 0 {
shifted[i] |= input[i-1] >> 7
}
}
if includeLSB {
lastOctet := (input[len(input)-1] >> 7 & 0x01) | (0x0D << 1) /* https://en.wikipedia.org/wiki/GSM_03.38 Ref tekst: "..When there are 7 spare bits in the last octet of a message..."*/
shifted = append(shifted, lastOctet)
}
return shifted
}
type ascii struct{}
func (*ascii) Encode(str string) ([]byte, error) {
return []byte(str), nil
}
func (*ascii) Decode(data []byte) (string, error) {
return string(data), nil
}
func (*ascii) DataCoding() byte { return ASCIICoding }
type iso88591 struct{}
func (*iso88591) Encode(str string) ([]byte, error) {
return encode(str, charmap.ISO8859_1.NewEncoder())
}
func (*iso88591) Decode(data []byte) (string, error) {
return decode(data, charmap.ISO8859_1.NewDecoder())
}
func (*iso88591) DataCoding() byte { return LATIN1Coding }
type binary8bit1 struct{}
func (*binary8bit1) Encode(_ string) ([]byte, error) {
return []byte{}, ErrNotImplEncode
}
func (*binary8bit1) Decode(_ []byte) (string, error) {
return "", ErrNotImplDecode
}
func (*binary8bit1) DataCoding() byte { return BINARY8BIT1Coding }
type binary8bit2 struct{}
func (*binary8bit2) Encode(_ string) ([]byte, error) {
return []byte{}, ErrNotImplEncode
}
func (*binary8bit2) Decode(_ []byte) (string, error) {
return "", ErrNotImplDecode
}
func (*binary8bit2) DataCoding() byte { return BINARY8BIT2Coding }
type iso88595 struct{}
func (*iso88595) Encode(str string) ([]byte, error) {
return encode(str, charmap.ISO8859_5.NewEncoder())
}
func (*iso88595) Decode(data []byte) (string, error) {
return decode(data, charmap.ISO8859_5.NewDecoder())
}
func (*iso88595) DataCoding() byte { return CYRILLICCoding }
type iso88598 struct{}
func (*iso88598) Encode(str string) ([]byte, error) {
return encode(str, charmap.ISO8859_8.NewEncoder())
}
func (*iso88598) Decode(data []byte) (string, error) {
return decode(data, charmap.ISO8859_8.NewDecoder())
}
func (*iso88598) DataCoding() byte { return HEBREWCoding }
type ucs2 struct{}
func (*ucs2) Encode(str string) ([]byte, error) {
tmp := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
return encode(str, tmp.NewEncoder())
}
func (*ucs2) Decode(data []byte) (string, error) {
tmp := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
return decode(data, tmp.NewDecoder())
}
func (*ucs2) ShouldSplit(text string, octetLimit uint) (shouldSplit bool) {
runeSlice := []rune(text)
return uint(len(runeSlice)*2) > octetLimit
}
func (c *ucs2) EncodeSplit(text string, octetLimit uint) (allSeg [][]byte, err error) {
if octetLimit < 64 {
octetLimit = 134
}
allSeg = [][]byte{}
runeSlice := []rune(text)
hextetLim := int(octetLimit / 2) // round down
// hextet = 16 bits, the correct terms should be hexadectet
fr, to := 0, hextetLim
for fr < len(runeSlice) {
if to > len(runeSlice) {
to = len(runeSlice)
}
seg, err := c.Encode(string(runeSlice[fr:to]))
if err != nil {
return nil, err
}
allSeg = append(allSeg, seg)
fr, to = to, to+hextetLim
}
return
}
func (*ucs2) DataCoding() byte { return UCS2Coding }
var (
// GSM7BIT is gsm-7bit encoding.
GSM7BIT Encoding = &gsm7bit{packed: false}
// GSM7BITPACKED is packed gsm-7bit encoding.
// Most of SMSC(s) use unpack version.
// Should be tested before using.
GSM7BITPACKED Encoding = &gsm7bitPacked{}
// ASCII is ascii encoding.
ASCII Encoding = &ascii{}
// BINARY8BIT1 is binary 8-bit encoding.
BINARY8BIT1 Encoding = &binary8bit1{}
// LATIN1 encoding.
LATIN1 Encoding = &iso88591{}
// BINARY8BIT2 is binary 8-bit encoding.
BINARY8BIT2 Encoding = &binary8bit2{}
// CYRILLIC encoding.
CYRILLIC Encoding = &iso88595{}
// HEBREW encoding.
HEBREW Encoding = &iso88598{}
// UCS2 encoding.
UCS2 Encoding = &ucs2{}
)
var codingMap = map[byte]Encoding{
GSM7BITCoding: GSM7BIT,
ASCIICoding: ASCII,
BINARY8BIT1Coding: BINARY8BIT1,
LATIN1Coding: LATIN1,
BINARY8BIT2Coding: BINARY8BIT2,
CYRILLICCoding: CYRILLIC,
HEBREWCoding: HEBREW,
UCS2Coding: UCS2,
}
// FromDataCoding returns encoding from DataCoding value.
func FromDataCoding(code byte) (enc Encoding) {
enc, ok := codingMap[code]
if !ok { // if encoding is reserved (custom)
enc = NewCustomEncoding(code, GSM7BIT) // GSM7BIT is a temporary patch to apply to Encode/Decode methods
}
return
}
// Splitter extend encoding object by defining a split function
// that split a string into multiple segments
// Each segment string, when encoded, must be within a certain octet limit
type Splitter interface {
// ShouldSplit check if the encoded data of given text should be splitted under octetLimit
ShouldSplit(text string, octetLimit uint) (should bool)
EncodeSplit(text string, octetLimit uint) ([][]byte, error)
}
================================================
FILE: data/codings_test.go
================================================
package data
import (
"encoding/hex"
"log"
"testing"
"github.com/stretchr/testify/require"
)
func fromHex(h string) (v []byte) {
var err error
v, err = hex.DecodeString(h)
if err != nil {
log.Fatal(err)
}
return
}
func testEncoding(t *testing.T, enc EncDec, original, expected string) {
encoded, err := enc.Encode(original)
require.Nil(t, err)
require.Equal(t, fromHex(expected), encoded)
decoded, err := enc.Decode(encoded)
require.Nil(t, err)
require.Equal(t, original, decoded)
}
func testEncodingSplit(t *testing.T, enc EncDec, octetLim uint, original string, expected []string, expectDecode []string) {
splitter, ok := enc.(Splitter)
require.Truef(t, ok, "Encoding must implement Splitter interface")
segEncoded, err := splitter.EncodeSplit(original, octetLim)
require.Nil(t, err)
for i, seg := range segEncoded {
require.Equal(t, fromHex(expected[i]), seg)
require.LessOrEqualf(t, uint(len(seg)), octetLim,
"Segment len must be less than or equal to %d, got %d", octetLim, len(seg))
if enc == GSM7BITPACKED {
seg = shiftBitsOneRight(seg)
}
decoded, err := enc.Decode(seg)
require.Nil(t, err)
require.Equal(t, expectDecode[i], decoded)
}
}
func shiftBitsOneRight(input []byte) []byte {
carry := byte(0)
for i := len(input) - 1; i >= 0; i-- {
// Save the carry bit from the previous byte
nextCarry := input[i] & 0b00000001
// Shift the current byte to the right
input[i] >>= 1
// Apply the carry from the previous byte to the current byte
input[i] |= carry << 7
// Update the carry for the next byte
carry = nextCarry
}
return input
}
func TestCoding(t *testing.T) {
require.Nil(t, FromDataCoding(12))
require.Equal(t, GSM7BIT, FromDataCoding(0))
require.Equal(t, ASCII, FromDataCoding(1))
require.Equal(t, UCS2, FromDataCoding(8))
require.Equal(t, LATIN1, FromDataCoding(3))
require.Equal(t, CYRILLIC, FromDataCoding(6))
require.Equal(t, HEBREW, FromDataCoding(7))
}
func TestGSM7Bit(t *testing.T) {
require.EqualValues(t, 0, GSM7BITPACKED.DataCoding())
testEncoding(t, GSM7BITPACKED, "gjwklgjkwP123+?", "67f57dcd3eabd777684c365bfd00")
}
func TestShouldSplit(t *testing.T) {
t.Run("testShouldSplit_GSM7BIT", func(t *testing.T) {
octetLim := uint(140)
expect := map[string]bool{
"": false,
"1": false,
"12312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311234121212": false,
"123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112342212121": true,
}
splitter, _ := GSM7BIT.(Splitter)
for k, v := range expect {
ok := splitter.ShouldSplit(k, octetLim)
require.Equalf(t, ok, v, "Test case %s", k)
}
})
t.Run("testShouldSplit_UCS2", func(t *testing.T) {
octetLim := uint(140)
expect := map[string]bool{
"": false,
"1": false,
"ởỀÊộẩừỰÉÊỗọễệớỡồỰỬỪựởặỬ̀ỵổẤỨợỶẰỢộứẶHữẹ̃ẾỆằỄéậÃỡẰộ̀ỀỗứẲữỪữộÊỵòALữộòC": false, /* 70 UCS2 chars */
"ợÁÊGỷẹííỡỮÂIỆàúễẠỮỊệÂỖÍắẵYẠừẲíộờíẵỠựẤằờởể̃ởỵởềệổồUỡỵầễÁÝởÝNè̉ỚổôỊộợKỨệ́": true, /* 71 UCS2 chars */
}
splitter, _ := UCS2.(Splitter)
for k, v := range expect {
ok := splitter.ShouldSplit(k, octetLim)
require.Equalf(t, ok, v, "Test case %s", k)
}
})
t.Run("testShouldSplit_GSM7BITPACKED", func(t *testing.T) {
octetLim := uint(140)
expect := map[string]bool{
"": false,
"1": false,
"12312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311234121212": false,
"gjwklgjkwP123+?sasdasdaqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdqwdqwDQWdqwdqwdqwdqwwqwdqwdqwddqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdwqdqwqwdqwdqwqwdqw": false, /* 160 regular basic alphabet chars */
"gjwklgjkwP123+?sasdasdaqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdqwdqwDQWdqwdqwdqwdqwwqwdqwdqwddqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdwqdqwqwdqwdqwqwdqwd": true, /* 161 regular basic alphabet chars */
"gjwklgjkwP123+?sasdasdaqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdqwdqwDQWdqwdqwdqwdqwwqwdqwdqwddqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdwqdqwqwdqwdqwqwdqw{": true, /* 159 regular basic alphabet chars + 1 escape char at the end */
"|}€€|]|€[~€^]€~{~^{|]]|[{|~€^|]^[[{€^]^{€}}^~~]€]~€[€€[]~~[}}]{^}{|}~~]]€^{^|€{^": false, /* 80 escape chars */
"|}€€|]|€[~€^]€~{~^{|]]|[{|~€^|]^[[{€^]^{€}}^~~]€]~€[€€[]~~[}}]{^}{|}~~]]€^{^|€{^{": true, /* 81 escape chars */
}
splitter, _ := GSM7BITPACKED.(Splitter)
for k, v := range expect {
ok := splitter.ShouldSplit(k, octetLim)
require.Equalf(t, ok, v, "Test case %s", k)
}
})
}
func TestSplit(t *testing.T) {
require.EqualValues(t, 0o0, GSM7BITPACKED.DataCoding())
t.Run("testSplitGSM7Empty", func(t *testing.T) {
testEncodingSplit(t, GSM7BIT,
134,
"",
[]string{
"",
},
[]string{
"",
})
})
t.Run("testSplitUCS2", func(t *testing.T) {
testEncodingSplit(t, UCS2,
134,
"biggest gift của Christmas là có nhiều big/challenging/meaningful problems để sấp mặt làm",
[]string{
"006200690067006700650073007400200067006900660074002000631ee700610020004300680072006900730074006d006100730020006c00e00020006300f30020006e006800691ec100750020006200690067002f006300680061006c006c0065006e00670069006e0067002f006d00650061006e0069006e006700660075006c00200070",
"0072006f0062006c0065006d0073002001111ec3002000731ea500700020006d1eb700740020006c00e0006d",
},
[]string{
"biggest gift của Christmas là có nhiều big/challenging/meaningful p",
"roblems để sấp mặt làm",
})
})
t.Run("testSplitUCS2Empty", func(t *testing.T) {
testEncodingSplit(t, UCS2,
134,
"",
[]string{
"",
},
[]string{
"",
})
})
// UCS2 character should not be splitted in the middle
// here 54 character is encoded to 108 octet, but since there are 107 octet limit,
// a whole 2 octet has to be carried over to the next segment
t.Run("testSplit_Middle_UCS2", func(t *testing.T) {
testEncodingSplit(t, UCS2,
107,
"biggest gift của Christmas là có nhiều big/challenging",
[]string{
"006200690067006700650073007400200067006900660074002000631ee700610020004300680072006900730074006d006100730020006c00e00020006300f30020006e006800691ec100750020006200690067002f006300680061006c006c0065006e00670069006e",
"0067", // 0x00 0x67 is "g"
},
[]string{
"biggest gift của Christmas là có nhiều big/challengin",
"g",
})
})
}
func TestSplit_GSM7BITPACKED(t *testing.T) {
require.EqualValues(t, 0o0, GSM7BITPACKED.DataCoding())
t.Run("testSplit_Escape_GSM7BITPACKED", func(t *testing.T) {
testEncodingSplit(t, GSM7BITPACKED,
134,
"gjwklgjkwP123+?sasdasdaqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdqwdqwDQWdqwdqwdqwdqwwqwdqwdqwddqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdwqdqwqwdqwdqwqwdqw{",
[]string{
"ceeafb9a7d56afefd0986cb6facdc37372784e0ec7efe4f89d1cbf93e37772fc4e8edfc9f13b397e27c7efe4f89d1cbf93e37772fc4e8edfc9f13b397e27c7efe438397e27c7efc4e8951cbf93e37772fc4e8edfeff13b397e27c7ef6472fc4e8edfc9f13b397e27c7efe4f89d1cbf93e37772fc4e8edfc9f13b394ebec7c9f17bfc4e8edfc9",
"e2f7f89d1cbf6f50",
},
[]string{
"gjwklgjkwP123+?sasdasdaqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdqwdqwDQWdqwdqwdqwdqwwqwdqwdqwddqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqwdqdwqdqwqwdqwd",
"qwqwdqw{",
})
})
/*
Total char count = 160,
Esc char count = 1,
Regular char count = 159,
Seg1 => 153->€
Expected behaviour: Should not split in the middle of ESC chars
*/
t.Run("testSplit_EscEndOfSeg1_GSM7BITPACKED", func(t *testing.T) {
testEncodingSplit(t, GSM7BITPACKED,
134,
"pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp€ppppppp",
[]string{
"e070381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c31b",
"3665381c0e87c3e1",
},
[]string{
"pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp\r",
"€ppppppp",
})
})
/*
Total char count = 160,
Esc char count = 2,
Regular char count = 158,
Seg1 => 152-> ....{
Seg2 => 1-> ....{
Expected behaviour: Should not split in the middle of ESC chars
*/
t.Run("testSplit_EscEndOfSeg1AndSeg2_1_GSM7BITPACKED", func(t *testing.T) {
testEncodingSplit(t, GSM7BITPACKED,
134,
"pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp{{pppppppp",
[]string{
"e070381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0edfa01a",
"3628381c0e87c3e170",
},
[]string{
"pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp{\r",
"{pppppppp",
})
})
/*
Total char count = 160,
Esc char count = 2,
Regular char count = 158,
Seg1 => 152-> ....€
Seg2 => 1-> ....€
Expected behaviour: Should not split in the middle of ESC chars
*/
t.Run("testSplit_EscEndOfSeg1AndSeg2_2_GSM7BITPACKED", func(t *testing.T) {
testEncodingSplit(t, GSM7BITPACKED,
134,
"pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp€€pppppppp",
[]string{
"e070381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0e87c3e170381c0edf941b",
"3665381c0e87c3e170",
},
[]string{
"pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp€\r",
"€pppppppp",
})
})
/*
Total char count = 162,
Esc char count = 0,
Regular char count = 162,
Seg1 => 153
Seg2 => 9
Scenario: All charcters in the GSM7Bit Basic Character Set table (non-escape chars) https://en.wikipedia.org/wiki/GSM_03.38
*/
t.Run("testSplit_AllGSM7BitBasicCharset_GSM7BITPACKED", func(t *testing.T) {
testEncodingSplit(t, GSM7BITPACKED,
134,
"ΩØ;19Ξòå1-¤6aΞΘANanΣ¡>)òΦ3L;aøΛ-o@>I¥1=-ü!N¤&o9Hmda3jΞ@ÅΣlhEE§/:Çù0Θ&:_&Π;KLÅÅ@fÜ-kFH?ΠB5/ÆΓ?55=<Ω¡N2ñ¥*L¤aÖ! ÖΘ+øF£_Ç?øΔΓ-lèòCìnEBmhÉF*<Åi/aΩ¥CDøfGÇ$/=Λ'ÅA3ò#fkù",
[]string{
"2a8b5d2ca7413c622d922dacc9049d613706e84b212433e62ecca0b4de005f7210ebb5fc2127c9f4ce21dbe4f04cad0138306c74b1f87de9120658c6a48b982cbb25d3e10098bdadb511f9b3086b2fcee457abf57815a053d61fa898a4303704e266560c632092f8312093169b80181edc45611bfd31aa788ef42b5c190c890cf3312178f528",
"4e8ee00c3132af0d",
},
[]string{
"ΩØ;19Ξòå1-¤6aΞΘANanΣ¡>)òΦ3L;aøΛ-o@>I¥1=-ü!N¤&o9Hmda3jΞ@ÅΣlhEE§/:Çù0Θ&:_&Π;KLÅÅ@fÜ-kFH?ΠB5/ÆΓ?55=<Ω¡N2ñ¥*L¤aÖ! ÖΘ+øF£_Ç?øΔΓ-lèòCìnEBmhÉF*<Åi/aΩ¥CDøfGÇ$/=Λ",
"'ÅA3ò#fkù",
})
})
/*
Total char count = 81,
Esc char count = 81,
Regular char count = 0,
Seg1 => 153
Seg2 => 9
Scenario: All charcters in the GSM7Bit Escape Character Set table https://en.wikipedia.org/wiki/GSM_03.38
*/
t.Run("testSplit_AllGSM7BitBasicCharset_GSM7BITPACKED", func(t *testing.T) {
testEncodingSplit(t, GSM7BITPACKED,
134,
"|{[€|^€[{|€{[|^{~[}€|}|^|^[^]€{[]~}€]{{^|^][€]|€~€^[~}^]{]~{^^€^[~|^]|€~|^€{]{~|}",
[]string{
"36c00d6ac3db9437c00d6553def036a80d7053dea036bc0d7043d9a036bd0d6f93da9437c04d6a03dc5036c00d65c3db5036be4d7983daf036be4d6f93da9437be0d6a83da5036c00d65e3dbf036e58d6f03dc9437bd4d7943d9f036bd4d6a43d9f836a88d6fd3dba036940d6553de5036bc4d6f03dc5036be0d7053def436c00d6553dea01a",
"36be0d6ad3db003729",
},
[]string{
"|{[€|^€[{|€{[|^{~[}€|}|^|^[^]€{[]~}€]{{^|^][€]|€~€^[~}^]{]~{^^€^[~|^]|€~|^€{\r",
"]{~|}",
})
})
}
func TestAscii(t *testing.T) {
require.EqualValues(t, 1, ASCII.DataCoding())
testEncoding(t, ASCII, "agjwklgjkwP", "61676a776b6c676a6b7750")
}
func TestUCS2(t *testing.T) {
require.EqualValues(t, 8, UCS2.DataCoding())
testEncoding(t, UCS2, "agjwklgjkwP", "00610067006a0077006b006c0067006a006b00770050")
}
func TestLatin1(t *testing.T) {
require.EqualValues(t, 3, LATIN1.DataCoding())
testEncoding(t, LATIN1, "agjwklgjkwPÓ", "61676a776b6c676a6b7750d3")
}
func TestCYRILLIC(t *testing.T) {
require.EqualValues(t, 6, CYRILLIC.DataCoding())
testEncoding(t, CYRILLIC, "agjwklgjkwPф", "61676A776B6C676A6B7750E4")
}
func TestHebrew(t *testing.T) {
require.EqualValues(t, 7, HEBREW.DataCoding())
testEncoding(t, HEBREW, "agjwklgjkwPץ", "61676A776B6C676A6B7750F5")
}
func TestOtherCodings(t *testing.T) {
testEncoding(t, UTF16BEM, "ngưỡng cứa cuỗc đợi", "feff006e006701b01ee1006e0067002000631ee900610020006300751ed70063002001111ee30069")
testEncoding(t, UTF16LEM, "ngưỡng cứa cuỗc đợi", "fffe6e006700b001e11e6e00670020006300e91e6100200063007500d71e630020001101e31e6900")
testEncoding(t, UTF16BE, "ngưỡng cứa cuỗc đợi", "006e006701b01ee1006e0067002000631ee900610020006300751ed70063002001111ee30069")
testEncoding(t, UTF16LE, "ngưỡng cứa cuỗc đợi", "6e006700b001e11e6e00670020006300e91e6100200063007500d71e630020001101e31e6900")
}
type noOpEncDec struct{}
func (*noOpEncDec) Encode(str string) ([]byte, error) {
return []byte(str), nil
}
func (*noOpEncDec) Decode(data []byte) (string, error) {
return string(data), nil
}
func TestCustomEncoding(t *testing.T) {
enc := NewCustomEncoding(GSM7BITCoding, &noOpEncDec{})
require.EqualValues(t, GSM7BITCoding, enc.DataCoding())
encoded, err := enc.Encode("abc")
require.NoError(t, err)
require.Equal(t, []byte("abc"), encoded)
decoded, err := enc.Decode(encoded)
require.NoError(t, err)
require.Equal(t, "abc", decoded)
}
================================================
FILE: data/header_data.go
================================================
//go:generate stringer -type=CommandStatusType,CommandIDType -output header_data_string.go
package data
// CommandStatusType is type of command status
type CommandStatusType int32
// CommandIDType is type of command id.
type CommandIDType int32
// nolint
const (
// SMPP Command ID Set
GENERIC_NACK = CommandIDType(-2147483648)
BIND_RECEIVER = CommandIDType(0x00000001)
BIND_RECEIVER_RESP = CommandIDType(-2147483647)
BIND_TRANSMITTER = CommandIDType(0x00000002)
BIND_TRANSMITTER_RESP = CommandIDType(-2147483646)
QUERY_SM = CommandIDType(0x00000003)
QUERY_SM_RESP = CommandIDType(-2147483645)
SUBMIT_SM = CommandIDType(0x00000004)
SUBMIT_SM_RESP = CommandIDType(-2147483644)
DELIVER_SM = CommandIDType(0x00000005)
DELIVER_SM_RESP = CommandIDType(-2147483643)
UNBIND = CommandIDType(0x00000006)
UNBIND_RESP = CommandIDType(-2147483642)
REPLACE_SM = CommandIDType(0x00000007)
REPLACE_SM_RESP = CommandIDType(-2147483641)
CANCEL_SM = CommandIDType(0x00000008)
CANCEL_SM_RESP = CommandIDType(-2147483640)
BIND_TRANSCEIVER = CommandIDType(0x00000009)
BIND_TRANSCEIVER_RESP = CommandIDType(-2147483639)
OUTBIND = CommandIDType(0x0000000B)
ENQUIRE_LINK = CommandIDType(0x00000015)
ENQUIRE_LINK_RESP = CommandIDType(-2147483627)
SUBMIT_MULTI = CommandIDType(0x00000021)
SUBMIT_MULTI_RESP = CommandIDType(-2147483615)
ALERT_NOTIFICATION = CommandIDType(0x00000102)
DATA_SM = CommandIDType(0x00000103)
DATA_SM_RESP = CommandIDType(-2147483389)
)
// nolint
const (
// Command_Status Error Codes
ESME_ROK = CommandStatusType(0x00000000) // No Error
ESME_RINVMSGLEN = CommandStatusType(0x00000001) // Message Length is invalid
ESME_RINVCMDLEN = CommandStatusType(0x00000002) // Command Length is invalid
ESME_RINVCMDID = CommandStatusType(0x00000003) // Invalid Command ID
ESME_RINVBNDSTS = CommandStatusType(0x00000004) // Incorrect BIND Status for given command
ESME_RALYBND = CommandStatusType(0x00000005) // ESME Already in Bound State
ESME_RINVPRTFLG = CommandStatusType(0x00000006) // Invalid Priority Flag
ESME_RINVREGDLVFLG = CommandStatusType(0x00000007) // Invalid Registered Delivery Flag
ESME_RSYSERR = CommandStatusType(0x00000008) // System Error
ESME_RINVSRCADR = CommandStatusType(0x0000000A) // Invalid Source Address
ESME_RINVDSTADR = CommandStatusType(0x0000000B) // Invalid Dest Addr
ESME_RINVMSGID = CommandStatusType(0x0000000C) // Message ID is invalid
ESME_RBINDFAIL = CommandStatusType(0x0000000D) // Bind Failed
ESME_RINVPASWD = CommandStatusType(0x0000000E) // Invalid Password
ESME_RINVSYSID = CommandStatusType(0x0000000F) // Invalid System ID
ESME_RCANCELFAIL = CommandStatusType(0x00000011) // Cancel SM Failed
ESME_RREPLACEFAIL = CommandStatusType(0x00000013) // Replace SM Failed
ESME_RMSGQFUL = CommandStatusType(0x00000014) // Message Queue Full
ESME_RINVSERTYP = CommandStatusType(0x00000015) // Invalid Service Type
ESME_RADDCUSTFAIL = CommandStatusType(0x00000019) // Failed to Add Customer
ESME_RDELCUSTFAIL = CommandStatusType(0x0000001A) // Failed to delete Customer
ESME_RMODCUSTFAIL = CommandStatusType(0x0000001B) // Failed to modify customer
ESME_RENQCUSTFAIL = CommandStatusType(0x0000001C) // Failed to Enquire Customer
ESME_RINVCUSTID = CommandStatusType(0x0000001D) // Invalid Customer ID
ESME_RINVCUSTNAME = CommandStatusType(0x0000001F) // Invalid Customer Name
ESME_RINVCUSTADR = CommandStatusType(0x00000021) // Invalid Customer Address
ESME_RINVADR = CommandStatusType(0x00000022) // Invalid Address
ESME_RCUSTEXIST = CommandStatusType(0x00000023) // Customer Exists
ESME_RCUSTNOTEXIST = CommandStatusType(0x00000024) // Customer does not exist
ESME_RADDDLFAIL = CommandStatusType(0x00000026) // Failed to Add DL
ESME_RMODDLFAIL = CommandStatusType(0x00000027) // Failed to modify DL
ESME_RDELDLFAIL = CommandStatusType(0x00000028) // Failed to Delete DL
ESME_RVIEWDLFAIL = CommandStatusType(0x00000029) // Failed to View DL
ESME_RLISTDLSFAIL = CommandStatusType(0x00000030) // Failed to list DLs
ESME_RPARAMRETFAIL = CommandStatusType(0x00000031) // Param Retrieve Failed
ESME_RINVPARAM = CommandStatusType(0x00000032) // Invalid Param
ESME_RINVNUMDESTS = CommandStatusType(0x00000033) // Invalid number of destinations
ESME_RINVDLNAME = CommandStatusType(0x00000034) // Invalid Distribution List name
ESME_RINVDLMEMBDESC = CommandStatusType(0x00000035) // Invalid DL Member Description
ESME_RINVDLMEMBTYP = CommandStatusType(0x00000038) // Invalid DL Member Type
ESME_RINVDLMODOPT = CommandStatusType(0x00000039) // Invalid DL Modify Option
ESME_RINVDESTFLAG = CommandStatusType(0x00000040) // Destination flag is invalid (submit_multi)
ESME_RINVSUBREP = CommandStatusType(0x00000042) // Invalid ‘submit with replace’ request (i.e. submit_sm with replace_if_present_flag set)
ESME_RINVESMCLASS = CommandStatusType(0x00000043) // Invalid esm_class field data
ESME_RCNTSUBDL = CommandStatusType(0x00000044) // Cannot Submit to Distribution List
ESME_RSUBMITFAIL = CommandStatusType(0x00000045) // submit_sm or submit_multi failed
ESME_RINVSRCTON = CommandStatusType(0x00000048) // Invalid Source address TON
ESME_RINVSRCNPI = CommandStatusType(0x00000049) // Invalid Source address NPI
ESME_RINVDSTTON = CommandStatusType(0x00000050) // Invalid Destination address TON
ESME_RINVDSTNPI = CommandStatusType(0x00000051) // Invalid Destination address NPI
ESME_RINVSYSTYP = CommandStatusType(0x00000053) // Invalid system_type field
ESME_RINVREPFLAG = CommandStatusType(0x00000054) // Invalid replace_if_present flag
ESME_RINVNUMMSGS = CommandStatusType(0x00000055) // Invalid number of messages
ESME_RTHROTTLED = CommandStatusType(0x00000058) // Throttling error (ESME has exceeded allowed message limits)
ESME_RPROVNOTALLWD = CommandStatusType(0x00000059) // Provisioning Not Allowed
ESME_RINVSCHED = CommandStatusType(0x00000061) // Invalid Scheduled Delivery Time
ESME_RINVEXPIRY = CommandStatusType(0x00000062) // Invalid message validity period (Expiry time)
ESME_RINVDFTMSGID = CommandStatusType(0x00000063) // Predefined Message Invalid or Not Found
ESME_RX_T_APPN = CommandStatusType(0x00000064) // ESME Receiver Temporary App Error Code
ESME_RX_P_APPN = CommandStatusType(0x00000065) // ESME Receiver Permanent App Error Code
ESME_RX_R_APPN = CommandStatusType(0x00000066) // ESME Receiver Reject Message Error Code
ESME_RQUERYFAIL = CommandStatusType(0x00000067) // query_sm request failed
ESME_RINVPGCUSTID = CommandStatusType(0x00000080) // Paging Customer ID Invalid No such subscriber
ESME_RINVPGCUSTIDLEN = CommandStatusType(0x00000081) // Paging Customer ID length Invalid
ESME_RINVCITYLEN = CommandStatusType(0x00000082) // City Length Invalid
ESME_RINVSTATELEN = CommandStatusType(0x00000083) // State Length Invalid
ESME_RINVZIPPREFIXLEN = CommandStatusType(0x00000084) // Zip Prefix Length Invalid
ESME_RINVZIPPOSTFIXLEN = CommandStatusType(0x00000085) // Zip Postfix Length Invalid
ESME_RINVMINLEN = CommandStatusType(0x00000086) // MIN Length Invalid
ESME_RINVMIN = CommandStatusType(0x00000087) // MIN Invalid (i.e. No such MIN)
ESME_RINVPINLEN = CommandStatusType(0x00000088) // PIN Length Invalid
ESME_RINVTERMCODELEN = CommandStatusType(0x00000089) // Terminal Code Length Invalid
ESME_RINVCHANNELLEN = CommandStatusType(0x0000008A) // Channel Length Invalid
ESME_RINVCOVREGIONLEN = CommandStatusType(0x0000008B) // Coverage Region Length Invalid
ESME_RINVCAPCODELEN = CommandStatusType(0x0000008C) // Cap Code Length Invalid
ESME_RINVMDTLEN = CommandStatusType(0x0000008D) // Message delivery time Length Invalid
ESME_RINVPRIORMSGLEN = CommandStatusType(0x0000008E) // Priority Message Length Invalid
ESME_RINVPERMSGLEN = CommandStatusType(0x0000008F) // Periodic Messages Length Invalid
ESME_RINVPGALERTLEN = CommandStatusType(0x00000090) // Paging Alerts Length Invalid
ESME_RINVSMUSERLEN = CommandStatusType(0x00000091) // int16 Message User Group Length Invalid
ESME_RINVRTDBLEN = CommandStatusType(0x00000092) // Real Time Data broadcasts Length Invalid
ESME_RINVREGDELLEN = CommandStatusType(0x00000093) // Registered Delivery Length Invalid
ESME_RINVMSGDISTLEN = CommandStatusType(0x00000094) // Message Distribution Length Invalid
ESME_RINVPRIORMSG = CommandStatusType(0x00000095) // Priority Message Length Invalid
ESME_RINVMDT = CommandStatusType(0x00000096) // Message delivery time Invalid
ESME_RINVPERMSG = CommandStatusType(0x00000097) // Periodic Messages Invalid
ESME_RINVMSGDIST = CommandStatusType(0x00000098) // Message Distribution Invalid
ESME_RINVPGALERT = CommandStatusType(0x00000099) // Paging Alerts Invalid
ESME_RINVSMUSER = CommandStatusType(0x0000009A) // int16 Message User Group Invalid
ESME_RINVRTDB = CommandStatusType(0x0000009B) // Real Time Data broadcasts Invalid
ESME_RINVREGDEL = CommandStatusType(0x0000009C) // Registered Delivery Invalid
ESME_RINVOPTPARLEN = CommandStatusType(0x0000009F) // Invalid Optional Parameter Length
ESME_RINVOPTPARSTREAM = CommandStatusType(0x000000C0) // KIF IW Field out of data
ESME_ROPTPARNOTALLWD = CommandStatusType(0x000000C1) // Optional Parameter not allowed
ESME_RINVPARLEN = CommandStatusType(0x000000C2) // Invalid Parameter Length.
ESME_RMISSINGOPTPARAM = CommandStatusType(0x000000C3) // Expected Optional Parameter missing
ESME_RINVOPTPARAMVAL = CommandStatusType(0x000000C4) // Invalid Optional Parameter Value
ESME_RDELIVERYFAILURE = CommandStatusType(0x000000FE) // Delivery Failure (used for data_sm_resp)
ESME_RUNKNOWNERR = CommandStatusType(0x000000FF) // Unknown Error
ESME_LAST_ERROR = CommandStatusType(0x0000012C) // THE VALUE OF THE LAST ERROR CODE
)
================================================
FILE: data/header_data_string.go
================================================
// Code generated by "stringer -type=CommandStatusType,CommandIDType -output header_data_string.go"; DO NOT EDIT.
package data
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ESME_ROK-0]
_ = x[ESME_RINVMSGLEN-1]
_ = x[ESME_RINVCMDLEN-2]
_ = x[ESME_RINVCMDID-3]
_ = x[ESME_RINVBNDSTS-4]
_ = x[ESME_RALYBND-5]
_ = x[ESME_RINVPRTFLG-6]
_ = x[ESME_RINVREGDLVFLG-7]
_ = x[ESME_RSYSERR-8]
_ = x[ESME_RINVSRCADR-10]
_ = x[ESME_RINVDSTADR-11]
_ = x[ESME_RINVMSGID-12]
_ = x[ESME_RBINDFAIL-13]
_ = x[ESME_RINVPASWD-14]
_ = x[ESME_RINVSYSID-15]
_ = x[ESME_RCANCELFAIL-17]
_ = x[ESME_RREPLACEFAIL-19]
_ = x[ESME_RMSGQFUL-20]
_ = x[ESME_RINVSERTYP-21]
_ = x[ESME_RADDCUSTFAIL-25]
_ = x[ESME_RDELCUSTFAIL-26]
_ = x[ESME_RMODCUSTFAIL-27]
_ = x[ESME_RENQCUSTFAIL-28]
_ = x[ESME_RINVCUSTID-29]
_ = x[ESME_RINVCUSTNAME-31]
_ = x[ESME_RINVCUSTADR-33]
_ = x[ESME_RINVADR-34]
_ = x[ESME_RCUSTEXIST-35]
_ = x[ESME_RCUSTNOTEXIST-36]
_ = x[ESME_RADDDLFAIL-38]
_ = x[ESME_RMODDLFAIL-39]
_ = x[ESME_RDELDLFAIL-40]
_ = x[ESME_RVIEWDLFAIL-41]
_ = x[ESME_RLISTDLSFAIL-48]
_ = x[ESME_RPARAMRETFAIL-49]
_ = x[ESME_RINVPARAM-50]
_ = x[ESME_RINVNUMDESTS-51]
_ = x[ESME_RINVDLNAME-52]
_ = x[ESME_RINVDLMEMBDESC-53]
_ = x[ESME_RINVDLMEMBTYP-56]
_ = x[ESME_RINVDLMODOPT-57]
_ = x[ESME_RINVDESTFLAG-64]
_ = x[ESME_RINVSUBREP-66]
_ = x[ESME_RINVESMCLASS-67]
_ = x[ESME_RCNTSUBDL-68]
_ = x[ESME_RSUBMITFAIL-69]
_ = x[ESME_RINVSRCTON-72]
_ = x[ESME_RINVSRCNPI-73]
_ = x[ESME_RINVDSTTON-80]
_ = x[ESME_RINVDSTNPI-81]
_ = x[ESME_RINVSYSTYP-83]
_ = x[ESME_RINVREPFLAG-84]
_ = x[ESME_RINVNUMMSGS-85]
_ = x[ESME_RTHROTTLED-88]
_ = x[ESME_RPROVNOTALLWD-89]
_ = x[ESME_RINVSCHED-97]
_ = x[ESME_RINVEXPIRY-98]
_ = x[ESME_RINVDFTMSGID-99]
_ = x[ESME_RX_T_APPN-100]
_ = x[ESME_RX_P_APPN-101]
_ = x[ESME_RX_R_APPN-102]
_ = x[ESME_RQUERYFAIL-103]
_ = x[ESME_RINVPGCUSTID-128]
_ = x[ESME_RINVPGCUSTIDLEN-129]
_ = x[ESME_RINVCITYLEN-130]
_ = x[ESME_RINVSTATELEN-131]
_ = x[ESME_RINVZIPPREFIXLEN-132]
_ = x[ESME_RINVZIPPOSTFIXLEN-133]
_ = x[ESME_RINVMINLEN-134]
_ = x[ESME_RINVMIN-135]
_ = x[ESME_RINVPINLEN-136]
_ = x[ESME_RINVTERMCODELEN-137]
_ = x[ESME_RINVCHANNELLEN-138]
_ = x[ESME_RINVCOVREGIONLEN-139]
_ = x[ESME_RINVCAPCODELEN-140]
_ = x[ESME_RINVMDTLEN-141]
_ = x[ESME_RINVPRIORMSGLEN-142]
_ = x[ESME_RINVPERMSGLEN-143]
_ = x[ESME_RINVPGALERTLEN-144]
_ = x[ESME_RINVSMUSERLEN-145]
_ = x[ESME_RINVRTDBLEN-146]
_ = x[ESME_RINVREGDELLEN-147]
_ = x[ESME_RINVMSGDISTLEN-148]
_ = x[ESME_RINVPRIORMSG-149]
_ = x[ESME_RINVMDT-150]
_ = x[ESME_RINVPERMSG-151]
_ = x[ESME_RINVMSGDIST-152]
_ = x[ESME_RINVPGALERT-153]
_ = x[ESME_RINVSMUSER-154]
_ = x[ESME_RINVRTDB-155]
_ = x[ESME_RINVREGDEL-156]
_ = x[ESME_RINVOPTPARLEN-159]
_ = x[ESME_RINVOPTPARSTREAM-192]
_ = x[ESME_ROPTPARNOTALLWD-193]
_ = x[ESME_RINVPARLEN-194]
_ = x[ESME_RMISSINGOPTPARAM-195]
_ = x[ESME_RINVOPTPARAMVAL-196]
_ = x[ESME_RDELIVERYFAILURE-254]
_ = x[ESME_RUNKNOWNERR-255]
_ = x[ESME_LAST_ERROR-300]
}
const _CommandStatusType_name = "ESME_ROKESME_RINVMSGLENESME_RINVCMDLENESME_RINVCMDIDESME_RINVBNDSTSESME_RALYBNDESME_RINVPRTFLGESME_RINVREGDLVFLGESME_RSYSERRESME_RINVSRCADRESME_RINVDSTADRESME_RINVMSGIDESME_RBINDFAILESME_RINVPASWDESME_RINVSYSIDESME_RCANCELFAILESME_RREPLACEFAILESME_RMSGQFULESME_RINVSERTYPESME_RADDCUSTFAILESME_RDELCUSTFAILESME_RMODCUSTFAILESME_RENQCUSTFAILESME_RINVCUSTIDESME_RINVCUSTNAMEESME_RINVCUSTADRESME_RINVADRESME_RCUSTEXISTESME_RCUSTNOTEXISTESME_RADDDLFAILESME_RMODDLFAILESME_RDELDLFAILESME_RVIEWDLFAILESME_RLISTDLSFAILESME_RPARAMRETFAILESME_RINVPARAMESME_RINVNUMDESTSESME_RINVDLNAMEESME_RINVDLMEMBDESCESME_RINVDLMEMBTYPESME_RINVDLMODOPTESME_RINVDESTFLAGESME_RINVSUBREPESME_RINVESMCLASSESME_RCNTSUBDLESME_RSUBMITFAILESME_RINVSRCTONESME_RINVSRCNPIESME_RINVDSTTONESME_RINVDSTNPIESME_RINVSYSTYPESME_RINVREPFLAGESME_RINVNUMMSGSESME_RTHROTTLEDESME_RPROVNOTALLWDESME_RINVSCHEDESME_RINVEXPIRYESME_RINVDFTMSGIDESME_RX_T_APPNESME_RX_P_APPNESME_RX_R_APPNESME_RQUERYFAILESME_RINVPGCUSTIDESME_RINVPGCUSTIDLENESME_RINVCITYLENESME_RINVSTATELENESME_RINVZIPPREFIXLENESME_RINVZIPPOSTFIXLENESME_RINVMINLENESME_RINVMINESME_RINVPINLENESME_RINVTERMCODELENESME_RINVCHANNELLENESME_RINVCOVREGIONLENESME_RINVCAPCODELENESME_RINVMDTLENESME_RINVPRIORMSGLENESME_RINVPERMSGLENESME_RINVPGALERTLENESME_RINVSMUSERLENESME_RINVRTDBLENESME_RINVREGDELLENESME_RINVMSGDISTLENESME_RINVPRIORMSGESME_RINVMDTESME_RINVPERMSGESME_RINVMSGDISTESME_RINVPGALERTESME_RINVSMUSERESME_RINVRTDBESME_RINVREGDELESME_RINVOPTPARLENESME_RINVOPTPARSTREAMESME_ROPTPARNOTALLWDESME_RINVPARLENESME_RMISSINGOPTPARAMESME_RINVOPTPARAMVALESME_RDELIVERYFAILUREESME_RUNKNOWNERRESME_LAST_ERROR"
var _CommandStatusType_map = map[CommandStatusType]string{
0: _CommandStatusType_name[0:8],
1: _CommandStatusType_name[8:23],
2: _CommandStatusType_name[23:38],
3: _CommandStatusType_name[38:52],
4: _CommandStatusType_name[52:67],
5: _CommandStatusType_name[67:79],
6: _CommandStatusType_name[79:94],
7: _CommandStatusType_name[94:112],
8: _CommandStatusType_name[112:124],
10: _CommandStatusType_name[124:139],
11: _CommandStatusType_name[139:154],
12: _CommandStatusType_name[154:168],
13: _CommandStatusType_name[168:182],
14: _CommandStatusType_name[182:196],
15: _CommandStatusType_name[196:210],
17: _CommandStatusType_name[210:226],
19: _CommandStatusType_name[226:243],
20: _CommandStatusType_name[243:256],
21: _CommandStatusType_name[256:271],
25: _CommandStatusType_name[271:288],
26: _CommandStatusType_name[288:305],
27: _CommandStatusType_name[305:322],
28: _CommandStatusType_name[322:339],
29: _CommandStatusType_name[339:354],
31: _CommandStatusType_name[354:371],
33: _CommandStatusType_name[371:387],
34: _CommandStatusType_name[387:399],
35: _CommandStatusType_name[399:414],
36: _CommandStatusType_name[414:432],
38: _CommandStatusType_name[432:447],
39: _CommandStatusType_name[447:462],
40: _CommandStatusType_name[462:477],
41: _CommandStatusType_name[477:493],
48: _CommandStatusType_name[493:510],
49: _CommandStatusType_name[510:528],
50: _CommandStatusType_name[528:542],
51: _CommandStatusType_name[542:559],
52: _CommandStatusType_name[559:574],
53: _CommandStatusType_name[574:593],
56: _CommandStatusType_name[593:611],
57: _CommandStatusType_name[611:628],
64: _CommandStatusType_name[628:645],
66: _CommandStatusType_name[645:660],
67: _CommandStatusType_name[660:677],
68: _CommandStatusType_name[677:691],
69: _CommandStatusType_name[691:707],
72: _CommandStatusType_name[707:722],
73: _CommandStatusType_name[722:737],
80: _CommandStatusType_name[737:752],
81: _CommandStatusType_name[752:767],
83: _CommandStatusType_name[767:782],
84: _CommandStatusType_name[782:798],
85: _CommandStatusType_name[798:814],
88: _CommandStatusType_name[814:829],
89: _CommandStatusType_name[829:847],
97: _CommandStatusType_name[847:861],
98: _CommandStatusType_name[861:876],
99: _CommandStatusType_name[876:893],
100: _CommandStatusType_name[893:907],
101: _CommandStatusType_name[907:921],
102: _CommandStatusType_name[921:935],
103: _CommandStatusType_name[935:950],
128: _CommandStatusType_name[950:967],
129: _CommandStatusType_name[967:987],
130: _CommandStatusType_name[987:1003],
131: _CommandStatusType_name[1003:1020],
132: _CommandStatusType_name[1020:1041],
133: _CommandStatusType_name[1041:1063],
134: _CommandStatusType_name[1063:1078],
135: _CommandStatusType_name[1078:1090],
136: _CommandStatusType_name[1090:1105],
137: _CommandStatusType_name[1105:1125],
138: _CommandStatusType_name[1125:1144],
139: _CommandStatusType_name[1144:1165],
140: _CommandStatusType_name[1165:1184],
141: _CommandStatusType_name[1184:1199],
142: _CommandStatusType_name[1199:1219],
143: _CommandStatusType_name[1219:1237],
144: _CommandStatusType_name[1237:1256],
145: _CommandStatusType_name[1256:1274],
146: _CommandStatusType_name[1274:1290],
147: _CommandStatusType_name[1290:1308],
148: _CommandStatusType_name[1308:1327],
149: _CommandStatusType_name[1327:1344],
150: _CommandStatusType_name[1344:1356],
151: _CommandStatusType_name[1356:1371],
152: _CommandStatusType_name[1371:1387],
153: _CommandStatusType_name[1387:1403],
154: _CommandStatusType_name[1403:1418],
155: _CommandStatusType_name[1418:1431],
156: _CommandStatusType_name[1431:1446],
159: _CommandStatusType_name[1446:1464],
192: _CommandStatusType_name[1464:1485],
193: _CommandStatusType_name[1485:1505],
194: _CommandStatusType_name[1505:1520],
195: _CommandStatusType_name[1520:1541],
196: _CommandStatusType_name[1541:1561],
254: _CommandStatusType_name[1561:1582],
255: _CommandStatusType_name[1582:1598],
300: _CommandStatusType_name[1598:1613],
}
func (i CommandStatusType) String() string {
if str, ok := _CommandStatusType_map[i]; ok {
return str
}
return "CommandStatusType(" + strconv.FormatInt(int64(i), 10) + ")"
}
func (i CommandStatusType) Desc() string {
switch i {
case ESME_ROK:
return "No Error"
case ESME_RINVMSGLEN:
return "Message Length is invalid"
case ESME_RINVCMDLEN:
return "Command Length is invalid"
case ESME_RINVCMDID:
return "Invalid Command ID"
case ESME_RINVBNDSTS:
return "Incorrect BIND Status for given command"
case ESME_RALYBND:
return "ESME Already in Bound State"
case ESME_RINVPRTFLG:
return "Invalid Priority Flag"
case ESME_RINVREGDLVFLG:
return "Invalid Registered Delivery Flag"
case ESME_RSYSERR:
return "System Error"
case ESME_RINVSRCADR:
return "Invalid Source Address"
case ESME_RINVDSTADR:
return "Invalid Dest Addr"
case ESME_RINVMSGID:
return "Message ID is invalid"
case ESME_RBINDFAIL:
return "Bind Failed"
case ESME_RINVPASWD:
return "Invalid Password"
case ESME_RINVSYSID:
return "Invalid System ID"
case ESME_RCANCELFAIL:
return "Cancel SM Failed"
case ESME_RREPLACEFAIL:
return "Replace SM Failed"
case ESME_RMSGQFUL:
return "Message Queue Full"
case ESME_RINVSERTYP:
return "Invalid Service Type"
case ESME_RADDCUSTFAIL:
return "Failed to Add Customer"
case ESME_RDELCUSTFAIL:
return "Failed to delete Customer"
case ESME_RMODCUSTFAIL:
return "Failed to modify customer"
case ESME_RENQCUSTFAIL:
return "Failed to Enquire Customer"
case ESME_RINVCUSTID:
return "Invalid Customer ID"
case ESME_RINVCUSTNAME:
return "Invalid Customer Name"
case ESME_RINVCUSTADR:
return "Invalid Customer Address"
case ESME_RINVADR:
return "Invalid Address"
case ESME_RCUSTEXIST:
return "Customer Exists"
case ESME_RCUSTNOTEXIST:
return "Customer does not exist"
case ESME_RADDDLFAIL:
return "Failed to Add DL"
case ESME_RMODDLFAIL:
return "Failed to modify DL"
case ESME_RDELDLFAIL:
return "Failed to Delete DL"
case ESME_RVIEWDLFAIL:
return "Failed to View DL"
case ESME_RLISTDLSFAIL:
return "Failed to list DLs"
case ESME_RPARAMRETFAIL:
return "Param Retrieve Failed"
case ESME_RINVPARAM:
return "Invalid Param"
case ESME_RINVNUMDESTS:
return "Invalid number of destinations"
case ESME_RINVDLNAME:
return "Invalid Distribution List name"
case ESME_RINVDLMEMBDESC:
return "Invalid DL Member Description"
case ESME_RINVDLMEMBTYP:
return "Invalid DL Member Type"
case ESME_RINVDLMODOPT:
return "Invalid DL Modify Option"
case ESME_RINVDESTFLAG:
return "Destination flag is invalid (submit_multi)"
case ESME_RINVSUBREP:
return "Invalid ‘submit with replace’ request (i.e. submit_sm with replace_if_present_flag set)"
case ESME_RINVESMCLASS:
return "Invalid esm_class field data"
case ESME_RCNTSUBDL:
return "Cannot Submit to Distribution List"
case ESME_RSUBMITFAIL:
return "submit_sm or submit_multi failed"
case ESME_RINVSRCTON:
return "Invalid Source address TON"
case ESME_RINVSRCNPI:
return "Invalid Source address NPI"
case ESME_RINVDSTTON:
return "Invalid Destination address TON"
case ESME_RINVDSTNPI:
return "Invalid Destination address NPI"
case ESME_RINVSYSTYP:
return "Invalid system_type field"
case ESME_RINVREPFLAG:
return "Invalid replace_if_present flag"
case ESME_RINVNUMMSGS:
return "Invalid number of messages"
case ESME_RTHROTTLED:
return "Throttling error (ESME has exceeded allowed message limits)"
case ESME_RPROVNOTALLWD:
return "Provisioning Not Allowed"
case ESME_RINVSCHED:
return "Invalid Scheduled Delivery Time"
case ESME_RINVEXPIRY:
return "Invalid message validity period (Expiry time)"
case ESME_RINVDFTMSGID:
return "Predefined Message Invalid or Not Found"
case ESME_RX_T_APPN:
return "ESME Receiver Temporary App Error Code"
case ESME_RX_P_APPN:
return "ESME Receiver Permanent App Error Code"
case ESME_RX_R_APPN:
return "ESME Receiver Reject Message Error Code"
case ESME_RQUERYFAIL:
return "query_sm request failed"
case ESME_RINVPGCUSTID:
return "Paging Customer ID Invalid No such subscriber"
case ESME_RINVPGCUSTIDLEN:
return "Paging Customer ID length Invalid"
case ESME_RINVCITYLEN:
return "City Length Invalid"
case ESME_RINVSTATELEN:
return "State Length Invalid"
case ESME_RINVZIPPREFIXLEN:
return "Zip Prefix Length Invalid"
case ESME_RINVZIPPOSTFIXLEN:
return "Zip Postfix Length Invalid"
case ESME_RINVMINLEN:
return "MIN Length Invalid"
case ESME_RINVMIN:
return "MIN Invalid (i.e. No such MIN)"
case ESME_RINVPINLEN:
return "PIN Length Invalid"
case ESME_RINVTERMCODELEN:
return "Terminal Code Length Invalid"
case ESME_RINVCHANNELLEN:
return "Channel Length Invalid"
case ESME_RINVCOVREGIONLEN:
return "Coverage Region Length Invalid"
case ESME_RINVCAPCODELEN:
return "Cap Code Length Invalid"
case ESME_RINVMDTLEN:
return "Message delivery time Length Invalid"
case ESME_RINVPRIORMSGLEN:
return "Priority Message Length Invalid"
case ESME_RINVPERMSGLEN:
return "Periodic Messages Length Invalid"
case ESME_RINVPGALERTLEN:
return "Paging Alerts Length Invalid"
case ESME_RINVSMUSERLEN:
return "int16 Message User Group Length Invalid"
case ESME_RINVRTDBLEN:
return "Real Time Data broadcasts Length Invalid"
case ESME_RINVREGDELLEN:
return "Registered Delivery Length Invalid"
case ESME_RINVMSGDISTLEN:
return "Message Distribution Length Invalid"
case ESME_RINVPRIORMSG:
return "Priority Message Length Invalid"
case ESME_RINVMDT:
return "Message delivery time Invalid"
case ESME_RINVPERMSG:
return "Periodic Messages Invalid"
case ESME_RINVMSGDIST:
return "Message Distribution Invalid"
case ESME_RINVPGALERT:
return "Paging Alerts Invalid"
case ESME_RINVSMUSER:
return "int16 Message User Group Invalid"
case ESME_RINVRTDB:
return "Real Time Data broadcasts Invalid"
case ESME_RINVREGDEL:
return "Registered Delivery Invalid"
case ESME_RINVOPTPARLEN:
return "Invalid Optional Parameter Length"
case ESME_RINVOPTPARSTREAM:
return "Error in the optional part of the PDU Body."
case ESME_ROPTPARNOTALLWD:
return "Optional Parameter not allowed"
case ESME_RINVPARLEN:
return "Invalid Parameter Length."
case ESME_RMISSINGOPTPARAM:
return "Expected Optional Parameter missing"
case ESME_RINVOPTPARAMVAL:
return "Invalid Optional Parameter Value"
case ESME_RDELIVERYFAILURE:
return "Delivery Failure (used for data_sm_resp)"
case ESME_RUNKNOWNERR:
return "Unknown Error"
case ESME_LAST_ERROR:
return "The value of the last error code"
}
return i.String()
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[GENERIC_NACK - -2147483648]
_ = x[BIND_RECEIVER-1]
_ = x[BIND_RECEIVER_RESP - -2147483647]
_ = x[BIND_TRANSMITTER-2]
_ = x[BIND_TRANSMITTER_RESP - -2147483646]
_ = x[QUERY_SM-3]
_ = x[QUERY_SM_RESP - -2147483645]
_ = x[SUBMIT_SM-4]
_ = x[SUBMIT_SM_RESP - -2147483644]
_ = x[DELIVER_SM-5]
_ = x[DELIVER_SM_RESP - -2147483643]
_ = x[UNBIND-6]
_ = x[UNBIND_RESP - -2147483642]
_ = x[REPLACE_SM-7]
_ = x[REPLACE_SM_RESP - -2147483641]
_ = x[CANCEL_SM-8]
_ = x[CANCEL_SM_RESP - -2147483640]
_ = x[BIND_TRANSCEIVER-9]
_ = x[BIND_TRANSCEIVER_RESP - -2147483639]
_ = x[OUTBIND-11]
_ = x[ENQUIRE_LINK-21]
_ = x[ENQUIRE_LINK_RESP - -2147483627]
_ = x[SUBMIT_MULTI-33]
_ = x[SUBMIT_MULTI_RESP - -2147483615]
_ = x[ALERT_NOTIFICATION-258]
_ = x[DATA_SM-259]
_ = x[DATA_SM_RESP - -2147483389]
}
const (
_CommandIDType_name_0 = "GENERIC_NACKBIND_RECEIVER_RESPBIND_TRANSMITTER_RESPQUERY_SM_RESPSUBMIT_SM_RESPDELIVER_SM_RESPUNBIND_RESPREPLACE_SM_RESPCANCEL_SM_RESPBIND_TRANSCEIVER_RESP"
_CommandIDType_name_1 = "ENQUIRE_LINK_RESP"
_CommandIDType_name_2 = "SUBMIT_MULTI_RESP"
_CommandIDType_name_3 = "DATA_SM_RESP"
_CommandIDType_name_4 = "BIND_RECEIVERBIND_TRANSMITTERQUERY_SMSUBMIT_SMDELIVER_SMUNBINDREPLACE_SMCANCEL_SMBIND_TRANSCEIVER"
_CommandIDType_name_5 = "OUTBIND"
_CommandIDType_name_6 = "ENQUIRE_LINK"
_CommandIDType_name_7 = "SUBMIT_MULTI"
_CommandIDType_name_8 = "ALERT_NOTIFICATIONDATA_SM"
)
var (
_CommandIDType_index_0 = [...]uint8{0, 12, 30, 51, 64, 78, 93, 104, 119, 133, 154}
_CommandIDType_index_4 = [...]uint8{0, 13, 29, 37, 46, 56, 62, 72, 81, 97}
_CommandIDType_index_8 = [...]uint8{0, 18, 25}
)
func (i CommandIDType) String() string {
switch {
case -2147483648 <= i && i <= -2147483639:
i -= -2147483648
return _CommandIDType_name_0[_CommandIDType_index_0[i]:_CommandIDType_index_0[i+1]]
case i == -2147483627:
return _CommandIDType_name_1
case i == -2147483615:
return _CommandIDType_name_2
case i == -2147483389:
return _CommandIDType_name_3
case 1 <= i && i <= 9:
i -= 1
return _CommandIDType_name_4[_CommandIDType_index_4[i]:_CommandIDType_index_4[i+1]]
case i == 11:
return _CommandIDType_name_5
case i == 21:
return _CommandIDType_name_6
case i == 33:
return _CommandIDType_name_7
case 258 <= i && i <= 259:
i -= 258
return _CommandIDType_name_8[_CommandIDType_index_8[i]:_CommandIDType_index_8[i+1]]
default:
return "CommandIDType(" + strconv.FormatInt(int64(i), 10) + ")"
}
}
================================================
FILE: data/other_codings.go
================================================
package data
import (
"golang.org/x/text/encoding/unicode"
)
var (
// UTF16BEM is UTF-16 Big Endian with BOM (byte order mark).
UTF16BEM = &utf16BEM{}
// UTF16LEM is UTF-16 Little Endian with BOM.
UTF16LEM = &utf16LEM{}
// UTF16BE is UTF-16 Big Endian without BOM.
UTF16BE = &utf16BE{}
// UTF16LE is UTF-16 Little Endian without BOM.
UTF16LE = &utf16LE{}
)
type utf16BEM struct{}
func (c utf16BEM) Encode(str string) ([]byte, error) {
tmp := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
return encode(str, tmp.NewEncoder())
}
func (c utf16BEM) Decode(data []byte) (string, error) {
tmp := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
return decode(data, tmp.NewDecoder())
}
type utf16LEM struct{}
func (c utf16LEM) Encode(str string) ([]byte, error) {
tmp := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM)
return encode(str, tmp.NewEncoder())
}
func (c utf16LEM) Decode(data []byte) (string, error) {
tmp := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM)
return decode(data, tmp.NewDecoder())
}
type utf16BE struct{}
func (c utf16BE) Encode(str string) ([]byte, error) {
tmp := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
return encode(str, tmp.NewEncoder())
}
func (c utf16BE) Decode(data []byte) (string, error) {
tmp := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
return decode(data, tmp.NewDecoder())
}
type utf16LE struct{}
func (c utf16LE) Encode(str string) ([]byte, error) {
tmp := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
return encode(str, tmp.NewEncoder())
}
func (c utf16LE) Decode(data []byte) (string, error) {
tmp := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
return decode(data, tmp.NewDecoder())
}
================================================
FILE: data/pkg.go
================================================
package data
import (
"fmt"
"sync/atomic"
)
//nolint
const (
SM_CONNID_LEN = 16
SM_MSG_LEN = 254
SM_SYSID_LEN = 16
SM_MSGID_LEN = 64
SM_PASS_LEN = 9
SM_DATE_LEN = 17
SM_SRVTYPE_LEN = 6
SM_SYSTYPE_LEN = 13
SM_ADDR_LEN = 21
SM_DATA_ADDR_LEN = 65
SM_ADDR_RANGE_LEN = 41
SM_TYPE_LEN = 13
SM_DL_NAME_LEN = 21
SM_PARAM_NAME_LEN = 10
SM_PARAM_VALUE_LEN = 10
SM_MAX_CNT_DEST_ADDR = 254
// GSM specific, short message must be no larger than 140 octets
SM_GSM_MSG_LEN = 140
CONNECTION_CLOSED = 0
CONNECTION_OPENED = 1
SM_ACK = 1
SM_NO_ACK = 0
SM_RESPONSE_ACK = 0
SM_RESPONSE_TNACK = 1
SM_RESPONSE_PNACK = 2
// Interface_Version
SMPP_V33 int8 = int8(-0x33)
SMPP_V34 = byte(0x34)
// Address_TON
GSM_TON_UNKNOWN = byte(0x00)
GSM_TON_INTERNATIONAL = byte(0x01)
GSM_TON_NATIONAL = byte(0x02)
GSM_TON_NETWORK = byte(0x03)
GSM_TON_SUBSCRIBER = byte(0x04)
GSM_TON_ALPHANUMERIC = byte(0x05)
GSM_TON_ABBREVIATED = byte(0x06)
GSM_TON_RESERVED_EXTN = byte(0x07)
// Address_NPI
GSM_NPI_UNKNOWN = byte(0x00)
GSM_NPI_E164 = byte(0x01)
GSM_NPI_ISDN = GSM_NPI_E164
GSM_NPI_X121 = byte(0x03)
GSM_NPI_TELEX = byte(0x04)
GSM_NPI_LAND_MOBILE = byte(0x06)
GSM_NPI_NATIONAL = byte(0x08)
GSM_NPI_PRIVATE = byte(0x09)
GSM_NPI_ERMES = byte(0x0A)
GSM_NPI_INTERNET = byte(0x0E)
GSM_NPI_WAP_CLIENT_ID = byte(0x12)
GSM_NPI_RESERVED_EXTN = byte(0x0F)
// Service_Type
SERVICE_NULL string = ""
SERVICE_CMT string = "CMT"
SERVICE_CPT string = "CPT"
SERVICE_VMN string = "VMN"
SERVICE_VMA string = "VMA"
SERVICE_WAP string = "WAP"
SERVICE_USSD string = "USSD"
SMPP_PROTOCOL = byte(1)
SMPPP_PROTOCOL = byte(2)
SM_SERVICE_MOBILE_TERMINATED = byte(0)
SM_SERVICE_MOBILE_ORIGINATED = byte(1)
SM_SERVICE_MOBILE_TRANSCEIVER = byte(2)
// State of message at SMSC
SM_STATE_EN_ROUTE = 1 // default state for messages in transit
SM_STATE_DELIVERED = 2 // message is delivered
SM_STATE_EXPIRED = 3 // validity period expired
SM_STATE_DELETED = 4 // message has been deleted
SM_STATE_UNDELIVERABLE = 5 // undeliverable
SM_STATE_ACCEPTED = 6 // message is in accepted state
SM_STATE_INVALID = 7 // message is in invalid state
SM_STATE_REJECTED = 8 // message is in rejected state
//******************
// ESMClass Defines
//******************
// Messaging Mode
SM_ESM_DEFAULT = 0x00 // Default SMSC Mode or Message Type
SM_DATAGRAM_MODE = 0x01 // Use one-shot express mode
SM_FORWARD_MODE = 0x02 // Do not use
SM_STORE_FORWARD_MODE = 0x03 // Use store & forward
// Send/Receive TDMA & CDMA Message Type
SM_SMSC_DLV_RCPT_TYPE = 0x04 // Recv Msg contains SMSC delivery receipt
SM_ESME_DLV_ACK_TYPE = 0x08 // Send/Recv Msg contains ESME delivery acknowledgement
SM_ESME_MAN_USER_ACK_TYPE = 0x10 // Send/Recv Msg contains manual/user acknowledgment
SM_CONV_ABORT_TYPE = 0x18 // Recv Msg contains conversation abort (Korean CDMA)
SM_INTMD_DLV_NOTIFY_TYPE = 0x20 // Recv Msg contains intermediate notification
// GSM Network features
SM_NONE_GSM = 0x00 // No specific features selected
SM_UDH_GSM = 0x40 // User Data Header indicator set
SM_REPLY_PATH_GSM = 0x80 // Reply path set
SM_UDH_REPLY_PATH_GSM = 0xC0 // Both UDH & Reply path
// Optional Parameter Tags, Min and Max Lengths
// Following are the 2 byte tag and min/max lengths for
// supported optional parameter (declann)
OPT_PAR_MSG_WAIT = 2
// Privacy Indicator
OPT_PAR_PRIV_IND = 0x0201
// Source Subaddress
OPT_PAR_SRC_SUBADDR = 0x0202
OPT_PAR_SRC_SUBADDR_MIN = 2
OPT_PAR_SRC_SUBADDR_MAX = 23
// Destination Subaddress
OPT_PAR_DEST_SUBADDR = 0x0203
OPT_PAR_DEST_SUBADDR_MIN = 2
OPT_PAR_DEST_SUBADDR_MAX = 23
// User Message Reference
OPT_PAR_USER_MSG_REF = 0x0204
// User Response Code
OPT_PAR_USER_RESP_CODE = 0x0205
// Language Indicator
OPT_PAR_LANG_IND = 0x020D
// Source Port
OPT_PAR_SRC_PORT = 0x020A
// Destination Port
OPT_PAR_DST_PORT = 0x020B
// Concat Msg Ref Num
OPT_PAR_SAR_MSG_REF_NUM = 0x020C
// Concat Total Segments
OPT_PAR_SAR_TOT_SEG = 0x020E
// Concat Segment Seqnums
OPT_PAR_SAR_SEG_SNUM = 0x020F
// SC Interface Version
OPT_PAR_SC_IF_VER = 0x0210
// Display Time
OPT_PAR_DISPLAY_TIME = 0x1201
// Validity Information
OPT_PAR_MS_VALIDITY = 0x1204
// DPF Result
OPT_PAR_DPF_RES = 0x0420
// Set DPF
OPT_PAR_SET_DPF = 0x0421
// MS Availability Status
OPT_PAR_MS_AVAIL_STAT = 0x0422
// Network Error Code
OPT_PAR_NW_ERR_CODE = 0x0423
OPT_PAR_NW_ERR_CODE_MIN = 3
OPT_PAR_NW_ERR_CODE_MAX = 3
// Extended int16 Message has no size limit
// Delivery Failure Reason
OPT_PAR_DEL_FAIL_RSN = 0x0425
// More Messages to Follow
OPT_PAR_MORE_MSGS = 0x0426
// Message State
OPT_PAR_MSG_STATE = 0x0427
// Callback Number
OPT_PAR_CALLBACK_NUM = 0x0381
OPT_PAR_CALLBACK_NUM_MIN = 4
OPT_PAR_CALLBACK_NUM_MAX = 19
// Callback Number Presentation Indicator
OPT_PAR_CALLBACK_NUM_PRES_IND = 0x0302
// Callback Number Alphanumeric Tag
OPT_PAR_CALLBACK_NUM_ATAG = 0x0303
OPT_PAR_CALLBACK_NUM_ATAG_MIN = 1
OPT_PAR_CALLBACK_NUM_ATAG_MAX = 65
// Number of messages in Mailbox
OPT_PAR_NUM_MSGS = 0x0304
// SMS Received Alert
OPT_PAR_SMS_SIGNAL = 0x1203
// Message Delivery Alert
OPT_PAR_ALERT_ON_MSG_DELIVERY = 0x130C
// ITS Reply Type
OPT_PAR_ITS_REPLY_TYPE = 0x1380
// ITS Session Info
OPT_PAR_ITS_SESSION_INFO = 0x1383
// USSD Service Op
OPT_PAR_USSD_SER_OP = 0x0501
// Priority
SM_NOPRIORITY = 0
SM_PRIORITY = 1
// Registered delivery
// SMSC Delivery Receipt (bits 1 & 0)
SM_SMSC_RECEIPT_MASK = byte(0x03)
SM_SMSC_RECEIPT_NOT_REQUESTED = byte(0x00)
SM_SMSC_RECEIPT_REQUESTED = byte(0x01)
SM_SMSC_RECEIPT_ON_FAILURE = byte(0x02)
// SME originated acknowledgement (bits 3 & 2)
SM_SME_ACK_MASK = byte(0x0c)
SM_SME_ACK_NOT_REQUESTED = byte(0x00)
SM_SME_ACK_DELIVERY_REQUESTED = byte(0x04)
SM_SME_ACK_MANUAL_REQUESTED = byte(0x08)
SM_SME_ACK_BOTH_REQUESTED = byte(0x0c)
// Intermediate notification (bit 5)
SM_NOTIF_MASK = byte(0x010)
SM_NOTIF_NOT_REQUESTED = byte(0x000)
SM_NOTIF_REQUESTED = byte(0x010)
// Replace if Present flag
SM_NOREPLACE = 0
SM_REPLACE = 1
// Destination flag
SM_DEST_SME_ADDRESS = 1
SM_DEST_DL_NAME = 2
// Higher Layer Message Type
SM_LAYER_WDP = 0
SM_LAYER_WCMP = 1
// Operation Class
SM_OPCLASS_DATAGRAM = 0
SM_OPCLASS_TRANSACTION = 3
// Originating MSC Address
OPT_PAR_ORIG_MSC_ADDR = -32639 // int16(0x8081)
OPT_PAR_ORIG_MSC_ADDR_MIN = 1
OPT_PAR_ORIG_MSC_ADDR_MAX = 24
// Destination MSC Address
OPT_PAR_DEST_MSC_ADDR = -32638 // int16(0x8082)
OPT_PAR_DEST_MSC_ADDR_MIN = 1
OPT_PAR_DEST_MSC_ADDR_MAX = 24
// Unused Tag
OPT_PAR_UNUSED = 0xffff
// Destination Address Subunit
OPT_PAR_DST_ADDR_SUBUNIT = 0x0005
// Destination Network Type
OPT_PAR_DST_NW_TYPE = 0x0006
// Destination Bearer Type
OPT_PAR_DST_BEAR_TYPE = 0x0007
// Destination Telematics ID
OPT_PAR_DST_TELE_ID = 0x0008
// Source Address Subunit
OPT_PAR_SRC_ADDR_SUBUNIT = 0x000D
// Source Network Type
OPT_PAR_SRC_NW_TYPE = 0x000E
// Source Bearer Type
OPT_PAR_SRC_BEAR_TYPE = 0x000F
// Source Telematics ID
OPT_PAR_SRC_TELE_ID = 0x0010
// QOS Time to Live
OPT_PAR_QOS_TIME_TO_LIVE = 0x0017
OPT_PAR_QOS_TIME_TO_LIVE_MIN = 1
OPT_PAR_QOS_TIME_TO_LIVE_MAX = 4
// Payload Type
OPT_PAR_PAYLOAD_TYPE = 0x0019
// Additional Status Info Text
OPT_PAR_ADD_STAT_INFO = 0x001D
OPT_PAR_ADD_STAT_INFO_MIN = 1
OPT_PAR_ADD_STAT_INFO_MAX = 256
// Receipted Message ID
OPT_PAR_RECP_MSG_ID = 0x001E
OPT_PAR_RECP_MSG_ID_MIN = 1
OPT_PAR_RECP_MSG_ID_MAX = 65
// Message Payload
OPT_PAR_MSG_PAYLOAD = 0x0424
OPT_PAR_MSG_PAYLOAD_MIN = 1
OPT_PAR_MSG_PAYLOAD_MAX = 1500
// User Data Header
UDH_CONCAT_MSG_8_BIT_REF = byte(0x00)
UDH_CONCAT_MSG_16_BIT_REF = byte(0x08)
/**
* @deprecated As of version 1.3 of the library there are defined
* new encoding constants for base set of encoding supported by Java Runtime.
* The <code>CHAR_ENC</code> is replaced by <code>ENC_ASCII</code>
* and redefined in this respect.
*/
DFLT_MSGID string = ""
DFLT_MSG string = ""
DFLT_SRVTYPE string = ""
DFLT_SYSID string = ""
DFLT_PASS string = ""
DFLT_SYSTYPE string = ""
DFLT_ADDR_RANGE string = ""
DFLT_DATE string = ""
DFLT_ADDR string = ""
DFLT_MSG_STATE byte = 0
DFLT_ERR byte = 0
DFLT_SCHEDULE string = ""
DFLT_VALIDITY string = ""
DFLT_REG_DELIVERY = SM_SMSC_RECEIPT_NOT_REQUESTED | SM_SME_ACK_NOT_REQUESTED | SM_NOTIF_NOT_REQUESTED
DFLT_DFLTMSGID = byte(0)
DFLT_MSG_LEN = byte(0)
DFLT_ESM_CLASS = byte(0)
DFLT_DATA_CODING = byte(0)
DFLT_PROTOCOLID = byte(0)
DFLT_PRIORITY_FLAG = byte(0)
DFTL_REPLACE_IFP = byte(0)
DFLT_DL_NAME string = ""
DFLT_GSM_TON = GSM_TON_UNKNOWN
DFLT_GSM_NPI = GSM_NPI_UNKNOWN
DFLT_DEST_FLAG = byte(0) // not set
MAX_PDU_LEN = 64 << 10
PDU_HEADER_SIZE = 16 // 4 integers
TLV_HEADER_SIZE = 4 // 2 int16s: tag & length
// all times in milliseconds
RECEIVER_TIMEOUT int64 = 60000
CONNECTION_RECEIVE_TIMEOUT int64 = 10000
UNBIND_RECEIVE_TIMEOUT int64 = 5000
CONNECTION_SEND_TIMEOUT int64 = 20000
COMMS_TIMEOUT int64 = 60000
QUEUE_TIMEOUT int64 = 10000
ACCEPT_TIMEOUT int64 = 60000
RECEIVE_BLOCKING int64 = -1
MAX_VALUE_PORT = 65535
MIN_VALUE_PORT = 100
MIN_LENGTH_ADDRESS = 7
)
var (
// ErrNotImplSplitterInterface indicates that encoding does not support Splitter interface
ErrNotImplSplitterInterface = fmt.Errorf("Encoding not implementing Splitter interface")
// ErrNotImplDecode indicates that encoding does not support Decode method
ErrNotImplDecode = fmt.Errorf("Decode is not implemented in this Encoding")
// ErrNotImplEncode indicates that encoding does not support Encode method
ErrNotImplEncode = fmt.Errorf("Encode is not implemented in this Encoding")
)
var defaultTon atomic.Value
var defaultNpi atomic.Value
func init() {
defaultTon.Store(DFLT_GSM_TON)
defaultNpi.Store(DFLT_GSM_NPI)
}
// SetDefaultTon set default ton.
func SetDefaultTon(dfltTon byte) {
defaultTon.Store(dfltTon)
}
// GetDefaultTon get default ton.
func GetDefaultTon() byte {
return defaultTon.Load().(byte)
}
// SetDefaultNpi set default npi.
func SetDefaultNpi(dfltNpi byte) {
defaultNpi.Store(dfltNpi)
}
// GetDefaultNpi get default npi.
func GetDefaultNpi() byte {
return defaultNpi.Load().(byte)
}
================================================
FILE: data/pkg_test.go
================================================
package data
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestDefaultNpi(t *testing.T) {
SetDefaultNpi(13)
require.EqualValues(t, 13, GetDefaultNpi())
}
func TestDefaultTon(t *testing.T) {
SetDefaultTon(19)
require.EqualValues(t, 19, GetDefaultTon())
}
================================================
FILE: data/utils.go
================================================
package data
import "unicode"
// FindEncoding returns suitable encoding for a string.
// If string is ascii, then GSM7Bit. If not, then UCS2.
func FindEncoding(s string) (enc Encoding) {
if isASCII(s) {
enc = GSM7BIT
} else {
enc = UCS2
}
return
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] > unicode.MaxASCII {
return false
}
}
return true
}
================================================
FILE: data/utils_test.go
================================================
package data
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestFindEncoding(t *testing.T) {
require.Equal(t, GSM7BIT, FindEncoding("abc30hb3bk2lopzSD=2-^"))
require.Equal(t, UCS2, FindEncoding("Trần Lập và ban nhạc Bức tường huyền thoại"))
require.Equal(t, UCS2, FindEncoding("Đừng buồn thế dù ngoài kia vẫn mưa nghiễng rợi tý tỵ"))
}
================================================
FILE: errors/pkg.go
================================================
package errors
import (
"fmt"
"github.com/linxGnu/gosmpp/data"
)
// SmppErr indicates smpp error(s), compatible with OpenSMPP.
type SmppErr struct {
err string
serialVersionUID int64
}
// Error interface.
func (s *SmppErr) Error() string {
return fmt.Sprintf("Error happened: [%s]. SerialVersionUID: [%d]", s.err, s.serialVersionUID)
}
var (
// ErrInvalidPDU indicates invalid pdu payload.
ErrInvalidPDU error = &SmppErr{err: "PDU payload is invalid", serialVersionUID: -6985061862208729984}
// ErrUnknownCommandID indicates unknown command id.
ErrUnknownCommandID error = &SmppErr{err: "Unknown command id", serialVersionUID: -5091873576710864441}
// ErrWrongDateFormat indicates wrong date format.
ErrWrongDateFormat error = &SmppErr{err: "Wrong date format", serialVersionUID: 5831937612139037591}
// ErrShortMessageLengthTooLarge indicates short message length is too large.
ErrShortMessageLengthTooLarge error = &SmppErr{err: fmt.Sprintf("Encoded short message data exceeds size of %d", data.SM_MSG_LEN), serialVersionUID: 78237205927624}
// ErrUDHTooLong UDH-L is larger than total length of short message data
ErrUDHTooLong = fmt.Errorf("User Data Header is too long for PDU short message")
)
================================================
FILE: errors/pkg_test.go
================================================
package errors
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestErr(t *testing.T) {
require.True(t, strings.HasPrefix(ErrInvalidPDU.Error(), "Error happened: ["))
}
================================================
FILE: example/smsc_simulator/smsc.cpp
================================================
//
// smscsimulator.cpp
// SMPPLib
//
// Created by Mark Hay on 12/05/2019.
// Copyright © 2019 Melrose Labs. All rights reserved.
//
// Build: g++ smscsimulator.cpp -o MLSMSCSimulator && ./MLSMSCSimulator
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <string>
#include <exception>
#include <map>
#include <list>
using namespace std;
#include <unistd.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define TRUE (1 == 1)
#define FALSE (!TRUE)
//
uint64_t session_id_next = 0; // ID for each session
// General
uint64_t currentUSecsSinceEpoch(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
}
// Client config
class ClientConfig {
private:
ClientConfig() {}
~ClientConfig() {}
public:
static ClientConfig& instance() {
static ClientConfig c;
return c;
}
typedef enum { BINDRESP_WITH_SC_INTERACE_VERSION_TLV } ConfigEntry;
bool is(string esme_id, ConfigEntry entry) { return false; }
};
// Message deliverer
class MessageDeliverer {
public:
class Message {
public:
uint8_t source_addr_ton;
uint8_t source_addr_npi;
char source_addr[32];
uint8_t dest_addr_ton;
uint8_t dest_addr_npi;
char destination_addr[32];
uint8_t esm_class;
uint8_t protocol_id;
uint8_t priority_flag;
char schedule_delivery_time[32];
char validity_period[32];
uint8_t registered_delivery;
uint8_t replace_if_present_flag;
uint8_t data_coding;
uint8_t sm_default_msg_id;
uint8_t sm_length;
uint8_t short_message[160];
string smscMessageID;
private:
string content;
public:
Message() {}
Message(char* in) { content = in; }
~Message() {}
string getContent(void) { return content; }
void setSource(uint8_t ton, uint8_t npi, char* addr) {
source_addr_ton = ton;
source_addr_npi = npi;
strcpy(source_addr, addr);
}
void setDestination(uint8_t ton, uint8_t npi, char* addr) {
dest_addr_ton = ton;
dest_addr_npi = npi;
strcpy(destination_addr, addr);
}
void setRegisteredDelivery(uint8_t val) { registered_delivery = val; }
void setShortMessage(uint8_t* sm_in, uint8_t sm_len_in) {
memcpy(short_message, sm_in, sm_len_in);
sm_length = sm_len_in;
}
void setSMSCMessageID(char* id) { smscMessageID = id; }
};
private:
// time-ordered list [using STL map] of lists containing messages
typedef map<uint64_t /*time*/, list<Message>> MessageQueue;
MessageQueue mq;
MessageDeliverer() {}
typedef map<string, MessageDeliverer*> MDMap;
static MDMap mapInstance;
bool empty(void) { return (mq.size() == 0); }
bool get(Message& msgout) {
if (mq.size() == 0) return false; // no time-lists
uint64_t firstListTime = (*mq.begin()).first;
uint64_t now = currentUSecsSinceEpoch();
if (firstListTime > now) return false; // nothing due to be deliverered
// we have a message (or messages) that are due to be delivered
msgout = (*mq.begin()).second.front();
(*mq.begin()).second.pop_front(); // remove from list
if ((*mq.begin()).second.size() == 0) // now empty - remove list
mq.erase(mq.begin());
return true;
}
public:
~MessageDeliverer() {}
static MessageDeliverer* getInstance(string& systemID) {
MDMap::iterator it = mapInstance.find(systemID);
if (it == mapInstance.end()) {
std::pair<MDMap::iterator, bool> res =
mapInstance.insert(MDMap::value_type(systemID, new MessageDeliverer));
return (res.first)->second;
} else
return (*it).second;
}
static bool getInstance_get(string& systemID, Message& msgout) {
MDMap::iterator it = mapInstance.find(systemID);
if (it == mapInstance.end()) {
return false;
}
bool found = (*it).second->get(msgout);
if ((*it).second->empty()) {
delete (*it).second;
mapInstance.erase(systemID);
}
return found;
}
void add(uint64_t timeDeliver, Message msg) {
MessageQueue::iterator it = mq.find(timeDeliver);
if (it == mq.end()) {
// no time-list exists - create
list<Message> msgList; // empty message list
std::pair<MessageQueue::iterator, bool> ret;
ret = mq.insert({timeDeliver, msgList});
if (ret.second == false) return; // failed to insert
it = ret.first; // iterator to newly inserted time-list
}
(*it).second.push_back(msg); // add message to time-list
}
};
MessageDeliverer::MDMap MessageDeliverer::mapInstance;
// Sub-SMPP layer
class SMPPSocket {
protected:
int socket;
public:
SMPPSocket() {}
virtual ~SMPPSocket() {}
virtual bool recvA(uint8_t&) = 0;
virtual void recv(void) = 0;
virtual bool send(uint8_t*, int len) = 0;
virtual long bytes_to_read(void) = 0;
};
class SMPPSocketUnencrypted : public SMPPSocket {
private:
public:
SMPPSocketUnencrypted() {}
SMPPSocketUnencrypted(int socket_in) { socket = socket_in; }
~SMPPSocketUnencrypted() {}
long bytes_to_read(void) {
long count = 0;
ioctl((int)socket, FIONREAD, &count);
return count;
}
bool recvA(uint8_t& oct) {
int n = (int)::recv(socket, (void*)&oct, 1, 0);
return (n > 0);
}
void recv(void) {}
bool send(uint8_t* buf, int len) {
return ::send(socket, (void*)buf, len, 0);
}
};
// SMPP
class SMPP {
public:
class CmdStatus {
public:
static const uint64_t ESME_ROK = 0x00000000;
static const uint64_t ESME_RINVBNDSTS = 0x00000004;
static const uint64_t ESME_INVDSTADR = 0x0000000B;
static const uint64_t ESME_RBINDFAIL = 0x0000000D;
static const uint64_t ESME_RINVSYSID = 0x0000000F;
static const uint64_t ESME_RSUBMITFAIL = 0x00000045;
static const uint64_t ESME_RINVSCHED = 0x00000061;
};
class CmdID {
public:
static const uint64_t BindReceiver = 0x00000001;
static const uint64_t BindTransmitter = 0x00000002;
static const uint64_t QuerySM = 0x00000003;
static const uint64_t SubmitSM = 0x00000004;
static const uint64_t DeliverSM = 0x00000005;
static const uint64_t Unbind = 0x00000006;
static const uint64_t ReplaceSM = 0x00000007;
static const uint64_t CancelSM = 0x00000008;
static const uint64_t BindTransceiver = 0x00000009;
static const uint64_t Outbind = 0x0000000B;
static const uint64_t EnquireLink = 0x00000015;
static const uint64_t SubmitMulti = 0x00000021;
static const uint64_t AlertNotification = 0x00000102;
static const uint64_t DataSM = 0x00000103;
static const uint64_t BroadcastSM = 0x00000111;
static const uint64_t QueryBroadcastSM = 0x00000112;
static const uint64_t CancelBroadcastSM = 0x00000113;
static const uint64_t GenericNack = 0x80000000;
static const uint64_t BindReceiverResp = 0x80000001;
static const uint64_t BindTransmitterResp = 0x80000002;
static const uint64_t QuerySMResp = 0x80000003;
static const uint64_t SubmitSMResp = 0x80000004;
static const uint64_t DeliverSMResp = 0x80000005;
static const uint64_t UnbindResp = 0x80000006;
static const uint64_t ReplaceSMResp = 0x80000007;
static const uint64_t CancelSMResp = 0x80000008;
static const uint64_t BindTransceiverResp = 0x80000009;
static const uint64_t EnquireLinkResp = 0x80000015;
static const uint64_t SubmitMultiResp = 0x80000021;
static const uint64_t DataSMResp = 0x80000103;
static const uint64_t BroadcastSMResp = 0x80000111;
static const uint64_t QueryBroadcastSMResp = 0x80000112;
static const uint64_t CancelBroadcastSMResp = 0x80000113;
};
typedef struct {
uint64_t cmdid;
const char* name;
} CmdStrings;
#define CMDEXP(A) CmdID::A, #A
CmdStrings cmdStrings[34] = {{CMDEXP(BindReceiver)},
{CMDEXP(BindTransmitter)},
{CMDEXP(QuerySM)},
{CMDEXP(SubmitSM)},
{CMDEXP(DeliverSM)},
{CMDEXP(Unbind)},
{CMDEXP(ReplaceSM)},
{CMDEXP(CancelSM)},
{CMDEXP(BindTransceiver)},
{CMDEXP(Outbind)},
{CMDEXP(EnquireLink)},
{CMDEXP(SubmitMulti)},
{CMDEXP(AlertNotification)},
{CMDEXP(DataSM)},
{CMDEXP(BroadcastSM)},
{CMDEXP(QueryBroadcastSM)},
{CMDEXP(CancelBroadcastSM)},
{CMDEXP(GenericNack)},
{CMDEXP(BindReceiverResp)},
{CMDEXP(BindTransmitterResp)},
{CMDEXP(QuerySMResp)},
{CMDEXP(SubmitSMResp)},
{CMDEXP(DeliverSMResp)},
{CMDEXP(UnbindResp)},
{CMDEXP(ReplaceSMResp)},
{CMDEXP(CancelSMResp)},
{CMDEXP(BindTransceiverResp)},
{CMDEXP(EnquireLinkResp)},
{CMDEXP(SubmitMultiResp)},
{CMDEXP(DataSMResp)},
{CMDEXP(BroadcastSMResp)},
{CMDEXP(QueryBroadcastSMResp)},
{CMDEXP(CancelBroadcastSMResp)}};
const char* cmdString(uint64_t id) {
for (int i = 0; i < 34; i++) {
if (cmdStrings[i].cmdid == id) return cmdStrings[i].name;
}
return "";
}
static void GSMTimeStringShort(time_t& t, char* szTimestamp, int nLen) {
if (t < 0) return;
szTimestamp[0] = 0x00;
tm* ptm = gmtime(&t);
if (ptm == NULL)
szTimestamp[0] = 0x00;
else
strftime(szTimestamp, nLen, "%y%m%d%H%M", ptm);
}
static time_t GSMStringTime(const char* szBuf) {
tm atm;
int tdif = 0;
char chDir = 0;
memset(&atm, 0, sizeof(tm));
int nRead = sscanf(szBuf, "%02d%02d%02d%02d%02d%02d%*1d%02d%c",
&atm.tm_year, &atm.tm_mon, &atm.tm_mday, &atm.tm_hour,
&atm.tm_min, &atm.tm_sec, &tdif, &chDir);
time_t t = 0;
if (nRead == 5) {
if (atm.tm_year >= 70)
atm.tm_year += 1900;
else
atm.tm_year += 2000;
t = timegm(&atm);
if (t == -1) { // invalid time
t = 0;
}
if (chDir == '+') {
t = t - (tdif * 15 * 60);
}
if (chDir == '-') {
t = t + (tdif * 15 * 60);
}
}
return t;
}
static time_t GSMRelativeTime(char* szBuf) {
time_t t = 0;
int mday, hour, min, sec;
int nRead = sscanf(szBuf, "%*02d%*02d%02d%02d%02d%02d%*1d%*02d%*c", &mday,
&hour, &min, &sec);
if (nRead == 4) t = ((mday * 24 + hour) * 60 + min) * 60 + sec;
return t;
}
};
class SMPPConnection {
public:
class SMPPException {};
private:
const int max_command_body_length = 1024;
bool debug = false;
SMPPSocket* socket = NULL;
char ip[64];
typedef enum { PV_INVALID, PV_LENGTH, PV_ALL } PDUValidity;
typedef struct {
PDUValidity valid; // indicate if this header structure has valid contents
uint64_t command_length;
uint64_t command_id;
uint64_t command_status;
uint64_t sequence_number;
} PDUHeader;
typedef struct {
bool valid;
uint8_t* body;
} PDUBody;
PDUHeader command_received_header = {PV_INVALID, 0, 0, 0, 0};
PDUBody command_received_body = {false, NULL};
// configuration
int enquire_link_period = 0; // seconds
// methods
uint64_t getInteger(void) {
if (socket->bytes_to_read() < 4) throw SMPPException();
uint8_t v0, v1, v2, v3;
socket->recvA(v0);
socket->recvA(v1);
socket->recvA(v2);
socket->recvA(v3);
return (uint64_t)(((v0 << 8) | v1) << 8 | v2) << 8 | v3;
}
uint64_t getBytes(uint64_t len, uint8_t* mem) {
if (socket->bytes_to_read() < len) throw SMPPException();
for (int i = 0; i < len; i++) {
if (socket->recvA(mem[i]) == 0) throw SMPPException();
}
return 0;
}
public:
SMPPConnection() {
socket = NULL;
command_received_header.valid = PV_INVALID;
command_received_body.body = new uint8_t[max_command_body_length];
ip[0] = '\0';
}
~SMPPConnection() {
if (command_received_body.body) delete[] command_received_body.body;
if (socket) delete socket;
}
void setDebug(bool val) { debug = val; }
void allocateSocket(void) { socket = new SMPPSocketUnencrypted; }
void allocateSocket(int fdsocket) {
socket = new SMPPSocketUnencrypted(fdsocket);
}
void setIP(char* ip_in) {
if (ip_in != NULL)
strcpy(ip, ip_in);
else
strcpy(ip, "");
}
char* getIP() { return ip; }
uint64_t endian(uint64_t a) {
uint64_t b;
((uint8_t*)&b)[0] = ((uint8_t*)&a)[3];
((uint8_t*)&b)[1] = ((uint8_t*)&a)[2];
((uint8_t*)&b)[2] = ((uint8_t*)&a)[1];
((uint8_t*)&b)[3] = ((uint8_t*)&a)[0];
return b;
}
bool put(uint64_t sequence_number, uint64_t cmdID, uint64_t status,
uint8_t* param, int len) {
int pdu_len = 16 + len;
uint8_t buf[pdu_len];
*((uint64_t*)(buf + 0)) = endian(pdu_len); // command length
*((uint64_t*)(buf + 4)) = endian(cmdID); // command ID
*((uint64_t*)(buf + 8)) = endian(status); // command status
*((uint64_t*)(buf + 12)) = endian(sequence_number); // sequence number
if ((param != NULL) && (len != 0)) memcpy((char*)(buf + 16), param, len);
// for(int i=0;i<pdu_len;i++) printf("%02x ",buf[i]);
// printf("\n");
return socket->send(buf, pdu_len);
}
uint8_t* getBodyPointer(int& len) {
len = (int)(command_received_header.command_length - 16);
return command_received_body.body;
}
bool get() {
// require "socket"
if (socket == NULL) return false;
// get header
if (command_received_header.valid != PV_ALL) {
// don't have any of the header yet
try {
command_received_header.command_length = getInteger();
command_received_header.command_id = getInteger();
command_received_header.command_status = getInteger();
command_received_header.sequence_number = getInteger();
command_received_header.valid =
PV_ALL; // all header values are now valid
} catch (SMPPException e) {
// no data
if (debug) std::cout << "HEADER No data - ABORT!" << std::endl;
return false;
}
}
if (command_received_header.valid != PV_ALL)
return false; // don't let past here until we have the header
// get body (if present)
command_received_body.valid = false;
uint64_t body_length = command_received_header.command_length - 16;
if (body_length > 0) {
try {
getBytes(body_length, command_received_body.body);
} catch (SMPPException e) {
if (debug) std::cout << "BODY No data" << std::endl;
return false;
}
command_received_body.valid = true;
command_received_header.valid = PV_INVALID;
return true;
} else {
// empty body
command_received_body.valid = true; // empty body (valid)
command_received_body.body = NULL;
command_received_header.valid = PV_INVALID;
return true;
}
return false;
}
uint64_t pduCommandID(void) { return command_received_header.command_id; }
uint64_t pduSequenceNo(void) {
return command_received_header.sequence_number;
}
};
class Session {
protected:
int sessionType;
public:
Session() {}
virtual ~Session() {}
virtual bool timedCheck(void) = 0;
virtual bool run(void) = 0;
};
class AdminSession : public Session {
public:
AdminSession() { sessionType = 0; }
AdminSession(int fdsocket) {
// conn.allocateSocket(fdsocket);
}
~AdminSession() {}
bool timedCheck(void) {
// return true if to close
return true;
}
bool run(void) { return true; }
};
class SMPPSession : public Session {
private:
SMPPConnection conn;
uint64_t session_id;
// session state
string system_id;
string system_type;
long sequence_number_in = -1;
long sequence_number_out = 1;
uint64_t lastPDUFromESMETime = 0;
uint64_t enquireLinkRespPending = 0;
uint64_t closingTime = 0;
public:
typedef enum { BS_NONE, BS_TRX, BS_TX, BS_RX } BindState;
uint8_t version;
BindState bindState;
public:
SMPPSession() {
sessionType = 1;
bindState = BS_NONE;
version = 0x00;
session_id = session_id_next++;
}
SMPPSession(int fdsocket, char* ip) {
bindState = BS_NONE;
version = 0x00;
conn.allocateSocket(fdsocket);
conn.setIP(ip);
session_id = session_id_next++;
}
~SMPPSession() {
if (bindState != BS_NONE) {
logCommand("session aborted", "--");
}
}
void setDebug(bool val) { conn.setDebug(val); }
bool getCOctetString(uint8_t* buf_ptr, int buf_len, int& idx, string& strout,
int max_param_len) {
char str[max_param_len];
int i = 0;
while (idx != buf_len) {
str[i++] = buf_ptr[idx++];
if (str[i - 1] == '\0') {
strout.assign(str);
return true;
}
if (i == max_param_len) return false;
}
return false;
}
bool timedCheck(void) {
// return true if session to close
uint64_t now = currentUSecsSinceEpoch();
// session management
//
if ((closingTime != 0) && (now >= closingTime))
return true; // session was due to close now
if ((lastPDUFromESMETime != 0) &&
((now - lastPDUFromESMETime) >
(120 *
1000000L))) // wait up to 2 mins of inactivity before enquire link
{
if (enquireLinkRespPending == 0) {
// issue enquire link
send(sequence_number_out++, SMPP::CmdID::EnquireLink,
SMPP::CmdStatus::ESME_ROK, NULL, 0);
enquireLinkRespPending = now;
closingTime = 0;
} else {
if (closingTime == 0) {
// waiting on enquire link
uint64_t tsinceenquirelinksent = now - enquireLinkRespPending;
if (tsinceenquirelinksent >
(60 * 1000000L)) // wait up to 1 min on enquire_link response
{
send(sequence_number_out++, SMPP::CmdID::Unbind,
SMPP::CmdStatus::ESME_ROK, NULL, 0);
closingTime =
now + 5 * 1000000L; // close session in 5 seconds time
}
}
}
}
// simulate message delivery + delivery receipt generation
//
if ((system_id.length() > 0) &&
((bindState == SMPPSession::BindState::BS_TRX) ||
(bindState == SMPPSession::BindState::BS_RX))) {
MessageDeliverer::Message msg;
while (MessageDeliverer::getInstance_get(system_id, msg)) {
// indicate message delivered
if (msg.registered_delivery !=
0) // ESME requested receipt so generate one
{
uint8_t source_addr_ton = msg.source_addr_ton,
source_addr_npi = msg.source_addr_npi;
string destination_addr = msg.destination_addr;
uint8_t dest_addr_ton = msg.dest_addr_ton,
dest_addr_npi = msg.dest_addr_npi;
string source_addr = msg.source_addr;
string msgid = msg.smscMessageID;
generateReceipt(source_addr_ton, source_addr_npi, source_addr,
dest_addr_ton, dest_addr_npi, destination_addr,
msgid);
}
if (strstr(msg.destination_addr, system_id.c_str()) !=
NULL) { // system_id is in destination address - assume MO for
// testing purposes
generateMO(msg.source_addr_ton, msg.source_addr_npi, msg.source_addr,
msg.dest_addr_ton, msg.dest_addr_npi, msg.destination_addr,
msg.short_message, msg.sm_length, msg.data_coding);
}
}
}
return false;
}
void generateMO(uint8_t source_addr_ton, uint8_t source_addr_npi,
string source_addr, uint8_t dest_addr_ton,
uint8_t dest_addr_npi, string destination_addr,
uint8_t* short_message, uint8_t sm_length,
uint8_t data_coding) {
uint8_t sbuf[1024];
int sidx = 0;
sbuf[sidx++] = 0x00; // service type
sbuf[sidx++] = source_addr_ton; //
sbuf[sidx++] = source_addr_npi; //
memcpy(sbuf + sidx, source_addr.c_str(),
source_addr.length() + 1); // destination_addr
sidx += source_addr.length() + 1;
sbuf[sidx++] = dest_addr_ton; //
sbuf[sidx++] = dest_addr_npi; //
memcpy(sbuf + sidx, destination_addr.c_str(),
destination_addr.length() + 1); // source_addr
sidx += destination_addr.length() + 1;
sbuf[sidx++] = 0x00; // esm_class
sbuf[sidx++] = 0x00; // protocol_id
sbuf[sidx++] = 0x00; // priority_flag
sbuf[sidx++] = 0x00; // schedule_delivery_time
sbuf[sidx++] = 0x00; // validity_period
sbuf[sidx++] = 0x00; // registered_delivery
sbuf[sidx++] = 0x00; // replace_if_present_flag
sbuf[sidx++] = data_coding; // data_coding
sbuf[sidx++] = 0x00; // sm_default_msg_id
sbuf[sidx++] = sm_length; // sm_length
memcpy((char*)(sbuf + sidx), short_message, sm_length);
sidx += sm_length;
send(sequence_number_out++, SMPP::CmdID::DeliverSM,
SMPP::CmdStatus::ESME_ROK, sbuf, sidx);
}
void generateReceipt(uint8_t source_addr_ton, uint8_t source_addr_npi,
string source_addr, uint8_t dest_addr_ton,
uint8_t dest_addr_npi, string destination_addr,
string msgid) {
// receipt
if ((bindState == SMPPSession::BindState::BS_TRX) ||
(bindState == SMPPSession::BindState::BS_RX)) {
uint8_t sbuf[1024];
int sidx = 0;
sbuf[sidx++] = 0x00; // service type
sbuf[sidx++] = dest_addr_ton; // source_addr_ton
sbuf[sidx++] = dest_addr_npi; // source_addr_npi
memcpy(sbuf + sidx, destination_addr.c_str(),
destination_addr.length() + 1); // source_addr
sidx += destination_addr.length() + 1;
sbuf[sidx++] = source_addr_ton; // dest_addr_ton
sbuf[sidx++] = source_addr_npi; // dest_addr_npi
memcpy(sbuf + sidx, source_addr.c_str(),
source_addr.length() + 1); // destination_addr
sidx += source_addr.length() + 1;
sbuf[sidx++] =
0x04; // esm_class [0x04 Short Message contains MC delivery report]
sbuf[sidx++] = 0x00; // protocol_id
sbuf[sidx++] = 0x00; // priority_flag
sbuf[sidx++] = 0x00; // schedule_delivery_time
sbuf[sidx++] = 0x00; // validity_period
sbuf[sidx++] = 0x00; // registered_delivery
sbuf[sidx++] = 0x00; // replace_if_present_flag
sbuf[sidx++] = 0x00; // data_coding
sbuf[sidx++] = 0x00; // sm_default_msg_id
// - short_message containing receipt in text format
time_t tSubmitStamp = time(NULL);
time_t tDoneStamp = time(NULL);
char szSubmitStamp[32];
char szDoneStamp[32];
SMPP::GSMTimeStringShort(tSubmitStamp, szSubmitStamp,
sizeof(szSubmitStamp));
SMPP::GSMTimeStringShort(tDoneStamp, szDoneStamp, sizeof(szDoneStamp));
char short_message[160];
sprintf(short_message,
"id:%s sub:000 dlvrd:%03d submit date:%s done date:%s stat:%s "
"err:%03d text:",
msgid.c_str(), 1 /* 1 message delivered */, szSubmitStamp,
szDoneStamp, "DELIVRD", 0 /*error*/);
sbuf[sidx++] = strlen(short_message) + 1; // sm_length
memcpy((char*)(sbuf + sidx), short_message,
(int)(strlen(short_message) + 1));
sidx += strlen(short_message) + 1;
// TLVs
if (bindState == SMPPSession::BindState::BS_TRX) {
uint8_t params1[] = {
// message_state TLV
0x04, 0x27, // tag
0x00, 0x01, // length
0x02, // value - delivered
// network_error TLV
0x04, 0x23, // tag
0x00, 0x03, // length
0x03, 0x00, 0x00, // value - GSM, 0, 0
// receipted_message_id TLV
0x00, 0x1e, // tag
0x00, 0x41, // length
// .. message_id (to be appended)
};
memcpy(sbuf + sidx, params1, sizeof(params1));
sidx += sizeof(params1);
memcpy(sbuf + sidx, msgid.c_str(), msgid.length() + 1);
sidx += msgid.length() + 1;
}
send(sequence_number_out++, SMPP::CmdID::DeliverSM,
SMPP::CmdStatus::ESME_ROK, sbuf, sidx);
}
}
bool run(void) {
// return true if closed
uint64_t now = currentUSecsSinceEpoch();
if ((closingTime != 0) && (now >= closingTime))
return true; // session was due to close now
// handle PDUs from ESME
//
bool allowBind = true;
uint64_t cmdid, seqno;
uint8_t sbuf[1024];
if (recv(cmdid, seqno)) {
// SMPP b;
// printf("<< 0x%08llx %s\n",cmdid,b.cmdString(cmdid));
lastPDUFromESMETime = now;
if ((cmdid == SMPP::CmdID::BindTransceiver) ||
(cmdid == SMPP::CmdID::BindReceiver) ||
(cmdid == SMPP::CmdID::BindTransmitter)) {
if (bindState !=
SMPPSession::BindState::BS_NONE) // PROTOCOL must be in unbound
// state for ESME to send bind
// command
{
send(seqno, cmdid + 0x80000000, SMPP::CmdStatus::ESME_RINVBNDSTS,
NULL, 0);
} else {
string esme_system_id = "";
string esme_password = "";
string esme_system_type = "";
uint8_t esme_smpp_ver = 0x00;
int ptr_max = 0;
uint8_t* ptr = conn.getBodyPointer(ptr_max);
int idx = 0;
if (!getCOctetString(ptr, ptr_max, idx, esme_system_id, 16)) {
allowBind = false;
goto parse_complete;
}
if (!getCOctetString(ptr, ptr_max, idx, esme_password, 9)) {
allowBind = false;
goto parse_complete;
}
if (!getCOctetString(ptr, ptr_max, idx, esme_system_type, 13)) {
allowBind = false;
goto parse_complete;
}
if (idx < ptr_max)
esme_smpp_ver = ptr[idx++];
else {
allowBind = false;
goto parse_complete;
}
if ((esme_smpp_ver < 0x34) && (cmdid == SMPP::CmdID::BindTransceiver))
allowBind =
false; // PROTOCOL transceiver bind only allowed for v3.4+
parse_complete: // parse complete label
if (allowBind) {
system_id = esme_system_id;
char smsc_system_id[] = "MelroseLabsSMSC";
uint64_t cmdStatus = SMPP::CmdStatus::ESME_ROK;
if (system_id == "invalid") {
cmdStatus = SMPP::CmdStatus::ESME_RINVSYSID;
// If there is an error in the bind_transmitter or bind_receiver request,
// the SMSC system_id is not returned (see SMPP reference 4.1.2 and 4.1.4).
if (cmdid == SMPP::CmdID::BindTransmitter || cmdid == SMPP::CmdID::BindReceiver) {
std::fill_n(sbuf, 1024, 0);
} else {
memcpy(sbuf, smsc_system_id, strlen(smsc_system_id) + 1);
}
} else {
memcpy(sbuf, smsc_system_id, strlen(smsc_system_id) + 1);
}
if (ClientConfig::instance().is(
esme_system_id,
ClientConfig::ConfigEntry::
BINDRESP_WITH_SC_INTERACE_VERSION_TLV)) {
uint8_t params[] = {
// sc_interface_version TLV
0x02, 0x10, // tag
0x00, 0x01, // length
0x34, // value [v3.4 supported]
};
memcpy(sbuf + strlen(smsc_system_id) + 1, params, sizeof(params));
send(seqno, cmdid + 0x80000000, cmdStatus, sbuf,
strlen(smsc_system_id) + 1 + sizeof(params));
} else
send(seqno, cmdid + 0x80000000, cmdStatus, sbuf,
strlen(smsc_system_id) + 1);
if (cmdid == SMPP::CmdID::BindTransceiver)
bindState = SMPPSession::BindState::BS_TRX;
else if (cmdid == SMPP::CmdID::BindTransmitter)
bindState = SMPPSession::BindState::BS_TX;
else if (cmdid == SMPP::CmdID::BindReceiver)
bindState = SMPPSession::BindState::BS_RX;
else
bindState = SMPPSession::BindState::BS_NONE;
version = esme_smpp_ver;
} else {
send(seqno, SMPP::CmdID::BindTransceiverResp,
SMPP::CmdStatus::ESME_RBINDFAIL, NULL,
0); // responding indicating bind unsuccessful
bindState = SMPPSession::BindState::BS_NONE;
}
}
} else if (cmdid == SMPP::CmdID::Unbind) {
if (bindState != SMPPSession::BindState::BS_NONE) {
send(seqno, SMPP::CmdID::UnbindResp, SMPP::CmdStatus::ESME_ROK, NULL,
0);
bindState = SMPPSession::BindState::BS_NONE;
} else {
send(seqno, SMPP::CmdID::UnbindResp, SMPP::CmdStatus::ESME_RINVBNDSTS,
NULL, 0);
}
} else if (cmdid == SMPP::CmdID::EnquireLinkResp) {
enquireLinkRespPending = 0; // received pending enquire link
} else if (cmdid == SMPP::CmdID::EnquireLink) {
send(seqno, SMPP::CmdID::EnquireLinkResp, SMPP::CmdStatus::ESME_ROK,
NULL, 0);
} else if (cmdid == SMPP::CmdID::GenericNack) {
// no response to GenericNack
} else if (cmdid == SMPP::CmdID::SubmitSM) {
if ((bindState == SMPPSession::BindState::BS_NONE) ||
(bindState == SMPPSession::BindState::BS_RX)) {
send(seqno, SMPP::CmdID::SubmitSMResp,
SMPP::CmdStatus::ESME_RINVBNDSTS, NULL, 0);
} else {
// process requested
uint64_t tNow = currentUSecsSinceEpoch();
uint64_t tESMEDeliveryTimeRequired =
tNow; // default to immediate delivery
bool allowSubmit = true;
uint64_t smppSubmitError = SMPP::CmdStatus::ESME_RSUBMITFAIL;
string service_type = "";
uint8_t source_addr_ton = 0;
uint8_t source_addr_npi = 0;
string source_addr = "";
uint8_t dest_addr_ton = 0;
uint8_t dest_addr_npi = 0;
string destination_addr = "";
string schedule_delivery_time = "";
string validity_period = "";
uint8_t registered_delivery = 0;
uint8_t sm_length;
uint8_t short_message[160];
uint8_t data_coding;
int ptr_max = 0;
uint8_t* ptr = conn.getBodyPointer(ptr_max);
int idx = 0;
if (!getCOctetString(ptr, ptr_max, idx, service_type, 6)) {
allowSubmit = false;
goto parse_complete_submit;
}
if (idx < ptr_max) {
source_addr_ton = ptr[idx++];
} else {
allowSubmit = false;
goto parse_complete_submit;
}
if (idx < ptr_max) {
source_addr_npi = ptr[idx++];
} else {
allowSubmit = false;
goto parse_complete_submit;
}
if (!getCOctetString(ptr, ptr_max, idx, source_addr, 21)) {
allowSubmit = false;
goto parse_complete_submit;
}
if (idx < ptr_max) {
dest_addr_ton = ptr[idx++];
} else {
allowSubmit = false;
goto parse_complete_submit;
}
if (idx < ptr_max) {
dest_addr_npi = ptr[idx++];
} else {
allowSubmit = false;
goto parse_complete_submit;
}
if (!getCOctetString(ptr, ptr_max, idx, destination_addr, 21)) {
allowSubmit = false;
goto parse_complete_submit;
}
idx++; // esm_class
idx++; // protocol_id
idx++; // priority_flag
if (!getCOctetString(ptr, ptr_max, idx, schedule_delivery_time, 17)) {
allowSubmit = false;
goto parse_complete_submit;
}
if (!getCOctetString(ptr, ptr_max, idx, validity_period, 17)) {
allowSubmit = false;
goto parse_complete_submit;
}
registered_delivery = ptr[idx++]; // registered_delivery
idx++; // replace_if_present_flag
data_coding = ptr[idx++]; // data_coding
idx++; // sm_default_msg_id
sm_length = ptr[idx++];
memcpy(short_message, ptr + idx, sm_length);
idx += sm_length;
if (schedule_delivery_time.length() > 0) // scheduled delivery
{
if (schedule_delivery_time[schedule_delivery_time.length() - 1] ==
'R') // relative
tESMEDeliveryTimeRequired =
tNow +
SMPP::GSMRelativeTime((char*)schedule_delivery_time.c_str()) *
1000000L;
else
tESMEDeliveryTimeRequired =
(SMPP::GSMStringTime(schedule_delivery_time.c_str()) + 3 +
(rand() % 10)) *
1000000L;
if (tESMEDeliveryTimeRequired <
tNow) // scheduled delivery time is before now
{
allowSubmit = false;
smppSubmitError = SMPP::CmdStatus::ESME_RINVSCHED;
goto parse_complete_submit;
}
}
// ...
if (destination_addr == "333") {
allowSubmit = false;
goto parse_complete_submit;
} // force ESME_RSUBMITFAIL
if (destination_addr.length() < 8) {
allowSubmit = false;
smppSubmitError = SMPP::CmdStatus::ESME_INVDSTADR;
goto parse_complete_submit;
}
parse_complete_submit:
// send response
if (allowSubmit) {
// accept message and send message ID back to ESME
int msgid_len =
64; // PROTOCOL v3.4 message_id field is COctet String of up to
// 65 chars (inc NULL terminator)
if (version < 0x34)
msgid_len =
8; // PROTOCOL v3.3 message_id field is COctet String (hex)
// of up to 9 characters (inc NULL terminator)
char msgid[msgid_len + 1];
for (int i = 0; i < msgid_len; i++)
msgid[i] =
(rand() % 16) < 10 ? ('0' + rand() % 10) : ('a' + rand() % 6);
msgid[msgid_len] = 0;
send(seqno, SMPP::CmdID::SubmitSMResp, SMPP::CmdStatus::ESME_ROK,
(uint8_t*)msgid, msgid_len + 1);
// sending back MO
generateMO(5, 0, "FakeFrom", 1, 1, "FakeTo", short_message,
sm_length, data_coding);
// add message to deliverer so that receipt will then be sent to
// ESME
uint64_t timeDeliver =
tESMEDeliveryTimeRequired + (3 + (rand() % 10)) * 1000000L;
MessageDeliverer::Message msg;
msg.setSource(source_addr_ton, source_addr_npi,
(char*)source_addr.c_str());
msg.setDestination(dest_addr_ton, dest_addr_npi,
(char*)destination_addr.c_str());
msg.setRegisteredDelivery(registered_delivery);
msg.setShortMessage(short_message, sm_length);
msg.setSMSCMessageID(msgid);
MessageDeliverer::getInstance(system_id)->add(timeDeliver, msg);
} else
send(seqno, SMPP::CmdID::SubmitSMResp, smppSubmitError, NULL,
0); // don't accept message and send NAK back to ESME
}
}
} else {
// error or closed
return true;
}
return false;
}
uint8_t getVersion(void) { return version; }
void setVersion(uint8_t version_in) { version = version_in; }
void logCommand(uint64_t cmdID, const char* direction) {
char buf[640];
SMPP b;
sprintf(buf, "0x%08llx %s", cmdID, b.cmdString(cmdID));
logCommand(buf, direction);
}
void logCommand(char* logline, const char* direction) {
time_t rawtime;
struct tm* timeinfo;
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 80, "%F %X ", timeinfo);
printf("%s %s [s%06llx:%-15s] %s\n", buffer, direction, session_id,
conn.getIP(), logline);
}
bool recv(uint64_t& cmdID, uint64_t& seqNo) {
bool ret = conn.get();
if (ret) {
cmdID = conn.pduCommandID();
seqNo = conn.pduSequenceNo();
logCommand(cmdID, ">>");
}
return ret;
}
bool send(uint64_t seqNo, uint64_t cmdID, uint64_t cmdStatus, uint8_t* param,
int len) {
// SMPP b;
// printf("<< 0x%08llx %s\n",cmdID,b.cmdString(cmdID));
logCommand(cmdID, "<<");
return conn.put(seqNo, cmdID, cmdStatus, param, len);
}
};
// Sockets reference:
// https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzab6/xnonblock.htm
int dolisten(int portno) {
struct sockaddr_in serv_addr;
/* First call to socket() function */
int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
if (listensockfd < 0) {
perror("ERROR opening socket");
return -1;
}
int rc, on = 1;
/*************************************************************/
/* Allow socket descriptor to be reuseable */
/*************************************************************/
rc = setsockopt(listensockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on,
sizeof(on));
if (rc < 0) {
perror("setsockopt() failed");
close(listensockfd);
exit(-1);
}
/*************************************************************/
/* Set socket to be nonblocking. All of the sockets for */
/* the incoming connections will also be nonblocking since */
/* they will inherit that state from the listening socket. */
/*************************************************************/
rc = ioctl(listensockfd, FIONBIO, (char*)&on);
if (rc < 0) {
perror("ioctl() failed");
close(listensockfd);
exit(-1);
}
/* Initialize socket structure */
bzero((char*)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (::bind(listensockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) <
0) {
perror("ERROR on binding");
return -1;
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(listensockfd, 32);
return listensockfd;
}
Session* sessionSockMap[32000]; // array of SMPP session by socket
int main(int argc, const char* argv[]) {
printf("%s build time: %s %s\n", argv[0], __DATE__, __TIME__);
//
int portSMPP = 2775;
int listensockfdSMPP = dolisten(portSMPP);
if (listensockfdSMPP == -1) {
perror("Failed to listen on SMPP port");
exit(1);
}
std::cout << "Listening for SMPP on port " << portSMPP << std::endl;
//
int portAdmin = 8775;
int listensockfdAdmin = dolisten(portAdmin);
if (listensockfdAdmin == -1) {
perror("Failed to listen on admin port");
exit(1);
}
std::cout << "Listening for admin on port " << portAdmin << std::endl;
// Initialize the master fd_set
fd_set master_set, working_set;
FD_ZERO(&master_set);
int max_sd = listensockfdSMPP;
FD_SET(listensockfdSMPP, &master_set);
if (listensockfdAdmin > max_sd) max_sd = listensockfdAdmin;
FD_SET(listensockfdAdmin, &master_set);
//
int rc, i, desc_ready;
int end_server = FALSE;
int new_sd;
int close_conn;
struct timeval timeout;
// Loop waiting for incoming connects or for incoming data
do {
// Copy the master fd_set over to the working fd_set.
memcpy(&working_set, &master_set, sizeof(master_set));
// Initialize the timeval struct to 1 second. If no
// activity after 1 second then wake-up and cycle.
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// Call select() and wait for it to complete.
rc = select(max_sd + 1, &working_set, NULL, NULL, &timeout);
// Check to see if the select call failed.
if (rc < 0) {
perror(" select() failed");
break;
}
// Check to see if select call timed out.
if (rc == 0) {
// perform periodic session tasks
for (i = 0; i <= max_sd; ++i) {
if (sessionSockMap[i] != NULL)
if (sessionSockMap[i]->timedCheck()) {
printf(" %ld Force close on connection - %d.\n", time(NULL), i);
if (sessionSockMap[i] != NULL) {
delete sessionSockMap[i];
sessionSockMap[i] = NULL;
}
/*
If the close_conn flag was turned on, we need
to clean up this active connection. This
clean up process includes removing the
descriptor from the master set and
determining the new maximum descriptor value
based on the bits that are still turned on in
the master set.
*/
close(i);
FD_CLR(i, &master_set);
if (i == max_sd) {
while (FD_ISSET(max_sd, &master_set) == FALSE) {
max_sd -= 1;
}
}
}
}
continue;
}
/**********************************************************/
/* One or more descriptors are readable. Need to */
/* determine which ones they are. */
/**********************************************************/
desc_ready = rc;
for (i = 0; i <= max_sd && desc_ready > 0; ++i) {
/*******************************************************/
/* Check to see if this descriptor is ready */
/*******************************************************/
if (FD_ISSET(i, &working_set)) {
/****************************************************/
/* A descriptor was found that was readable - one */
/* less has to be looked for. This is being done */
/* so that we can stop looking at the working set */
/* once we have found all of the descriptors that */
/* were ready. */
/****************************************************/
desc_ready -= 1;
/***********************************************************/
/* Check to see if this is the listening socket (SMPP) */
/***********************************************************/
if (i == listensockfdSMPP) {
// printf(" Listening socket (SMPP) is readable\n");
/*************************************************/
/* Accept all incoming connections that are */
/* queued up on the listening socket before we */
/* loop back and call select again. */
/*************************************************/
do {
/**********************************************/
/* Accept each incoming connection. If */
/* accept fails with EWOULDBLOCK, then we */
/* have accepted all of them. Any other */
/* failure on accept will cause us to end the */
/* server. */
/**********************************************/
struct sockaddr_in client_addr;
int clen = sizeof(sockaddr_in);
new_sd = accept(listensockfdSMPP, (struct sockaddr*)&client_addr,
(socklen_t*)&clen);
if (new_sd < 0) {
if (errno != EWOULDBLOCK) {
perror(" accept() failed (SMPP)");
if (errno != EMFILE) end_server = TRUE;
}
break;
}
char* ip = inet_ntoa(client_addr.sin_addr);
//
SMPPSession* newsession = new SMPPSession(new_sd, ip);
sessionSockMap[new_sd] = newsession;
/**********************************************/
/* Add the new incoming connection to the */
/* master read set */
/**********************************************/
// printf(" New incoming connection - %d\n", new_sd);
FD_SET(new_sd, &master_set);
if (new_sd > max_sd) max_sd = new_sd;
/**********************************************/
/* Loop back up and accept another incoming */
/* connection */
/**********************************************/
} while (new_sd != -1);
} else
/***********************************************************/
/* Check to see if this is the listening socket (admin) */
/***********************************************************/
if (i == listensockfdAdmin) {
// printf(" Listening socket (admin) is readable\n");
/*************************************************/
/* Accept all incoming connections that are */
/* queued up on the listening socket before we */
/* loop back and call select again. */
/*************************************************/
do {
/**********************************************/
/* Accept each incoming connection. If */
/* accept fails with EWOULDBLOCK, then we */
/* have accepted all of them. Any other */
/* failure on accept will cause us to end the */
/* server. */
/**********************************************/
new_sd = accept(listensockfdAdmin, NULL, NULL);
if (new_sd < 0) {
if (errno != EWOULDBLOCK) {
perror(" accept() failed (admin)");
if (errno != EMFILE) end_server = TRUE;
}
break;
}
//
AdminSession* newsession = new AdminSession(new_sd);
sessionSockMap[new_sd] = newsession;
/**********************************************/
/* Add the new incoming connection to the */
/* master read set */
/**********************************************/
// printf(" New incoming connection (Admin) - %d\n", new_sd);
FD_SET(new_sd, &master_set);
if (new_sd > max_sd) max_sd = new_sd;
/**********************************************/
/* Loop back up and accept another incoming */
/* connection */
/**********************************************/
} while (new_sd != -1);
}
/****************************************************/
/* This is not the listening socket, therefore an */
/* existing connection must be readable */
/****************************************************/
else {
// printf(" Descriptor %d is readable\n", i);
close_conn = FALSE;
bool closed = sessionSockMap[i]->run();
if (closed) {
// printf(" Closing connection - %d\n", i);
if (sessionSockMap[i] != NULL) {
delete sessionSockMap[i];
sessionSockMap[i] = NULL;
}
close_conn = TRUE;
} else
close_conn = FALSE;
/*************************************************/
/* If the close_conn flag was turned on, we need */
/* to clean up this active connection. This */
/* clean up process includes removing the */
/* descriptor from the master set and */
/* determining the new maximum descriptor value */
/* based on the bits that are still turned on in */
/* the master set. */
/*************************************************/
if (close_conn) {
close(i);
FD_CLR(i, &master_set);
if (i == max_sd) {
while (FD_ISSET(max_sd, &master_set) == FALSE) max_sd -= 1;
}
}
} /* End of existing connection is readable */
} /* End of if (FD_ISSET(i, &working_set)) */
} /* End of loop through selectable descriptors */
} while (end_server == FALSE);
//
close(listensockfdSMPP);
close(listensockfdAdmin);
std::cout << "No longer listening on port " << portSMPP << std::endl;
return 0;
}
================================================
FILE: example/transceiver_with_auto_response/main.go
================================================
package main
import (
"fmt"
"log"
"strings"
"sync"
"time"
"github.com/linxGnu/gosmpp"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go sendingAndReceiveSMS(&wg)
wg.Wait()
}
func sendingAndReceiveSMS(wg *sync.WaitGroup) {
defer wg.Done()
auth := gosmpp.Auth{
SMSC: "localhost:2775",
SystemID: "169994",
Password: "EDXPJU",
SystemType: "",
}
trans, err := gosmpp.NewSession(
gosmpp.TRXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
EnquireLink: 5 * time.Second,
ReadTimeout: 10 * time.Second,
OnSubmitError: func(_ pdu.PDU, err error) {
log.Fatal("SubmitPDU error:", err)
},
OnReceivingError: func(err error) {
fmt.Println("Receiving PDU/Network error:", err)
},
OnRebindingError: func(err error) {
fmt.Println("Rebinding but error:", err)
},
OnPDU: handlePDU(),
OnClosed: func(state gosmpp.State) {
fmt.Println(state)
},
}, 5*time.Second)
if err != nil {
log.Fatal(err)
}
defer func() {
_ = trans.Close()
}()
// sending SMS(s)
for i := 0; i < 1800; i++ {
if err = trans.Transceiver().Submit(newSubmitSM()); err != nil {
fmt.Println(err)
}
time.Sleep(time.Second)
}
}
func handlePDU() func(pdu.PDU, bool) {
concatenated := map[uint8][]string{}
return func(p pdu.PDU, _ bool) {
switch pd := p.(type) {
case *pdu.SubmitSMResp:
fmt.Printf("SubmitSMResp:%+v\n", pd)
case *pdu.GenericNack:
fmt.Println("GenericNack Received")
case *pdu.EnquireLinkResp:
fmt.Println("EnquireLinkResp Received")
case *pdu.DataSM:
fmt.Printf("DataSM:%+v\n", pd)
case *pdu.DeliverSM:
fmt.Printf("DeliverSM:%+v\n", pd)
log.Println(pd.Message.GetMessage())
// region concatenated sms (sample code)
message, err := pd.Message.GetMessage()
if err != nil {
log.Fatal(err)
}
totalParts, sequence, reference, found := pd.Message.UDH().GetConcatInfo()
if found {
if _, ok := concatenated[reference]; !ok {
concatenated[reference] = make([]string, totalParts)
}
concatenated[reference][sequence-1] = message
}
if !found {
log.Println(message)
} else if parts, ok := concatenated[reference]; ok && isConcatenatedDone(parts, totalParts) {
log.Println(strings.Join(parts, ""))
delete(concatenated, reference)
}
// endregion
}
}
}
func newSubmitSM() *pdu.SubmitSM {
// build up submitSM
srcAddr := pdu.NewAddress()
srcAddr.SetTon(5)
srcAddr.SetNpi(0)
_ = srcAddr.SetAddress("00" + "522241")
destAddr := pdu.NewAddress()
destAddr.SetTon(1)
destAddr.SetNpi(1)
_ = destAddr.SetAddress("99" + "522241")
submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
submitSM.SourceAddr = srcAddr
submitSM.DestAddr = destAddr
_ = submitSM.Message.SetMessageWithEncoding("Đừng buồn thế dù ngoài kia vẫn mưa nghiễng rợi tý tỵ", data.UCS2)
submitSM.ProtocolID = 0
submitSM.RegisteredDelivery = 1
submitSM.ReplaceIfPresentFlag = 0
submitSM.EsmClass = 0
return submitSM
}
func isConcatenatedDone(parts []string, total byte) bool {
for _, part := range parts {
if part != "" {
total--
}
}
return total == 0
}
================================================
FILE: example/transceiver_with_manual_response/main.go
================================================
package main
import (
"fmt"
"log"
"sync"
"time"
"github.com/linxGnu/gosmpp"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go sendingAndReceiveSMS(&wg)
wg.Wait()
}
func sendingAndReceiveSMS(wg *sync.WaitGroup) {
defer wg.Done()
auth := gosmpp.Auth{
SMSC: "localhost:2775",
SystemID: "169994",
Password: "EDXPJU",
SystemType: "",
}
trans, err := gosmpp.NewSession(
gosmpp.TRXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
EnquireLink: 5 * time.Second,
ReadTimeout: 10 * time.Second,
OnSubmitError: func(_ pdu.PDU, err error) {
log.Fatal("SubmitPDU error:", err)
},
OnReceivingError: func(err error) {
fmt.Println("Receiving PDU/Network error:", err)
},
OnRebindingError: func(err error) {
fmt.Println("Rebinding but error:", err)
},
OnAllPDU: handlePDU(),
OnClosed: func(state gosmpp.State) {
fmt.Println(state)
},
}, 5*time.Second)
if err != nil {
log.Fatal(err)
}
defer func() {
_ = trans.Close()
}()
// sending SMS(s)
for i := 0; i < 30; i++ {
if err = trans.Transceiver().Submit(newSubmitSM()); err != nil {
fmt.Println(err)
}
time.Sleep(time.Second)
}
}
func handlePDU() func(pdu.PDU) (pdu.PDU, bool) {
return func(p pdu.PDU) (pdu.PDU, bool) {
switch pd := p.(type) {
case *pdu.Unbind:
fmt.Println("Unbind Received")
return pd.GetResponse(), true
case *pdu.UnbindResp:
fmt.Println("UnbindResp Received")
case *pdu.SubmitSMResp:
fmt.Println("SubmitSMResp Received")
case *pdu.GenericNack:
fmt.Println("GenericNack Received")
case *pdu.EnquireLinkResp:
fmt.Println("EnquireLinkResp Received")
case *pdu.EnquireLink:
fmt.Println("EnquireLink Received")
return pd.GetResponse(), false
case *pdu.DataSM:
fmt.Println("DataSM receiver")
return pd.GetResponse(), false
case *pdu.DeliverSM:
fmt.Println("DeliverSM receiver")
return pd.GetResponse(), false
}
return nil, false
}
}
func newSubmitSM() *pdu.SubmitSM {
// build up submitSM
srcAddr := pdu.NewAddress()
srcAddr.SetTon(5)
srcAddr.SetNpi(0)
_ = srcAddr.SetAddress("00" + "522241")
destAddr := pdu.NewAddress()
destAddr.SetTon(1)
destAddr.SetNpi(1)
_ = destAddr.SetAddress("99" + "522241")
submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
submitSM.SourceAddr = srcAddr
submitSM.DestAddr = destAddr
_ = submitSM.Message.SetMessageWithEncoding("Đừng buồn thế dù ngoài kia vẫn mưa nghiễng rợi tý tỵ", data.UCS2)
submitSM.ProtocolID = 0
submitSM.RegisteredDelivery = 1
submitSM.ReplaceIfPresentFlag = 0
submitSM.EsmClass = 0
return submitSM
}
================================================
FILE: example/transeiver_with_custom_store/CustomStore.go
================================================
package main
import (
"bytes"
"context"
"encoding/gob"
"errors"
"fmt"
"strconv"
"time"
"github.com/allegro/bigcache/v3"
"github.com/linxGnu/gosmpp/pdu"
"github.com/linxGnu/gosmpp"
)
// This is a just an example how to implement a custom store.
//
// Your implementation must be concurrency safe
//
// In this example we use bigcache https://github.com/allegro/bigcache
// Warning:
// - This is just an example and should be tested before using in production
// - We are serializing with gob, some field cannot be serialized for simplicity
// - We recommend you implement your own serialization/deserialization if you choose to use bigcache
type CustomStore struct {
store *bigcache.BigCache
}
func NewCustomStore() CustomStore {
cache, _ := bigcache.New(context.Background(), bigcache.DefaultConfig(30*time.Second))
return CustomStore{
store: cache,
}
}
func (s CustomStore) Set(ctx context.Context, request gosmpp.Request) error {
select {
case <-ctx.Done():
fmt.Println("Task cancelled")
return ctx.Err()
default:
b, _ := serialize(request)
err := s.store.Set(strconv.Itoa(int(request.PDU.GetSequenceNumber())), b)
if err != nil {
return err
}
return nil
}
}
func (s CustomStore) Get(ctx context.Context, sequenceNumber int32) (gosmpp.Request, bool) {
select {
case <-ctx.Done():
fmt.Println("Task cancelled")
return gosmpp.Request{}, false
default:
bRequest, err := s.store.Get(strconv.Itoa(int(sequenceNumber)))
if err != nil {
return gosmpp.Request{}, false
}
request, err := deserialize(bRequest)
if err != nil {
return gosmpp.Request{}, false
}
return request, true
}
}
func (s CustomStore) List(ctx context.Context) []gosmpp.Request {
var requests []gosmpp.Request
select {
case <-ctx.Done():
return requests
default:
it := s.store.Iterator()
for it.SetNext() {
value, err := it.Value()
if err != nil {
return requests
}
request, _ := deserialize(value.Value())
requests = append(requests, request)
}
return requests
}
}
func (s CustomStore) Delete(ctx context.Context, sequenceNumber int32) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
err := s.store.Delete(strconv.Itoa(int(sequenceNumber)))
if err != nil {
return err
}
return nil
}
}
func (s CustomStore) Clear(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
err := s.store.Reset()
if err != nil {
return err
}
return nil
}
}
func (s CustomStore) Length(ctx context.Context) (int, error) {
select {
case <-ctx.Done():
return 0, ctx.Err()
default:
return s.store.Len(), nil
}
}
func serialize(request gosmpp.Request) ([]byte, error) {
buf := pdu.NewBuffer(make([]byte, 0, 64))
request.PDU.Marshal(buf)
b := bytes.Buffer{}
e := gob.NewEncoder(&b)
err := e.Encode(requestGob{
Pdu: buf.Bytes(),
TimeSent: time.Time{},
})
if err != nil {
return b.Bytes()[:], errors.New("serialization failed")
}
return b.Bytes(), nil
}
func deserialize(bRequest []byte) (request gosmpp.Request, err error) {
r := requestGob{}
b := bytes.Buffer{}
_, err = b.Write(bRequest)
if err != nil {
return request, errors.New("deserialization failed")
}
d := gob.NewDecoder(&b)
err = d.Decode(&r)
if err != nil {
return request, errors.New("deserialization failed")
}
p, err := pdu.Parse(bytes.NewReader(r.Pdu))
if err != nil {
return gosmpp.Request{}, err
}
return gosmpp.Request{
PDU: p,
TimeSent: r.TimeSent,
}, nil
}
type requestGob struct {
Pdu []byte
TimeSent time.Time
}
================================================
FILE: example/transeiver_with_custom_store/main.go
================================================
package main
import (
"errors"
"fmt"
"log"
"sync"
"time"
"github.com/linxGnu/gosmpp"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go sendingAndReceiveSMS(&wg)
wg.Wait()
}
func sendingAndReceiveSMS(wg *sync.WaitGroup) {
defer wg.Done()
auth := gosmpp.Auth{
SMSC: "localhost:2775",
SystemID: "169994",
Password: "EDXPJU",
SystemType: "",
}
trans, err := gosmpp.NewSession(
gosmpp.TRXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
EnquireLink: 5 * time.Second,
ReadTimeout: 10 * time.Second,
OnSubmitError: func(p pdu.PDU, err error) {
if errors.Is(err, gosmpp.ErrWindowsFull) {
log.Println("SubmitPDU error:", err)
} else {
log.Fatal("SubmitPDU error:", err)
}
},
OnReceivingError: func(err error) {
fmt.Println("Receiving PDU/Network error:", err)
},
OnRebindingError: func(err error) {
fmt.Println("Rebinding but error:", err)
},
OnClosed: func(state gosmpp.State) {
fmt.Println(state)
},
WindowedRequestTracking: &gosmpp.WindowedRequestTracking{
OnReceivedPduRequest: handleReceivedPduRequest(),
OnExpectedPduResponse: handleExpectedPduResponse(),
OnExpiredPduRequest: handleExpirePduRequest(),
OnClosePduRequest: handleOnClosePduRequest(),
PduExpireTimeOut: 30 * time.Second,
ExpireCheckTimer: 10 * time.Second,
MaxWindowSize: 30,
EnableAutoRespond: false,
},
},
5*time.Second,
gosmpp.WithRequestStore(NewCustomStore()),
)
if err != nil {
log.Fatal(err)
}
defer func() {
_ = trans.Close()
}()
// sending SMS(s)
for i := 0; i < 60; i++ {
var size int
size, err = trans.GetWindowSize()
if err != nil {
fmt.Println("could not get window size: ", err)
} else {
fmt.Println("Current window size: ", size)
}
p := newSubmitSM()
if err = trans.Transceiver().Submit(p); err != nil {
fmt.Println(err)
}
fmt.Printf("Sent SubmitSM with id: %+v\n", p)
time.Sleep(1 * time.Second)
}
time.Sleep(1 * time.Second)
}
func handleExpirePduRequest() func(pdu.PDU) bool {
return func(p pdu.PDU) bool {
switch p.(type) {
case *pdu.SubmitSM:
fmt.Printf("Expired SubmitSM: %+v\n", p)
case *pdu.EnquireLink:
fmt.Printf("Expired EnquireLink: %+v\n", p)
return true // if the enquire_link expired, usually means the bind is stale
case *pdu.DataSM:
fmt.Printf("Expired DataSM: %+v\n", p)
default:
fmt.Printf("Expired PDU: %+v\n", p)
}
return false
}
}
func handleOnClosePduRequest() func(pdu.PDU) {
return func(p pdu.PDU) {
switch p.(type) {
case *pdu.Unbind:
fmt.Printf("OnClose Unbind: %+v\n", p)
case *pdu.SubmitSM:
fmt.Printf("OnClose SubmitSM: %+v\n", p)
case *pdu.EnquireLink:
fmt.Printf("OnClose EnquireLink: %+v\n", p)
case *pdu.DataSM:
fmt.Printf("OnClose DataSM: %+v\n", p)
}
}
}
func handleExpectedPduResponse() func(response gosmpp.Response) {
return func(response gosmpp.Response) {
switch response.PDU.(type) {
case *pdu.UnbindResp:
fmt.Println("UnbindResp Received")
fmt.Printf("OriginalSM id:%+v\n", response.OriginalRequest.PDU)
case *pdu.SubmitSMResp:
fmt.Printf("SubmitSMResp Received: %+v\n", response.PDU)
fmt.Printf("OriginalSM SubmitSM:%+v\n", response.OriginalRequest.PDU)
case *pdu.EnquireLinkResp:
fmt.Println("EnquireLinkResp Received")
fmt.Printf("Original EnquireLink:%+v\n", response.OriginalRequest.PDU)
}
}
}
func handleReceivedPduRequest() func(pdu.PDU) (pdu.PDU, bool) {
return func(p pdu.PDU) (pdu.PDU, bool) {
switch pd := p.(type) {
case *pdu.Unbind:
fmt.Println("Unbind Received")
return pd.GetResponse(), true
case *pdu.GenericNack:
fmt.Println("GenericNack Received")
case *pdu.EnquireLinkResp:
fmt.Println("EnquireLinkResp Received")
case *pdu.EnquireLink:
fmt.Println("EnquireLink Received")
return pd.GetResponse(), false
case *pdu.DataSM:
fmt.Println("DataSM Received")
return pd.GetResponse(), false
case *pdu.DeliverSM:
fmt.Println("DeliverSM Received")
return pd.GetResponse(), false
}
return nil, false
}
}
func newSubmitSM() *pdu.SubmitSM {
// build up submitSM
srcAddr := pdu.NewAddress()
srcAddr.SetTon(5)
srcAddr.SetNpi(0)
_ = srcAddr.SetAddress("00" + "522241")
destAddr := pdu.NewAddress()
destAddr.SetTon(1)
destAddr.SetNpi(1)
_ = destAddr.SetAddress("99" + "522241")
submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
submitSM.SourceAddr = srcAddr
submitSM.DestAddr = destAddr
_ = submitSM.Message.SetMessageWithEncoding("Đừng buồn thế dù ngoài kia vẫn mưa nghiễng rợi tý tỵ", data.UCS2)
submitSM.ProtocolID = 0
submitSM.RegisteredDelivery = 1
submitSM.ReplaceIfPresentFlag = 0
submitSM.EsmClass = 0
return submitSM
}
================================================
FILE: example/transeiver_with_request_window_and_custom_submitSm/CustomSubmitSM.go
================================================
package main
import (
"math/rand"
"strconv"
"github.com/linxGnu/gosmpp/pdu"
)
// CustomSubmitSM by embedding the PDU interface
// and adding messageId as an extra field to SubmitSM
type CustomSubmitSM struct {
pdu.PDU
messageId string
}
// newCustomSubmitSM returns CustomSubmitSM PDU.
// Using rand.Int to generate new id for each CustomSubmitSM
func newCustomSubmitSM() CustomSubmitSM {
return CustomSubmitSM{
PDU: newSubmitSM(),
messageId: strconv.Itoa(rand.Int()),
}
}
================================================
FILE: example/transeiver_with_request_window_and_custom_submitSm/main.go
================================================
package main
import (
"errors"
"fmt"
"log"
"sync"
"time"
"github.com/linxGnu/gosmpp"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go sendingAndReceiveSMS(&wg)
wg.Wait()
}
func sendingAndReceiveSMS(wg *sync.WaitGroup) {
defer wg.Done()
auth := gosmpp.Auth{
SMSC: "localhost:2775",
SystemID: "169994",
Password: "EDXPJU",
SystemType: "",
}
trans, err := gosmpp.NewSession(
gosmpp.TRXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
EnquireLink: 5 * time.Second,
ReadTimeout: 10 * time.Second,
OnSubmitError: func(p pdu.PDU, err error) {
if errors.Is(err, gosmpp.ErrWindowsFull) {
log.Println("SubmitPDU error: ", err)
} else {
log.Fatal("SubmitPDU error: ", err)
}
},
OnReceivingError: func(err error) {
fmt.Println("Receiving PDU/Network error: ", err)
},
OnRebindingError: func(err error) {
fmt.Println("Rebinding but error: ", err)
},
OnClosed: func(state gosmpp.State) {
fmt.Println("Bind has been closed: ", state.String())
},
WindowedRequestTracking: &gosmpp.WindowedRequestTracking{
OnReceivedPduRequest: handleReceivedPduRequest(),
OnExpectedPduResponse: handleExpectedPduResponse(),
OnExpiredPduRequest: handleExpirePduRequest(),
OnClosePduRequest: handleOnClosePduRequest(),
PduExpireTimeOut: 30 * time.Second,
ExpireCheckTimer: 10 * time.Second,
MaxWindowSize: 30,
StoreAccessTimeOut: 1 * time.Second,
EnableAutoRespond: false,
},
}, 5*time.Second)
if err != nil {
log.Fatal(err)
}
defer func() {
_ = trans.Close()
}()
// sending SMS(s)
for i := 0; i < 60; i++ {
var size int
size, err = trans.GetWindowSize()
if err != nil {
fmt.Println("could not get window size: ", err)
} else {
fmt.Println("Current window size: ", size)
}
p := newCustomSubmitSM()
if err = trans.Transceiver().Submit(p); err != nil {
fmt.Println(err)
}
fmt.Printf("Sent CustomSubmitSM with id: %+v\n", p.messageId)
time.Sleep(1 * time.Second)
}
time.Sleep(1 * time.Second)
}
func handleExpirePduRequest() func(pdu.PDU) bool {
return func(p pdu.PDU) bool {
switch p.(type) {
case *pdu.Unbind:
fmt.Printf("Expired Unbind :%+v\n", p)
fmt.Println("Unbind Expired")
case *pdu.SubmitSM:
fmt.Printf("Expired SubmitSM :%+v\n", p)
case *pdu.EnquireLink:
fmt.Printf("Expired EnquireLink:%+v\n", p)
return true // if the enquire_link expired, usually means the bind is stale
case *pdu.DataSM:
fmt.Printf("Expired DataSM:%+v\n", p)
}
return false
}
}
func handleOnClosePduRequest() func(pdu.PDU) {
return func(p pdu.PDU) {
switch p.(type) {
case *pdu.Unbind:
fmt.Printf("OnClose Unbind:%+v\n", p)
case *pdu.SubmitSM:
fmt.Printf("OnClose SubmitSM:%+v\n", p)
case *pdu.EnquireLink:
fmt.Printf("OnClose EnquireLink:%+v\n", p)
case *pdu.DataSM:
fmt.Printf("OnClose DataSM:%+v\n", p)
}
}
}
func handleExpectedPduResponse() func(response gosmpp.Response) {
return func(response gosmpp.Response) {
switch response.PDU.(type) {
case *pdu.UnbindResp:
fmt.Println("UnbindResp Received")
fmt.Printf("OriginalSM id:%+v\n", response.OriginalRequest.PDU)
case *pdu.SubmitSMResp:
fmt.Printf("SubmitSMResp Received: %+v\n", response.PDU)
fmt.Printf("OriginalSM SubmitSM:%+v\n", response.OriginalRequest.PDU)
case *pdu.EnquireLinkResp:
fmt.Println("EnquireLinkResp Received")
fmt.Printf("Original EnquireLink:%+v\n", response.OriginalRequest.PDU)
}
}
}
func handleReceivedPduRequest() func(pdu.PDU) (pdu.PDU, bool) {
return func(p pdu.PDU) (pdu.PDU, bool) {
switch pd := p.(type) {
case *pdu.Unbind:
fmt.Println("Unbind Received")
return pd.GetResponse(), true
case *pdu.GenericNack:
fmt.Println("GenericNack Received")
case *pdu.EnquireLinkResp:
fmt.Println("EnquireLinkResp Received")
case *pdu.EnquireLink:
fmt.Println("EnquireLink Received")
return pd.GetResponse(), false
case *pdu.DataSM:
fmt.Println("DataSM Received")
return pd.GetResponse(), false
case *pdu.DeliverSM:
fmt.Println("DeliverSM Received")
return pd.GetResponse(), false
}
return nil, false
}
}
func newSubmitSM() *pdu.SubmitSM {
// build up submitSM
srcAddr := pdu.NewAddress()
srcAddr.SetTon(5)
srcAddr.SetNpi(0)
_ = srcAddr.SetAddress("00" + "522241")
destAddr := pdu.NewAddress()
destAddr.SetTon(1)
destAddr.SetNpi(1)
_ = destAddr.SetAddress("99" + "522241")
submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
submitSM.SourceAddr = srcAddr
submitSM.DestAddr = destAddr
_ = submitSM.Message.SetMessageWithEncoding("Đừng buồn thế dù ngoài kia vẫn mưa nghiễng rợi tý tỵ", data.UCS2)
submitSM.ProtocolID = 0
submitSM.RegisteredDelivery = 1
submitSM.ReplaceIfPresentFlag = 0
submitSM.EsmClass = 0
return submitSM
}
================================================
FILE: go.mod
================================================
module github.com/linxGnu/gosmpp
go 1.24.0
require (
github.com/allegro/bigcache/v3 v3.1.0
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/stretchr/testify v1.11.1
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b
golang.org/x/text v0.33.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
================================================
FILE: go.sum
================================================
github.com/allegro/bigcache/v3 v3.1.0 h1:H2Vp8VOvxcrB91o86fUSVJFqeuz8kpyyB02eH3bSzwk=
github.com/allegro/bigcache/v3 v3.1.0/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
================================================
FILE: pdu/Address.go
================================================
package pdu
import (
"fmt"
"github.com/linxGnu/gosmpp/data"
)
// Address smpp address of src and dst.
type Address struct {
ton byte
npi byte
address string
}
// NewAddress returns new address with default max length.
func NewAddress() Address {
return Address{ton: data.GetDefaultTon(), npi: data.GetDefaultNpi()}
}
// NewAddressWithAddr returns new address.
func NewAddressWithAddr(addr string) (a Address, err error) {
a = NewAddress()
err = a.SetAddress(addr)
return
}
// NewAddressWithTonNpi returns new address with ton, npi.
func NewAddressWithTonNpi(ton, npi byte) Address {
return Address{ton: ton, npi: npi}
}
// NewAddressWithTonNpiAddr returns new address with ton, npi, addr string.
func NewAddressWithTonNpiAddr(ton, npi byte, addr string) (a Address, err error) {
a = NewAddressWithTonNpi(ton, npi)
err = a.SetAddress(addr)
return
}
// Unmarshal from buffer.
func (c *Address) Unmarshal(b *ByteBuffer) (err error) {
if c.ton, err = b.ReadByte(); err == nil {
if c.npi, err = b.ReadByte(); err == nil {
c.address, err = b.ReadCString()
}
}
return
}
// Marshal to buffer.
func (c *Address) Marshal(b *ByteBuffer) {
b.Grow(3 + len(c.address))
_ = b.WriteByte(c.ton)
_ = b.WriteByte(c.npi)
_ = b.WriteCString(c.address)
}
// SetTon sets ton.
func (c *Address) SetTon(ton byte) {
c.ton = ton
}
// SetNpi sets npi.
func (c *Address) SetNpi(npi byte) {
c.npi = npi
}
// SetAddress sets address.
func (c *Address) SetAddress(addr string) (err error) {
if len(addr) > data.SM_ADDR_LEN {
err = fmt.Errorf("Address len exceed limit. (%d > %d)", len(addr), data.SM_ADDR_LEN)
} else {
c.address = addr
}
return
}
// Ton returns assigned ton.
func (c Address) Ton() byte {
return c.ton
}
// Npi returns assigned npi.
func (c Address) Npi() byte {
return c.npi
}
// Address returns assigned address (in string).
func (c Address) Address() string {
return c.address
}
// String implement stringer interface
func (c Address) String() string {
return c.address
}
================================================
FILE: pdu/AddressRange.go
================================================
package pdu
import "github.com/linxGnu/gosmpp/data"
// AddressRange smpp address range of src and dst.
type AddressRange struct {
Ton byte
Npi byte
AddressRange string
}
// NewAddressRange create new AddressRange with default max length.
func NewAddressRange() AddressRange {
return AddressRange{Ton: data.GetDefaultTon(), Npi: data.GetDefaultNpi()}
}
// NewAddressRangeWithAddr create new AddressRange.
func NewAddressRangeWithAddr(addr string) AddressRange {
gitextract_d637zljl/ ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ └── go.yml ├── .gitignore ├── .golangci.yml ├── LICENSE ├── README.md ├── connect.go ├── connect_test.go ├── connection.go ├── connection_test.go ├── data/ │ ├── 7bit.go │ ├── 7bit_test.go │ ├── codings.go │ ├── codings_test.go │ ├── header_data.go │ ├── header_data_string.go │ ├── other_codings.go │ ├── pkg.go │ ├── pkg_test.go │ ├── utils.go │ └── utils_test.go ├── errors/ │ ├── pkg.go │ └── pkg_test.go ├── example/ │ ├── smsc_simulator/ │ │ └── smsc.cpp │ ├── transceiver_with_auto_response/ │ │ └── main.go │ ├── transceiver_with_manual_response/ │ │ └── main.go │ ├── transeiver_with_custom_store/ │ │ ├── CustomStore.go │ │ └── main.go │ └── transeiver_with_request_window_and_custom_submitSm/ │ ├── CustomSubmitSM.go │ └── main.go ├── go.mod ├── go.sum ├── pdu/ │ ├── Address.go │ ├── AddressRange.go │ ├── AddressRange_test.go │ ├── Address_test.go │ ├── AlertNotification.go │ ├── AlertNotification_test.go │ ├── BindRequest.go │ ├── BindRequest_test.go │ ├── BindResponse.go │ ├── BindResponse_test.go │ ├── Buffer.go │ ├── Buffer_test.go │ ├── CancelSM.go │ ├── CancelSMResp.go │ ├── CancelSMResp_test.go │ ├── CancelSM_test.go │ ├── DataSM.go │ ├── DataSMResp.go │ ├── DataSMResp_test.go │ ├── DataSM_test.go │ ├── DeliverSM.go │ ├── DeliverSMResp.go │ ├── DeliverSMResp_test.go │ ├── DeliverSM_test.go │ ├── DestinationAddress.go │ ├── DestinationAddress_test.go │ ├── DistributionList.go │ ├── DistributionList_test.go │ ├── EnquireLink.go │ ├── EnquireLinkResp.go │ ├── EnquireLinkResp_test.go │ ├── EnquireLink_test.go │ ├── GenericNack.go │ ├── GenericNack_test.go │ ├── Outbind.go │ ├── Outbind_test.go │ ├── PDU.go │ ├── PDUFactory.go │ ├── PDUFactory_test.go │ ├── PDUHeader.go │ ├── PDUHeader_test.go │ ├── PDU_test.go │ ├── QuerySM.go │ ├── QuerySMResp.go │ ├── QuerySMResp_test.go │ ├── QuerySM_test.go │ ├── ReplaceSM.go │ ├── ReplaceSMResp.go │ ├── ReplaceSMResp_test.go │ ├── ReplaceSM_test.go │ ├── ShortMessage.go │ ├── ShortMessage_test.go │ ├── SubmitMulti.go │ ├── SubmitMultiResp.go │ ├── SubmitMultiResp_test.go │ ├── SubmitMulti_test.go │ ├── SubmitSM.go │ ├── SubmitSMResp.go │ ├── SubmitSMResp_test.go │ ├── SubmitSM_test.go │ ├── TLV.go │ ├── UDH.go │ ├── UDH_test.go │ ├── Unbind.go │ ├── UnbindResp.go │ ├── UnbindResp_test.go │ ├── Unbind_test.go │ ├── UnsuccessSME.go │ ├── UnsuccessSME_test.go │ └── helper_test.go ├── pkg.go ├── receivable.go ├── receivable_test.go ├── request_store.go ├── session.go ├── session_test.go ├── state.go ├── state_test.go ├── transceivable.go ├── transceivable_test.go ├── transmittable.go ├── transmittable_test.go └── types.go
SYMBOL INDEX (1106 symbols across 107 files)
FILE: connect.go
type Dialer (line 19) | type Dialer
type Auth (line 22) | type Auth struct
type BindError (line 30) | type BindError struct
method Error (line 34) | func (err BindError) Error() string {
function newBindRequest (line 38) | func newBindRequest(s Auth, bindingType pdu.BindingType, addressRange pd...
type Connector (line 48) | type Connector interface
type connector (line 53) | type connector struct
method GetBindType (line 60) | func (c *connector) GetBindType() pdu.BindingType {
method Connect (line 64) | func (c *connector) Connect() (conn *Connection, err error) {
function connect (line 69) | func connect(dialer Dialer, addr string, bindReq *pdu.BindRequest) (c *C...
function TXConnector (line 114) | func TXConnector(dialer Dialer, auth Auth) Connector {
function RXConnector (line 123) | func RXConnector(dialer Dialer, auth Auth, opts ...connectorOption) Conn...
function TRXConnector (line 136) | func TRXConnector(dialer Dialer, auth Auth, opts ...connectorOption) Con...
type connectorOption (line 148) | type connectorOption
function WithAddressRange (line 150) | func WithAddressRange(addressRange pdu.AddressRange) connectorOption {
FILE: connect_test.go
constant smscAddr (line 18) | smscAddr = "127.0.0.1:2775"
constant mess (line 19) | mess = "Thử nghiệm: chuẩn bị nế mễ"
function nextAuth (line 22) | func nextAuth() Auth {
function TestBindingSMSC (line 32) | func TestBindingSMSC(t *testing.T) {
function TestBindingSMSC_Error (line 64) | func TestBindingSMSC_Error(t *testing.T) {
function TestBindingType (line 85) | func TestBindingType(t *testing.T) {
FILE: connection.go
type Connection (line 12) | type Connection struct
method Read (line 30) | func (c *Connection) Read(b []byte) (n int, err error) {
method Write (line 38) | func (c *Connection) Write(b []byte) (n int, err error) {
method WritePDU (line 44) | func (c *Connection) WritePDU(p pdu.PDU) (n int, err error) {
method Close (line 53) | func (c *Connection) Close() error {
method LocalAddr (line 58) | func (c *Connection) LocalAddr() net.Addr {
method RemoteAddr (line 63) | func (c *Connection) RemoteAddr() net.Addr {
method SetDeadline (line 89) | func (c *Connection) SetDeadline(t time.Time) error {
method SetReadDeadline (line 96) | func (c *Connection) SetReadDeadline(t time.Time) error {
method SetReadTimeout (line 101) | func (c *Connection) SetReadTimeout(t time.Duration) error {
method SetWriteDeadline (line 110) | func (c *Connection) SetWriteDeadline(t time.Time) error {
method SetWriteTimeout (line 115) | func (c *Connection) SetWriteTimeout(t time.Duration) error {
function NewConnection (line 19) | func NewConnection(conn net.Conn) (c *Connection) {
FILE: connection_test.go
function TestConnection (line 11) | func TestConnection(t *testing.T) {
FILE: data/7bit.go
constant escapeSequence (line 27) | escapeSequence = 0x1B
function ValidateGSM7String (line 73) | func ValidateGSM7String(text string) []rune {
function ValidateGSM7Buffer (line 86) | func ValidateGSM7Buffer(buffer []byte) []byte {
function GetEscapeChars (line 110) | func GetEscapeChars(runeText []rune) []rune {
function IsEscapeChar (line 121) | func IsEscapeChar(c rune) bool {
function GSM7 (line 130) | func GSM7(packed bool) encoding.Encoding {
type gsm7Encoding (line 134) | type gsm7Encoding struct
method NewDecoder (line 138) | func (g gsm7Encoding) NewDecoder() *encoding.Decoder {
method NewEncoder (line 144) | func (g gsm7Encoding) NewEncoder() *encoding.Encoder {
method String (line 150) | func (g gsm7Encoding) String() string {
type gsm7Decoder (line 157) | type gsm7Decoder struct
method Reset (line 161) | func (g *gsm7Decoder) Reset() { /* not needed */ }
method Transform (line 225) | func (g *gsm7Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nS...
function unpack (line 163) | func unpack(src []byte, packed bool) (septets []byte) {
type gsm7Encoder (line 265) | type gsm7Encoder struct
method Reset (line 269) | func (g *gsm7Encoder) Reset() {
method Transform (line 345) | func (g *gsm7Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nS...
function pack (line 273) | func pack(dst []byte, septets []byte) (nDst int) {
FILE: data/7bit_test.go
function TestGSM7EncodingString (line 96) | func TestGSM7EncodingString(t *testing.T) {
function TestValidateGSM7String (line 113) | func TestValidateGSM7String(t *testing.T) {
function TestValidateGSM7Buffer (line 122) | func TestValidateGSM7Buffer(t *testing.T) {
function TestPackedEncoder (line 131) | func TestPackedEncoder(t *testing.T) {
function TestUnpackedEncoder (line 144) | func TestUnpackedEncoder(t *testing.T) {
function TestPackedDecoder (line 157) | func TestPackedDecoder(t *testing.T) {
function TestUnpackedDecoder (line 170) | func TestUnpackedDecoder(t *testing.T) {
function TestInvalidCharacter (line 183) | func TestInvalidCharacter(t *testing.T) {
function TestInvalidByte (line 196) | func TestInvalidByte(t *testing.T) {
FILE: data/codings.go
constant GSM7BITCoding (line 11) | GSM7BITCoding byte = 0x00
constant ASCIICoding (line 13) | ASCIICoding byte = 0x01
constant BINARY8BIT1Coding (line 15) | BINARY8BIT1Coding byte = 0x02
constant LATIN1Coding (line 17) | LATIN1Coding byte = 0x03
constant BINARY8BIT2Coding (line 19) | BINARY8BIT2Coding byte = 0x04
constant CYRILLICCoding (line 21) | CYRILLICCoding byte = 0x06
constant HEBREWCoding (line 23) | HEBREWCoding byte = 0x07
constant UCS2Coding (line 25) | UCS2Coding byte = 0x08
type EncDec (line 29) | type EncDec interface
type Encoding (line 35) | type Encoding interface
function encode (line 40) | func encode(str string, encoder *encoding.Encoder) ([]byte, error) {
function decode (line 44) | func decode(data []byte, decoder *encoding.Decoder) (st string, err erro...
type CustomEncoding (line 53) | type CustomEncoding struct
method Encode (line 67) | func (c *CustomEncoding) Encode(str string) ([]byte, error) {
method Decode (line 72) | func (c *CustomEncoding) Decode(data []byte) (string, error) {
method DataCoding (line 77) | func (c *CustomEncoding) DataCoding() byte {
function NewCustomEncoding (line 59) | func NewCustomEncoding(coding byte, encDec EncDec) Encoding {
type gsm7bit (line 81) | type gsm7bit struct
method Encode (line 85) | func (c *gsm7bit) Encode(str string) ([]byte, error) {
method Decode (line 89) | func (c *gsm7bit) Decode(data []byte) (string, error) {
method DataCoding (line 93) | func (c *gsm7bit) DataCoding() byte { return GSM7BITCoding }
method ShouldSplit (line 95) | func (c *gsm7bit) ShouldSplit(text string, octetLimit uint) (shouldSpl...
method EncodeSplit (line 103) | func (c *gsm7bit) EncodeSplit(text string, octetLimit uint) (allSeg []...
type gsm7bitPacked (line 127) | type gsm7bitPacked struct
method Encode (line 130) | func (c *gsm7bitPacked) Encode(str string) ([]byte, error) {
method Decode (line 134) | func (c *gsm7bitPacked) Decode(data []byte) (string, error) {
method DataCoding (line 138) | func (c *gsm7bitPacked) DataCoding() byte { return GSM7BITCoding }
method ShouldSplit (line 140) | func (c *gsm7bitPacked) ShouldSplit(text string, octetLimit uint) (sho...
method GetSeptetCount (line 151) | func (c *gsm7bitPacked) GetSeptetCount(runeSlice []rune) int {
method EncodeSplit (line 158) | func (c *gsm7bitPacked) EncodeSplit(text string, octetLimit uint) (all...
function determineTo (line 195) | func determineTo(from int, to int, lim int, runeSlice []rune) int {
function shiftBitsLeftOne (line 222) | func shiftBitsLeftOne(input []byte, includeLSB bool) []byte {
type ascii (line 239) | type ascii struct
method Encode (line 241) | func (*ascii) Encode(str string) ([]byte, error) {
method Decode (line 245) | func (*ascii) Decode(data []byte) (string, error) {
method DataCoding (line 249) | func (*ascii) DataCoding() byte { return ASCIICoding }
type iso88591 (line 251) | type iso88591 struct
method Encode (line 253) | func (*iso88591) Encode(str string) ([]byte, error) {
method Decode (line 257) | func (*iso88591) Decode(data []byte) (string, error) {
method DataCoding (line 261) | func (*iso88591) DataCoding() byte { return LATIN1Coding }
type binary8bit1 (line 263) | type binary8bit1 struct
method Encode (line 265) | func (*binary8bit1) Encode(_ string) ([]byte, error) {
method Decode (line 269) | func (*binary8bit1) Decode(_ []byte) (string, error) {
method DataCoding (line 273) | func (*binary8bit1) DataCoding() byte { return BINARY8BIT1Coding }
type binary8bit2 (line 275) | type binary8bit2 struct
method Encode (line 277) | func (*binary8bit2) Encode(_ string) ([]byte, error) {
method Decode (line 281) | func (*binary8bit2) Decode(_ []byte) (string, error) {
method DataCoding (line 285) | func (*binary8bit2) DataCoding() byte { return BINARY8BIT2Coding }
type iso88595 (line 287) | type iso88595 struct
method Encode (line 289) | func (*iso88595) Encode(str string) ([]byte, error) {
method Decode (line 293) | func (*iso88595) Decode(data []byte) (string, error) {
method DataCoding (line 297) | func (*iso88595) DataCoding() byte { return CYRILLICCoding }
type iso88598 (line 299) | type iso88598 struct
method Encode (line 301) | func (*iso88598) Encode(str string) ([]byte, error) {
method Decode (line 305) | func (*iso88598) Decode(data []byte) (string, error) {
method DataCoding (line 309) | func (*iso88598) DataCoding() byte { return HEBREWCoding }
type ucs2 (line 311) | type ucs2 struct
method Encode (line 313) | func (*ucs2) Encode(str string) ([]byte, error) {
method Decode (line 318) | func (*ucs2) Decode(data []byte) (string, error) {
method ShouldSplit (line 323) | func (*ucs2) ShouldSplit(text string, octetLimit uint) (shouldSplit bo...
method EncodeSplit (line 328) | func (c *ucs2) EncodeSplit(text string, octetLimit uint) (allSeg [][]b...
method DataCoding (line 356) | func (*ucs2) DataCoding() byte { return UCS2Coding }
function FromDataCoding (line 401) | func FromDataCoding(code byte) (enc Encoding) {
type Splitter (line 412) | type Splitter interface
FILE: data/codings_test.go
function fromHex (line 11) | func fromHex(h string) (v []byte) {
function testEncoding (line 20) | func testEncoding(t *testing.T, enc EncDec, original, expected string) {
function testEncodingSplit (line 30) | func testEncodingSplit(t *testing.T, enc EncDec, octetLim uint, original...
function shiftBitsOneRight (line 51) | func shiftBitsOneRight(input []byte) []byte {
function TestCoding (line 66) | func TestCoding(t *testing.T) {
function TestGSM7Bit (line 76) | func TestGSM7Bit(t *testing.T) {
function TestShouldSplit (line 81) | func TestShouldSplit(t *testing.T) {
function TestSplit (line 134) | func TestSplit(t *testing.T) {
function TestSplit_GSM7BITPACKED (line 193) | func TestSplit_GSM7BITPACKED(t *testing.T) {
function TestAscii (line 320) | func TestAscii(t *testing.T) {
function TestUCS2 (line 325) | func TestUCS2(t *testing.T) {
function TestLatin1 (line 330) | func TestLatin1(t *testing.T) {
function TestCYRILLIC (line 335) | func TestCYRILLIC(t *testing.T) {
function TestHebrew (line 340) | func TestHebrew(t *testing.T) {
function TestOtherCodings (line 345) | func TestOtherCodings(t *testing.T) {
type noOpEncDec (line 352) | type noOpEncDec struct
method Encode (line 354) | func (*noOpEncDec) Encode(str string) ([]byte, error) {
method Decode (line 358) | func (*noOpEncDec) Decode(data []byte) (string, error) {
function TestCustomEncoding (line 362) | func TestCustomEncoding(t *testing.T) {
FILE: data/header_data.go
type CommandStatusType (line 6) | type CommandStatusType
type CommandIDType (line 9) | type CommandIDType
constant GENERIC_NACK (line 14) | GENERIC_NACK = CommandIDType(-2147483648)
constant BIND_RECEIVER (line 15) | BIND_RECEIVER = CommandIDType(0x00000001)
constant BIND_RECEIVER_RESP (line 16) | BIND_RECEIVER_RESP = CommandIDType(-2147483647)
constant BIND_TRANSMITTER (line 17) | BIND_TRANSMITTER = CommandIDType(0x00000002)
constant BIND_TRANSMITTER_RESP (line 18) | BIND_TRANSMITTER_RESP = CommandIDType(-2147483646)
constant QUERY_SM (line 19) | QUERY_SM = CommandIDType(0x00000003)
constant QUERY_SM_RESP (line 20) | QUERY_SM_RESP = CommandIDType(-2147483645)
constant SUBMIT_SM (line 21) | SUBMIT_SM = CommandIDType(0x00000004)
constant SUBMIT_SM_RESP (line 22) | SUBMIT_SM_RESP = CommandIDType(-2147483644)
constant DELIVER_SM (line 23) | DELIVER_SM = CommandIDType(0x00000005)
constant DELIVER_SM_RESP (line 24) | DELIVER_SM_RESP = CommandIDType(-2147483643)
constant UNBIND (line 25) | UNBIND = CommandIDType(0x00000006)
constant UNBIND_RESP (line 26) | UNBIND_RESP = CommandIDType(-2147483642)
constant REPLACE_SM (line 27) | REPLACE_SM = CommandIDType(0x00000007)
constant REPLACE_SM_RESP (line 28) | REPLACE_SM_RESP = CommandIDType(-2147483641)
constant CANCEL_SM (line 29) | CANCEL_SM = CommandIDType(0x00000008)
constant CANCEL_SM_RESP (line 30) | CANCEL_SM_RESP = CommandIDType(-2147483640)
constant BIND_TRANSCEIVER (line 31) | BIND_TRANSCEIVER = CommandIDType(0x00000009)
constant BIND_TRANSCEIVER_RESP (line 32) | BIND_TRANSCEIVER_RESP = CommandIDType(-2147483639)
constant OUTBIND (line 33) | OUTBIND = CommandIDType(0x0000000B)
constant ENQUIRE_LINK (line 34) | ENQUIRE_LINK = CommandIDType(0x00000015)
constant ENQUIRE_LINK_RESP (line 35) | ENQUIRE_LINK_RESP = CommandIDType(-2147483627)
constant SUBMIT_MULTI (line 36) | SUBMIT_MULTI = CommandIDType(0x00000021)
constant SUBMIT_MULTI_RESP (line 37) | SUBMIT_MULTI_RESP = CommandIDType(-2147483615)
constant ALERT_NOTIFICATION (line 38) | ALERT_NOTIFICATION = CommandIDType(0x00000102)
constant DATA_SM (line 39) | DATA_SM = CommandIDType(0x00000103)
constant DATA_SM_RESP (line 40) | DATA_SM_RESP = CommandIDType(-2147483389)
constant ESME_ROK (line 46) | ESME_ROK = CommandStatusType(0x00000000)
constant ESME_RINVMSGLEN (line 47) | ESME_RINVMSGLEN = CommandStatusType(0x00000001)
constant ESME_RINVCMDLEN (line 48) | ESME_RINVCMDLEN = CommandStatusType(0x00000002)
constant ESME_RINVCMDID (line 49) | ESME_RINVCMDID = CommandStatusType(0x00000003)
constant ESME_RINVBNDSTS (line 50) | ESME_RINVBNDSTS = CommandStatusType(0x00000004)
constant ESME_RALYBND (line 51) | ESME_RALYBND = CommandStatusType(0x00000005)
constant ESME_RINVPRTFLG (line 52) | ESME_RINVPRTFLG = CommandStatusType(0x00000006)
constant ESME_RINVREGDLVFLG (line 53) | ESME_RINVREGDLVFLG = CommandStatusType(0x00000007)
constant ESME_RSYSERR (line 54) | ESME_RSYSERR = CommandStatusType(0x00000008)
constant ESME_RINVSRCADR (line 55) | ESME_RINVSRCADR = CommandStatusType(0x0000000A)
constant ESME_RINVDSTADR (line 56) | ESME_RINVDSTADR = CommandStatusType(0x0000000B)
constant ESME_RINVMSGID (line 57) | ESME_RINVMSGID = CommandStatusType(0x0000000C)
constant ESME_RBINDFAIL (line 58) | ESME_RBINDFAIL = CommandStatusType(0x0000000D)
constant ESME_RINVPASWD (line 59) | ESME_RINVPASWD = CommandStatusType(0x0000000E)
constant ESME_RINVSYSID (line 60) | ESME_RINVSYSID = CommandStatusType(0x0000000F)
constant ESME_RCANCELFAIL (line 61) | ESME_RCANCELFAIL = CommandStatusType(0x00000011)
constant ESME_RREPLACEFAIL (line 62) | ESME_RREPLACEFAIL = CommandStatusType(0x00000013)
constant ESME_RMSGQFUL (line 63) | ESME_RMSGQFUL = CommandStatusType(0x00000014)
constant ESME_RINVSERTYP (line 64) | ESME_RINVSERTYP = CommandStatusType(0x00000015)
constant ESME_RADDCUSTFAIL (line 66) | ESME_RADDCUSTFAIL = CommandStatusType(0x00000019)
constant ESME_RDELCUSTFAIL (line 67) | ESME_RDELCUSTFAIL = CommandStatusType(0x0000001A)
constant ESME_RMODCUSTFAIL (line 68) | ESME_RMODCUSTFAIL = CommandStatusType(0x0000001B)
constant ESME_RENQCUSTFAIL (line 69) | ESME_RENQCUSTFAIL = CommandStatusType(0x0000001C)
constant ESME_RINVCUSTID (line 70) | ESME_RINVCUSTID = CommandStatusType(0x0000001D)
constant ESME_RINVCUSTNAME (line 71) | ESME_RINVCUSTNAME = CommandStatusType(0x0000001F)
constant ESME_RINVCUSTADR (line 72) | ESME_RINVCUSTADR = CommandStatusType(0x00000021)
constant ESME_RINVADR (line 73) | ESME_RINVADR = CommandStatusType(0x00000022)
constant ESME_RCUSTEXIST (line 74) | ESME_RCUSTEXIST = CommandStatusType(0x00000023)
constant ESME_RCUSTNOTEXIST (line 75) | ESME_RCUSTNOTEXIST = CommandStatusType(0x00000024)
constant ESME_RADDDLFAIL (line 76) | ESME_RADDDLFAIL = CommandStatusType(0x00000026)
constant ESME_RMODDLFAIL (line 77) | ESME_RMODDLFAIL = CommandStatusType(0x00000027)
constant ESME_RDELDLFAIL (line 78) | ESME_RDELDLFAIL = CommandStatusType(0x00000028)
constant ESME_RVIEWDLFAIL (line 79) | ESME_RVIEWDLFAIL = CommandStatusType(0x00000029)
constant ESME_RLISTDLSFAIL (line 80) | ESME_RLISTDLSFAIL = CommandStatusType(0x00000030)
constant ESME_RPARAMRETFAIL (line 81) | ESME_RPARAMRETFAIL = CommandStatusType(0x00000031)
constant ESME_RINVPARAM (line 82) | ESME_RINVPARAM = CommandStatusType(0x00000032)
constant ESME_RINVNUMDESTS (line 84) | ESME_RINVNUMDESTS = CommandStatusType(0x00000033)
constant ESME_RINVDLNAME (line 85) | ESME_RINVDLNAME = CommandStatusType(0x00000034)
constant ESME_RINVDLMEMBDESC (line 87) | ESME_RINVDLMEMBDESC = CommandStatusType(0x00000035)
constant ESME_RINVDLMEMBTYP (line 88) | ESME_RINVDLMEMBTYP = CommandStatusType(0x00000038)
constant ESME_RINVDLMODOPT (line 89) | ESME_RINVDLMODOPT = CommandStatusType(0x00000039)
constant ESME_RINVDESTFLAG (line 91) | ESME_RINVDESTFLAG = CommandStatusType(0x00000040)
constant ESME_RINVSUBREP (line 92) | ESME_RINVSUBREP = CommandStatusType(0x00000042)
constant ESME_RINVESMCLASS (line 93) | ESME_RINVESMCLASS = CommandStatusType(0x00000043)
constant ESME_RCNTSUBDL (line 94) | ESME_RCNTSUBDL = CommandStatusType(0x00000044)
constant ESME_RSUBMITFAIL (line 95) | ESME_RSUBMITFAIL = CommandStatusType(0x00000045)
constant ESME_RINVSRCTON (line 96) | ESME_RINVSRCTON = CommandStatusType(0x00000048)
constant ESME_RINVSRCNPI (line 97) | ESME_RINVSRCNPI = CommandStatusType(0x00000049)
constant ESME_RINVDSTTON (line 98) | ESME_RINVDSTTON = CommandStatusType(0x00000050)
constant ESME_RINVDSTNPI (line 99) | ESME_RINVDSTNPI = CommandStatusType(0x00000051)
constant ESME_RINVSYSTYP (line 100) | ESME_RINVSYSTYP = CommandStatusType(0x00000053)
constant ESME_RINVREPFLAG (line 101) | ESME_RINVREPFLAG = CommandStatusType(0x00000054)
constant ESME_RINVNUMMSGS (line 102) | ESME_RINVNUMMSGS = CommandStatusType(0x00000055)
constant ESME_RTHROTTLED (line 103) | ESME_RTHROTTLED = CommandStatusType(0x00000058)
constant ESME_RPROVNOTALLWD (line 105) | ESME_RPROVNOTALLWD = CommandStatusType(0x00000059)
constant ESME_RINVSCHED (line 107) | ESME_RINVSCHED = CommandStatusType(0x00000061)
constant ESME_RINVEXPIRY (line 108) | ESME_RINVEXPIRY = CommandStatusType(0x00000062)
constant ESME_RINVDFTMSGID (line 109) | ESME_RINVDFTMSGID = CommandStatusType(0x00000063)
constant ESME_RX_T_APPN (line 110) | ESME_RX_T_APPN = CommandStatusType(0x00000064)
constant ESME_RX_P_APPN (line 111) | ESME_RX_P_APPN = CommandStatusType(0x00000065)
constant ESME_RX_R_APPN (line 112) | ESME_RX_R_APPN = CommandStatusType(0x00000066)
constant ESME_RQUERYFAIL (line 113) | ESME_RQUERYFAIL = CommandStatusType(0x00000067)
constant ESME_RINVPGCUSTID (line 115) | ESME_RINVPGCUSTID = CommandStatusType(0x00000080)
constant ESME_RINVPGCUSTIDLEN (line 116) | ESME_RINVPGCUSTIDLEN = CommandStatusType(0x00000081)
constant ESME_RINVCITYLEN (line 117) | ESME_RINVCITYLEN = CommandStatusType(0x00000082)
constant ESME_RINVSTATELEN (line 118) | ESME_RINVSTATELEN = CommandStatusType(0x00000083)
constant ESME_RINVZIPPREFIXLEN (line 119) | ESME_RINVZIPPREFIXLEN = CommandStatusType(0x00000084)
constant ESME_RINVZIPPOSTFIXLEN (line 120) | ESME_RINVZIPPOSTFIXLEN = CommandStatusType(0x00000085)
constant ESME_RINVMINLEN (line 121) | ESME_RINVMINLEN = CommandStatusType(0x00000086)
constant ESME_RINVMIN (line 122) | ESME_RINVMIN = CommandStatusType(0x00000087)
constant ESME_RINVPINLEN (line 123) | ESME_RINVPINLEN = CommandStatusType(0x00000088)
constant ESME_RINVTERMCODELEN (line 124) | ESME_RINVTERMCODELEN = CommandStatusType(0x00000089)
constant ESME_RINVCHANNELLEN (line 125) | ESME_RINVCHANNELLEN = CommandStatusType(0x0000008A)
constant ESME_RINVCOVREGIONLEN (line 126) | ESME_RINVCOVREGIONLEN = CommandStatusType(0x0000008B)
constant ESME_RINVCAPCODELEN (line 127) | ESME_RINVCAPCODELEN = CommandStatusType(0x0000008C)
constant ESME_RINVMDTLEN (line 128) | ESME_RINVMDTLEN = CommandStatusType(0x0000008D)
constant ESME_RINVPRIORMSGLEN (line 129) | ESME_RINVPRIORMSGLEN = CommandStatusType(0x0000008E)
constant ESME_RINVPERMSGLEN (line 130) | ESME_RINVPERMSGLEN = CommandStatusType(0x0000008F)
constant ESME_RINVPGALERTLEN (line 131) | ESME_RINVPGALERTLEN = CommandStatusType(0x00000090)
constant ESME_RINVSMUSERLEN (line 132) | ESME_RINVSMUSERLEN = CommandStatusType(0x00000091)
constant ESME_RINVRTDBLEN (line 133) | ESME_RINVRTDBLEN = CommandStatusType(0x00000092)
constant ESME_RINVREGDELLEN (line 134) | ESME_RINVREGDELLEN = CommandStatusType(0x00000093)
constant ESME_RINVMSGDISTLEN (line 135) | ESME_RINVMSGDISTLEN = CommandStatusType(0x00000094)
constant ESME_RINVPRIORMSG (line 136) | ESME_RINVPRIORMSG = CommandStatusType(0x00000095)
constant ESME_RINVMDT (line 137) | ESME_RINVMDT = CommandStatusType(0x00000096)
constant ESME_RINVPERMSG (line 138) | ESME_RINVPERMSG = CommandStatusType(0x00000097)
constant ESME_RINVMSGDIST (line 139) | ESME_RINVMSGDIST = CommandStatusType(0x00000098)
constant ESME_RINVPGALERT (line 140) | ESME_RINVPGALERT = CommandStatusType(0x00000099)
constant ESME_RINVSMUSER (line 141) | ESME_RINVSMUSER = CommandStatusType(0x0000009A)
constant ESME_RINVRTDB (line 142) | ESME_RINVRTDB = CommandStatusType(0x0000009B)
constant ESME_RINVREGDEL (line 143) | ESME_RINVREGDEL = CommandStatusType(0x0000009C)
constant ESME_RINVOPTPARLEN (line 144) | ESME_RINVOPTPARLEN = CommandStatusType(0x0000009F)
constant ESME_RINVOPTPARSTREAM (line 145) | ESME_RINVOPTPARSTREAM = CommandStatusType(0x000000C0)
constant ESME_ROPTPARNOTALLWD (line 146) | ESME_ROPTPARNOTALLWD = CommandStatusType(0x000000C1)
constant ESME_RINVPARLEN (line 147) | ESME_RINVPARLEN = CommandStatusType(0x000000C2)
constant ESME_RMISSINGOPTPARAM (line 148) | ESME_RMISSINGOPTPARAM = CommandStatusType(0x000000C3)
constant ESME_RINVOPTPARAMVAL (line 149) | ESME_RINVOPTPARAMVAL = CommandStatusType(0x000000C4)
constant ESME_RDELIVERYFAILURE (line 150) | ESME_RDELIVERYFAILURE = CommandStatusType(0x000000FE)
constant ESME_RUNKNOWNERR (line 151) | ESME_RUNKNOWNERR = CommandStatusType(0x000000FF)
constant ESME_LAST_ERROR (line 153) | ESME_LAST_ERROR = CommandStatusType(0x0000012C)
FILE: data/header_data_string.go
function _ (line 7) | func _() {
constant _CommandStatusType_name (line 113) | _CommandStatusType_name = "ESME_ROKESME_RINVMSGLENESME_RINVCMDLENESME_RI...
method String (line 218) | func (i CommandStatusType) String() string {
method Desc (line 225) | func (i CommandStatusType) Desc() string {
function _ (line 431) | func _() {
constant _CommandIDType_name_0 (line 465) | _CommandIDType_name_0 = "GENERIC_NACKBIND_RECEIVER_RESPBIND_TRANSMITTER_...
constant _CommandIDType_name_1 (line 466) | _CommandIDType_name_1 = "ENQUIRE_LINK_RESP"
constant _CommandIDType_name_2 (line 467) | _CommandIDType_name_2 = "SUBMIT_MULTI_RESP"
constant _CommandIDType_name_3 (line 468) | _CommandIDType_name_3 = "DATA_SM_RESP"
constant _CommandIDType_name_4 (line 469) | _CommandIDType_name_4 = "BIND_RECEIVERBIND_TRANSMITTERQUERY_SMSUBMIT_SMD...
constant _CommandIDType_name_5 (line 470) | _CommandIDType_name_5 = "OUTBIND"
constant _CommandIDType_name_6 (line 471) | _CommandIDType_name_6 = "ENQUIRE_LINK"
constant _CommandIDType_name_7 (line 472) | _CommandIDType_name_7 = "SUBMIT_MULTI"
constant _CommandIDType_name_8 (line 473) | _CommandIDType_name_8 = "ALERT_NOTIFICATIONDATA_SM"
method String (line 482) | func (i CommandIDType) String() string {
FILE: data/other_codings.go
type utf16BEM (line 21) | type utf16BEM struct
method Encode (line 23) | func (c utf16BEM) Encode(str string) ([]byte, error) {
method Decode (line 28) | func (c utf16BEM) Decode(data []byte) (string, error) {
type utf16LEM (line 33) | type utf16LEM struct
method Encode (line 35) | func (c utf16LEM) Encode(str string) ([]byte, error) {
method Decode (line 40) | func (c utf16LEM) Decode(data []byte) (string, error) {
type utf16BE (line 45) | type utf16BE struct
method Encode (line 47) | func (c utf16BE) Encode(str string) ([]byte, error) {
method Decode (line 52) | func (c utf16BE) Decode(data []byte) (string, error) {
type utf16LE (line 57) | type utf16LE struct
method Encode (line 59) | func (c utf16LE) Encode(str string) ([]byte, error) {
method Decode (line 64) | func (c utf16LE) Decode(data []byte) (string, error) {
FILE: data/pkg.go
constant SM_CONNID_LEN (line 10) | SM_CONNID_LEN = 16
constant SM_MSG_LEN (line 11) | SM_MSG_LEN = 254
constant SM_SYSID_LEN (line 12) | SM_SYSID_LEN = 16
constant SM_MSGID_LEN (line 13) | SM_MSGID_LEN = 64
constant SM_PASS_LEN (line 14) | SM_PASS_LEN = 9
constant SM_DATE_LEN (line 15) | SM_DATE_LEN = 17
constant SM_SRVTYPE_LEN (line 16) | SM_SRVTYPE_LEN = 6
constant SM_SYSTYPE_LEN (line 17) | SM_SYSTYPE_LEN = 13
constant SM_ADDR_LEN (line 18) | SM_ADDR_LEN = 21
constant SM_DATA_ADDR_LEN (line 19) | SM_DATA_ADDR_LEN = 65
constant SM_ADDR_RANGE_LEN (line 20) | SM_ADDR_RANGE_LEN = 41
constant SM_TYPE_LEN (line 21) | SM_TYPE_LEN = 13
constant SM_DL_NAME_LEN (line 22) | SM_DL_NAME_LEN = 21
constant SM_PARAM_NAME_LEN (line 23) | SM_PARAM_NAME_LEN = 10
constant SM_PARAM_VALUE_LEN (line 24) | SM_PARAM_VALUE_LEN = 10
constant SM_MAX_CNT_DEST_ADDR (line 25) | SM_MAX_CNT_DEST_ADDR = 254
constant SM_GSM_MSG_LEN (line 28) | SM_GSM_MSG_LEN = 140
constant CONNECTION_CLOSED (line 30) | CONNECTION_CLOSED = 0
constant CONNECTION_OPENED (line 31) | CONNECTION_OPENED = 1
constant SM_ACK (line 33) | SM_ACK = 1
constant SM_NO_ACK (line 34) | SM_NO_ACK = 0
constant SM_RESPONSE_ACK (line 35) | SM_RESPONSE_ACK = 0
constant SM_RESPONSE_TNACK (line 36) | SM_RESPONSE_TNACK = 1
constant SM_RESPONSE_PNACK (line 37) | SM_RESPONSE_PNACK = 2
constant SMPP_V33 (line 40) | SMPP_V33 int8 = int8(-0x33)
constant SMPP_V34 (line 41) | SMPP_V34 = byte(0x34)
constant GSM_TON_UNKNOWN (line 44) | GSM_TON_UNKNOWN = byte(0x00)
constant GSM_TON_INTERNATIONAL (line 45) | GSM_TON_INTERNATIONAL = byte(0x01)
constant GSM_TON_NATIONAL (line 46) | GSM_TON_NATIONAL = byte(0x02)
constant GSM_TON_NETWORK (line 47) | GSM_TON_NETWORK = byte(0x03)
constant GSM_TON_SUBSCRIBER (line 48) | GSM_TON_SUBSCRIBER = byte(0x04)
constant GSM_TON_ALPHANUMERIC (line 49) | GSM_TON_ALPHANUMERIC = byte(0x05)
constant GSM_TON_ABBREVIATED (line 50) | GSM_TON_ABBREVIATED = byte(0x06)
constant GSM_TON_RESERVED_EXTN (line 51) | GSM_TON_RESERVED_EXTN = byte(0x07)
constant GSM_NPI_UNKNOWN (line 54) | GSM_NPI_UNKNOWN = byte(0x00)
constant GSM_NPI_E164 (line 55) | GSM_NPI_E164 = byte(0x01)
constant GSM_NPI_ISDN (line 56) | GSM_NPI_ISDN = GSM_NPI_E164
constant GSM_NPI_X121 (line 57) | GSM_NPI_X121 = byte(0x03)
constant GSM_NPI_TELEX (line 58) | GSM_NPI_TELEX = byte(0x04)
constant GSM_NPI_LAND_MOBILE (line 59) | GSM_NPI_LAND_MOBILE = byte(0x06)
constant GSM_NPI_NATIONAL (line 60) | GSM_NPI_NATIONAL = byte(0x08)
constant GSM_NPI_PRIVATE (line 61) | GSM_NPI_PRIVATE = byte(0x09)
constant GSM_NPI_ERMES (line 62) | GSM_NPI_ERMES = byte(0x0A)
constant GSM_NPI_INTERNET (line 63) | GSM_NPI_INTERNET = byte(0x0E)
constant GSM_NPI_WAP_CLIENT_ID (line 64) | GSM_NPI_WAP_CLIENT_ID = byte(0x12)
constant GSM_NPI_RESERVED_EXTN (line 65) | GSM_NPI_RESERVED_EXTN = byte(0x0F)
constant SERVICE_NULL (line 68) | SERVICE_NULL string = ""
constant SERVICE_CMT (line 69) | SERVICE_CMT string = "CMT"
constant SERVICE_CPT (line 70) | SERVICE_CPT string = "CPT"
constant SERVICE_VMN (line 71) | SERVICE_VMN string = "VMN"
constant SERVICE_VMA (line 72) | SERVICE_VMA string = "VMA"
constant SERVICE_WAP (line 73) | SERVICE_WAP string = "WAP"
constant SERVICE_USSD (line 74) | SERVICE_USSD string = "USSD"
constant SMPP_PROTOCOL (line 76) | SMPP_PROTOCOL = byte(1)
constant SMPPP_PROTOCOL (line 77) | SMPPP_PROTOCOL = byte(2)
constant SM_SERVICE_MOBILE_TERMINATED (line 78) | SM_SERVICE_MOBILE_TERMINATED = byte(0)
constant SM_SERVICE_MOBILE_ORIGINATED (line 79) | SM_SERVICE_MOBILE_ORIGINATED = byte(1)
constant SM_SERVICE_MOBILE_TRANSCEIVER (line 80) | SM_SERVICE_MOBILE_TRANSCEIVER = byte(2)
constant SM_STATE_EN_ROUTE (line 83) | SM_STATE_EN_ROUTE = 1
constant SM_STATE_DELIVERED (line 84) | SM_STATE_DELIVERED = 2
constant SM_STATE_EXPIRED (line 85) | SM_STATE_EXPIRED = 3
constant SM_STATE_DELETED (line 86) | SM_STATE_DELETED = 4
constant SM_STATE_UNDELIVERABLE (line 87) | SM_STATE_UNDELIVERABLE = 5
constant SM_STATE_ACCEPTED (line 88) | SM_STATE_ACCEPTED = 6
constant SM_STATE_INVALID (line 89) | SM_STATE_INVALID = 7
constant SM_STATE_REJECTED (line 90) | SM_STATE_REJECTED = 8
constant SM_ESM_DEFAULT (line 97) | SM_ESM_DEFAULT = 0x00
constant SM_DATAGRAM_MODE (line 98) | SM_DATAGRAM_MODE = 0x01
constant SM_FORWARD_MODE (line 99) | SM_FORWARD_MODE = 0x02
constant SM_STORE_FORWARD_MODE (line 100) | SM_STORE_FORWARD_MODE = 0x03
constant SM_SMSC_DLV_RCPT_TYPE (line 103) | SM_SMSC_DLV_RCPT_TYPE = 0x04
constant SM_ESME_DLV_ACK_TYPE (line 104) | SM_ESME_DLV_ACK_TYPE = 0x08
constant SM_ESME_MAN_USER_ACK_TYPE (line 105) | SM_ESME_MAN_USER_ACK_TYPE = 0x10
constant SM_CONV_ABORT_TYPE (line 106) | SM_CONV_ABORT_TYPE = 0x18
constant SM_INTMD_DLV_NOTIFY_TYPE (line 107) | SM_INTMD_DLV_NOTIFY_TYPE = 0x20
constant SM_NONE_GSM (line 110) | SM_NONE_GSM = 0x00
constant SM_UDH_GSM (line 111) | SM_UDH_GSM = 0x40
constant SM_REPLY_PATH_GSM (line 112) | SM_REPLY_PATH_GSM = 0x80
constant SM_UDH_REPLY_PATH_GSM (line 113) | SM_UDH_REPLY_PATH_GSM = 0xC0
constant OPT_PAR_MSG_WAIT (line 119) | OPT_PAR_MSG_WAIT = 2
constant OPT_PAR_PRIV_IND (line 122) | OPT_PAR_PRIV_IND = 0x0201
constant OPT_PAR_SRC_SUBADDR (line 125) | OPT_PAR_SRC_SUBADDR = 0x0202
constant OPT_PAR_SRC_SUBADDR_MIN (line 126) | OPT_PAR_SRC_SUBADDR_MIN = 2
constant OPT_PAR_SRC_SUBADDR_MAX (line 127) | OPT_PAR_SRC_SUBADDR_MAX = 23
constant OPT_PAR_DEST_SUBADDR (line 130) | OPT_PAR_DEST_SUBADDR = 0x0203
constant OPT_PAR_DEST_SUBADDR_MIN (line 131) | OPT_PAR_DEST_SUBADDR_MIN = 2
constant OPT_PAR_DEST_SUBADDR_MAX (line 132) | OPT_PAR_DEST_SUBADDR_MAX = 23
constant OPT_PAR_USER_MSG_REF (line 135) | OPT_PAR_USER_MSG_REF = 0x0204
constant OPT_PAR_USER_RESP_CODE (line 138) | OPT_PAR_USER_RESP_CODE = 0x0205
constant OPT_PAR_LANG_IND (line 141) | OPT_PAR_LANG_IND = 0x020D
constant OPT_PAR_SRC_PORT (line 144) | OPT_PAR_SRC_PORT = 0x020A
constant OPT_PAR_DST_PORT (line 147) | OPT_PAR_DST_PORT = 0x020B
constant OPT_PAR_SAR_MSG_REF_NUM (line 150) | OPT_PAR_SAR_MSG_REF_NUM = 0x020C
constant OPT_PAR_SAR_TOT_SEG (line 153) | OPT_PAR_SAR_TOT_SEG = 0x020E
constant OPT_PAR_SAR_SEG_SNUM (line 156) | OPT_PAR_SAR_SEG_SNUM = 0x020F
constant OPT_PAR_SC_IF_VER (line 159) | OPT_PAR_SC_IF_VER = 0x0210
constant OPT_PAR_DISPLAY_TIME (line 162) | OPT_PAR_DISPLAY_TIME = 0x1201
constant OPT_PAR_MS_VALIDITY (line 165) | OPT_PAR_MS_VALIDITY = 0x1204
constant OPT_PAR_DPF_RES (line 168) | OPT_PAR_DPF_RES = 0x0420
constant OPT_PAR_SET_DPF (line 171) | OPT_PAR_SET_DPF = 0x0421
constant OPT_PAR_MS_AVAIL_STAT (line 174) | OPT_PAR_MS_AVAIL_STAT = 0x0422
constant OPT_PAR_NW_ERR_CODE (line 177) | OPT_PAR_NW_ERR_CODE = 0x0423
constant OPT_PAR_NW_ERR_CODE_MIN (line 178) | OPT_PAR_NW_ERR_CODE_MIN = 3
constant OPT_PAR_NW_ERR_CODE_MAX (line 179) | OPT_PAR_NW_ERR_CODE_MAX = 3
constant OPT_PAR_DEL_FAIL_RSN (line 184) | OPT_PAR_DEL_FAIL_RSN = 0x0425
constant OPT_PAR_MORE_MSGS (line 187) | OPT_PAR_MORE_MSGS = 0x0426
constant OPT_PAR_MSG_STATE (line 190) | OPT_PAR_MSG_STATE = 0x0427
constant OPT_PAR_CALLBACK_NUM (line 193) | OPT_PAR_CALLBACK_NUM = 0x0381
constant OPT_PAR_CALLBACK_NUM_MIN (line 194) | OPT_PAR_CALLBACK_NUM_MIN = 4
constant OPT_PAR_CALLBACK_NUM_MAX (line 195) | OPT_PAR_CALLBACK_NUM_MAX = 19
constant OPT_PAR_CALLBACK_NUM_PRES_IND (line 198) | OPT_PAR_CALLBACK_NUM_PRES_IND = 0x0302
constant OPT_PAR_CALLBACK_NUM_ATAG (line 201) | OPT_PAR_CALLBACK_NUM_ATAG = 0x0303
constant OPT_PAR_CALLBACK_NUM_ATAG_MIN (line 202) | OPT_PAR_CALLBACK_NUM_ATAG_MIN = 1
constant OPT_PAR_CALLBACK_NUM_ATAG_MAX (line 203) | OPT_PAR_CALLBACK_NUM_ATAG_MAX = 65
constant OPT_PAR_NUM_MSGS (line 206) | OPT_PAR_NUM_MSGS = 0x0304
constant OPT_PAR_SMS_SIGNAL (line 209) | OPT_PAR_SMS_SIGNAL = 0x1203
constant OPT_PAR_ALERT_ON_MSG_DELIVERY (line 212) | OPT_PAR_ALERT_ON_MSG_DELIVERY = 0x130C
constant OPT_PAR_ITS_REPLY_TYPE (line 215) | OPT_PAR_ITS_REPLY_TYPE = 0x1380
constant OPT_PAR_ITS_SESSION_INFO (line 218) | OPT_PAR_ITS_SESSION_INFO = 0x1383
constant OPT_PAR_USSD_SER_OP (line 221) | OPT_PAR_USSD_SER_OP = 0x0501
constant SM_NOPRIORITY (line 224) | SM_NOPRIORITY = 0
constant SM_PRIORITY (line 225) | SM_PRIORITY = 1
constant SM_SMSC_RECEIPT_MASK (line 229) | SM_SMSC_RECEIPT_MASK = byte(0x03)
constant SM_SMSC_RECEIPT_NOT_REQUESTED (line 230) | SM_SMSC_RECEIPT_NOT_REQUESTED = byte(0x00)
constant SM_SMSC_RECEIPT_REQUESTED (line 231) | SM_SMSC_RECEIPT_REQUESTED = byte(0x01)
constant SM_SMSC_RECEIPT_ON_FAILURE (line 232) | SM_SMSC_RECEIPT_ON_FAILURE = byte(0x02)
constant SM_SME_ACK_MASK (line 234) | SM_SME_ACK_MASK = byte(0x0c)
constant SM_SME_ACK_NOT_REQUESTED (line 235) | SM_SME_ACK_NOT_REQUESTED = byte(0x00)
constant SM_SME_ACK_DELIVERY_REQUESTED (line 236) | SM_SME_ACK_DELIVERY_REQUESTED = byte(0x04)
constant SM_SME_ACK_MANUAL_REQUESTED (line 237) | SM_SME_ACK_MANUAL_REQUESTED = byte(0x08)
constant SM_SME_ACK_BOTH_REQUESTED (line 238) | SM_SME_ACK_BOTH_REQUESTED = byte(0x0c)
constant SM_NOTIF_MASK (line 240) | SM_NOTIF_MASK = byte(0x010)
constant SM_NOTIF_NOT_REQUESTED (line 241) | SM_NOTIF_NOT_REQUESTED = byte(0x000)
constant SM_NOTIF_REQUESTED (line 242) | SM_NOTIF_REQUESTED = byte(0x010)
constant SM_NOREPLACE (line 245) | SM_NOREPLACE = 0
constant SM_REPLACE (line 246) | SM_REPLACE = 1
constant SM_DEST_SME_ADDRESS (line 249) | SM_DEST_SME_ADDRESS = 1
constant SM_DEST_DL_NAME (line 250) | SM_DEST_DL_NAME = 2
constant SM_LAYER_WDP (line 253) | SM_LAYER_WDP = 0
constant SM_LAYER_WCMP (line 254) | SM_LAYER_WCMP = 1
constant SM_OPCLASS_DATAGRAM (line 257) | SM_OPCLASS_DATAGRAM = 0
constant SM_OPCLASS_TRANSACTION (line 258) | SM_OPCLASS_TRANSACTION = 3
constant OPT_PAR_ORIG_MSC_ADDR (line 261) | OPT_PAR_ORIG_MSC_ADDR = -32639
constant OPT_PAR_ORIG_MSC_ADDR_MIN (line 262) | OPT_PAR_ORIG_MSC_ADDR_MIN = 1
constant OPT_PAR_ORIG_MSC_ADDR_MAX (line 263) | OPT_PAR_ORIG_MSC_ADDR_MAX = 24
constant OPT_PAR_DEST_MSC_ADDR (line 266) | OPT_PAR_DEST_MSC_ADDR = -32638
constant OPT_PAR_DEST_MSC_ADDR_MIN (line 267) | OPT_PAR_DEST_MSC_ADDR_MIN = 1
constant OPT_PAR_DEST_MSC_ADDR_MAX (line 268) | OPT_PAR_DEST_MSC_ADDR_MAX = 24
constant OPT_PAR_UNUSED (line 271) | OPT_PAR_UNUSED = 0xffff
constant OPT_PAR_DST_ADDR_SUBUNIT (line 274) | OPT_PAR_DST_ADDR_SUBUNIT = 0x0005
constant OPT_PAR_DST_NW_TYPE (line 277) | OPT_PAR_DST_NW_TYPE = 0x0006
constant OPT_PAR_DST_BEAR_TYPE (line 280) | OPT_PAR_DST_BEAR_TYPE = 0x0007
constant OPT_PAR_DST_TELE_ID (line 283) | OPT_PAR_DST_TELE_ID = 0x0008
constant OPT_PAR_SRC_ADDR_SUBUNIT (line 286) | OPT_PAR_SRC_ADDR_SUBUNIT = 0x000D
constant OPT_PAR_SRC_NW_TYPE (line 289) | OPT_PAR_SRC_NW_TYPE = 0x000E
constant OPT_PAR_SRC_BEAR_TYPE (line 292) | OPT_PAR_SRC_BEAR_TYPE = 0x000F
constant OPT_PAR_SRC_TELE_ID (line 295) | OPT_PAR_SRC_TELE_ID = 0x0010
constant OPT_PAR_QOS_TIME_TO_LIVE (line 298) | OPT_PAR_QOS_TIME_TO_LIVE = 0x0017
constant OPT_PAR_QOS_TIME_TO_LIVE_MIN (line 299) | OPT_PAR_QOS_TIME_TO_LIVE_MIN = 1
constant OPT_PAR_QOS_TIME_TO_LIVE_MAX (line 300) | OPT_PAR_QOS_TIME_TO_LIVE_MAX = 4
constant OPT_PAR_PAYLOAD_TYPE (line 303) | OPT_PAR_PAYLOAD_TYPE = 0x0019
constant OPT_PAR_ADD_STAT_INFO (line 306) | OPT_PAR_ADD_STAT_INFO = 0x001D
constant OPT_PAR_ADD_STAT_INFO_MIN (line 307) | OPT_PAR_ADD_STAT_INFO_MIN = 1
constant OPT_PAR_ADD_STAT_INFO_MAX (line 308) | OPT_PAR_ADD_STAT_INFO_MAX = 256
constant OPT_PAR_RECP_MSG_ID (line 311) | OPT_PAR_RECP_MSG_ID = 0x001E
constant OPT_PAR_RECP_MSG_ID_MIN (line 312) | OPT_PAR_RECP_MSG_ID_MIN = 1
constant OPT_PAR_RECP_MSG_ID_MAX (line 313) | OPT_PAR_RECP_MSG_ID_MAX = 65
constant OPT_PAR_MSG_PAYLOAD (line 316) | OPT_PAR_MSG_PAYLOAD = 0x0424
constant OPT_PAR_MSG_PAYLOAD_MIN (line 317) | OPT_PAR_MSG_PAYLOAD_MIN = 1
constant OPT_PAR_MSG_PAYLOAD_MAX (line 318) | OPT_PAR_MSG_PAYLOAD_MAX = 1500
constant UDH_CONCAT_MSG_8_BIT_REF (line 321) | UDH_CONCAT_MSG_8_BIT_REF = byte(0x00)
constant UDH_CONCAT_MSG_16_BIT_REF (line 322) | UDH_CONCAT_MSG_16_BIT_REF = byte(0x08)
constant DFLT_MSGID (line 331) | DFLT_MSGID string = ""
constant DFLT_MSG (line 332) | DFLT_MSG string = ""
constant DFLT_SRVTYPE (line 333) | DFLT_SRVTYPE string = ""
constant DFLT_SYSID (line 334) | DFLT_SYSID string = ""
constant DFLT_PASS (line 335) | DFLT_PASS string = ""
constant DFLT_SYSTYPE (line 336) | DFLT_SYSTYPE string = ""
constant DFLT_ADDR_RANGE (line 337) | DFLT_ADDR_RANGE string = ""
constant DFLT_DATE (line 338) | DFLT_DATE string = ""
constant DFLT_ADDR (line 339) | DFLT_ADDR string = ""
constant DFLT_MSG_STATE (line 340) | DFLT_MSG_STATE byte = 0
constant DFLT_ERR (line 341) | DFLT_ERR byte = 0
constant DFLT_SCHEDULE (line 342) | DFLT_SCHEDULE string = ""
constant DFLT_VALIDITY (line 343) | DFLT_VALIDITY string = ""
constant DFLT_REG_DELIVERY (line 344) | DFLT_REG_DELIVERY = SM_SMSC_RECEIPT_NOT_REQUESTED | SM_SME_ACK_N...
constant DFLT_DFLTMSGID (line 345) | DFLT_DFLTMSGID = byte(0)
constant DFLT_MSG_LEN (line 346) | DFLT_MSG_LEN = byte(0)
constant DFLT_ESM_CLASS (line 347) | DFLT_ESM_CLASS = byte(0)
constant DFLT_DATA_CODING (line 348) | DFLT_DATA_CODING = byte(0)
constant DFLT_PROTOCOLID (line 349) | DFLT_PROTOCOLID = byte(0)
constant DFLT_PRIORITY_FLAG (line 350) | DFLT_PRIORITY_FLAG = byte(0)
constant DFTL_REPLACE_IFP (line 351) | DFTL_REPLACE_IFP = byte(0)
constant DFLT_DL_NAME (line 352) | DFLT_DL_NAME string = ""
constant DFLT_GSM_TON (line 353) | DFLT_GSM_TON = GSM_TON_UNKNOWN
constant DFLT_GSM_NPI (line 354) | DFLT_GSM_NPI = GSM_NPI_UNKNOWN
constant DFLT_DEST_FLAG (line 355) | DFLT_DEST_FLAG = byte(0)
constant MAX_PDU_LEN (line 356) | MAX_PDU_LEN = 64 << 10
constant PDU_HEADER_SIZE (line 358) | PDU_HEADER_SIZE = 16
constant TLV_HEADER_SIZE (line 359) | TLV_HEADER_SIZE = 4
constant RECEIVER_TIMEOUT (line 362) | RECEIVER_TIMEOUT int64 = 60000
constant CONNECTION_RECEIVE_TIMEOUT (line 363) | CONNECTION_RECEIVE_TIMEOUT int64 = 10000
constant UNBIND_RECEIVE_TIMEOUT (line 364) | UNBIND_RECEIVE_TIMEOUT int64 = 5000
constant CONNECTION_SEND_TIMEOUT (line 365) | CONNECTION_SEND_TIMEOUT int64 = 20000
constant COMMS_TIMEOUT (line 366) | COMMS_TIMEOUT int64 = 60000
constant QUEUE_TIMEOUT (line 367) | QUEUE_TIMEOUT int64 = 10000
constant ACCEPT_TIMEOUT (line 368) | ACCEPT_TIMEOUT int64 = 60000
constant RECEIVE_BLOCKING (line 370) | RECEIVE_BLOCKING int64 = -1
constant MAX_VALUE_PORT (line 372) | MAX_VALUE_PORT = 65535
constant MIN_VALUE_PORT (line 373) | MIN_VALUE_PORT = 100
constant MIN_LENGTH_ADDRESS (line 374) | MIN_LENGTH_ADDRESS = 7
function init (line 389) | func init() {
function SetDefaultTon (line 395) | func SetDefaultTon(dfltTon byte) {
function GetDefaultTon (line 400) | func GetDefaultTon() byte {
function SetDefaultNpi (line 405) | func SetDefaultNpi(dfltNpi byte) {
function GetDefaultNpi (line 410) | func GetDefaultNpi() byte {
FILE: data/pkg_test.go
function TestDefaultNpi (line 9) | func TestDefaultNpi(t *testing.T) {
function TestDefaultTon (line 14) | func TestDefaultTon(t *testing.T) {
FILE: data/utils.go
function FindEncoding (line 7) | func FindEncoding(s string) (enc Encoding) {
function isASCII (line 16) | func isASCII(s string) bool {
FILE: data/utils_test.go
function TestFindEncoding (line 9) | func TestFindEncoding(t *testing.T) {
FILE: errors/pkg.go
type SmppErr (line 10) | type SmppErr struct
method Error (line 16) | func (s *SmppErr) Error() string {
FILE: errors/pkg_test.go
function TestErr (line 10) | func TestErr(t *testing.T) {
FILE: example/smsc_simulator/smsc.cpp
function currentUSecsSinceEpoch (line 43) | uint64_t currentUSecsSinceEpoch(void) {
class ClientConfig (line 51) | class ClientConfig {
method ClientConfig (line 53) | ClientConfig() {}
method ClientConfig (line 58) | static ClientConfig& instance() {
method is (line 65) | bool is(string esme_id, ConfigEntry entry) { return false; }
class MessageDeliverer (line 70) | class MessageDeliverer {
class Message (line 72) | class Message {
method Message (line 98) | Message() {}
method Message (line 99) | Message(char* in) { content = in; }
method string (line 102) | string getContent(void) { return content; }
method setSource (line 104) | void setSource(uint8_t ton, uint8_t npi, char* addr) {
method setDestination (line 109) | void setDestination(uint8_t ton, uint8_t npi, char* addr) {
method setRegisteredDelivery (line 114) | void setRegisteredDelivery(uint8_t val) { registered_delivery = val; }
method setShortMessage (line 115) | void setShortMessage(uint8_t* sm_in, uint8_t sm_len_in) {
method setSMSCMessageID (line 119) | void setSMSCMessageID(char* id) { smscMessageID = id; }
method MessageDeliverer (line 127) | MessageDeliverer() {}
method empty (line 132) | bool empty(void) { return (mq.size() == 0); }
method get (line 134) | bool get(Message& msgout) {
method MessageDeliverer (line 156) | static MessageDeliverer* getInstance(string& systemID) {
method getInstance_get (line 166) | static bool getInstance_get(string& systemID, Message& msgout) {
method add (line 182) | void add(uint64_t timeDeliver, Message msg) {
class SMPPSocket (line 201) | class SMPPSocket {
method SMPPSocket (line 206) | SMPPSocket() {}
class SMPPSocketUnencrypted (line 216) | class SMPPSocketUnencrypted : public SMPPSocket {
method SMPPSocketUnencrypted (line 219) | SMPPSocketUnencrypted() {}
method SMPPSocketUnencrypted (line 220) | SMPPSocketUnencrypted(int socket_in) { socket = socket_in; }
method bytes_to_read (line 223) | long bytes_to_read(void) {
method recvA (line 229) | bool recvA(uint8_t& oct) {
method recv (line 233) | void recv(void) {}
method send (line 234) | bool send(uint8_t* buf, int len) {
class SMPP (line 241) | class SMPP {
class CmdStatus (line 243) | class CmdStatus {
class CmdID (line 254) | class CmdID {
method GSMTimeStringShort (line 339) | static void GSMTimeStringShort(time_t& t, char* szTimestamp, int nLen) {
method time_t (line 352) | static time_t GSMStringTime(const char* szBuf) {
method time_t (line 388) | static time_t GSMRelativeTime(char* szBuf) {
class SMPPConnection (line 398) | class SMPPConnection {
class SMPPException (line 400) | class SMPPException {}
method getInteger (line 434) | uint64_t getInteger(void) {
method getBytes (line 444) | uint64_t getBytes(uint64_t len, uint8_t* mem) {
method SMPPConnection (line 453) | SMPPConnection() {
method setDebug (line 466) | void setDebug(bool val) { debug = val; }
method allocateSocket (line 468) | void allocateSocket(void) { socket = new SMPPSocketUnencrypted; }
method allocateSocket (line 470) | void allocateSocket(int fdsocket) {
method setIP (line 474) | void setIP(char* ip_in) {
method endian (line 483) | uint64_t endian(uint64_t a) {
method put (line 492) | bool put(uint64_t sequence_number, uint64_t cmdID, uint64_t status,
method get (line 514) | bool get() {
method pduCommandID (line 571) | uint64_t pduCommandID(void) { return command_received_header.command_i...
method pduSequenceNo (line 572) | uint64_t pduSequenceNo(void) {
class Session (line 577) | class Session {
method Session (line 582) | Session() {}
class AdminSession (line 589) | class AdminSession : public Session {
method AdminSession (line 591) | AdminSession() { sessionType = 0; }
method AdminSession (line 592) | AdminSession(int fdsocket) {
method timedCheck (line 597) | bool timedCheck(void) {
method run (line 602) | bool run(void) { return true; }
class SMPPSession (line 605) | class SMPPSession : public Session {
method SMPPSession (line 627) | SMPPSession() {
method SMPPSession (line 636) | SMPPSession(int fdsocket, char* ip) {
method setDebug (line 651) | void setDebug(bool val) { conn.setDebug(val); }
method getCOctetString (line 653) | bool getCOctetString(uint8_t* buf_ptr, int buf_len, int& idx, string& ...
method timedCheck (line 668) | bool timedCheck(void) {
method generateMO (line 746) | void generateMO(uint8_t source_addr_ton, uint8_t source_addr_npi,
method generateReceipt (line 789) | void generateReceipt(uint8_t source_addr_ton, uint8_t source_addr_npi,
method run (line 876) | bool run(void) {
method getVersion (line 1193) | uint8_t getVersion(void) { return version; }
method setVersion (line 1194) | void setVersion(uint8_t version_in) { version = version_in; }
method logCommand (line 1196) | void logCommand(uint64_t cmdID, const char* direction) {
method logCommand (line 1203) | void logCommand(char* logline, const char* direction) {
method recv (line 1217) | bool recv(uint64_t& cmdID, uint64_t& seqNo) {
method send (line 1227) | bool send(uint64_t seqNo, uint64_t cmdID, uint64_t cmdStatus, uint8_t*...
function dolisten (line 1240) | int dolisten(int portno) {
function main (line 1302) | int main(int argc, const char* argv[]) {
FILE: example/transceiver_with_auto_response/main.go
function main (line 15) | func main() {
function sendingAndReceiveSMS (line 24) | func sendingAndReceiveSMS(wg *sync.WaitGroup) {
function handlePDU (line 75) | func handlePDU() func(pdu.PDU, bool) {
function newSubmitSM (line 117) | func newSubmitSM() *pdu.SubmitSM {
function isConcatenatedDone (line 141) | func isConcatenatedDone(parts []string, total byte) bool {
FILE: example/transceiver_with_manual_response/main.go
function main (line 14) | func main() {
function sendingAndReceiveSMS (line 23) | func sendingAndReceiveSMS(wg *sync.WaitGroup) {
function handlePDU (line 74) | func handlePDU() func(pdu.PDU) (pdu.PDU, bool) {
function newSubmitSM (line 109) | func newSubmitSM() *pdu.SubmitSM {
FILE: example/transeiver_with_custom_store/CustomStore.go
type CustomStore (line 28) | type CustomStore struct
method Set (line 39) | func (s CustomStore) Set(ctx context.Context, request gosmpp.Request) ...
method Get (line 54) | func (s CustomStore) Get(ctx context.Context, sequenceNumber int32) (g...
method List (line 72) | func (s CustomStore) List(ctx context.Context) []gosmpp.Request {
method Delete (line 91) | func (s CustomStore) Delete(ctx context.Context, sequenceNumber int32)...
method Clear (line 104) | func (s CustomStore) Clear(ctx context.Context) error {
method Length (line 117) | func (s CustomStore) Length(ctx context.Context) (int, error) {
function NewCustomStore (line 32) | func NewCustomStore() CustomStore {
function serialize (line 126) | func serialize(request gosmpp.Request) ([]byte, error) {
function deserialize (line 141) | func deserialize(bRequest []byte) (request gosmpp.Request, err error) {
type requestGob (line 163) | type requestGob struct
FILE: example/transeiver_with_custom_store/main.go
function main (line 15) | func main() {
function sendingAndReceiveSMS (line 24) | func sendingAndReceiveSMS(wg *sync.WaitGroup) {
function handleExpirePduRequest (line 101) | func handleExpirePduRequest() func(pdu.PDU) bool {
function handleOnClosePduRequest (line 123) | func handleOnClosePduRequest() func(pdu.PDU) {
function handleExpectedPduResponse (line 141) | func handleExpectedPduResponse() func(response gosmpp.Response) {
function handleReceivedPduRequest (line 160) | func handleReceivedPduRequest() func(pdu.PDU) (pdu.PDU, bool) {
function newSubmitSM (line 189) | func newSubmitSM() *pdu.SubmitSM {
FILE: example/transeiver_with_request_window_and_custom_submitSm/CustomSubmitSM.go
type CustomSubmitSM (line 12) | type CustomSubmitSM struct
function newCustomSubmitSM (line 19) | func newCustomSubmitSM() CustomSubmitSM {
FILE: example/transeiver_with_request_window_and_custom_submitSm/main.go
function main (line 15) | func main() {
function sendingAndReceiveSMS (line 24) | func sendingAndReceiveSMS(wg *sync.WaitGroup) {
function handleExpirePduRequest (line 99) | func handleExpirePduRequest() func(pdu.PDU) bool {
function handleOnClosePduRequest (line 120) | func handleOnClosePduRequest() func(pdu.PDU) {
function handleExpectedPduResponse (line 138) | func handleExpectedPduResponse() func(response gosmpp.Response) {
function handleReceivedPduRequest (line 157) | func handleReceivedPduRequest() func(pdu.PDU) (pdu.PDU, bool) {
function newSubmitSM (line 186) | func newSubmitSM() *pdu.SubmitSM {
FILE: pdu/Address.go
type Address (line 10) | type Address struct
method Unmarshal (line 41) | func (c *Address) Unmarshal(b *ByteBuffer) (err error) {
method Marshal (line 51) | func (c *Address) Marshal(b *ByteBuffer) {
method SetTon (line 60) | func (c *Address) SetTon(ton byte) {
method SetNpi (line 65) | func (c *Address) SetNpi(npi byte) {
method SetAddress (line 70) | func (c *Address) SetAddress(addr string) (err error) {
method Ton (line 80) | func (c Address) Ton() byte {
method Npi (line 85) | func (c Address) Npi() byte {
method Address (line 90) | func (c Address) Address() string {
method String (line 95) | func (c Address) String() string {
function NewAddress (line 17) | func NewAddress() Address {
function NewAddressWithAddr (line 22) | func NewAddressWithAddr(addr string) (a Address, err error) {
function NewAddressWithTonNpi (line 29) | func NewAddressWithTonNpi(ton, npi byte) Address {
function NewAddressWithTonNpiAddr (line 34) | func NewAddressWithTonNpiAddr(ton, npi byte, addr string) (a Address, er...
FILE: pdu/AddressRange.go
type AddressRange (line 6) | type AddressRange struct
method Unmarshal (line 37) | func (c *AddressRange) Unmarshal(b *ByteBuffer) (err error) {
method Marshal (line 47) | func (c *AddressRange) Marshal(b *ByteBuffer) {
function NewAddressRange (line 13) | func NewAddressRange() AddressRange {
function NewAddressRangeWithAddr (line 18) | func NewAddressRangeWithAddr(addr string) AddressRange {
function NewAddressRangeWithTonNpi (line 25) | func NewAddressRangeWithTonNpi(ton, npi byte) AddressRange {
function NewAddressRangeWithTonNpiAddr (line 30) | func NewAddressRangeWithTonNpiAddr(ton, npi byte, addr string) AddressRa...
FILE: pdu/AddressRange_test.go
function TestAddressRange (line 9) | func TestAddressRange(t *testing.T) {
FILE: pdu/Address_test.go
function TestAddress (line 9) | func TestAddress(t *testing.T) {
FILE: pdu/AlertNotification.go
type AlertNotification (line 10) | type AlertNotification struct
method CanResponse (line 26) | func (a *AlertNotification) CanResponse() bool {
method GetResponse (line 31) | func (a *AlertNotification) GetResponse() PDU {
method Marshal (line 36) | func (a *AlertNotification) Marshal(b *ByteBuffer) {
method Unmarshal (line 44) | func (a *AlertNotification) Unmarshal(b *ByteBuffer) error {
function NewAlertNotification (line 17) | func NewAlertNotification() PDU {
FILE: pdu/AlertNotification_test.go
function TestAlertNotification (line 11) | func TestAlertNotification(t *testing.T) {
FILE: pdu/BindRequest.go
type BindingType (line 8) | type BindingType
constant Receiver (line 12) | Receiver BindingType = iota
constant Transceiver (line 14) | Transceiver
constant Transmitter (line 16) | Transmitter
type BindRequest (line 20) | type BindRequest struct
method CanResponse (line 72) | func (b *BindRequest) CanResponse() bool {
method GetResponse (line 77) | func (b *BindRequest) GetResponse() PDU {
method Marshal (line 82) | func (b *BindRequest) Marshal(w *ByteBuffer) {
method Unmarshal (line 95) | func (b *BindRequest) Unmarshal(w *ByteBuffer) error {
function NewBindRequest (line 31) | func NewBindRequest(t BindingType) (b *BindRequest) {
function NewBindTransmitter (line 57) | func NewBindTransmitter() PDU {
function NewBindTransceiver (line 62) | func NewBindTransceiver() PDU {
function NewBindReceiver (line 67) | func NewBindReceiver() PDU {
FILE: pdu/BindRequest_test.go
function TestBindRequest (line 11) | func TestBindRequest(t *testing.T) {
FILE: pdu/BindResponse.go
type BindResp (line 8) | type BindResp struct
method CanResponse (line 62) | func (c *BindResp) CanResponse() bool {
method GetResponse (line 67) | func (c *BindResp) GetResponse() PDU {
method Marshal (line 72) | func (c *BindResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 81) | func (c *BindResp) Unmarshal(b *ByteBuffer) error {
function NewBindResp (line 14) | func NewBindResp(req BindRequest) (c *BindResp) {
function NewBindTransmitterResp (line 35) | func NewBindTransmitterResp() PDU {
function NewBindTransceiverResp (line 44) | func NewBindTransceiverResp() PDU {
function NewBindReceiverResp (line 53) | func NewBindReceiverResp() PDU {
FILE: pdu/BindResponse_test.go
function TestBindResponse (line 11) | func TestBindResponse(t *testing.T) {
FILE: pdu/Buffer.go
constant SizeByte (line 13) | SizeByte = 1
constant SizeShort (line 16) | SizeShort = 2
constant SizeInt (line 19) | SizeInt = 4
constant SizeLong (line 22) | SizeLong = 8
type ByteBuffer (line 33) | type ByteBuffer struct
method ReadN (line 46) | func (c *ByteBuffer) ReadN(n int) (r []byte, err error) {
method ReadShort (line 59) | func (c *ByteBuffer) ReadShort() (r int16, err error) {
method WriteShort (line 68) | func (c *ByteBuffer) WriteShort(v int16) {
method ReadInt (line 75) | func (c *ByteBuffer) ReadInt() (r int32, err error) {
method WriteInt (line 84) | func (c *ByteBuffer) WriteInt(v int32) {
method WriteBuffer (line 91) | func (c *ByteBuffer) WriteBuffer(d *ByteBuffer) {
method writeString (line 97) | func (c *ByteBuffer) writeString(st string, isCString bool, enc data.E...
method WriteCString (line 113) | func (c *ByteBuffer) WriteCString(s string) error {
method WriteCStringWithEnc (line 118) | func (c *ByteBuffer) WriteCStringWithEnc(s string, enc data.Encoding) ...
method ReadCString (line 123) | func (c *ByteBuffer) ReadCString() (st string, err error) {
method HexDump (line 132) | func (c *ByteBuffer) HexDump() string {
function NewBuffer (line 38) | func NewBuffer(inp []byte) *ByteBuffer {
FILE: pdu/Buffer_test.go
function TestBuffer (line 12) | func TestBuffer(t *testing.T) {
FILE: pdu/CancelSM.go
type CancelSM (line 10) | type CancelSM struct
method CanResponse (line 32) | func (c *CancelSM) CanResponse() bool {
method GetResponse (line 37) | func (c *CancelSM) GetResponse() PDU {
method Marshal (line 42) | func (c *CancelSM) Marshal(b *ByteBuffer) {
method Unmarshal (line 54) | func (c *CancelSM) Unmarshal(b *ByteBuffer) error {
function NewCancelSM (line 19) | func NewCancelSM() PDU {
FILE: pdu/CancelSMResp.go
type CancelSMResp (line 8) | type CancelSMResp struct
method CanResponse (line 31) | func (c *CancelSMResp) CanResponse() bool {
method GetResponse (line 36) | func (c *CancelSMResp) GetResponse() PDU {
method Marshal (line 41) | func (c *CancelSMResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 46) | func (c *CancelSMResp) Unmarshal(b *ByteBuffer) error {
function NewCancelSMResp (line 13) | func NewCancelSMResp() PDU {
function NewCancelSMRespFromReq (line 22) | func NewCancelSMRespFromReq(req *CancelSM) PDU {
FILE: pdu/CancelSMResp_test.go
function TestCancelSMResp (line 11) | func TestCancelSMResp(t *testing.T) {
FILE: pdu/CancelSM_test.go
function TestCancelSM (line 11) | func TestCancelSM(t *testing.T) {
FILE: pdu/DataSM.go
type DataSM (line 9) | type DataSM struct
method CanResponse (line 35) | func (c *DataSM) CanResponse() bool {
method GetResponse (line 40) | func (c *DataSM) GetResponse() PDU {
method Marshal (line 45) | func (c *DataSM) Marshal(b *ByteBuffer) {
method Unmarshal (line 59) | func (c *DataSM) Unmarshal(b *ByteBuffer) error {
function NewDataSM (line 20) | func NewDataSM() PDU {
FILE: pdu/DataSMResp.go
type DataSMResp (line 8) | type DataSMResp struct
method CanResponse (line 33) | func (c *DataSMResp) CanResponse() bool {
method GetResponse (line 38) | func (c *DataSMResp) GetResponse() PDU {
method Marshal (line 43) | func (c *DataSMResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 52) | func (c *DataSMResp) Unmarshal(b *ByteBuffer) error {
function NewDataSMResp (line 14) | func NewDataSMResp() PDU {
function NewDataSMRespFromReq (line 24) | func NewDataSMRespFromReq(req *DataSM) PDU {
FILE: pdu/DataSMResp_test.go
function TestDataSMResp (line 11) | func TestDataSMResp(t *testing.T) {
FILE: pdu/DataSM_test.go
function TestDataSM (line 11) | func TestDataSM(t *testing.T) {
FILE: pdu/DeliverSM.go
type DeliverSM (line 9) | type DeliverSM struct
method CanResponse (line 46) | func (c *DeliverSM) CanResponse() bool {
method GetResponse (line 51) | func (c *DeliverSM) GetResponse() PDU {
method Marshal (line 56) | func (c *DeliverSM) Marshal(b *ByteBuffer) {
method Unmarshal (line 75) | func (c *DeliverSM) Unmarshal(b *ByteBuffer) error {
function NewDeliverSM (line 25) | func NewDeliverSM() PDU {
FILE: pdu/DeliverSMResp.go
type DeliverSMResp (line 8) | type DeliverSMResp struct
method CanResponse (line 33) | func (c *DeliverSMResp) CanResponse() bool {
method GetResponse (line 38) | func (c *DeliverSMResp) GetResponse() PDU {
method Marshal (line 43) | func (c *DeliverSMResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 52) | func (c *DeliverSMResp) Unmarshal(b *ByteBuffer) error {
function NewDeliverSMResp (line 14) | func NewDeliverSMResp() PDU {
function NewDeliverSMRespFromReq (line 24) | func NewDeliverSMRespFromReq(req *DeliverSM) PDU {
FILE: pdu/DeliverSMResp_test.go
function TestDeliverSMResp (line 11) | func TestDeliverSMResp(t *testing.T) {
FILE: pdu/DeliverSM_test.go
function TestDeliverSM (line 11) | func TestDeliverSM(t *testing.T) {
function TestDeliverSMwithUDH (line 43) | func TestDeliverSMwithUDH(t *testing.T) {
FILE: pdu/DestinationAddress.go
type DestinationAddress (line 10) | type DestinationAddress struct
method Unmarshal (line 23) | func (c *DestinationAddress) Unmarshal(b *ByteBuffer) (err error) {
method Marshal (line 42) | func (c *DestinationAddress) Marshal(b *ByteBuffer) {
method Address (line 55) | func (c *DestinationAddress) Address() Address {
method DistributionList (line 60) | func (c *DestinationAddress) DistributionList() DistributionList {
method SetAddress (line 65) | func (c *DestinationAddress) SetAddress(addr Address) {
method SetDistributionList (line 71) | func (c *DestinationAddress) SetDistributionList(list DistributionList) {
method HasValue (line 77) | func (c *DestinationAddress) HasValue() bool {
method IsAddress (line 82) | func (c *DestinationAddress) IsAddress() bool {
method IsDistributionList (line 87) | func (c *DestinationAddress) IsDistributionList() bool {
function NewDestinationAddress (line 17) | func NewDestinationAddress() (c DestinationAddress) {
type DestinationAddresses (line 92) | type DestinationAddresses struct
method Add (line 103) | func (c *DestinationAddresses) Add(addresses ...DestinationAddress) {
method Get (line 108) | func (c *DestinationAddresses) Get() []DestinationAddress {
method Unmarshal (line 113) | func (c *DestinationAddresses) Unmarshal(b *ByteBuffer) (err error) {
method Marshal (line 129) | func (c *DestinationAddresses) Marshal(b *ByteBuffer) {
function NewDestinationAddresses (line 97) | func NewDestinationAddresses() (u DestinationAddresses) {
FILE: pdu/DestinationAddress_test.go
function TestDestinationAddress (line 11) | func TestDestinationAddress(t *testing.T) {
FILE: pdu/DistributionList.go
type DistributionList (line 10) | type DistributionList struct
method Unmarshal (line 21) | func (c *DistributionList) Unmarshal(b *ByteBuffer) (err error) {
method Marshal (line 27) | func (c *DistributionList) Marshal(b *ByteBuffer) {
method SetName (line 34) | func (c *DistributionList) SetName(name string) (err error) {
method Name (line 44) | func (c DistributionList) Name() string {
function NewDistributionList (line 15) | func NewDistributionList(name string) (c DistributionList, err error) {
FILE: pdu/DistributionList_test.go
function TestDistributionList (line 9) | func TestDistributionList(t *testing.T) {
FILE: pdu/EnquireLink.go
type EnquireLink (line 13) | type EnquireLink struct
method CanResponse (line 27) | func (c *EnquireLink) CanResponse() bool {
method GetResponse (line 32) | func (c *EnquireLink) GetResponse() PDU {
method Marshal (line 37) | func (c *EnquireLink) Marshal(b *ByteBuffer) {
method Unmarshal (line 42) | func (c *EnquireLink) Unmarshal(b *ByteBuffer) error {
function NewEnquireLink (line 18) | func NewEnquireLink() PDU {
FILE: pdu/EnquireLinkResp.go
type EnquireLinkResp (line 8) | type EnquireLinkResp struct
method CanResponse (line 31) | func (c *EnquireLinkResp) CanResponse() bool {
method GetResponse (line 36) | func (c *EnquireLinkResp) GetResponse() PDU {
method Marshal (line 41) | func (c *EnquireLinkResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 46) | func (c *EnquireLinkResp) Unmarshal(b *ByteBuffer) error {
function NewEnquireLinkResp (line 13) | func NewEnquireLinkResp() PDU {
function NewEnquireLinkRespFromReq (line 22) | func NewEnquireLinkRespFromReq(req *EnquireLink) PDU {
FILE: pdu/EnquireLinkResp_test.go
function TestEnquireLinkResp (line 11) | func TestEnquireLinkResp(t *testing.T) {
FILE: pdu/EnquireLink_test.go
function TestEnquireLink (line 11) | func TestEnquireLink(t *testing.T) {
FILE: pdu/GenericNack.go
type GenericNack (line 17) | type GenericNack struct
method CanResponse (line 31) | func (c *GenericNack) CanResponse() bool {
method GetResponse (line 36) | func (c *GenericNack) GetResponse() PDU {
method Marshal (line 41) | func (c *GenericNack) Marshal(b *ByteBuffer) {
method Unmarshal (line 46) | func (c *GenericNack) Unmarshal(b *ByteBuffer) error {
function NewGenericNack (line 22) | func NewGenericNack() PDU {
FILE: pdu/GenericNack_test.go
function TestGNack (line 10) | func TestGNack(t *testing.T) {
FILE: pdu/Outbind.go
type Outbind (line 8) | type Outbind struct
method CanResponse (line 24) | func (c *Outbind) CanResponse() bool {
method GetResponse (line 29) | func (c *Outbind) GetResponse() PDU {
method Marshal (line 34) | func (c *Outbind) Marshal(b *ByteBuffer) {
method Unmarshal (line 44) | func (c *Outbind) Unmarshal(b *ByteBuffer) error {
function NewOutbind (line 15) | func NewOutbind() PDU {
FILE: pdu/Outbind_test.go
function TestOutbind (line 11) | func TestOutbind(t *testing.T) {
FILE: pdu/PDU.go
type PDU (line 11) | type PDU interface
type base (line 49) | type base struct
method GetHeader (line 61) | func (c *base) GetHeader() Header {
method unmarshal (line 65) | func (c *base) unmarshal(b *ByteBuffer, bodyReader func(*ByteBuffer) e...
method unmarshalOptionalParam (line 107) | func (c *base) unmarshalOptionalParam(optParam []byte) (err error) {
method marshal (line 121) | func (c *base) marshal(b *ByteBuffer, bodyWriter func(*ByteBuffer)) {
method RegisterOptionalParam (line 143) | func (c *base) RegisterOptionalParam(tlv Field) {
method IsOk (line 148) | func (c *base) IsOk() bool {
method IsGNack (line 153) | func (c *base) IsGNack() bool {
function newBase (line 54) | func newBase() (v base) {
function Parse (line 158) | func Parse(r io.Reader) (pdu PDU, err error) {
FILE: pdu/PDUFactory.go
type pduGenerator (line 8) | type pduGenerator
function CreatePDUFromCmdID (line 41) | func CreatePDUFromCmdID(cmdID data.CommandIDType) (PDU, error) {
FILE: pdu/PDUFactory_test.go
function TestInvalidCmdID (line 9) | func TestInvalidCmdID(t *testing.T) {
FILE: pdu/PDUHeader.go
function nextSequenceNumber (line 10) | func nextSequenceNumber(s *int32) (v int32) {
type Header (line 22) | type Header struct
method Unmarshal (line 39) | func (c *Header) Unmarshal(b *ByteBuffer) (err error) {
method AssignSequenceNumber (line 58) | func (c *Header) AssignSequenceNumber() {
method ResetSequenceNumber (line 63) | func (c *Header) ResetSequenceNumber() {
method GetSequenceNumber (line 68) | func (c *Header) GetSequenceNumber() int32 {
method SetSequenceNumber (line 73) | func (c *Header) SetSequenceNumber(v int32) {
method Marshal (line 78) | func (c *Header) Marshal(b *ByteBuffer) {
function ParseHeader (line 30) | func ParseHeader(v [16]byte) (h Header) {
FILE: pdu/PDUHeader_test.go
function TestNextSeq (line 10) | func TestNextSeq(t *testing.T) {
FILE: pdu/PDU_test.go
function TestParsePDU (line 11) | func TestParsePDU(t *testing.T) {
FILE: pdu/QuerySM.go
type QuerySM (line 11) | type QuerySM struct
method CanResponse (line 27) | func (c *QuerySM) CanResponse() bool {
method GetResponse (line 32) | func (c *QuerySM) GetResponse() PDU {
method Marshal (line 37) | func (c *QuerySM) Marshal(b *ByteBuffer) {
method Unmarshal (line 47) | func (c *QuerySM) Unmarshal(b *ByteBuffer) error {
function NewQuerySM (line 18) | func NewQuerySM() PDU {
FILE: pdu/QuerySMResp.go
type QuerySMResp (line 8) | type QuerySMResp struct
method CanResponse (line 38) | func (c *QuerySMResp) CanResponse() bool {
method GetResponse (line 43) | func (c *QuerySMResp) GetResponse() PDU {
method Marshal (line 48) | func (c *QuerySMResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 60) | func (c *QuerySMResp) Unmarshal(b *ByteBuffer) error {
function NewQuerySMResp (line 17) | func NewQuerySMResp() PDU {
function NewQuerySMRespFromReq (line 29) | func NewQuerySMRespFromReq(req *QuerySM) PDU {
FILE: pdu/QuerySMResp_test.go
function TestQuerySMResp (line 11) | func TestQuerySMResp(t *testing.T) {
FILE: pdu/QuerySM_test.go
function TestQuerySM (line 11) | func TestQuerySM(t *testing.T) {
FILE: pdu/ReplaceSM.go
type ReplaceSM (line 11) | type ReplaceSM struct
method CanResponse (line 38) | func (c *ReplaceSM) CanResponse() bool {
method GetResponse (line 43) | func (c *ReplaceSM) GetResponse() PDU {
method Marshal (line 48) | func (c *ReplaceSM) Marshal(b *ByteBuffer) {
method Unmarshal (line 62) | func (c *ReplaceSM) Unmarshal(b *ByteBuffer) error {
function NewReplaceSM (line 22) | func NewReplaceSM() PDU {
FILE: pdu/ReplaceSMResp.go
type ReplaceSMResp (line 8) | type ReplaceSMResp struct
method CanResponse (line 31) | func (c *ReplaceSMResp) CanResponse() bool {
method GetResponse (line 36) | func (c *ReplaceSMResp) GetResponse() PDU {
method Marshal (line 41) | func (c *ReplaceSMResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 46) | func (c *ReplaceSMResp) Unmarshal(b *ByteBuffer) error {
function NewReplaceSMResp (line 13) | func NewReplaceSMResp() PDU {
function NewReplaceSMRespFromReq (line 22) | func NewReplaceSMRespFromReq(req *ReplaceSM) PDU {
FILE: pdu/ReplaceSMResp_test.go
function TestReplaceSMResp (line 11) | func TestReplaceSMResp(t *testing.T) {
FILE: pdu/ReplaceSM_test.go
function TestReplaceSM (line 11) | func TestReplaceSM(t *testing.T) {
FILE: pdu/ShortMessage.go
type ShortMessage (line 13) | type ShortMessage struct
method SetMessageWithEncoding (line 61) | func (c *ShortMessage) SetMessageWithEncoding(message string, enc data...
method SetLongMessageWithEnc (line 86) | func (c *ShortMessage) SetLongMessageWithEnc(message string, enc data....
method UDH (line 93) | func (c *ShortMessage) UDH() UDH {
method SetUDH (line 99) | func (c *ShortMessage) SetUDH(udh UDH) {
method SetMessageDataWithEncoding (line 104) | func (c *ShortMessage) SetMessageDataWithEncoding(d []byte, enc data.E...
method GetMessageData (line 115) | func (c *ShortMessage) GetMessageData() (d []byte, err error) {
method GetMessage (line 120) | func (c *ShortMessage) GetMessage() (st string, err error) {
method GetMessageWithEncoding (line 130) | func (c *ShortMessage) GetMessageWithEncoding(enc data.Encoding) (st s...
method split (line 142) | func (c *ShortMessage) split() (multiSM []*ShortMessage, err error) {
method Marshal (line 195) | func (c *ShortMessage) Marshal(b *ByteBuffer) {
method Unmarshal (line 236) | func (c *ShortMessage) Unmarshal(b *ByteBuffer, udhi bool) (err error) {
method Encoding (line 282) | func (c *ShortMessage) Encoding() data.Encoding {
function NewShortMessage (line 23) | func NewShortMessage(message string) (s ShortMessage, err error) {
function NewShortMessageWithEncoding (line 29) | func NewShortMessageWithEncoding(message string, enc data.Encoding) (s S...
function NewBinaryShortMessage (line 35) | func NewBinaryShortMessage(messageData []byte) (s ShortMessage, err erro...
function NewBinaryShortMessageWithEncoding (line 41) | func NewBinaryShortMessageWithEncoding(messageData []byte, enc data.Enco...
function NewLongMessage (line 47) | func NewLongMessage(message string) (s []*ShortMessage, err error) {
function NewLongMessageWithEncoding (line 52) | func NewLongMessageWithEncoding(message string, enc data.Encoding) (s []...
function getRefNum (line 287) | func getRefNum() uint32 {
FILE: pdu/ShortMessage_test.go
type customEncoder (line 12) | type customEncoder struct
method Encode (line 14) | func (*customEncoder) Encode(str string) ([]byte, error) {
method Decode (line 18) | func (*customEncoder) Decode(data []byte) (string, error) {
function TestShortMessage (line 22) | func TestShortMessage(t *testing.T) {
FILE: pdu/SubmitMulti.go
type SubmitMulti (line 10) | type SubmitMulti struct
method CanResponse (line 47) | func (c *SubmitMulti) CanResponse() bool {
method GetResponse (line 52) | func (c *SubmitMulti) GetResponse() PDU {
method Marshal (line 57) | func (c *SubmitMulti) Marshal(b *ByteBuffer) {
method Unmarshal (line 76) | func (c *SubmitMulti) Unmarshal(b *ByteBuffer) error {
function NewSubmitMulti (line 26) | func NewSubmitMulti() PDU {
FILE: pdu/SubmitMultiResp.go
type SubmitMultiResp (line 8) | type SubmitMultiResp struct
method CanResponse (line 35) | func (c *SubmitMultiResp) CanResponse() bool {
method GetResponse (line 40) | func (c *SubmitMultiResp) GetResponse() PDU {
method Marshal (line 45) | func (c *SubmitMultiResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 55) | func (c *SubmitMultiResp) Unmarshal(b *ByteBuffer) error {
function NewSubmitMultiResp (line 15) | func NewSubmitMultiResp() PDU {
function NewSubmitMultiRespFromReq (line 26) | func NewSubmitMultiRespFromReq(req *SubmitMulti) PDU {
FILE: pdu/SubmitMultiResp_test.go
function TestSubmitMultiResp (line 11) | func TestSubmitMultiResp(t *testing.T) {
FILE: pdu/SubmitMulti_test.go
function TestSubmitMulti (line 11) | func TestSubmitMulti(t *testing.T) {
function TestSubmitMultiwithUDH (line 61) | func TestSubmitMultiwithUDH(t *testing.T) {
FILE: pdu/SubmitSM.go
type SubmitSM (line 10) | type SubmitSM struct
method ShouldSplit (line 47) | func (c *SubmitSM) ShouldSplit() bool {
method CanResponse (line 53) | func (c *SubmitSM) CanResponse() bool {
method GetResponse (line 58) | func (c *SubmitSM) GetResponse() PDU {
method Split (line 66) | func (c *SubmitSM) Split() (multiSubSM []*SubmitSM, err error) {
method Marshal (line 99) | func (c *SubmitSM) Marshal(b *ByteBuffer) {
method Unmarshal (line 118) | func (c *SubmitSM) Unmarshal(b *ByteBuffer) error {
function NewSubmitSM (line 26) | func NewSubmitSM() PDU {
FILE: pdu/SubmitSMResp.go
type SubmitSMResp (line 10) | type SubmitSMResp struct
method CanResponse (line 35) | func (c *SubmitSMResp) CanResponse() bool {
method GetResponse (line 40) | func (c *SubmitSMResp) GetResponse() PDU {
method Marshal (line 45) | func (c *SubmitSMResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 54) | func (c *SubmitSMResp) Unmarshal(b *ByteBuffer) error {
function NewSubmitSMResp (line 16) | func NewSubmitSMResp() PDU {
function NewSubmitSMRespFromReq (line 26) | func NewSubmitSMRespFromReq(req *SubmitSM) PDU {
FILE: pdu/SubmitSMResp_test.go
function TestSubmitSMResp (line 11) | func TestSubmitSMResp(t *testing.T) {
FILE: pdu/SubmitSM_test.go
function TestSubmitSM (line 11) | func TestSubmitSM(t *testing.T) {
FILE: pdu/TLV.go
type Tag (line 10) | type Tag
method Hex (line 13) | func (t Tag) Hex() string {
constant TagDestAddrSubunit (line 21) | TagDestAddrSubunit Tag = 0x0005
constant TagDestNetworkType (line 22) | TagDestNetworkType Tag = 0x0006
constant TagDestBearerType (line 23) | TagDestBearerType Tag = 0x0007
constant TagDestTelematicsID (line 24) | TagDestTelematicsID Tag = 0x0008
constant TagSourceAddrSubunit (line 25) | TagSourceAddrSubunit Tag = 0x000D
constant TagSourceNetworkType (line 26) | TagSourceNetworkType Tag = 0x000E
constant TagSourceBearerType (line 27) | TagSourceBearerType Tag = 0x000F
constant TagSourceTelematicsID (line 28) | TagSourceTelematicsID Tag = 0x0010
constant TagQosTimeToLive (line 29) | TagQosTimeToLive Tag = 0x0017
constant TagPayloadType (line 30) | TagPayloadType Tag = 0x0019
constant TagAdditionalStatusInfoText (line 31) | TagAdditionalStatusInfoText Tag = 0x001D
constant TagReceiptedMessageID (line 32) | TagReceiptedMessageID Tag = 0x001E
constant TagMsMsgWaitFacilities (line 33) | TagMsMsgWaitFacilities Tag = 0x0030
constant TagPrivacyIndicator (line 34) | TagPrivacyIndicator Tag = 0x0201
constant TagSourceSubaddress (line 35) | TagSourceSubaddress Tag = 0x0202
constant TagDestSubaddress (line 36) | TagDestSubaddress Tag = 0x0203
constant TagUserMessageReference (line 37) | TagUserMessageReference Tag = 0x0204
constant TagUserResponseCode (line 38) | TagUserResponseCode Tag = 0x0205
constant TagSourcePort (line 39) | TagSourcePort Tag = 0x020A
constant TagDestinationPort (line 40) | TagDestinationPort Tag = 0x020B
constant TagSarMsgRefNum (line 41) | TagSarMsgRefNum Tag = 0x020C
constant TagLanguageIndicator (line 42) | TagLanguageIndicator Tag = 0x020D
constant TagSarTotalSegments (line 43) | TagSarTotalSegments Tag = 0x020E
constant TagSarSegmentSeqnum (line 44) | TagSarSegmentSeqnum Tag = 0x020F
constant TagCallbackNumPresInd (line 45) | TagCallbackNumPresInd Tag = 0x0302
constant TagCallbackNumAtag (line 46) | TagCallbackNumAtag Tag = 0x0303
constant TagNumberOfMessages (line 47) | TagNumberOfMessages Tag = 0x0304
constant TagCallbackNum (line 48) | TagCallbackNum Tag = 0x0381
constant TagDpfResult (line 49) | TagDpfResult Tag = 0x0420
constant TagSetDpf (line 50) | TagSetDpf Tag = 0x0421
constant TagMsAvailabilityStatus (line 51) | TagMsAvailabilityStatus Tag = 0x0422
constant TagNetworkErrorCode (line 52) | TagNetworkErrorCode Tag = 0x0423
constant TagMessagePayload (line 53) | TagMessagePayload Tag = 0x0424
constant TagDeliveryFailureReason (line 54) | TagDeliveryFailureReason Tag = 0x0425
constant TagMoreMessagesToSend (line 55) | TagMoreMessagesToSend Tag = 0x0426
constant TagMessageStateOption (line 56) | TagMessageStateOption Tag = 0x0427
constant TagUssdServiceOp (line 57) | TagUssdServiceOp Tag = 0x0501
constant TagDisplayTime (line 58) | TagDisplayTime Tag = 0x1201
constant TagSmsSignal (line 59) | TagSmsSignal Tag = 0x1203
constant TagMsValidity (line 60) | TagMsValidity Tag = 0x1204
constant TagAlertOnMessageDelivery (line 61) | TagAlertOnMessageDelivery Tag = 0x130C
constant TagItsReplyType (line 62) | TagItsReplyType Tag = 0x1380
constant TagItsSessionInfo (line 63) | TagItsSessionInfo Tag = 0x1383
type Field (line 67) | type Field struct
method String (line 73) | func (t *Field) String() string {
method Marshal (line 81) | func (t *Field) Marshal(w *ByteBuffer) {
method Unmarshal (line 92) | func (t *Field) Unmarshal(b *ByteBuffer) (err error) {
FILE: pdu/UDH.go
type UDH (line 16) | type UDH
method UDHL (line 21) | func (u UDH) UDHL() (l int) {
method MarshalBinary (line 50) | func (u UDH) MarshalBinary() (b []byte, err error) {
method UnmarshalBinary (line 101) | func (u *UDH) UnmarshalBinary(src []byte) (int, error) {
method FindInfoElement (line 142) | func (u UDH) FindInfoElement(id byte) (ie *InfoElement, found bool) {
method GetConcatInfo (line 152) | func (u UDH) GetConcatInfo() (totalParts, partNum, mref byte, found bo...
type InfoElement (line 171) | type InfoElement struct
method UnmarshalBinary (line 189) | func (ie *InfoElement) UnmarshalBinary(src []byte) (int, error) {
function NewIEConcatMessage (line 178) | func NewIEConcatMessage(totalParts, partNum, mref byte) InfoElement {
FILE: pdu/UDH_test.go
function TestUserDataHeader (line 9) | func TestUserDataHeader(t *testing.T) {
FILE: pdu/Unbind.go
type Unbind (line 10) | type Unbind struct
method CanResponse (line 24) | func (c *Unbind) CanResponse() bool {
method GetResponse (line 29) | func (c *Unbind) GetResponse() PDU {
method Marshal (line 34) | func (c *Unbind) Marshal(b *ByteBuffer) {
method Unmarshal (line 39) | func (c *Unbind) Unmarshal(b *ByteBuffer) error {
function NewUnbind (line 15) | func NewUnbind() PDU {
FILE: pdu/UnbindResp.go
type UnbindResp (line 8) | type UnbindResp struct
method CanResponse (line 31) | func (c *UnbindResp) CanResponse() bool {
method GetResponse (line 36) | func (c *UnbindResp) GetResponse() PDU {
method Marshal (line 41) | func (c *UnbindResp) Marshal(b *ByteBuffer) {
method Unmarshal (line 46) | func (c *UnbindResp) Unmarshal(b *ByteBuffer) error {
function NewUnbindResp (line 13) | func NewUnbindResp() PDU {
function NewUnbindRespFromReq (line 22) | func NewUnbindRespFromReq(req *Unbind) PDU {
FILE: pdu/UnbindResp_test.go
function TestUnbindResp (line 11) | func TestUnbindResp(t *testing.T) {
FILE: pdu/Unbind_test.go
function TestUnbind (line 11) | func TestUnbind(t *testing.T) {
FILE: pdu/UnsuccessSME.go
type UnsuccessSME (line 8) | type UnsuccessSME struct
method Unmarshal (line 40) | func (c *UnsuccessSME) Unmarshal(b *ByteBuffer) (err error) {
method Marshal (line 52) | func (c *UnsuccessSME) Marshal(b *ByteBuffer) {
method SetErrorStatusCode (line 58) | func (c *UnsuccessSME) SetErrorStatusCode(v data.CommandStatusType) {
method ErrorStatusCode (line 63) | func (c *UnsuccessSME) ErrorStatusCode() data.CommandStatusType {
function NewUnsuccessSME (line 14) | func NewUnsuccessSME() (c UnsuccessSME) {
function NewUnsuccessSMEWithAddr (line 23) | func NewUnsuccessSMEWithAddr(addr string, status data.CommandStatusType)...
function NewUnsuccessSMEWithTonNpi (line 32) | func NewUnsuccessSMEWithTonNpi(ton, npi byte, status data.CommandStatusT...
type UnsuccessSMEs (line 68) | type UnsuccessSMEs struct
method Add (line 79) | func (c *UnsuccessSMEs) Add(us ...UnsuccessSME) {
method Get (line 84) | func (c *UnsuccessSMEs) Get() []UnsuccessSME {
method Unmarshal (line 89) | func (c *UnsuccessSMEs) Unmarshal(b *ByteBuffer) (err error) {
method Marshal (line 105) | func (c *UnsuccessSMEs) Marshal(b *ByteBuffer) {
function NewUnsuccessSMEs (line 73) | func NewUnsuccessSMEs() (u UnsuccessSMEs) {
FILE: pdu/UnsuccessSME_test.go
function TestMalformUSME (line 9) | func TestMalformUSME(t *testing.T) {
FILE: pdu/helper_test.go
function fromHex (line 13) | func fromHex(h string) (v []byte) {
function toHex (line 22) | func toHex(v []byte) (h string) {
function validate (line 27) | func validate(t *testing.T, p PDU, hexValue string, expectCommandID data...
function expectAfterParse (line 35) | func expectAfterParse(t *testing.T, b *ByteBuffer, expect PDU, expectCom...
FILE: pkg.go
type Transceiver (line 11) | type Transceiver interface
type Transmitter (line 18) | type Transmitter interface
type Receiver (line 25) | type Receiver interface
type Settings (line 31) | type Settings struct
type WindowedRequestTracking (line 89) | type WindowedRequestTracking struct
FILE: receivable.go
type receivable (line 12) | type receivable struct
method close (line 33) | func (t *receivable) close(state State) (err error) {
method closing (line 57) | func (t *receivable) closing(state State) {
method start (line 63) | func (t *receivable) start() {
method loop (line 71) | func (t *receivable) loop() {
method handleWindowPdu (line 112) | func (t *receivable) handleWindowPdu(p pdu.PDU) (closing bool) {
method handleAllPdu (line 176) | func (t *receivable) handleAllPdu(p pdu.PDU) (closing bool) {
method handleOrClose (line 188) | func (t *receivable) handleOrClose(p pdu.PDU) (closing bool) {
function newReceivable (line 22) | func newReceivable(conn *Connection, settings Settings, requestStore Req...
FILE: receivable_test.go
function TestReceive (line 14) | func TestReceive(t *testing.T) {
function Test_receivable_handleAllPdu (line 49) | func Test_receivable_handleAllPdu(t1 *testing.T) {
function receivableHandleAllPDU (line 121) | func receivableHandleAllPDU(t1 *testing.T) func(pdu.PDU) (pdu.PDU, bool) {
function Test_receivable_handleOrClose (line 156) | func Test_receivable_handleOrClose(t1 *testing.T) {
function Test_receivable_handleWindowPdu (line 212) | func Test_receivable_handleWindowPdu(t1 *testing.T) {
FILE: request_store.go
type Request (line 14) | type Request struct
type Response (line 20) | type Response struct
type RequestStore (line 26) | type RequestStore interface
type DefaultStore (line 35) | type DefaultStore struct
method Set (line 45) | func (s DefaultStore) Set(ctx context.Context, request Request) error {
method Get (line 56) | func (s DefaultStore) Get(ctx context.Context, sequenceNumber int32) (...
method List (line 66) | func (s DefaultStore) List(ctx context.Context) []Request {
method Delete (line 75) | func (s DefaultStore) Delete(ctx context.Context, sequenceNumber int32...
method Clear (line 85) | func (s DefaultStore) Clear(ctx context.Context) error {
method Length (line 95) | func (s DefaultStore) Length(ctx context.Context) (int, error) {
function NewDefaultStore (line 39) | func NewDefaultStore() DefaultStore {
FILE: session.go
type Session (line 19) | type Session struct
method bound (line 110) | func (s *Session) bound() *transceivable {
method Transmitter (line 116) | func (s *Session) Transmitter() Transmitter {
method Receiver (line 121) | func (s *Session) Receiver() Receiver {
method Transceiver (line 126) | func (s *Session) Transceiver() Transceiver {
method GetWindowSize (line 130) | func (s *Session) GetWindowSize() (int, error) {
method Close (line 142) | func (s *Session) Close() (err error) {
method close (line 149) | func (s *Session) close() (err error) {
method rebind (line 156) | func (s *Session) rebind() {
type SessionOption (line 34) | type SessionOption
function NewSession (line 44) | func NewSession(c Connector, settings Settings, rebindingInterval time.D...
function WithRequestStore (line 104) | func WithRequestStore(store RequestStore) SessionOption {
FILE: session_test.go
function TestInvalidSessionSettings (line 10) | func TestInvalidSessionSettings(t *testing.T) {
function TestGetWindowSize (line 27) | func TestGetWindowSize(t *testing.T) {
FILE: state.go
constant Alive (line 4) | Alive int32 = iota
constant Closed (line 5) | Closed
type State (line 9) | type State
method String (line 35) | func (s *State) String() string {
constant ExplicitClosing (line 14) | ExplicitClosing State = iota
constant StoppingProcessOnly (line 17) | StoppingProcessOnly
constant InvalidStreaming (line 24) | InvalidStreaming
constant ConnectionIssue (line 28) | ConnectionIssue
constant UnbindClosing (line 31) | UnbindClosing
FILE: state_test.go
function TestState_String (line 8) | func TestState_String(t *testing.T) {
FILE: transceivable.go
type transceivable (line 16) | type transceivable struct
method start (line 98) | func (t *transceivable) start() {
method SystemID (line 112) | func (t *transceivable) SystemID() string {
method Close (line 117) | func (t *transceivable) Close() (err error) {
method Submit (line 122) | func (t *transceivable) Submit(p pdu.PDU) error {
method GetWindowSize (line 126) | func (t *transceivable) GetWindowSize() (int, error) {
method windowCleanup (line 136) | func (t *transceivable) windowCleanup() {
method closing (line 160) | func (t *transceivable) closing(state State) (err error) {
type TransceivableOption (line 29) | type TransceivableOption
function newTransceivable (line 31) | func newTransceivable(conn *Connection, settings Settings, requestStore ...
FILE: transceivable_test.go
function handlePDU (line 19) | func handlePDU(t *testing.T) func(pdu.PDU, bool) {
function transceivableHandleAllPDU (line 50) | func transceivableHandleAllPDU(t *testing.T) func(pdu.PDU) (pdu.PDU, boo...
function TestTRXSubmitSM (line 84) | func TestTRXSubmitSM(t *testing.T) {
function TestTRXSubmitSM_with_OnAllPDU (line 141) | func TestTRXSubmitSM_with_OnAllPDU(t *testing.T) {
function newSubmitSM (line 198) | func newSubmitSM(systemID string) *pdu.SubmitSM {
function TestTRXSubmitSM_with_WindowConfig (line 222) | func TestTRXSubmitSM_with_WindowConfig(t *testing.T) {
function TestTRXSubmitSM_with_WindowConfig_and_AutoRespond (line 288) | func TestTRXSubmitSM_with_WindowConfig_and_AutoRespond(t *testing.T) {
function handleReceivedPduRequest (line 354) | func handleReceivedPduRequest(t *testing.T) func(pdu.PDU) (pdu.PDU, bool) {
function handleExpectedPduResponse (line 384) | func handleExpectedPduResponse(t *testing.T) func(response Response) {
function Test_newTransceivable (line 402) | func Test_newTransceivable(t *testing.T) {
FILE: transmittable.go
type transmittable (line 21) | type transmittable struct
method close (line 47) | func (t *transmittable) close(state State) (err error) {
method closing (line 99) | func (t *transmittable) closing(state State) {
method Submit (line 106) | func (t *transmittable) Submit(p pdu.PDU) (err error) {
method start (line 119) | func (t *transmittable) start() {
method drain (line 134) | func (t *transmittable) drain() {
method loop (line 139) | func (t *transmittable) loop() {
method loopWithEnquireLink (line 152) | func (t *transmittable) loopWithEnquireLink() {
method check (line 184) | func (t *transmittable) check(p pdu.PDU, n int, err error) (closing bo...
method write (line 213) | func (t *transmittable) write(p pdu.PDU) (n int, err error) {
function newTransmittable (line 34) | func newTransmittable(conn *Connection, settings Settings, requestStore ...
function isAllowPDU (line 252) | func isAllowPDU(p pdu.PDU) bool {
FILE: transmittable_test.go
function TestTransmit (line 16) | func TestTransmit(t *testing.T) {
function TestConcurrentSubmitClose (line 122) | func TestConcurrentSubmitClose(t *testing.T) {
FILE: types.go
type PDUCallback (line 8) | type PDUCallback
type AllPDUCallback (line 14) | type AllPDUCallback
type PDUErrorCallback (line 17) | type PDUErrorCallback
type ErrorCallback (line 20) | type ErrorCallback
type ClosedCallback (line 23) | type ClosedCallback
type RebindCallback (line 26) | type RebindCallback
Condensed preview — 115 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (387K chars).
[
{
"path": ".github/dependabot.yml",
"chars": 504,
"preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
},
{
"path": ".github/workflows/go.yml",
"chars": 1068,
"preview": "name: Build\non: [push, pull_request]\njobs:\n build:\n name: Build\n runs-on: ubuntu-latest\n steps:\n - name: "
},
{
"path": ".gitignore",
"chars": 36,
"preview": ".idea/\nvendor/\n*DS_Store\n*.out\nsmsc\n"
},
{
"path": ".golangci.yml",
"chars": 4064,
"preview": "version: \"2\"\nlinters:\n # Default set of linters.\n # The value can be:\n # - `standard`: https://golangci-lint.run/docs"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 2709,
"preview": "# gosmpp\n\n[]()\n[\n\nvar (\n\t// "
},
{
"path": "connect_test.go",
"chars": 2308,
"preview": "package gosmpp\n\nimport (\n\t\"github.com/linxGnu/gosmpp/pdu\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/requi"
},
{
"path": "connection.go",
"chars": 3668,
"preview": "package gosmpp\n\nimport (\n\t\"bufio\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp/pdu\"\n)\n\n// Connection wraps over net.Conn "
},
{
"path": "connection_test.go",
"chars": 520,
"preview": "package gosmpp\n\nimport (\n\t\"net\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestConnection(t *tes"
},
{
"path": "data/7bit.go",
"chars": 13893,
"preview": "package data\n\n// Source code in this file is copied from: https://github.com/fiorix/go-smpp/master/smpp/encoding/gsm7.go"
},
{
"path": "data/7bit_test.go",
"chars": 9604,
"preview": "package data\n\n// Source code in this file is copied from: https://github.com/fiorix\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"re"
},
{
"path": "data/codings.go",
"chars": 10540,
"preview": "package data\n\nimport (\n\t\"golang.org/x/text/encoding\"\n\t\"golang.org/x/text/encoding/charmap\"\n\t\"golang.org/x/text/encoding/"
},
{
"path": "data/codings_test.go",
"chars": 14360,
"preview": "package data\n\nimport (\n\t\"encoding/hex\"\n\t\"log\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc fromHex(h strin"
},
{
"path": "data/header_data.go",
"chars": 10181,
"preview": "//go:generate stringer -type=CommandStatusType,CommandIDType -output header_data_string.go\n\npackage data\n\n// CommandStat"
},
{
"path": "data/header_data_string.go",
"chars": 18199,
"preview": "// Code generated by \"stringer -type=CommandStatusType,CommandIDType -output header_data_string.go\"; DO NOT EDIT.\n\npacka"
},
{
"path": "data/other_codings.go",
"chars": 1717,
"preview": "package data\n\nimport (\n\t\"golang.org/x/text/encoding/unicode\"\n)\n\nvar (\n\t// UTF16BEM is UTF-16 Big Endian with BOM (byte o"
},
{
"path": "data/pkg.go",
"chars": 11007,
"preview": "package data\n\nimport (\n\t\"fmt\"\n\t\"sync/atomic\"\n)\n\n//nolint\nconst (\n\tSM_CONNID_LEN = 16\n\tSM_MSG_LEN = 254\n"
},
{
"path": "data/pkg_test.go",
"chars": 282,
"preview": "package data\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestDefaultNpi(t *testing.T) {\n\tSetDef"
},
{
"path": "data/utils.go",
"chars": 389,
"preview": "package data\n\nimport \"unicode\"\n\n// FindEncoding returns suitable encoding for a string.\n// If string is ascii, then GSM7"
},
{
"path": "data/utils_test.go",
"chars": 361,
"preview": "package data\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestFindEncoding(t *testing.T) {\n\trequ"
},
{
"path": "errors/pkg.go",
"chars": 1237,
"preview": "package errors\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// SmppErr indicates smpp error(s), compatible wit"
},
{
"path": "errors/pkg_test.go",
"chars": 201,
"preview": "package errors\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestErr(t *testing.T) {\n\t"
},
{
"path": "example/smsc_simulator/smsc.cpp",
"chars": 49999,
"preview": "//\n// smscsimulator.cpp\n// SMPPLib\n//\n// Created by Mark Hay on 12/05/2019.\n// Copyright © 2019 Melrose Labs. All ri"
},
{
"path": "example/transceiver_with_auto_response/main.go",
"chars": 3178,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp\"\n\t\"github.com/linxGnu/gosmp"
},
{
"path": "example/transceiver_with_manual_response/main.go",
"chars": 2676,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp\"\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"g"
},
{
"path": "example/transeiver_with_custom_store/CustomStore.go",
"chars": 3575,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/gob\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/allegro/big"
},
{
"path": "example/transeiver_with_custom_store/main.go",
"chars": 4829,
"preview": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp\"\n\t\"github.com/linxGnu/gosmpp"
},
{
"path": "example/transeiver_with_request_window_and_custom_submitSm/CustomSubmitSM.go",
"chars": 494,
"preview": "package main\n\nimport (\n\t\"math/rand\"\n\t\"strconv\"\n\n\t\"github.com/linxGnu/gosmpp/pdu\"\n)\n\n// CustomSubmitSM by embedding the P"
},
{
"path": "example/transeiver_with_request_window_and_custom_submitSm/main.go",
"chars": 4921,
"preview": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp\"\n\t\"github.com/linxGnu/gosmpp"
},
{
"path": "go.mod",
"chars": 405,
"preview": "module github.com/linxGnu/gosmpp\n\ngo 1.24.0\n\nrequire (\n\tgithub.com/allegro/bigcache/v3 v3.1.0\n\tgithub.com/orcaman/concur"
},
{
"path": "go.sum",
"chars": 1615,
"preview": "github.com/allegro/bigcache/v3 v3.1.0 h1:H2Vp8VOvxcrB91o86fUSVJFqeuz8kpyyB02eH3bSzwk=\ngithub.com/allegro/bigcache/v3 v3."
},
{
"path": "pdu/Address.go",
"chars": 2026,
"preview": "package pdu\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// Address smpp address of src and dst.\ntype Address "
},
{
"path": "pdu/AddressRange.go",
"chars": 1389,
"preview": "package pdu\n\nimport \"github.com/linxGnu/gosmpp/data\"\n\n// AddressRange smpp address range of src and dst.\ntype AddressRan"
},
{
"path": "pdu/AddressRange_test.go",
"chars": 1256,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestAddressRange(t *testing.T) {\n\tt.Run"
},
{
"path": "pdu/Address_test.go",
"chars": 1657,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestAddress(t *testing.T) {\n\tt.Run(\"new"
},
{
"path": "pdu/AlertNotification.go",
"chars": 1241,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// AlertNotification PDU is sent by the SMSC to the ESME, whe"
},
{
"path": "pdu/AlertNotification_test.go",
"chars": 531,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/BindRequest.go",
"chars": 2517,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// BindingType indicates type of binding.\ntype BindingType by"
},
{
"path": "pdu/BindRequest_test.go",
"chars": 2057,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/BindResponse.go",
"chars": 1750,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// BindResp PDU.\ntype BindResp struct {\n\tbase\n\tSystemID strin"
},
{
"path": "pdu/BindResponse_test.go",
"chars": 1173,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/Buffer.go",
"chars": 2805,
"preview": "package pdu\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\nconst (\n\t// SizeByte is s"
},
{
"path": "pdu/Buffer_test.go",
"chars": 323,
"preview": "package pdu\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)"
},
{
"path": "pdu/CancelSM.go",
"chars": 1628,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// CancelSM PDU is issued by the ESME to cancel one or more p"
},
{
"path": "pdu/CancelSMResp.go",
"chars": 930,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// CancelSMResp PDU.\ntype CancelSMResp struct {\n\tbase\n}\n\n// N"
},
{
"path": "pdu/CancelSMResp_test.go",
"chars": 412,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/CancelSM_test.go",
"chars": 674,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/DataSM.go",
"chars": 1831,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// DataSM PDU is used to transfer data between the SMSC and t"
},
{
"path": "pdu/DataSMResp.go",
"chars": 1115,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// DataSMResp PDU.\ntype DataSMResp struct {\n\tbase\n\tMessageID "
},
{
"path": "pdu/DataSMResp_test.go",
"chars": 442,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/DataSM_test.go",
"chars": 1112,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/DeliverSM.go",
"chars": 3012,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// DeliverSM PDU is issued by the SMSC to send a message to a"
},
{
"path": "pdu/DeliverSMResp.go",
"chars": 1174,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// DeliverSMResp PDU.\ntype DeliverSMResp struct {\n\tbase\n\tMess"
},
{
"path": "pdu/DeliverSMResp_test.go",
"chars": 460,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/DeliverSM_test.go",
"chars": 1869,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/DestinationAddress.go",
"chars": 3203,
"preview": "package pdu\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// DestinationAddress represents Address or Distribut"
},
{
"path": "pdu/DestinationAddress_test.go",
"chars": 1354,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/DistributionList.go",
"chars": 970,
"preview": "package pdu\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// DistributionList represents group of contacts.\ntyp"
},
{
"path": "pdu/DistributionList_test.go",
"chars": 201,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestDistributionList(t *testing.T) {\n\t_"
},
{
"path": "pdu/EnquireLink.go",
"chars": 1156,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// EnquireLink PDU. This message can be sent by either the ES"
},
{
"path": "pdu/EnquireLinkResp.go",
"chars": 981,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// EnquireLinkResp PDU.\ntype EnquireLinkResp struct {\n\tbase\n}"
},
{
"path": "pdu/EnquireLinkResp_test.go",
"chars": 430,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/EnquireLink_test.go",
"chars": 426,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/GenericNack.go",
"chars": 1301,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// GenericNack PDU is a generic negative acknowledgement to a"
},
{
"path": "pdu/GenericNack_test.go",
"chars": 383,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestG"
},
{
"path": "pdu/Outbind.go",
"chars": 1060,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// Outbind PDU is used by the SMSC to signal an ESME to origi"
},
{
"path": "pdu/Outbind_test.go",
"chars": 463,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/PDU.go",
"chars": 3877,
"preview": "package pdu\n\nimport (\n\t\"io\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"github.com/linxGnu/gosmpp/errors\"\n)\n\n// PDU represents "
},
{
"path": "pdu/PDUFactory.go",
"chars": 1621,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"github.com/linxGnu/gosmpp/errors\"\n)\n\ntype pduGenerator func() "
},
{
"path": "pdu/PDUFactory_test.go",
"chars": 194,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestInvalidCmdID(t *testing.T) {\n\tv, er"
},
{
"path": "pdu/PDUHeader.go",
"chars": 2087,
"preview": "package pdu\n\nimport (\n\t\"encoding/binary\"\n\t\"sync/atomic\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\nfunc nextSequenceNumber(s "
},
{
"path": "pdu/PDUHeader_test.go",
"chars": 199,
"preview": "package pdu\n\nimport (\n\t\"math\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestNextSeq(t *testing.T) {\n\tva"
},
{
"path": "pdu/PDU_test.go",
"chars": 1516,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/errors\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Te"
},
{
"path": "pdu/QuerySM.go",
"chars": 1333,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// QuerySM PDU is issued by the ESME to query the status of a"
},
{
"path": "pdu/QuerySMResp.go",
"chars": 1573,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// QuerySMResp PDU.\ntype QuerySMResp struct {\n\tbase\n\tMessageI"
},
{
"path": "pdu/QuerySMResp_test.go",
"chars": 414,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/QuerySM_test.go",
"chars": 554,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/ReplaceSM.go",
"chars": 2255,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// ReplaceSM PDU is issued by the ESME to replace a previousl"
},
{
"path": "pdu/ReplaceSMResp.go",
"chars": 947,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// ReplaceSMResp PDU.\ntype ReplaceSMResp struct {\n\tbase\n}\n\n//"
},
{
"path": "pdu/ReplaceSMResp_test.go",
"chars": 418,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/ReplaceSM_test.go",
"chars": 908,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/ShortMessage.go",
"chars": 9406,
"preview": "package pdu\n\nimport (\n\t\"sync/atomic\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"github.com/linxGnu/gosmpp/errors\"\n)\n\nvar ref ="
},
{
"path": "pdu/ShortMessage_test.go",
"chars": 7171,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"github.com/linxGnu/gosmpp/errors\"\n\n\t\"github.com/st"
},
{
"path": "pdu/SubmitMulti.go",
"chars": 3101,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// SubmitMulti PDU is used to submit an SMPP message for deli"
},
{
"path": "pdu/SubmitMultiResp.go",
"chars": 1374,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// SubmitMultiResp PDU.\ntype SubmitMultiResp struct {\n\tbase\n\t"
},
{
"path": "pdu/SubmitMultiResp_test.go",
"chars": 898,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/SubmitMulti_test.go",
"chars": 2777,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/SubmitSM.go",
"chars": 4461,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// SubmitSM PDU is used by an ESME to submit a short message "
},
{
"path": "pdu/SubmitSMResp.go",
"chars": 1221,
"preview": "package pdu\n\nimport (\n\t\"errors\"\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"io\"\n)\n\n// SubmitSMResp PDU.\ntype SubmitSMResp struct"
},
{
"path": "pdu/SubmitSMResp_test.go",
"chars": 457,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/SubmitSM_test.go",
"chars": 965,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/TLV.go",
"chars": 2978,
"preview": "package pdu\n\n// Source code in this file is copied from: https://github.com/fiorix\nimport (\n\t\"encoding/binary\"\n\t\"encodin"
},
{
"path": "pdu/UDH.go",
"chars": 5319,
"preview": "package pdu\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// For now, this package only support messag"
},
{
"path": "pdu/UDH_test.go",
"chars": 1745,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestUserDataHeader(t *testing.T) {\n\tt.R"
},
{
"path": "pdu/Unbind.go",
"chars": 860,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// Unbind PDU is to deregister an instance of an ESME from th"
},
{
"path": "pdu/UnbindResp.go",
"chars": 895,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// UnbindResp PDU.\ntype UnbindResp struct {\n\tbase\n}\n\n// NewUn"
},
{
"path": "pdu/UnbindResp_test.go",
"chars": 399,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/Unbind_test.go",
"chars": 399,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
},
{
"path": "pdu/UnsuccessSME.go",
"chars": 2505,
"preview": "package pdu\n\nimport (\n\t\"github.com/linxGnu/gosmpp/data\"\n)\n\n// UnsuccessSME indicates submission was unsuccessful and the"
},
{
"path": "pdu/UnsuccessSME_test.go",
"chars": 389,
"preview": "package pdu\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestMalformUSME(t *testing.T) {\n\tt.Run("
},
{
"path": "pdu/helper_test.go",
"chars": 829,
"preview": "package pdu\n\nimport (\n\t\"encoding/hex\"\n\t\"log\"\n\t\"testing\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\n\t\"github.com/stretchr/testif"
},
{
"path": "pkg.go",
"chars": 4434,
"preview": "package gosmpp\n\nimport (\n\t\"io\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp/pdu\"\n)\n\n// Transceiver interface.\ntype Transceiver i"
},
{
"path": "receivable.go",
"chars": 4884,
"preview": "package gosmpp\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp/pdu\"\n)\n\ntype receivable "
},
{
"path": "receivable_test.go",
"chars": 5415,
"preview": "package gosmpp\n\nimport (\n\t\"fmt\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp/pd"
},
{
"path": "request_store.go",
"chars": 2148,
"preview": "package gosmpp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/linxGnu/gosmpp/pdu\"\n\tcmap \"github.com/orcaman/concurrent-map/v2\""
},
{
"path": "session.go",
"chars": 4430,
"preview": "package gosmpp\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/linxGnu/gosmpp/pdu\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\nvar (\n\tErrWindowSiz"
},
{
"path": "session_test.go",
"chars": 2551,
"preview": "package gosmpp\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestInvalidSessionSettings(t"
},
{
"path": "state.go",
"chars": 1307,
"preview": "package gosmpp\n\nconst (\n\tAlive int32 = iota\n\tClosed\n)\n\n// State represents Transmitter/Receiver/Transceiver state.\ntype "
},
{
"path": "state_test.go",
"chars": 780,
"preview": "package gosmpp\n\nimport (\n\t\"github.com/stretchr/testify/assert\"\n\t\"testing\"\n)\n\nfunc TestState_String(t *testing.T) {\n\ttest"
},
{
"path": "transceivable.go",
"chars": 3879,
"preview": "package gosmpp\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"github.com/linxGnu/gosmpp/pdu\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\nvar (\n\t"
},
{
"path": "transceivable_test.go",
"chars": 9427,
"preview": "package gosmpp\n\nimport (\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp/data\"\n\t\"github.com/linxGnu/gosmp"
},
{
"path": "transmittable.go",
"chars": 4845,
"preview": "package gosmpp\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net\"\n\t\"runtime\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gos"
},
{
"path": "transmittable_test.go",
"chars": 3463,
"preview": "package gosmpp\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/linxGnu/gosmpp/pdu\"\n\n\t\"gi"
},
{
"path": "types.go",
"chars": 795,
"preview": "package gosmpp\n\nimport (\n\t\"github.com/linxGnu/gosmpp/pdu\"\n)\n\n// PDUCallback handles received PDU.\ntype PDUCallback func("
}
]
About this extraction
This page contains the full source code of the linxGnu/gosmpp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 115 files (344.5 KB), approximately 110.8k tokens, and a symbol index with 1106 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.