diff options
| -rw-r--r-- | host/include/uhd/transport/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/include/uhd/transport/if_addrs.hpp | 47 | ||||
| -rw-r--r-- | host/include/uhd/transport/smart_buffer.hpp | 2 | ||||
| -rw-r--r-- | host/include/uhd/transport/udp_simple.hpp | 2 | ||||
| -rw-r--r-- | host/include/uhd/transport/udp_zero_copy.hpp | 2 | ||||
| -rw-r--r-- | host/lib/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | host/lib/transport/if_addrs.cpp | 343 | ||||
| -rw-r--r-- | host/lib/transport/udp_simple.cpp | 1 | ||||
| -rw-r--r-- | host/lib/transport/udp_zero_copy_asio.cpp | 1 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 20 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 1 | 
11 files changed, 429 insertions, 6 deletions
| diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 75b07c540..14b5ccd29 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -17,6 +17,7 @@  INSTALL(FILES +    if_addrs.hpp      smart_buffer.hpp      udp_simple.hpp      udp_zero_copy.hpp diff --git a/host/include/uhd/transport/if_addrs.hpp b/host/include/uhd/transport/if_addrs.hpp new file mode 100644 index 000000000..fbbb35e1d --- /dev/null +++ b/host/include/uhd/transport/if_addrs.hpp @@ -0,0 +1,47 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_IFADDRS_HPP +#define INCLUDED_UHD_IFADDRS_HPP + +#include <uhd/config.hpp> +#include <string> +#include <vector> + +namespace uhd{ namespace transport{ + +    /*! +     * The address for a network interface. +     */ +    struct UHD_API if_addrs_t{ +        std::string inet; +        std::string mask; +        std::string bcast; +        if_addrs_t(void); +    }; + +    /*! +     * Get a list of network interface addresses. +     * The internal implementation is system-dependent. +     * \return a vector of if addrs +     */ +    UHD_API std::vector<if_addrs_t> get_if_addrs(void); + +}} //namespace + + +#endif /* INCLUDED_UHD_IFADDRS_HPP */ diff --git a/host/include/uhd/transport/smart_buffer.hpp b/host/include/uhd/transport/smart_buffer.hpp index 9e1032feb..a9bc259e9 100644 --- a/host/include/uhd/transport/smart_buffer.hpp +++ b/host/include/uhd/transport/smart_buffer.hpp @@ -18,7 +18,7 @@  #ifndef INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP  #define INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP -#include <boost/asio.hpp> +#include <boost/asio/buffer.hpp>  #include <boost/utility.hpp>  #include <boost/shared_ptr.hpp> diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp index 40e60d091..793ec4fd7 100644 --- a/host/include/uhd/transport/udp_simple.hpp +++ b/host/include/uhd/transport/udp_simple.hpp @@ -19,7 +19,7 @@  #define INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP  #include <uhd/config.hpp> -#include <boost/asio.hpp> +#include <boost/asio/buffer.hpp>  #include <boost/utility.hpp>  #include <boost/shared_ptr.hpp> diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index 03d89b3a5..0441a8e74 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -20,7 +20,7 @@  #include <uhd/config.hpp>  #include <uhd/transport/smart_buffer.hpp> -#include <boost/asio.hpp> +#include <boost/asio/buffer.hpp>  #include <boost/utility.hpp>  #include <boost/shared_ptr.hpp> diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 22fbde265..4dd638336 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -28,6 +28,7 @@ SET(libuhd_sources      time_spec.cpp      types.cpp      wax.cpp +    transport/if_addrs.cpp      transport/udp_simple.cpp      transport/vrt.cpp      usrp/dboard/basic.cpp @@ -60,7 +61,6 @@ LIST(APPEND libuhd_sources  # Setup defines for module loading  ########################################################################  INCLUDE(CheckIncludeFileCXX) -  CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H)  CHECK_INCLUDE_FILE_CXX(Winbase.h HAVE_WINBASE_H) @@ -75,6 +75,19 @@ ELSE(HAVE_DLFCN_H)  ENDIF(HAVE_DLFCN_H)  ######################################################################## +# Setup defines for interface address discovery +######################################################################## +INCLUDE(CheckIncludeFileCXX) +CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H) + +IF(HAVE_IFADDRS_H) +    MESSAGE(STATUS "Interface address discovery supported through getifaddrs...") +    ADD_DEFINITIONS(-DHAVE_IFADDRS_H) +ELSE(HAVE_IFADDRS_H) +    MESSAGE(STATUS "Interface address discovery not supported...") +ENDIF(HAVE_IFADDRS_H) + +########################################################################  # Setup libuhd library  ########################################################################  ADD_LIBRARY(uhd SHARED ${libuhd_sources}) diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp new file mode 100644 index 000000000..d3ea448fd --- /dev/null +++ b/host/lib/transport/if_addrs.cpp @@ -0,0 +1,343 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/transport/if_addrs.hpp> + +uhd::transport::if_addrs_t::if_addrs_t(void){ +    /* NOP */ +} + +/*********************************************************************** + * Interface address discovery through ifaddrs api + **********************************************************************/ +#ifdef HAVE_IFADDRS_H +#include <ifaddrs.h> +#include <boost/asio/ip/address_v4.hpp> + +static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){ +    if (addr->sa_family == AF_INET) return boost::asio::ip::address_v4(ntohl( +        reinterpret_cast<sockaddr_in*>(addr)->sin_addr.s_addr +    )); +    return boost::asio::ip::address_v4::any(); +} + +static bool ifaddrs_valid(const struct ifaddrs *ifaddrs){ +    return ( +        ifaddrs->ifa_addr->sa_family == AF_INET and +        sockaddr_to_ip_addr(ifaddrs->ifa_addr) != boost::asio::ip::address_v4::loopback() +    ); +} + +std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){ +    std::vector<if_addrs_t> if_addrs; +    struct ifaddrs *ifap; +    if (getifaddrs(&ifap) == 0){ +        for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next){ +            if (not ifaddrs_valid(iter)) continue; +            if_addrs_t if_addr; +            if_addr.inet = sockaddr_to_ip_addr(iter->ifa_addr).to_string(); +            if_addr.mask = sockaddr_to_ip_addr(iter->ifa_netmask).to_string(); +            if_addr.bcast = sockaddr_to_ip_addr(iter->ifa_broadaddr).to_string(); +            if_addrs.push_back(if_addr); +        } +        freeifaddrs(ifap); +    } +    return if_addrs; +} + +/*********************************************************************** + * Interface address discovery through windows api (TODO) + **********************************************************************/ +//#elif HAVE_XXX_H + +/*********************************************************************** + * Interface address discovery not included + **********************************************************************/ +#else /* HAVE_IFADDRS_H */ + +std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){ +    return std::vector<if_addrs_t>(); +} + +#endif /* HAVE_IFADDRS_H */ + +//////////////////////////////////////////////////////////////////////// +// How to extract the ip address: unix/windows +// http://www.developerweb.net/forum/showthread.php?t=5085 +//////////////////////////////////////////////////////////////////////// + +/* +#include <stdio.h> + +#ifdef WIN32 +# include <windows.h> +# include <winsock.h> +# include <iphlpapi.h> +#else +# include <unistd.h> +# include <stdlib.h> +# include <sys/socket.h> +# include <netdb.h> +# include <netinet/in.h> +# include <net/if.h> +# include <sys/ioctl.h> +#endif + +#include <string.h> +#include <sys/stat.h> + +typedef unsigned long uint32; + +#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__) || defined(__linux__) +# define USE_GETIFADDRS 1 +# include <ifaddrs.h> +static uint32 SockAddrToUint32(struct sockaddr * a) +{ +   return ((a)&&(a->sa_family == AF_INET)) ? ntohl(((struct sockaddr_in *)a)->sin_addr.s_addr) : 0; +} +#endif + +// convert a numeric IP address into its string representation +static void Inet_NtoA(uint32 addr, char * ipbuf) +{ +   sprintf(ipbuf, "%li.%li.%li.%li", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF); +} + +// convert a string represenation of an IP address into its numeric equivalent +static uint32 Inet_AtoN(const char * buf) +{ +   // net_server inexplicably doesn't have this function; so I'll just fake it +   uint32 ret = 0; +   int shift = 24;  // fill out the MSB first +   bool startQuad = true; +   while((shift >= 0)&&(*buf)) +   { +      if (startQuad) +      { +         unsigned char quad = (unsigned char) atoi(buf); +         ret |= (((uint32)quad) << shift); +         shift -= 8; +      } +      startQuad = (*buf == '.'); +      buf++; +   } +   return ret; +} + +static void PrintNetworkInterfaceInfos() +{ +#if defined(USE_GETIFADDRS) +   // BSD-style implementation +   struct ifaddrs * ifap; +   if (getifaddrs(&ifap) == 0) +   { +      struct ifaddrs * p = ifap; +      while(p) +      { +         uint32 ifaAddr  = SockAddrToUint32(p->ifa_addr); +         uint32 maskAddr = SockAddrToUint32(p->ifa_netmask); +         uint32 dstAddr  = SockAddrToUint32(p->ifa_dstaddr); +         if (ifaAddr > 0) +         { +            char ifaAddrStr[32];  Inet_NtoA(ifaAddr,  ifaAddrStr); +            char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr); +            char dstAddrStr[32];  Inet_NtoA(dstAddr,  dstAddrStr); +            printf("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); +         } +         p = p->ifa_next; +      } +      freeifaddrs(ifap); +   } +#elif defined(WIN32) +   // Windows XP style implementation + +   // Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx +   // Now get Windows' IPv4 addresses table.  Once again, we gotta call GetIpAddrTable() +   // multiple times in order to deal with potential race conditions properly. +   MIB_IPADDRTABLE * ipTable = NULL; +   { +      ULONG bufLen = 0; +      for (int i=0; i<5; i++) +      { +         DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false); +         if (ipRet == ERROR_INSUFFICIENT_BUFFER) +         { +            free(ipTable);  // in case we had previously allocated it +            ipTable = (MIB_IPADDRTABLE *) malloc(bufLen); +         } +         else if (ipRet == NO_ERROR) break; +         else +         { +            free(ipTable); +            ipTable = NULL; +            break; +         } +     } +   } + +   if (ipTable) +   { +      // Try to get the Adapters-info table, so we can given useful names to the IP +      // addresses we are returning.  Gotta call GetAdaptersInfo() up to 5 times to handle +      // the potential race condition between the size-query call and the get-data call. +      // I love a well-designed API :^P +      IP_ADAPTER_INFO * pAdapterInfo = NULL; +      { +         ULONG bufLen = 0; +         for (int i=0; i<5; i++) +         { +            DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen); +            if (apRet == ERROR_BUFFER_OVERFLOW) +            { +               free(pAdapterInfo);  // in case we had previously allocated it +               pAdapterInfo = (IP_ADAPTER_INFO *) malloc(bufLen); +            } +            else if (apRet == ERROR_SUCCESS) break; +            else +            { +               free(pAdapterInfo); +               pAdapterInfo = NULL; +               break; +            } +         } +      } + +      for (DWORD i=0; i<ipTable->dwNumEntries; i++) +      { +         const MIB_IPADDRROW & row = ipTable->table[i]; + +         // Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it +         const char * name = NULL; +         const char * desc = NULL; +         if (pAdapterInfo) +         { +            IP_ADAPTER_INFO * next = pAdapterInfo; +            while((next)&&(name==NULL)) +            { +               IP_ADDR_STRING * ipAddr = &next->IpAddressList; +               while(ipAddr) +               { +                  if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr)) +                  { +                     name = next->AdapterName; +                     desc = next->Description; +                     break; +                  } +                  ipAddr = ipAddr->Next; +               } +               next = next->Next; +            } +         } +         char buf[128]; +         if (name == NULL) +         { +            sprintf(buf, "unnamed-%i", i); +            name = buf; +         } + +         uint32 ipAddr  = ntohl(row.dwAddr); +         uint32 netmask = ntohl(row.dwMask); +         uint32 baddr   = ipAddr & netmask; +         if (row.dwBCastAddr) baddr |= ~netmask; + +         char ifaAddrStr[32];  Inet_NtoA(ipAddr,  ifaAddrStr); +         char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr); +         char dstAddrStr[32];  Inet_NtoA(baddr,   dstAddrStr); +         printf("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); +      } + +      free(pAdapterInfo); +      free(ipTable); +   } +#else +   // Dunno what we're running on here! +#  error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!" +#endif +} + +int main(int, char **) +{ +   PrintNetworkInterfaceInfos(); +   return 0; +} +*/ + +//////////////////////////////////////////////////////////////////////// +// How to extract the mac address: linux/windows +// http://old.nabble.com/MAC-Address-td19111197.html +//////////////////////////////////////////////////////////////////////// + +/* +Linux: + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <netpacket/packet.h> +#include <ifaddrs.h> + +ifaddrs * ifap = 0; +if(getifaddrs(&ifap) == 0) +{ +     ifaddrs * iter = ifap; +     while(iter) +     { +         sockaddr_ll * sal = +                    reinterpret_cast<sockaddr_ll*>(iter->ifa_addr); +        if(sal->sll_family == AF_PACKET) +        { +                 // get the mac bytes +                // copy(sal->sll_addr, +                 //      sal->sll_addr+sal->sll_hallen, +                 //      buffer); +        } +         iter = iter->ifa_next; +     } +     freeifaddrs(ifap); +} + +Windows: +#include <winsock2.h> +#include <iphlpapi.h> + +std::vector<boost::uint8_t> buf; +DWORD bufLen = 0; +GetAdaptersAddresses(0, 0, 0, 0, &bufLen); +if(bufLen) +{ +     buf.resize(bufLen, 0); +     IP_ADAPTER_ADDRESSES * ptr = +                     reinterpret_cast<IP_ADAPTER_ADDRESSES*>(&buf[0]); +     DWORD err = GetAdaptersAddresses(0, 0, 0, ptr, &bufLen); +     if(err == NO_ERROR) +     { +          while(ptr) +         { +              if(ptr->PhysicalAddressLength) +              { +                 // get the mac bytes +                // copy(ptr->PhysicalAddress, +                 //      ptr->PhysicalAddress+ptr->PhysicalAddressLength, +                 //      buffer); +              } +              ptr = ptr->Next; +          } +     } +}  +*/ diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp index 3c8ecb70d..f339127ad 100644 --- a/host/lib/transport/udp_simple.cpp +++ b/host/lib/transport/udp_simple.cpp @@ -16,6 +16,7 @@  //  #include <uhd/transport/udp_simple.hpp> +#include <boost/asio.hpp>  #include <boost/thread.hpp>  #include <boost/format.hpp>  #include <iostream> diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 219ae8720..63944b2bf 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -17,6 +17,7 @@  #include <uhd/transport/udp_zero_copy.hpp>  #include <boost/cstdint.hpp> +#include <boost/asio.hpp>  #include <boost/thread.hpp>  #include <boost/format.hpp>  #include <iostream> diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 85d73e83a..f04ae8d2c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -15,9 +15,11 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +#include <uhd/transport/if_addrs.hpp> +#include <uhd/utils.hpp>  #include <boost/format.hpp> +#include <boost/foreach.hpp>  #include <boost/bind.hpp> -#include <uhd/utils.hpp>  #include <iostream>  #include "usrp2_impl.hpp" @@ -36,7 +38,21 @@ STATIC_BLOCK(register_usrp2_device){  uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){      device_addrs_t usrp2_addrs; -    if (not hint.has_key("addr")) return usrp2_addrs; +    //if no address was specified, send a broadcast on each interface +    if (not hint.has_key("addr")){ +        BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){ +            //create a new hint with this broadcast address +            device_addr_t new_hint = hint; +            new_hint["addr"] = if_addrs.bcast; + +            //call discover with the new hint and append results +            device_addrs_t new_usrp2_addrs = usrp2::discover(new_hint); +            usrp2_addrs.insert(usrp2_addrs.begin(), +                new_usrp2_addrs.begin(), new_usrp2_addrs.end() +            ); +        } +        return usrp2_addrs; +    }      //create a udp transport to communicate      //TODO if an addr is not provided, search all interfaces? diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 55ac0b192..a2f454c61 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -22,6 +22,7 @@  #include <uhd/dict.hpp>  #include <uhd/types.hpp>  #include <uhd/time_spec.hpp> +#include <boost/asio.hpp>  #include <boost/thread.hpp>  #include <boost/shared_ptr.hpp>  #include <boost/function.hpp> | 
