diff --git a/common/terminalClient.go b/common/terminalClient.go index 0022449..748c9f7 100644 --- a/common/terminalClient.go +++ b/common/terminalClient.go @@ -2,29 +2,35 @@ package common import ( "bufio" + "crypto/rand" "encoding/binary" + "encoding/hex" "fmt" "io" "net" - "test/common/tmkind" + + "git.cheetah.cat/cheetah/opentetraflex-go/common/tmkind" ) type TerminalClient struct { - address string - conn net.Conn - netWriter *bufio.Writer - netReader *bufio.Reader - GroupConfig []GroupConfig + address string + conn net.Conn + netWriter *bufio.Writer + netReader *bufio.Reader - HandlerMap map[uint32]chan any + HandlerMap map[uint32]chan HandlerResponse RX chan *TerminalMessageResponse + + GroupConfig []GroupConfig + RegistrationInfo RegistrationInfo } func NewTerminalClient(address string) (tc *TerminalClient) { return &TerminalClient{ - address: address, - RX: make(chan *TerminalMessageResponse), + address: address, + RX: make(chan *TerminalMessageResponse), + HandlerMap: make(map[uint32]chan HandlerResponse), } } func (tc *TerminalClient) Connect() (err error) { @@ -49,6 +55,82 @@ func (tc *TerminalClient) Send(message *TerminalMessage) (err error) { } return nil } + +func (tc *TerminalClient) Authenticate(addr TetraFlexAddress) (err error) { + randomBytes := make([]byte, 10) + _, err = rand.Read(randomBytes) + if err != nil { + return err + } + // 20160111 + tfAuthReq, err := NewTMAuthReq(addr, 0, randomBytes, 1, "OpenTetraFlex-Go", 20230831, "1.0.0") + if err != nil { + return err + } + tc.HandlerMap[tfAuthReq.handler] = make(chan HandlerResponse) + + //fmt.Println(hex.EncodeToString(tfAuthReq.Encode())) + err = tc.Send(tfAuthReq) + if err != nil { + return err + } + response := <-tc.HandlerMap[tfAuthReq.handler] + if !response.Success { + return response.Error + } + tc.RegistrationInfo, err = response.TMR.AsRegistrationInfo() + if err != nil { + return err + } + return nil +} +func (tc *TerminalClient) AttachGroups(groups []GroupConfig) (err error) { + tfGroupAttachReq, err := NewTMIpApiGroupAttachRequest(groups) + if err != nil { + panic(err) + } + fmt.Println(hex.EncodeToString(tfGroupAttachReq.Encode())) + tc.HandlerMap[tfGroupAttachReq.handler] = make(chan HandlerResponse) + + //fmt.Println(hex.EncodeToString(tfAuthReq.Encode())) + err = tc.Send(tfGroupAttachReq) + if err != nil { + return err + } + response := <-tc.HandlerMap[tfGroupAttachReq.handler] + if !response.Success { + return response.Error + } + + return nil +} +func (tc *TerminalClient) CallSetup(address TetraFlexAddress, callType TetraFlexCallTypes, callPriority TetraFlexCallPriorities, hookCall bool, identityInfo TetraFlexIdentityInfo) (err error) { + // + return nil +} + +func (tc *TerminalClient) PTTRequest() { + // IpApiCallPttRequest +} + +/* +groupAddr := common.NewAddressFromSSINumber(103) +identityNum := common.NewAddressFromSSINumber(1007) + + response, err = common.NewTMIpApiCallSetupRequest(*groupAddr, common.CallTypeGroup, common.CallPriorityDefault, false, common.TetraFlexIdentityInfo{ + Description: "blurb", + Kind: common.IdentityKindTerminal, + Address: *identityNum, + UnifiedSSIKinds: common.UnifiedKindPersonalNumber, + }) + + if err != nil { + panic(err) + } + +fmt.Println(hex.EncodeToString(response.Encode())) +terminalClient.Send(response) +*/ func (tc *TerminalClient) rxLoop() { var err error for { @@ -85,7 +167,31 @@ func (tc *TerminalClient) rxLoop() { if err != nil { panic(err) } - tc.RX <- parsedResp + if _, ok := tc.HandlerMap[messageHandler]; ok { + tc.HandlerMap[messageHandler] <- HandlerResponse{ + Success: true, + TMR: parsedResp, + } + delete(tc.HandlerMap, messageHandler) + } else { + // Lets Handle KeepAlive for ourself + if parsedResp.Kind == tmkind.IpApiKeepAliveChallenge { + challenge, err := parsedResp.AsKeepAliveChallenge() + if err != nil { + panic(err) + } + response, err := NewTMKeepAliveResponse(challenge) + if err != nil { + panic(err) + } + err = tc.Send(response) + if err != nil { + panic(err) + } + continue + } + tc.RX <- parsedResp + } } } diff --git a/common/terminalMessage.go b/common/terminalMessage.go index fbe6180..a82ccef 100644 --- a/common/terminalMessage.go +++ b/common/terminalMessage.go @@ -2,9 +2,15 @@ package common import ( "bytes" - "test/common/tmkind" + "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 @@ -180,7 +186,7 @@ func (tm *TerminalMessage) Encode() []byte { } 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, 0) + tfAuthReq, err := NewTerminalMessage(256, tmkind.IpApiRegistrationRequest, NextHandlerID()) if err != nil { return nil, err } @@ -227,7 +233,7 @@ func NewTMAuthReq(addr TetraFlexAddress, num uint32, randomBytes []byte, termina } func NewTMKeepAliveResponse(challenge KeepAliveChallenge) (tm *TerminalMessage, err error) { response := KeepAliveResponse{} - terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiKeepAliveResponse, 0) + terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiKeepAliveResponse, NextHandlerID()) if err != nil { return nil, err } @@ -258,7 +264,7 @@ func NewTMKeepAliveResponse(challenge KeepAliveChallenge) (tm *TerminalMessage, return terminalMessage, nil } func NewTMNotificationRequest(messageTypes []tmkind.TetraFlexTerminalMessageKinds) (tm *TerminalMessage, err error) { - terminalMessage, err := NewTerminalMessage(128, tmkind.IpApiNotificationRequest, 0) + terminalMessage, err := NewTerminalMessage(128, tmkind.IpApiNotificationRequest, NextHandlerID()) if err != nil { return nil, err } @@ -290,7 +296,7 @@ func NewTMNotificationRequest(messageTypes []tmkind.TetraFlexTerminalMessageKind return terminalMessage, nil } func NewTMIpApiGroupAttachRequest(groupConfig []GroupConfig) (tm *TerminalMessage, err error) { - terminalMessage, err := NewTerminalMessage(384, tmkind.IpApiGroupAttachRequest, 0) + terminalMessage, err := NewTerminalMessage(384, tmkind.IpApiGroupAttachRequest, NextHandlerID()) if err != nil { return nil, err } @@ -315,8 +321,49 @@ func NewTMIpApiGroupAttachRequest(groupConfig []GroupConfig) (tm *TerminalMessag return terminalMessage, nil } -func NewTMIpApiCallSetupRequest(address TetraFlexAddress, callType TetraFlexCallTypes, callPriority TetraFlexCallPriorities, idkBool bool, identityInfo TetraFlexIdentityInfo) (tm *TerminalMessage, err error) { - terminalMessage, err := NewTerminalMessage(192, tmkind.IpApiCallSetupRequest, 0) +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 + } + //Fill 55 + if err = terminalMessage.FillZero(55); 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 } @@ -329,7 +376,7 @@ func NewTMIpApiCallSetupRequest(address TetraFlexAddress, callType TetraFlexCall if err = terminalMessage.WriteByte(byte(callPriority)); err != nil { return nil, err } - if idkBool { + if hookCall { if err = terminalMessage.WriteByte(4); err != nil { return nil, err } @@ -367,9 +414,8 @@ func NewTMIpApiCallSetupRequest(address TetraFlexAddress, callType TetraFlexCall } return terminalMessage, nil } - -func NewTMSendIpApiCallStreamRequest(uint1 uint, callRef byte, streamRef byte, audioChannelType TetraFlexAudioChannelTypes) (tm *TerminalMessage, err error) { - terminalMessage, err := NewTerminalMessage(64, tmkind.IpApiCallStreamRequest, 0) +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 } @@ -429,3 +475,38 @@ func NewTMSendIpApiCallStreamRequest(uint1 uint, callRef byte, streamRef byte, a } 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 +} diff --git a/common/terminalMessageResponse.go b/common/terminalMessageResponse.go index 24db724..d11e35d 100644 --- a/common/terminalMessageResponse.go +++ b/common/terminalMessageResponse.go @@ -3,7 +3,8 @@ package common import ( "bytes" "encoding/binary" - "test/common/tmkind" + + "git.cheetah.cat/cheetah/opentetraflex-go/common/tmkind" ) type TerminalMessageResponse struct { @@ -14,6 +15,11 @@ type TerminalMessageResponse struct { data bytes.Buffer payload []byte } +type HandlerResponse struct { + Success bool + Error error + TMR *TerminalMessageResponse +} func NewTerminalMessageResponse(length uint16, kind tmkind.TetraFlexTerminalMessageKinds, handler uint32, payload []byte) (tm *TerminalMessageResponse, err error) { tm = &TerminalMessageResponse{ diff --git a/main.go b/main.go index e966d3b..0adb5bf 100644 --- a/main.go +++ b/main.go @@ -1,16 +1,20 @@ package main import ( - "crypto/rand" "encoding/hex" "encoding/json" "fmt" - "test/common" - "test/common/tmkind" + "math/rand" + "time" + + "git.cheetah.cat/cheetah/opentetraflex-go/common" + "git.cheetah.cat/cheetah/opentetraflex-go/common/tmkind" // "strings" ) func main() { + rand.Seed(time.Now().UnixNano()) + var err error terminalClient := common.NewTerminalClient("192.168.133.106:42381") @@ -20,22 +24,33 @@ func main() { panic(err) } - randomBytes := make([]byte, 10) - _, err = rand.Read(randomBytes) - if err != nil { - panic(err) - } myAddr := common.TetraFlexAddress{ Kind: common.UserNo, UserNo: "1005", } - // 20160111 - tfAuthReq, err := common.NewTMAuthReq(myAddr, 0, randomBytes, 1, "OpenTetraFlex", 20230831, "1.0.0") + err = terminalClient.Authenticate(myAddr) if err != nil { panic(err) } - fmt.Println(hex.EncodeToString(tfAuthReq.Encode())) - terminalClient.Send(tfAuthReq) + //fmt.Println(hex.EncodeToString(parsedMsg.Bytes())) + regInfoBytes, _ := json.Marshal(terminalClient.RegistrationInfo) + fmt.Println(string(regInfoBytes)) + + terminalClient.AttachGroups([]common.GroupConfig{ + { + Group: common.NewAddressFromSSINumber(101), + ScanMode: common.Scanned, + }, + { + Group: common.NewAddressFromSSINumber(102), + ScanMode: common.Scanned, + }, + { + Group: common.NewAddressFromSSINumber(103), + ScanMode: common.Scanned, + }, + }) + for { select { case parsedMsg := <-terminalClient.RX: @@ -50,72 +65,9 @@ func main() { //terminalClient.SendTM() } } - if parsedMsg.Kind == tmkind.IpApiKeepAliveChallenge { - challenge, err := parsedMsg.AsKeepAliveChallenge() - if err != nil { - panic(err) - } - keepAliveBytes, _ := json.Marshal(challenge) - fmt.Println(string(keepAliveBytes)) - response, err := common.NewTMKeepAliveResponse(challenge) - if err != nil { - panic(err) - } - fmt.Println(hex.EncodeToString(response.Encode())) - terminalClient.Send(response) - - // Send Subscribe - response, err = common.NewTMNotificationRequest([]tmkind.TetraFlexTerminalMessageKinds{ - tmkind.IpApiCallUpdateNotification, - tmkind.IpApiSdsTlReportNotification, - tmkind.IpApiSdsTlShortReportNotification, - tmkind.IpApiSdsDataType4Notification, - tmkind.IpApiSdsStatusNotification, - tmkind.IpApiSdsTlTransferNotification, - }) - if err != nil { - panic(err) - } - fmt.Println(hex.EncodeToString(response.Encode())) - terminalClient.Send(response) - - response, err = common.NewTMIpApiGroupAttachRequest([]common.GroupConfig{ - { - Group: common.NewAddressFromSSINumber(101), - ScanMode: common.Scanned, - }, - { - Group: common.NewAddressFromSSINumber(102), - ScanMode: common.Scanned, - }, - { - Group: common.NewAddressFromSSINumber(103), - ScanMode: common.Scanned, - }, - }) - if err != nil { - panic(err) - } - fmt.Println(hex.EncodeToString(response.Encode())) - terminalClient.Send(response) - - groupAddr := common.NewAddressFromSSINumber(103) - identityNum := common.NewAddressFromSSINumber(1007) - response, err = common.NewTMIpApiCallSetupRequest(*groupAddr, common.CallTypeGroup, common.CallPriorityDefault, false, common.TetraFlexIdentityInfo{ - Description: "blurb", - Kind: common.IdentityKindTerminal, - Address: *identityNum, - UnifiedSSIKinds: common.UnifiedKindPersonalNumber, - }) - if err != nil { - panic(err) - } - fmt.Println(hex.EncodeToString(response.Encode())) - terminalClient.Send(response) - - } if parsedMsg.Kind == tmkind.IpApiRegistrationConfirm { + regInfo, err := parsedMsg.AsRegistrationInfo() if err != nil { panic(err)