chore: release v0.26.0
This commit is contained in:
@@ -2,6 +2,7 @@ package udp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"hamlog/internal/applog"
|
||||
@@ -185,3 +186,94 @@ func (m *Manager) sendTo(c Config, payload []byte) {
|
||||
applog.Printf("udp: [%s] sent %d bytes to %s (%s)%s",
|
||||
c.Name, len(payload), dst, c.ServiceType, sentPreview(c, payload))
|
||||
}
|
||||
|
||||
// RelayInbound re-sends one received datagram, unchanged, to every configured
|
||||
// relay destination.
|
||||
//
|
||||
// Called with the RAW bytes as they arrived — before parsing, and whatever the
|
||||
// parse made of them. A packet this build cannot decode is still a packet the
|
||||
// application downstream may understand perfectly well, and a relay that only
|
||||
// forwards what it understood is a relay that silently drops the fields it has
|
||||
// not learned about yet.
|
||||
//
|
||||
// Loop guard: a destination that is one of our OWN inbound ports on a local
|
||||
// address would come straight back in and be relayed again, for ever, at line
|
||||
// rate. Such a row is skipped and said so once — quietly dropping it would look
|
||||
// like a relay that does not work.
|
||||
func (m *Manager) RelayInbound(pkt []byte, fromPort int) {
|
||||
if len(pkt) == 0 {
|
||||
return
|
||||
}
|
||||
rows := m.Outbound(ServiceWSJTRelay)
|
||||
if len(rows) == 0 {
|
||||
return
|
||||
}
|
||||
m.mu.Lock()
|
||||
ports := make(map[int]struct{}, len(m.inbound))
|
||||
for _, s := range m.inbound {
|
||||
ports[s.cfg.Port] = struct{}{}
|
||||
}
|
||||
m.mu.Unlock()
|
||||
|
||||
for _, c := range rows {
|
||||
if isLoopback(c.DestinationIP) {
|
||||
if _, mine := ports[c.Port]; mine {
|
||||
m.relayLoopOnce(c)
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Deliberately not sendTo: that logs a line per datagram, and this runs
|
||||
// on every decode of every period — it would bury the log within minutes.
|
||||
host := strings.TrimSpace(c.DestinationIP)
|
||||
if host == "" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
dst := fmt.Sprintf("%s:%d", host, c.Port)
|
||||
if err := SendUDP(dst, pkt); err != nil {
|
||||
m.relayErrOnce(c, dst, err)
|
||||
}
|
||||
}
|
||||
_ = fromPort
|
||||
}
|
||||
|
||||
// isLoopback reports whether a destination names this machine. Empty counts:
|
||||
// sendTo defaults it to 127.0.0.1.
|
||||
func isLoopback(host string) bool {
|
||||
h := strings.TrimSpace(host)
|
||||
if h == "" || h == "localhost" {
|
||||
return true
|
||||
}
|
||||
ip := net.ParseIP(h)
|
||||
return ip != nil && ip.IsLoopback()
|
||||
}
|
||||
|
||||
// relayLoopOnce and relayErrOnce keep a repeating relay complaint to one line a
|
||||
// session. Both fire per datagram otherwise, which on a busy band is hundreds a
|
||||
// minute and makes the log useless for anything else.
|
||||
func (m *Manager) relayLoopOnce(c Config) {
|
||||
m.relayWarnMu.Lock()
|
||||
defer m.relayWarnMu.Unlock()
|
||||
if m.relayWarned == nil {
|
||||
m.relayWarned = map[int64]bool{}
|
||||
}
|
||||
if m.relayWarned[c.ID] {
|
||||
return
|
||||
}
|
||||
m.relayWarned[c.ID] = true
|
||||
applog.Printf("udp: [%s] relay target %s:%d is one of OpsLog's OWN listening ports — "+
|
||||
"that would feed the stream back into itself for ever. Nothing is relayed on this row; "+
|
||||
"point it at the other application's port.", c.Name, c.DestinationIP, c.Port)
|
||||
}
|
||||
|
||||
func (m *Manager) relayErrOnce(c Config, dst string, err error) {
|
||||
m.relayWarnMu.Lock()
|
||||
defer m.relayWarnMu.Unlock()
|
||||
if m.relayWarned == nil {
|
||||
m.relayWarned = map[int64]bool{}
|
||||
}
|
||||
if m.relayWarned[-c.ID-1] {
|
||||
return
|
||||
}
|
||||
m.relayWarned[-c.ID-1] = true
|
||||
applog.Printf("udp: [%s] relay to %s failed: %v (said once)", c.Name, dst, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user