NSIS-ka
A free C++ implementation of NSIS protocols

Changeset 4198


Ignore:
Timestamp:
Aug 4, 2009, 3:24:30 PM (8 years ago)
Author:
stud-lenk
Message:
  • Bugfixes and improvements for class networkinterface
  • extend TPoverUDP::join_multicast_group() and TPoverUDP::leave_multicast_group() by an optional interface parameter, specifying the interface on which to join a multicast group
Location:
protlib/branches/20090723-multicast
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • protlib/branches/20090723-multicast/include/networkinterface.h

    r4163 r4198  
    7373  protected:
    7474        void throw_nomem_error() const;
     75  private:
     76        void setup_iface_name();
     77
    7578};
    7679
    77 ostream &operator<<(ostream &out, const networkinterface &iface) {
    78      return out << iface.get_name();
    79 }
     80ostream &operator<<(ostream &out, const networkinterface &iface);
     81
     82istream& operator>>(istream& inputstream, networkinterface& ni);
    8083
    8184typedef list<networkinterface> networkinterfacelist_t;
     
    8386ostream &operator<<(ostream &out, const networkinterfacelist_t &list);
    8487
     88istream& operator>>(istream& inputstream, networkinterfacelist_t& nilist);
     89
    8590} // end namespace protlib
    8691
  • protlib/branches/20090723-multicast/include/tp_over_udp.h

    r4159 r4198  
    4242#include "connectionmap.h"
    4343#include "assocdata.h"
     44#include "networkinterface.h"
    4445
    4546namespace protlib
     
    139140  };
    140141
    141   int join_multicast_group(const hostaddress group);
    142   int leave_multicast_group(const hostaddress group);
     142  int join_multicast_group(const hostaddress group, const networkinterface* nif = NULL);
     143  int leave_multicast_group(const hostaddress group, const networkinterface* nif = NULL);
    143144
    144145  int get_listener_socket() const { return master_listener_socket; }
  • protlib/branches/20090723-multicast/src/networkinterface.cpp

    r4163 r4198  
    6565} // end operator==
    6666
    67 networkinterface::networkinterface(const networkinterface& other_ni)
    68 {
    69         networkinterface(other_ni.get_index());
    70 }
    71 
    72 networkinterface::networkinterface(const unsigned int if_index)
    73 {
    74         if (if_index == 0)
    75           throw std::invalid_argument("No such interface");
    76         if (if_indextoname(if_index, (char *)&iface_name) == NULL)
    77           throw std::invalid_argument("No such interface");
    78         iface_index = if_index;
    79 }
    80 
    81 networkinterface::networkinterface(const char *str)
    82 {
    83         if (str == NULL)
    84           throw std::invalid_argument("No such interface");
    85         unsigned int index = if_nametoindex(str);
    86         if (index == 0)
    87           throw std::invalid_argument("No such interface");
    88         iface_index = index;
    89         strncpy(iface_name, str, IFNAMSIZ);
    90 }
    91 
    92 networkinterface::networkinterface(const char *str, bool *res)
     67
     68networkinterface::networkinterface(const networkinterface& other_ni) :
     69        iface_index(other_ni.iface_index)
     70{
     71        setup_iface_name();
     72}
     73
     74
     75
     76networkinterface::networkinterface(const unsigned int if_index) :
     77        iface_index(if_index)
     78{
     79        setup_iface_name();
     80}
     81
     82
     83networkinterface::networkinterface(const char *str) :
     84        iface_index(str ? if_nametoindex(str) : 0)
     85{
     86        setup_iface_name();
     87}
     88
     89networkinterface::networkinterface(const char *str, bool *res) :
     90        iface_index(str ? if_nametoindex(str) : 0)
    9391{
    9492        register bool tmpres = false;
     93        iface_name[0] = 0;
    9594        if (str != NULL) {
    96                 unsigned int index = if_nametoindex(str);
    97                 if (index != 0) {
    98                         iface_index = index;
     95                if (iface_index != 0) {
    9996                        strncpy(iface_name, str, IFNAMSIZ);
    10097                        tmpres = true;
     
    10299        }
    103100        if (res) *res = tmpres;
     101}
     102
     103networkinterface::networkinterface(const hostaddress addr) :
     104        iface_index(0)
     105{
     106        // search all network interfaces for the specified address
     107        // See http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html
     108        bool interface_found = false;
     109        struct ifaddrs *ifaddr, *ifa;
     110        hostaddress cmp_addr;
     111        if (getifaddrs(&ifaddr) == -1)
     112          throw std::runtime_error("getifaddrs() failed");
     113        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
     114          switch (ifa->ifa_addr->sa_family)
     115          {
     116            case AF_INET:       // IPv4
     117              cmp_addr.set_ip(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr);
     118              break;
     119            case AF_INET6:
     120              cmp_addr.set_ip(((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr);
     121              break;
     122          }
     123          if (cmp_addr == addr) {
     124            strncpy(iface_name, ifa->ifa_name, IFNAMSIZ);
     125            iface_index = if_nametoindex(ifa->ifa_name);
     126            if (iface_index != 0) {
     127              interface_found = true;
     128              break;
     129            }
     130          }
     131        }
     132        freeifaddrs(ifaddr);
     133        if (!interface_found)
     134          throw std::invalid_argument("No such interface");
     135}
     136
     137void networkinterface::setup_iface_name()
     138{
     139        if (iface_index == 0)
     140          throw std::invalid_argument("No such interface");
     141        if (if_indextoname(iface_index, (char *)&iface_name) == NULL)
     142          throw std::invalid_argument("No such interface");
     143}
     144
     145istream& operator>>(istream& inputstream, networkinterface& ni)
     146{
     147  string inputstr;
     148  inputstream >> inputstr;
     149
     150  networkinterface netif(inputstr.c_str());
     151  ni = netif;
     152  return inputstream;
     153}
     154
     155
     156istream& operator>>(istream& inputstream, networkinterfacelist_t& nilist)
     157{
     158  while ( inputstream ) {
     159    std::string token;
     160    inputstream >> token;
     161   
     162    bool success;
     163    networkinterface ni(token.c_str(), &success);
     164   
     165    if ( success )
     166      nilist.push_back(ni);
     167  }
     168
     169  return inputstream;
     170}
     171
     172ostream &operator<<(ostream &out, const networkinterface &iface) {
     173     return out << iface.get_name();
    104174}
    105175
  • protlib/branches/20090723-multicast/src/tp_over_udp.cpp

    r4159 r4198  
    492492
    493493// helper function for joining/leaving an IPv4 multicast group
    494 inline int multicast_request_ipv4(int socket, const hostaddress group, const int action)
     494inline int multicast_request_ipv4(int socket, const hostaddress group, const networkinterface *ni, const int action)
    495495{
    496496  struct ip_mreq mreq;
     497  mreq.imr_interface.s_addr=htonl(INADDR_ANY);
     498  if (ni) {
     499    hostaddresslist_t hal;
     500    ni->get_addresses(&hal);
     501    if (!hal.empty()) {
     502      hal.front().get_ip(mreq.imr_interface);
     503    }
     504  }
    497505  group.get_ip(mreq.imr_multiaddr);
    498   mreq.imr_interface.s_addr=htonl(INADDR_ANY);
    499506  return setsockopt(socket, IPPROTO_IP, action, &mreq, sizeof(mreq));
    500507}
    501508
    502509// helper function for joining/leaving an IPv6 multicast group
    503 inline int multicast_request_ipv6(int socket, const hostaddress group, const int action)
     510inline int multicast_request_ipv6(int socket, const hostaddress group, const networkinterface *ni, const int action)
    504511{
    505512  struct ipv6_mreq mreq;
    506513  group.get_ip(mreq.ipv6mr_multiaddr);
    507   mreq.ipv6mr_interface = INADDR_ANY;
     514  if (ni) {
     515    mreq.ipv6mr_interface = ni->get_index();
     516  } else {
     517    mreq.ipv6mr_interface = INADDR_ANY;
     518  }
    508519  return setsockopt(socket, IPPROTO_IPV6, action, &mreq, sizeof(mreq));
    509520}
    510521
    511522int
    512 TPoverUDP::join_multicast_group(const hostaddress group)
     523TPoverUDP::join_multicast_group(const hostaddress group, const networkinterface *nif)
    513524{
    514525  int udp_socket = -1;
     
    531542      WLog(tpparam.name, "IPv4 multicast loopback of own datagrams is still enabled!");
    532543    // join IPv4 multicast group
    533     status = multicast_request_ipv4(udp_socket, group, IP_ADD_MEMBERSHIP);
     544    status = multicast_request_ipv4(udp_socket, group, nif, IP_ADD_MEMBERSHIP);
    534545  } else if (group.is_ipv6()) {
    535546    // disable loopback of IPv6 multicast packages
     
    541552      WLog(tpparam.name, "IPv6 multicast loopback of own datagrams is still enabled!");
    542553    // join IPv6 multicast group
    543     status = multicast_request_ipv6(udp_socket, group, IPV6_JOIN_GROUP);
     554    status = multicast_request_ipv6(udp_socket, group, nif, IPV6_JOIN_GROUP);
    544555  }
    545556
     
    547558}
    548559
    549 int   
    550 TPoverUDP::leave_multicast_group(const hostaddress group)
     560int
     561TPoverUDP::leave_multicast_group(const hostaddress group, const networkinterface *nif)
    551562{
    552563  int udp_socket = -1;
     
    560571  if (group.is_ipv4()) {
    561572    // join IPv4 multicast group
    562     status = multicast_request_ipv4(udp_socket, group, IP_DROP_MEMBERSHIP);
     573    status = multicast_request_ipv4(udp_socket, group, nif, IP_DROP_MEMBERSHIP);
    563574  } else if (group.is_ipv6()) {
    564575    // join IPv6 multicast group
    565     status = multicast_request_ipv6(udp_socket, group, IPV6_LEAVE_GROUP);
     576    status = multicast_request_ipv6(udp_socket, group, nif, IPV6_LEAVE_GROUP);
    566577  }
    567578
  • protlib/branches/20090723-multicast/test/test_networkinterface.cpp

    r4163 r4198  
    1313
    1414  CPPUNIT_TEST( test_networkinterface_constructors );
     15  CPPUNIT_TEST( test_networkinterface_output_operators );
    1516
    1617  CPPUNIT_TEST_SUITE_END();
     
    5354          }
    5455          CPPUNIT_ASSERT(empty_string_failed);
     56
     57          // Triage constructors by hostaddress
     58          bool ipv4_loopback_addr_succeeded = true;
     59          hostaddress lo_addr("127.0.0.1");
     60          try {
     61            ni = new networkinterface(lo_addr);
     62          } catch (invalid_argument& ia) {
     63            ipv4_loopback_addr_succeeded = false;
     64          }
     65          DLog(methodname, "Got interface " << *ni << " (interface #" << ni->get_index() <<
     66                           ") from address " << lo_addr);
     67          CPPUNIT_ASSERT(ipv4_loopback_addr_succeeded);
     68          CPPUNIT_ASSERT(ni->get_index() == 1);
     69
     70          bool ipv4_bogon_addr_failed = false;
     71          hostaddress bogon_addr("255.255.255.255");
     72          try {
     73            ni = new networkinterface(bogon_addr);
     74          } catch (invalid_argument& ia) {
     75            ipv4_bogon_addr_failed = true;
     76          }
     77          CPPUNIT_ASSERT(ipv4_bogon_addr_failed);
     78
     79          // Triage copy constructor
     80          networkinterface ni1((unsigned int)1);
     81          networkinterface ni2(ni1);
     82          CPPUNIT_ASSERT(ni1 == ni2);
     83          CPPUNIT_ASSERT(ni1.get_index() == ni2.get_index());
     84          CPPUNIT_ASSERT(strncmp(ni1.get_name(), ni2.get_name(), IFNAMSIZ) == 0);
     85        }
     86       
     87        void test_networkinterface_output_operators() {
     88          const char *const methodname="test_networkinterface_output_operators()";
     89          // Triage output operator for networkinterface
     90          networkinterface a_ni("lo");
     91          std::ostringstream test_output;
     92          test_output << a_ni;
     93          std::string lo("lo");
     94          CPPUNIT_ASSERT(test_output.str() == lo);
     95
     96          // Triage output operator for networkinterfacelist_t
     97          networkinterfacelist_t ni_list;
     98          networkinterface ni_1("lo");
     99          ni_list.push_back(ni_1);
     100          networkinterface ni_2("eth0");
     101          ni_list.push_back(ni_2);
     102          std::ostringstream test_output_2;
     103          test_output_2 << ni_list;
     104          DLog(methodname, "Output of networkinterfacelist is: " << ni_list);
     105          std::string lo_and_eth0("lo eth0");
     106          CPPUNIT_ASSERT(test_output_2.str() == lo_and_eth0);
     107
    55108        }
    56109};
Note: See TracChangeset for help on using the changeset viewer.