fix issues

This commit is contained in:
2026-06-13 16:55:57 +02:00
parent 00cab6b204
commit d3ba7c71f4
5 changed files with 61 additions and 23 deletions
+30 -5
View File
@@ -5,6 +5,7 @@ package ultrabeam
import (
"bufio"
"errors"
"fmt"
"log"
"net"
@@ -12,6 +13,17 @@ import (
"time"
)
// Connection tuning. Remote operation (the antenna controller reached over the
// internet, not the LAN) sees real latency and jitter, so the read timeout is
// generous and a few transient timeouts are tolerated before the link is torn
// down — otherwise a single slow reply dropped the whole connection and the
// client churned reconnect/disconnect.
const (
ubReadTimeout = 4 * time.Second // was 1s — too tight for a remote link
ubKeepAlive = 15 * time.Second // OS-level TCP keepalive
ubMaxPollTimeout = 3 // consecutive read timeouts tolerated before reconnecting
)
// Protocol constants
const (
STX byte = 0xF5 // 245 decimal
@@ -110,6 +122,7 @@ func (c *Client) pollLoop() {
defer ticker.Stop()
pollCount := 0
pollFails := 0 // consecutive failed status polls (transient timeouts tolerated)
for {
select {
@@ -120,7 +133,8 @@ func (c *Client) pollLoop() {
c.connMu.Lock()
if c.conn == nil {
log.Printf("Ultrabeam: Not connected, attempting connection...")
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", c.host, c.port), 5*time.Second)
dialer := net.Dialer{Timeout: 5 * time.Second, KeepAlive: ubKeepAlive}
conn, err := dialer.Dial("tcp", net.JoinHostPort(c.host, fmt.Sprintf("%d", c.port)))
if err != nil {
log.Printf("Ultrabeam: Connection failed: %v", err)
c.connMu.Unlock()
@@ -133,6 +147,7 @@ func (c *Client) pollLoop() {
}
c.conn = conn
c.reader = bufio.NewReader(c.conn)
pollFails = 0
log.Printf("Ultrabeam: Connected to %s:%d", c.host, c.port)
}
c.connMu.Unlock()
@@ -140,8 +155,17 @@ func (c *Client) pollLoop() {
// Query status
status, err := c.queryStatus()
if err != nil {
log.Printf("Ultrabeam: Failed to query status: %v", err)
// Close connection and retry
// A single slow/lost reply over a remote link is normal — keep
// the connection (and the last status) for a few tries before
// tearing it down, so we don't churn reconnect/disconnect.
var ne net.Error
transient := errors.As(err, &ne) && ne.Timeout()
pollFails++
if transient && pollFails < ubMaxPollTimeout {
log.Printf("Ultrabeam: status timeout (%d/%d), keeping link: %v", pollFails, ubMaxPollTimeout, err)
continue
}
log.Printf("Ultrabeam: Failed to query status, reconnecting: %v", err)
c.connMu.Lock()
if c.conn != nil {
c.conn.Close()
@@ -156,6 +180,7 @@ func (c *Client) pollLoop() {
c.statusMu.Unlock()
continue
}
pollFails = 0
// Mark as connected
status.Connected = true
@@ -318,8 +343,8 @@ func (c *Client) sendCommand(cmd byte, data []byte) ([]byte, error) {
return nil, fmt.Errorf("failed to write: %w", err)
}
// Read reply with timeout
c.conn.SetReadDeadline(time.Now().Add(1 * time.Second)) // Reduced from 2s to 1s
// Read reply with timeout (generous — tolerates remote-link latency).
c.conn.SetReadDeadline(time.Now().Add(ubReadTimeout))
// Read until we get a complete packet
var buffer []byte