Files
lneto/x/xnet/stack-retrying.go
T
2025-08-03 11:30:51 -03:00

99 lines
2.4 KiB
Go

package xnet
import (
"errors"
"net/netip"
"time"
"github.com/soypat/lneto/tcp"
)
func (s *StackAsync) StackRetrying() StackRetrying {
return StackRetrying{
block: s.StackBlocking(),
}
}
var (
errRetriesExceeded = errors.New("cywnet: retries exceeded")
)
type StackRetrying struct {
block StackBlocking
}
func (s StackRetrying) DoDHCPv4(reqAddr [4]byte, timeout time.Duration, retries int) (results *DHCPResults, err error) {
expectEnd := time.Now().Add(timeout * time.Duration(retries))
for i := 0; i < retries; i++ {
if i > 0 {
println("Retrying DHCP")
}
results, err = s.block.DoDHCPv4(reqAddr, timeout)
if err == nil {
return results, nil
}
}
if time.Now().Before(expectEnd) {
return nil, err
}
return nil, errRetriesExceeded
}
func (s StackRetrying) DoNTP(ntpHost netip.Addr, timeout time.Duration, retries int) (offset time.Duration, err error) {
expectEnd := time.Now().Add(timeout * time.Duration(retries))
for i := 0; i < retries; i++ {
if i > 0 {
println("Retrying DHCP")
}
offset, err = s.block.DoNTP(ntpHost, timeout)
if err == nil {
return offset, nil
}
}
if time.Now().Before(expectEnd) {
return -1, err
}
return -1, errRetriesExceeded
}
func (s StackRetrying) DoLookupIP(host string, timeout time.Duration, retries int) (addrs []netip.Addr, err error) {
expectEnd := time.Now().Add(timeout * time.Duration(retries))
for i := 0; i < retries; i++ {
addrs, err = s.block.DoLookupIP(host, timeout)
if err == nil {
return addrs, nil
}
}
if time.Now().Before(expectEnd) {
return addrs, err
}
return nil, errRetriesExceeded
}
func (s StackRetrying) DoResolveHardwareAddress6(addr netip.Addr, timeout time.Duration, retries int) (hw [6]byte, err error) {
expectEnd := time.Now().Add(timeout * time.Duration(retries))
for i := 0; i < retries; i++ {
hw, err = s.block.DoResolveHardwareAddress6(addr, timeout)
if err == nil {
return hw, nil
}
}
if time.Now().Before(expectEnd) {
return hw, err
}
return hw, errRetriesExceeded
}
func (s StackRetrying) DoDialTCP(localPort uint16, addrp netip.AddrPort, timeout time.Duration, retries int) (conn *tcp.Conn, err error) {
expectEnd := time.Now().Add(timeout * time.Duration(retries))
for i := 0; i < retries; i++ {
conn, err = s.block.DoDialTCP(localPort, addrp, timeout)
if err == nil {
return conn, nil
}
}
if time.Now().Before(expectEnd) {
return conn, err
}
return nil, errRetriesExceeded
}