LCOV - code coverage report
Current view: top level - server_common - portconfig.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 61 66 92.4 %
Date: 2012-05-15 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 132 235 56.2 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #include <server_common/portconfig.h>
      16                 :            : #include <server_common/logger.h>
      17                 :            : #include <server_common/socket_request.h>
      18                 :            : 
      19                 :            : #include <asiolink/io_address.h>
      20                 :            : #include <asiodns/dns_service.h>
      21                 :            : 
      22                 :            : #include <boost/foreach.hpp>
      23                 :            : #include <boost/lexical_cast.hpp>
      24                 :            : 
      25                 :            : using namespace std;
      26                 :            : using namespace isc::data;
      27                 :            : using namespace isc::asiolink;
      28                 :            : using namespace isc::asiodns;
      29                 :            : 
      30                 :            : namespace isc {
      31                 :            : namespace server_common {
      32                 :            : namespace portconfig {
      33                 :            : 
      34                 :            : AddressList
      35                 :        207 : parseAddresses(isc::data::ConstElementPtr addresses,
      36                 :            :                const std::string& elemName)
      37                 :            : {
      38                 :         35 :     AddressList result;
      39         [ +  + ]:        207 :     if (addresses) {
      40         [ +  + ]:         64 :         if (addresses->getType() == Element::list) {
      41 [ +  - ][ +  + ]:         77 :             for (size_t i(0); i < addresses->size(); ++ i) {
      42         [ +  - ]:         53 :                 ConstElementPtr addrPair(addresses->get(i));
      43 [ +  - ][ +  - ]:         53 :                 ConstElementPtr addr(addrPair->get("address"));
      44 [ +  - ][ +  - ]:         53 :                 ConstElementPtr port(addrPair->get("port"));
      45 [ +  + ][ +  - ]:         53 :                 if (!addr || ! port) {
                 [ +  + ]
      46 [ +  - ][ +  - ]:         12 :                     LOG_ERROR(logger, SRVCOMM_ADDRESS_MISSING).
                 [ +  - ]
      47 [ +  - ][ +  - ]:         12 :                         arg(addrPair->str());
                 [ +  - ]
      48 [ +  - ][ +  - ]:         12 :                     isc_throw(BadValue, "Address must contain both the IP"
      49                 :            :                         "address and port");
      50                 :            :                 }
      51                 :            :                 try {
      52 [ +  - ][ +  + ]:         47 :                     IOAddress(addr->stringValue());
      53 [ +  + ][ +  + ]:         70 :                     if (port->intValue() < 0 ||
         [ +  + ][ +  + ]
      54         [ +  - ]:         29 :                         port->intValue() > 0xffff) {
      55 [ +  - ][ +  - ]:         22 :                         LOG_ERROR(logger, SRVCOMM_PORT_RANGE).
                 [ +  - ]
      56 [ +  - ][ +  - ]:         22 :                             arg(port->intValue()).arg(addrPair->str());
         [ +  - ][ +  - ]
                 [ +  - ]
      57 [ +  - ][ +  - ]:         33 :                         isc_throw(BadValue, "Bad port value (" <<
         [ +  - ][ +  - ]
      58                 :            :                             port->intValue() << ")");
      59                 :            :                     }
      60                 :         48 :                     result.push_back(AddressPair(addr->stringValue(),
      61   [ +  -  +  - ]:         48 :                         port->intValue()));
      62         [ +  + ]:         29 :                 } catch (const TypeError&) { // Better error message
      63 [ -  + ][ +  - ]:         12 :                     LOG_ERROR(logger, SRVCOMM_ADDRESS_TYPE).
                 [ -  + ]
      64 [ -  + ][ -  + ]:         12 :                         arg(addrPair->str());
                 [ -  + ]
      65 [ -  + ][ -  + ]:         12 :                     isc_throw(TypeError,
      66                 :            :                         "Address must be a string and port an integer");
      67                 :            :                 }
      68                 :            :             }
      69         [ +  + ]:         11 :         } else if (addresses->getType() != Element::null) {
      70 [ +  - ][ +  - ]:          6 :             LOG_ERROR(logger, SRVCOMM_ADDRESSES_NOT_LIST).arg(elemName);
         [ +  - ][ +  - ]
                 [ +  - ]
      71 [ +  - ][ +  - ]:         18 :             isc_throw(TypeError, elemName + " config element must be a list");
      72                 :            :         }
      73                 :            :     }
      74                 :        172 :     return (result);
      75                 :            : }
      76                 :            : 
      77                 :            : namespace {
      78                 :            : 
      79                 :          5 : vector<string> current_sockets;
      80                 :            : 
      81                 :            : void
      82                 :        166 : setAddresses(DNSServiceBase& service, const AddressList& addresses,
      83                 :            :              DNSService::ServerFlag server_options)
      84                 :            : {
      85                 :        166 :     service.clearServers();
      86 [ +  + ][ +  - ]:        382 :     BOOST_FOREACH(const string& token, current_sockets) {
         [ +  - ][ +  + ]
                 [ +  + ]
      87                 :        108 :         socketRequestor().releaseSocket(token);
      88                 :            :     }
      89                 :            :     current_sockets.clear();
      90 [ +  + ][ +  - ]:        274 :     BOOST_FOREACH(const AddressPair &address, addresses) {
         [ +  - ][ +  + ]
                 [ +  + ]
      91                 :         68 :         const int af(IOAddress(address.first).getFamily());
      92                 :            :         // We use the application name supplied to the socket requestor on
      93                 :            :         // creation. So we can freely use the SHARE_SAME
      94                 :            :         const SocketRequestor::SocketID
      95                 :         68 :             tcp(socketRequestor().requestSocket(SocketRequestor::TCP,
      96                 :            :                                                 address.first, address.second,
      97         [ +  + ]:         68 :                                                 SocketRequestor::SHARE_SAME));
      98         [ +  - ]:         54 :         current_sockets.push_back(tcp.second);
      99         [ +  - ]:         54 :         service.addServerTCPFromFD(tcp.first, af);
     100                 :            :         const SocketRequestor::SocketID
     101         [ +  - ]:         54 :             udp(socketRequestor().requestSocket(SocketRequestor::UDP,
     102                 :            :                                                 address.first, address.second,
     103 [ +  - ][ +  - ]:         54 :                                                 SocketRequestor::SHARE_SAME));
     104         [ +  - ]:         54 :         current_sockets.push_back(udp.second);
     105         [ +  - ]:         54 :         service.addServerUDPFromFD(udp.first, af, server_options);
     106                 :            :     }
     107                 :        152 : }
     108                 :            : 
     109                 :            : }
     110                 :            : 
     111                 :            : void
     112                 :        152 : installListenAddresses(const AddressList& new_addresses,
     113                 :            :                        AddressList& address_store,
     114                 :            :                        DNSServiceBase& service,
     115                 :            :                        DNSService::ServerFlag server_options)
     116                 :            : {
     117                 :            :     try {
     118 [ +  - ][ +  - ]:        152 :         LOG_DEBUG(logger, DBG_TRACE_BASIC, SRVCOMM_SET_LISTEN);
         [ +  - ][ +  - ]
     119 [ +  + ][ +  - ]:        314 :         BOOST_FOREACH(const AddressPair& addr, new_addresses) {
         [ +  - ][ +  + ]
                 [ +  + ]
     120 [ +  - ][ +  - ]:        162 :             LOG_DEBUG(logger, DBG_TRACE_VALUES, SRVCOMM_ADDRESS_VALUE).
                 [ +  - ]
     121 [ +  - ][ +  - ]:         54 :                 arg(addr.first).arg(addr.second);
                 [ +  - ]
     122                 :            :         }
     123         [ +  + ]:        152 :         setAddresses(service, new_addresses, server_options);
     124         [ +  - ]:        141 :         address_store = new_addresses;
     125                 :         22 :     } catch (const SocketRequestor::NonFatalSocketError& e) {
     126                 :            :         /*
     127                 :            :          * If one of the addresses isn't set successfully, we will restore
     128                 :            :          * the old addresses, the behavior is that either all address are
     129                 :            :          * set successuflly or none of them will be used. whether this
     130                 :            :          * behavior is user desired, maybe we need revisited it later. And
     131                 :            :          * if address setting is more smarter, it should check whether some
     132                 :            :          * part of the new address already in used to avoid interuption the
     133                 :            :          * service.
     134                 :            :          *
     135                 :            :          * If the address setting still failed, we can live with it, since
     136                 :            :          * user will get error info, command control can be used to set new
     137                 :            :          * address. So we just catch the exception without propagating outside
     138                 :            :          */
     139 [ -  + ][ +  - ]:         11 :         LOG_ERROR(logger, SRVCOMM_ADDRESS_FAIL).arg(e.what());
         [ -  + ][ -  + ]
                 [ -  + ]
     140                 :            :         try {
     141         [ +  + ]:         11 :             setAddresses(service, address_store, server_options);
     142 [ -  + ][ -  + ]:          6 :         } catch (const SocketRequestor::NonFatalSocketError& e2) {
     143 [ -  + ][ +  - ]:          3 :             LOG_FATAL(logger, SRVCOMM_ADDRESS_UNRECOVERABLE).arg(e2.what());
         [ -  + ][ -  + ]
                 [ -  + ]
     144                 :            :             // If we can't set the new ones, nor the old ones, at least
     145                 :            :             // releasing everything should work. If it doesn't, there isn't
     146                 :            :             // anything else we could do.
     147         [ -  + ]:          3 :             setAddresses(service, AddressList(), server_options);
     148                 :            :             address_store.clear();
     149                 :            :         }
     150                 :            :         //Anyway the new configure has problem, we need to notify configure
     151                 :            :         //manager the new configure doesn't work
     152                 :         11 :         throw;
     153                 :          0 :     } catch (const exception& e) {
     154                 :            :         // Any other kind of exception is fatal. It might mean we are in
     155                 :            :         // inconsistent state with the boss/socket creator, so we abort
     156                 :            :         // to make sure it doesn't last.
     157 [ #  # ][ #  # ]:          0 :         LOG_FATAL(logger, SRVCOMM_EXCEPTION_ALLOC).arg(e.what());
         [ #  # ][ #  # ]
                 [ #  # ]
     158                 :          0 :         abort();
     159      [ +  -  - ]:         11 :     } catch (...) {
     160                 :            :         // As the previous one, but we know even less info
     161 [ #  # ][ #  # ]:          0 :         LOG_FATAL(logger, SRVCOMM_UNKNOWN_EXCEPTION_ALLOC);
         [ #  # ][ #  # ]
     162                 :          0 :         abort();
     163                 :            :     }
     164                 :        141 : }
     165                 :            : 
     166                 :            : }
     167                 :            : }
     168                 :          5 : }

Generated by: LCOV version 1.9