* 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 <Archivable.h>
|
||||
#include <NetworkAddressResolver.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class BNetworkAddress : public BArchivable {
|
||||
public:
|
||||
BNetworkAddress();
|
||||
BNetworkAddress(int family,
|
||||
const char* address, uint16 port = 0);
|
||||
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_storage& address);
|
||||
@ -38,10 +43,16 @@ public:
|
||||
|
||||
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);
|
||||
status_t SetTo(const char* address, uint16 port = 0);
|
||||
uint16 port = 0, uint32 flags = 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, size_t length);
|
||||
void SetTo(const sockaddr_storage& address);
|
||||
void SetTo(const sockaddr_in& address);
|
||||
void SetTo(const sockaddr_in6& address);
|
||||
@ -56,6 +67,7 @@ public:
|
||||
status_t SetToMask(int family, uint32 prefixLength);
|
||||
status_t SetToWildcard(int family);
|
||||
void SetPort(uint16 port);
|
||||
status_t SetPort(const char* service);
|
||||
|
||||
void SetToLinkLevel(uint8* address, size_t length);
|
||||
void SetToLinkLevel(const char* name);
|
||||
@ -97,7 +109,7 @@ public:
|
||||
|
||||
BString ToString(bool includePort = true) const;
|
||||
BString HostName() const;
|
||||
BString PortName() const;
|
||||
BString ServiceName() const;
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
static BArchivable* Instantiate(BMessage* archive);
|
||||
@ -111,8 +123,8 @@ public:
|
||||
bool operator!=(const BNetworkAddress& other) const;
|
||||
bool operator<(const BNetworkAddress& other) const;
|
||||
|
||||
operator sockaddr*() const;
|
||||
operator sockaddr&() const;
|
||||
operator const sockaddr*() const;
|
||||
operator const sockaddr&() const;
|
||||
|
||||
private:
|
||||
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
|
||||
|
||||
NetworkAddress.cpp
|
||||
NetworkAddressResolver.cpp
|
||||
NetworkInterface.cpp
|
||||
NetworkRoster.cpp
|
||||
|
||||
|
@ -6,96 +6,40 @@
|
||||
|
||||
#include <NetworkAddress.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <NetworkInterface.h>
|
||||
#include <NetworkRoster.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
|
||||
static bool
|
||||
strip_port(BString& host, BString& port)
|
||||
BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags)
|
||||
{
|
||||
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;
|
||||
SetTo(host, port, flags);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
resolve_address(int family, const char* host, const char* port,
|
||||
int type, sockaddr_storage& address)
|
||||
BNetworkAddress::BNetworkAddress(const char* host, const char* service,
|
||||
uint32 flags)
|
||||
{
|
||||
addrinfo hint = {0};
|
||||
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;
|
||||
SetTo(host, service, flags);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port)
|
||||
BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
|
||||
uint32 flags)
|
||||
{
|
||||
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
|
||||
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;
|
||||
if (strip_port(hostAddress, portString) && port == 0)
|
||||
port = strtoul(portString.String(), NULL, 0);
|
||||
uint32 cookie = 0;
|
||||
status = resolver.GetNextAddress(AF_INET6, &cookie, *this);
|
||||
if (status == B_OK)
|
||||
return B_OK;
|
||||
|
||||
// Resolve address
|
||||
|
||||
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;
|
||||
cookie = 0;
|
||||
return resolver.GetNextAddress(&cookie, *this);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
strip_port(hostAddress, portString);
|
||||
uint32 cookie = 0;
|
||||
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,
|
||||
host != NULL ? hostAddress.String() : NULL,
|
||||
portString.Length() == 0 ? NULL : portString.String(), 0, fAddress);
|
||||
if (fStatus != B_OK)
|
||||
return fStatus;
|
||||
status_t
|
||||
BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags)
|
||||
{
|
||||
BNetworkAddressResolver resolver;
|
||||
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:
|
||||
{
|
||||
struct sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
||||
if (address.sin6_port == 0)
|
||||
address.sin6_port = htons(port);
|
||||
break;
|
||||
}
|
||||
status_t
|
||||
BNetworkAddress::SetTo(int family, const char* host, const char* service,
|
||||
uint32 flags)
|
||||
{
|
||||
BNetworkAddressResolver resolver;
|
||||
status_t status = resolver.SetTo(family, host, service, flags);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
uint32 cookie = 0;
|
||||
return resolver.GetNextAddress(&cookie, *this);
|
||||
}
|
||||
|
||||
|
||||
@ -317,8 +211,24 @@ BNetworkAddress::SetTo(const sockaddr& address)
|
||||
length = sizeof(sockaddr_in6);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@ -935,7 +845,7 @@ BNetworkAddress::HostName() const
|
||||
|
||||
|
||||
BString
|
||||
BNetworkAddress::PortName() const
|
||||
BNetworkAddress::ServiceName() const
|
||||
{
|
||||
// TODO: implement service lookup
|
||||
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