215 lines
5.4 KiB
Go
215 lines
5.4 KiB
Go
package cmppadapter
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
cmpp "github.com/bigwhite/gocmpp"
|
|
cmpputils "github.com/bigwhite/gocmpp/utils"
|
|
)
|
|
|
|
const (
|
|
spikeUser = "900001"
|
|
spikePassword = "888888"
|
|
)
|
|
|
|
func TestGocmppConnectSubmitAndActiveTest(t *testing.T) {
|
|
addr := reserveTCPAddr(t)
|
|
handlers := []cmpp.Handler{
|
|
cmpp.HandlerFunc(handleSpikeLogin),
|
|
cmpp.HandlerFunc(handleSpikeSubmit),
|
|
}
|
|
|
|
go func() {
|
|
err := cmpp.ListenAndServe(addr, cmpp.V30, 2*time.Second, 3, nil, handlers...)
|
|
if err != nil {
|
|
log.Printf("gocmpp spike server stopped: %v", err)
|
|
}
|
|
}()
|
|
time.Sleep(300 * time.Millisecond)
|
|
|
|
client := cmpp.NewClient(cmpp.V30)
|
|
defer client.Disconnect()
|
|
|
|
if err := client.Connect(addr, spikeUser, spikePassword, 2*time.Second); err != nil {
|
|
t.Fatalf("connect gocmpp server: %v", err)
|
|
}
|
|
|
|
content, err := cmpputils.Utf8ToUcs2("测试gocmpp submit")
|
|
if err != nil {
|
|
t.Fatalf("encode submit content: %v", err)
|
|
}
|
|
|
|
_, err = client.SendReqPkt(&cmpp.Cmpp3SubmitReqPkt{
|
|
PkTotal: 1,
|
|
PkNumber: 1,
|
|
RegisteredDelivery: 1,
|
|
MsgLevel: 1,
|
|
ServiceId: "test",
|
|
FeeUserType: 2,
|
|
FeeTerminalId: "13500002696",
|
|
FeeTerminalType: 0,
|
|
MsgFmt: 8,
|
|
MsgSrc: spikeUser,
|
|
FeeType: "02",
|
|
FeeCode: "10",
|
|
ValidTime: "151105131555101+",
|
|
AtTime: "",
|
|
SrcId: spikeUser,
|
|
DestUsrTl: 1,
|
|
DestTerminalId: []string{"13500002696"},
|
|
DestTerminalType: 0,
|
|
MsgLength: uint8(len(content)),
|
|
MsgContent: content,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("send submit: %v", err)
|
|
}
|
|
|
|
submitRsp := recvUntil[*cmpp.Cmpp3SubmitRspPkt](t, client, 2*time.Second)
|
|
if submitRsp.Result != 0 {
|
|
t.Fatalf("unexpected submit result: %d", submitRsp.Result)
|
|
}
|
|
if submitRsp.MsgId == 0 {
|
|
t.Fatal("expected gateway msg id")
|
|
}
|
|
|
|
_, err = client.SendReqPkt(&cmpp.CmppActiveTestReqPkt{})
|
|
if err != nil {
|
|
t.Fatalf("send active test: %v", err)
|
|
}
|
|
_ = recvUntil[*cmpp.CmppActiveTestRspPkt](t, client, 2*time.Second)
|
|
}
|
|
|
|
func TestGocmppDeliverReceiptPackAndUnpack(t *testing.T) {
|
|
receipt := &cmpp.CmppReceiptPkt{
|
|
MsgId: 12878564852733378560,
|
|
Stat: "DELIVRD",
|
|
SubmitTime: "2607010900",
|
|
DoneTime: "2607010901",
|
|
DestTerminalId: "13500002696",
|
|
SmscSequence: 42,
|
|
}
|
|
receiptBytes, err := receipt.Pack()
|
|
if err != nil {
|
|
t.Fatalf("pack receipt: %v", err)
|
|
}
|
|
|
|
deliver := &cmpp.Cmpp3DeliverReqPkt{
|
|
MsgId: 12878564852733378560,
|
|
DestId: "106900000000",
|
|
ServiceId: "test",
|
|
TpPid: 0,
|
|
TpUdhi: 0,
|
|
MsgFmt: 0,
|
|
SrcTerminalId: "13500002696",
|
|
SrcTerminalType: 0,
|
|
RegisterDelivery: 1,
|
|
MsgLength: uint8(cmpp.CmppReceiptPktLen),
|
|
MsgContent: string(receiptBytes),
|
|
}
|
|
|
|
data, err := deliver.Pack(1001)
|
|
if err != nil {
|
|
t.Fatalf("pack deliver receipt: %v", err)
|
|
}
|
|
|
|
var unpacked cmpp.Cmpp3DeliverReqPkt
|
|
if err := unpacked.Unpack(data[8:]); err != nil {
|
|
t.Fatalf("unpack deliver receipt: %v", err)
|
|
}
|
|
|
|
var gotReceipt cmpp.CmppReceiptPkt
|
|
if err := gotReceipt.Unpack([]byte(unpacked.MsgContent)); err != nil {
|
|
t.Fatalf("unpack receipt content: %v", err)
|
|
}
|
|
if gotReceipt.Stat != "DELIVRD" || gotReceipt.SmscSequence != 42 {
|
|
t.Fatalf("unexpected receipt payload: %+v", &gotReceipt)
|
|
}
|
|
}
|
|
|
|
func reserveTCPAddr(t *testing.T) string {
|
|
t.Helper()
|
|
|
|
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatalf("reserve tcp addr: %v", err)
|
|
}
|
|
addr := listener.Addr().String()
|
|
if err := listener.Close(); err != nil {
|
|
t.Fatalf("close reserved listener: %v", err)
|
|
}
|
|
return addr
|
|
}
|
|
|
|
func recvUntil[T any](t *testing.T, client *cmpp.Client, timeout time.Duration) T {
|
|
t.Helper()
|
|
|
|
deadline := time.Now().Add(timeout)
|
|
for time.Now().Before(deadline) {
|
|
packet, err := client.RecvAndUnpackPkt(200 * time.Millisecond)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if typed, ok := packet.(T); ok {
|
|
return typed
|
|
}
|
|
}
|
|
|
|
var zero T
|
|
t.Fatalf("timed out waiting for %T", zero)
|
|
return zero
|
|
}
|
|
|
|
func handleSpikeLogin(response *cmpp.Response, packet *cmpp.Packet, logger *log.Logger) (bool, error) {
|
|
req, ok := packet.Packer.(*cmpp.CmppConnReqPkt)
|
|
if !ok {
|
|
return true, nil
|
|
}
|
|
|
|
resp := response.Packer.(*cmpp.Cmpp3ConnRspPkt)
|
|
resp.Version = 0x30
|
|
|
|
if req.SrcAddr != cmpputils.OctetString(spikeUser, 6) {
|
|
resp.Status = uint32(cmpp.ErrnoConnInvalidSrcAddr)
|
|
return false, cmpp.ConnRspStatusErrMap[cmpp.ErrnoConnInvalidSrcAddr]
|
|
}
|
|
|
|
authSrc := md5.Sum(bytes.Join([][]byte{
|
|
[]byte(cmpputils.OctetString(spikeUser, 6)),
|
|
make([]byte, 9),
|
|
[]byte(spikePassword),
|
|
[]byte(cmpputils.TimeStamp2Str(req.Timestamp)),
|
|
}, nil))
|
|
|
|
if req.AuthSrc != string(authSrc[:]) {
|
|
resp.Status = uint32(cmpp.ErrnoConnAuthFailed)
|
|
return false, cmpp.ConnRspStatusErrMap[cmpp.ErrnoConnAuthFailed]
|
|
}
|
|
|
|
authIsmg := md5.Sum(bytes.Join([][]byte{{byte(resp.Status)}, authSrc[:], []byte(spikePassword)}, nil))
|
|
resp.AuthIsmg = string(authIsmg[:])
|
|
return false, nil
|
|
}
|
|
|
|
func handleSpikeSubmit(response *cmpp.Response, packet *cmpp.Packet, logger *log.Logger) (bool, error) {
|
|
req, ok := packet.Packer.(*cmpp.Cmpp3SubmitReqPkt)
|
|
if !ok {
|
|
return true, nil
|
|
}
|
|
|
|
if req.DestUsrTl == 0 || len(req.DestTerminalId) == 0 {
|
|
return false, fmt.Errorf("missing submit destination")
|
|
}
|
|
|
|
resp := response.Packer.(*cmpp.Cmpp3SubmitRspPkt)
|
|
resp.MsgId = 12878564852733378560
|
|
resp.Result = 0
|
|
return false, nil
|
|
}
|