mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
256 lines
11 KiB
C
256 lines
11 KiB
C
![]() |
/*
|
||
|
GameSpy GT2 SDK
|
||
|
Dan "Mr. Pants" Schoenblum
|
||
|
dan@gamespy.com
|
||
|
|
||
|
Copyright 2002 GameSpy Industries, Inc
|
||
|
|
||
|
devsupport@gamespy.com
|
||
|
*/
|
||
|
|
||
|
#ifndef _GT2_MAIN_H_
|
||
|
#define _GT2_MAIN_H_
|
||
|
|
||
|
#include "gt2.h"
|
||
|
#include "../darray.h"
|
||
|
#include "../hashtable.h"
|
||
|
#include "gt2Auth.h"
|
||
|
|
||
|
/*************************
|
||
|
** CONFIGURABLE DEFINES **
|
||
|
*************************/
|
||
|
|
||
|
// these defines are internal to GT2 and are NOT guaranteed to persist from version to version.
|
||
|
|
||
|
|
||
|
// If set, this will convert all big endian vars to little endian before sending accross the net
|
||
|
// And on big endian machines, convert little endian to big endian on recv
|
||
|
//#define _GT2_ENDIAN_CONVERT_ENABLE // add this to your compiler pre-processor options
|
||
|
|
||
|
#if defined GSI_BIG_ENDIAN && defined _GT2_ENDIAN_CONVERT_ENABLE
|
||
|
#define _GT2_ENDIAN_CONVERT
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
// any unreliable application message that starts with this magic string will have extra overhead.
|
||
|
// the string can be changed to something that your application will not use, or not use frequently.
|
||
|
// the only impact of this change will be to make your application incomatible with other application's
|
||
|
// using either the original or another different magic string.
|
||
|
// the string can consist of any number of characters, as long as there's at least one character, and the
|
||
|
// length define matches the string's length.
|
||
|
#define GTI2_MAGIC_STRING "\xFE\xFE"
|
||
|
#define GTI2_MAGIC_STRING_LEN 2
|
||
|
|
||
|
// the size of the buffer into which GT2 directly receives messages. this buffer is declared on the stack,
|
||
|
// and so can be fairly large on most systems without having any impact. however, on some systems with small
|
||
|
// stacks, this size can overflow the stack, in which case it should be lowered.
|
||
|
// note, this buffer size only needs to be slighty larger than the largest message that will be sent ("slighty
|
||
|
// larger" due to overhead with reliable messages, and unreliable messages starting with the magic string).
|
||
|
#if defined(_PS2) && defined(INSOCK)
|
||
|
#define GTI2_STACK_RECV_BUFFER_SIZE NETBUFSIZE // Max for Insock. Otherwise SOCKET_ERROR
|
||
|
#elif defined(_NITRO)
|
||
|
#define GTI2_STACK_RECV_BUFFER_SIZE 1500
|
||
|
#elif defined (_XBOX) // Xbox packets are 1304,
|
||
|
#define GTI2_STACK_RECV_BUFFER_SIZE 4096 // when using VDP sockets, 2 bytes are used for data length
|
||
|
#else
|
||
|
#define GTI2_STACK_RECV_BUFFER_SIZE 65535
|
||
|
#endif
|
||
|
|
||
|
// a server will disconnect a client that doesn't not successfully connect within this time (in milliseconds).
|
||
|
// if the connectAttemptCallback has been called, and GT2 is awaiting an accept/reject, the attempt will
|
||
|
// not be timed-out (although the client may abort the attempt at any time).
|
||
|
#define GTI2_SERVER_TIMEOUT (1 * 60 * 1000)
|
||
|
// the time (in milliseconds) GT2 waits between resending a message whose delivery has not yet been confirmed.
|
||
|
#define GTI2_RESEND_TIME 1000
|
||
|
// the time (in milliseconds) GT2 waits after receiving a message it must acknowledge before it actually sends
|
||
|
// the ack. this allows it to combine acks, or include acks as part of other reliable messages it sends.
|
||
|
// if an ack is pending, a new incoming message does not reset this timer.
|
||
|
#define GTI2_PENDING_ACK_TIME 100
|
||
|
// if GT2 does not send a message for this amount of time (in milliseconds), it sends a keep-alive message.
|
||
|
#define GTI2_KEEP_ALIVE_TIME (30 * 1000)
|
||
|
// if this is defined, it sets the percentage of sent datagrams to drop. this is good for simulating what will
|
||
|
// happen on a high packet loss connection.
|
||
|
//#define GTI2_DROP_SEND_RATE 30
|
||
|
typedef enum
|
||
|
{
|
||
|
GTI2UdpProtocol, // UDP socket type for standard sockets
|
||
|
GTI2VdpProtocol = 2, // VDP socket type only used for Xbox VDP sockets
|
||
|
GTI2AdHocProtocol = 3 // socket type only used for PSP Adhoc sockets
|
||
|
} GTI2ProtocolType;
|
||
|
|
||
|
// The Maximum offset of eiter UDP or VDP
|
||
|
// measured in bytes
|
||
|
// used as a buffer offset
|
||
|
#define MAX_PROTOCOL_OFFSET 2
|
||
|
|
||
|
/**********
|
||
|
** TYPES **
|
||
|
**********/
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
// client-only states
|
||
|
GTI2AwaitingServerChallenge, // sent challenge, waiting for server's challenge
|
||
|
GTI2AwaitingAcceptance, // sent response, waiting for accept/reject from server
|
||
|
|
||
|
// server-only states
|
||
|
GTI2AwaitingClientChallenge, // receiving challenge from a new client
|
||
|
GTI2AwaitingClientResponse, // sent challenge, waiting for client's response
|
||
|
GTI2AwaitingAcceptReject, // got client's response, waiting for app to accept/reject
|
||
|
|
||
|
// post-negotiation states
|
||
|
GTI2Connected, // connected
|
||
|
GTI2Closing, // sent a close message (GTI2Close or GTI2Reject), waiting for confirmation
|
||
|
GTI2Closed // connection has been closed, free it as soon as possible
|
||
|
} GTI2ConnectionState;
|
||
|
|
||
|
// message types
|
||
|
typedef enum
|
||
|
{
|
||
|
// reliable messages
|
||
|
// all start with <magic-string> <type> <serial-number> <expected-serial-number>
|
||
|
// type is 1 bytes, SN and ESN are 2 bytes each
|
||
|
GTI2MsgAppReliable, // reliable application message
|
||
|
GTI2MsgClientChallenge, // client's challenge to the server (initial connection request)
|
||
|
GTI2MsgServerChallenge, // server's response to the client's challenge, and his challenge to the client
|
||
|
GTI2MsgClientResponse, // client's response to the server's challenge
|
||
|
GTI2MsgAccept, // server accepting client's connection attempt
|
||
|
GTI2MsgReject, // server rejecting client's connection attempt
|
||
|
GTI2MsgClose, // message indicating the connection is closing
|
||
|
GTI2MsgKeepAlive, // keep-alive used to help detect dropped connections
|
||
|
|
||
|
GTI2NumReliableMessages,
|
||
|
|
||
|
// unreliable messages
|
||
|
GTI2MsgAck = 100, // acknowledge receipt of reliable message(s)
|
||
|
GTI2MsgNack, // alert sender to missing reliable message(s)
|
||
|
GTI2MsgPing, // used to determine latency
|
||
|
GTI2MsgPong, // a reply to a ping
|
||
|
GTI2MsgClosed // confirmation of connection closure (GTI2MsgClose or GTI2MsgReject) - also sent in response to bad messages from unknown addresses
|
||
|
|
||
|
// unreliable messages don't really have a message type, just the magic string repeated at the start
|
||
|
} GTI2MessageType;
|
||
|
|
||
|
/***************
|
||
|
** STRUCTURES **
|
||
|
***************/
|
||
|
|
||
|
typedef struct GTI2Buffer
|
||
|
{
|
||
|
GT2Byte * buffer; // The buffer's bytes.
|
||
|
int size; // Number of bytes in buffer.
|
||
|
int len; // Length of actual data in buffer.
|
||
|
} GTI2Buffer;
|
||
|
|
||
|
typedef struct GTI2IncomingBufferMessage
|
||
|
{
|
||
|
int start; // the start of the message
|
||
|
int len; // the length of the message
|
||
|
GTI2MessageType type; // the type
|
||
|
unsigned short serialNumber; // the serial number
|
||
|
} GTI2IncomingBufferMessage;
|
||
|
|
||
|
typedef struct GTI2OutgoingBufferMessage
|
||
|
{
|
||
|
int start; // the start of the message
|
||
|
int len; // the length of the message
|
||
|
unsigned short serialNumber; // the serial number
|
||
|
gsi_time lastSend; // last time this message was sent
|
||
|
} GTI2OutgoingBufferMessage;
|
||
|
|
||
|
typedef struct GTI2Socket
|
||
|
{
|
||
|
SOCKET socket; // the network socket used for all network communication
|
||
|
|
||
|
unsigned int ip; // the ip this socket is bound to
|
||
|
unsigned short port; // the port this socket is bound to
|
||
|
|
||
|
HashTable connections; // the connections that are using this socket
|
||
|
DArray closedConnections; // connections that are closed no longer get a spot in the hash table
|
||
|
|
||
|
GT2Bool close; // if true, a close was attempted inside a callback, and it should be closed as soon as possible
|
||
|
GT2Bool error; // if true, there was a socket error using this socket
|
||
|
|
||
|
int callbackLevel; // if >0, then we're inside a callback (or recursive callbacks)
|
||
|
gt2ConnectAttemptCallback connectAttemptCallback; // if set, callback used to handle incoming connection attempts
|
||
|
gt2SocketErrorCallback socketErrorCallback; // if set, call this in case of an error
|
||
|
gt2DumpCallback sendDumpCallback; // if set, gets called for every datagram sent
|
||
|
gt2DumpCallback receiveDumpCallback; // if set, gets called for every datagram and connection reset received
|
||
|
gt2UnrecognizedMessageCallback unrecognizedMessageCallback; // if set, gets called for all unrecognized messages
|
||
|
|
||
|
void * data; // user data
|
||
|
|
||
|
int outgoingBufferSize; // per-connection buffer sizes
|
||
|
int incomingBufferSize;
|
||
|
|
||
|
GTI2ProtocolType protocolType; // set to UDP or VDP protocol depending on the call to create socket
|
||
|
// also used as an offset for VDP sockets
|
||
|
int protocolOffset;
|
||
|
GT2Bool broadcastEnabled; // set to true if the socket has already been broadcast enabled
|
||
|
} GTI2Socket;
|
||
|
|
||
|
typedef struct GTI2Connection
|
||
|
{
|
||
|
// ip and port uniquely identify this connection on this socket
|
||
|
unsigned int ip; // the ip on the other side of this connection (network byte order)
|
||
|
unsigned short port; // the port on the other side of this connection (host byte order)
|
||
|
|
||
|
GTI2Socket * socket; // the parent socket
|
||
|
|
||
|
GTI2ConnectionState state; // connection state
|
||
|
|
||
|
GT2Bool initiated; // if true, the local side of the connection initiated the connection (client)
|
||
|
|
||
|
GT2Bool freeAtAcceptReject; // if true, don't free the connection until accept/reject is called
|
||
|
|
||
|
GT2Result connectionResult; // the result of the connect attempt
|
||
|
|
||
|
gsi_time startTime; // the time the connection was created
|
||
|
gsi_time timeout; // the timeout value passed into gt2Connect
|
||
|
|
||
|
int callbackLevel; // if >0, then we're inside a callback (or recursive callbacks)
|
||
|
GT2ConnectionCallbacks callbacks; // connection callbacks
|
||
|
|
||
|
char * initialMessage; // this is the initial message for the client
|
||
|
int initialMessageLen; // the initial message length
|
||
|
|
||
|
void * data; // user data
|
||
|
|
||
|
GTI2Buffer incomingBuffer; // buffer for incoming data
|
||
|
GTI2Buffer outgoingBuffer; // buffer for outgoing data
|
||
|
DArray incomingBufferMessages; // identifies incoming messages stored in the buffer
|
||
|
DArray outgoingBufferMessages; // identifies outgoing messages stored in the buffer
|
||
|
|
||
|
unsigned short serialNumber; // serial number of the next message to be sent out
|
||
|
unsigned short expectedSerialNumber; // the next serial number we're expecting from the remote side
|
||
|
|
||
|
char response[GTI2_RESPONSE_LEN]; // after the challenge is sent during negotiation, this is the response we're expecting
|
||
|
|
||
|
gsi_time lastSend; // the last time something was sent on this connection
|
||
|
gsi_time challengeTime; // the time the challenge was sent
|
||
|
|
||
|
GT2Bool pendingAck; // if true, there is an ack waiting to go out, either on its own or as part of a reliable message
|
||
|
|
||
|
gsi_time pendingAckTime; // the time at which the pending ack was first set
|
||
|
|
||
|
DArray sendFilters; // filters that apply to outgoing data
|
||
|
DArray receiveFilters; // filters that apply to incoming data
|
||
|
|
||
|
} GTI2Connection;
|
||
|
|
||
|
// store last 32 ip's in a ring buffer
|
||
|
#define MAC_TABLE_SIZE 32 // must be power of 2
|
||
|
typedef struct
|
||
|
{
|
||
|
gsi_u32 ip;
|
||
|
char mac[6];
|
||
|
} GTI2MacEntry;
|
||
|
|
||
|
#ifdef GSI_ADHOC
|
||
|
static int lastmactableentry = 0;
|
||
|
static GTI2MacEntry MacTable[MAC_TABLE_SIZE];
|
||
|
#endif // GSI_ADHOC
|
||
|
|
||
|
#endif
|