diff --git a/tcpclient.go b/tcpclient.go index 283e1dd..1582e89 100644 --- a/tcpclient.go +++ b/tcpclient.go @@ -155,6 +155,15 @@ func (mb *tcpTransporter) Send(aduRequest []byte) (aduResponse []byte, err error return } + // If an answer to a previously timed-out request is already in teh buffer, this will result + // in a transaction ID mismatch from which we will never recover. To prevent this, just + // flush any previous reponses before launching the next poll. That's throwing away + // possibly useful data, but the previous request was already satisfied with a timeout + // error so that probably makes the most sense here. + + // Be aware that this call resets the read deadline. + mb.flushAll() + // Set timer to close when idle mb.lastActivity = time.Now() mb.startCloseTimer() @@ -332,3 +341,27 @@ func (mb *tcpTransporter) closeIdle() { mb.close() } } + +// flushAll implements a non-blocking read flush. Be warned it resets +// the read deadline. +func (mb *tcpTransporter) flushAll() (int, error) { + if err := mb.conn.SetReadDeadline(time.Now()); err != nil { + return 0, err + } + + count := 0 + buffer := make([]byte, 1024) + + for { + n, err := mb.conn.Read(buffer) + + if err != nil { + return count + n, err + } else if n > 0 { + count = count + n + } else { + // didn't flush any new bytes, return + return count, err + } + } +}