Files

490 lines
13 KiB
Go

// 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 (
"encoding/binary"
"errors"
)
// Packet length const for cmpp fwd request and response packets.
const (
Cmpp2FwdReqPktMaxLen uint32 = 12 + 2379 //2277d, 0x957
Cmpp2FwdRspPktLen uint32 = 12 + 8 + 1 + 1 + 1 //23d, 0x17
Cmpp3FwdReqPktMaxLen uint32 = 12 + 2491 //2503d, 0x9c7
Cmpp3FwdRspPktLen uint32 = 12 + 8 + 1 + 1 + 4 //26d, 0x1a
)
// Errors for result in fwd resp.
var (
ErrnoFwdInvalidStruct uint8 = 1
ErrnoFwdInvalidCommandId uint8 = 2
ErrnoFwdInvalidSequence uint8 = 3
ErrnoFwdInvalidMsgLength uint8 = 4
ErrnoFwdInvalidFeeCode uint8 = 5
ErrnoFwdExceedMaxMsgLength uint8 = 6
ErrnoFwdInvalidServiceId uint8 = 7
ErrnoFwdNotPassFlowControl uint8 = 8
ErrnoFwdNoPrivilege uint8 = 9
FwdRspResultErrMap = map[uint8]error{
ErrnoFwdInvalidStruct: errFwdInvalidStruct,
ErrnoFwdInvalidCommandId: errFwdInvalidCommandId,
ErrnoFwdInvalidSequence: errFwdInvalidSequence,
ErrnoFwdInvalidMsgLength: errFwdInvalidMsgLength,
ErrnoFwdInvalidFeeCode: errFwdInvalidFeeCode,
ErrnoFwdExceedMaxMsgLength: errFwdExceedMaxMsgLength,
ErrnoFwdInvalidServiceId: errFwdInvalidServiceId,
ErrnoFwdNotPassFlowControl: errFwdNotPassFlowControl,
ErrnoFwdNoPrivilege: errFwdNoPrivilege,
}
errFwdInvalidStruct = errors.New("fwd response status: invalid protocol structure")
errFwdInvalidCommandId = errors.New("fwd response status: invalid command id")
errFwdInvalidSequence = errors.New("fwd response status: invalid message sequence")
errFwdInvalidMsgLength = errors.New("fwd response status: invalid message length")
errFwdInvalidFeeCode = errors.New("fwd response status: invalid fee code")
errFwdExceedMaxMsgLength = errors.New("fwd response status: exceed max message length")
errFwdInvalidServiceId = errors.New("fwd response status: invalid service id")
errFwdNotPassFlowControl = errors.New("fwd response status: not pass the flow control")
errFwdNoPrivilege = errors.New("fwd response status: msg has no fwd privilege")
)
type Cmpp2FwdReqPkt struct {
SourceId string
DestinationId string
NodesCount uint8
MsgFwdType uint8
MsgId uint64
PkTotal uint8
PkNumber uint8
RegisteredDelivery uint8
MsgLevel uint8
ServiceId string
FeeUserType uint8
FeeTerminalId string
TpPid uint8
TpUdhi uint8
MsgFmt uint8
MsgSrc string
FeeType string
FeeCode string
ValidTime string
AtTime string
SrcId string
DestUsrTl uint8
DestId []string
MsgLength uint8
MsgContent string
Reserve string
// session info
SeqId uint32
}
type Cmpp2FwdRspPkt struct {
MsgId uint64
PkTotal uint8
PkNumber uint8
Result uint8
// session info
SeqId uint32
}
type Cmpp3FwdReqPkt struct {
SourceId string
DestinationId string
NodesCount uint8
MsgFwdType uint8
MsgId uint64
PkTotal uint8
PkNumber uint8
RegisteredDelivery uint8
MsgLevel uint8
ServiceId string
FeeUserType uint8
FeeTerminalId string
FeeTerminalPseudo string
FeeTerminalUserType uint8
TpPid uint8
TpUdhi uint8
MsgFmt uint8
MsgSrc string
FeeType string
FeeCode string
ValidTime string
AtTime string
SrcId string
SrcPseudo string
SrcUserType uint8
SrcType uint8
DestUsrTl uint8
DestId []string
DestPseudo string
DestUserType uint8
MsgLength uint8
MsgContent string
LinkId string
// session info
SeqId uint32
}
type Cmpp3FwdRspPkt struct {
MsgId uint64
PkTotal uint8
PkNumber uint8
Result uint32
// session info
SeqId uint32
}
// Pack packs the Cmpp2FwdReqPkt to bytes stream for client side.
// Before calling Pack, you should initialize a Cmpp2FwdReqPkt variable
// with correct field value.
func (p *Cmpp2FwdReqPkt) Pack(seqId uint32) ([]byte, error) {
var pktLen uint32 = CMPP_HEADER_LEN + 131 + uint32(p.DestUsrTl)*21 + 1 + uint32(p.MsgLength) + 8
var w = newPacketWriter(pktLen)
// Pack header
w.WriteInt(binary.BigEndian, pktLen)
w.WriteInt(binary.BigEndian, CMPP_FWD)
w.WriteInt(binary.BigEndian, seqId)
p.SeqId = seqId
// Pack Body
w.WriteFixedSizeString(p.SourceId, 6)
w.WriteFixedSizeString(p.DestinationId, 6)
w.WriteByte(p.NodesCount)
w.WriteByte(p.MsgFwdType)
w.WriteInt(binary.BigEndian, p.MsgId)
if p.PkTotal == 0 && p.PkNumber == 0 {
p.PkTotal, p.PkNumber = 1, 1
}
w.WriteByte(p.PkTotal)
w.WriteByte(p.PkNumber)
w.WriteByte(p.RegisteredDelivery)
w.WriteByte(p.MsgLevel)
w.WriteFixedSizeString(p.ServiceId, 10)
w.WriteByte(p.FeeUserType)
w.WriteFixedSizeString(p.FeeTerminalId, 21)
w.WriteByte(p.TpPid)
w.WriteByte(p.TpUdhi)
w.WriteByte(p.MsgFmt)
w.WriteFixedSizeString(p.MsgSrc, 6)
w.WriteFixedSizeString(p.FeeType, 2)
w.WriteFixedSizeString(p.FeeCode, 6)
w.WriteFixedSizeString(p.ValidTime, 17)
w.WriteFixedSizeString(p.AtTime, 17)
w.WriteFixedSizeString(p.SrcId, 21)
w.WriteByte(p.DestUsrTl)
for _, d := range p.DestId {
w.WriteFixedSizeString(d, 21)
}
w.WriteByte(p.MsgLength)
w.WriteString(p.MsgContent)
w.WriteFixedSizeString(p.Reserve, 8)
return w.Bytes()
}
// Unpack unpack the binary byte stream to a Cmpp2FwdReqPkt variable.
// After unpack, you will get all value of fields in Cmpp2FwdReqPkt struct.
func (p *Cmpp2FwdReqPkt) Unpack(data []byte) error {
var r = newPacketReader(data)
// Sequence Id
r.ReadInt(binary.BigEndian, &p.SeqId)
sourceId := r.ReadCString(6)
p.SourceId = string(sourceId)
destinationId := r.ReadCString(6)
p.DestinationId = string(destinationId)
p.NodesCount = r.ReadByte()
p.MsgFwdType = r.ReadByte()
r.ReadInt(binary.BigEndian, &p.MsgId)
p.PkTotal = r.ReadByte()
p.PkNumber = r.ReadByte()
p.RegisteredDelivery = r.ReadByte()
p.MsgLevel = r.ReadByte()
serviceId := r.ReadCString(10)
p.ServiceId = string(serviceId)
p.FeeUserType = r.ReadByte()
feeTerminalId := r.ReadCString(21)
p.FeeTerminalId = string(feeTerminalId)
p.TpPid = r.ReadByte()
p.TpUdhi = r.ReadByte()
p.MsgFmt = r.ReadByte()
msgSrc := r.ReadCString(6)
p.MsgSrc = string(msgSrc)
feeType := make([]byte, 2)
r.ReadBytes(feeType)
p.FeeType = string(feeType)
feeCode := r.ReadCString(6)
p.FeeCode = string(feeCode)
validTime := r.ReadCString(17)
p.ValidTime = string(validTime)
atTime := r.ReadCString(17)
p.AtTime = string(atTime)
srcId := r.ReadCString(21)
p.SrcId = string(srcId)
p.DestUsrTl = r.ReadByte()
for i := 0; i < int(p.DestUsrTl); i++ {
destId := r.ReadCString(21)
p.DestId = append(p.DestId, string(destId))
}
p.MsgLength = r.ReadByte()
msgContent := make([]byte, p.MsgLength)
r.ReadBytes(msgContent)
p.MsgContent = string(msgContent)
reserve := r.ReadCString(8)
p.Reserve = string(reserve)
return r.Error()
}
// Pack packs the Cmpp2FwdRspPkt to bytes stream for server side.
// Before calling Pack, you should initialize a Cmpp2FwdRspPkt variable
// with correct field value.
func (p *Cmpp2FwdRspPkt) Pack(seqId uint32) ([]byte, error) {
var pktLen = Cmpp2FwdRspPktLen
var w = newPacketWriter(pktLen)
// Pack header
w.WriteInt(binary.BigEndian, pktLen)
w.WriteInt(binary.BigEndian, CMPP_FWD_RESP)
w.WriteInt(binary.BigEndian, seqId)
p.SeqId = seqId
// Pack Body
w.WriteInt(binary.BigEndian, p.MsgId)
w.WriteByte(p.PkTotal)
w.WriteByte(p.PkNumber)
w.WriteByte(p.Result)
return w.Bytes()
}
// Unpack unpack the binary byte stream to a Cmpp2FwdRspPkt variable.
// After unpack, you will get all value of fields in Cmpp2FwdRspPkt struct.
func (p *Cmpp2FwdRspPkt) Unpack(data []byte) error {
var r = newPacketReader(data)
// Sequence Id
r.ReadInt(binary.BigEndian, &p.SeqId)
r.ReadInt(binary.BigEndian, &p.MsgId)
p.PkTotal = r.ReadByte()
p.PkNumber = r.ReadByte()
p.Result = r.ReadByte()
return r.Error()
}
// Pack packs the Cmpp3FwdReqPkt to bytes stream for client side.
// Before calling Pack, you should initialize a Cmpp3FwdReqPkt variable
// with correct field value.
func (p *Cmpp3FwdReqPkt) Pack(seqId uint32) ([]byte, error) {
var pktLen uint32 = CMPP_HEADER_LEN + 198 + uint32(p.DestUsrTl)*21 + 32 + 1 + 1 + uint32(p.MsgLength) + 20
var w = newPacketWriter(pktLen)
// Pack header
w.WriteInt(binary.BigEndian, pktLen)
w.WriteInt(binary.BigEndian, CMPP_FWD)
w.WriteInt(binary.BigEndian, seqId)
p.SeqId = seqId
// Pack Body
w.WriteFixedSizeString(p.SourceId, 6)
w.WriteFixedSizeString(p.DestinationId, 6)
w.WriteByte(p.NodesCount)
w.WriteByte(p.MsgFwdType)
w.WriteInt(binary.BigEndian, p.MsgId)
if p.PkTotal == 0 && p.PkNumber == 0 {
p.PkTotal, p.PkNumber = 1, 1
}
w.WriteByte(p.PkTotal)
w.WriteByte(p.PkNumber)
w.WriteByte(p.RegisteredDelivery)
w.WriteByte(p.MsgLevel)
w.WriteFixedSizeString(p.ServiceId, 10)
w.WriteByte(p.FeeUserType)
w.WriteFixedSizeString(p.FeeTerminalId, 21)
w.WriteFixedSizeString(p.FeeTerminalPseudo, 32)
w.WriteByte(p.FeeTerminalUserType)
w.WriteByte(p.TpPid)
w.WriteByte(p.TpUdhi)
w.WriteByte(p.MsgFmt)
w.WriteFixedSizeString(p.MsgSrc, 6)
w.WriteFixedSizeString(p.FeeType, 2)
w.WriteFixedSizeString(p.FeeCode, 6)
w.WriteFixedSizeString(p.ValidTime, 17)
w.WriteFixedSizeString(p.AtTime, 17)
w.WriteFixedSizeString(p.SrcId, 21)
w.WriteFixedSizeString(p.SrcPseudo, 32)
w.WriteByte(p.SrcUserType)
w.WriteByte(p.SrcType)
w.WriteByte(p.DestUsrTl)
for _, d := range p.DestId {
w.WriteFixedSizeString(d, 21)
}
w.WriteFixedSizeString(p.DestPseudo, 32)
w.WriteByte(p.DestUserType)
w.WriteByte(p.MsgLength)
w.WriteString(p.MsgContent)
w.WriteFixedSizeString(p.LinkId, 20)
return w.Bytes()
}
// Unpack unpack the binary byte stream to a Cmpp3FwdReqPkt variable.
// After unpack, you will get all value of fields in Cmpp3FwdReqPkt struct.
func (p *Cmpp3FwdReqPkt) Unpack(data []byte) error {
var r = newPacketReader(data)
// Sequence Id
r.ReadInt(binary.BigEndian, &p.SeqId)
// Body
sourceId := r.ReadCString(6)
p.SourceId = string(sourceId)
destinationId := r.ReadCString(6)
p.DestinationId = string(destinationId)
p.NodesCount = r.ReadByte()
p.MsgFwdType = r.ReadByte()
r.ReadInt(binary.BigEndian, &p.MsgId)
p.PkTotal = r.ReadByte()
p.PkNumber = r.ReadByte()
p.RegisteredDelivery = r.ReadByte()
p.MsgLevel = r.ReadByte()
serviceId := r.ReadCString(10)
p.ServiceId = string(serviceId)
p.FeeUserType = r.ReadByte()
feeTerminalId := r.ReadCString(21)
p.FeeTerminalId = string(feeTerminalId)
feeTerminalPseudo := r.ReadCString(32)
p.FeeTerminalPseudo = string(feeTerminalPseudo)
p.FeeTerminalUserType = r.ReadByte()
p.TpPid = r.ReadByte()
p.TpUdhi = r.ReadByte()
p.MsgFmt = r.ReadByte()
msgSrc := r.ReadCString(6)
p.MsgSrc = string(msgSrc)
feeType := make([]byte, 2)
r.ReadBytes(feeType)
p.FeeType = string(feeType)
feeCode := r.ReadCString(6)
p.FeeCode = string(feeCode)
validTime := r.ReadCString(17)
p.ValidTime = string(validTime)
atTime := r.ReadCString(17)
p.AtTime = string(atTime)
srcId := r.ReadCString(21)
p.SrcId = string(srcId)
srcPseudo := r.ReadCString(32)
p.SrcPseudo = string(srcPseudo)
p.SrcUserType = r.ReadByte()
p.SrcType = r.ReadByte()
p.DestUsrTl = r.ReadByte()
for i := 0; i < int(p.DestUsrTl); i++ {
destId := r.ReadCString(21)
p.DestId = append(p.DestId, string(destId))
}
destPseudo := r.ReadCString(32)
p.DestPseudo = string(destPseudo)
p.DestUserType = r.ReadByte()
p.MsgLength = r.ReadByte()
msgContent := make([]byte, p.MsgLength)
r.ReadBytes(msgContent)
p.MsgContent = string(msgContent)
linkId := r.ReadCString(20)
p.LinkId = string(linkId)
return r.Error()
}
// Pack packs the Cmpp3FwdRspPkt to bytes stream for server side.
// Before calling Pack, you should initialize a Cmpp3FwdRspPkt variable
// with correct field value.
func (p *Cmpp3FwdRspPkt) Pack(seqId uint32) ([]byte, error) {
var pktLen = Cmpp3FwdRspPktLen
var w = newPacketWriter(pktLen)
// Pack header
w.WriteInt(binary.BigEndian, pktLen)
w.WriteInt(binary.BigEndian, CMPP_FWD_RESP)
w.WriteInt(binary.BigEndian, seqId)
p.SeqId = seqId
// Pack Body
w.WriteInt(binary.BigEndian, p.MsgId)
w.WriteByte(p.PkTotal)
w.WriteByte(p.PkNumber)
w.WriteInt(binary.BigEndian, p.Result)
return w.Bytes()
}
// Unpack unpack the binary byte stream to a Cmpp3FwdRspPkt variable.
// After unpack, you will get all value of fields in Cmpp3FwdRspPkt struct.
func (p *Cmpp3FwdRspPkt) Unpack(data []byte) error {
var r = newPacketReader(data)
// Sequence Id
r.ReadInt(binary.BigEndian, &p.SeqId)
r.ReadInt(binary.BigEndian, &p.MsgId)
p.PkTotal = r.ReadByte()
p.PkNumber = r.ReadByte()
r.ReadInt(binary.BigEndian, &p.Result)
return r.Error()
}