Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

782 lines
29 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dplayi.h
  6. * Content: DirectPlay data structures
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 1/96 andyco created it
  11. * 1/26/96 andyco list data structures
  12. * 4/10/96 andyco removed dpmess.h
  13. * 4/23/96 andyco added ipx support
  14. * 4/25/96 andyco messages now have blobs (sockaddr's) instead of dwReserveds
  15. * 8/10/96 kipo update max message size to be (2^20) - 1
  16. * 8/15/96 andyco added local data
  17. * 8/30/96 andyco clean it up b4 you shut it down! added globaldata.
  18. * 9/3/96 andyco bagosockets
  19. * 12/18/96 andyco de-threading - use a fixed # of prealloced threads.
  20. * cruised the enum socket / thread - use the system
  21. * socket / thread instead. updated global struct.
  22. * 2/7/97 andyco moved all per IDirectPlay globals into globaldata
  23. * 3/17/97 kipo GetServerAddress() now returns an error so that we can
  24. * return DPERR_USERCANCEL from the EnumSessions dialog
  25. * 3/25/97 andyco dec debug lock counter b4 dropping lock!
  26. * 4/11/97 andyco added saddrControlSocket
  27. * 5/12/97 kipo added ADDR_BUFFER_SIZE constant and removed unused variables
  28. * 5/15/97 andyco added ipx spare thread to global data - used when nameserver
  29. * migrates to this host to make sure that old system receive
  30. * thread shuts down
  31. * 6/22/97 kipo include wsnwlink.h
  32. * 7/11/97 andyco added support for ws2 + async reply thread
  33. * 8/25/97 sohailm added DEFAULT_RECEIVE_BUFFERSIZE
  34. * 12/5/97 andyco voice support
  35. * 01/5/97 sohailm added fd big set related definitions and macros (#15244).
  36. * 1/20/98 myronth #ifdef'd out voice support
  37. * 1/27/98 sohailm added firewall support
  38. * 2/13/98 aarono added async support
  39. * 2/18/98 a-peterz Comment byte order mess-up with SERVER_xxx_PORT constants
  40. * 3/3/98 aarono Bug#19188 remove accept thread
  41. * 12/15/98 aarono make async enum run async
  42. * 01/12/2000 aarono added rsip support
  43. * 09/12/2000 aarono workaround winsock bug, only allow 1 pending async send per socket
  44. * otherwise data can get misordered. (MB#43990)
  45. **************************************************************************/
  46. #ifndef __DPSP_INCLUDED__
  47. #define __DPSP_INCLUDED__
  48. #include "windows.h"
  49. #include "windowsx.h"
  50. #include "wsipx.h"
  51. #include "wsnwlink.h"
  52. #include "dplaysp.h"
  53. #include "bilink.h"
  54. #include "fpm.h"
  55. #include "dpf.h"
  56. #include "dputils.h"
  57. #include "memalloc.h"
  58. #include "resource.h"
  59. #include <winsock.h>
  60. // to turn off SendEx support, comment this flag out.
  61. #define SENDEX 1
  62. // NOTE! USE_RSIP and USE_NATHLP should be mutually exclusive
  63. // to turn off RSIP support, comment this flag out.
  64. //#define USE_RSIP 1
  65. // turn ON to use NATHLP helper DLL
  66. #define USE_NATHELP 1
  67. #if USE_NATHELP
  68. #include "dpnathlp.h"
  69. #endif
  70. // use ddraw's assert code (see orion\misc\dpf.h)
  71. #define ASSERT DDASSERT
  72. typedef WORD PORT;
  73. typedef UINT SOCKERR;
  74. // server ports
  75. // Oops! We forgot to convert these constants to net byte order in the code so we
  76. // are really using port 47624 (0xBA08) instead of 2234 (0x08BA)
  77. // We are living with the mistake.
  78. #define SERVER_STREAM_PORT 2234
  79. #define SERVER_DGRAM_PORT 2234
  80. // range of ports used by sp (these are properly converted in the code)
  81. #define DPSP_MIN_PORT 2300
  82. #define DPSP_MAX_PORT 2400
  83. #define DPSP_NUM_PORTS ((DPSP_MAX_PORT - DPSP_MIN_PORT)+1)
  84. #define SPMESSAGEHEADERLEN (sizeof(DWORD))
  85. #define DEFAULT_RECEIVE_BUFFERSIZE (4*1024) // default receive buffer size per connection
  86. // token means this message was received from a remote
  87. // dplay.
  88. #define TOKEN 0xFAB00000
  89. // helper_token means this message was forwarded by our server helper (host)
  90. #define HELPER_TOKEN 0xCAB00000
  91. // server_token means this message is exchanged with dplaysvr (needed to distinguish
  92. // messages from a remote dpwsockx)
  93. #define SERVER_TOKEN 0xBAB00000
  94. // tells receiver to reuse the connection for replies (needed to support fullduplex
  95. // connections)
  96. #define REUSE_TOKEN 0xAAB00000
  97. // we linger on async sends for 2.5 seconds before hard closing them
  98. // this avoids letting the socket get into the TIME_WAIT state for 4 minutes.
  99. // essentially we are doing a close with linger for 2.5 secs followed by an abort.
  100. #define LINGER_TIME 2500
  101. // masks
  102. #define TOKEN_MASK 0xFFF00000
  103. #define SIZE_MASK (~TOKEN_MASK)
  104. // maxmessagelen = 2^20 (need 12 bits for token)
  105. #define SPMAXMESSAGELEN ( 1048576 - 1)
  106. #define VALID_SP_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == TOKEN ? TRUE : FALSE)
  107. #define VALID_HELPER_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == HELPER_TOKEN ? TRUE : FALSE)
  108. #define VALID_REUSE_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == REUSE_TOKEN ? TRUE : FALSE)
  109. #define VALID_SERVER_MESSAGE(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK) == SERVER_TOKEN ? TRUE : FALSE)
  110. #define SP_MESSAGE_SIZE(pMsg) ( (*((DWORD *)pMsg) & SIZE_MASK))
  111. #define SP_MESSAGE_TOKEN(pMsg) ( (*((DWORD *)pMsg) & TOKEN_MASK))
  112. #define VALID_DPWS_MESSAGE(pMsg) ( VALID_SP_MESSAGE(pMsg) || VALID_HELPER_MESSAGE(pMsg) || \
  113. VALID_SERVER_MESSAGE(pMsg) || VALID_REUSE_MESSAGE(pMsg) )
  114. #define VALID_DPLAYSVR_MESSAGE(pMsg) ( VALID_SP_MESSAGE(pMsg) || VALID_SERVER_MESSAGE(pMsg) || \
  115. VALID_REUSE_MESSAGE(pMsg) )
  116. // the actual value is ~ 1500 bytes.
  117. // we use 1024 to be safe (IPX won't packetize for us - it can only
  118. // send what the underlying net can handle (MTU))
  119. #define IPX_MAX_DGRAM 1024
  120. // relation of timeout to latency
  121. #define TIMEOUT_SCALE 10
  122. #define SPTIMEOUT(latency) (TIMEOUT_SCALE * latency)
  123. // the default size of the socket cache (gBagOSockets)
  124. #define MAX_CONNECTED_SOCKETS 64
  125. // the initial size of the receive list
  126. #define INITIAL_RECEIVELIST_SIZE 16
  127. // version number for service provider
  128. #define SPMINORVERSION 0x0000 // service provider-specific version number
  129. #define VERSIONNUMBER (DPSP_MAJORVERSION | SPMINORVERSION) // version number for service provider
  130. // biggest user enterable addess
  131. #define ADDR_BUFFER_SIZE 128
  132. // macro picks the service socket depending on ipx vs. tcp
  133. // ipx uses dgram, tcp uses stream
  134. #define SERVICE_SOCKET(pgd) ( (pgd->AddressFamily == AF_IPX) \
  135. ? pgd->sSystemDGramSocket : pgd->sSystemStreamSocket)
  136. #if USE_RSIP
  137. #define SERVICE_SADDR_PUBLIC(pgd)( (pgd->sRsip == INVALID_SOCKET) \
  138. ? (NULL) : (&pgd->saddrpubSystemStreamSocket) )
  139. #define DGRAM_SADDR_RSIP(pgd) ( (pgd->sRsip == INVALID_SOCKET) \
  140. ? (NULL) : (&pgd->saddrpubSystemDGramSocket) )
  141. #elif USE_NATHELP
  142. #define SERVICE_SADDR_PUBLIC(pgd)( (pgd->pINatHelp) \
  143. ? (&pgd->saddrpubSystemStreamSocket):NULL )
  144. #define DGRAM_SADDR_RSIP(pgd) ( (pgd->pINatHelp) \
  145. ? (&pgd->saddrpubSystemDGramSocket):NULL )
  146. #else
  147. #define SERVICE_SADDR_PUBLIC(pgd) NULL
  148. #define DGRAM_SADDR_RSIP(pgd) NULL
  149. #endif
  150. //
  151. // In order to listen to any number of sockets we need our own version
  152. // of fd_set and FD_SET(). We call them fd_big_set and FD_BIG_SET().
  153. //
  154. typedef struct fd_big_set {
  155. u_int fd_count; // how many are SET?
  156. SOCKET fd_array[0]; // an array of SOCKETs
  157. } fd_big_set;
  158. // stolen from winsock2.h
  159. #ifndef _WINSOCK2API_
  160. typedef HANDLE WSAEVENT;
  161. typedef struct _WSAOVERLAPPED {
  162. DWORD Internal;
  163. DWORD InternalHigh;
  164. DWORD Offset;
  165. DWORD OffsetHigh;
  166. WSAEVENT hEvent;
  167. } WSAOVERLAPPED, FAR * LPWSAOVERLAPPED;
  168. typedef struct _WSABUF {
  169. u_long len; /* the length of the buffer */
  170. char FAR * buf; /* the pointer to the buffer */
  171. } WSABUF, FAR * LPWSABUF;
  172. #endif // _WINSOCK2API_
  173. #define MAX_SG 9
  174. typedef WSABUF SENDARRAY[MAX_SG];
  175. typedef SENDARRAY *PSENDARRAY;
  176. #define SI_RELIABLE 0x0000001
  177. #define SI_DATAGRAM 0x0000002
  178. #define SI_INTERNALBUFF 0x00000004
  179. typedef struct _SENDINFO {
  180. WSAOVERLAPPED wsao;
  181. SENDARRAY SendArray; // Array of buffers
  182. DWORD dwFlags;
  183. DWORD dwSendFlags; // DPLAY Send Flags.
  184. UINT iFirstBuf; // First buffer in array to use
  185. UINT cBuffers; // number of buffers to send (starting at iFirstBuf)
  186. BILINK PendingSendQ; // when we're pending
  187. BILINK PendingConnSendQ; // send queue for pending connections, also for pending when an async send is outstanding.
  188. BILINK ReadyToSendQ; // still waiting to send on this queue.
  189. DPID idTo;
  190. DPID idFrom;
  191. SOCKET sSocket; // reliable sends
  192. SOCKADDR sockaddr; // datagram sends
  193. DWORD_PTR dwUserContext;
  194. DWORD dwMessageSize;
  195. DWORD RefCount;
  196. LONG Status;
  197. struct _PLAYERCONN *pConn;
  198. struct _GLOBALDATA *pgd;
  199. IDirectPlaySP * lpISP; // indication interface
  200. } SENDINFO, *PSENDINFO, FAR *LPSENDINFO;
  201. //
  202. // This code is stolen from winsock.h. It does the same thing as FD_SET()
  203. // except that it assumes the fd_array is large enough. AddSocketToReceiveList()
  204. // grows the buffer as needed, so this better always be true.
  205. //
  206. #define FD_BIG_SET(fd, address) do { \
  207. ASSERT((address)->dwArraySize > (address)->pfdbigset->fd_count); \
  208. (address)->pfdbigset->fd_array[(address)->pfdbigset->fd_count++]=(fd);\
  209. } while(0)
  210. typedef struct fds {
  211. DWORD dwArraySize; // # of sockets that can be stored in pfdbigset->fd_array buffer
  212. fd_big_set *pfdbigset;
  213. } FDS;
  214. typedef struct _CONNECTION
  215. {
  216. SOCKET socket; // socket we can receive off of
  217. DWORD dwCurMessageSize; // current message size
  218. DWORD dwTotalMessageSize; // total message size
  219. SOCKADDR sockAddr; // addresses connected to
  220. LPBYTE pBuffer; // points to either default or temporary receive buffer
  221. LPBYTE pDefaultBuffer; // default receive buffer (pBuffer points to this by default)
  222. // added in DX6
  223. DWORD dwFlags; // connection attributes e.g. SP_CONNECION_FULLDUPLEX
  224. } CONNECTION, *LPCONNECTION;
  225. typedef struct _RECEIVELIST
  226. {
  227. UINT nConnections; // how many peers are we connected to
  228. LPCONNECTION pConnection;// list of connections
  229. } RECEIVELIST;
  230. typedef struct _REPLYLIST * LPREPLYLIST;
  231. typedef struct _REPLYLIST
  232. {
  233. LPREPLYLIST pNextReply; // next reply in list
  234. LPVOID lpMessage; // bufffer to send
  235. SOCKADDR sockaddr; // addr to send to
  236. DWORD dwMessageSize;
  237. SOCKET sSocket; // socket to send on
  238. LPBYTE pbSend; // index into message pointing to next byte to send
  239. DWORD dwBytesLeft; // how many bytes are left to send
  240. DWORD dwPlayerTo; // dpid of to player, 0=>not in use.
  241. DWORD tSent; // time we sent the last bit of reply.
  242. } REPLYLIST;
  243. // w store one of these w/ each sys player
  244. typedef struct _SPPLAYERDATA
  245. {
  246. SOCKADDR saddrStream,saddrDatagram;
  247. }SPPLAYERDATA,*LPSPPLAYERDATA;
  248. // the message header
  249. typedef struct _MESSAGEHEADER
  250. {
  251. DWORD dwMessageSize; // size of message
  252. SOCKADDR sockaddr;
  253. } MESSAGEHEADER,*LPMESSAGEHEADER;
  254. // this is one element in our bagosockets
  255. typedef struct _PLAYERSOCK
  256. {
  257. SOCKET sSocket;
  258. DPID dwPlayerID;
  259. // added in DX6
  260. SOCKADDR sockaddr;
  261. DWORD dwFlags; // SP_CONNECTION_FULLDUPLEX, etc.
  262. } PLAYERSOCK,*LPPLAYERSOCK;
  263. // PLAYERCONN structure is used for describing the reliable connection between
  264. // this node and the remote player ID.
  265. #define PLAYER_HASH_SIZE 256
  266. #define SOCKET_HASH_SIZE 256
  267. #define PLYR_CONN_PENDING 0x00000001 // connection pending.
  268. #define PLYR_ACCEPT_PENDING 0x00000002 // expecting an accept(got WSAEISCONN on connect attempt).
  269. #define PLYR_CONNECTED 0x00000004 // connection has succeeded.
  270. #define PLYR_ACCEPTED 0x00000008
  271. // players using old dpwsockx will use seperate inbound/outbound connections.
  272. #define PLYR_NEW_CLIENT 0x00000010 // player uses just 1 socket.
  273. #define PLYR_SOCKHASH 0x00000020
  274. #define PLYR_DPIDHASH 0x00000040
  275. #define PLYR_PENDINGLIST 0x00000080
  276. #define PLYR_OLD_CLIENT 0x00000100
  277. #define PLYR_DESTROYED 0x80000000 // already Dumped existence ref.
  278. typedef struct _PLAYERCONN {
  279. struct _PLAYERCONN *pNextP; // dwPlayerId hash table list.
  280. struct _PLAYERCONN *pNextS; // IOSock hash table list.
  281. DWORD dwRefCount; // References.
  282. DPID dwPlayerID;
  283. SOCKET sSocket;
  284. DWORD lNetEventsSocket;
  285. SOCKET sSocketIn; // they may have a different inbound socket.
  286. DWORD lNetEventsSocketIn;
  287. DWORD dwFlags;
  288. VOL BOOL bSendOutstanding; // if we have a send in process. only 1 at a time per connection.
  289. BILINK PendingConnSendQ; // Sends waiting for connection to complete, and now also for sends to complete.
  290. BILINK InboundPendingList; // On the list of pending inbound connections
  291. // index of listener list we are listening in.(not the index in the list).
  292. INT iEventHandle;
  293. PCHAR pReceiveBuffer; // if we get bigger than 4K.
  294. PCHAR pDefaultReceiveBuffer; // 4K Receive Buffer
  295. DWORD cbReceiveBuffer; // total size of receive buffer
  296. DWORD cbReceived; // total bytes received in buffer
  297. DWORD cbExpected; // number of bytes we're trying to receive.
  298. BOOL bCombine; // whether we combined with another connection.
  299. BOOL bTrusted; // whether we trust the remote client
  300. // this is the socket address corresponding to the sSocket which may
  301. // be used for both inbound and outbound connections. Socket hash keys
  302. // off of this value. Which will be the "reply" address of any inbound
  303. // messages not associated with a player.
  304. union {
  305. SOCKADDR sockaddr;
  306. SOCKADDR_IN sockaddr_in;
  307. } IOSock;
  308. // clients without the new dpwsockx.dll will connect with a socket they
  309. // are not listening on. This is the address we are receiving from,
  310. // corresponds to sSocketIn.
  311. union {
  312. SOCKADDR sockaddr;
  313. SOCKADDR_IN sockaddr_in;
  314. } IOnlySock;
  315. } PLAYERCONN, *PPLAYERCONN;
  316. // number of handles we distribute listens across so we can use
  317. // wait for multiple objects and WSAEvent Select for listening.
  318. #define NUM_EVENT_HANDLES 48
  319. #define MAX_EVENTS_PER_HANDLE 32
  320. //#define NUM_EVENT_HANDLES 3
  321. //#define MAX_EVENTS_PER_HANDLE 2
  322. #define INVALID_EVENT_SLOT 0xFFFFFFFF
  323. // Note this sets an absolute cap of 48*32 = 1536 listeners
  324. // per session. Any connect attempts after that must be failed.
  325. // Note also, with old clients this can mean a max of half that
  326. // many actual players. (We could pull out listening from a player
  327. // if he got a different inbound connection rather than re-using
  328. // the outbound connection to solve this)
  329. typedef struct _EVENTLIST {
  330. VOL DWORD nConn; // number of
  331. PPLAYERCONN pConn[MAX_EVENTS_PER_HANDLE];
  332. } EVENTLIST, *PEVENTLIST;
  333. #if USE_RSIP
  334. typedef struct _RSIP_LEASE_RECORD {
  335. struct _RSIP_LEASE_RECORD * pNext;
  336. DWORD dwRefCount;
  337. BOOL ftcp_udp;
  338. DWORD tExpiry;
  339. DWORD bindid;
  340. DWORD addrV4; // remote IP address
  341. SHORT rport; // remote port
  342. SHORT port; // local port
  343. } RSIP_LEASE_RECORD, *PRSIP_LEASE_RECORD;
  344. // Cache of queried address mappings so we don't
  345. // need to requery the mappings over and over
  346. typedef struct _ADDR_ENTRY {
  347. struct _ADDR_ENTRY *pNext;
  348. BOOL ftcp_udp;
  349. DWORD tExpiry;
  350. DWORD addr;
  351. DWORD raddr;
  352. WORD port;
  353. WORD rport;
  354. } ADDR_ENTRY, *PADDR_ENTRY;
  355. #endif
  356. // flags that describe a socket
  357. #define SP_CONNECTION_FULLDUPLEX 0x00000001
  358. // stream accept socket in the socket list.
  359. #define SP_STREAM_ACCEPT 0x00000002
  360. #ifdef SENDEX
  361. typedef struct FPOOL *LPFPOOL;
  362. #endif
  363. typedef struct _GLOBALDATA
  364. {
  365. IDirectPlaySP * pISP;
  366. SOCKET sSystemDGramSocket;
  367. SOCKET sSystemStreamSocket;
  368. HANDLE hStreamReceiveThread; // does receive and accept.
  369. HANDLE hDGramReceiveThread;
  370. HANDLE hReplyThread;
  371. RECEIVELIST ReceiveList; // the list of sockets that StreamReceiveThread is listening on
  372. // reply thread
  373. LPREPLYLIST pReplyList; // list of replies for reply thread to send
  374. LPREPLYLIST pReplyCloseList; // list of replies to close.
  375. HANDLE hReplyEvent; // signal the replythread that something is up
  376. // bago sockets stuff
  377. LPPLAYERSOCK BagOSockets; // socket cache
  378. UINT nSocketsInBag; // how many sockets in our bag
  379. ULONG uEnumAddress; // address entered by user for game server
  380. ULONG AddressFamily;
  381. SOCKADDR saddrNS; // address for name server
  382. DWORD dwLatency; // from dwreserved1 in registry
  383. BOOL bShutdown;
  384. BOOL bHaveServerAddress;
  385. CHAR szServerAddress[ADDR_BUFFER_SIZE];
  386. HANDLE hIPXSpareThread; // if nameserver migrates to this host, we start a new receive thread
  387. // (bound to our well known socket). this is the handle to our old receive
  388. // thread - at shutdown, we need to make sure it's gone
  389. UINT iMaxUdpDg; // maximum udp datagram size
  390. // added in DX6
  391. FDS readfds; // dynamic read fdset
  392. DWORD dwFlags; // DPSP_OUTBOUNDONLY, etc.
  393. DWORD dwSessionFlags; // session flags passed by app
  394. WORD wApplicationPort; // port used for creating system player sockets
  395. #ifdef BIGMESSAGEDEFENSE
  396. DWORD dwMaxMessageSize; // the max message size we should receive
  397. #endif
  398. HANDLE hTCPEnumAsyncThread; // fix async enum.
  399. LPVOID lpEnumMessage;
  400. DWORD dwEnumMessageSize;
  401. SOCKADDR saEnum;
  402. DWORD dwEnumAddrSize;
  403. SOCKET sEnum;
  404. BOOL bOutBoundOnly;
  405. HANDLE hSelectEvent;
  406. #ifdef SENDEX
  407. CRITICAL_SECTION csSendEx; // locks sendex data.
  408. LPFPOOL pSendInfoPool; // pool for allocating SENDINFO+SPHeaders for scatter gather sends
  409. DWORD dwBytesPending; // count of total bytes in pending messages.
  410. DWORD dwMessagesPending; // count of total bytes pending.
  411. BILINK PendingSendQ;
  412. BILINK ReadyToSendQ;
  413. HANDLE hSendWait; // alert thread wait here.
  414. HANDLE BogusHandle; // don't be fooled by waitfor multiple probs in Win9x, put -1 here.
  415. BOOL bSendThreadRunning;
  416. BOOL bStopSendThread;
  417. #endif
  418. #if USE_RSIP
  419. VOL SOCKET sRsip;
  420. SOCKADDR_IN saddrGateway;
  421. CRITICAL_SECTION csRsip;
  422. DWORD msgid;
  423. DWORD clientid;
  424. // cache the public addresses of these sockets so we don't
  425. // need to keep querying the name server every time.
  426. SOCKADDR saddrpubSystemDGramSocket;
  427. SOCKADDR saddrpubSystemStreamSocket;
  428. DWORD dwBindDGEnumListener;
  429. PRSIP_LEASE_RECORD pRsipLeaseRecords; // list of leases.
  430. PADDR_ENTRY pAddrEntry; // cache of mappings.
  431. DWORD tuRetry; //microseconds starting retry time.
  432. #endif
  433. #if USE_NATHELP
  434. HMODULE hNatHelp; // module handle for dpnhxxx.dll
  435. IDirectPlayNATHelp *pINatHelp; // interface pointer for IDirectPlayNATHelp object
  436. DPNHCAPS NatHelpCaps;
  437. // we only ever map 2 ports, 1 for UDP, 1 for TCP.
  438. DPNHHANDLE hNatHelpUDP;
  439. DPNHHANDLE hNatHelpTCP;
  440. SOCKADDR saddrpubSystemDGramSocket;
  441. SOCKADDR saddrpubSystemStreamSocket;
  442. SOCKADDR INADDRANY;
  443. #endif
  444. SHORT SystemStreamPort; // will always be in 2300-2400 range when valid.
  445. //SHORT SystemStreamPortOut; // When running on Win9x < Millenium, need to use separate outbound port.
  446. BOOL bSeparateIO; // When set workaround Winsock bug in Win9x < Millenium
  447. BOOL bFastSock; // if we are using FastSocket support.
  448. CRITICAL_SECTION csFast; // guards fast socket structures
  449. BILINK InboundPendingList; // connected from remote, but haven't created local player yet.
  450. VOL PPLAYERCONN PlayerHash[PLAYER_HASH_SIZE];
  451. VOL PPLAYERCONN SocketHash[SOCKET_HASH_SIZE];
  452. HANDLE hAccept;
  453. HANDLE EventHandles[NUM_EVENT_HANDLES];
  454. HANDLE BackStop; // Invalid handle to avoid Win95 bug in Wait for Multiple Objects
  455. EVENTLIST EventList[NUM_EVENT_HANDLES];
  456. UINT iEventAlloc; // runs around through EventList Index to try next allocation
  457. INT nEventSlotsAvail;
  458. } GLOBALDATA,*LPGLOBALDATA;
  459. /*
  460. * SP Flags (from registry)
  461. */
  462. #define DPSP_OUTBOUNDONLY 0x00000001
  463. /*
  464. * DPLAYSVR - DPWSOCKX communication related information
  465. */
  466. // MSG_HDR indicates a dpwsock system message
  467. #define MSG_HDR 0x736F636B
  468. #define SP_MSG_VERSION 1 // DX6
  469. #define IS_VALID_DPWS_MESSAGE(pMsg) (MSG_HDR == (*((DWORD *)(pMsg))) )
  470. #define COMMAND_MASK 0X0000FFFF
  471. #define GET_MESSAGE_VERSION(pMsg) ( ((pMsg)->dwCmdToken & ~COMMAND_MASK) >> 16 )
  472. #define GET_MESSAGE_COMMAND(pMsg) ( (pMsg)->dwCmdToken & COMMAND_MASK)
  473. #define SET_MESSAGE_HDR(pMsg) (*((DWORD *)(pMsg)) = MSG_HDR )
  474. #define SET_MESSAGE_COMMAND(pMsg,dwCmd) ((pMsg)->dwCmdToken = ((dwCmd & COMMAND_MASK) \
  475. | (SP_MSG_VERSION<<16)) )
  476. typedef struct {
  477. DWORD dwHeader;
  478. DWORD dwCmdToken;
  479. } MSG_GENERIC, *LPMSG_GENERIC;
  480. // DPLAYSVR
  481. // macros for manipulating the sockaddr in the player data
  482. #ifdef DEBUG
  483. extern int gCSCount;
  484. #endif
  485. extern CRITICAL_SECTION gcsDPSPCritSection; // defined in dllmain.c
  486. extern CRITICAL_SECTION csMem;
  487. #define INIT_DPSP_CSECT() InitializeCriticalSection(&gcsDPSPCritSection);InitializeCriticalSection(&csMem);
  488. #define FINI_DPSP_CSECT() DeleteCriticalSection(&gcsDPSPCritSection);DeleteCriticalSection(&csMem);
  489. #ifdef DEBUG
  490. #define ENTER_DPSP() EnterCriticalSection(&gcsDPSPCritSection),gCSCount++;
  491. #define LEAVE_DPSP() gCSCount--,LeaveCriticalSection(&gcsDPSPCritSection);
  492. #else
  493. #define ENTER_DPSP() EnterCriticalSection(&gcsDPSPCritSection);
  494. #define LEAVE_DPSP() LeaveCriticalSection(&gcsDPSPCritSection);
  495. #endif // DEBUG
  496. // get a pointer to the players socket address - used by macros below
  497. #define DGRAM_PSOCKADDR(ppd) ((SOCKADDR *)&(((LPSPPLAYERDATA)ppd)->saddrDatagram))
  498. #define STREAM_PSOCKADDR(ppd) ((SOCKADDR *)&(((LPSPPLAYERDATA)ppd)->saddrStream))
  499. // get the udp ip addr from a player
  500. #define IP_DGRAM_ADDR(ppd) (((SOCKADDR_IN *)DGRAM_PSOCKADDR(ppd))->sin_addr.s_addr)
  501. #define IP_DGRAM_PORT(ppd) (((SOCKADDR_IN *)DGRAM_PSOCKADDR(ppd))->sin_port)
  502. // get the stream ip addr from a player
  503. #define IP_STREAM_ADDR(ppd) (((SOCKADDR_IN *)STREAM_PSOCKADDR(ppd))->sin_addr.s_addr)
  504. #define IP_STREAM_PORT(ppd) (((SOCKADDR_IN *)STREAM_PSOCKADDR(ppd))->sin_port)
  505. // used to get the name of the computer we're running on in spinit
  506. #define HOST_NAME_LENGTH 50
  507. // if it's not ipx, it's ip
  508. // {685BC400-9D2C-11cf-A9CD-00AA006886E3}
  509. DEFINE_GUID(GUID_IPX,
  510. 0x685bc400, 0x9d2c, 0x11cf, 0xa9, 0xcd, 0x0, 0xaa, 0x0, 0x68, 0x86, 0xe3);
  511. // 36E95EE0-8577-11cf-960C-0080C7534E82
  512. DEFINE_GUID(GUID_TCP,
  513. 0x36E95EE0, 0x8577, 0x11cf, 0x96, 0xc, 0x0, 0x80, 0xc7, 0x53, 0x4e, 0x82);
  514. // {3A826E00-31DF-11d0-9CF9-00A0C90A43CB}
  515. DEFINE_GUID(GUID_LOCAL_TCP,
  516. 0x3a826e00, 0x31df, 0x11d0, 0x9c, 0xf9, 0x0, 0xa0, 0xc9, 0xa, 0x43, 0xcb);
  517. // globals
  518. // ghinstance is used when putting up the dialog box to prompt for ip addr
  519. extern HANDLE ghInstance; // set in dllmain. instance handle for dpwsock.dll
  520. #ifdef DEBUG
  521. extern void DebugPrintAddr(UINT level,LPSTR pStr,SOCKADDR * psockaddr);
  522. #define DEBUGPRINTADDR(n,pstr,psockaddr) DebugPrintAddr(n,pstr,psockaddr);
  523. extern void DebugPrintSocket(UINT level,LPSTR pStr,SOCKET * pSock);
  524. #define DEBUGPRINTSOCK(n,pstr,psock) DebugPrintSocket(n,pstr,psock);
  525. #else // debug
  526. #define DEBUGPRINTADDR(n,pstr,psockaddr)
  527. #define DEBUGPRINTSOCK(n,pstr,psock)
  528. #endif // debug
  529. // global vars
  530. extern BOOL gbVoiceOpen; // set to TRUE if we have nm call open
  531. // from dpsp.c
  532. extern HRESULT WaitForThread(HANDLE hThread);
  533. extern HRESULT SetupControlSocket();
  534. extern HRESULT WINAPI SP_Close(LPDPSP_CLOSEDATA pcd);
  535. extern HRESULT InternalReliableSend(LPGLOBALDATA pgd, DPID idPlayerTo, SOCKADDR *
  536. lpSockAddr, LPBYTE lpMessage, DWORD dwMessageSize);
  537. extern HRESULT DoTCPEnumSessions(LPGLOBALDATA pgd, SOCKADDR *lpSockAddr, DWORD dwAddrSize,
  538. LPDPSP_ENUMSESSIONSDATA ped, BOOL bHostWillReuseConnection);
  539. extern HRESULT SendControlMessage(LPGLOBALDATA pgd);
  540. extern HRESULT SendReuseConnectionMessage(SOCKET sSocket);
  541. extern HRESULT AddSocketToBag(LPGLOBALDATA pgd, SOCKET socket, DPID dpid, SOCKADDR *psockaddr, DWORD dwFlags);
  542. extern BOOL FindSocketInReceiveList(LPGLOBALDATA pgd, SOCKADDR *pSockAddr, SOCKET * psSocket);
  543. extern void RemoveSocketFromReceiveList(LPGLOBALDATA pgd, SOCKET socket);
  544. extern void RemoveSocketFromBag(LPGLOBALDATA pgd, SOCKET socket);
  545. extern BOOL FindSocketInBag(LPGLOBALDATA pgd, SOCKADDR *pSockAddr, SOCKET * psSocket, LPDPID lpdpidPlayer);
  546. extern HRESULT GetSocketFromBag(LPGLOBALDATA pgd,SOCKET * psSocket, DWORD dwID, LPSOCKADDR psockaddr);
  547. extern HRESULT CreateAndConnectSocket(LPGLOBALDATA pgd,SOCKET * psSocket,DWORD dwType,LPSOCKADDR psockaddr, BOOL bOutBoundOnly);
  548. extern void RemovePlayerFromSocketBag(LPGLOBALDATA pgd,DWORD dwID);
  549. extern void SetMessageHeader(LPDWORD pdwMsg,DWORD dwSize, DWORD dwToken);
  550. extern void KillTCPEnumAsyncThread(LPGLOBALDATA pgd);
  551. // Support for SendEx in dpsp.c
  552. extern HRESULT UnreliableSendEx(LPDPSP_SENDEXDATA psd, LPSENDINFO lpSendInfo);
  553. extern HRESULT ReliableSendEx(LPDPSP_SENDEXDATA psd, LPSENDINFO pSendInfo);
  554. extern VOID RemovePendingAsyncSends(LPGLOBALDATA pgd, DPID dwPlayerTo);
  555. extern BOOL bAsyncSendsPending(LPGLOBALDATA pgd, DPID dwPlayerTo);
  556. extern HRESULT GetSPPlayerData(LPGLOBALDATA pgd, IDirectPlaySP * lpISP, DPID idPlayer, LPSPPLAYERDATA *ppPlayerData, DWORD *lpdwSize);
  557. // from winsock.c
  558. extern HRESULT FAR PASCAL CreateSocket(LPGLOBALDATA pgd,SOCKET * psock,INT type,
  559. WORD port,ULONG address,SOCKERR * perr, BOOL bInRange);
  560. extern HRESULT SPConnect(SOCKET* psSocket, LPSOCKADDR psockaddr,UINT addrlen, BOOL bOutBoundOnly);
  561. extern HRESULT CreateAndInitStreamSocket(LPGLOBALDATA pgd);
  562. extern HRESULT SetPlayerAddress(LPGLOBALDATA pgd,LPSPPLAYERDATA ppd,SOCKET sSocket,BOOL fStream);
  563. extern HRESULT CreatePlayerDgramSocket(LPGLOBALDATA pgd,LPSPPLAYERDATA ppd,DWORD dwFlags);
  564. extern HRESULT CreatePlayerStreamSocket(LPGLOBALDATA pgd,LPSPPLAYERDATA ppd,DWORD dwFlags);
  565. extern HRESULT SetDescriptionAddress(LPSPPLAYERDATA ppd,LPDPSESSIONDESC2 lpsdDesc);
  566. extern HRESULT SetReturnAddress(LPVOID pmsg,SOCKET sSocket, LPSOCKADDR psaddr);
  567. extern HRESULT GetReturnAddress(LPVOID pmsg,LPSOCKADDR psockaddr);
  568. extern HRESULT GetServerAddress(LPGLOBALDATA pgd,LPSOCKADDR psockaddr) ;
  569. extern void IPX_SetNodenum(LPVOID pmsg,SOCKADDR_IPX * psockaddr);
  570. extern void IP_GetAddr(SOCKADDR_IN * paddrDest,SOCKADDR_IN * paddrSrc) ;
  571. extern void IP_SetAddr(LPVOID pBuffer,SOCKADDR_IN * psockaddr);
  572. extern void IPX_GetNodenum(SOCKADDR_IPX * paddrDest,SOCKADDR_IPX * paddrSrc) ;
  573. extern HRESULT KillSocket(SOCKET sSocket,BOOL fStream,BOOL fHard);
  574. extern HRESULT KillPlayerSockets();
  575. extern HRESULT GetAddress(ULONG * puAddress,char *pBuffer,int cch);
  576. extern HRESULT KillThread(HANDLE hThread);
  577. // from wsock2.c
  578. extern DWORD WINAPI AsyncSendThreadProc(LPVOID pvCast);
  579. extern HRESULT InitWinsock2();
  580. extern HRESULT GetMaxUdpBufferSize(SOCKET socket, unsigned int * lpiSize);
  581. extern HRESULT InternalReliableSendEx(LPGLOBALDATA pgd, LPDPSP_SENDEXDATA psd,
  582. LPSENDINFO pSendInfo, SOCKADDR *lpSockAddr);
  583. extern DWORD WINAPI SPSendThread(LPVOID lpv);
  584. extern void QueueForSend(LPGLOBALDATA pgd,LPSENDINFO pSendInfo);
  585. extern BOOL SetExclusivePortAccess(SOCKET sNew);
  586. extern BOOL SetSharedPortAccess(SOCKET sNew);
  587. // from handler.c
  588. extern HRESULT HandleServerMessage(LPGLOBALDATA pgd, SOCKET sSocket, LPBYTE pBuffer, DWORD dwSize);
  589. #ifdef FULLDUPLEX_SUPPORT
  590. // from registry.c
  591. extern HRESULT GetFlagsFromRegistry(LPGUID lpguidSP, LPDWORD lpdwFlags);
  592. #endif // FULLDUPLEX_SUPPORT
  593. #if USE_RSIP
  594. // from registry.c
  595. extern HRESULT GetGatewayFromRegistry(LPGUID lpguidSP, LPBYTE lpszGateway, DWORD cbszGateway);
  596. #elif USE_NATHELP
  597. // from registry.c
  598. extern HRESULT GetNATHelpDLLFromRegistry(LPGUID lpguidSP, LPBYTE lpszNATHelpDLL, DWORD cbszNATHelpDLL);
  599. #endif
  600. extern BOOL FastSockInit(LPGLOBALDATA pgd);
  601. extern VOID FastSockFini(LPGLOBALDATA pgd);
  602. extern PPLAYERCONN CreatePlayerConn(LPGLOBALDATA pgd, DPID dpid, SOCKADDR *psockaddr);
  603. extern PPLAYERCONN FindPlayerById(LPGLOBALDATA pgd, DPID dpid);
  604. extern PPLAYERCONN FindPlayerBySocket(LPGLOBALDATA pgd, SOCKADDR *psockaddr);
  605. extern HRESULT AddConnToPlayerHash(LPGLOBALDATA pgd, PPLAYERCONN pConn);
  606. extern HRESULT AddConnToSocketHash(LPGLOBALDATA pgd, PPLAYERCONN pConn);
  607. extern PPLAYERCONN RemoveConnFromSocketHash(LPGLOBALDATA pgd, PPLAYERCONN pConn);
  608. extern PPLAYERCONN RemoveConnFromPlayerHash(LPGLOBALDATA pgd, PPLAYERCONN pConn);
  609. extern VOID QueueSendOnConn(LPGLOBALDATA pgd, PPLAYERCONN pConn, PSENDINFO pSendInfo);
  610. extern PPLAYERCONN GetPlayerConn(LPGLOBALDATA pgd, DPID dpid, SOCKADDR *psockaddr);
  611. extern INT DecRefConn(LPGLOBALDATA pgd, PPLAYERCONN pConn);
  612. extern INT DecRefConnExist(LPGLOBALDATA pgd, PPLAYERCONN pConn);
  613. extern HRESULT FastInternalReliableSend(LPGLOBALDATA pgd, LPDPSP_SENDDATA psd, SOCKADDR *lpSockAddr);
  614. extern HRESULT FastInternalReliableSendEx(LPGLOBALDATA pgd, LPDPSP_SENDEXDATA psd, LPSENDINFO pSendInfo, SOCKADDR *lpSockAddr);
  615. extern PPLAYERCONN CleanPlayerConn(LPGLOBALDATA pgd, PPLAYERCONN pConn, BOOL bHard);
  616. extern HRESULT FastReply(LPGLOBALDATA pgd, LPDPSP_REPLYDATA prd, DPID dwPlayerID);
  617. extern PPLAYERCONN FindConnInPendingList(LPGLOBALDATA pgd, SOCKADDR *psaddr);
  618. extern DWORD WINAPI FastStreamReceiveThreadProc(LPVOID pvCast);
  619. extern VOID FastSockCleanConnList(LPGLOBALDATA pgd);
  620. extern INT DecRefConn(LPGLOBALDATA pgd, PPLAYERCONN pConn);
  621. extern VOID QueueNextSend(LPGLOBALDATA pgd,PPLAYERCONN pConn);
  622. // Wrap Malloc
  623. void _inline __cdecl SP_MemFree( LPVOID lptr )
  624. {
  625. EnterCriticalSection(&csMem);
  626. MemFree(lptr);
  627. LeaveCriticalSection(&csMem);
  628. }
  629. LPVOID _inline __cdecl SP_MemAlloc(UINT size)
  630. {
  631. LPVOID lpv;
  632. EnterCriticalSection(&csMem);
  633. lpv = MemAlloc(size);
  634. LeaveCriticalSection(&csMem);
  635. return lpv;
  636. }
  637. LPVOID _inline __cdecl SP_MemReAlloc(LPVOID lptr, UINT size)
  638. {
  639. LPVOID lpv;
  640. EnterCriticalSection(&csMem);
  641. lpv = MemReAlloc(lptr, size);
  642. LeaveCriticalSection(&csMem);
  643. return lpv;
  644. }
  645. #define AddRefConn(_p) InterlockedIncrement(&((_p)->dwRefCount))
  646. #endif