diff --git a/main.go b/main.go index d9afd47..9af3cdf 100644 --- a/main.go +++ b/main.go @@ -6,12 +6,20 @@ import ( "encoding/binary" "fmt" "net" + "os" + "os/signal" + "syscall" "time" "github.com/nonoo/kappanhang/log" ) var conn *net.UDPConn +var localSID uint32 +var remoteSID uint32 +var sendSeq uint16 +var longPingSendSeq uint16 +var authID [6]byte func send(d []byte) { _, err := conn.Write(d) @@ -36,9 +44,27 @@ func read() ([]byte, error) { return b[:n], err } +func setupCloseHandler() { + c := make(chan os.Signal) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + go func() { + <-c + log.Print("disconnecting") + send([]byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, byte(sendSeq), byte(sendSeq >> 8), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), + 0x00, 0x00, 0x00, 0x30, 0x01, 0x01, 0x00, byte(longPingSendSeq), + byte(longPingSendSeq >> 8), 0x00, authID[0], authID[1], authID[2], authID[3], authID[4], authID[5], + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + os.Exit(0) + }() +} + func main() { log.Init() parseArgs() + setupCloseHandler() hostPort := fmt.Sprint(connectAddress, ":", connectPort) log.Print("connecting to ", hostPort) @@ -53,7 +79,7 @@ func main() { // Constructing the local session ID by combining the local IP address and port. laddr := conn.LocalAddr().(*net.UDPAddr) - localSID := binary.BigEndian.Uint32(laddr.IP[len(laddr.IP)-4:])<<16 | uint32(laddr.Port&0xffff) + localSID = binary.BigEndian.Uint32(laddr.IP[len(laddr.IP)-4:])<<16 | uint32(laddr.Port&0xffff) log.Debugf("using session id %.8x", localSID) send([]byte{0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00}) @@ -62,7 +88,6 @@ func main() { // send([]byte{0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x3e, 0x10, 0x00}) // send([]byte{0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00}) - var remoteSID uint32 for { r, _ := read() if bytes.Equal(r[:8], []byte{0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}) { @@ -75,8 +100,8 @@ func main() { send([]byte{0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID)}) send([]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), - 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x09, 0x27, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, byte(longPingSendSeq), + byte(longPingSendSeq >> 8), 0x00, 0x09, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -90,14 +115,12 @@ func main() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) - var sendSeq uint8 - var lastReceivedSeq uint8 + var lastReceivedSeq uint16 var receivedSeq bool var lastPingAt time.Time var lastLongPingAt time.Time var errCount int var randID [4]byte - var authID [6]byte for { r, err := read() if err != nil { @@ -130,25 +153,25 @@ func main() { } } if len(r) == 21 && bytes.Equal(r[1:6], []byte{0x00, 0x00, 0x00, 0x07, 0x00}) { - gotSeq := r[6] + // Replying to the radio. + // Example request from radio: 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1c, 0x0e, 0xe4, 0x35, 0xdd, 0x72, 0xbe, 0xd9, 0xf2, 0x63, 0x00, 0x57, 0x2b, 0x12, 0x00 + // Example answer from PC: 0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1c, 0x0e, 0xbe, 0xd9, 0xf2, 0x63, 0xe4, 0x35, 0xdd, 0x72, 0x01, 0x57, 0x2b, 0x12, 0x00 + gotSeq := binary.LittleEndian.Uint16(r[6:8]) if receivedSeq && lastReceivedSeq+1 != gotSeq { log.Error("packet loss detected") } lastReceivedSeq = gotSeq receivedSeq = true - // Replying to the radio. - // Example request from radio: 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1c, 0x0e, 0xe4, 0x35, 0xdd, 0x72, 0xbe, 0xd9, 0xf2, 0x63, 0x00, 0x57, 0x2b, 0x12, 0x00 - // Example answer from PC: 0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1c, 0x0e, 0xbe, 0xd9, 0xf2, 0x63, 0xe4, 0x35, 0xdd, 0x72, 0x01, 0x57, 0x2b, 0x12, 0x00 - send([]byte{0x15, 0x00, 0x00, 0x00, 0x07, 0x00, gotSeq, r[7], byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x01, + send([]byte{0x15, 0x00, 0x00, 0x00, 0x07, 0x00, byte(gotSeq), byte(gotSeq >> 8), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x01, r[17], r[18], r[19], r[20]}) } if len(r) == 16 && bytes.Equal(r[:6], []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}) { // Replying to the radio. // Example request from radio: 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0xe4, 0x35, 0xdd, 0x72, 0xbe, 0xd9, 0xf2, 0x63 // Example answer from PC: 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0xbe, 0xd9, 0xf2, 0x63, 0xe4, 0x35, 0xdd, 0x72 - gotSeq := r[6] - send([]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, gotSeq, r[7], byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID)}) + gotSeq := binary.LittleEndian.Uint16(r[6:8]) + send([]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, byte(gotSeq), byte(gotSeq >> 8), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID)}) } if time.Since(lastPingAt) >= 100*time.Millisecond { @@ -158,13 +181,13 @@ func main() { if err != nil { log.Fatal(err) } - send([]byte{0x15, 0x00, 0x00, 0x00, 0x07, 0x00, sendSeq, 0x00, byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x01, + send([]byte{0x15, 0x00, 0x00, 0x00, 0x07, 0x00, byte(sendSeq), byte(sendSeq >> 8), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x01, randID[0], randID[1], randID[2], randID[3]}) - send([]byte{0x10, 0x00, 0x00, 0x00, 0x03, 0x00, sendSeq, 0x00, byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID)}) + send([]byte{0x10, 0x00, 0x00, 0x00, 0x03, 0x00, byte(sendSeq), byte(sendSeq >> 8), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID)}) sendSeq++ lastPingAt = time.Now() - if time.Since(lastLongPingAt) >= 60*time.Second { + if time.Since(lastLongPingAt) >= 30*time.Second { // Example request from PC: 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, // 0xbb, 0x41, 0x3f, 0x2b, 0xe6, 0xb2, 0x7b, 0x7b, // 0x00, 0x00, 0x00, 0x30, 0x01, 0x05, 0x00, 0x02, @@ -181,9 +204,9 @@ func main() { // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - send([]byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, sendSeq, 0x00, byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), - 0x00, 0x00, 0x00, 0x30, 0x01, 0x05, 0x00, 0x3f, - 0x00, 0x00, authID[0], authID[1], authID[2], authID[3], authID[4], authID[5], + send([]byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, byte(sendSeq), byte(sendSeq >> 8), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), + 0x00, 0x00, 0x00, 0x30, 0x01, 0x05, 0x00, byte(longPingSendSeq), + byte(longPingSendSeq >> 8), 0x00, authID[0], authID[1], authID[2], authID[3], authID[4], authID[5], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,