multi source
This commit is contained in:
+23
-26
@@ -12,20 +12,20 @@ const (
|
||||
readBufSize = 65536
|
||||
)
|
||||
|
||||
// UDPClient manages the UDP connection to the MARTe2 streamer.
|
||||
// UDPClient manages the UDP connection to one MARTe2 streamer source.
|
||||
type UDPClient struct {
|
||||
serverAddr string
|
||||
localPort int
|
||||
sourceID string
|
||||
hub *Hub
|
||||
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
// NewUDPClient creates a UDPClient. Call Run() in a goroutine.
|
||||
func NewUDPClient(serverAddr string, localPort int, hub *Hub) *UDPClient {
|
||||
// NewUDPClient creates a UDPClient bound to a specific source ID. Call Run() in a goroutine.
|
||||
func NewUDPClient(serverAddr, sourceID string, hub *Hub) *UDPClient {
|
||||
return &UDPClient{
|
||||
serverAddr: serverAddr,
|
||||
localPort: localPort,
|
||||
sourceID: sourceID,
|
||||
hub: hub,
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
@@ -45,13 +45,14 @@ func (u *UDPClient) Run() {
|
||||
default:
|
||||
}
|
||||
|
||||
log.Printf("udp: connecting to %s (local port %d)", u.serverAddr, u.localPort)
|
||||
u.hub.SetSourceState(u.sourceID, "connecting")
|
||||
log.Printf("[%s] udp: connecting to %s", u.sourceID, u.serverAddr)
|
||||
err := u.runSession()
|
||||
if err != nil {
|
||||
log.Printf("udp: session ended: %v", err)
|
||||
log.Printf("[%s] udp: session ended: %v", u.sourceID, err)
|
||||
}
|
||||
u.hub.SetSourceState(u.sourceID, "disconnected")
|
||||
|
||||
// Check stop before sleeping.
|
||||
select {
|
||||
case <-u.stopCh:
|
||||
return
|
||||
@@ -63,8 +64,8 @@ func (u *UDPClient) Run() {
|
||||
// runSession opens a UDP socket, sends CONNECT, reads data until the server
|
||||
// goes silent or an error occurs.
|
||||
func (u *UDPClient) runSession() error {
|
||||
localAddr := &net.UDPAddr{Port: u.localPort}
|
||||
conn, err := net.ListenUDP("udp4", localAddr)
|
||||
// Port 0 lets the OS pick a free local port.
|
||||
conn, err := net.ListenUDP("udp4", &net.UDPAddr{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -75,36 +76,33 @@ func (u *UDPClient) runSession() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Send CONNECT.
|
||||
if _, err := conn.WriteToUDP(BuildConnectPacket(), serverAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("udp: sent CONNECT")
|
||||
log.Printf("[%s] udp: sent CONNECT", u.sourceID)
|
||||
|
||||
reassembler := NewReassembler(2 * time.Second)
|
||||
buf := make([]byte, readBufSize)
|
||||
var currentSigs []SignalInfo
|
||||
|
||||
for {
|
||||
// Silence timeout.
|
||||
conn.SetReadDeadline(time.Now().Add(silenceTimeout))
|
||||
|
||||
n, _, err := conn.ReadFromUDP(buf)
|
||||
arrivalTime := time.Now()
|
||||
if err != nil {
|
||||
// Send DISCONNECT best-effort before returning.
|
||||
conn.WriteToUDP(BuildDisconnectPacket(), serverAddr)
|
||||
return err
|
||||
}
|
||||
|
||||
if n < HeaderSize {
|
||||
log.Printf("udp: short datagram (%d bytes), skipping", n)
|
||||
log.Printf("[%s] udp: short datagram (%d bytes), skipping", u.sourceID, n)
|
||||
continue
|
||||
}
|
||||
|
||||
hdr, err := ParseHeader(buf[:n])
|
||||
if err != nil {
|
||||
log.Printf("udp: parse header: %v", err)
|
||||
log.Printf("[%s] udp: parse header: %v", u.sourceID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -120,37 +118,36 @@ func (u *UDPClient) runSession() error {
|
||||
case PktConfig:
|
||||
sigs, err := ParseConfig(complete)
|
||||
if err != nil {
|
||||
log.Printf("udp: parse config: %v", err)
|
||||
log.Printf("[%s] udp: parse config: %v", u.sourceID, err)
|
||||
continue
|
||||
}
|
||||
currentSigs = sigs
|
||||
log.Printf("udp: received CONFIG (%d signals)", len(sigs))
|
||||
u.hub.UpdateConfig(sigs)
|
||||
log.Printf("[%s] udp: received CONFIG (%d signals)", u.sourceID, len(sigs))
|
||||
u.hub.SetSourceState(u.sourceID, "connected")
|
||||
u.hub.UpdateConfigForSource(u.sourceID, sigs)
|
||||
|
||||
case PktData:
|
||||
if len(currentSigs) == 0 {
|
||||
// We haven't received a CONFIG yet – ignore.
|
||||
continue
|
||||
}
|
||||
sample, err := ParseData(complete, currentSigs, arrivalTime)
|
||||
if err != nil {
|
||||
log.Printf("udp: parse data: %v", err)
|
||||
log.Printf("[%s] udp: parse data: %v", u.sourceID, err)
|
||||
continue
|
||||
}
|
||||
u.hub.PushData(sample)
|
||||
u.hub.PushDataForSource(u.sourceID, sample)
|
||||
|
||||
case PktACK:
|
||||
log.Printf("udp: received ACK (counter=%d)", hdr.Counter)
|
||||
log.Printf("[%s] udp: received ACK (counter=%d)", u.sourceID, hdr.Counter)
|
||||
|
||||
case PktDisconnect:
|
||||
log.Printf("udp: server sent DISCONNECT")
|
||||
log.Printf("[%s] udp: server sent DISCONNECT", u.sourceID)
|
||||
return nil
|
||||
|
||||
default:
|
||||
log.Printf("udp: unknown packet type %d", hdr.Type)
|
||||
log.Printf("[%s] udp: unknown packet type %d", u.sourceID, hdr.Type)
|
||||
}
|
||||
|
||||
// Check stop request.
|
||||
select {
|
||||
case <-u.stopCh:
|
||||
conn.WriteToUDP(BuildDisconnectPacket(), serverAddr)
|
||||
|
||||
Reference in New Issue
Block a user