generalize Client Query packet forwarding logic

This commit is contained in:
Reese Norris
2025-05-23 11:50:48 -07:00
parent e6e45b0e72
commit 97a6292974
2 changed files with 67 additions and 63 deletions

View File

@@ -254,63 +254,52 @@ func (s *Server) handleClientQuery(client *Client, packet []byte) {
return
}
// Handle broadcast queries (recipient starts with "@")
if bytes.HasPrefix(recipient, []byte("@")) {
switch string(queryType) {
// Unprivileged ATC queries
case
"BY", // Request relief
"HI", // Cancel request relief
"HLP", // Request help
"NOHLP", // Cancel request help
"WH", // Who has
"NEWATIS", // Broadcast new ATIS letter
"NEWINFO": // Broadcast new ATIS info
// ATC only
if !client.isAtc {
client.sendError(InvalidControlError, "Invalid control")
return
}
broadcastRangedAtcOnly(s.postOffice, client, packet)
// Privileged ATC queries
case
"IT", // Initiate track
"DR", // Drop track
"HT", // Accept handoff
"TA", // Set temporary altitude
"FA", // Set final altitude
"BC", // Set beacon code
"SC", // Set scratchpad
"VT", // Set voice type
"EST", // Set estimate time
"GD": // Set global data
// ATC above OBS facility only
if !client.isAtc || client.facilityType <= 0 {
client.sendError(InvalidControlError, "Invalid control")
return
}
broadcastRangedAtcOnly(s.postOffice, client, packet)
// Allow aircraft configuration queries from any client
case "ACC":
broadcastRanged(s.postOffice, client, packet)
}
return
}
// Handle direct queries to another client
switch string(queryType) {
// General unprivileged queries
case "CAPS", "C?", "RN", "ATIS", "ACC":
sendDirectOrErr(s.postOffice, client, recipient, packet)
// Unprivileged ATC queries
case
"BY", // Request relief
"HI", // Cancel request relief
"HLP", // Request help
"NOHLP", // Cancel request help
"WH", // Who has
"NEWATIS", // Broadcast new ATIS letter
"NEWINFO": // Broadcast new ATIS info
// Supervisor queries
case "SV", "INF":
// ATC only
if !client.isAtc {
client.sendError(InvalidControlError, "Invalid control")
return
}
forwardClientQuery(s.postOffice, client, packet)
// Privileged ATC queries
case
"IT", // Initiate track
"DR", // Drop track
"HT", // Accept handoff
"TA", // Set temporary altitude
"FA", // Set final altitude
"BC", // Set beacon code
"SC", // Set scratchpad
"VT", // Set voice type
"EST", // Set estimate time
"GD", // Set global data
"IPC": // Force squawk code change
// ATC above OBS facility only
if !client.isAtc || client.facilityType <= 0 {
client.sendError(InvalidControlError, "Invalid control")
return
}
forwardClientQuery(s.postOffice, client, packet)
// Allow aircraft configuration queries from any client
case "ACC", "CAPS", "C?", "RN", "ATIS", "SV":
forwardClientQuery(s.postOffice, client, packet)
// INF queries
case "INF":
// Allow responses from any client
if getPacketType(packet) == PacketTypeClientQueryResponse {
sendDirectOrErr(s.postOffice, client, recipient, packet)
@@ -322,15 +311,7 @@ func (s *Server) handleClientQuery(client *Client, packet []byte) {
client.sendError(InvalidControlError, "Invalid control")
return
}
sendDirectOrErr(s.postOffice, client, recipient, packet)
// Force squawk code change. I have no idea if anyone even supports this.
case "IPC":
if !client.isAtc || client.facilityType <= 0 {
client.sendError(InvalidControlError, "Invalid control")
return
}
sendDirectOrErr(s.postOffice, client, recipient, packet)
forwardClientQuery(s.postOffice, client, packet)
}
}

View File

@@ -207,6 +207,29 @@ func parseVisRange(packet []byte, index int) (visRange float64, ok bool) {
return
}
// forwardClientQuery freely routes a client query packet depending on the recipient.
func forwardClientQuery(po *postOffice, client *Client, packet []byte) {
recipient := getField(packet, 1)
if len(recipient) < 2 {
client.sendError(NoSuchCallsignError, "Invalid recipient")
return
}
switch string(recipient) {
case "@94835":
// Broadcast to in-range ATC
broadcastRangedAtcOnly(po, client, packet)
return
case "@94836":
// Broadcast to all in-range clients
broadcastRanged(po, client, packet)
return
}
sendDirectOrErr(po, client, recipient, packet)
}
// broadcastRanged broadcasts a packet to all clients in range
func broadcastRanged(po *postOffice, client *Client, packet []byte) {
packetStr := string(packet)