#include "p_apps.h"
#include "v_task.h"
#include "p_http.h"
#include "page12.h"

#define HTTP_CLIENT_NULL		0
#define HTTP_CLIENT_CHECK_IP	1

XCHAR Http_pRecvPacket[HTTP_MAX_RECV_LEN+1];

XCHAR Http_iClientType;
XCHAR Http_iRecvLen;
XCHAR Http_iState;
XSHORT Http_iCurMsgLen;
XLONG Http_lContentLen;
BOOLEAN Http_bBrokenLine;
XCHAR Http_iExtraDataTask;

static XCHAR _pServerIP[IP_ALEN];
static XSHORT _iDstPort;

static BOOLEAN _bProxyIPFound = FALSE;
static XCHAR _iDnsIndex = 255;

#define CHECKIP_DNS_NUM		8
#define CHECKIP_DNS_LENGTH	26
static CCHAR _cCheckIPDns[CHECKIP_DNS_NUM][CHECKIP_DNS_LENGTH] = {
"www.ipchicken.com",
"www.whatismyip.com",
"www.formyip.com",
"www.myipaddress.com",
"www.whatismyipaddress.com",
"www.showmyip.com",
"checkip.dyndns.org",
"checkip.dyndns.org:8245",
};

BOOLEAN ProxyDecodeIP(PXCHAR pSrc, USHORT iLength)
{
	DSHORT i;

	for (i = 0; i < iLength; i ++)
	{
		if (pSrc[i] >= '0' && pSrc[i] <= '9')
		{
			if (p_String2IP((PXCHAR)(pSrc+i), Sys_pProxyIP))
			{
				if (IsPublicIP(Sys_pProxyIP))
				{
					OutputIP(Sys_pProxyIP, IDS_CHECK_POINT_0);
					Sys_bNATed = (p_memcmp_ip(Sys_pProxyIP, Local_pIPAddress)) ? TRUE : FALSE;
					return TRUE;
				}
			}
		}
	}

	return FALSE;
}

void CheckIPStart(PXCHAR pDstIP, USHORT iDstPort)
{
	_bProxyIPFound = FALSE;
	Http_iClientType = HTTP_CLIENT_CHECK_IP;
	Http_iExtraDataTask = FALSE;
	HttpGetIPStart(pDstIP, iDstPort);
}

void CheckIPHandleConnectEvent()
{
	p_line_start((PXCHAR)Adapter_pSendTcpData);

	p_line_add_c((PCCHAR)"GET / ");
	p_line_add_c(Http_cName);
	p_line_add_newline();

	p_line_add_c(Http_cAccept);
	p_line_add_colon();
	p_line_add_c((PCCHAR)"*/*");
	p_line_add_newline();

	p_line_add_c(Http_cAcceptLanguage);
	p_line_add_newline();

	p_line_add_c(Http_cAcceptEncoding);
	p_line_add_colon();
	p_line_add_c((PCCHAR)"none");
	p_line_add_newline();

	p_line_add_c(Http_cUserAgent);
	p_line_add_colon();
	p_line_add_c((PCCHAR)"PA1688");
	p_line_add_newline();

	p_line_add_c((PCCHAR)"Host");
	p_line_add_colon();
	SdramReadData(DNS_STRING_SDRAM_LO);
	p_line_add_x((PXCHAR)Sdram_pDataCache);
	p_line_add_newline();

	p_line_add_c(Http_cConnection);
	p_line_add_c((PCCHAR)"Keep-Alive");
	p_line_add_newline();
	p_line_add_newline();

	Http_iCurMsgLen = (UCHAR)p_line_get_len();
}

void CheckIPHandleDataEvent()
{
	if (_bProxyIPFound)		return;

	if (ProxyDecodeIP((PXCHAR)Adapter_pReceiveTcpData, Adapter_iReceiveLen))
	{
		SdramSaveData(OPTIONS_SDRAM_POS+PUBLIC_IP_SDRAM_LO, Sys_pProxyIP, IP_ALEN);
		SdramUpdateFlagByte(FLAGS_PAGE12_ATTR, PAGE12_PUBLIC_IP);
		_bProxyIPFound = TRUE;
		TcpClose(HTTP_CLIENT_SDRAM_LO);
		Http_iExtraDataTask = TRUE;
	}
//	OutputVals((PXCHAR)Adapter_pReceiveTcpData, Adapter_iReceiveLen);
}

void CheckIPHandleExtraTask()
{
	if (Http_iExtraDataTask)
	{
		OnPage12End();
		Http_iExtraDataTask = FALSE;
	}
}

void _CheckIPHandleException()
{
	HttpGetIPInitialize();	
	if (_bProxyIPFound)
	{
		OnPage12End();
	}

	CheckIPFromStoredDns();
}

void CheckIPHandleCloseEvent()
{
	_CheckIPHandleException();
}

void CheckIPHandleResetEvent()
{
	_CheckIPHandleException();
}

void CheckIPHandleTimerOut()
{
	_CheckIPHandleException();
}

void CheckIPFromStoredDns()
{
	_iDnsIndex ++;
	if (_iDnsIndex < CHECKIP_DNS_NUM)
	{
		Task_iDnsType = DNS_TYPE_PROXY;
		p_strcpy_c2x((PXCHAR)Sdram_pDataCache, (PCCHAR)_cCheckIPDns[_iDnsIndex]);
		DnsSend((PXCHAR)Sdram_pDataCache, FALSE);
	}
	else
	{
		_iDnsIndex = 255;
		Task_iDnsType = DNS_TYPE_NONE;
		OnPage12End();
	}
}



/////////////////////////////////////////////////////////////////////////////////////
//     Global Http function
////////////////////////////////////////////////////////////////////////////////////

void HttpGetIPInitialize()
{
	TcbInit(HTTP_SERVER_PORT, HTTP_TIME_OUT, HTTP_CLIENT_SDRAM_LO);
	Http_bBrokenLine = FALSE;
	Http_iState = HTTP_STATE_INIT;
	Http_iRecvLen = 0;
	Http_iCurMsgLen = 0;
	Http_lContentLen = 0;
}

void _ClientInitialize()
{
	// Tcp init
	Http_iState = HTTP_STATE_INIT;
	Http_iRecvLen = 0;
	Http_iCurMsgLen = 0;
	Http_lContentLen = 0;
	Http_bBrokenLine = FALSE;
}

BOOLEAN HttpGetIPRun()
{
	if (!TcbRun(HTTP_CLIENT_SDRAM_LO))	return FALSE;

	if (Tcp_bAcceptEvent)
	{
//		OutputString(IDS_HTTP_ACCEPT);
		Tcp_bAcceptEvent = FALSE;
	}
	if (Tcp_bConnectEvent)
	{
//		OutputString(IDS_HTTP_CONNECT);
		Tcp_bConnectEvent = FALSE;
		if (Http_iClientType == HTTP_CLIENT_CHECK_IP)
		{
			CheckIPHandleConnectEvent();
		}
	}

    if (Tcp_bDataEvent)
    {
//		DebugCString((PCCHAR)"http rcv data");
		if (Http_iClientType == HTTP_CLIENT_CHECK_IP)
		{
			CheckIPHandleDataEvent();
		}
		Tcp_bDataEvent = FALSE;
    }
    if (Tcp_bCloseEvent)
	{
		TcpClose(HTTP_CLIENT_SDRAM_LO);
	}

	TcpSend(Http_iCurMsgLen);
	Http_iCurMsgLen = 0;

	if (TcbAcked())
	{
		if (Http_iClientType == HTTP_CLIENT_CHECK_IP)
		{
			CheckIPHandleExtraTask();
		}
	}
    if (Tcp_bCloseEvent)
    {
//		DebugCString((PCCHAR)"http close");
		Tcp_bCloseEvent = FALSE;
		_ClientInitialize();
		if (Http_iClientType == HTTP_CLIENT_CHECK_IP)
		{
			CheckIPHandleCloseEvent();
		}
	}

	if (Tcp_bResetEvent)
	{
		Tcp_bResetEvent = FALSE;
		if (Http_iClientType == HTTP_CLIENT_CHECK_IP)
		{
			CheckIPHandleResetEvent();
		}
	}
	return TRUE;
}

void HttpGetIPHandleTimer()
{
	if (TcbHandleTimer(HTTP_CLIENT_SDRAM_LO))
	{
		return;
	}

	OutputString(IDS_HTTP_TIMER_FAIL);

	// Handle time out failure
	TcpSendClose(HTTP_CLIENT_SDRAM_LO);
	if (Http_iClientType == HTTP_CLIENT_CHECK_IP)
	{
		CheckIPHandleTimerOut();
	}
}

void HttpGetIPStart(PXCHAR pDstIP, USHORT iDstPort)
{
	_ClientInitialize();
	p_memcpy_ip(_pServerIP, pDstIP);
	_iDstPort = iDstPort;
	HttpGetIPStartAgain();
}

void HttpGetIPStartAgain()
{
	TcbInit((USHORT)(TCP_SRC_PORT_MIN + p_rand_char()), HTTP_TIME_OUT, HTTP_CLIENT_SDRAM_LO);
	TcpOpen(_pServerIP, _iDstPort, HTTP_CLIENT_SDRAM_LO);
}

