Files
lislgosms/gateway/internal/cmpp/gocmpp_integration_test.go
T

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
}