2024-07-25 02:57:29 +08:00

441 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef HGL_NETWORK_IP_INCLUDE
#define HGL_NETWORK_IP_INCLUDE
#include<hgl/platform/Platform.h>
#if HGL_OS == HGL_OS_Windows
#include<ws2tcpip.h>
#if SOMAXCONN == 5
#error Please use <winsock2.h>
#endif//
typedef int socklen_t;
typedef ULONG in_addr_t;
#define GetLastSocketError() WSAGetLastError()
#ifndef SOCK_DCCP
#define SOCK_DCCP 6
#endif//SOCK_DCCP
#ifndef SOCK_PACKET
#define SOCK_PACKET 10
#endif//SOCK_PACKET
#ifndef IPPROTO_DCCP
#define IPPROTO_DCCP 33
#endif//IPPROTO_DCCP
#ifndef IPPROTO_UDPLITE
#define IPPROTO_UDPLITE 136
#endif//IPPROTO_UDPLITE
#else
#include<errno.h>
#include<sys/types.h>
#include<sys/ioctl.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netdb.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#define GetLastSocketError() (errno)
#if HGL_OS == HGL_OS_Linux
#include<sys/sendfile.h>
inline int sendfile(int tfd,int sfd,size_t size)
{
return sendfile(tfd,sfd,nullptr,size);
}
#endif//HGL_OS == HGL_OS_Linux
#if HGL_OS == HGL_OS_FreeBSD
#include<sys/uio.h>
inline int sendfile(int tfd,int sfd,size_t size)
{
return sendfile(tfd,sfd,0,size,nullptr,nullptr,0);
}
#endif//HGL_OS == HGL_OS_FreeBSD
#if (HGL_OS == HGL_OS_macOS)||(HGL_OS == HGL_OS_iOS)
#ifndef IPPROTO_UDPLITE
#define IPPROTO_UDPLITE 136
#endif//IPPROTO_UDPLITE
#endif//
#endif//HGL_OS == HGL_OS_Windows
#include<hgl/type/DataType.h>
#include<hgl/type/List.h>
#include<hgl/type/String.h>
#include<hgl/type/StrChar.h>
namespace hgl
{
namespace network
{
/**
* IP类型枚举
*/
enum IPType
{
iptNone=0,
iptV4,
iptV6,
iptEnd
};//enum IPType
inline IPType CheckIPType(const char *name)
{
if(!name)return(iptNone);
while(*name)
{
if(*name==':')return(iptV6);
if(*name=='.')return(iptV4);
++name;
}
return(iptNone);
}
struct IPSupport
{
uint family; ///<协议家族AF_INET,AF_INET6,AF_NETBIOS
uint socktype; ///<Socket类型SOCK_STREAM,SOCK_DGRAM,SOCK_RAW,SOCK_RDM,SOCK_SEQPACKET
uint protocol; ///<协议类型IPPROTO_TCP,IPPROTO_UDP,IPPROTO_SCTP
union
{
sockaddr_in ipv4;
sockaddr_in6 ipv6;
};
union
{
char ipv4str[INET_ADDRSTRLEN+1];
char ipv6str[INET6_ADDRSTRLEN+1];
};
};
int GetIPSupport(List<IPSupport> &); ///<取得本机IP支持列表
bool CheckIPSupport(const List<IPSupport> &ips_list,uint family,uint socktype,uint protocol);
bool CheckIPSupport(uint family,uint socktype,uint protocol);
inline bool CheckIPv4SupportTCP (){return CheckIPSupport(AF_INET,SOCK_STREAM, IPPROTO_TCP );}
inline bool CheckIPv4SupportUDP (){return CheckIPSupport(AF_INET,SOCK_DGRAM, IPPROTO_UDP );}
inline bool CheckIPv4SupportUDPLite (){return CheckIPSupport(AF_INET,SOCK_DGRAM, IPPROTO_UDPLITE );}
inline bool CheckIPv4SupportSCTP (){return CheckIPSupport(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP );}
inline bool CheckIPv6SupportTCP (){return CheckIPSupport(AF_INET6,SOCK_STREAM, IPPROTO_TCP );}
inline bool CheckIPv6SupportUDP (){return CheckIPSupport(AF_INET6,SOCK_DGRAM, IPPROTO_UDP );}
inline bool CheckIPv6SupportUDPLite (){return CheckIPSupport(AF_INET6,SOCK_DGRAM, IPPROTO_UDPLITE );}
inline bool CheckIPv6SupportSCTP (){return CheckIPSupport(AF_INET6,SOCK_SEQPACKET,IPPROTO_SCTP );}
/**
* IP地址类
*/
class IPAddress
{
protected:
int socktype;
int protocol;
const char *protocol_name;
void RefreshProtocolName();
public:
IPAddress()
{
socktype=0;
protocol=0;
protocol_name=nullptr;
}
IPAddress(int s,int p)
{
socktype=s;
protocol=p;
RefreshProtocolName();
}
virtual ~IPAddress()=default;
virtual const int GetFamily()const=0; ///<返回网络家族
const int GetSocketType()const{return socktype;} ///<返回Socket类型
const int GetProtocol()const{return protocol;} ///<返回协议类型
virtual const uint GetIPSize()const=0; ///<取得IP地址的长度
virtual const uint GetSockAddrInSize()const=0; ///<取得SockAddrIn变量长度
virtual const uint GetIPStringMaxSize()const=0; ///<取得IP字符串最大长度
virtual const bool IsBoradcast()const=0; ///<是否为广播
virtual const char *GetProtocolName()const{return protocol_name;} ///<取得协议名称
/**
* 设置IP地址
* @param _name 域名或地址字符串
* @param _port 端口号
* @param socktype Socket类型(可以为SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_RDM、SOCK_SEQPACKET等值),默认为所有类型。
* @param protocol 协议类型(可以为IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP),默认为所有类型。
*/
virtual bool Set(const char *_name,ushort _port,int socktype,int protocol)=0;
bool SetTCP (const char *_name,ushort _port){return Set(_name,_port,SOCK_STREAM, IPPROTO_TCP );}
bool SetUDP (const char *_name,ushort _port){return Set(_name,_port,SOCK_DGRAM, IPPROTO_UDP );}
bool SetUDPLite (const char *_name,ushort _port){return Set(_name,_port,SOCK_DGRAM, IPPROTO_UDPLITE );}
bool SetSCTP (const char *_name,ushort _port){return Set(_name,_port,SOCK_SEQPACKET, IPPROTO_SCTP );}
const bool IsTCP ()const{if(socktype!=SOCK_STREAM )return(false);if(protocol!=IPPROTO_TCP )return(false);return(true);}
const bool IsUDP ()const{if(socktype!=SOCK_DGRAM )return(false);if(protocol!=IPPROTO_UDP )return(false);return(true);}
const bool IsUDPLite ()const{if(socktype!=SOCK_DGRAM )return(false);if(protocol!=IPPROTO_UDPLITE )return(false);return(true);}
const bool IsSCTP ()const{if(socktype!=SOCK_SEQPACKET )return(false);if(protocol!=IPPROTO_SCTP )return(false);return(true);}
/**
* 设置一个仅有端口号的地址,一般用于服务器监听本机所有地址
*/
virtual void Set(ushort port)=0;
/**
* 绑定当前IP地址到一个socket上
* @param ThisSocket Socket号
* @param reuse 是否可以复用这个IP默认为true
*/
virtual bool Bind(int ThisSocket,int reuse=1)const=0;
/**
* 获取当前地址的主机名称
*/
virtual bool GetHostname(UTF8String &)const=0;
virtual sockaddr *GetSockAddr()=0;
virtual void *GetIP()=0;
/**
* 获取当前地址的IP信息
*/
virtual void GetIP(void *)=0;
/**
* 取得当前地址的端口号
*/
virtual const ushort GetPort()const=0;
/**
* 转换当前地址到一个可视字符串,字符串所需长度请使用GetIPStringMaxSize()获取
*/
virtual void ToString(u8char *,int)const=0;
/**
* 创建一个可视字符串地址需自行delete[]
*/
virtual u8char *CreateString()const
{
const int max_size=GetIPStringMaxSize();
u8char *ipstr=new u8char[max_size+1];
ToString(ipstr,max_size);
return ipstr;
}
/**
* 创建一个当前地址的副本
*/
virtual IPAddress *CreateCopy()const=0;
/**
* 创建一个空的IP地址副本
*/
virtual IPAddress *Create()const=0;
/**
* 与较与另一个IP地址是否一样
*/
virtual bool Comp(const IPAddress *)const=0;
};//class IPAddress
/**
* IPv4地址
*/
class IPv4Address:public IPAddress
{
sockaddr_in addr;
public:
IPv4Address(){hgl_zero(addr);}
IPv4Address(const uint32 _addr,ushort port,int _socktype,int _protocol):IPAddress(_socktype,_protocol)
{
Set(_addr,port);
}
IPv4Address(const char *name,ushort port,int _socktype,int _protocol)
{
Set(name,port,_socktype,_protocol);
}
IPv4Address(ushort port,int _socktype,int _protocol)
{
Set(nullptr,port,_socktype,_protocol);
}
IPv4Address(const IPv4Address *src)
{
hgl_cpy(addr,src->addr);
socktype=src->socktype;
protocol=src->protocol;
}
const int GetFamily()const override{return AF_INET;}
const uint GetIPSize()const override{return sizeof(in_addr);}
const uint GetSockAddrInSize()const override{return sizeof(sockaddr_in);}
const uint GetIPStringMaxSize()const override{return INET_ADDRSTRLEN+6;}
const bool IsBoradcast()const override{return(addr.sin_addr.s_addr==htonl(INADDR_BROADCAST));}
bool Set(const char *name,ushort port,int _socktype,int _protocol) override;
void Set(const uint32 _addr,ushort port)
{
hgl_zero(addr);
addr.sin_family =AF_INET;
addr.sin_addr.s_addr=_addr;
addr.sin_port =htons(port);
}
void Set(ushort port) override;
bool Bind(int ThisSocket,int reuse=1)const override;
bool GetHostname(UTF8String &)const override;
sockaddr *GetSockAddr()override{return (sockaddr *)&addr;}
void *GetIP() override {return &(addr.sin_addr);}
void GetIP(void *data) override { memcpy(data,&(addr.sin_addr),sizeof(in_addr)); }
const uint32 GetInt32IP()const{return addr.sin_addr.s_addr;}
const ushort GetPort()const override;
static void ToString(u8char *str,const int,const in_addr *);
static void ToString(u8char *str,const int,const sockaddr_in *);
void ToString(u8char *str,const int)const override;
static int GetDomainIPList(List<in_addr> &addr_list,const char *domain,int _socktype,int _protocol); ///<取得当指定域名的IPv4地址列表
static int GetLocalIPList(List<in_addr> &addr_list,int _socktype,int _protocol); ///<取得本机的IPv4地址列表
IPAddress *CreateCopy()const override{return(new IPv4Address(this));}
IPAddress *Create()const override{return(new IPv4Address());}
bool Comp(const IPAddress *ipa)const override;
};//class IPv4Address
/**
* IPv6地址
*/
class IPv6Address:public IPAddress
{
sockaddr_in6 addr;
public:
IPv6Address(){hgl_zero(addr);}
IPv6Address(const in6_addr *ip,ushort port,int _socktype,int _protocol):IPAddress(_socktype,_protocol)
{
hgl_zero(addr);
addr.sin6_family=AF_INET6;
memcpy(&(addr.sin6_addr),ip,sizeof(in6_addr));
addr.sin6_port=htons(port);
}
IPv6Address(const char *name,ushort port,int _socktype,int _protocol)
{
Set(name,port,_socktype,_protocol);
}
IPv6Address(ushort port,int _socktype,int _protocol)
{
Set(nullptr,port,_socktype,_protocol);
}
IPv6Address(const IPv6Address *src)
{
hgl_cpy(addr,src->addr);
socktype=src->socktype;
protocol=src->protocol;
}
const int GetFamily()const override{return AF_INET6;}
const uint GetIPSize()const override{return sizeof(in6_addr);}
const uint GetSockAddrInSize()const override{return sizeof(sockaddr_in6);}
const uint GetIPStringMaxSize()const override{return INET6_ADDRSTRLEN+6;}
const bool IsBoradcast()const override{return(false);}
bool Set(const char *name,ushort port,int _socktype,int _protocol) override;
void Set(ushort port) override;
bool Bind(int ThisSocket,int reuse=1)const override;
bool GetHostname(UTF8String &)const override;
sockaddr *GetSockAddr() override{return (sockaddr *)&addr;}
void *GetIP() override {return &(addr.sin6_addr);}
void GetIP(void *data) override{memcpy(data,&(addr.sin6_addr),sizeof(in6_addr));}
const ushort GetPort()const override;
static void ToString(u8char *str,const int,const in6_addr *);
static void ToString(u8char *str,const int,const sockaddr_in6 *);
void ToString(u8char *str,const int)const override;
static int GetDomainIPList(List<in6_addr> &addr_list,const char *domain,int _socktype,int _protocol); ///<取得指定域名的IPv6地址列表
static int GetLocalIPList(List<in6_addr> &addr_list,int _socktype,int _protocol); ///<取得本机的IPv6地址列表
IPAddress *CreateCopy()const override{return(new IPv6Address(this));}
IPAddress *Create()const override{return(new IPv6Address());}
bool Comp(const IPAddress *ipa)const override;
};//class IPv6Address
inline IPv4Address *CreateIPv4TCP (const char *name,ushort port){return(new IPv4Address(name,port,SOCK_STREAM, IPPROTO_TCP));}
inline IPv6Address *CreateIPv6TCP (const char *name,ushort port){return(new IPv6Address(name,port,SOCK_STREAM, IPPROTO_TCP));}
inline IPv4Address *CreateIPv4UDP (const char *name,ushort port){return(new IPv4Address(name,port,SOCK_DGRAM, IPPROTO_UDP));}
inline IPv6Address *CreateIPv6UDP (const char *name,ushort port){return(new IPv6Address(name,port,SOCK_DGRAM, IPPROTO_UDP));}
inline IPv4Address *CreateIPv4UDPLite (const char *name,ushort port){return(new IPv4Address(name,port,SOCK_DGRAM, IPPROTO_UDPLITE));}
inline IPv6Address *CreateIPv6UDPLite (const char *name,ushort port){return(new IPv6Address(name,port,SOCK_DGRAM, IPPROTO_UDPLITE));}
inline IPv4Address *CreateIPv4SCTP (const char *name,ushort port){return(new IPv4Address(name,port,SOCK_SEQPACKET, IPPROTO_SCTP));}
inline IPv6Address *CreateIPv6SCTP (const char *name,ushort port){return(new IPv6Address(name,port,SOCK_SEQPACKET, IPPROTO_SCTP));}
inline IPv4Address *CreateIPv4TCP (const uint32 &ip,ushort port){return(new IPv4Address(ip,port,SOCK_STREAM, IPPROTO_TCP));}
inline IPv4Address *CreateIPv4UDP (const uint32 &ip,ushort port){return(new IPv4Address(ip,port,SOCK_DGRAM, IPPROTO_UDP));}
inline IPv4Address *CreateIPv4UDPLite (const uint32 &ip,ushort port){return(new IPv4Address(ip,port,SOCK_DGRAM, IPPROTO_UDPLITE));}
inline IPv4Address *CreateIPv4SCTP (const uint32 &ip,ushort port){return(new IPv4Address(ip,port,SOCK_SEQPACKET, IPPROTO_SCTP));}
inline IPv6Address *CreateIPv6TCP (const in6_addr *ip,ushort port){return(new IPv6Address(ip,port,SOCK_STREAM, IPPROTO_TCP));}
inline IPv6Address *CreateIPv6UDP (const in6_addr *ip,ushort port){return(new IPv6Address(ip,port,SOCK_DGRAM, IPPROTO_UDP));}
inline IPv6Address *CreateIPv6UDPLite (const in6_addr *ip,ushort port){return(new IPv6Address(ip,port,SOCK_DGRAM, IPPROTO_UDPLITE));}
inline IPv6Address *CreateIPv6SCTP (const in6_addr *ip,ushort port){return(new IPv6Address(ip,port,SOCK_SEQPACKET, IPPROTO_SCTP));}
inline IPv4Address *CreateIPv4TCP (ushort port){return(new IPv4Address(port,SOCK_STREAM, IPPROTO_TCP));}
inline IPv6Address *CreateIPv6TCP (ushort port){return(new IPv6Address(port,SOCK_STREAM, IPPROTO_TCP));}
inline IPv4Address *CreateIPv4UDP (ushort port){return(new IPv4Address(port,SOCK_DGRAM, IPPROTO_UDP));}
inline IPv6Address *CreateIPv6UDP (ushort port){return(new IPv6Address(port,SOCK_DGRAM, IPPROTO_UDP));}
inline IPv4Address *CreateIPv4UDPLite (ushort port){return(new IPv4Address(port,SOCK_DGRAM, IPPROTO_UDPLITE));}
inline IPv6Address *CreateIPv6UDPLite (ushort port){return(new IPv6Address(port,SOCK_DGRAM, IPPROTO_UDPLITE));}
inline IPv4Address *CreateIPv4SCTP (ushort port){return(new IPv4Address(port,SOCK_SEQPACKET, IPPROTO_SCTP));}
inline IPv6Address *CreateIPv6SCTP (ushort port){return(new IPv6Address(port,SOCK_SEQPACKET, IPPROTO_SCTP));}
inline IPv4Address *CreateIPv4UDPBoradcast (ushort port){return(new IPv4Address(htonl(INADDR_BROADCAST),port,SOCK_DGRAM, IPPROTO_UDP));}
inline IPv4Address *CreateIPv4UDPLiteBoradcast (ushort port){return(new IPv4Address(htonl(INADDR_BROADCAST),port,SOCK_DGRAM, IPPROTO_UDPLITE));}
}//namespace network
}//namespace hgl
#endif//HGL_NETWORK_IP_TOOL_INCLUDE