-
Notifications
You must be signed in to change notification settings - Fork 66
/
Copy pathpacket.go
384 lines (335 loc) · 8.67 KB
/
packet.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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
// Copyright 2015 Tony Bai.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.
package cmpp
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"strings"
)
type Type int8
const (
V30 Type = 0x30
V21 Type = 0x21
V20 Type = 0x20
)
func (t Type) String() string {
switch {
case t == V30:
return "cmpp30"
case t == V21:
return "cmpp21"
case t == V20:
return "cmpp20"
default:
return "unknown"
}
}
const (
CMPP_HEADER_LEN uint32 = 12
CMPP2_PACKET_MAX uint32 = 2477
CMPP2_PACKET_MIN uint32 = 12
CMPP3_PACKET_MAX uint32 = 3335
CMPP3_PACKET_MIN uint32 = 12
)
// Common errors.
var ErrMethodParamsInvalid = errors.New("params passed to method is invalid")
// Protocol errors.
var ErrTotalLengthInvalid = errors.New("total_length in Packet data is invalid")
var ErrCommandIdInvalid = errors.New("command_Id in Packet data is invalid")
var ErrCommandIdNotSupported = errors.New("command_Id in Packet data is not supported")
type CommandId uint32
const (
CMPP_REQUEST_MIN, CMPP_RESPONSE_MIN CommandId = iota, 0x80000000 + iota
CMPP_CONNECT, CMPP_CONNECT_RESP
CMPP_TERMINATE, CMPP_TERMINATE_RESP
_, _
CMPP_SUBMIT, CMPP_SUBMIT_RESP
CMPP_DELIVER, CMPP_DELIVER_RESP
CMPP_QUERY, CMPP_QUERY_RESP
CMPP_CANCEL, CMPP_CANCEL_RESP
CMPP_ACTIVE_TEST, CMPP_ACTIVE_TEST_RESP
CMPP_FWD, CMPP_FWD_RESP
CMPP_MT_ROUTE, CMPP_MT_ROUTE_RESP CommandId = 0x00000010 - 10 + iota, 0x80000010 - 10 + iota
CMPP_MO_ROUTE, CMPP_MO_ROUTE_RESP
CMPP_GET_MT_ROUTE, CMPP_GET_MT_ROUTE_RESP
CMPP_MT_ROUTE_UPDATE, CMPP_MT_ROUTE_UPDATE_RESP
CMPP_MO_ROUTE_UPDATE, CMPP_MO_ROUTE_UPDATE_RESP
CMPP_PUSH_MT_ROUTE_UPDATE, CMPP_PUSH_MT_ROUTE_UPDATE_RESP
CMPP_PUSH_MO_ROUTE_UPDATE, CMPP_PUSH_MO_ROUTE_UPDATE_RESP
CMPP_GET_MO_ROUTE, CMPP_GET_MO_ROUTE_RESP
CMPP_REQUEST_MAX, CMPP_RESPONSE_MAX
)
func (id CommandId) String() string {
if id <= CMPP_FWD && id > CMPP_REQUEST_MIN {
return []string{
"CMPP_CONNECT",
"CMPP_TERMINATE",
"CMPP_UNKNOWN",
"CMPP_SUBMIT",
"CMPP_DELIVER",
"CMPP_QUERY",
"CMPP_CANCEL",
"CMPP_ACTIVE_TEST",
"CMPP_FWD",
}[id-1]
} else if id >= CMPP_MT_ROUTE && id < CMPP_REQUEST_MAX {
return []string{
"CMPP_MT_ROUTE",
"CMPP_MO_ROUTE",
"CMPP_GET_MT_ROUTE",
"CMPP_MT_ROUTE_UPDATE",
"CMPP_MO_ROUTE_UPDATE",
"CMPP_PUSH_MT_ROUTE_UPDATE",
"CMPP_PUSH_MO_ROUTE_UPDATE",
"CMPP_GET_MO_ROUTE",
}[id-0x00000010]
}
if id <= CMPP_FWD_RESP && id > CMPP_RESPONSE_MIN {
return []string{
"CMPP_CONNECT_RESP",
"CMPP_TERMINATE_RESP",
"CMPP_UNKNOWN",
"CMPP_SUBMIT_RESP",
"CMPP_DELIVER_RESP",
"CMPP_QUERY_RESP",
"CMPP_CANCEL_RESP",
"CMPP_ACTIVE_TEST_RESP",
"CMPP_FWD_RESP",
}[id-0x80000001]
} else if id >= CMPP_MT_ROUTE_RESP && id < CMPP_RESPONSE_MAX {
return []string{
"CMPP_MT_ROUTE_RESP",
"CMPP_MO_ROUTE_RESP",
"CMPP_GET_MT_ROUTE_RESP",
"CMPP_MT_ROUTE_UPDATE_RESP",
"CMPP_MO_ROUTE_UPDATE_RESP",
"CMPP_PUSH_MT_ROUTE_UPDATE_RESP",
"CMPP_PUSH_MO_ROUTE_UPDATE_RESP",
"CMPP_GET_MO_ROUTE_RESP",
}[id-0x80000010]
}
return "unknown"
}
type Packer interface {
Pack(seqId uint32) ([]byte, error)
Unpack(data []byte) error
}
// OpError is the error type usually returned by functions in the cmpppacket
// package. It describes the operation and the error which the operation caused.
type OpError struct {
// err is the error that occurred during the operation.
// it is the origin error.
err error
// op is the operation which caused the error, such as
// some "read" or "write" in packetWriter or packetReader.
op string
}
func NewOpError(e error, op string) *OpError {
return &OpError{
err: e,
op: op,
}
}
func (e *OpError) Error() string {
if e.err == nil {
return "<nil>"
}
return e.op + " error: " + e.err.Error()
}
func (e *OpError) Cause() error {
return e.err
}
func (e *OpError) Op() string {
return e.op
}
type packetWriter struct {
wb *bytes.Buffer
err *OpError
}
func newPacketWriter(initSize uint32) *packetWriter {
buf := make([]byte, 0, initSize)
return &packetWriter{
wb: bytes.NewBuffer(buf),
}
}
// Bytes returns a slice of the contents of the inner buffer;
// If the caller changes the contents of the
// returned slice, the contents of the buffer will change provided there
// are no intervening method calls on the Buffer.
func (w *packetWriter) Bytes() ([]byte, error) {
if w.err != nil {
return nil, w.err
}
len := w.wb.Len()
return (w.wb.Bytes())[:len], nil
}
// WriteByte appends the byte of b to the inner buffer, growing the buffer as
// needed.
func (w *packetWriter) WriteByte(b byte) {
if w.err != nil {
return
}
err := w.wb.WriteByte(b)
if err != nil {
w.err = NewOpError(err,
fmt.Sprintf("packetWriter.WriteByte writes: %x", b))
return
}
}
// WriteFixedSizeString writes a string to buffer, if the length of s is less than size,
// Pad binary zero to the right.
func (w *packetWriter) WriteFixedSizeString(s string, size int) {
if w.err != nil {
return
}
l1 := len(s)
l2 := l1
if l2 > 10 {
l2 = 10
}
if l1 > size {
w.err = NewOpError(ErrMethodParamsInvalid,
fmt.Sprintf("packetWriter.WriteFixedSizeString writes: %s", s[0:l2]))
return
}
w.WriteString(strings.Join([]string{s, string(make([]byte, size-l1))}, ""))
}
// WriteString appends the contents of s to the inner buffer, growing the buffer as
// needed.
func (w *packetWriter) WriteString(s string) {
if w.err != nil {
return
}
l1 := len(s)
l2 := l1
if l2 > 10 {
l2 = 10
}
n, err := w.wb.WriteString(s)
if err != nil {
w.err = NewOpError(err,
fmt.Sprintf("packetWriter.WriteString writes: %s", s[0:l2]))
return
}
if n != l1 {
w.err = NewOpError(fmt.Errorf("WriteString writes %d bytes, not equal to %d we expected", n, l1),
fmt.Sprintf("packetWriter.WriteString writes: %s", s[0:l2]))
return
}
}
// WriteInt appends the content of data to the inner buffer in order, growing the buffer as
// needed.
func (w *packetWriter) WriteInt(order binary.ByteOrder, data interface{}) {
if w.err != nil {
return
}
err := binary.Write(w.wb, order, data)
if err != nil {
w.err = NewOpError(err,
fmt.Sprintf("packetWriter.WriteInt writes: %#v", data))
return
}
}
const maxCStringSize = 160
type packetReader struct {
rb *bytes.Buffer
err *OpError
cbuf [maxCStringSize]byte
}
func newPacketReader(data []byte) *packetReader {
return &packetReader{
rb: bytes.NewBuffer(data),
}
}
// ReadByte reads and returns the next byte from the inner buffer.
// If no byte is available, it returns an OpError.
func (r *packetReader) ReadByte() byte {
if r.err != nil {
return 0
}
b, err := r.rb.ReadByte()
if err != nil {
r.err = NewOpError(err,
"packetReader.ReadByte")
return 0
}
return b
}
// ReadInt reads reads structured binary data from r into data.
// Data must be a pointer to a fixed-size value or a slice
// of fixed-size values.
// Bytes read from r are decoded using the specified byte order
// and written to successive fields of the data.
func (r *packetReader) ReadInt(order binary.ByteOrder, data interface{}) {
if r.err != nil {
return
}
err := binary.Read(r.rb, order, data)
if err != nil {
r.err = NewOpError(err,
"packetReader.ReadInt")
return
}
}
// ReadBytes reads the next len(s) bytes from the inner buffer to s.
// If the buffer has no data to return, an OpError would be stored in r.err.
func (r *packetReader) ReadBytes(s []byte) {
if r.err != nil {
return
}
n, err := r.rb.Read(s)
if err != nil {
r.err = NewOpError(err,
"packetReader.ReadBytes")
return
}
if n != len(s) {
r.err = NewOpError(fmt.Errorf("ReadBytes reads %d bytes, not equal to %d we expected", n, len(s)),
"packetWriter.ReadBytes")
return
}
}
// ReadCString read bytes from packerReader's inner buffer,
// it would trim the tail-zero byte and the bytes after that.
func (r *packetReader) ReadCString(length int) []byte {
if r.err != nil {
return nil
}
var tmp = r.cbuf[:length]
n, err := r.rb.Read(tmp)
if err != nil {
r.err = NewOpError(err,
"packetReader.ReadCString")
return nil
}
if n != length {
r.err = NewOpError(fmt.Errorf("ReadCString reads %d bytes, not equal to %d we expected", n, length),
"packetWriter.ReadCString")
return nil
}
i := bytes.IndexByte(tmp, 0)
if i == -1 {
return tmp
} else {
return tmp[:i]
}
}
// Error return the inner err.
func (r *packetReader) Error() error {
if r.err != nil {
return r.err
}
return nil
}