//===========================================================================//
// File:	netnub.hpp                                                          //
// Project: MUNGA real mode network nub                                      //
// Contents: Implementation details for the Affine matrices                  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 03/27/95  GAC  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#if !defined(NETNUB_HPP)
#	define NETNUB_HPP

// Version number of the netcom common block

#define	NETCOM_VERSION				11

// Maximum size of send and receive buffers (one ethernet packet)

#define	MAX_TRANSFER_SIZE			0xFF00U
#define	SHARED_MEMORY_SIZE	 	(MAX_TRANSFER_SIZE+4)

// Function codes (set by protected mode app before calling our interrupt)

#define	NETNUB_UNDEFINED			(-1)	// Netnub sets this function code after each operation is done
#define	NETNUB_STATUS				0		// Lets the netnub run and return status
#define	NETNUB_SEND_PACKET		1     // Send the packet in the buffer
#define	NETNUB_RECEIVE_PACKET	2     // Return a packet in the buffer
#define	NETNUB_TCP_OPEN         3		// Opens a TCP stream to another computer
#define	NETNUB_TCP_LISTEN       4     // Queue's a TCP listen that we can accept a connection on
#define	NETNUB_TCP_CLOSE        5		// Closes a TCP stream
#define	NETNUB_RESOLVE_ADDRESS	6     // Resolves a text IP address into a 32 bit number
#define	NETNUB_CHECK_SOCKET		7		// Checks a socket to see if anyone has connected yet
#define	NETNUB_UDP_OPEN			8		// Opens a UDP socket
#define	NETNUB_UDP_READ			9		// Returns a UDP record
#define	NETNUB_UDP_SEND			10		// Returns a UDP record
#define	NETNUB_MARKER_TEXT		11		// Writes the text supplied to standard out
#define	NETNUB_OPEN_FILE			12
#define	NETNUB_WRITE_FILE			13
#define	NETNUB_CLOSE_FILE			14
#define	NETNUB_MULTIPLE_SEND		15		// The has a request to send to multiple streams
#define 	NETNUB_MULTIPLE_RECEIVE	16		// Request to receive from several streams at once
#define	NETNUB_SET_SWITCHES		17		// Set the netnub runtime switches
#define	NETNUB_READ_FILE			18
#define	NETNUB_SEEK_FILE			19
#define	NETNUB_TCP_TICK			20

// Status returns from the netnub

#define	NETNUB_PARTIAL_TRANSMIT		(-5)  // Some part of a packet was not sent (very fatal)
#define	NETNUB_DATA_DUMPED			(-4)	// Data was dumped on the floor to avoid blocking
#define	NETNUB_STREAM_DISCONNECTED	(-3)	// Stream has been disconnected at the remote end
#define	NETNUB_RESOLVE_ERROR			(-2)	// Unable to resolve an internet address
#define	NETNUB_ERROR					(-1)	// Unspecified error (something broke)
#define	NETNUB_OK						0		// No error (everything ok)
#define	NETNUB_RECEIVED_PACKET		1		// A packet has been received and is in the buffer
#define	NETNUB_TCP_CONNECTED			2		// Notifys us that someone connected to the socket

// Netcom shared memory structure, used to pass commands and packets between the
// real and protected mode part of the application.  This structure should be
// allocated in the real mode application.
//
// IMPORTANT: The Version Number field must stay in the same place and should be
// checked by the protected mode app to make sure it was spawned by a real mode
// server with a matching Version Number.  This prevents the real and protected
// mode applications from accidentally getting out of sync.
//
// NOTE: More data will eventually be added, but it will be at the END of the
// structure so as not to mess up any machine code.

struct Netcom
	{
	long
		Version_Number;									// Version number of real mode netnub
	short
		Interrupt_Number,									// Interrupt number to use for communcations
		Function,											// * Function code (from protected mode app)
		Status;												// * Current status of the netnub
	unsigned short
		Buffer_Length;										// * Length of data in shared memory buffer
	char
		Shared_Memory_Buffer[SHARED_MEMORY_SIZE]; // * Data to send (from protected mode app)
	};

// NOTE: Fields marked with a * should be copied from real to protected mode,
// the interrupt called, then on return they should be copied back.  It is never
// necessary to copy more than "Buffer_Length" bytes of the Shared_Memory_Buffer.
//
// Typedef for a pointer to the netcom structure

typedef Netcom *Netcom_Ptr;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Description of operations
//
// Regardless of what function is being sent, the machine code procedure
// should always copy to real mode all the fields marked with a * before
// calling the interrupt.  On return from the interrupt all these fields should
// be copied back from real to protected mode.  It is never necessary to copy
// more than "Buffer_Length" bytes of the Shared_Memory_Buffer.  If "Buffer_Length"
// is zero, the copy of shared memory should be skipped.
//
// For each function code there can be two structures.  One will be the format
// of data in the Shared_Memory_Buffer for a "request" and the other for a reply
// to that request.  Either may be omitted if not necessary. When Shared_Memory_Buffer
// is received by either the protected mode or real mode part of the application
// it will be "cast" into the proper structure based on the function code.
// Note that some of these structures have only one data entry in them, they were
// made structures to allow for future expansion.
//
// After processing each function the real mode netnub will set the Function
// code to NETNUB_UNDEFINED so it can detect if the protected mode program
// has forgotten to set the function code for any reason.
//
// A Function of  NETNUB_RECEIVE_PACKET can result in either a packet or a connect
// being returned.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct	SetSwitchesRequest
{
	int
		blocking_switch;	// Setting of the blocking/non blocking mode
};
typedef SetSwitchesRequest *SetSwitchesRequestPtr;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

struct	StatusReturn
{
	unsigned long
		My_Net_Address;
};

typedef StatusReturn *StatusReturnPtr;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Structure in Shared_Memory_Buffer for a receive data packet

struct	ReceivePacketRequest
	{
	unsigned long
		Socket_Ptr;					// Socket pointer, see note above
	};

typedef ReceivePacketRequest *ReceivePacketRequestPtr;

#define	MAX_RECEIVE_DATA_SIZE	1600
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define	MULTIPLE_RECEIVE_PACKET_MAX	10

struct	MultipleReceivePacketRequest
	{
	unsigned long		// It's a long to insure structure alignment is predictable
		Socket_Count;										// Number of sockets in the list below
	unsigned long
		Socket_Ptrs[MULTIPLE_RECEIVE_PACKET_MAX];		// Contains socket pointers
	};

typedef MultipleReceivePacketRequest *MultipleReceivePacketRequestPtr;

struct	MultipleReceivePacketReturn
	{
	unsigned long		// It's a long to insure structure alignment is predictable
		Socket_Count;										// Number of sockets in the list below
	unsigned long		// long so it matches the format of MultipleSendPacketRequest
		Status[MULTIPLE_RECEIVE_PACKET_MAX];		  // length or error code for this socket
	char
		Received_Data[4];
	};
typedef MultipleReceivePacketReturn *MultipleReceivePacketReturnPtr;

#define MULTIPLE_RECEIVE_BUFFER_SIZE(data_size) (data_size + sizeof(MultipleReceivePacketReturn)-4)
#define MULTIPLE_RECEIVE_DATA_SIZE(buffer_size)	(buffer_size - sizeof(MultipleReceivePacketReturn)+4)

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

struct	SendPacketRequest
	{
	unsigned long
		Socket_Ptr;					// Socket pointer, see note above
	char
		Send_Data[4];				// !!! set to 4 to insure word alignment
	};

#define SEND_BUFFER_SIZE(data_size) ((data_size) + sizeof(SendPacketRequest) - 4)
#define SEND_DATA_SIZE(buffer_size)	((buffer_size) - sizeof(SendPacketRequest) + 4)
#define MAX_SEND_DATA_SIZE	(1604 - sizeof(SendPacketRequest))

struct	SendPacketReturn
	{
	unsigned long
		Send_Buffer_Used;					// Number of bytes in the send buffer
	};

typedef SendPacketReturn	*SendPacketReturnPtr;
typedef SendPacketRequest 	*SendPacketRequestPtr;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This command sends the same data to multiple destinations
//
#define MULTIPLE_SEND_PACKET_MAX		10

struct	MultipleSendPacketRequest
	{
	unsigned long		// It's a long to insure structure alignment is predictable
		Socket_Count;										// Number of sockets to send to
	unsigned long
		Socket_Ptrs[MULTIPLE_SEND_PACKET_MAX];		// Contains socket pointers
	char
		Send_Data[4];										// !!! set to 4 to insure word alignment
	};

struct	MultipleSendPacketReturn
	{
	unsigned long		// It's a long to insure structure alignment is predictable
		Socket_Count;										// Number of sockets to send to
	unsigned long		// long so it matches the format of MultipleSendPacketRequest
		Errors[MULTIPLE_SEND_PACKET_MAX];		  // Contains socket pointers
	unsigned long
		Send_Buffer_Used[MULTIPLE_SEND_PACKET_MAX];	 // Number of bytes in the send buffer
	};

#define MULTIPLE_SEND_BUFFER_SIZE(data_size) (data_size + sizeof(MultipleSendPacketRequest) - 4)
#define MULTIPLE_SEND_DATA_SIZE(buffer_size)	(buffer_size - sizeof(MultipleSendPacketRequest) + 4)
#define MAX_MULTIPLE_SEND_DATA_SIZE	(MAX_TRANSFER_SIZE - sizeof(MultipleSendPacketRequest) + 4)

typedef MultipleSendPacketRequest *MultipleSendPacketRequestPtr;
typedef MultipleSendPacketReturn  *MultipleSendPacketReturnPtr;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

struct	ResolveReturn
	{
	unsigned long
		Internet_Address;			// 32 bit internet address (if no error)
	};

typedef ResolveReturn *ResolveReturnPtr;

struct	TCPOpenRequest
	{
	short
		Local_Port,					// Local port number
		Remote_Port;				// Remote port number
	unsigned long
		Internet_Address;			// Internet address to connect with
	unsigned long
		Socket_Ptr;					// tcp_Socket address (at least 4300 bytes) if 0 netnub will try to allocate one
	};

struct	TCPOpenReturn
	{
	unsigned	long
		Socket_Ptr;					// pointer to the socket opened or error number
	};

typedef TCPOpenRequest *TCPOpenRequestPtr;
typedef TCPOpenReturn *TCPOpenReturnPtr;

struct	TCPCloseRequest
	{
	unsigned long
		Socket_Ptr;					// pointer to the socket to be closed
	};
typedef TCPCloseRequest *TCPCloseRequestPtr;

struct	TCPCheckSocketRequest
	{
	unsigned long
		Socket_Ptr;					// pointer to the socket to be checked
	};

struct	TCPCheckSocketReturn
	{
	unsigned long
		Socket_Net_Address;		// Net address of the person who connected
	};

typedef TCPCheckSocketRequest *TCPCheckSocketRequestPtr;
typedef TCPCheckSocketReturn *TCPCheckSocketReturnPtr;

struct	UDPOpenRequest
	{
	short
		Local_Port,					// Local port number
		Remote_Port;				// Remote port number
	unsigned long
		Internet_Address;			// Internet address to connect with
	unsigned long
		Socket_Ptr;					// UDP_Socket address (at least 2200 bytes) if 0 netnub will try to allocate one
	};

struct	UDPOpenReturn
	{
	unsigned	long
		Socket_Ptr;					// pointer to the socket opened or error number
	};

typedef UDPOpenRequest *UDPOpenRequestPtr;
typedef UDPOpenReturn *UDPOpenReturnPtr;

struct	OpenFileRequest
	{
		char
			File_Name[80];
		short
			Access;
		unsigned short
			Model;
	};

struct	OpenFileReturn
	{
		short
			File_Handle;
	};

typedef OpenFileRequest *OpenFileRequestPtr;
typedef OpenFileReturn *OpenFileReturnPtr;

struct	CloseFileRequest
	{
		short
			File_Handle;
	};

typedef CloseFileRequest *CloseFileRequestPtr;

struct	WriteFileRequest
	{
		short
			File_Handle;
		unsigned short
			Write_Length;
		char
			Write_Data[4];
	};

struct	WriteFileReturn
	{
		unsigned short
			Bytes_Written;
	};

typedef WriteFileRequest *WriteFileRequestPtr;
typedef WriteFileReturn *WriteFileReturnPtr;

struct	ReadFileRequest
	{
		short
			File_Handle;
		unsigned short
			Read_Length;
	};

struct	ReadFileReturn
	{
		char
			Read_Data[4];
	};

typedef ReadFileRequest *ReadFileRequestPtr;
typedef ReadFileReturn *ReadFileReturnPtr;

struct	SeekFileRequest
	{
		short
			File_Handle;
		short
			Seek_Mode;
		long
			Seek_Offset;
	};

struct	SeekFileReturn
	{
		long
			Seek_Position;
	};

typedef SeekFileRequest *SeekFileRequestPtr;
typedef SeekFileReturn *SeekFileReturnPtr;

#endif
