$treeview $search $mathjax $extrastylesheet
artdaq_mfextensions
v1_03_03a
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef TCPConnect_hh 00002 #define TCPConnect_hh 00003 #include <arpa/inet.h> // inet_aton 00004 #include <netdb.h> // gethostbyname 00005 #include <netinet/in.h> 00006 #include <netinet/in.h> // struct sockaddr_in 00007 #include <netinet/in.h> // inet_aton 00008 #include <stdio.h> // printf 00009 #include <stdlib.h> // exit 00010 #include <string.h> // bzero 00011 #include <sys/socket.h> // socket, bind, listen, accept 00012 #include <sys/socket.h> // inet_aton 00013 #include <sys/types.h> // socket, bind, listen, accept 00014 #include <unistd.h> // close 00015 00016 #include <ifaddrs.h> 00017 #include <linux/if_link.h> 00018 00019 #include <regex> 00020 #include <string> 00021 00022 #include "trace.h" 00023 00024 // This file (TCPConnect.hh) was created by Ron Rechenmacher <ron@fnal.gov> on 00025 // Sep 15, 2016. "TERMS AND CONDITIONS" governing this file are in the README 00026 // or COPYING file. If you do not have such a file, one can be obtained by 00027 // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000. 00028 // $RCSfile: .emacs.gnu,v $ 00029 // rev="$Revision: 1.30 $$Date: 2016/03/01 14:27:27 $"; 00030 00042 int ResolveHost(char const* host_in, in_addr& addr) { 00043 std::string host; 00044 struct hostent* hostent_sp; 00045 std::cmatch mm; 00046 // Note: the regex expression used by regex_match has an implied ^ and $ 00047 // at the beginning and end respectively. 00048 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)"))) { 00049 host = mm[1].str(); 00050 } else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)"))) { 00051 host = std::string("127.0.0.1"); 00052 } else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}"))) { 00053 host = mm[1].str().c_str(); 00054 } else { 00055 host = std::string("127.0.0.1"); 00056 } 00057 TLOG(TLVL_INFO) << "Resolving host " << host; 00058 00059 bzero((char*)&addr, sizeof(addr)); 00060 00061 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}"))) 00062 inet_aton(host.c_str(), &addr); 00063 else { 00064 hostent_sp = gethostbyname(host.c_str()); 00065 if (!hostent_sp) { 00066 perror("gethostbyname"); 00067 return (-1); 00068 } 00069 addr = *(struct in_addr*)(hostent_sp->h_addr_list[0]); 00070 } 00071 return 0; 00072 } 00073 00080 int GetInterfaceForNetwork(char const* host_in, in_addr& addr) { 00081 std::string host; 00082 struct hostent* hostent_sp; 00083 std::cmatch mm; 00084 int sts = 0; 00085 // Note: the regex expression used by regex_match has an implied ^ and $ 00086 // at the beginning and end respectively. 00087 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)"))) { 00088 host = mm[1].str(); 00089 } else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)"))) { 00090 host = std::string("127.0.0.1"); 00091 } else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}"))) { 00092 host = mm[1].str().c_str(); 00093 } else { 00094 host = std::string("127.0.0.1"); 00095 } 00096 TLOG(TLVL_INFO) << "Resolving ip " << host; 00097 00098 bzero((char*)&addr, sizeof(addr)); 00099 00100 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}"))) { 00101 in_addr desired_host; 00102 inet_aton(host.c_str(), &desired_host); 00103 struct ifaddrs *ifaddr, *ifa; 00104 00105 if (getifaddrs(&ifaddr) == -1) { 00106 perror("getifaddrs"); 00107 return -1; 00108 } 00109 00110 /* Walk through linked list, maintaining head pointer so we 00111 can free list later */ 00112 00113 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { 00114 if (ifa->ifa_addr == NULL) continue; 00115 00116 /* For an AF_INET* interface address, display the address */ 00117 00118 if (ifa->ifa_addr->sa_family == AF_INET) { 00119 auto if_addr = (struct sockaddr_in*)ifa->ifa_addr; 00120 auto sa = (struct sockaddr_in*)ifa->ifa_netmask; 00121 00122 TLOG(15) << "IF: " << ifa->ifa_name << " Desired: " << desired_host.s_addr 00123 << " netmask: " << sa->sin_addr.s_addr << " this interface: " << if_addr->sin_addr.s_addr; 00124 00125 if ((if_addr->sin_addr.s_addr & sa->sin_addr.s_addr) == (desired_host.s_addr & sa->sin_addr.s_addr)) { 00126 TLOG(TLVL_INFO) << "Using interface " << ifa->ifa_name; 00127 memcpy(&addr, &if_addr->sin_addr, sizeof(addr)); 00128 break; 00129 } 00130 } 00131 } 00132 if (ifa == NULL) { 00133 TLOG(TLVL_WARNING) << "No matches for ip " << host << ", using 0.0.0.0"; 00134 inet_aton("0.0.0.0", &addr); 00135 sts = 2; 00136 } 00137 00138 freeifaddrs(ifaddr); 00139 } else { 00140 hostent_sp = gethostbyname(host.c_str()); 00141 if (!hostent_sp) { 00142 perror("gethostbyname"); 00143 return (-1); 00144 } 00145 addr = *(struct in_addr*)(hostent_sp->h_addr_list[0]); 00146 } 00147 return sts; 00148 } 00149 00157 int ResolveHost(char const* host_in, int dflt_port, sockaddr_in& sin) { 00158 int port; 00159 std::string host; 00160 struct hostent* hostent_sp; 00161 std::cmatch mm; 00162 // Note: the regex expression used by regex_match has an implied ^ and $ 00163 // at the beginning and end respectively. 00164 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)"))) { 00165 host = mm[1].str(); 00166 port = strtoul(mm[2].str().c_str(), NULL, 0); 00167 } else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)"))) { 00168 host = std::string("127.0.0.1"); 00169 port = strtoul(mm[1].str().c_str(), NULL, 0); 00170 } else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}"))) { 00171 host = mm[1].str().c_str(); 00172 port = dflt_port; 00173 } else { 00174 host = std::string("127.0.0.1"); 00175 port = dflt_port; 00176 } 00177 TLOG(TLVL_INFO) << "Resolving host " << host << ", on port " << port; 00178 00179 if (host == "localhost") host = "127.0.0.1"; 00180 00181 bzero((char*)&sin, sizeof(sin)); 00182 sin.sin_family = AF_INET; 00183 sin.sin_port = htons(port); // just a guess at an open port 00184 00185 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}"))) 00186 inet_aton(host.c_str(), &sin.sin_addr); 00187 else { 00188 hostent_sp = gethostbyname(host.c_str()); 00189 if (!hostent_sp) { 00190 perror("gethostbyname"); 00191 return (-1); 00192 } 00193 sin.sin_addr = *(struct in_addr*)(hostent_sp->h_addr_list[0]); 00194 } 00195 return 0; 00196 } 00197 00206 int TCPConnect(char const* host_in, int dflt_port, long flags = 0, int sndbufsiz = 0) { 00207 int s_fd, sts; 00208 struct sockaddr_in sin; 00209 00210 s_fd = socket(PF_INET, SOCK_STREAM /*|SOCK_NONBLOCK*/, 0); // man socket,man TCP(7P) 00211 00212 if (s_fd == -1) { 00213 perror("socket error"); 00214 return (-1); 00215 } 00216 00217 sts = ResolveHost(host_in, dflt_port, sin); 00218 if (sts == -1) { 00219 close(s_fd); 00220 return -1; 00221 } 00222 00223 sts = connect(s_fd, (struct sockaddr*)&sin, sizeof(sin)); 00224 if (sts == -1) { 00225 // perror( "connect error" ); 00226 close(s_fd); 00227 return (-1); 00228 } 00229 00230 if (flags) { 00231 sts = fcntl(s_fd, F_SETFL, flags); 00232 TLOG(TLVL_TRACE) << "TCPConnect fcntl(fd=" << s_fd << ",flags=0x" << std::hex << flags << std::dec << ") =" << sts; 00233 } 00234 00235 if (sndbufsiz > 0) { 00236 int len; 00237 socklen_t lenlen = sizeof(len); 00238 len = 0; 00239 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen); 00240 TLOG(TLVL_DEBUG) << "TCPConnect SNDBUF initial: " << len << " sts/errno=" << sts << "/" << errno 00241 << " lenlen=" << lenlen; 00242 len = sndbufsiz; 00243 sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen); 00244 if (sts == -1) TLOG(TLVL_ERROR) << "Error with setsockopt SNDBUF " << errno; 00245 len = 0; 00246 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen); 00247 if (len < (sndbufsiz * 2)) 00248 TLOG(TLVL_WARNING) << "SNDBUF " << len << " not expected (" << sndbufsiz << " sts/errno=" << sts << "/" << errno 00249 << ")"; 00250 else 00251 TLOG(TLVL_DEBUG) << "SNDBUF " << len << " sts/errno=" << sts << "/" << errno; 00252 } 00253 return (s_fd); 00254 } 00255 00256 #endif // TCPConnect_hh