* Factored out a BNetworkAddressResolver from BNetworkAddress, that also allows
to iterate over all possible addresses, as suggested privately by Rene. * Added flags to the resolving methods that allow more control over the addresses returned. * Added setters to BNetworkAddress that accept a service name instead of port number, renamed PortName() to ServiceName(). * Made the sockaddr* cast operators return a const sockaddr as it was supposed to be, although I should probably add non-const ones as well. * This also simplified the code somewhat. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38039 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
e05f4ded2d
commit
836c43f2b8
@ -12,16 +12,21 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include <Archivable.h>
|
#include <Archivable.h>
|
||||||
|
#include <NetworkAddressResolver.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
class BNetworkAddress : public BArchivable {
|
class BNetworkAddress : public BArchivable {
|
||||||
public:
|
public:
|
||||||
BNetworkAddress();
|
BNetworkAddress();
|
||||||
BNetworkAddress(int family,
|
|
||||||
const char* address, uint16 port = 0);
|
|
||||||
BNetworkAddress(const char* address,
|
BNetworkAddress(const char* address,
|
||||||
uint16 port = 0);
|
uint16 port = 0, uint32 flags = 0);
|
||||||
|
BNetworkAddress(const char* address,
|
||||||
|
const char* service, uint32 flags = 0);
|
||||||
|
BNetworkAddress(int family, const char* address,
|
||||||
|
uint16 port = 0, uint32 flags = 0);
|
||||||
|
BNetworkAddress(int family, const char* address,
|
||||||
|
const char* service, uint32 flags = 0);
|
||||||
BNetworkAddress(const sockaddr& address);
|
BNetworkAddress(const sockaddr& address);
|
||||||
BNetworkAddress(
|
BNetworkAddress(
|
||||||
const sockaddr_storage& address);
|
const sockaddr_storage& address);
|
||||||
@ -38,10 +43,16 @@ public:
|
|||||||
|
|
||||||
void Unset();
|
void Unset();
|
||||||
|
|
||||||
|
status_t SetTo(const char* address, uint16 port = 0,
|
||||||
|
uint32 flags = 0);
|
||||||
|
status_t SetTo(const char* address, const char* service,
|
||||||
|
uint32 flags = 0);
|
||||||
status_t SetTo(int family, const char* address,
|
status_t SetTo(int family, const char* address,
|
||||||
uint16 port = 0);
|
uint16 port = 0, uint32 flags = 0);
|
||||||
status_t SetTo(const char* address, uint16 port = 0);
|
status_t SetTo(int family, const char* address,
|
||||||
|
const char* service, uint32 flags = 0);
|
||||||
void SetTo(const sockaddr& address);
|
void SetTo(const sockaddr& address);
|
||||||
|
void SetTo(const sockaddr& address, size_t length);
|
||||||
void SetTo(const sockaddr_storage& address);
|
void SetTo(const sockaddr_storage& address);
|
||||||
void SetTo(const sockaddr_in& address);
|
void SetTo(const sockaddr_in& address);
|
||||||
void SetTo(const sockaddr_in6& address);
|
void SetTo(const sockaddr_in6& address);
|
||||||
@ -56,6 +67,7 @@ public:
|
|||||||
status_t SetToMask(int family, uint32 prefixLength);
|
status_t SetToMask(int family, uint32 prefixLength);
|
||||||
status_t SetToWildcard(int family);
|
status_t SetToWildcard(int family);
|
||||||
void SetPort(uint16 port);
|
void SetPort(uint16 port);
|
||||||
|
status_t SetPort(const char* service);
|
||||||
|
|
||||||
void SetToLinkLevel(uint8* address, size_t length);
|
void SetToLinkLevel(uint8* address, size_t length);
|
||||||
void SetToLinkLevel(const char* name);
|
void SetToLinkLevel(const char* name);
|
||||||
@ -97,7 +109,7 @@ public:
|
|||||||
|
|
||||||
BString ToString(bool includePort = true) const;
|
BString ToString(bool includePort = true) const;
|
||||||
BString HostName() const;
|
BString HostName() const;
|
||||||
BString PortName() const;
|
BString ServiceName() const;
|
||||||
|
|
||||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||||
static BArchivable* Instantiate(BMessage* archive);
|
static BArchivable* Instantiate(BMessage* archive);
|
||||||
@ -111,8 +123,8 @@ public:
|
|||||||
bool operator!=(const BNetworkAddress& other) const;
|
bool operator!=(const BNetworkAddress& other) const;
|
||||||
bool operator<(const BNetworkAddress& other) const;
|
bool operator<(const BNetworkAddress& other) const;
|
||||||
|
|
||||||
operator sockaddr*() const;
|
operator const sockaddr*() const;
|
||||||
operator sockaddr&() const;
|
operator const sockaddr&() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sockaddr_storage fAddress;
|
sockaddr_storage fAddress;
|
||||||
|
62
headers/os/net/NetworkAddressResolver.h
Normal file
62
headers/os/net/NetworkAddressResolver.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _NETWORK_ADDRESS_RESOLVER_H
|
||||||
|
#define _NETWORK_ADDRESS_RESOLVER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BNetworkAddress;
|
||||||
|
struct addrinfo;
|
||||||
|
|
||||||
|
|
||||||
|
// flags for name resolution
|
||||||
|
enum {
|
||||||
|
B_NO_ADDRESS_RESOLUTION = 0x0001,
|
||||||
|
B_UNCONFIGURED_ADDRESS_FAMILIES = 0x0002,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BNetworkAddressResolver {
|
||||||
|
public:
|
||||||
|
BNetworkAddressResolver();
|
||||||
|
BNetworkAddressResolver(const char* address,
|
||||||
|
uint16 port = 0, uint32 flags = 0);
|
||||||
|
BNetworkAddressResolver(const char* address,
|
||||||
|
const char* service, uint32 flags = 0);
|
||||||
|
BNetworkAddressResolver(int family,
|
||||||
|
const char* address, uint16 port = 0,
|
||||||
|
uint32 flags = 0);
|
||||||
|
BNetworkAddressResolver(int family,
|
||||||
|
const char* address, const char* service,
|
||||||
|
uint32 flags = 0);
|
||||||
|
~BNetworkAddressResolver();
|
||||||
|
|
||||||
|
status_t InitCheck() const;
|
||||||
|
|
||||||
|
void Unset();
|
||||||
|
|
||||||
|
status_t SetTo(const char* address, uint16 port = 0,
|
||||||
|
uint32 flags = 0);
|
||||||
|
status_t SetTo(const char* address, const char* service,
|
||||||
|
uint32 flags = 0);
|
||||||
|
status_t SetTo(int family, const char* address,
|
||||||
|
uint16 port = 0, uint32 flags = 0);
|
||||||
|
status_t SetTo(int family, const char* address,
|
||||||
|
const char* service, uint32 flags = 0);
|
||||||
|
|
||||||
|
status_t GetNextAddress(uint32* cookie,
|
||||||
|
BNetworkAddress& address) const;
|
||||||
|
status_t GetNextAddress(int family, uint32* cookie,
|
||||||
|
BNetworkAddress& address) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
addrinfo* fInfo;
|
||||||
|
status_t fStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _NETWORK_ADDRESS_RESOLVER_H
|
@ -11,6 +11,7 @@ SharedLibrary libbnetapi.so :
|
|||||||
NetDebug.cpp
|
NetDebug.cpp
|
||||||
|
|
||||||
NetworkAddress.cpp
|
NetworkAddress.cpp
|
||||||
|
NetworkAddressResolver.cpp
|
||||||
NetworkInterface.cpp
|
NetworkInterface.cpp
|
||||||
NetworkRoster.cpp
|
NetworkRoster.cpp
|
||||||
|
|
||||||
|
@ -6,96 +6,40 @@
|
|||||||
|
|
||||||
#include <NetworkAddress.h>
|
#include <NetworkAddress.h>
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
|
||||||
#include <NetworkInterface.h>
|
#include <NetworkInterface.h>
|
||||||
#include <NetworkRoster.h>
|
#include <NetworkRoster.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/route.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <stdlib.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
|
|
||||||
|
|
||||||
static bool
|
BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags)
|
||||||
strip_port(BString& host, BString& port)
|
|
||||||
{
|
{
|
||||||
int32 separator = host.FindFirst(':');
|
SetTo(host, port, flags);
|
||||||
if (separator != -1) {
|
|
||||||
// looks like there is a port
|
|
||||||
host.CopyInto(port, separator + 1, -1);
|
|
||||||
host.Truncate(separator);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
BNetworkAddress::BNetworkAddress(const char* host, const char* service,
|
||||||
resolve_address(int family, const char* host, const char* port,
|
uint32 flags)
|
||||||
int type, sockaddr_storage& address)
|
|
||||||
{
|
{
|
||||||
addrinfo hint = {0};
|
SetTo(host, service, flags);
|
||||||
hint.ai_family = family;
|
|
||||||
hint.ai_socktype = type;
|
|
||||||
hint.ai_protocol = 0;
|
|
||||||
|
|
||||||
if (host == NULL && port == NULL) {
|
|
||||||
port = "0";
|
|
||||||
hint.ai_flags = AI_PASSIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
addrinfo* info;
|
|
||||||
int status = getaddrinfo(host, port, &hint, &info);
|
|
||||||
if (status != 0) {
|
|
||||||
// TODO: improve error reporting
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool foundAddress = false;
|
|
||||||
|
|
||||||
if (family == AF_UNSPEC) {
|
|
||||||
// Prefer IPv6 addresses over IPv4 addresses
|
|
||||||
|
|
||||||
for (const addrinfo* next = info; next != NULL; next = next->ai_next) {
|
|
||||||
if (next->ai_family == AF_INET6) {
|
|
||||||
memcpy(&address, next->ai_addr, next->ai_addrlen);
|
|
||||||
foundAddress = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundAddress) {
|
|
||||||
// No preferred, or no IPv6 address found, just take the first one
|
|
||||||
// that works
|
|
||||||
memcpy(&address, info->ai_addr, info->ai_addrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(info);
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
|
||||||
|
uint32 flags)
|
||||||
|
|
||||||
BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port)
|
|
||||||
{
|
{
|
||||||
SetTo(family, host, port);
|
SetTo(family, host, port, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BNetworkAddress::BNetworkAddress(const char* host, uint16 port)
|
BNetworkAddress::BNetworkAddress(int family, const char* host,
|
||||||
|
const char* service, uint32 flags)
|
||||||
{
|
{
|
||||||
SetTo(host, port);
|
SetTo(family, host, service, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -184,119 +128,69 @@ BNetworkAddress::Unset()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BNetworkAddress::SetTo(int family, const char* host, uint16 port)
|
BNetworkAddress::SetTo(const char* host, uint16 port, uint32 flags)
|
||||||
{
|
{
|
||||||
// Check if the address contains a port
|
BNetworkAddressResolver resolver;
|
||||||
|
status_t status = resolver.SetTo(host, port, flags);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
BString hostAddress(host);
|
// Prefer IPv6 addresses
|
||||||
|
|
||||||
BString portString;
|
uint32 cookie = 0;
|
||||||
if (strip_port(hostAddress, portString) && port == 0)
|
status = resolver.GetNextAddress(AF_INET6, &cookie, *this);
|
||||||
port = strtoul(portString.String(), NULL, 0);
|
if (status == B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
// Resolve address
|
cookie = 0;
|
||||||
|
return resolver.GetNextAddress(&cookie, *this);
|
||||||
memset(&fAddress, 0, sizeof(sockaddr_storage));
|
|
||||||
fAddress.ss_family = family;
|
|
||||||
|
|
||||||
if (host != NULL) {
|
|
||||||
switch (family) {
|
|
||||||
case AF_INET:
|
|
||||||
{
|
|
||||||
hostent* server = gethostbyname(hostAddress.String());
|
|
||||||
if (server == NULL)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
struct sockaddr_in& address = (sockaddr_in&)fAddress;
|
|
||||||
address.sin_port = htons(port);
|
|
||||||
address.sin_addr.s_addr = *(in_addr_t*)server->h_addr_list[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
fStatus = resolve_address(family, host, "0", 0, fAddress);
|
|
||||||
if (fStatus != B_OK)
|
|
||||||
return fStatus;
|
|
||||||
|
|
||||||
if (family == AF_INET6) {
|
|
||||||
struct sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
|
||||||
address.sin6_port = htons(port);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (fAddress.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
{
|
|
||||||
struct sockaddr_in& address = (sockaddr_in&)fAddress;
|
|
||||||
address.sin_port = htons(port);
|
|
||||||
address.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AF_INET6:
|
|
||||||
{
|
|
||||||
struct sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
|
||||||
address.sin6_port = htons(port);
|
|
||||||
address.sin6_addr = in6addr_any;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fStatus = B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BNetworkAddress::SetTo(const char* host, uint16 port)
|
BNetworkAddress::SetTo(const char* host, const char* service, uint32 flags)
|
||||||
{
|
{
|
||||||
// Check if the address contains a port
|
BNetworkAddressResolver resolver;
|
||||||
|
status_t status = resolver.SetTo(host, service, flags);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
BString hostAddress(host);
|
// Prefer IPv6 addresses
|
||||||
|
|
||||||
BString portString;
|
uint32 cookie = 0;
|
||||||
strip_port(hostAddress, portString);
|
status = resolver.GetNextAddress(AF_INET6, &cookie, *this);
|
||||||
|
if (status == B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
// Resolve address
|
cookie = 0;
|
||||||
|
return resolver.GetNextAddress(&cookie, *this);
|
||||||
|
}
|
||||||
|
|
||||||
memset(&fAddress, 0, sizeof(sockaddr_storage));
|
|
||||||
|
|
||||||
fStatus = resolve_address(AF_UNSPEC,
|
status_t
|
||||||
host != NULL ? hostAddress.String() : NULL,
|
BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags)
|
||||||
portString.Length() == 0 ? NULL : portString.String(), 0, fAddress);
|
{
|
||||||
if (fStatus != B_OK)
|
BNetworkAddressResolver resolver;
|
||||||
return fStatus;
|
status_t status = resolver.SetTo(family, host, port, flags);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
// Set port if specified separately
|
uint32 cookie = 0;
|
||||||
|
return resolver.GetNextAddress(&cookie, *this);
|
||||||
|
}
|
||||||
|
|
||||||
switch (fAddress.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
{
|
|
||||||
struct sockaddr_in& address = (sockaddr_in&)fAddress;
|
|
||||||
if (address.sin_port == 0)
|
|
||||||
address.sin_port = htons(port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AF_INET6:
|
status_t
|
||||||
{
|
BNetworkAddress::SetTo(int family, const char* host, const char* service,
|
||||||
struct sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
uint32 flags)
|
||||||
if (address.sin6_port == 0)
|
{
|
||||||
address.sin6_port = htons(port);
|
BNetworkAddressResolver resolver;
|
||||||
break;
|
status_t status = resolver.SetTo(family, host, service, flags);
|
||||||
}
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
default:
|
uint32 cookie = 0;
|
||||||
break;
|
return resolver.GetNextAddress(&cookie, *this);
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -317,8 +211,24 @@ BNetworkAddress::SetTo(const sockaddr& address)
|
|||||||
length = sizeof(sockaddr_in6);
|
length = sizeof(sockaddr_in6);
|
||||||
break;
|
break;
|
||||||
case AF_LINK:
|
case AF_LINK:
|
||||||
length = sizeof(sockaddr_dl);
|
{
|
||||||
|
sockaddr_dl& link = (sockaddr_dl&)address;
|
||||||
|
length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen
|
||||||
|
+ link.sdl_nlen + link.sdl_slen;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetTo(address, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BNetworkAddress::SetTo(const sockaddr& address, size_t length)
|
||||||
|
{
|
||||||
|
if (address.sa_family == AF_UNSPEC || length == 0) {
|
||||||
|
Unset();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&fAddress, &address, length);
|
memcpy(&fAddress, &address, length);
|
||||||
@ -935,7 +845,7 @@ BNetworkAddress::HostName() const
|
|||||||
|
|
||||||
|
|
||||||
BString
|
BString
|
||||||
BNetworkAddress::PortName() const
|
BNetworkAddress::ServiceName() const
|
||||||
{
|
{
|
||||||
// TODO: implement service lookup
|
// TODO: implement service lookup
|
||||||
BString portName;
|
BString portName;
|
||||||
@ -1062,7 +972,13 @@ BNetworkAddress::operator<(const BNetworkAddress& other) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BNetworkAddress::operator sockaddr*() const
|
BNetworkAddress::operator const sockaddr*() const
|
||||||
{
|
{
|
||||||
return (sockaddr*)&fAddress;
|
return (const sockaddr*)&fAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BNetworkAddress::operator const sockaddr&() const
|
||||||
|
{
|
||||||
|
return (const sockaddr&)fAddress;
|
||||||
}
|
}
|
||||||
|
221
src/kits/network/libnetapi/NetworkAddressResolver.cpp
Normal file
221
src/kits/network/libnetapi/NetworkAddressResolver.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <NetworkAddressResolver.h>
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include <NetworkAddress.h>
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
strip_port(BString& host, BString& port)
|
||||||
|
{
|
||||||
|
int32 separator = host.FindFirst(':');
|
||||||
|
if (separator != -1) {
|
||||||
|
// looks like there is a port
|
||||||
|
host.CopyInto(port, separator + 1, -1);
|
||||||
|
host.Truncate(separator);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
BNetworkAddressResolver::BNetworkAddressResolver()
|
||||||
|
:
|
||||||
|
fInfo(NULL),
|
||||||
|
fStatus(B_NO_INIT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BNetworkAddressResolver::BNetworkAddressResolver(const char* address,
|
||||||
|
uint16 port, uint32 flags)
|
||||||
|
:
|
||||||
|
fInfo(NULL),
|
||||||
|
fStatus(B_NO_INIT)
|
||||||
|
{
|
||||||
|
SetTo(address, port, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
BNetworkAddressResolver::BNetworkAddressResolver(const char* address,
|
||||||
|
const char* service, uint32 flags)
|
||||||
|
:
|
||||||
|
fInfo(NULL),
|
||||||
|
fStatus(B_NO_INIT)
|
||||||
|
{
|
||||||
|
SetTo(address, service, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BNetworkAddressResolver::BNetworkAddressResolver(int family,
|
||||||
|
const char* address, uint16 port, uint32 flags)
|
||||||
|
:
|
||||||
|
fInfo(NULL),
|
||||||
|
fStatus(B_NO_INIT)
|
||||||
|
{
|
||||||
|
SetTo(family, address, port, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BNetworkAddressResolver::BNetworkAddressResolver(int family,
|
||||||
|
const char* address, const char* service, uint32 flags)
|
||||||
|
:
|
||||||
|
fInfo(NULL),
|
||||||
|
fStatus(B_NO_INIT)
|
||||||
|
{
|
||||||
|
SetTo(family, address, service, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BNetworkAddressResolver::~BNetworkAddressResolver()
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkAddressResolver::InitCheck() const
|
||||||
|
{
|
||||||
|
return fStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BNetworkAddressResolver::Unset()
|
||||||
|
{
|
||||||
|
if (fInfo != NULL) {
|
||||||
|
freeaddrinfo(fInfo);
|
||||||
|
fInfo = NULL;
|
||||||
|
}
|
||||||
|
fStatus = B_NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkAddressResolver::SetTo(const char* address, uint16 port, uint32 flags)
|
||||||
|
{
|
||||||
|
return SetTo(AF_UNSPEC, address, port, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkAddressResolver::SetTo(const char* address, const char* service,
|
||||||
|
uint32 flags)
|
||||||
|
{
|
||||||
|
return SetTo(AF_UNSPEC, address, service, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkAddressResolver::SetTo(int family, const char* address, uint16 port,
|
||||||
|
uint32 flags)
|
||||||
|
{
|
||||||
|
BString service;
|
||||||
|
service << port;
|
||||||
|
|
||||||
|
return SetTo(family, address, port != 0 ? service.String() : NULL, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkAddressResolver::SetTo(int family, const char* host,
|
||||||
|
const char* service, uint32 flags)
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
|
||||||
|
// Check if the address contains a port
|
||||||
|
|
||||||
|
BString hostString(host);
|
||||||
|
|
||||||
|
BString portString;
|
||||||
|
if (!strip_port(hostString, portString) && service != NULL)
|
||||||
|
portString = service;
|
||||||
|
|
||||||
|
// Resolve address
|
||||||
|
|
||||||
|
addrinfo hint = {0};
|
||||||
|
hint.ai_family = family;
|
||||||
|
if ((flags & B_UNCONFIGURED_ADDRESS_FAMILIES) == 0)
|
||||||
|
hint.ai_flags |= AI_ADDRCONFIG;
|
||||||
|
if ((flags & B_NO_ADDRESS_RESOLUTION) != 0)
|
||||||
|
hint.ai_flags |= AI_NUMERICHOST;
|
||||||
|
|
||||||
|
if (host == NULL && portString.Length() == 0) {
|
||||||
|
portString = "0";
|
||||||
|
hint.ai_flags |= AI_PASSIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = getaddrinfo(host != NULL ? hostString.String() : NULL,
|
||||||
|
portString.Length() != 0 ? portString.String() : NULL, &hint, &fInfo);
|
||||||
|
if (status != 0) {
|
||||||
|
// TODO: improve error reporting
|
||||||
|
return fStatus = B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fStatus = B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkAddressResolver::GetNextAddress(uint32* cookie,
|
||||||
|
BNetworkAddress& address) const
|
||||||
|
{
|
||||||
|
if (fStatus != B_OK)
|
||||||
|
return fStatus;
|
||||||
|
|
||||||
|
// Skip previous info entries
|
||||||
|
|
||||||
|
addrinfo* info = fInfo;
|
||||||
|
int32 first = *cookie;
|
||||||
|
for (int32 index = 0; index < first && info != NULL; index++) {
|
||||||
|
info = info->ai_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// Return current
|
||||||
|
|
||||||
|
address.SetTo(*info->ai_addr, info->ai_addrlen);
|
||||||
|
(*cookie)++;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkAddressResolver::GetNextAddress(int family, uint32* cookie,
|
||||||
|
BNetworkAddress& address) const
|
||||||
|
{
|
||||||
|
if (fStatus != B_OK)
|
||||||
|
return fStatus;
|
||||||
|
|
||||||
|
// Skip previous info entries, and those that have a non-matching family
|
||||||
|
|
||||||
|
addrinfo* info = fInfo;
|
||||||
|
int32 first = *cookie;
|
||||||
|
for (int32 index = 0; index < first && info != NULL; index++) {
|
||||||
|
while (info != NULL && info->ai_family != family)
|
||||||
|
info = info->ai_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// Return current
|
||||||
|
|
||||||
|
address.SetTo(*info->ai_addr, info->ai_addrlen);
|
||||||
|
(*cookie)++;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user