-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Better organization hand handling of data resending
- Loading branch information
Showing
3 changed files
with
193 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"sync" | ||
"time" | ||
) | ||
|
||
var responseManager = &_responseManager{make(map[int]*responseListener), sync.Mutex{}, make(chan int)} | ||
|
||
type _responseManager struct { | ||
// Struct to manage which responses we are waiting for | ||
mapping map[int]*responseListener | ||
lock sync.Mutex | ||
resolved chan int | ||
} | ||
|
||
type responseListener struct { | ||
// Struct to manage waiting for responses | ||
packet Packet | ||
timer *time.Timer | ||
recv chan error | ||
resend chan Packet | ||
} | ||
|
||
func (rman *_responseManager) addPacket(p Packet) { // Add a packet to the response map and start waiting for it | ||
rl := &responseListener{p, time.NewTimer(10 * time.Second), make(chan error), client.resend} | ||
rman.lock.Lock() // Safe map access | ||
defer rman.lock.Unlock() | ||
rman.mapping[p.ID] = rl | ||
go rl.awaitResponse() // Start waiting | ||
} | ||
|
||
func (rman *_responseManager) received(p Packet) { | ||
rman.lock.Lock() | ||
listener, found := rman.mapping[p.ID] // Get the response listener | ||
rman.lock.Unlock() | ||
|
||
if !found { | ||
fmt.Printf("Well, we received a response for packet %v, which is unexpected because there's no listener for it\n", p.ID) | ||
return | ||
} | ||
|
||
var err error = nil | ||
|
||
message := string(p.Message) // See what the message was | ||
if message != messageReceived { // The only one that's implemented right now is messageReceived so this shouldn't fail | ||
err = errors.New(fmt.Sprintf("Unexpected response message for packet %v: %v\n", p.ID, message)) | ||
} else { | ||
fmt.Printf("Got good response for packet %v\n", p.ID) | ||
} | ||
|
||
listener.recv <- err | ||
} | ||
|
||
func (rman *_responseManager) remove(id int) { | ||
rman.lock.Lock() | ||
defer rman.lock.Unlock() | ||
delete(rman.mapping, id) | ||
} | ||
|
||
func (rl *responseListener) awaitResponse() { // Gets a message from the timer or the Recv channel | ||
select { | ||
case <-rl.timer.C: // Timer expires, no response | ||
fmt.Printf("Didn't get a response for packet %v, queueing for resend...\n", rl.packet.ID) | ||
client.resend <- rl.packet | ||
responseManager.remove(rl.packet.ID) | ||
|
||
case err := <-rl.recv: // We got a response | ||
rl.timer.Stop() // Stop that timer | ||
if err != nil { // Something went wrong, resend TODO: probably check to make sure this is a server-side error | ||
fmt.Printf("Response to packet %v was an error: %v\n", rl.packet.ID, err) | ||
fmt.Printf("Queueing packet %v for resend...\n", rl.packet.ID) | ||
client.resend <- rl.packet | ||
} | ||
responseManager.remove(rl.packet.ID) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.