Skip to content

Commit 057c7df

Browse files
committed
Add publish ack timeout
+Retry last publish on timeout +Disconnect on 5th retry on same packet
1 parent 369bd88 commit 057c7df

File tree

3 files changed

+38
-15
lines changed

3 files changed

+38
-15
lines changed

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
func main() {
99
done := make(chan bool)
10-
com, err := protocol.NewComHandler("COM6", 115200, done)
10+
com, err := protocol.NewComHandler("COM3", 115200, done)
1111
if err != nil {
1212
log.Fatalf("Error starting COM Handler: %v", err)
1313
}

protocol/COMHandler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net"
77
)
88

9+
// Connection State
910
const (
1011
disconnected = iota
1112
connected

protocol/protocol.go

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99
)
1010

11+
// Protocol Commands
1112
const (
1213
connect = iota
1314
connack
@@ -58,6 +59,7 @@ PACKET_RX_LOOP:
5859
return
5960
}
6061
case <-time.After(time.Millisecond * 100):
62+
log.Println("<<<Packet in from COM TIMEOUT")
6163
continue PACKET_RX_LOOP // discard
6264
}
6365

@@ -99,11 +101,11 @@ PACKET_RX_LOOP:
99101
continue PACKET_RX_LOOP
100102
}
101103

102-
// Packet receive done. Process it.
103104
com.handleRxPacket(&p)
104105
}
105106
}
106107

108+
// Packet RX done. Handle it.
107109
func (com *comHandler) handleRxPacket(packet *Packet) {
108110
rxSeqFlag := (packet.command & 0x80) > 0
109111
switch packet.command & 0x7F {
@@ -117,53 +119,73 @@ func (com *comHandler) handleRxPacket(packet *Packet) {
117119
}
118120
}
119121
case acknowledge:
120-
com.acknowledgeEvent <- rxSeqFlag // TODO: if not connected this will block forever
122+
if com.state == connected {
123+
com.acknowledgeEvent <- rxSeqFlag
124+
}
121125
case connect:
122-
log.Println("got CONNECT PACKET")
123126
if com.state != disconnected {
124127
return
125128
}
126129
if len(packet.payload) != 6 {
127130
return
128131
}
132+
129133
port := binary.LittleEndian.Uint16(packet.payload[4:])
130-
destination := strconv.Itoa(int(packet.payload[0])) + "." + strconv.Itoa(int(packet.payload[1])) + "." + strconv.Itoa(int(packet.payload[2])) + "." + strconv.Itoa(int(packet.payload[3])) + ":" + strconv.Itoa(int(port))
134+
135+
destination := strconv.Itoa(int(packet.payload[0])) + "."
136+
destination += strconv.Itoa(int(packet.payload[1])) + "."
137+
destination += strconv.Itoa(int(packet.payload[2])) + "."
138+
destination += strconv.Itoa(int(packet.payload[3])) + ":"
139+
destination += strconv.Itoa(int(port))
140+
131141
log.Printf("Dialing to: %v", destination)
132142
if err := com.dialTCP(destination); err != nil { // TODO: add timeout
143+
log.Printf("Failed to connect to: %v", destination)
133144
com.txBuffer <- Packet{command: disconnect} // TODO: payload to contain error or timeout
134145
return
135146
}
147+
log.Printf("Connected")
136148
com.startEvent <- true
137149
com.state = connected
138150
com.txBuffer <- Packet{command: connack}
139151
}
140152
}
141153

142-
// Publish packet received from a channel.
143-
// Will block for second publish, until ack is received for first.
154+
// Publish data received from upstream tcp server.
155+
// We need to get an Ack before sending the next publish packet.
156+
// Resend same publish packet after timeout, and kill link after 5 retries.
144157
func (com *comHandler) packetSender() {
145158
sequenceTxFlag := false
159+
retries := 0
146160
tx := make([]byte, 512)
147161
for {
148162
nRx, err := com.tcpLink.Read(tx)
149163
if err != nil {
150164
log.Fatal("Error Receiving from TCP")
151165
}
152-
log.Println(">>>Packet out to COM START")
153-
log.Println("------------------->>>>>>>")
154166
p := Packet{command: publish, payload: tx[:nRx]}
155167
if sequenceTxFlag {
156168
p.command |= 0x80
157169
}
170+
PUB_LOOP:
158171
for {
159172
com.txBuffer <- p
160-
ack := <-com.acknowledgeEvent
161-
if ack == sequenceTxFlag {
162-
sequenceTxFlag = !sequenceTxFlag
163-
break
173+
select {
174+
case ack := <-com.acknowledgeEvent:
175+
retries = 0
176+
if ack == sequenceTxFlag {
177+
sequenceTxFlag = !sequenceTxFlag
178+
break PUB_LOOP // success
179+
}
180+
case <-time.After(time.Millisecond * 500):
181+
retries++
182+
if retries >= 5 {
183+
com.txBuffer <- Packet{command: disconnect}
184+
com.state = disconnected
185+
log.Println("Too many send retries. Client disconnected")
186+
return
187+
}
164188
}
165-
log.Println(">>>RETRY out to COM")
166189
}
167-
log.Println(">>>Packet out to COM DONE")
168190
}
169191
}

0 commit comments

Comments
 (0)