Files
RP412/MUNGA_L4/L4NETTRANSPORT.h
CydandClaude Fable 5 22421fb418 NetTransport seam: the wire moves behind an interface
The Steam-multiplayer prerequisite from the design doc: L4NET keeps
hosts, message queues, and the deterministic mesh ordering, while
connect/listen/accept/close, send/receive, startup/cleanup, the local
interface list, and ip[:port] parsing move behind NetTransport
(L4NETTRANSPORT.h). WinsockNetTransport carries the existing TCP
behavior over verbatim - including the connect retry-while-refused
loop the egg-ACK ordering relies on - and is the process default;
NetTransport_Set installs a replacement before the network manager
comes up.

L4STEAMTRANSPORT.h documents the ISteamNetworkingSockets mapping
per method (FakeIP keeps [pilots] entries as IPv4 strings) behind
RP412_STEAM until the Steamworks SDK lands.

Also fixed in passing: the ExclusiveBroadcast path sent
sizeof(network_packet) - four bytes of pointer - instead of the
message size, which would have sheared the stream framing had it
ever fired.

Verified: single-player race cycle (menu, race, results, menu, race)
green; -net 8000 boots, listens for a console through the transport,
and idles stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 19:38:37 -05:00

127 lines
4.1 KiB
C++

//===========================================================================//
// File: l4nettransport.h //
// Project: MUNGA Brick: Network Transport Seam //
// Contents: The wire interface under the network manager //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#pragma once
#include "..\munga\style.h"
#include <Winsock2.h>
//########################################################################
// NetTransport - the seam between the network manager's mesh/console
// logic and the wire (docs/RP412-FRONTEND-DESIGN.md section 3). Mirrors
// the RIOBase pattern: L4NET keeps hosts, message queues, and the
// deterministic mesh ordering; only connect/listen/send/recv live
// behind this interface.
//
// Implementations:
// WinsockNetTransport (l4nettransport.cpp) - TCP; the arcade/LAN wire
// SteamNetTransport (future) - ISteamNetworkingSockets
// P2P over SDR
//
// Addresses stay SOCKADDR_IN-shaped on purpose: Steam's FakeIP system
// hands out fake IPv4 addresses for exactly this kind of engine, so
// the [pilots] list keeps working as ip[:port] strings in both worlds.
//########################################################################
class NetTransport
{
public:
// Opaque connection handle. SOCKET for Winsock (SOCKET is UINT_PTR),
// HSteamNetConnection for Steam - both fit; callers must not
// interpret it.
typedef UINT_PTR Connection;
static const Connection InvalidConnection = (Connection) ~0; // == INVALID_SOCKET
// Receive() results when no payload came back
enum
{
ReceiveDisconnected = 0, // orderly close or connection reset
ReceiveNoData = -1 // nothing pending (connections are nonblocking)
};
virtual ~NetTransport()
{
}
//---------------------------------------------------------------
// Lifecycle
//---------------------------------------------------------------
virtual Logical
Startup() = 0;
virtual void
Cleanup() = 0;
//---------------------------------------------------------------
// Addressing: the local interface list (the mesh identifies
// "which [pilots] entry is me" against it) and numeric ip[:port]
// parsing. Port 0 in the result means "caller applies default".
//---------------------------------------------------------------
virtual int
GetLocalAddresses(
unsigned long *addresses,
int max_count
) = 0;
virtual Logical
Resolve(
const char *host_name,
SOCKADDR_IN *address
) = 0;
//---------------------------------------------------------------
// Connections (the deterministic mesh + the console channel).
// Connect blocks until the remote end accepts (the mesh relies
// on retry-until-up ordering), then goes nonblocking. Listeners
// are nonblocking from the start; Accept polls one.
//---------------------------------------------------------------
virtual Connection
Connect(
const SOCKADDR_IN *remote,
int local_port
) = 0;
virtual Connection
Listen(
int local_port,
int backlog
) = 0;
virtual Connection
Accept(Connection listener) = 0;
virtual void
Close(Connection connection) = 0;
//---------------------------------------------------------------
// Data plane (nonblocking)
//---------------------------------------------------------------
virtual int
Send(
Connection connection,
const void *data,
int size
) = 0;
virtual int
Receive(
Connection connection,
void *buffer,
int size
) = 0;
// remote endpoint of a live connection (mesh identity checks)
virtual Logical
GetRemoteAddress(
Connection connection,
SOCKADDR_IN *address
) = 0;
};
// The process-wide transport. Defaults to Winsock TCP; a Steam build
// installs its transport BEFORE the network manager comes up.
NetTransport *
NetTransport_Get();
void
NetTransport_Set(NetTransport *transport);