forked from fiorix/go-smpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
190 lines (171 loc) · 4.29 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright 2015 go-smpp authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package smpptest
import (
"crypto/tls"
"errors"
"fmt"
"io"
"log"
"net"
"sync"
"github.com/Zensey/go-smpp/smpp/pdu"
"github.com/Zensey/go-smpp/smpp/pdu/pdufield"
)
// Default settings.
var (
DefaultUser = "client"
DefaultPasswd = "secret"
DefaultSystemID = "smpptest"
)
// HandlerFunc is the signature of a function passed to Server instances,
// that is called when client PDU messages arrive.
type HandlerFunc func(c Conn, m pdu.Body)
// Server is an SMPP server for testing purposes. By default it authenticate
// clients with the configured credentials, and echoes any other PDUs
// back to the client.
type Server struct {
User string
Passwd string
TLS *tls.Config
Handler HandlerFunc
conns []Conn
mu sync.Mutex
l net.Listener
}
// NewServer creates and initializes a new Server. Callers are supposed
// to call Close on that server later.
func NewServer() *Server {
s := NewUnstartedServer()
s.Start()
return s
}
// NewUnstartedServer creates a new Server with default settings, and
// does not start it. Callers are supposed to call Start and Close later.
func NewUnstartedServer() *Server {
return &Server{
User: DefaultUser,
Passwd: DefaultPasswd,
Handler: EchoHandler,
l: newLocalListener(),
}
}
func newLocalListener() net.Listener {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err == nil {
return l
}
if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
panic(fmt.Sprintf("smpptest: failed to listen on a port: %v", err))
}
return l
}
// Start starts the server.
func (srv *Server) Start() {
go srv.Serve()
}
// Addr returns the local address of the server, or an empty string
// if the server hasn't been started yet.
func (srv *Server) Addr() string {
if srv.l == nil {
return ""
}
return srv.l.Addr().String()
}
// Close stops the server, causing the accept loop to break out.
func (srv *Server) Close() {
if srv.l == nil {
panic("smpptest: server is not started")
}
srv.l.Close()
}
// Serve accepts new clients and handle them by authenticating the
// first PDU, expected to be a Bind PDU, then echoing all other PDUs.
func (srv *Server) Serve() {
for {
cli, err := srv.l.Accept()
if err != nil {
break // on srv.l.Close
}
c := newConn(cli)
srv.conns = append(srv.conns, c)
go srv.handle(c)
}
}
// broadcasts a test PDU to all clients bind to this server
func (srv *Server) BroadcastMessage(p pdu.Body) {
for i := range srv.conns {
srv.conns[i].Write(p)
}
}
// handle new clients.
func (srv *Server) handle(c *conn) {
defer c.Close()
if err := srv.auth(c); err != nil {
if err != io.EOF {
log.Println("smpptest: server auth failed:", err)
}
return
}
for {
p, err := c.Read()
if err != nil {
if err != io.EOF {
log.Println("smpptest: read failed:", err)
}
break
}
srv.Handler(c, p)
}
}
// auth authenticate new clients.
func (srv *Server) auth(c *conn) error {
p, err := c.Read()
if err != nil {
return err
}
var resp pdu.Body
switch p.Header().ID {
case pdu.BindTransmitterID:
resp = pdu.NewBindTransmitterResp()
case pdu.BindReceiverID:
resp = pdu.NewBindReceiverResp()
case pdu.BindTransceiverID:
resp = pdu.NewBindTransceiverResp()
default:
return errors.New("unexpected pdu, want bind")
}
f := p.Fields()
user := f[pdufield.SystemID]
passwd := f[pdufield.Password]
if user == nil || passwd == nil {
return errors.New("malformed pdu, missing system_id/password")
}
if user.String() != srv.User {
return errors.New("invalid user")
}
if passwd.String() != srv.Passwd {
return errors.New("invalid passwd")
}
resp.Fields().Set(pdufield.SystemID, DefaultSystemID)
if err = c.Write(resp); err != nil {
return err
}
return nil
}
// EchoHandler is the default Server HandlerFunc, and echoes back
// any PDUs received.
func EchoHandler(cli Conn, m pdu.Body) {
// log.Printf("smpptest: echo PDU from %s: %#v", cli.RemoteAddr(), m)
//
// Real servers will reply with at least the same sequence number
// from the request:
// resp := pdu.NewSubmitSMResp()
// resp.Header().Seq = m.Header().Seq
// resp.Fields().Set(pdufield.MessageID, "1234")
// cli.Write(resp)
//
// We just echo m back:
cli.Write(m)
}