STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_elodin_read_path.cpp File Reference
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <atomic>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include "elodin/ElodinClient.hpp"
Include dependency graph for test_elodin_read_path.cpp:

Go to the source code of this file.

Classes

struct  FakeDb
 Fake elodin-db: accept one connection, write blob, then hold the socket open. More...

Functions

static void check (bool ok, const std::string &what)
static std::vector< uint8_t > frame (uint8_t hi, uint8_t lo, size_t payload_len, uint8_t fill)
 One wire packet: len(4, LE) then len bytes of body, where the first 4 body bytes are ty/packet_id(2)/request_id.
int main ()

Variables

static int g_failures = 0
 ElodinClient::read_packet() framing — what happens when a packet does not fit.

Function Documentation

◆ check()

void check ( bool ok,
const std::string & what )
static

Definition at line 39 of file test_elodin_read_path.cpp.

References g_failures, and ok.

Referenced by main().

◆ frame()

std::vector< uint8_t > frame ( uint8_t hi,
uint8_t lo,
size_t payload_len,
uint8_t fill )
static

One wire packet: len(4, LE) then len bytes of body, where the first 4 body bytes are ty/packet_id(2)/request_id.

So len = payload + 4, and the whole frame is payload + 8. read_packet() reports packet_len + 4, i.e. the same payload + 8.

Definition at line 50 of file test_elodin_read_path.cpp.

Referenced by ack(), configure(), gnss_core_request_status(), main(), main(), pvt(), sd_command(), sd_read_cid(), send_config(), anonymous_namespace{idle_e2e.cpp}::send_heartbeat(), test_command_frames(), test_send_keeps_a_packet_that_just_arrived(), test_send_refuses_bad_input_and_dead_chip(), test_send_returns_to_duty_cycle_not_continuous(), test_send_times_out(), and test_send_waits_for_tx_done_and_returns_to_rx().

◆ main()

Variable Documentation

◆ g_failures

int g_failures = 0
static

ElodinClient::read_packet() framing — what happens when a packet does not fit.

The stream is length-prefixed packets back to back on one TCP connection, so the only thing keeping a reader aligned is consuming exactly as many bytes as each length announced.

read_packet() used to break that. On a packet larger than the caller's buffer it returned -1 having already consumed the 8-byte header but not the body, leaving the rest of that packet in the socket. Every later read then parsed payload bytes as a header, and since nothing marked the socket dead, is_connected() kept reporting true and callers looped on garbage forever. Observed against a real elodin-db: one 179-byte packet against a 160-byte buffer, then "Invalid packet length: 1638688", "134742016", "268436225" ... indefinitely.

It also mis-sized its own bound. The check was packet_len > max_len, but the function writes 8 + (packet_len - 4) = packet_len + 4 bytes, so packet_len == max_len passed and overran the caller's buffer by 4. Confirmed with a guard page: the kernel returned EFAULT at exactly that boundary.

These tests use a fake elodin-db rather than the real one so they can produce packet sizes on demand — nothing a live db emits today is big enough to trip either bug, which is why neither was noticed.

Definition at line 37 of file test_elodin_read_path.cpp.