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>
129 lines
4.6 KiB
C++
129 lines
4.6 KiB
C++
//===========================================================================//
|
|
// File: l4steamtransport.h //
|
|
// Project: MUNGA Brick: Steam Network Transport (skeleton) //
|
|
// Contents: NetTransport over ISteamNetworkingSockets - awaiting the SDK //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#pragma once
|
|
|
|
//########################################################################
|
|
// SteamNetTransport - the retail wire. NOT BUILT YET: everything below
|
|
// is guarded by RP412_STEAM, which stays undefined until the Steamworks
|
|
// SDK is dropped into the tree (needs a Steamworks partner login to
|
|
// download; put it at extern\steamworks and add steam_api.lib +
|
|
// steam_api.dll to the link/dist).
|
|
//
|
|
// Method mapping (see also docs/RP412-FRONTEND-DESIGN.md section 3):
|
|
//
|
|
// Startup SteamAPI_Init + ISteamNetworkingUtils::InitRelay
|
|
// NetworkAccessAuthorization; then
|
|
// BeginAsyncRequestFakeIP so this pod has a fake
|
|
// IPv4 identity to put in the [pilots] list.
|
|
// Cleanup SteamAPI_Shutdown.
|
|
// GetLocalAddresses our allocated FakeIP (the mesh identifies
|
|
// "which pilots entry is me" against it, same as
|
|
// the LAN build matches its interface list).
|
|
// Resolve parse ip[:port] exactly like Winsock - FakeIPs
|
|
// ARE IPv4 strings, so egg text stays unchanged.
|
|
// Connect ConnectP2PByFakeIP (SDR picks the route, NAT
|
|
// traversal and IP privacy come free); block on
|
|
// the connection state callback until Connected,
|
|
// mirroring the TCP retry-until-accepted loop.
|
|
// Listen CreateListenSocketP2PFakeIP(port index); the
|
|
// game port / console port pair becomes fake-port
|
|
// index 0 / 1.
|
|
// Accept poll the connection-request callback queue,
|
|
// AcceptConnection, return the HSteamNetConnection
|
|
// (it fits the NetTransport::Connection handle).
|
|
// Close CloseConnection(reason 0, linger enabled).
|
|
// Send SendMessageToConnection with
|
|
// k_nSteamNetworkingSend_Reliable: the engine's
|
|
// stream framing (NetworkPacketHeader + payload)
|
|
// assumes ordered reliable delivery, exactly what
|
|
// a reliable Steam message lane provides.
|
|
// Receive ReceiveMessagesOnConnection; copy into the
|
|
// host's pad buffer, normalize "no messages" to
|
|
// ReceiveNoData and connection-closed callbacks
|
|
// to ReceiveDisconnected.
|
|
// GetRemoteAddress GetConnectionInfo -> m_addrRemote (the FakeIP),
|
|
// so the mesh's identity checks keep working on
|
|
// SOCKADDR_IN values.
|
|
//
|
|
// Lobby flow that drives this transport (front-end work, not here):
|
|
// the lobby owner collects members' FakeIPs + loadouts via lobby data,
|
|
// builds the canonical egg with the ordered [pilots] list of FakeIPs,
|
|
// distributes it, and doubles as the console (RPL4CONSOLE marshals the
|
|
// mission; StopMissionMessage goes out over the console channel).
|
|
//
|
|
// Install with NetTransport_Set(new SteamNetTransport) BEFORE the
|
|
// network manager constructs (front of WinMain, when -steam / a Steam
|
|
// launch is detected).
|
|
//########################################################################
|
|
|
|
#ifdef RP412_STEAM
|
|
|
|
#include "l4nettransport.h"
|
|
|
|
class SteamNetTransport:
|
|
public NetTransport
|
|
{
|
|
public:
|
|
SteamNetTransport();
|
|
~SteamNetTransport();
|
|
|
|
Logical
|
|
Startup();
|
|
void
|
|
Cleanup();
|
|
|
|
int
|
|
GetLocalAddresses(
|
|
unsigned long *addresses,
|
|
int max_count
|
|
);
|
|
Logical
|
|
Resolve(
|
|
const char *host_name,
|
|
SOCKADDR_IN *address
|
|
);
|
|
|
|
Connection
|
|
Connect(
|
|
const SOCKADDR_IN *remote,
|
|
int local_port
|
|
);
|
|
Connection
|
|
Listen(
|
|
int local_port,
|
|
int backlog
|
|
);
|
|
Connection
|
|
Accept(Connection listener);
|
|
void
|
|
Close(Connection connection);
|
|
|
|
int
|
|
Send(
|
|
Connection connection,
|
|
const void *data,
|
|
int size
|
|
);
|
|
int
|
|
Receive(
|
|
Connection connection,
|
|
void *buffer,
|
|
int size
|
|
);
|
|
|
|
Logical
|
|
GetRemoteAddress(
|
|
Connection connection,
|
|
SOCKADDR_IN *address
|
|
);
|
|
};
|
|
|
|
#endif // RP412_STEAM
|