hopp: Add SetDeadline methods to Conn and Trans

This commit is contained in:
2025-09-05 18:48:12 -04:00
parent 44fb561758
commit 12fbfa6293
3 changed files with 92 additions and 11 deletions

View File

@@ -1,9 +1,11 @@
package hopp
import "io"
import "os"
import "fmt"
import "net"
import "sync"
import "time"
import "sync/atomic"
import "git.tebibyte.media/sashakoshka/go-util/sync"
@@ -108,6 +110,10 @@ func (this *a) AcceptTrans() (Trans, error) {
}
}
func (this *a) SetDeadline(t time.Time) error {
return this.underlying.SetDeadline(t)
}
func (this *a) SetSizeLimit(limit int64) {
this.sizeLimit = limit
}
@@ -212,6 +218,10 @@ type transA struct {
currentWriter io.Closer
writeBuffer []byte
closed atomic.Bool
closeErr error
deadline *time.Timer
deadlineLock sync.Mutex
}
func (this *transA) Close() error {
@@ -221,6 +231,11 @@ func (this *transA) Close() error {
return err
}
func (this *transA) closeWithError(err error) error {
this.closeErr = err
return this.Close()
}
func (this *transA) closeDontUnlist() (err error) {
// MUST be goroutine safe
this.incoming.Close()
@@ -269,9 +284,9 @@ func (this *transA) Receive() (method uint16, data []byte, err error) {
}
func (this *transA) ReceiveReader() (uint16, io.Reader, error) {
// if the transaction has been closed, return an io.EOF
if this.closed.Load() {
return 0, nil, io.EOF
// if the transaction has been closed, return an appropriate error.
if err := this.errIfClosed(); err != nil {
return 0, nil, err
}
// drain previous reader if necessary
@@ -289,6 +304,54 @@ func (this *transA) ReceiveReader() (uint16, io.Reader, error) {
return method, reader, nil
}
func (this *transA) SetDeadline(t time.Time) error {
this.deadlineLock.Lock()
defer this.deadlineLock.Unlock()
if t == (time.Time { }) {
if this.deadline != nil {
this.deadline.Stop()
}
return nil
}
until := time.Until(t)
if this.deadline == nil {
this.deadline.Reset(until)
return nil
}
this.deadline = time.AfterFunc(until, func () {
this.closeWithError(os.ErrDeadlineExceeded)
})
return nil
}
// TODO
// func (this *transA) SetReadDeadline(t time.Time) error {
// // TODO
// }
//
// func (this *transA) SetWriteDeadline(t time.Time) error {
// // TODO
// }
func (this *transA) errIfClosed() error {
if !this.closed.Load() {
return nil
}
return this.bestErr()
}
func (this *transA) bestErr() error {
if this.parent.err != nil {
return this.parent.err
}
if this.closeErr != nil {
return this.closeErr
}
return io.EOF
}
type readerA struct {
parent *transA
leftover []byte
@@ -319,11 +382,7 @@ func (this *readerA) pull() (uint16, error) {
// close and return error on failure
this.eof = true
this.parent.Close()
if this.parent.parent.err == nil {
return 0, fmt.Errorf("could not receive message: %w", io.EOF)
} else {
return 0, this.parent.parent.err
}
return 0, fmt.Errorf("could not receive message: %w", this.parent.bestErr())
}
func (this *readerA) Read(buffer []byte) (int, error) {