LCOV - code coverage report
Current view: top level - artdaq/DAQdata - TCPConnect.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 23.3 % 189 44
Test Date: 2025-09-04 00:45:34 Functions: 26.9 % 26 7

            Line data    Source code
       1              : //  This file (TCPConnect.cc) was created by Ron Rechenmacher <ron@fnal.gov> on
       2              : //  Apr 26, 2010. "TERMS AND CONDITIONS" governing this file are in the README
       3              : //  or COPYING file. If you do not have such a file, one can be obtained by
       4              : //  contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000.
       5              : //  $RCSfile: TCPConnect.cpp,v $
       6              : //  rev="$Revision: 1.4 $$Date: 2010/06/24 03:49:45 $";
       7              : 
       8              : #include "artdaq/DAQdata/TCPConnect.hh"
       9              : 
      10              : #include "TRACE/tracemf.h"
      11              : #include "artdaq/DAQdata/Globals.hh"
      12              : #define TRACE_NAME (app_name + "_TCPConnect").c_str()
      13              : 
      14              : #include <arpa/inet.h>   // inet_aton
      15              : #include <netdb.h>       // gethostbyname
      16              : #include <netinet/in.h>  // struct sockaddr_in
      17              : #include <netinet/in.h>  // inet_aton
      18              : #include <sys/socket.h>  // socket, bind, listen, accept
      19              : #include <sys/socket.h>  // inet_aton
      20              : #include <sys/types.h>   // socket, bind, listen, accept
      21              : #include <unistd.h>      // close
      22              : #include <cstdio>        // printf
      23              : #include <cstdlib>       // exit
      24              : #include <cstring>       // bzero
      25              : 
      26              : #include <ifaddrs.h>
      27              : #include <linux/if_link.h>
      28              : 
      29              : #include <map>
      30              : #include <regex>
      31              : #include <string>
      32              : 
      33              : // Return sts, put result in addr
      34            0 : int ResolveHost(char const *host_in, in_addr &addr)
      35              : {
      36            0 :         std::string host;
      37              :         struct hostent *hostent_sp;
      38            0 :         std::cmatch mm;
      39              :         //  Note: the regex expression used by regex_match has an implied ^ and $
      40              :         //        at the beginning and end respectively.
      41            0 :         if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
      42              :         {
      43            0 :                 host = mm[1].str();
      44              :         }
      45            0 :         else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
      46              :         {
      47            0 :                 host = std::string("127.0.0.1");
      48              :         }
      49            0 :         else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
      50              :         {
      51            0 :                 host = mm[1].str();
      52              :         }
      53              :         else
      54              :         {
      55            0 :                 host = std::string("127.0.0.1");
      56              :         }
      57            0 :         TLOG(TLVL_INFO) << "Resolving host " << host;
      58              : 
      59            0 :         memset(static_cast<void *>(&addr), 0, sizeof(addr));
      60              : 
      61            0 :         if (regex_match(host.c_str(), mm, std::regex(R"(\d+(\.\d+){3})")))
      62              :         {
      63            0 :                 inet_aton(host.c_str(), &addr);
      64              :         }
      65              :         else
      66              :         {
      67            0 :                 hostent_sp = gethostbyname(host.c_str());
      68            0 :                 if (hostent_sp == nullptr)
      69              :                 {
      70            0 :                         perror("gethostbyname");
      71            0 :                         return (-1);
      72              :                 }
      73            0 :                 addr = *reinterpret_cast<struct in_addr *>(hostent_sp->h_addr_list[0]);  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
      74              :         }
      75            0 :         return 0;
      76            0 : }
      77              : 
      78            0 : int GetIPOfInterface(const std::string &interface_name, in_addr &addr)
      79              : {
      80            0 :         int sts = 0;
      81              : 
      82            0 :         TLOG(TLVL_INFO) << "Finding address for interface " << interface_name;
      83              : 
      84            0 :         memset(static_cast<void *>(&addr), 0, sizeof(addr));
      85              : 
      86              :         struct ifaddrs *ifaddr, *ifa;
      87              : 
      88            0 :         if (getifaddrs(&ifaddr) == -1)
      89              :         {
      90            0 :                 perror("getifaddrs");
      91            0 :                 return -1;
      92              :         }
      93              : 
      94              :         /* Walk through linked list, maintaining head pointer so we
      95              :         can free list later */
      96              : 
      97            0 :         for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
      98              :         {
      99            0 :                 if (ifa->ifa_addr == nullptr)
     100              :                 {
     101            0 :                         continue;
     102              :                 }
     103              : 
     104              :                 /* For an AF_INET* interface address, display the address */
     105              : 
     106            0 :                 if (ifa->ifa_addr->sa_family == AF_INET)
     107              :                 {
     108            0 :                         auto if_addr = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr);  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
     109              : 
     110            0 :                         TLOG(TLVL_DEBUG + 35) << "IF: " << ifa->ifa_name << " Desired: " << interface_name << " IP: " << if_addr->sin_addr.s_addr;
     111              : 
     112            0 :                         if (std::string(ifa->ifa_name) == interface_name)
     113              :                         {
     114            0 :                                 TLOG(TLVL_INFO) << "Interface " << ifa->ifa_name << " matches " << interface_name << " IP: " << if_addr->sin_addr.s_addr;
     115            0 :                                 memcpy(&addr, &if_addr->sin_addr, sizeof(addr));
     116            0 :                                 break;
     117              :                         }
     118              :                 }
     119              :         }
     120            0 :         if (ifa == nullptr)
     121              :         {
     122            0 :                 TLOG(TLVL_WARNING) << "No matches for if " << interface_name << ", using 0.0.0.0";
     123            0 :                 inet_aton("0.0.0.0", &addr);
     124            0 :                 sts = 2;
     125              :         }
     126              : 
     127            0 :         freeifaddrs(ifaddr);
     128              : 
     129            0 :         return sts;
     130              : }
     131              : 
     132            0 : int AutodetectPrivateInterface(in_addr &addr)
     133              : {
     134            0 :         int sts = 0;
     135              : 
     136            0 :         memset(static_cast<void *>(&addr), 0, sizeof(addr));
     137              : 
     138              :         struct ifaddrs *ifaddr, *ifa;
     139              : 
     140              :         enum ip_preference : int
     141              :         {
     142              :                 IP_192 = 1,
     143              :                 IP_172 = 2,
     144              :                 IP_10 = 3,
     145              :                 IP_131 = 4
     146              :         };
     147              : 
     148              :         struct in_addr addr_192, addr_172, addr_10, addr_131, nm_16, nm_12, nm_8;
     149            0 :         inet_aton("192.168.0.0", &addr_192);
     150            0 :         inet_aton("172.16.0.0", &addr_172);
     151            0 :         inet_aton("10.0.0.0", &addr_10);
     152            0 :         inet_aton("131.225.0.0", &addr_131);
     153            0 :         inet_aton("255.255.0.0", &nm_16);
     154            0 :         inet_aton("255.240.0.0", &nm_12);
     155            0 :         inet_aton("255.0.0.0", &nm_8);
     156              : 
     157            0 :         std::map<ip_preference, in_addr> preference_map;
     158              : 
     159            0 :         if (getifaddrs(&ifaddr) == -1)
     160              :         {
     161            0 :                 perror("getifaddrs");
     162            0 :                 return -1;
     163              :         }
     164              : 
     165              :         /* Walk through linked list, maintaining head pointer so we
     166              :         can free list later */
     167              : 
     168            0 :         for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
     169              :         {
     170            0 :                 if (ifa->ifa_addr == nullptr)
     171              :                 {
     172            0 :                         continue;
     173              :                 }
     174              : 
     175              :                 /* For an AF_INET* interface address, display the address */
     176              : 
     177            0 :                 if (ifa->ifa_addr->sa_family == AF_INET)
     178              :                 {
     179            0 :                         auto if_addr = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr);  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
     180              : 
     181            0 :                         TLOG(TLVL_DEBUG + 35) << "IF: " << ifa->ifa_name << " IP: " << if_addr->sin_addr.s_addr;
     182              : 
     183            0 :                         if (preference_map.count(IP_192) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_192.s_addr)
     184              :                         {
     185            0 :                                 preference_map[IP_192];
     186            0 :                                 memcpy(&preference_map[IP_192], &if_addr->sin_addr, sizeof(addr));
     187              :                         }
     188            0 :                         else if (preference_map.count(IP_172) == 0 && (if_addr->sin_addr.s_addr & nm_12.s_addr) == addr_172.s_addr)
     189              :                         {
     190            0 :                                 preference_map[IP_172];
     191            0 :                                 memcpy(&preference_map[IP_172], &if_addr->sin_addr, sizeof(addr));
     192              :                         }
     193            0 :                         else if (preference_map.count(IP_10) == 0 && (if_addr->sin_addr.s_addr & nm_8.s_addr) == addr_10.s_addr)
     194              :                         {
     195            0 :                                 preference_map[IP_10];
     196            0 :                                 memcpy(&preference_map[IP_10], &if_addr->sin_addr, sizeof(addr));
     197              :                         }
     198            0 :                         else if (preference_map.count(IP_131) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_131.s_addr)
     199              :                         {
     200            0 :                                 preference_map[IP_131];
     201            0 :                                 memcpy(&preference_map[IP_131], &if_addr->sin_addr, sizeof(addr));
     202              :                         }
     203              :                 }
     204              :         }
     205              : 
     206            0 :         if (preference_map.empty())
     207              :         {
     208            0 :                 TLOG(TLVL_WARNING) << "AutodetectPrivateInterface: No matches, using 0.0.0.0";
     209            0 :                 inet_aton("0.0.0.0", &addr);
     210            0 :                 sts = 2;
     211              :         }
     212              :         else
     213              :         {
     214            0 :                 TLOG(TLVL_INFO) << "AutodetectPrivateInterface: Using " << inet_ntoa(addr);
     215            0 :                 memcpy(&addr, &preference_map.begin()->second, sizeof(addr));
     216              :         }
     217              : 
     218            0 :         freeifaddrs(ifaddr);
     219              : 
     220            0 :         return sts;
     221            0 : }
     222              : 
     223              : // Return sts, put result in addr
     224            0 : int GetInterfaceForNetwork(char const *host_in, in_addr &addr)
     225              : {
     226            0 :         std::string host;
     227              :         struct hostent *hostent_sp;
     228            0 :         std::cmatch mm;
     229            0 :         int sts = 0;
     230              :         //  Note: the regex expression used by regex_match has an implied ^ and $
     231              :         //        at the beginning and end respectively.
     232            0 :         if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
     233              :         {
     234            0 :                 host = mm[1].str();
     235              :         }
     236            0 :         else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
     237              :         {
     238            0 :                 host = std::string("127.0.0.1");
     239              :         }
     240            0 :         else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
     241              :         {
     242            0 :                 host = mm[1].str();
     243              :         }
     244              :         else
     245              :         {
     246            0 :                 host = std::string("127.0.0.1");
     247              :         }
     248            0 :         TLOG(TLVL_INFO) << "Resolving ip " << host;
     249              : 
     250            0 :         memset(static_cast<void *>(&addr), 0, sizeof(addr));
     251              : 
     252            0 :         if (regex_match(host.c_str(), mm, std::regex(R"(\d+(\.\d+){3})")))
     253              :         {
     254              :                 in_addr desired_host;
     255            0 :                 inet_aton(host.c_str(), &desired_host);
     256              :                 struct ifaddrs *ifaddr, *ifa;
     257              : 
     258            0 :                 if (getifaddrs(&ifaddr) == -1)
     259              :                 {
     260            0 :                         perror("getifaddrs");
     261            0 :                         return -1;
     262              :                 }
     263              : 
     264              :                 /* Walk through linked list, maintaining head pointer so we
     265              :                 can free list later */
     266              : 
     267            0 :                 for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
     268              :                 {
     269            0 :                         if (ifa->ifa_addr == nullptr)
     270              :                         {
     271            0 :                                 continue;
     272              :                         }
     273              : 
     274              :                         /* For an AF_INET* interface address, display the address */
     275              : 
     276            0 :                         if (ifa->ifa_addr->sa_family == AF_INET)
     277              :                         {
     278            0 :                                 auto if_addr = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr);  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
     279            0 :                                 auto sa = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_netmask);    // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
     280              : 
     281            0 :                                 TLOG(TLVL_DEBUG + 35) << "IF: " << ifa->ifa_name << " Desired: " << desired_host.s_addr << " netmask: " << sa->sin_addr.s_addr << " this interface: " << if_addr->sin_addr.s_addr;
     282              : 
     283            0 :                                 if ((if_addr->sin_addr.s_addr & sa->sin_addr.s_addr) == (desired_host.s_addr & sa->sin_addr.s_addr))
     284              :                                 {
     285            0 :                                         TLOG(TLVL_INFO) << "Using interface " << ifa->ifa_name;
     286            0 :                                         memcpy(&addr, &if_addr->sin_addr, sizeof(addr));
     287            0 :                                         break;
     288              :                                 }
     289              :                         }
     290              :                 }
     291            0 :                 if (ifa == nullptr)
     292              :                 {
     293            0 :                         if (host != std::string("0.0.0.0"))
     294              :                         {
     295            0 :                                 TLOG(TLVL_WARNING) << "No matches for ip " << host << ", using 0.0.0.0";
     296              :                         }
     297            0 :                         inet_aton("0.0.0.0", &addr);
     298            0 :                         sts = 2;
     299              :                 }
     300              : 
     301            0 :                 freeifaddrs(ifaddr);
     302              :         }
     303              :         else
     304              :         {
     305            0 :                 hostent_sp = gethostbyname(host.c_str());
     306            0 :                 if (hostent_sp == nullptr)
     307              :                 {
     308            0 :                         perror("gethostbyname");
     309            0 :                         return (-1);
     310              :                 }
     311            0 :                 addr = *reinterpret_cast<struct in_addr *>(hostent_sp->h_addr_list[0]);  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
     312              :         }
     313            0 :         return sts;
     314            0 : }
     315              : 
     316              : // Return sts, put result in sin
     317            2 : int ResolveHost(char const *host_in, int dflt_port, sockaddr_in &sin)
     318              : {
     319              :         int port;
     320            2 :         std::string host;
     321              :         struct hostent *hostent_sp;
     322            2 :         std::cmatch mm;
     323              :         //  Note: the regex expression used by regex_match has an implied ^ and $
     324              :         //        at the beginning and end respectively.
     325            2 :         if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
     326              :         {
     327            0 :                 host = mm[1].str();
     328            0 :                 port = strtoul(mm[2].str().c_str(), nullptr, 0);
     329              :         }
     330            2 :         else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
     331              :         {
     332            0 :                 host = std::string("127.0.0.1");
     333            0 :                 port = strtoul(mm[1].str().c_str(), nullptr, 0);
     334              :         }
     335            2 :         else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
     336              :         {
     337            1 :                 host = mm[1].str();
     338            1 :                 port = dflt_port;
     339              :         }
     340              :         else
     341              :         {
     342            1 :                 host = std::string("127.0.0.1");
     343            1 :                 port = dflt_port;
     344              :         }
     345            6 :         TLOG(TLVL_INFO) << "Resolving host " << host << ", on port " << port;
     346              : 
     347            2 :         if (host == "localhost")
     348              :         {
     349            1 :                 host = "127.0.0.1";
     350              :         }
     351              : 
     352            2 :         memset(static_cast<void *>(&sin), 0, sizeof(sin));
     353            2 :         sin.sin_family = AF_INET;
     354            2 :         sin.sin_port = htons(port);  // just a guess at an open port
     355              : 
     356            2 :         if (regex_match(host.c_str(), mm, std::regex(R"(\d+(\.\d+){3})")))
     357              :         {
     358            2 :                 inet_aton(host.c_str(), &sin.sin_addr);
     359              :         }
     360              :         else
     361              :         {
     362            0 :                 hostent_sp = gethostbyname(host.c_str());
     363            0 :                 if (hostent_sp == nullptr)
     364              :                 {
     365            0 :                         TLOG(TLVL_ERROR) << "Error calling gethostbyname: " << errno << " (" << strerror(errno) << ")";
     366            0 :                         perror("gethostbyname");
     367            0 :                         return (-1);
     368              :                 }
     369            0 :                 sin.sin_addr = *reinterpret_cast<struct in_addr *>(hostent_sp->h_addr_list[0]);  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
     370              :         }
     371              : 
     372            6 :         TLOG(TLVL_INFO) << "Host resolved as " << inet_ntoa(sin.sin_addr);
     373            2 :         return 0;
     374            2 : }
     375              : // return connection fd.
     376              : //
     377            1 : int TCPConnect(char const *host_in, int dflt_port, int64_t flags, int sndbufsiz)
     378              : {
     379              :         int s_fd, sts;
     380              :         struct sockaddr_in sin;
     381              : 
     382            1 :         s_fd = socket(PF_INET, SOCK_STREAM /*|SOCK_NONBLOCK*/, 0);  // man socket,man TCP(7P)
     383              : 
     384            1 :         if (s_fd == -1)
     385              :         {
     386            0 :                 perror("socket error");
     387            0 :                 return (-1);
     388              :         }
     389              : 
     390            1 :         sts = ResolveHost(host_in, dflt_port, sin);
     391            1 :         if (sts == -1)
     392              :         {
     393            0 :                 close(s_fd);
     394            0 :                 return -1;
     395              :         }
     396              : 
     397            1 :         sts = connect(s_fd, reinterpret_cast<struct sockaddr *>(&sin), sizeof(sin));  // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
     398            1 :         if (sts == -1)
     399              :         {
     400              :                 // perror( "connect error" );
     401            0 :                 close(s_fd);
     402            0 :                 return (-1);
     403              :         }
     404              : 
     405            1 :         if (flags != 0)
     406              :         {
     407            1 :                 sts = fcntl(s_fd, F_SETFL, flags);
     408            2 :                 TLOG(TLVL_DEBUG + 33) << "TCPConnect fcntl(fd=" << s_fd << ",flags=0x" << std::hex << flags << std::dec << ") =" << sts;
     409              :         }
     410              : 
     411            1 :         if (sndbufsiz > 0)
     412              :         {
     413              :                 int len;
     414            1 :                 socklen_t lenlen = sizeof(len);
     415            1 :                 len = 0;
     416            1 :                 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
     417            2 :                 TLOG(TLVL_DEBUG + 32) << "TCPConnect SNDBUF initial: " << len << " sts/errno=" << sts << "/" << errno << " lenlen=" << lenlen;
     418            1 :                 len = sndbufsiz;
     419            1 :                 sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen);
     420            1 :                 if (sts == -1)
     421              :                 {
     422            0 :                         TLOG(TLVL_ERROR) << "Error with setsockopt SNDBUF " << errno;
     423              :                 }
     424            1 :                 len = 0;
     425            1 :                 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
     426            1 :                 if (len < (sndbufsiz * 2))
     427              :                 {
     428            0 :                         TLOG(TLVL_WARNING) << "SNDBUF " << len << " not expected (" << sndbufsiz << " sts/errno=" << sts << "/" << errno << ")";
     429              :                 }
     430              :                 else
     431              :                 {
     432            2 :                         TLOG(TLVL_DEBUG + 32) << "SNDBUF " << len << " sts/errno=" << sts << "/" << errno;
     433              :                 }
     434              :         }
     435            1 :         return (s_fd);
     436              : }
        

Generated by: LCOV version 2.0-1