Fix slow exchanges on linux by adding polling and other improvements (#14)

* add prints to investigate slowness

* add loop sleep for blocking Stack

* add connection close http attribute and detect end of HTML page

* add timeout to bridge read

* examples/xnet: add ntp timestamp to prints and show output in readme

* add polling to http tap interface

* more digits in ntp format

* prevent crashes on non-8 timestamp
This commit is contained in:
Pat Whittingslow
2026-01-01 09:35:35 -03:00
committed by GitHub
parent 3cbef6fa92
commit f8166aea05
9 changed files with 297 additions and 36 deletions
+45 -14
View File
@@ -26,6 +26,16 @@ type Interface interface {
IPMask() (netip.Prefix, error)
}
type HTTPTapClient struct {
c http.Client
infoURL string
recvurl string
sendurl string
ip netip.Prefix
hwaddr [6]byte
buf []byte
}
var _ Interface = (*HTTPTapClient)(nil)
// NewHTTPTapClient returns a HTTPTapClient ready for use.
@@ -65,12 +75,7 @@ func (h *HTTPTapClient) ensureMTU() (err error) {
err = fmt.Errorf("unable to get MTU from server: %w", err)
}
}()
resp, err := h.c.Get(h.infoURL)
if err != nil {
return err
}
var info tapInfo
err = json.NewDecoder(resp.Body).Decode(&info)
info, err := h.info()
if err != nil {
return err
} else if info.MTU <= minMTU {
@@ -88,14 +93,14 @@ func (h *HTTPTapClient) ensureMTU() (err error) {
return nil
}
type HTTPTapClient struct {
c http.Client
infoURL string
recvurl string
sendurl string
ip netip.Prefix
hwaddr [6]byte
buf []byte
func (h *HTTPTapClient) info() (tapInfo, error) {
resp, err := h.c.Get(h.infoURL)
if err != nil {
return tapInfo{}, err
}
var info tapInfo
err = json.NewDecoder(resp.Body).Decode(&info)
return info, err
}
func (h *HTTPTapClient) ReadDiscard() (err error) {
@@ -109,6 +114,24 @@ func (h *HTTPTapClient) ReadDiscard() (err error) {
return err
}
func (h *HTTPTapClient) Poll(d time.Duration) (ready bool, err error) {
info, err := h.info()
if err != nil {
return false, err
} else if info.DataReady {
return true, nil
}
deadline := time.Now().Add(d)
for !info.DataReady && time.Until(deadline) > 0 {
time.Sleep(5 * time.Millisecond)
info, err = h.info()
if err != nil {
return false, err
}
}
return info.DataReady, err
}
func (h *HTTPTapClient) ReadBytes() (data []byte, err error) {
err = h.ensureMTU()
if err != nil {
@@ -177,6 +200,7 @@ type tapInfo struct {
MTU int
IPPrefix string
HardwareAddr string
DataReady bool
}
func (sv *HTTPTapServer) OnTransfer(cb func(channel int, pkt []byte)) {
@@ -255,10 +279,17 @@ func NewHTTPTapServer(iface Interface, minMTU, queueOut, queueIn int) (*HTTPTapS
hwstr := net.HardwareAddr(hw6[:]).String()
ipstr := netmask.String()
sv.HandleFunc("/info", func(w http.ResponseWriter, r *http.Request) {
var dataready bool = true
if poller, ok := taps.tap.(interface {
Poll(time.Duration) (bool, error)
}); ok {
dataready, err = poller.Poll(0)
}
info := tapInfo{
MTU: mtu,
IPPrefix: ipstr,
HardwareAddr: hwstr,
DataReady: dataready,
}
json.NewEncoder(w).Encode(info)
})