//
// Asura_DemonWare.cpp
//
// Created by Andrew Catlender - 27 March 2006 11:07:42
//
// Copyright (C) 2006 Rebellion (Derby), All Rights Reserved.
//
//
// Wrapper class to allow integration of DemonWare's Matchmaking+ SDK
//

// Asura include
#include "Core/Asura.h"

#if defined(ASURA_SUPPORT_EXTERNAL_NETWORK) && defined (ASURA_SUPPORT_DEMONWARE)

// Middleware includes (must be guarded by Asura_MemoryManagement_DebugOff/On)
#include "Core/Asura_MemoryManagement_DebugOff.h"
#include "DemonWare/bdNet/bdNet.h"

// Engine includes
#include "Debugging/Asura_Assert.h"
#include "Network/Asura_DemonWare_LogSubscriber.h"
#include "Network/Asura_DemonWare_MemoryManager.h"
#include "Network/Asura_NetSocket.h"
#include "Network/Asura_DemonWare_PacketInterceptor.h"
#include "Network/Asura_NetSocket.h"
#include "Network/Asura_Demonware_CustomMatchMakingInfo.h"
#include "bdLobby/bdMatchMaking/bdMatchMakingInfo.h"


// This file's header
#include "Network/Asura_DemonWare.h"

// Platform includes
#include <ipexport.h>
#include <iptypes.h>
#include <iphlpapi.h>

// Need to move this into the project settings
#pragma comment(lib, "iphlpapi.lib")

//
//	Platform_Initialise()
//
// MRD changed to only initialise the platforms network system
// it used to do some Demonware stuff as well which isn't really 
// what it should be doing 
int32 Asura_Demonware::Platform_Initialise( bdNetStartParams& xParams)
{
	// Start WinSock (this is also done in Asura_NetTransport_System::Platform_Initialise() but hopefully it won't go bang if we do it twice)
	WSADATA data;
	const int32 iVal = WSAStartup(0x0101, &data);

	Asura_Assert( iVal == 0, "Failed to start Winsock!" );
	if( iVal != 0 )
	{
		return iVal;
	}

	// GetAdaptersInfo treats first argument as a chunk of memory.
	bdByte8* pcHeapOutBuffer = NULL;
	bdByte8  cStackOutBuffer[sizeof(IP_ADAPTER_INFO)];
	bdULong uOutBufferLength = sizeof(IP_ADAPTER_INFO);
	PIP_ADAPTER_INFO pxAdapterInfo = reinterpret_cast<PIP_ADAPTER_INFO>(&cStackOutBuffer);

	ASURA_DEMONWARE_LOG(("Determining adapter information"));

	// Make an initial call to GetAdaptersInfo to get the necessary size into the uiBufferLength variable
	if (GetAdaptersInfo(pxAdapterInfo, &uOutBufferLength) == ERROR_BUFFER_OVERFLOW)
	{
		pcHeapOutBuffer = reinterpret_cast<bdByte8*>(Asura_DemonWare_Allocate(uOutBufferLength));
		pxAdapterInfo = reinterpret_cast<PIP_ADAPTER_INFO>(pcHeapOutBuffer);
	}

	//Get info for the adapters
	if (GetAdaptersInfo(pxAdapterInfo, &uOutBufferLength) != ERROR_SUCCESS)
	{
		//Call failed
		Asura_Assert(false, "Asura_DemonWare::Platform_Initialise(): Unable to get adapter info!");
	}
	else
	{
		int iIndex = 0;

		while (pxAdapterInfo != NULL)
		{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
			ASURA_DEMONWARE_LOG(("Adapter %u: %s", iIndex, pxAdapterInfo->Description));
			ASURA_DEMONWARE_LOG(("Adapter %u: default gw: %s", iIndex, pxAdapterInfo->GatewayList.IpAddress.String));
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE

			PIP_ADDR_STRING pxAddrString = &pxAdapterInfo->IpAddressList;
			while (pxAddrString != NULL)
			{
				if (strcmp(pxAddrString->IpAddress.String, "0.0.0.0") != 0)
				{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
					ASURA_DEMONWARE_LOG(("Adapter %u: %s", iIndex, pxAddrString->IpAddress.String));
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE

					xParams.m_localAddresses.pushBack(bdInetAddr(pxAddrString->IpAddress.String));
				}
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
				else
				{
					ASURA_DEMONWARE_LOG(("Adapter %u: %s skipping (invalid address)", iIndex, pxAddrString->IpAddress.String));
				}
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE

				pxAddrString = pxAddrString->Next;
			}

			pxAdapterInfo = pxAdapterInfo->Next;
			iIndex++;
		}

#if defined(ASURA_LOGFILES_ENABLED)
		ASURA_DEMONWARE_LOG(("Using %u valid network adapter(s) out of %u total", true, xParams.m_localAddresses.getSize(), iIndex));
#endif // ASURA_LOGFILES_ENABLED
	}

	if (xParams.m_localAddresses.isEmpty())
	{
		// Machine is not connected to any kind of network. Add loopback as local.
		ASURA_DEMONWARE_LOG(("No valid network adapters - using loopback as local address"));
		xParams.m_localAddresses.pushBack(bdInetAddr("127.0.0.1"));
	}

	if (pcHeapOutBuffer != NULL)
	{
		// MRD 12/10/07 - Free up the adapter memory if we allocated any
		Asura_DemonWare_Deallocate(pcHeapOutBuffer);
	}

	return iVal;
}
void Asura_Demonware::Platform_ShutDown(void)
{
	// Clean up WinSock
	WSACleanup();
}
//
//	Platform_ShutDown()
//

#endif // ASURA_SUPPORT_EXTERNAL_NETWORK && ASURA_SUPPORT_DEMONWARE
