LCOV - code coverage report
Current view: top level - posix - net_posix.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 2 100.0 %
Date: 2026-02-22 12:14:12 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * PeerTalk POSIX Networking Layer
       3             :  *
       4             :  * Platform-specific networking implementation using BSD sockets.
       5             :  * Implements UDP discovery, TCP connections, and message I/O.
       6             :  */
       7             : 
       8             : #ifndef PT_NET_POSIX_H
       9             : #define PT_NET_POSIX_H
      10             : 
      11             : #include "pt_internal.h"
      12             : #include "protocol.h"
      13             : #include <sys/uio.h>     /* For struct iovec, writev() */
      14             : #include <sys/select.h>  /* For fd_set, FD_SET, etc. */
      15             : 
      16             : /* ========================================================================== */
      17             : /* Receive State Machine (Data-Oriented Design)                              */
      18             : /* ========================================================================== */
      19             : 
      20             : /**
      21             :  * Receive state - using uint8_t instead of enum for cache efficiency
      22             :  *
      23             :  * On 68030, enum uses 4 bytes. Using uint8_t reduces hot section from
      24             :  * 4 bytes to 1 byte, keeping per-peer state smaller.
      25             :  */
      26             : typedef uint8_t pt_recv_state;
      27             : #define PT_RECV_HEADER   0   /* Waiting for header bytes */
      28             : #define PT_RECV_PAYLOAD  1   /* Waiting for payload bytes */
      29             : #define PT_RECV_CRC      2   /* Waiting for CRC bytes */
      30             : 
      31             : /* ========================================================================== */
      32             : /* Per-Peer Receive Buffers (HOT/COLD Separation)                           */
      33             : /* ========================================================================== */
      34             : 
      35             : /**
      36             :  * HOT Section - checked every poll cycle per active connection (8 bytes)
      37             :  *
      38             :  * CRITICAL 68k ALIGNMENT: _pad0 ensures bytes_needed starts at even offset.
      39             :  * On 68000/68020/68030, uint16_t at odd offsets causes performance penalty
      40             :  * or crashes. This padding is NOT optional.
      41             :  *
      42             :  * With 16 peers, hot scan touches only 128 bytes (fits in 68030 L1 cache)
      43             :  * instead of 131KB if payload buffers were inline.
      44             :  */
      45             : typedef struct {
      46             :     pt_recv_state state;           /* 1 byte at offset 0 */
      47             :     uint8_t       is_compact;      /* 1 byte at offset 1: 1 if current msg is compact header */
      48             :     uint16_t      bytes_needed;    /* 2 bytes at offset 2 */
      49             :     uint16_t      bytes_received;  /* 2 bytes at offset 4 */
      50             :     uint16_t      _pad1;           /* 2 bytes at offset 6: align to 8 bytes */
      51             : } pt_recv_hot;  /* Total: 8 bytes, all uint16_t at even offsets */
      52             : 
      53             : /**
      54             :  * COLD Section - only accessed when actual I/O happens
      55             :  *
      56             :  * Large buffers separated to avoid cache pollution during hot scans.
      57             :  */
      58             : typedef struct {
      59             :     pt_message_header hdr;
      60             :     uint8_t header_buf[PT_MESSAGE_HEADER_SIZE];  /* 10 bytes */
      61             :     uint8_t crc_buf[2];
      62             :     uint8_t payload_buf[PT_MAX_MESSAGE_SIZE];
      63             : } pt_recv_cold;
      64             : 
      65             : /**
      66             :  * Complete receive buffer - hot and cold sections
      67             :  *
      68             :  * IMPORTANT: These are allocated separately (not inline in pt_posix_data)
      69             :  * to prevent massive payload buffers from polluting cache when accessing
      70             :  * hot fields in the platform context.
      71             :  */
      72             : typedef struct {
      73             :     pt_recv_hot  hot;
      74             :     pt_recv_cold cold;
      75             : } pt_recv_buffer;
      76             : 
      77             : /* ========================================================================== */
      78             : /* Platform Context Extension (pt_posix_data)                                */
      79             : /* ========================================================================== */
      80             : 
      81             : /**
      82             :  * POSIX platform-specific data
      83             :  *
      84             :  * Extends pt_context with networking state. Allocated after pt_context
      85             :  * structure via pt_posix_extra_size().
      86             :  *
      87             :  * Field ordering follows Data-Oriented Design:
      88             :  * - HOT: Accessed every poll cycle
      89             :  * - WARM: Accessed on socket operations
      90             :  * - COLD: Per-peer data
      91             :  *
      92             :  * recv_bufs is a POINTER, not inline array, to avoid cache pollution.
      93             :  */
      94             : typedef struct {
      95             :     /* HOT - accessed every poll cycle (20 bytes on 32-bit) */
      96             :     int max_fd;                    /* 4 bytes: highest fd for select() */
      97             :     uint8_t active_count;          /* 1 byte: number of active peer connections */
      98             :     uint8_t fd_dirty;              /* 1 byte: non-zero when fd_sets need rebuild */
      99             :     uint16_t batch_count;          /* 2 bytes: messages in current batch */
     100             :     pt_tick_t last_announce;       /* 4 bytes: tick of last discovery announce */
     101             :     uint32_t local_ip;             /* 4 bytes: our IP (for filtering own broadcasts) */
     102             :     uint8_t _pad0[4];              /* 4 bytes: align to 8-byte boundary */
     103             : 
     104             :     /* Active peer tracking - O(1) removal via swap-back */
     105             :     uint8_t active_peers[PT_MAX_PEERS];     /* Indices of peers with active sockets */
     106             :     uint8_t active_position[PT_MAX_PEERS];  /* Reverse mapping for O(1) removal */
     107             : 
     108             :     /* WARM - accessed on socket operations (24 bytes) */
     109             :     int discovery_sock;
     110             :     int listen_sock;
     111             :     int udp_msg_sock;
     112             :     uint32_t broadcast_addr;       /* INADDR_BROADCAST */
     113             :     uint16_t discovery_port;
     114             :     uint16_t listen_port;
     115             :     uint16_t udp_msg_port;
     116             :     uint16_t _pad1;
     117             : 
     118             :     /* Cached fd_set - rebuilt only when fd_dirty is set */
     119             :     fd_set cached_read_fds;
     120             :     fd_set cached_write_fds;
     121             : 
     122             :     /* COLD - per-peer data */
     123             :     int tcp_socks[PT_MAX_PEERS];   /* TCP socket per peer, -1 if not connected */
     124             : 
     125             :     /* SEPARATE ALLOCATION - do NOT embed inline */
     126             :     pt_recv_buffer *recv_bufs;     /* Pointer to allocated array */
     127             : } pt_posix_data;
     128             : 
     129             : /* ========================================================================== */
     130             : /* Helper Inline Functions                                                   */
     131             : /* ========================================================================== */
     132             : 
     133             : /**
     134             :  * Get POSIX platform data from context
     135             :  *
     136             :  * The platform data is allocated immediately after the context structure.
     137             :  */
     138        1965 : static inline pt_posix_data *pt_posix_get(struct pt_context *ctx) {
     139        1965 :     return (pt_posix_data *)((char *)ctx + sizeof(struct pt_context));
     140             : }
     141             : 
     142             : /* ========================================================================== */
     143             : /* Platform Size/Init                                                        */
     144             : /* ========================================================================== */
     145             : 
     146             : /**
     147             :  * Return extra memory size needed for POSIX platform data
     148             :  */
     149             : size_t pt_posix_extra_size(void);
     150             : 
     151             : /**
     152             :  * Initialize POSIX networking subsystem
     153             :  *
     154             :  * Creates sockets, initializes data structures, detects local IP.
     155             :  * Called from PeerTalk_Init().
     156             :  *
     157             :  * Returns: 0 on success, -1 on failure
     158             :  */
     159             : int pt_posix_net_init(struct pt_context *ctx);
     160             : 
     161             : /**
     162             :  * Shutdown POSIX networking subsystem
     163             :  *
     164             :  * Closes all sockets, frees allocated buffers.
     165             :  * Called from PeerTalk_Shutdown().
     166             :  */
     167             : void pt_posix_net_shutdown(struct pt_context *ctx);
     168             : 
     169             : /* ========================================================================== */
     170             : /* Discovery                                                                  */
     171             : /* ========================================================================== */
     172             : 
     173             : /**
     174             :  * Start UDP discovery broadcasts
     175             :  *
     176             :  * Creates discovery socket, enables broadcast, sends initial announcement.
     177             :  *
     178             :  * Returns: 0 on success, -1 on failure
     179             :  */
     180             : int pt_posix_discovery_start(struct pt_context *ctx);
     181             : 
     182             : /**
     183             :  * Stop UDP discovery broadcasts
     184             :  *
     185             :  * Closes discovery socket.
     186             :  */
     187             : void pt_posix_discovery_stop(struct pt_context *ctx);
     188             : 
     189             : /**
     190             :  * Poll discovery socket for incoming packets
     191             :  *
     192             :  * Non-blocking receive of discovery packets. Processes ANNOUNCE, QUERY,
     193             :  * GOODBYE types. Creates/updates/removes peers as appropriate.
     194             :  *
     195             :  * Returns: 1 if packet processed, 0 if no data, -1 on error
     196             :  */
     197             : int pt_posix_discovery_poll(struct pt_context *ctx);
     198             : 
     199             : /**
     200             :  * Send discovery packet
     201             :  *
     202             :  * @param ctx Context
     203             :  * @param type PT_DISC_TYPE_ANNOUNCE, PT_DISC_TYPE_QUERY, or PT_DISC_TYPE_GOODBYE
     204             :  *
     205             :  * Returns: 0 on success, -1 on failure
     206             :  */
     207             : int pt_posix_discovery_send(struct pt_context *ctx, uint8_t type);
     208             : 
     209             : /* ========================================================================== */
     210             : /* TCP Server                                                                 */
     211             : /* ========================================================================== */
     212             : 
     213             : /**
     214             :  * Start TCP listening socket
     215             :  *
     216             :  * Creates listening socket on TCP port for incoming connections.
     217             :  *
     218             :  * Returns: 0 on success, -1 on failure
     219             :  */
     220             : int pt_posix_listen_start(struct pt_context *ctx);
     221             : 
     222             : /**
     223             :  * Stop TCP listening socket
     224             :  */
     225             : void pt_posix_listen_stop(struct pt_context *ctx);
     226             : 
     227             : /**
     228             :  * Poll TCP listening socket for incoming connections
     229             :  *
     230             :  * Non-blocking accept() of incoming connections.
     231             :  *
     232             :  * Returns: 1 if connection accepted, 0 if no pending, -1 on error
     233             :  */
     234             : int pt_posix_listen_poll(struct pt_context *ctx);
     235             : 
     236             : /* ========================================================================== */
     237             : /* TCP Client                                                                 */
     238             : /* ========================================================================== */
     239             : 
     240             : /**
     241             :  * Connect to a peer via TCP
     242             :  *
     243             :  * Initiates non-blocking connection to peer. Connection completes
     244             :  * asynchronously; poll for writability to detect completion.
     245             :  *
     246             :  * Returns: 0 on success (connecting), -1 on failure
     247             :  */
     248             : int pt_posix_connect(struct pt_context *ctx, struct pt_peer *peer);
     249             : 
     250             : /**
     251             :  * Disconnect from a peer
     252             :  *
     253             :  * Closes TCP connection, removes from active peer tracking.
     254             :  *
     255             :  * Returns: 0 on success, -1 on failure
     256             :  */
     257             : int pt_posix_disconnect(struct pt_context *ctx, struct pt_peer *peer);
     258             : 
     259             : /* ========================================================================== */
     260             : /* I/O                                                                        */
     261             : /* ========================================================================== */
     262             : 
     263             : /**
     264             :  * Send data to peer
     265             :  *
     266             :  * Non-blocking send. If socket buffer is full, returns PT_ERR_WOULD_BLOCK.
     267             :  *
     268             :  * Returns: 0 on success, PT_ERR_WOULD_BLOCK if would block, -1 on error
     269             :  */
     270             : int pt_posix_send(struct pt_context *ctx, struct pt_peer *peer,
     271             :                   const void *data, size_t len);
     272             : 
     273             : /**
     274             :  * Receive data from peer
     275             :  *
     276             :  * Non-blocking receive with state machine for header/payload/CRC.
     277             :  *
     278             :  * Returns: 1 if complete message received, 0 if incomplete, -1 on error
     279             :  */
     280             : int pt_posix_recv(struct pt_context *ctx, struct pt_peer *peer);
     281             : 
     282             : /**
     283             :  * Send control message to peer
     284             :  *
     285             :  * Helper for sending protocol control messages (PING, PONG, etc).
     286             :  *
     287             :  * Returns: 0 on success, -1 on failure
     288             :  */
     289             : int pt_posix_send_control(struct pt_context *ctx, struct pt_peer *peer,
     290             :                           uint8_t msg_type);
     291             : 
     292             : /**
     293             :  * Send capability message to peer
     294             :  *
     295             :  * Called after connection established to exchange capability information.
     296             :  * Enables automatic fragmentation for constrained peers.
     297             :  *
     298             :  * Returns: PT_OK on success, error code on failure
     299             :  */
     300             : int pt_posix_send_capability(struct pt_context *ctx, struct pt_peer *peer);
     301             : 
     302             : /* ========================================================================== */
     303             : /* UDP Messaging (Session 4.4)                                               */
     304             : /* ========================================================================== */
     305             : 
     306             : /**
     307             :  * Initialize UDP messaging socket (separate from discovery)
     308             :  *
     309             :  * Returns: 0 on success, -1 on failure
     310             :  */
     311             : int pt_posix_udp_init(struct pt_context *ctx);
     312             : 
     313             : /**
     314             :  * Shutdown UDP messaging socket
     315             :  */
     316             : void pt_posix_udp_shutdown(struct pt_context *ctx);
     317             : 
     318             : /**
     319             :  * Send unreliable UDP message to peer
     320             :  *
     321             :  * Returns: 0 on success, -1 on failure
     322             :  */
     323             : int pt_posix_send_udp(struct pt_context *ctx, struct pt_peer *peer,
     324             :                       const void *data, uint16_t len);
     325             : 
     326             : /**
     327             :  * Receive UDP message
     328             :  *
     329             :  * Non-blocking receive of UDP messages (not discovery packets).
     330             :  *
     331             :  * Returns: 1 if message received, 0 if no data, -1 on error
     332             :  */
     333             : int pt_posix_recv_udp(struct pt_context *ctx);
     334             : 
     335             : /* ========================================================================== */
     336             : /* Main Poll                                                                  */
     337             : /* ========================================================================== */
     338             : 
     339             : /**
     340             :  * Main POSIX poll function
     341             :  *
     342             :  * Polls all sockets (discovery, listen, UDP, TCP peers) using select().
     343             :  * Delegates to appropriate handlers based on ready sockets.
     344             :  *
     345             :  * Returns: 0 on success, -1 on error
     346             :  */
     347             : int pt_posix_poll(struct pt_context *ctx);
     348             : 
     349             : /**
     350             :  * Fast POSIX poll function
     351             :  *
     352             :  * Only handles TCP I/O for connected peers - no discovery, UDP, listen,
     353             :  * periodic announces, or peer timeouts. Use for tight game loops.
     354             :  *
     355             :  * Performs:
     356             :  * - TCP send queue drain for connected peers
     357             :  * - TCP receive for connected peers
     358             :  *
     359             :  * Does NOT:
     360             :  * - Poll discovery socket
     361             :  * - Poll UDP message socket
     362             :  * - Poll listen socket for new connections
     363             :  * - Send periodic discovery announces
     364             :  * - Check peer timeouts
     365             :  *
     366             :  * Returns: 0 on success, -1 on error
     367             :  */
     368             : int pt_posix_poll_fast(struct pt_context *ctx);
     369             : 
     370             : #endif /* PT_NET_POSIX_H */

Generated by: LCOV version 1.14