/*
	IPAddress
	IPアドレスを抽象化する

	Version		: 0.0 (Release1)

	作成日		: 2002/05/25 (Yuh)
	修正日		: 2008/12/04 (Yuh)
	修正日		: 2009/02/12 (Yuh)
	改定履歴	: 2009/02/12 UTF8化、掃除
*/

#include "stdafx.h"
#include "IPAddress.h"
#include <ws2tcpip.h>

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

//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////
/*!
	ノーマルコンストラクタ
*/
CIPAddress::CIPAddress()
{
	*this = (DWORD)0;
}

/*!
	in_addr コンストラクタ
*/
CIPAddress::CIPAddress(in_addr other)
{
	*this = other;
}

/*!
	DWORD コンストラクタ
*/
CIPAddress::CIPAddress(DWORD other)
{
	*this = other;
}



//////////////////////////////////////////////////////////////////////
// 代入
//////////////////////////////////////////////////////////////////////
/*!
	in_addr コピー
*/
void CIPAddress::operator=(in_addr other)
{
	m_ip = other;
}

/*!
	DWORDから
*/
void CIPAddress::operator=(DWORD other)
{
	m_ip.S_un.S_addr = ntohl(other);
}

/*!
	文字列から
*/
void CIPAddress::SetAddressByString(CUTF8String other)
{
	//	UTF8を読ませる
	m_ip.S_un.S_addr = inet_addr((LPCSTR)other.GetString());
}

/*
	ホスト名より指定

		ポート番号が付いていれば、返す
	*/
int CIPAddress::SetAddressByHostName(CUTF8String host)
{
	//	マルチバイトを読ませる
	hostent	*ent = gethostbyname(_cnvMBCS(host));
	if(ent == NULL)
		return(-1);

	sockaddr_in *in = (sockaddr_in *)ent->h_addr_list[0];
	m_ip = in->sin_addr;

	return(htons(in->sin_port));
}

//////////////////////////////////////////////////////////////////////
// 取得
//////////////////////////////////////////////////////////////////////
/*!
	in_addr
*/
CIPAddress::operator in_addr() const
{
	return(m_ip);
}


/*!
	DWORD 
*/
CIPAddress::operator DWORD() const
{
	return(htonl(m_ip.S_un.S_addr));
}


/*!
	文字列取得
*/
CUTF8String CIPAddress::GetString() const
{
	return(_cnvU8(inet_ntoa(m_ip)));
}

/*!
	ホスト名をDNSから逆引き
*/
CUTF8String CIPAddress::GetHostName() const
{
	hostent	*ent = gethostbyaddr((char *)&m_ip,sizeof(m_ip),AF_INET);
	if(ent == NULL || strlen(ent->h_name)==0)
		return(_cnvU8(inet_ntoa(m_ip)));

	return(_cnvU8(ent->h_name));
}

//////////////////////////////////////////////////////////////////////
// 比較
//////////////////////////////////////////////////////////////////////
/*!
	CIPAddress 比較
*/
int CIPAddress::operator==(CIPAddress other)
{
	return(other.m_ip.S_un.S_addr == m_ip.S_un.S_addr);
}

/*!
	in_addr 比較
*/
int CIPAddress::operator==(in_addr other)
{
	return(CIPAddress(other) == *this);
}

/*!
	DWORD 比較
*/
int CIPAddress::operator==(DWORD other)
{
	return(CIPAddress(other) == *this);
}


//////////////////////////////////////////////////////////////////////////////////
//	接続情報
//////////////////////////////////////////////////////////////////////////////////
/*!
	実行中のPCのアドレスを得る
*/
CIPAddress CIPAddress::GetLocalhost()
{
	//	ダミーのソケットを生成
	SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
	if(sd == SOCKET_ERROR)
		return(0);

	INTERFACE_INFO InterfaceList[20];
	unsigned long nBytesReturned;
	if(WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
		sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
		return(0);

	int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
	if(nNumInterfaces <= 0)
		return(0);
	
	sockaddr_in *pAddress;
	pAddress = (sockaddr_in *) & (InterfaceList[0].iiAddress);
	return(pAddress->sin_addr);
}
