[haiku-commits] r38039 - in haiku/trunk: headers/os/net src/kits/network/libnetapi

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 12 Aug 2010 13:27:14 +0200 (CEST)

Author: axeld
Date: 2010-08-12 13:27:14 +0200 (Thu, 12 Aug 2010)
New Revision: 38039
Changeset: http://dev.haiku-os.org/changeset/38039

Added:
   haiku/trunk/headers/os/net/NetworkAddressResolver.h
   haiku/trunk/src/kits/network/libnetapi/NetworkAddressResolver.cpp
Modified:
   haiku/trunk/headers/os/net/NetworkAddress.h
   haiku/trunk/src/kits/network/libnetapi/Jamfile
   haiku/trunk/src/kits/network/libnetapi/NetworkAddress.cpp
Log:
* 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.


Modified: haiku/trunk/headers/os/net/NetworkAddress.h
===================================================================
--- haiku/trunk/headers/os/net/NetworkAddress.h 2010-08-12 11:26:25 UTC (rev 
38038)
+++ haiku/trunk/headers/os/net/NetworkAddress.h 2010-08-12 11:27:14 UTC (rev 
38039)
@@ -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 @@
 
                        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 @@
                        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 @@
 
                        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 @@
                        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;

Added: haiku/trunk/headers/os/net/NetworkAddressResolver.h
===================================================================
--- haiku/trunk/headers/os/net/NetworkAddressResolver.h                         
(rev 0)
+++ haiku/trunk/headers/os/net/NetworkAddressResolver.h 2010-08-12 11:27:14 UTC 
(rev 38039)
@@ -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

Modified: haiku/trunk/src/kits/network/libnetapi/Jamfile
===================================================================
--- haiku/trunk/src/kits/network/libnetapi/Jamfile      2010-08-12 11:26:25 UTC 
(rev 38038)
+++ haiku/trunk/src/kits/network/libnetapi/Jamfile      2010-08-12 11:27:14 UTC 
(rev 38039)
@@ -11,6 +11,7 @@
        NetDebug.cpp
 
        NetworkAddress.cpp
+       NetworkAddressResolver.cpp
        NetworkInterface.cpp
        NetworkRoster.cpp
 

Modified: haiku/trunk/src/kits/network/libnetapi/NetworkAddress.cpp
===================================================================
--- haiku/trunk/src/kits/network/libnetapi/NetworkAddress.cpp   2010-08-12 
11:26:25 UTC (rev 38038)
+++ haiku/trunk/src/kits/network/libnetapi/NetworkAddress.cpp   2010-08-12 
11:27:14 UTC (rev 38039)
@@ -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 @@
 
 
 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
+       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;
+status_t
+BNetworkAddress::SetTo(const char* host, const char* service, uint32 flags)
+{
+       BNetworkAddressResolver resolver;
+       status_t status = resolver.SetTo(host, service, flags);
+       if (status != B_OK)
+               return status;
 
-                               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;
+       // Prefer IPv6 addresses
 
-                               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;
-                       }
+       uint32 cookie = 0;
+       status = resolver.GetNextAddress(AF_INET6, &cookie, *this);
+       if (status == B_OK)
+               return B_OK;
 
-                       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(int family, const char* host, uint16 port, uint32 flags)
 {
-       // Check if the address contains a port
+       BNetworkAddressResolver resolver;
+       status_t status = resolver.SetTo(family, host, port, flags);
+       if (status != B_OK)
+               return status;
 
-       BString hostAddress(host);
+       uint32 cookie = 0;
+       return resolver.GetNextAddress(&cookie, *this);
+}
 
-       BString portString;
-       strip_port(hostAddress, portString);
 
-       // Resolve address
+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;
 
-       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;
-
-       // Set port if specified separately
-
-       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;
-               }
-
-               default:
-                       break;
-       }
-
-       return B_OK;
+       uint32 cookie = 0;
+       return resolver.GetNextAddress(&cookie, *this);
 }
 
 
@@ -317,10 +211,26 @@
                        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);
        fAddress.ss_len = length;
        fStatus = B_OK;
@@ -935,7 +845,7 @@
 
 
 BString
-BNetworkAddress::PortName() const
+BNetworkAddress::ServiceName() const
 {
        // TODO: implement service lookup
        BString portName;
@@ -1062,7 +972,13 @@
 }
 
 
-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;
+}

Added: haiku/trunk/src/kits/network/libnetapi/NetworkAddressResolver.cpp
===================================================================
--- haiku/trunk/src/kits/network/libnetapi/NetworkAddressResolver.cpp           
                (rev 0)
+++ haiku/trunk/src/kits/network/libnetapi/NetworkAddressResolver.cpp   
2010-08-12 11:27:14 UTC (rev 38039)
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * 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;
+}


Other related posts:

  • » [haiku-commits] r38039 - in haiku/trunk: headers/os/net src/kits/network/libnetapi - axeld