//===========================================================================//
// 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);
