You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
560 lines
15 KiB
Go
560 lines
15 KiB
Go
package common
|
|
|
|
import (
|
|
"bytes"
|
|
"math/rand"
|
|
|
|
"git.cheetah.cat/cheetah/opentetraflex-go/common/tmkind"
|
|
)
|
|
|
|
func NextHandlerID() uint32 {
|
|
return uint32(rand.Int())
|
|
}
|
|
|
|
type TerminalMessage struct {
|
|
length uint16
|
|
kind tmkind.TetraFlexTerminalMessageKinds
|
|
handler uint32
|
|
|
|
data bytes.Buffer
|
|
}
|
|
|
|
func NewTerminalMessage(length uint16, kind tmkind.TetraFlexTerminalMessageKinds, handler uint32) (tm *TerminalMessage, err error) {
|
|
tm = &TerminalMessage{
|
|
length: length,
|
|
kind: kind,
|
|
handler: handler,
|
|
}
|
|
if err = tm.WriteShort(length); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tm.WriteShort(uint16(kind)); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tm.WriteUInt(handler); err != nil {
|
|
return nil, err
|
|
}
|
|
return tm, nil
|
|
}
|
|
|
|
// Write<Type> Functions
|
|
func (tm *TerminalMessage) WriteShort(data uint16) (err error) {
|
|
_, err = tm.data.Write(uint16ToBytes(data))
|
|
return err
|
|
}
|
|
func (tm *TerminalMessage) WriteUInt(data uint32) (err error) {
|
|
_, err = tm.data.Write(uint32ToBytes(data))
|
|
return err
|
|
}
|
|
func (tm *TerminalMessage) WriteByte(data byte) (err error) {
|
|
return tm.data.WriteByte(data)
|
|
}
|
|
func (tm *TerminalMessage) WriteBytes(data []byte, count int) (err error) {
|
|
bytes := make([]byte, count)
|
|
copy(bytes, data)
|
|
_, err = tm.data.Write(bytes)
|
|
return err
|
|
}
|
|
func (tm *TerminalMessage) WriteString(text string, len int) (err error) {
|
|
bytes := make([]byte, len)
|
|
copy(bytes, text)
|
|
_, err = tm.data.Write(bytes)
|
|
return err
|
|
}
|
|
func (tm *TerminalMessage) WriteTFAddress(addr TetraFlexAddress) (err error) {
|
|
if err = tm.data.WriteByte(byte(addr.Kind)); err != nil {
|
|
return err
|
|
}
|
|
var (
|
|
text string
|
|
num1 uint32
|
|
num2, num3 uint16
|
|
num4 byte
|
|
)
|
|
if len(addr.UserNo) > 0 {
|
|
text = addr.UserNo
|
|
}
|
|
if addr.TSI.IsValid() {
|
|
num1 = addr.TSI.SSI
|
|
num2 = addr.TSI.MNC
|
|
num3 = addr.TSI.MCC
|
|
}
|
|
if err = tm.FillZero(3); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = tm.WriteUInt(num1); err != nil {
|
|
return err
|
|
}
|
|
if err = tm.WriteShort(num2); err != nil {
|
|
return err
|
|
}
|
|
if err = tm.WriteShort(num3); err != nil {
|
|
return err
|
|
}
|
|
num4 = byte(len(text))
|
|
if num4 > 24 {
|
|
num4 = 24
|
|
}
|
|
// this.#c.Write((byte)num4);
|
|
if err = tm.data.WriteByte(num4); err != nil {
|
|
return err
|
|
}
|
|
// this.#c.Write(0); 3x
|
|
if err = tm.FillZero(3); err != nil {
|
|
return err
|
|
}
|
|
if err = tm.WriteString(text, 24); err != nil {
|
|
return err
|
|
}
|
|
|
|
/*
|
|
AddressType kind = #LBc.Kind;
|
|
string text = #i.#f.#8q(473);
|
|
uint num = 0U;
|
|
ushort num2 = 0;
|
|
ushort num3 = 0;
|
|
if (#LBc.#v6c())
|
|
{
|
|
text = #LBc.UserNumber.Number;
|
|
}
|
|
if (#LBc.#x6c())
|
|
{
|
|
num = #LBc.TSI.SSI;
|
|
num2 = #LBc.TSI.MNC;
|
|
num3 = #LBc.TSI.MCC;
|
|
}
|
|
this.#c.Write((byte)kind);
|
|
this.#c.Write(num);
|
|
this.#c.Write(num2);
|
|
this.#c.Write(num3);
|
|
uint num4 = (uint)text.Length;
|
|
if (num4 > 24U)
|
|
{
|
|
num4 = 24U;
|
|
}
|
|
|
|
this.#c.Write((byte)num4);
|
|
this.#c.Write(0);
|
|
this.#c.Write(0);
|
|
this.#c.Write(0);
|
|
for (uint num5 = 0U; num5 < num4; num5 += 1U)
|
|
{
|
|
this.#c.Write((byte)text[(int)num5]);
|
|
}
|
|
for (uint num6 = num4; num6 < 24U; num6 += 1U)
|
|
{
|
|
this.#c.Write(0);
|
|
}
|
|
*/
|
|
//return tm.data.WriteByte(data)
|
|
return nil
|
|
}
|
|
func (tm *TerminalMessage) WriteIdentityInfoAddress(identityInfo TetraFlexIdentityInfo) (err error) {
|
|
return tm.WriteTFAddress(identityInfo.Address)
|
|
}
|
|
func (tm *TerminalMessage) WriteIdentityInfoKind(identityInfo TetraFlexIdentityInfo) (err error) {
|
|
/*
|
|
case TetraFlexIdentityKind.Mobile:
|
|
case TetraFlexIdentityKind.Group:
|
|
case TetraFlexIdentityKind.DMRRADIO:
|
|
case TetraFlexIdentityKind.Application:
|
|
case TetraFlexIdentityKind.DialInUser:
|
|
case TetraFlexIdentityKind.EmergencyNumber:
|
|
case TetraFlexIdentityKind.Terminal:
|
|
case TetraFlexIdentityKind.Personal:
|
|
*/
|
|
return tm.data.WriteByte(byte(identityInfo.Kind))
|
|
}
|
|
func (tm *TerminalMessage) WriteIdentityInfoUnfied(identityInfo TetraFlexIdentityInfo) (err error) {
|
|
byteVal := byte(0)
|
|
if identityInfo.Kind == IdentityKindPersonal {
|
|
byteVal = byte(UnifiedKindPersonalNumber)
|
|
}
|
|
return tm.data.WriteByte(byteVal)
|
|
}
|
|
func (tm *TerminalMessage) FillZero(zeroCount uint32) (err error) {
|
|
_, err = tm.data.Write(make([]byte, zeroCount))
|
|
return err
|
|
}
|
|
func (tm *TerminalMessage) Encode() []byte {
|
|
return tm.data.Bytes()
|
|
}
|
|
|
|
// TerminalMessage Builder for PDUs
|
|
func NewTMAuthReq(addr TetraFlexAddress, num uint32, randomBytes []byte, terminalTypeID byte, terminalTypeStr string, terminalVersionDate uint32, terminalVersionStr string) (tm *TerminalMessage, err error) {
|
|
tfAuthReq, err := NewTerminalMessage(256, tmkind.IpApiRegistrationRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteUInt(20140604); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteTFAddress(addr); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteByte(10); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteByte(10); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteByte(0); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteByte(terminalTypeID); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteUInt(num); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteString(terminalTypeStr, 16); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteString(terminalVersionStr, 16); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteBytes(randomBytes, 10); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.FillZero(2); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.WriteUInt(terminalVersionDate); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = tfAuthReq.FillZero(148); err != nil {
|
|
return nil, err
|
|
}
|
|
return tfAuthReq, nil
|
|
}
|
|
func NewTMKeepAliveResponse(challenge KeepAliveChallenge) (tm *TerminalMessage, err error) {
|
|
response := KeepAliveResponse{}
|
|
terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiKeepAliveResponse, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(8); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteUInt(uint32(response.GPSLatitude)); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteUInt(uint32(response.GPSLongitude)); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteShort(response.Value3); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteShort(response.Value4); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteUInt(response.GPSTime); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteUInt(response.Accuracy); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(28); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMNotificationRequest(messageTypes []tmkind.TetraFlexTerminalMessageKinds) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(128, tmkind.IpApiNotificationRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// IpApiNotificationRequest
|
|
if err = terminalMessage.WriteShort(uint16(len(messageTypes))); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(2); err != nil {
|
|
return nil, err
|
|
}
|
|
for i := range messageTypes {
|
|
if err = terminalMessage.WriteShort(uint16(messageTypes[i])); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for i := len(messageTypes); i < 32; i++ {
|
|
if err = terminalMessage.WriteShort(0); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
/*
|
|
if err = terminalMessage.FillZero(uint32(2 * (32 - len(messageTypes)))); err != nil {
|
|
return nil, err
|
|
}*/
|
|
|
|
if err = terminalMessage.FillZero(52); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiGroupAttachRequest(groupConfig []GroupConfig) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(384, tmkind.IpApiGroupAttachRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(4); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, group := range groupConfig {
|
|
if err = terminalMessage.WriteTFAddress(*group.Group); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for i := 0; i < 8-len(groupConfig); i++ {
|
|
if err = terminalMessage.WriteTFAddress(TetraFlexAddressEmpty); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if err = terminalMessage.FillZero(52); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
|
|
func NewTMIpApiSoftwareInfoRequest(ref byte) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiSoftwareInfoRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(ref); err != nil {
|
|
return nil, err
|
|
}
|
|
//Fill 55
|
|
if err = terminalMessage.FillZero(55); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiSubscriberInfoRequest(address TetraFlexAddress) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiSubscriberInfoRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteTFAddress(address); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(16); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiCallSetupRequest(address TetraFlexAddress, callType TetraFlexCallTypes, callPriority TetraFlexCallPriorities, hookCall bool, identityInfo TetraFlexIdentityInfo) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(192, tmkind.IpApiCallSetupRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(byte(callType)); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(byte(callPriority)); err != nil {
|
|
return nil, err
|
|
}
|
|
if hookCall {
|
|
if err = terminalMessage.WriteByte(4); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err = terminalMessage.WriteByte(0); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if err = terminalMessage.WriteTFAddress(address); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoAddress
|
|
if err = terminalMessage.WriteIdentityInfoAddress(identityInfo); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoDescr (protoHelper1:334)
|
|
if err = terminalMessage.WriteString(identityInfo.Description, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoKind
|
|
if err = terminalMessage.WriteIdentityInfoKind(identityInfo); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteByte 0
|
|
if err = terminalMessage.WriteByte(0); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoUnfied ()
|
|
if err = terminalMessage.WriteIdentityInfoUnfied(identityInfo); err != nil {
|
|
return nil, err
|
|
}
|
|
//Fill 33
|
|
if err = terminalMessage.FillZero(33); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiCallConnectRequest(callRef byte) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiCallConnectRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(callRef); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(55); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiCallDisconnectRequest(callRef byte, disconnectCause TetraFlexCallDisconnectCauses) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiCallDisconnectRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(callRef); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(byte(disconnectCause)); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(54); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiCallStreamRequest(uint1 uint, callRef byte, streamRef byte, audioChannelType TetraFlexAudioChannelTypes) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiCallStreamRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(callRef); err != nil {
|
|
return nil, err
|
|
}
|
|
if audioChannelType < AudioChannel_CMoIP_uLaw {
|
|
switch audioChannelType {
|
|
case AudioChannel_RTP_uLaw:
|
|
if err = terminalMessage.WriteByte(1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(0); err != nil {
|
|
return nil, err
|
|
}
|
|
case AudioChannel_RTP_aLaw:
|
|
if err = terminalMessage.WriteByte(1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(8); err != nil {
|
|
return nil, err
|
|
}
|
|
default:
|
|
if audioChannelType == AudioChannel_CMoIP_uLaw {
|
|
if err = terminalMessage.WriteByte(2); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(16); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if audioChannelType == AudioChannel_CMoIP_aLaw {
|
|
if err = terminalMessage.WriteByte(2); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(1); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if audioChannelType == AudioChannel_CMoIP_Tetra {
|
|
if err = terminalMessage.WriteByte(2); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(2); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
if err = terminalMessage.WriteByte(streamRef); err != nil {
|
|
return nil, err
|
|
}
|
|
//Fill 52
|
|
if err = terminalMessage.FillZero(52); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiCallPTTRequest(callRef byte, identityInfo TetraFlexIdentityInfo, octaStateByte byte) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(128, tmkind.IpApiCallPttRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(callRef); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(octaStateByte); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(2); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoAddress
|
|
if err = terminalMessage.WriteIdentityInfoAddress(identityInfo); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoDescr (protoHelper1:334)
|
|
if err = terminalMessage.WriteString(identityInfo.Description, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoKind
|
|
if err = terminalMessage.WriteIdentityInfoKind(identityInfo); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoUnfied ()
|
|
if err = terminalMessage.WriteIdentityInfoUnfied(identityInfo); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(10); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|
|
func NewTMIpApiCallPTTRelease(callRef byte) (tm *TerminalMessage, err error) {
|
|
terminalMessage, err := NewTerminalMessage(128, tmkind.IpApiCallPttRequest, NextHandlerID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(callRef); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.WriteByte(255); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(2); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoAddress
|
|
if err = terminalMessage.WriteTFAddress(TetraFlexAddressEmpty); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoDescr (protoHelper1:334)
|
|
if err = terminalMessage.WriteString("", 64); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoKind
|
|
if err = terminalMessage.WriteByte(0); err != nil {
|
|
return nil, err
|
|
}
|
|
//WriteIdentityInfoUnfied ()
|
|
if err = terminalMessage.WriteByte(0); err != nil {
|
|
return nil, err
|
|
}
|
|
if err = terminalMessage.FillZero(10); err != nil {
|
|
return nil, err
|
|
}
|
|
return terminalMessage, nil
|
|
}
|