//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//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., 675 Mass Ave, Cambridge, MA 02139, USA.
#pragma once

#define CS_FATALERROR	-5
#define CS_DISCONNECTED	-4
#define CS_SERVERDEAD	-3
#define	CS_ERROR		-2
#define CS_SERVERFULL	-1
#define	CS_NOTCONNECTED	0
#define	CS_CONNECTING	1
#define	CS_CONNECTED	2
#define	CS_WAITFORLOGIN	3
#define CS_WAITFORPROXYLISTENING 4 // deadlake PROXYSUPPORT

#define CS_RETRYCONNECTTIME  30 // seconds

class CServerList;
class CUDPSocket;
class CServerSocket;
class CServer;
class Packet;

// NEO: NEW - [NewCoded] -- Xanatos -->
class CServerConnect
{
public:
	CServerConnect();
	~CServerConnect();
	void	ConnectionFailed(CServerSocket* sender);
	void	ConnectionEstablished(CServerSocket* sender);
	
	void	ConnectToAnyServer() {ConnectToAnyServer(0,true,true);}
	void	ConnectToAnyServer(UINT startAt, bool prioSort = false, bool isAuto = true, bool bNoCrypt = false);
	void	ConnectToServer(CServer* toconnect, bool multiconnect = false, bool bNoCrypt = false);
	void	StopConnectionTry();

	void	Process();
	void	CheckForTimeout();
	void	DestroySocket(CServerSocket* pSck);	// safe socket closure and destruction
	bool	SendPacket(Packet* packet,bool delpacket = true, CServerSocket* to = 0);
	// NEO: MOD - [BindToAdapter] -- Xanatos -->
	bool	CreateUDP();
	bool	Rebind();
	// NEO: MOD END <-- Xanatos --
	bool	IsUDPSocketAvailable() const { return udpsocket != NULL; }
	bool	SendUDPPacket(Packet* packet,CServer* host, bool delpacket = false, uint16 nSpecialPort = 0, BYTE* pRawPacket = NULL, uint32 nLen = 0);
	void	KeepConnectionAlive();
	bool	Disconnect();
	bool	IsConnecting(bool bEx = false)	{if(bEx) return !connectionattemps.IsEmpty(); return connecting;}
	bool	IsConnected()	{return tcpsocket != NULL;}
	uint32	GetClientID()	{return clientid;}

	CServer*	GetCurrentServer();
	bool		IsConnectedServer(const CServer* server);
	uint32	clientid;

	bool	IsLowID();
	void	SetClientID(uint32 newid);
	CServerSocket*	IsLocalServer(uint32 dwIP, uint16 nPort, bool bConnecting = false);
	void	TryAnotherConnectionRequest();
	void	InitLocalIP();
	uint32	GetLocalIP()		{return m_nLocalIP;}
	// NEO: RLD - [ReconnectOnLowID] -- Xanatos -->
	void	AddLowIdRetried()	{m_uLowIDRetrys++;}
	int		GetLowIdRetris()	{return m_uLowIDRetrys;}
	void	ResetLowIdRetried()	{m_uLowIDRetrys = 0;}
	// NEO: RLD END <-- Xanatos --

	bool	AwaitingTestFromIP(uint32 dwIP) const;
	bool	IsConnectedObfuscated() const;

private:
	bool	connecting;
	bool	autoretry;
	bool	m_bTryObfuscated;
	UINT	m_uStartAutoConnectPos;
	CServerSocket*	tcpsocket;
	CUDPSocket*		udpsocket;
	uint32	m_uOutOfServers;
	uint32	m_nLocalIP;
	int		m_uLowIDRetrys; // NEO: RLD - [ReconnectOnLowID] <-- Xanatos --

	CList<CServerSocket*,CServerSocket*> connectionattemps;
};
// NEO: NEW END <-- Xanatos --
