@@ -301,6 +301,152 @@ bool parse_u64(const uint8_t* data, size_t len, size_t& off, uint64_t& out)
301301 return true ;
302302}
303303
304+ bool try_parse_cmd_tx_app_data_legacy (const Frame& frame, PendingCommand* command)
305+ {
306+ if (!command)
307+ {
308+ return false ;
309+ }
310+
311+ size_t off = 0 ;
312+ uint32_t portnum = 0 ;
313+ uint32_t to = 0 ;
314+ uint16_t payload_len = 0 ;
315+ if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, portnum))
316+ {
317+ return false ;
318+ }
319+ if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, to))
320+ {
321+ return false ;
322+ }
323+ if (off + 2 > frame.payload .size ())
324+ {
325+ return false ;
326+ }
327+ uint8_t channel = frame.payload [off++];
328+ uint8_t flags = frame.payload [off++];
329+ if (!parse_u16 (frame.payload .data (), frame.payload .size (), off, payload_len))
330+ {
331+ return false ;
332+ }
333+ if (off + payload_len != frame.payload .size ())
334+ {
335+ return false ;
336+ }
337+ if (channel >= static_cast <uint8_t >(chat::ChannelId::MAX_CHANNELS))
338+ {
339+ return false ;
340+ }
341+ if (payload_len > kMaxFrameLen )
342+ {
343+ return false ;
344+ }
345+
346+ command->type = PendingCommandType::TxAppData;
347+ command->to = to;
348+ command->portnum = portnum;
349+ command->channel = channel;
350+ command->flags = flags;
351+ command->payload_len = payload_len;
352+ if (payload_len > 0 )
353+ {
354+ memcpy (command->payload , frame.payload .data () + off, payload_len);
355+ }
356+ return true ;
357+ }
358+
359+ bool try_parse_cmd_tx_app_data_extended (const Frame& frame,
360+ bool include_timestamp_field,
361+ PendingCommand* command)
362+ {
363+ if (!command)
364+ {
365+ return false ;
366+ }
367+
368+ size_t off = 0 ;
369+ uint32_t portnum = 0 ;
370+ uint32_t from = 0 ;
371+ uint32_t to = 0 ;
372+ uint32_t team_key_id = 0 ;
373+ uint32_t timestamp_s = 0 ;
374+ uint32_t total_len = 0 ;
375+ uint32_t chunk_offset = 0 ;
376+ uint16_t chunk_len = 0 ;
377+ if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, portnum))
378+ {
379+ return false ;
380+ }
381+ if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, from))
382+ {
383+ return false ;
384+ }
385+ if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, to))
386+ {
387+ return false ;
388+ }
389+ if (off + 2 > frame.payload .size ())
390+ {
391+ return false ;
392+ }
393+ uint8_t channel = frame.payload [off++];
394+ uint8_t flags = frame.payload [off++];
395+ if (off + team::proto::kTeamIdSize > frame.payload .size ())
396+ {
397+ return false ;
398+ }
399+ off += team::proto::kTeamIdSize ;
400+ if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, team_key_id))
401+ {
402+ return false ;
403+ }
404+ if (include_timestamp_field &&
405+ !parse_u32 (frame.payload .data (), frame.payload .size (), off, timestamp_s))
406+ {
407+ return false ;
408+ }
409+ if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, total_len) ||
410+ !parse_u32 (frame.payload .data (), frame.payload .size (), off, chunk_offset) ||
411+ !parse_u16 (frame.payload .data (), frame.payload .size (), off, chunk_len))
412+ {
413+ return false ;
414+ }
415+ if (off + chunk_len != frame.payload .size ())
416+ {
417+ return false ;
418+ }
419+ if (channel >= static_cast <uint8_t >(chat::ChannelId::MAX_CHANNELS))
420+ {
421+ return false ;
422+ }
423+ if (chunk_len > kMaxFrameLen )
424+ {
425+ return false ;
426+ }
427+ // Current command queue carries one payload per command; require full payload in one frame.
428+ if (chunk_offset != 0 || total_len != chunk_len)
429+ {
430+ return false ;
431+ }
432+
433+ (void )from;
434+ (void )team_key_id;
435+ (void )timestamp_s;
436+
437+ command->type = PendingCommandType::TxAppData;
438+ command->to = to;
439+ command->portnum = portnum;
440+ command->channel = channel;
441+ command->flags = flags;
442+ command->payload_len = chunk_len;
443+ if (chunk_len > 0 )
444+ {
445+ memcpy (command->payload , frame.payload .data () + off, chunk_len);
446+ }
447+ return true ;
448+ }
449+
304450ErrorCode map_team_send_error (team::TeamService::SendError err)
305451{
306452 switch (err)
@@ -557,48 +703,12 @@ ErrorCode handle_cmd_tx_msg(const Frame& frame)
557703
558704ErrorCode handle_cmd_tx_app_data (const Frame& frame)
559705{
560- size_t off = 0 ;
561- uint32_t portnum = 0 ;
562- uint32_t to = 0 ;
563- uint16_t payload_len = 0 ;
564- if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, portnum))
565- {
566- return ErrorCode::InvalidParam;
567- }
568- if (!parse_u32 (frame.payload .data (), frame.payload .size (), off, to))
569- {
570- return ErrorCode::InvalidParam;
571- }
572- if (off + 2 > frame.payload .size ())
573- {
574- return ErrorCode::InvalidParam;
575- }
576- uint8_t channel = frame.payload [off++];
577- uint8_t flags = frame.payload [off++];
578- if (!parse_u16 (frame.payload .data (), frame.payload .size (), off, payload_len))
579- {
580- return ErrorCode::InvalidParam;
581- }
582- if (off + payload_len != frame.payload .size ())
583- {
584- return ErrorCode::InvalidParam;
585- }
586-
587- if (channel >= static_cast <uint8_t >(chat::ChannelId::MAX_CHANNELS))
588- {
589- return ErrorCode::InvalidParam;
590- }
591-
592706 PendingCommand command{};
593- command.type = PendingCommandType::TxAppData;
594- command.to = to;
595- command.portnum = portnum;
596- command.channel = channel;
597- command.flags = flags;
598- command.payload_len = payload_len;
599- if (payload_len > 0 )
707+ if (!try_parse_cmd_tx_app_data_legacy (frame, &command) &&
708+ !try_parse_cmd_tx_app_data_extended (frame, false , &command) &&
709+ !try_parse_cmd_tx_app_data_extended (frame, true , &command))
600710 {
601- memcpy (command. payload , frame. payload . data () + off, payload_len) ;
711+ return ErrorCode::InvalidParam ;
602712 }
603713
604714 if (!enqueue_pending_command (command))
0 commit comments