/*
Copyright (C) 1996-2001 Id Software, Inc.
Copyright (C) 2002-2009 John Fitzgibbons and others
Copyright (C) 2009-2010 Ozkan Sezer
Copyright (C) 2009-2014 Baker and others

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
//	net_defs.h
//	functions and data private to the network layer
//
//	net_sys.h and its dependencies must be included
//	before net_defs.h.


#ifndef __NET_DEFS_H__
#define __NET_DEFS_H__

#include "quakedef.h" // Baker ... Evile

struct qsockaddr
{
#if defined(HAVE_SA_LEN)
	unsigned char qsa_len;
	unsigned char qsa_family;
#else
	short qsa_family;
#endif	/* BSD, sockaddr */
	unsigned char qsa_data[NET_NAMELEN_64]; // NETQ 3.1 NET_NAMELEN instead?
};

#define NET_HEADERSIZE		(2 * sizeof(unsigned int))
//#define NET_DATAGRAMSIZE	(MAX_DATAGRAM + NET_HEADERSIZE)
#define	NET_MARK_V_DATAGRAMSIZE	(MAX_MARK_V_DATAGRAM + NET_HEADERSIZE)
#define NET_WINQUAKE_DATAGRAMSIZE	(MAX_WINQUAKE_DATAGRAM + NET_HEADERSIZE)


// NetHeader flags
#define NETFLAG_LENGTH_MASK	0x0000ffff
#define NETFLAG_DATA		0x00010000
#define NETFLAG_ACK			0x00020000
#define NETFLAG_NAK			0x00040000
#define NETFLAG_EOM			0x00080000
#define NETFLAG_UNRELIABLE	0x00100000
#define NETFLAG_CTL			0x80000000


#define NET_PROTOCOL_VERSION	3

/**

 This is the network info/connection protocol.  It is used to find Quake
 servers, get info about them, and connect to them.  Once connected, the
 Quake game protocol (documented elsewhere) is used.


 General notes:
	game_name is currently always "QUAKE", but is there so this same protocol
		can be used for future games as well; can you say Quake2?

 CCREQ_CONNECT
		string	game_name				"QUAKE"
		byte	net_protocol_version	NET_PROTOCOL_VERSION

 CCREQ_SERVER_INFO
		string	game_name				"QUAKE"
		byte	net_protocol_version	NET_PROTOCOL_VERSION

 CCREQ_PLAYER_INFO
		byte	player_number

 CCREQ_RULE_INFO
		string	rule

 CCREP_ACCEPT
		long	port

 CCREP_REJECT
		string	reason

 CCREP_SERVER_INFO
		string	server_address
		string	host_name
		string	level_name
		byte	current_players
		byte	max_players
		byte	protocol_version	NET_PROTOCOL_VERSION

 CCREP_PLAYER_INFO
		byte	player_number
		string	name
		long	colors
		long	frags
		long	connect_time
		string	address

 CCREP_RULE_INFO
		string	rule
		string	value

	note:
		There are two address forms used above.  The short form is just a
		port number.  The address that goes along with the port is defined as
		"whatever address you receive this reponse from".  This lets us use
		the host OS to solve the problem of multiple host addresses (possibly
		with no routing between them); the host will use the right address
		when we reply to the inbound connection request.  The long from is
		a full address and port in a string.  It is used for returning the
		address of a server that is not running locally.

**/

#define CCREQ_CONNECT		0x01
#define CCREQ_SERVER_INFO	0x02
#define CCREQ_PLAYER_INFO	0x03
#define CCREQ_RULE_INFO		0x04
#define CCREQ_RCON			0x05

#define CCREP_ACCEPT		0x81
#define CCREP_REJECT		0x82
#define CCREP_SERVER_INFO	0x83
#define CCREP_PLAYER_INFO	0x84
#define CCREP_RULE_INFO		0x85

#define CCREP_RCON			0x86 // Rcon

// JPG - support for mods
#define MOD_PROQUAKE_1	0x01
//#define MOD_NONE			0x00	Retired
//#define MOD_QSMACK		0x02	Legacy.

typedef struct qsocket_s
{
	struct qsocket_s * next;
	double			connecttime;
	double			lastMessageTime;
	double			lastSendTime;

	cbool			isvirtual;	 // qsocket is emulated by the network layer (closing will not close any system sockets).
	cbool			disconnected;
	cbool			canSend;
	cbool			sendNext;

	int				driver;
	int				landriver;
	sys_socket_t	socket;
	void			*driverdata;

	unsigned int	ackSequence;
	unsigned int	sendSequence;
	unsigned int	unreliableSendSequence;
	int				sendMessageLength;
	byte			sendMessage [NET_MARK_V_MAXMESSAGE];

	unsigned int	receiveSequence;
	unsigned int	unreliableReceiveSequence;
	int				receiveMessageLength;
	byte			receiveMessage [NET_MARK_V_MAXMESSAGE];

	struct 			qsockaddr addr;
	char			trueaddress[NET_NAMELEN_64];	//lazy address string
	char			maskedaddress[NET_NAMELEN_64];	//addresses for this player that may be displayed publically


	// JPG - new stuff here (must be after address for crmod compatibility)
	byte			proquake_connection;
	byte			proquake_version;	// = floor(version * 10) (must fit in one byte)
	byte			proquake_flags;
} qsocket_t;

extern qsocket_t	*net_activeSockets;
extern qsocket_t	*net_freeSockets;
extern int			net_numsockets;

typedef struct
{
	const char	*name;
	cbool	initialized;
	sys_socket_t	controlSock;
	sys_socket_t	(*Init) (void);
	void			(*Shutdown) (void);
	sys_socket_t	(*Listen) (cbool state);
	sys_socket_t	(*Open_Socket) (int port);
	int				(*Close_Socket) (sys_socket_t socketid);
	int 			(*Connect) (sys_socket_t socketid, struct qsockaddr *addr);
	sys_socket_t 	(*CheckNewConnections) (void);
	int 			(*Read) (sys_socket_t socketid, byte *buf, int len, struct qsockaddr *addr);
	int 			(*Write) (sys_socket_t socketid, byte *buf, int len, struct qsockaddr *addr);
	int 			(*Broadcast) (sys_socket_t socketid, byte *buf, int len);
	const char *	(*AddrToString) (struct qsockaddr *addr, cbool masked);
	int 			(*StringToAddr) (const char *string, struct qsockaddr *addr);
	int 			(*GetSocketAddr) (sys_socket_t socketid, struct qsockaddr *addr);
	int 			(*GetNameFromAddr) (struct qsockaddr *addr, char *name, size_t len); // NETQ - TODO Baker: Fix by adding maxsize?
	int 			(*GetAddrFromName) (const char *name, struct qsockaddr *addr);
	int				(*AddrCompare) (struct qsockaddr *addr1, struct qsockaddr *addr2);
	int				(*GetSocketPort) (struct qsockaddr *addr);
	int				(*SetSocketPort) (struct qsockaddr *addr, int port);

	sys_socket_t	listeningSock;
} net_landriver_t;

#define	MAX_NET_DRIVERS		8
extern net_landriver_t	net_landrivers[];
extern const int 		net_numlandrivers;

typedef struct
{
	const char	*	name;
	cbool			initialized;
	int				(*Init) (void);
	void			(*Listen) (cbool state);
	cbool			(*SearchForHosts) (cbool xmit); // netq 3.5  /// tobe cbool
	qsocket_t	*	(*Connect) (const char *host);
	qsocket_t 	*	(*CheckNewConnections) (void);
	qsocket_t	*	(*QGetAnyMessage) (void);
	int				(*QGetMessage) (qsocket_t *sock);
	int				(*QSendMessage) (qsocket_t *sock, sizebuf_t *data);
	int				(*SendUnreliableMessage) (qsocket_t *sock, sizebuf_t *data);
	cbool			(*CanSendMessage) (qsocket_t *sock);
	cbool			(*CanSendUnreliableMessage) (qsocket_t *sock);
	void			(*Close) (qsocket_t *sock);
	void			(*Shutdown) (void);
} net_driver_t;

extern net_driver_t	net_drivers[];
extern const int net_numdrivers;

/* Loop driver must always be registered the first */
#define IS_LOOP_DRIVER(p)	((p) == 0)

extern int net_driverlevel;

extern int		messagesSent;
extern int		messagesReceived;
extern int		unreliableMessagesSent;
extern int		unreliableMessagesReceived;

qsocket_t *NET_NewQSocket (void);
void NET_FreeQSocket(qsocket_t *);
double SetNetTime(void);


#define HOSTCACHESIZE	128	 // netq 3.7 //fixme: make dynamic. originally 8

typedef struct
{
	char	name[16];
	char	map[16];
	char	cname[NET_NAMELEN_64];  // netq 3.8 (already had been done!  Yay!)
	int		users;
	int		maxusers;
	int		driver;
	int		ldriver;
	struct qsockaddr addr;
} hostcache_t;

extern int hostCacheCount;
extern hostcache_t hostcache[HOSTCACHESIZE];


typedef struct _PollProcedure
{
	struct _PollProcedure	*next;
	double					nextTime;
	void					(*procedure)(void *);
	void					*arg;
} PollProcedure;

void SchedulePollProcedure(PollProcedure *pp, double timeOffset);

#endif // ! __NET_DEFS_H__

