#include "stdafx.h"
#include <stdlib.h>

#define WINSOCK_API_LINKAGE
#include <winsock2.h>

#include <ras.h>
#include <raserror.h>
#include <nb30.h>
#include "WatchConnection.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

CWatchConnection::CWatchConnection()
{
	cConn = 0;
	lpRasConn = (LPRASCONN)malloc(sizeof(RASCONN));
	lphRasConn = (LPHRASCONN)malloc(sizeof(HRASCONN));
	RasStatus.dwSize = sizeof(RASCONNSTATUS);
}

CWatchConnection::~CWatchConnection()
{
	if(lpRasConn)
		free(lpRasConn);
	if(lphRasConn)
		free(lphRasConn);

	lpRasConn = NULL;
	lphRasConn = NULL;
}

bool CWatchConnection::TestIP(char *ip)
{
	char szHostname[100];
	HOSTENT *pHent;
	int nAdapter = 0;
	SOCKADDR_IN sinRemote;

	if(!ip)
		return false;

	if(gethostname(szHostname, sizeof(szHostname)) != 0)
		return false;

	pHent = gethostbyname(szHostname);
	if(!pHent)
		return false;

	if(!pHent->h_addr)
		return false;

     sinRemote.sin_addr.s_addr = *(u_long *)pHent->h_addr;
	 if(sinRemote.sin_addr.S_un.S_un_b.s_b1 == 0 &&
		 sinRemote.sin_addr.S_un.S_un_b.s_b2 == 0 &&
		 sinRemote.sin_addr.S_un.S_un_b.s_b3 == 0 &&
		 sinRemote.sin_addr.S_un.S_un_b.s_b4 == 0)
		 return false;

     wsprintf(ip, "%i.%i.%i.%i",
             sinRemote.sin_addr.S_un.S_un_b.s_b1,
             sinRemote.sin_addr.S_un.S_un_b.s_b2,
             sinRemote.sin_addr.S_un.S_un_b.s_b3,
             sinRemote.sin_addr.S_un.S_un_b.s_b4);

	return true;
}

bool CWatchConnection::Refresh()
{
	DWORD dwStatus = 0;
	DWORD cbBuf = 0, ndx;
	LPRASCONN  lpTemp = NULL;
	LPHRASCONN lphTemp = NULL;

	cbBuf = sizeof(RASCONN);
	lpRasConn->dwSize = sizeof(RASCONN);
	dwStatus = RasEnumConnections(lpRasConn, &cbBuf, &cConn);
	if(dwStatus == ERROR_BUFFER_TOO_SMALL)
	{
		lpTemp = (LPRASCONN)realloc(lpRasConn, cbBuf);
		if(!lpTemp)
			return false;

		lpRasConn = lpTemp;
		dwStatus = RasEnumConnections(lpRasConn, &cbBuf, &cConn);
		lphTemp = (LPHRASCONN)realloc(lphRasConn, sizeof(HRASCONN) * cConn);
		if(!lphTemp)
		{
			free((void *)lpTemp);
			return false;
		}

		lphRasConn = lphTemp;
	}

	for(ndx = 0; ndx < cConn; ndx++)
		lphRasConn[ndx] = lpRasConn[ndx].hrasconn;

	return true;
}

bool CWatchConnection::IsConnected()
{
	char LocalIP[24];
	NCB ncb;
	struct
	{
		SESSION_HEADER status;
		SESSION_BUFFER names[10];
	} sessiondata;
	LANA_ENUM LEnum;

	/* Check for RAS (dialup) connection first */
	if(cConn)
	{
		for(DWORD ndx = 0; ndx < cConn; ndx++)
		{
			RasGetConnectStatus(lpRasConn[ndx].hrasconn, 
				&RasStatus);

			if(RasStatus.rasconnstate == RASCS_Connected)
			{
				return TestIP(LocalIP);
			}
		}
	}

	/* No dialup connection found.  Begin the search for an Ethernet
	   connection */

	/* Get the adapter number(s) */
	memset((void *)&ncb,  (char)0, sizeof(NCB));
	memset((void *)&LEnum, (char)0, sizeof(LANA_ENUM));

	ncb.ncb_command = NCBENUM;
	ncb.ncb_buffer = (unsigned char *)(&LEnum);
	ncb.ncb_length = sizeof(LANA_ENUM);
	ncb.ncb_lana_num = 0;
	
	Netbios(&ncb);
	if(ncb.ncb_retcode != NRC_GOODRET)
		return false;

	/* Get the session statistics, using the first adapter number */
	memset((void *)&ncb,  (char)0, sizeof(NCB));
	memset((void *)&sessiondata, (char)0, sizeof(sessiondata));

	ncb.ncb_command = NCBSSTAT;
	ncb.ncb_buffer = (unsigned char *)(&sessiondata);
	ncb.ncb_length = sizeof(sessiondata);
	ncb.ncb_lana_num = LEnum.lana[0];
	strcpy((char *)ncb.ncb_callname, "*             ");
	strcpy((char *)ncb.ncb_name, "*             ");
	
	Netbios(&ncb);
	if(ncb.ncb_retcode != NRC_GOODRET)
		return false;

	return TestIP(LocalIP);
}
