//
// Asura_Platform_NetSocket.cpp
//
// PS2 version
//
// Created by MH - 19.07.2004
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

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

#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK

#include "Core/Asura_Timers.h"

#include "Core/Asura_PS2_OS.h"

// (MH - 19.07.2004) these are platform functions in order to work around funny packet headers on the
// XBox (used for Voice Data) and the XBox limit of 1304 bytes per sendto call. On PC/PS2 we don't need
// to fiddle about with headers or impose a limit (the independent code should keep packet sizes down 
// below about 1kb anyway).
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);

	return sendto(m_xSocket, pxMessageInfo->m_pcMessage, pxMessageInfo->m_iLength, 0, (SOCKADDR *)&xAddress, sizeof(SOCKADDR_IN)) != SOCKET_ERROR;
}

// (MH - 21.07.2004) HACK - align the message on a (4-byte + 2) boundary to match what it was when it was sent.
// this must be sorted out
//static char g_acAlignedBuffer[2048];
bool Asura_NetSocket::Platform_GetData(const char*& pcMessage, int& iLength)
{
//	const u_short* pusSequenceNumber = reinterpret_cast<const u_short*>(pcMessage);
//	u_short usMessageID = *(pusSequenceNumber + 1);
//	if (usMessageID >= ASURA_MSG_TRANSPORT_LAYER && usMessageID < ASURA_NETTRANSPORT_END_OF_MSG_IDS)
//	{
//		return true;
//	}
//
//	if (iLength <= 2046)
//	{
//		memcpy(g_acAlignedBuffer + 2, pcMessage, iLength);
//		pcMessage = g_acAlignedBuffer + 2;
//		return true;
//	}
//	return false;
	return true;
}

bool Asura_NetSocket::Platform_SetToNonBlocking()
{
	int iNonBlocking = 1;
	int iResult = sceEENetSetsockopt (m_xSocket, SOL_SOCKET, SO_NBIO, &iNonBlocking, sizeof(int));
    Asura_Assert( iResult != SOCKET_ERROR, "Error setting socket to non blocking" );
	return iResult != SOCKET_ERROR;
}

const u_int uTHREAD_DELAY_TIME = 1;
const u_int uMIN_TIME_BETWEEN_UPDATES = 10;

// SNH - 27/10/2004 10:17:12 - when connecting, the socket seems to be updated too frequently.
//	This doesn't allow the EENet threads to get enough execution time, so connection fails.
//	If called more than once in 10ms Platform_Update will delay for 1ms to prevent this.
void Asura_NetSocket::Platform_Update()
{
	static u_int uLastUpdateTime = 0;
	u_int uCurrentTime = Asura_Timers::GetMSecsSinceStart();

	// called more than once per frame
	if((uCurrentTime != uLastUpdateTime) && (uCurrentTime - uLastUpdateTime < uMIN_TIME_BETWEEN_UPDATES))
	{
		Asura_PS2_OS::DelayThread(uTHREAD_DELAY_TIME);
	}	

	uLastUpdateTime = uCurrentTime;
}

// 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 //#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
