Skip to content

Commit 4488bc6

Browse files
committed
BUGFIX:
- Core: Messages duplication on falsely detected split messages - Coalitions: Typo in coalition detection - Coalitions: /missionstats did not check coalition membership - Coalition: /airbase info did not check coalition membership
1 parent f406858 commit 4488bc6

File tree

6 files changed

+34
-28
lines changed

6 files changed

+34
-28
lines changed

Scripts/net/DCSServerBot/DCSServerBot.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ if base.dcsbot ~= nil then
1010
return
1111
end
1212

13+
local MAGIC_BYTE = string.char(1)
1314
local MAX_CHUNK = 65000 -- safe UDP payload size
1415
local HEADER_SEP = '|' -- separator in the header
1516
local HEADER_FMT = '%s'..HEADER_SEP..'%d'..HEADER_SEP..'%d'..HEADER_SEP..'%d'..HEADER_SEP
@@ -57,7 +58,7 @@ dcsbot.sendBotTable = dcsbot.sendBotTable or function (tbl, channel)
5758
local payload = msg:sub(start_idx, end_idx)
5859

5960
local header = string.format(HEADER_FMT, msg_id, config.DCS_PORT, total_parts, part)
60-
local packet = header .. payload
61+
local packet = MAGIC_BYTE .. header .. payload
6162
socket.try(dcsbot.UDPSendSocket:sendto(packet, config.BOT_HOST, config.BOT_PORT))
6263
end
6364
end

Scripts/net/DCSServerBot/DCSServerBotUtils.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ end
3434
-- this is the DCS server name
3535
server_name = nil
3636

37+
local MAGIC_BYTE = string.char(1)
3738
local MAX_CHUNK = 65000 -- safe UDP payload size
3839
local HEADER_SEP = '|' -- separator in the header
3940
local HEADER_FMT = '%s'..HEADER_SEP..'%d'..HEADER_SEP..'%d'..HEADER_SEP..'%d'..HEADER_SEP
@@ -61,7 +62,7 @@ function sendBotTable(tbl, channel)
6162
local payload = msg:sub(start_idx, end_idx)
6263

6364
local header = string.format(HEADER_FMT, msg_id, config.DCS_PORT, total_parts, part)
64-
local packet = header .. payload
65+
local packet = MAGIC_BYTE .. header .. payload
6566
socket.try(UDPSendSocket:sendto(packet, config.BOT_HOST, config.BOT_PORT))
6667
end
6768
end

core/utils/coalitions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def get_sides(bot: DCSServerBot, ctx: discord.Interaction | discord.Message, ser
2525
da_roles = [bot.get_role(x) for x in bot.roles['DCS Admin']]
2626
gm_roles = [bot.get_role(x) for x in bot.roles['GameMaster']]
2727
blue_role = bot.get_role(server.locals['coalitions']['blue_role'])
28-
red_role = bot.get_role(server.locals['coalitions']['blue_role'])
28+
red_role = bot.get_role(server.locals['coalitions']['red_role'])
2929
everyone = discord.utils.get(channel.guild.roles, name="@everyone")
3030

3131
# check which coalition-specific data can be displayed in the questioned channel by that user

plugins/missionstats/listener.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import asyncio
2-
import psycopg_pool
32

43
from core import EventListener, PersistentReport, Server, Coalition, Channel, event, Report, get_translation, \
54
ThreadSafeDict
@@ -282,5 +281,6 @@ async def do_update(self):
282281
if 'coalitions' in stats:
283282
report = PersistentReport(self.bot, self.plugin_name, 'missionstats.json',
284283
embed_name='stats_embed', server=server)
285-
await report.render(stats=stats, mission_id=server.mission_id, title='Mission Statistics')
284+
await report.render(stats=stats, mission_id=server.mission_id, title='Mission Statistics',
285+
sides=[Coalition.BLUE, Coalition.RED])
286286
self.update[server_name] = False

plugins/missionstats/reports.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@ async def render(self, ucid: str, flt: StatisticsFilter) -> None:
111111

112112

113113
class MissionStats(report.EmbedElement):
114-
async def render(self, stats: dict, sql: str, mission_id: int) -> None:
114+
async def render(self, stats: dict, sql: str, mission_id: int, sides: list[Coalition]) -> None:
115115
self.add_field(name='▬▬▬▬▬▬▬▬▬▬▬ {} ▬▬▬▬▬▬▬▬▬▬▬'.format(_('Current Situation')),
116116
value='_ _', inline=False)
117117
self.add_field(
118118
name='_ _', value=_('Airbases / FARPs\nPlanes\nHelicopters\nGround Units\nShips\nStructures'))
119-
for coalition in [Coalition.BLUE, Coalition.RED]:
119+
for coalition in sides:
120120
coalition_data = stats['coalitions'][coalition.name]
121121
value = '{}\n'.format(len(coalition_data['airbases']))
122122
for unit_type in [_('Airplanes'), _('Helicopters'), _('Ground Units'), _('Ships')]:
@@ -141,10 +141,12 @@ async def render(self, stats: dict, sql: str, mission_id: int) -> None:
141141
continue
142142
elements[s][name] = value
143143
self.add_field(name='_ _', value='\n'.join(elements[Side.BLUE].keys()) or '_ _')
144-
self.add_field(name=Side.BLUE.name.capitalize(),
145-
value='\n'.join([str(x) for x in elements[Side.BLUE].values()]) or '_ _')
146-
self.add_field(name=Side.RED.name.capitalize(),
147-
value='\n'.join([str(x) for x in elements[Side.RED].values()]) or '_ _')
144+
if Coalition.BLUE in sides:
145+
self.add_field(name=Side.BLUE.name.capitalize(),
146+
value='\n'.join([str(x) for x in elements[Side.BLUE].values()]) or '_ _')
147+
if Coalition.RED in sides:
148+
self.add_field(name=Side.RED.name.capitalize(),
149+
value='\n'.join([str(x) for x in elements[Side.RED].values()]) or '_ _')
148150

149151

150152
class ModuleStats1(report.EmbedElement):

services/servicebus/service.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -820,23 +820,25 @@ def datagram_received(derived, data: bytes, addr):
820820
self.log.warning(f"Empty request received from {addr} - ignoring.")
821821
return
822822

823-
# Check for the split header
824-
parts = data.split(b"|", 4)
825-
if len(parts) == 5:
826-
msg_id_b, port_b, total_b, seq_b, payload = parts
827-
try:
828-
msg_id = msg_id_b.decode("ascii")
829-
port = int(port_b)
830-
total = int(total_b)
831-
seq = int(seq_b)
832-
except Exception as e:
833-
self.log.debug("Invalid split header %s – treating as normal", parts)
834-
derived._handle_raw_payload(data)
835-
else:
836-
# 2️⃣ Store fragment and see if we are finished
837-
loop = asyncio.get_running_loop()
838-
loop.create_task(derived._process_fragment(msg_id, port, total, seq, payload))
839-
return # early exit – we’ll process once all fragments are in
823+
if data[0:1] == b'\x01':
824+
data = data[1:]
825+
826+
# Check for the split header
827+
parts = data.split(b"|", 4)
828+
if len(parts) == 5:
829+
msg_id_b, port_b, total_b, seq_b, payload = parts
830+
try:
831+
msg_id = msg_id_b.decode("ascii")
832+
port = int(port_b)
833+
total = int(total_b)
834+
seq = int(seq_b)
835+
except Exception as e:
836+
self.log.debug("Malformed header after magic byte – dropping packet")
837+
return
838+
else:
839+
loop = asyncio.get_running_loop()
840+
loop.create_task(derived._process_fragment(msg_id, port, total, seq, payload))
841+
return # early exit – we’ll process once all fragments are in
840842

841843
# Normal (unsplit) JSON packet
842844
derived._handle_raw_payload(data)

0 commit comments

Comments
 (0)