//////////////////////////////////////////////////////////////////////////////
//
// Asura_Platform_NetSocket.cpp
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

/******************************************************************************/
/* Included Files                                                             */
/******************************************************************************/

#include "Core/Asura.h"

#include "Network/Asura_NetSocket.h"

#if defined ASURA_SUPPORT_EXTERNAL_NETWORK

/******************************************************************************/
/* Asura_NetSocket Static Class Functions                                     */
/******************************************************************************/

static char g_acFullMessage[1264];
bool Asura_NetSocket::Platform_GetData( const char*& pcMessage, int& iLength )
{
	// First two bytes are length of game data
	if(!m_bUseAlternativeProtocol)
	{
		Asura_Assert(iLength > 2, "No data");
		if(iLength <= 2)
		{
			return false;
		}
		memcpy(g_acFullMessage, pcMessage + 2, iLength - 2);
		pcMessage = g_acFullMessage;

		iLength -= 2;
// #ifdef ASURA_ASSERT
// 		const u_short usSize = *reinterpret_cast<const u_short*>(pcMessage);
// 		Asura_Assert(usSize == 0 || usSize == iLength, "Message size mismatch .");
// #endif
// 		pcMessage += 2;
	}
	return true;

}

// 1264 is the maximum packet size that can be sent using Xbox sockets
static u_short* g_pusSize = reinterpret_cast<u_short*>(g_acFullMessage);


bool Asura_NetSocket::Platform_SendTo( const Asura_NetSocket_MessageInfo* pxMessageInfo )
{
	SOCKADDR_IN xAddress;
	memset(&xAddress, 0, sizeof(SOCKADDR_IN));
	xAddress.sin_family = AF_INET;
	xAddress.sin_addr.s_addr = pxMessageInfo->m_xAddress;
	xAddress.sin_port = htons(pxMessageInfo->m_usPort);

	Asura_Assert(pxMessageInfo->m_iLength <= 1262, "Message too large");
	int iBytesToSend = pxMessageInfo->m_iLength;

	if(!m_bUseAlternativeProtocol)
	{
		memcpy(g_acFullMessage + 2, pxMessageInfo->m_pcMessage, pxMessageInfo->m_iLength);
		// Xbox VDP protocol takes first two bytes as length of game (encrypted) data; remaining bytes are voice (unencrypted)
		// We are not doing any clever packaging of game data with voice data, so it is all or nothing.
		if(pxMessageInfo->m_bEncrypted)
		{
			*g_pusSize = static_cast<u_short>(pxMessageInfo->m_iLength);
		}
		else
		{
			*g_pusSize = 0;
		}
		iBytesToSend = pxMessageInfo->m_iLength + 2;
	}
	else
	{
		memcpy(g_acFullMessage, pxMessageInfo->m_pcMessage, pxMessageInfo->m_iLength);
	}

	return sendto(m_xSocket, g_acFullMessage, iBytesToSend, 0, (SOCKADDR *)&xAddress, sizeof(SOCKADDR_IN)) != SOCKET_ERROR;
}

bool Asura_NetSocket::Platform_SetToNonBlocking()
{
	DWORD dwNonBlocking = 1;
	int iResult = ioctlsocket( m_xSocket, FIONBIO, &dwNonBlocking );
	Asura_Assert( iResult != SOCKET_ERROR, "Error setting socket to non blocking" );
	return iResult != SOCKET_ERROR;
}

void Asura_NetSocket::Platform_Update()
{
	// Only necessary on PS2
}

// if Asura_NetAddress is u_int this function is easy, just return it. On PSP things are harder...
u_int Asura_NetSocket::Platform_GetINetAddress( const Asura_NetAddress& xAddress )
{
	return xAddress;
}

#endif // defined ASURA_SUPPORT_EXTERNAL_NETWORK
