/*==========================================================================;
 *
 *  Copyright (C) 1994-1995 Microsoft Corporation.  All Rights Reserved.
 *
 *  File:       dplayi.h
 *  Content:	DirectPlay data structures
 *  History:
 *   Date		By	Reason
 *   ====		==	======
 *	1/96		andyco	created it
 *  1/26/96		andyco	list data structures
 *	4/10/96		andyco	removed dpmess.h
 *	4/23/96		andyco	added ipx support
 *	4/25/96		andyco	messages now have blobs (sockaddr's) instead of dwReserveds  
 *	8/10/96		kipo	update max message size to be (2^20) - 1
 *	8/15/96		andyco	added local data
 *	8/30/96		andyco	clean it up b4 you shut it down! added globaldata.
 *	9/3/96		andyco	bagosockets
 *	12/18/96	andyco	de-threading - use a fixed # of prealloced threads.
 *						cruised the enum socket / thread - use the system
 *						socket / thread instead. updated global struct.
 *	2/7/97		andyco	moved all per IDirectPlay globals into globaldata
 *	3/17/97		kipo	GetServerAddress() now returns an error so that we can
 *						return DPERR_USERCANCEL from the EnumSessions dialog
 *	3/25/97		andyco	dec debug lock counter b4 dropping lock! 
 *	4/11/97		andyco	added saddrControlSocket
 *	5/12/97		kipo	added ADDR_BUFFER_SIZE constant and removed unused variables
 *	5/15/97		andyco	added ipx spare thread to global data - used when nameserver 
 *						migrates to this host to make sure that old system receive 
 *						thread shuts down 
 *	6/22/97		kipo	include wsnwlink.h
 *	7/11/97		andyco	added support for ws2 + async reply thread
 *	8/25/97		sohailm	added DEFAULT_RECEIVE_BUFFERSIZE
 *	12/5/97		andyco	voice support
 *	01/5/97		sohailm	added fd big set related definitions and macros (#15244).
 *	1/20/98		myronth	#ifdef'd out voice support
 *	1/27/98		sohailm	added firewall support
 *  2/13/98     aarono  added async support
 *	2/18/98    a-peterz Comment byte order mess-up with SERVER_xxx_PORT constants
 *  3/3/98      aarono  Bug#19188 remove accept thread 
 *  12/15/98    aarono  make async enum run async
 **************************************************************************/

#ifndef __DPSP_INCLUDED__
#define __DPSP_INCLUDED__
#include "windows.h"
#include "windowsx.h"
#include "wsipx.h"
#include "wsnwlink.h"
#include "dplaysp.h"
#include "bilink.h"
#include "fpm.h"

#ifdef DPLAY_VOICE_SUPPORT
#include "nmvoice.h"
#endif // DPLAY_VOICE_SUPPORT

#include "dpf.h"
#include "dputils.h"
#include "memalloc.h"
#include "resource.h"
#include <winsock.h>

// to turn off SendEx support, comment this flag out.
#define SENDEX 1

// use ddraw's assert code (see orion\misc\dpf.h)
#define ASSERT DDASSERT

typedef WORD PORT;
typedef UINT SOCKERR;

// server ports
// Oops! We forgot to convert these constants to net byte order in the code so we
// are really using port 47624 (0xBA08) instead of 2234 (0x08BA)
// We are living with the mistake.
#define SERVER_STREAM_PORT 2234
#define SERVER_DGRAM_PORT 2234

// range of ports used by sp (these are properly converted in the code)
#define DPSP_MIN_PORT	2300
#define DPSP_MAX_PORT	2400
#define DPSP_NUM_PORTS   ((DPSP_MAX_PORT - DPSP_MIN_PORT)+1)

#define SPMESSAGEHEADERLEN (sizeof(DWORD))
#define DEFAULT_RECEIVE_BUFFERSIZE	(4*1024)	// default receive buffer size per connection

// token means this message was received from a remote
// dplay.  
#define TOKEN 0xFAB00000

// helper_token means this message was forwarded by our server helper (host)
#define HELPER_TOKEN 0xCAB00000

// server_token means this message is exchanged with dplaysvr (needed to distinguish 
// messages from a remote dpwsockx)
#define SERVER_TOKEN 0xBAB00000

// tells receiver to reuse the connection for replies (needed to support fullduplex
// connections)
#define REUSE_TOKEN 0xAAB00000


// masks
#define TOKEN_MASK 0xFFF00000
#define SIZE_MASK (~TOKEN_MASK)

// maxmessagelen = 2^20 (need 12 bits for token)
#define SPMAXMESSAGELEN ( 1048576 - 1)
#define VALID_SP_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == TOKEN ? TRUE : FALSE)
#define VALID_HELPER_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == HELPER_TOKEN ? TRUE : FALSE)
#define VALID_REUSE_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == REUSE_TOKEN ? TRUE : FALSE)
#define VALID_SERVER_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == SERVER_TOKEN ? TRUE : FALSE)
#define SP_MESSAGE_SIZE(pMsg) ( (*((DWORD *)pMsg) & SIZE_MASK))
#define SP_MESSAGE_TOKEN(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK))

#define VALID_DPWS_MESSAGE(pMsg) (  VALID_SP_MESSAGE(pMsg) || VALID_HELPER_MESSAGE(pMsg) || \
									VALID_SERVER_MESSAGE(pMsg) || VALID_REUSE_MESSAGE(pMsg) )
#define VALID_DPLAYSVR_MESSAGE(pMsg) (	VALID_SP_MESSAGE(pMsg) || VALID_SERVER_MESSAGE(pMsg) || \
										VALID_REUSE_MESSAGE(pMsg) )

// the actual value is ~ 1500 bytes.
// we use 1024 to be safe (IPX won't packetize for us - it can only 
// send what the underlying net can handle (MTU))
#define IPX_MAX_DGRAM 1024

// relation of timeout to latency
#define TIMEOUT_SCALE 10
#define SPTIMEOUT(latency) (TIMEOUT_SCALE * latency)

// the default size of the socket cache (gBagOSockets)
#define MAX_CONNECTED_SOCKETS 64

// the initial size of the receive list
#define INITIAL_RECEIVELIST_SIZE 16

// version number for service provider
#define SPMINORVERSION      0x0000				// service provider-specific version number
#define VERSIONNUMBER		(DPSP_MAJORVERSION | SPMINORVERSION) // version number for service provider

// biggest user enterable addess
#define ADDR_BUFFER_SIZE 128
								 
// macro picks the service socket depending on ipx vs. tcp
// ipx uses dgram, tcp uses stream
#define SERVICE_SOCKET(pgd) ( (pgd->AddressFamily == AF_IPX) \
	? pgd->sSystemDGramSocket : pgd->sSystemStreamSocket)

//
// In order to listen to any number of sockets we need our own version
// of fd_set and FD_SET().  We call them fd_big_set and FD_BIG_SET().
//
typedef struct fd_big_set {
    u_int   fd_count;           // how many are SET?   
    SOCKET  fd_array[0];        // an array of SOCKETs 
} fd_big_set;

// stolen from winsock2.h

#ifndef _WINSOCK2API_

typedef HANDLE WSAEVENT;

typedef struct _WSAOVERLAPPED {
    DWORD        Internal;
    DWORD        InternalHigh;
    DWORD        Offset;
    DWORD        OffsetHigh;
    WSAEVENT     hEvent;
} WSAOVERLAPPED, FAR * LPWSAOVERLAPPED;

typedef struct _WSABUF {
    u_long      len;     /* the length of the buffer */
    char FAR *  buf;     /* the pointer to the buffer */
} WSABUF, FAR * LPWSABUF;
 
#endif // _WINSOCK2API_

#define MAX_SG 9
typedef WSABUF SENDARRAY[MAX_SG];
typedef SENDARRAY *PSENDARRAY;

#define SI_RELIABLE 0x0000001
#define SI_DATAGRAM 0x0000000

typedef struct _SENDINFO {
	WSAOVERLAPPED wsao;
	SENDARRAY     SendArray;	// Array of buffers
	DWORD         dwFlags;
	DWORD         dwSendFlags;  // DPLAY Send Flags.
	UINT          iFirstBuf;	// First buffer in array to use
	UINT          cBuffers;		// number of buffers to send (starting at iFirstBuf)
	BILINK        PendingSendQ; // when we're pending
	BILINK        ReadyToSendQ; // still waiting to send on this queue.
	DPID          idTo;
	DPID          idFrom;
	SOCKET        sSocket;		// reliable sends
	SOCKADDR      sockaddr;		// datagram sends
	DWORD_PTR     dwUserContext;
	DWORD         dwMessageSize;
	DWORD         RefCount;
	LONG          Status;
	struct _GLOBALDATA *pgd;
	IDirectPlaySP * lpISP;			//  indication interface
	#ifdef DEBUG
	DWORD         wserr;			// winsock extended error on wsasend call
	#endif
} SENDINFO, FAR *LPSENDINFO;

//
// This code is stolen from winsock.h.  It does the same thing as FD_SET()
// except that it assumes the fd_array is large enough.  AddSocketToReceiveList()
// grows the buffer as needed, so this better always be true.
//

#define FD_BIG_SET(fd, address) do { \
    ASSERT((address)->dwArraySize > (address)->pfdbigset->fd_count); \
    (address)->pfdbigset->fd_array[(address)->pfdbigset->fd_count++]=(fd);\
} while(0)

typedef struct fds {
	DWORD		dwArraySize;	// # of sockets that can be stored in pfdbigset->fd_array buffer
	fd_big_set	*pfdbigset;		
} FDS;

typedef struct _CONNECTION
{
	SOCKET	socket;				// socket we can receive off of
	DWORD	dwCurMessageSize;	// current message size
	DWORD	dwTotalMessageSize;	// total message size
	SOCKADDR sockAddr;			// addresses connected to
	LPBYTE	pBuffer;			// points to either default or temporary receive buffer
	LPBYTE	pDefaultBuffer;		// default receive buffer (pBuffer points to this by default)
	// added in DX6
	DWORD	dwFlags;			// connection attributes e.g. SP_CONNECION_FULLDUPLEX
} CONNECTION, *LPCONNECTION;

typedef struct _RECEIVELIST
{
	UINT nConnections;			// how many peers are we connected to
	LPCONNECTION pConnection;// list of connections
} RECEIVELIST;

typedef struct _REPLYLIST * LPREPLYLIST;
typedef struct _REPLYLIST
{
	LPREPLYLIST pNextReply; // next reply in list
	LPVOID	lpMessage; // bufffer to send
	SOCKADDR sockaddr;  // addr to send to
	DWORD dwMessageSize;
	SOCKET sSocket; // socket to send on
	LPBYTE pbSend; // index into message pointing to next byte to send
	DWORD  dwBytesLeft; // how many bytes are left to send
	DWORD  dwPlayerTo; // dpid of to player, 0=>not in use.
} REPLYLIST;

// w store one of these w/ each sys player
typedef struct _SPPLAYERDATA 
{
	SOCKADDR saddrStream,saddrDatagram;
}SPPLAYERDATA,*LPSPPLAYERDATA;

	
// the message header
typedef struct _MESSAGEHEADER
{
	DWORD dwMessageSize; // size of message
	SOCKADDR sockaddr;
} MESSAGEHEADER,*LPMESSAGEHEADER;


// this is one element in our bagosockets
typedef struct _PLAYERSOCK
{
	SOCKET sSocket;
	DPID dwPlayerID;
	// added in DX6
	SOCKADDR sockaddr;
	DWORD dwFlags;			// SP_CONNECTION_FULLDUPLEX, etc.
} PLAYERSOCK,*LPPLAYERSOCK;

// flags that describe a socket
#define SP_CONNECTION_FULLDUPLEX	0x00000001
// stream accept socket in the socket list.
#define SP_STREAM_ACCEPT            0x00000002	

#ifdef SENDEX
typedef struct FPOOL *LPFPOOL;
#endif

typedef struct _GLOBALDATA
{
	SOCKET sSystemDGramSocket;
	SOCKET sSystemStreamSocket;
	HANDLE hStreamReceiveThread;	// does receive and accept.
	HANDLE hDGramReceiveThread;
	HANDLE hReplyThread;
	RECEIVELIST ReceiveList;  // the list of sockets that StreamReceiveThread is listening on
	SOCKET sUnreliableSocket; // cached for unreliable send
	// reply thread	
	LPREPLYLIST pReplyList; // list of replies for reply thread to send
	HANDLE hReplyEvent; // signal the replythread that something is up
	// bago sockets stuff
	LPPLAYERSOCK BagOSockets; // socket cache
	UINT nSocketsInBag; // how many sockets in our bag
	ULONG uEnumAddress; // address entered by user for game server
	ULONG AddressFamily;
	SOCKADDR saddrNS; // address for name server
	DWORD dwLatency; // from dwreserved1 in registry
	BOOL bShutdown;
	SOCKADDR saddrControlSocket;
	BOOL bHaveServerAddress;
    CHAR szServerAddress[ADDR_BUFFER_SIZE];
	HANDLE	hIPXSpareThread; // if nameserver migrates to this host, we start a new receive thread 
							// (bound to our well known socket).  this is the handle to our old receive
							// thread - at shutdown, we need to make sure it's gone
	UINT iMaxUdpDg;			// maximum udp datagram size
	// added in DX6
	FDS	readfds;			// dynamic read fdset
	DWORD dwFlags;			// DPSP_OUTBOUNDONLY, etc.
	DWORD dwSessionFlags;	// session flags passed by app
	WORD wApplicationPort;	// port used for creating system player sockets
#ifdef BIGMESSAGEDEFENSE
	DWORD 	dwMaxMessageSize;	// the max message size we should receive
#endif

	HANDLE  hTCPEnumAsyncThread; // fix async enum.
	LPVOID  lpEnumMessage;
	DWORD   dwEnumMessageSize;
	SOCKADDR saEnum;
	DWORD    dwEnumAddrSize;
	SOCKET   sEnum;
	BOOL     bOutBoundOnly;

#ifdef SENDEX
	CRITICAL_SECTION csSendEx;  // locks sendex data.
	LPFPOOL	pSendInfoPool;     // pool for allocating SENDINFO+SPHeaders for scatter gather sends
	DWORD   dwBytesPending;		// count of total bytes in pending messages.
	DWORD   dwMessagesPending;  // count of total bytes pending.
	BILINK  PendingSendQ;
	BILINK  ReadyToSendQ;
	HANDLE  hSendWait;         // alert thread wait here.
	HANDLE  BogusHandle;	   // don't be fooled by waitfor multiple probs in Win9x, put -1 here.
	BOOL    bSendThreadRunning;
	BOOL    bStopSendThread;
#endif

} GLOBALDATA,*LPGLOBALDATA;

/*
 * SP Flags (from registry)
 */
#define DPSP_OUTBOUNDONLY	0x00000001

/*
 * DPLAYSVR - DPWSOCKX communication related information
 */

// MSG_HDR indicates a dpwsock system message
#define MSG_HDR 0x736F636B

#define SP_MSG_VERSION	1	// DX6

#define IS_VALID_DPWS_MESSAGE(pMsg) (MSG_HDR == (*((DWORD *)(pMsg))) )
#define COMMAND_MASK 0X0000FFFF

#define GET_MESSAGE_VERSION(pMsg) ( ((pMsg)->dwCmdToken & ~COMMAND_MASK) >> 16 )
#define GET_MESSAGE_COMMAND(pMsg) ( (pMsg)->dwCmdToken & COMMAND_MASK)

#define SET_MESSAGE_HDR(pMsg)  (*((DWORD *)(pMsg)) = MSG_HDR )
#define SET_MESSAGE_COMMAND(pMsg,dwCmd) ((pMsg)->dwCmdToken = ((dwCmd & COMMAND_MASK) \
	| (SP_MSG_VERSION<<16)) )

typedef struct {
	DWORD dwHeader;
    DWORD dwCmdToken;	
} MSG_GENERIC, *LPMSG_GENERIC;


// DPLAYSVR


// macros for manipulating the sockaddr in the player data
#ifdef DEBUG
extern int gCSCount;
#endif
extern CRITICAL_SECTION gcsDPSPCritSection;	// defined in dllmain.c
#define INIT_DPSP_CSECT() InitializeCriticalSection(&gcsDPSPCritSection);
#define FINI_DPSP_CSECT() DeleteCriticalSection(&gcsDPSPCritSection);
#ifdef DEBUG
#define ENTER_DPSP() EnterCriticalSection(&gcsDPSPCritSection),gCSCount++;
#define LEAVE_DPSP() gCSCount--,LeaveCriticalSection(&gcsDPSPCritSection);
#else
#define ENTER_DPSP() EnterCriticalSection(&gcsDPSPCritSection);
#define LEAVE_DPSP() LeaveCriticalSection(&gcsDPSPCritSection);
#endif // DEBUG

// get a pointer to the players socket address - used by macros below
#define DGRAM_PSOCKADDR(ppd) ((SOCKADDR *)&(((LPSPPLAYERDATA)ppd)->saddrDatagram))
#define STREAM_PSOCKADDR(ppd) ((SOCKADDR *)&(((LPSPPLAYERDATA)ppd)->saddrStream))

// get the udp ip addr from a player
#define IP_DGRAM_ADDR(ppd) 	(((SOCKADDR_IN *)DGRAM_PSOCKADDR(ppd))->sin_addr.s_addr)
#define IP_DGRAM_PORT(ppd) 	(((SOCKADDR_IN *)DGRAM_PSOCKADDR(ppd))->sin_port)

// get the stream ip addr from a player
#define IP_STREAM_ADDR(ppd) 	(((SOCKADDR_IN *)STREAM_PSOCKADDR(ppd))->sin_addr.s_addr)
#define IP_STREAM_PORT(ppd) 	(((SOCKADDR_IN *)STREAM_PSOCKADDR(ppd))->sin_port)

// used to get the name of the computer we're running on in spinit
#define HOST_NAME_LENGTH 50

// if it's not ipx, it's ip
// {685BC400-9D2C-11cf-A9CD-00AA006886E3}
DEFINE_GUID(GUID_IPX, 
0x685bc400, 0x9d2c, 0x11cf, 0xa9, 0xcd, 0x0, 0xaa, 0x0, 0x68, 0x86, 0xe3);

// 36E95EE0-8577-11cf-960C-0080C7534E82
DEFINE_GUID(GUID_TCP,
0x36E95EE0, 0x8577, 0x11cf, 0x96, 0xc, 0x0, 0x80, 0xc7, 0x53, 0x4e, 0x82);

// {3A826E00-31DF-11d0-9CF9-00A0C90A43CB}
DEFINE_GUID(GUID_LOCAL_TCP, 
0x3a826e00, 0x31df, 0x11d0, 0x9c, 0xf9, 0x0, 0xa0, 0xc9, 0xa, 0x43, 0xcb);


// globals
// ghinstance is used when putting up the dialog box to prompt for ip addr
extern HANDLE ghInstance; // set in dllmain. instance handle for dpwsock.dll

#ifdef DEBUG

extern void DebugPrintAddr(UINT level,LPSTR pStr,SOCKADDR * psockaddr);
#define DEBUGPRINTADDR(n,pstr,psockaddr) DebugPrintAddr(n,pstr,psockaddr);
extern void DebugPrintSocket(UINT level,LPSTR pStr,SOCKET * pSock);
#define DEBUGPRINTSOCK(n,pstr,psock) DebugPrintSocket(n,pstr,psock);

#else // debug

#define DEBUGPRINTADDR(n,pstr,psockaddr)
#define DEBUGPRINTSOCK(n,pstr,psock)

#endif // debug

// global vars
extern BOOL gbVoiceOpen; // set to TRUE if we have nm call open

// from dpsp.c
extern HRESULT WaitForThread(HANDLE hThread);
extern HRESULT SetupControlSocket();
extern HRESULT WINAPI SP_Close(LPDPSP_CLOSEDATA pcd);
extern HRESULT InternalReliableSend(LPGLOBALDATA pgd, DPID idPlayerTo, SOCKADDR *
	lpSockAddr, LPBYTE lpMessage, DWORD dwMessageSize);
extern HRESULT DoTCPEnumSessions(LPGLOBALDATA pgd, SOCKADDR *lpSockAddr, DWORD dwAddrSize,
	LPDPSP_ENUMSESSIONSDATA ped, BOOL bHostWillReuseConnection);
extern HRESULT SendControlMessage(LPGLOBALDATA pgd);
extern HRESULT SendReuseConnectionMessage(SOCKET sSocket);
extern HRESULT AddSocketToBag(LPGLOBALDATA pgd, SOCKET socket, DPID dpid, SOCKADDR *psockaddr, DWORD dwFlags);
extern BOOL FindSocketInReceiveList(LPGLOBALDATA pgd, SOCKADDR *pSockAddr, SOCKET * psSocket);
extern void RemoveSocketFromReceiveList(LPGLOBALDATA pgd, SOCKET socket);
extern void RemoveSocketFromBag(LPGLOBALDATA pgd, SOCKET socket);
extern BOOL FindSocketInBag(LPGLOBALDATA pgd, SOCKADDR *pSockAddr, SOCKET * psSocket, LPDPID lpdpidPlayer);
extern HRESULT GetSocketFromBag(LPGLOBALDATA pgd,SOCKET * psSocket, DWORD dwID, LPSOCKADDR psockaddr);
extern HRESULT CreateAndConnectSocket(LPGLOBALDATA pgd,SOCKET * psSocket,DWORD dwType,LPSOCKADDR psockaddr, BOOL bOutBoundOnly);
extern void RemovePlayerFromSocketBag(LPGLOBALDATA pgd,DWORD dwID);
extern void SetMessageHeader(LPDWORD pdwMsg,DWORD dwSize, DWORD dwToken);
extern void KillTCPEnumAsyncThread(LPGLOBALDATA pgd);

// Support for SendEx in dpsp.c

extern HRESULT UnreliableSendEx(LPDPSP_SENDEXDATA psd, LPSENDINFO lpSendInfo);
extern HRESULT ReliableSendEx(LPDPSP_SENDEXDATA psd, LPSENDINFO pSendInfo);
extern VOID RemovePendingAsyncSends(LPGLOBALDATA pgd, DPID dwPlayerTo);
extern BOOL bAsyncSendsPending(LPGLOBALDATA pgd, DPID dwPlayerTo);

// from winsock.c
extern HRESULT FAR PASCAL CreateSocket(LPGLOBALDATA pgd,SOCKET * psock,INT type,
	WORD port,ULONG address,SOCKERR * perr, BOOL bInRange);
extern HRESULT SPConnect(SOCKET* psSocket, LPSOCKADDR psockaddr,UINT addrlen, BOOL bOutBoundOnly);
extern HRESULT CreateAndInitStreamSocket(LPGLOBALDATA pgd);
extern HRESULT SetPlayerAddress(LPGLOBALDATA pgd,LPSPPLAYERDATA ppd,SOCKET sSocket,BOOL fStream); 
extern HRESULT CreatePlayerDgramSocket(LPGLOBALDATA pgd,LPSPPLAYERDATA ppd,DWORD dwFlags); 
extern HRESULT CreatePlayerStreamSocket(LPGLOBALDATA pgd,LPSPPLAYERDATA ppd,DWORD dwFlags); 
extern HRESULT SetDescriptionAddress(LPSPPLAYERDATA ppd,LPDPSESSIONDESC2 lpsdDesc);
extern HRESULT SetReturnAddress(LPVOID pmsg,SOCKET sSocket);
extern HRESULT GetReturnAddress(LPVOID pmsg,LPSOCKADDR psockaddr);
extern HRESULT GetServerAddress(LPGLOBALDATA pgd,LPSOCKADDR psockaddr) ;
extern void IPX_SetNodenum(LPVOID pmsg,SOCKADDR_IPX * psockaddr);
extern void IP_GetAddr(SOCKADDR_IN * paddrDest,SOCKADDR_IN * paddrSrc) ;
extern void IP_SetAddr(LPVOID pBuffer,SOCKADDR_IN * psockaddr);
extern void IPX_GetNodenum(SOCKADDR_IPX * paddrDest,SOCKADDR_IPX * paddrSrc) ;
extern HRESULT KillSocket(SOCKET sSocket,BOOL fStream,BOOL fHard);
extern HRESULT KillPlayerSockets();
extern HRESULT GetAddress(ULONG * puAddress,char *pBuffer,int cch);
extern HRESULT KillThread(HANDLE hThread);

// from wsock2.c
extern DWORD WINAPI AsyncSendThreadProc(LPVOID pvCast);
extern HRESULT InitWinsock2();
extern HRESULT GetMaxUdpBufferSize(SOCKET socket, unsigned int * lpiSize);

extern HRESULT InternalReliableSendEx(LPGLOBALDATA pgd, LPDPSP_SENDEXDATA psd, 
				LPSENDINFO pSendInfo, SOCKADDR *lpSockAddr);
extern DWORD WINAPI SPSendThread(LPVOID lpv);


#ifdef DPLAY_VOICE_SUPPORT
// from spvoice.c
extern HRESULT WINAPI SP_OpenVoice(LPDPSP_OPENVOICEDATA pod) ;
extern HRESULT WINAPI SP_CloseVoice(LPDPSP_CLOSEVOICEDATA pod) ;
#endif // DPLAY_VOICE_SUPPORT

// from handler.c
HRESULT HandleServerMessage(LPGLOBALDATA pgd, SOCKET sSocket, LPBYTE pBuffer, DWORD dwSize);

#ifdef FULLDUPLEX_SUPPORT
// from registry.c
HRESULT GetFlagsFromRegistry(LPGUID lpguidSP, LPDWORD lpdwFlags);
#endif // FULLDUPLEX_SUPPORT

// MACROS based on fixed pool manager.

#endif

