ipaddress.cpp

来自「很好用的网络封装库,不熟悉网络编程的人也可以使用。使用风格良好的标准c++编写。」· C++ 代码 · 共 802 行 · 第 1/2 页

CPP
802
字号
//
// IPAddress.cpp
//
// $Id: //poco/1.3/Net/src/IPAddress.cpp#6 $
//
// Library: Net
// Package: NetCore
// Module:  IPAddress
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//


#include "Poco/Net/IPAddress.h"
#include "Poco/Net/NetException.h"
#include "Poco/RefCountedObject.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Types.h"
#include <algorithm>
#include <cstring>


using Poco::RefCountedObject;
using Poco::NumberFormatter;
using Poco::UInt8;
using Poco::UInt16;
using Poco::UInt32;


namespace Poco {
namespace Net {


//
// IPAddressImpl
//


class IPAddressImpl: public RefCountedObject
{
public:
	virtual std::string toString() const = 0;
	virtual poco_socklen_t length() const = 0;
	virtual const void* addr() const = 0;
	virtual IPAddress::Family family() const = 0;
	virtual int af() const = 0;
	virtual bool isWildcard() const	= 0;
	virtual bool isBroadcast() const = 0;
	virtual bool isLoopback() const = 0;
	virtual bool isMulticast() const = 0;
	virtual bool isLinkLocal() const = 0;
	virtual bool isSiteLocal() const = 0;
	virtual bool isIPv4Mapped() const = 0;
	virtual bool isIPv4Compatible() const = 0;
	virtual bool isWellKnownMC() const = 0;
	virtual bool isNodeLocalMC() const = 0;
	virtual bool isLinkLocalMC() const = 0;
	virtual bool isSiteLocalMC() const = 0;
	virtual bool isOrgLocalMC() const = 0;
	virtual bool isGlobalMC() const = 0;
	virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0;
	virtual IPAddressImpl* clone() const = 0;

protected:
	IPAddressImpl()
	{
	}
	
	virtual ~IPAddressImpl()
	{
	}

private:
	IPAddressImpl(const IPAddressImpl&);
	IPAddressImpl& operator = (const IPAddressImpl&);
};


class IPv4AddressImpl: public IPAddressImpl
{
public:
	IPv4AddressImpl()
	{
		std::memset(&_addr, 0, sizeof(_addr));
	}
	
	IPv4AddressImpl(const void* addr)
	{
		std::memcpy(&_addr, addr, sizeof(_addr));
	}
	
	std::string toString() const
	{
		const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
		std::string result;
		result.reserve(16);
		result.append(NumberFormatter::format(bytes[0]));
		result.append(".");
		result.append(NumberFormatter::format(bytes[1]));
		result.append(".");
		result.append(NumberFormatter::format(bytes[2]));
		result.append(".");
		result.append(NumberFormatter::format(bytes[3]));
		return result;
	}

	poco_socklen_t length() const
	{
		return sizeof(_addr);
	}
	
	const void* addr() const
	{
		return &_addr;
	}
	
	IPAddress::Family family() const
	{
		return IPAddress::IPv4;
	}
	
	int af() const
	{
		return AF_INET;
	}
	
	bool isWildcard() const
	{
		return _addr.s_addr == INADDR_ANY;
	}
	
	bool isBroadcast() const
	{
		return _addr.s_addr == INADDR_NONE;
	}
	
	bool isLoopback() const
	{
		return ntohl(_addr.s_addr) == 0x7F000001; // 127.0.0.1
	}
	
	bool isMulticast() const
	{
		return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24
	}
		
	bool isLinkLocal() const
	{
		return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
	}
	
	bool isSiteLocal() const
	{
		UInt32 addr = ntohl(_addr.s_addr);
		return (addr & 0xFF000000) == 0x0A000000 ||      // 10.0.0.0/24
		       (addr & 0xFFFF0000) == 0xC0A80000 ||      // 192.68.0.0/16
		       addr >= 0xAC100000 && addr <= 0xAC1FFFFF; // 172.16.0.0 to 172.31.255.255
	}
	
	bool isIPv4Compatible() const
	{
		return true;
	}

	bool isIPv4Mapped() const
	{
		return true;
	}

	bool isWellKnownMC() const
	{
		return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8
	}
	
	bool isNodeLocalMC() const
	{
		return false;
	}
	
	bool isLinkLocalMC() const
	{
		return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24
	}
	
	bool isSiteLocalMC() const
	{
		return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16
	}
	
	bool isOrgLocalMC() const
	{
		return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16
	}
	
	bool isGlobalMC() const
	{
		UInt32 addr = ntohl(_addr.s_addr);
		return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255
	}

	static IPv4AddressImpl* parse(const std::string& addr)
	{
		if (addr.empty()) return 0;		
#if defined(_WIN32) 
		struct in_addr ia;
		ia.s_addr = inet_addr(addr.c_str());
		if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
			return 0;
		else
			return new IPv4AddressImpl(&ia);
#else
#if __GNUC__ < 3
		struct in_addr ia;
		ia.s_addr = inet_addr(addr.c_str());
		if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
			return 0;
		else
			return new IPv4AddressImpl(&ia);
#else
		struct in_addr ia;
		if (inet_aton(addr.c_str(), &ia))
			return new IPv4AddressImpl(&ia);
		else
			return 0;
#endif
#endif
	}
	
	void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
	{
		poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET);
		
		_addr.s_addr &= static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
		_addr.s_addr |= static_cast<const IPv4AddressImpl*>(pSet)->_addr.s_addr & ~static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
	}
	
	IPAddressImpl* clone() const
	{
		return new IPv4AddressImpl(&_addr);
	}
		
private:
	struct in_addr _addr;	
};


#if defined(POCO_HAVE_IPv6)


class IPv6AddressImpl: public IPAddressImpl
{
public:
	IPv6AddressImpl()
	{
		std::memset(&_addr, 0, sizeof(_addr));
	}

	IPv6AddressImpl(const void* addr)
	{
		std::memcpy(&_addr, addr, sizeof(_addr));
	}

	std::string toString() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		if (isIPv4Compatible() || isIPv4Mapped())
		{
			std::string result;
			result.reserve(24);
			if (words[5] == 0)
				result.append("::");
			else
				result.append("::FFFF:");
			const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
			result.append(NumberFormatter::format(bytes[12]));
			result.append(".");
			result.append(NumberFormatter::format(bytes[13]));
			result.append(".");
			result.append(NumberFormatter::format(bytes[14]));
			result.append(".");
			result.append(NumberFormatter::format(bytes[15]));
			return result;
		}
		else
		{
			std::string result;
			result.reserve(46);
			bool zeroSequence = false;
			int i = 0;
			while (i < 8)
			{
				if (!zeroSequence && words[i] == 0)
				{
					int zi = i;
					while (zi < 8 && words[zi] == 0) ++zi;
					if (zi > i + 1)
					{
						i = zi;
						result.append(":");
						zeroSequence = true;
					}
				}
				if (i > 0) result.append(":");
				if (i < 8) result.append(NumberFormatter::formatHex(ntohs(words[i++])));
			}
			return result;
		}
	}
	
	poco_socklen_t length() const
	{
		return sizeof(_addr);
	}

	const void* addr() const
	{
		return &_addr;
	}

	IPAddress::Family family() const
	{
		return IPAddress::IPv6;
	}

	int af() const
	{
		return AF_INET6;
	}

	bool isWildcard() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && 
		       words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0;
	}
	
	bool isBroadcast() const
	{
		return false;
	}
	
	bool isLoopback() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && 
		       words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 1;
	}
	
	bool isMulticast() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		return (words[0] & 0xFFE0) == 0xFF00;
	}
		
	bool isLinkLocal() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		return (words[0] & 0xFFE0) == 0xFE80;
	}
	
	bool isSiteLocal() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		return (words[0] & 0xFFE0) == 0xFEC0;
	}
	
	bool isIPv4Compatible() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0;
	}

	bool isIPv4Mapped() const
	{
		const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
		return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0xFFFF;
	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?