00001
00002
00003
00004
00005
00006
00007
00008 #define TRACE_NAME "TCPConnect"
00009
00010 #include <stdio.h>
00011 #include <sys/types.h>
00012 #include <sys/socket.h>
00013 #include <netinet/in.h>
00014 #include <stdlib.h>
00015 #include <unistd.h>
00016 #include <string.h>
00017 #include <sys/socket.h>
00018 #include <netinet/in.h>
00019 #include <arpa/inet.h>
00020 #include <netdb.h>
00021
00022 #include <ifaddrs.h>
00023 #include <linux/if_link.h>
00024
00025 #include <string>
00026 #include <regex>
00027
00028 #include "artdaq/DAQdata/Globals.hh"
00029 #include "artdaq/DAQdata/TCPConnect.hh"
00030
00031
00032 int ResolveHost(char const* host_in, in_addr& addr)
00033 {
00034 std::string host;
00035 struct hostent* hostent_sp;
00036 std::cmatch mm;
00037
00038
00039 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00040 {
00041 host = mm[1].str();
00042 }
00043 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00044 {
00045 host = std::string("127.0.0.1");
00046 }
00047 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00048 {
00049 host = mm[1].str().c_str();
00050 }
00051 else
00052 {
00053 host = std::string("127.0.0.1");
00054 }
00055 TLOG(TLVL_INFO) << "Resolving host " << host;
00056
00057 bzero((char *)&addr, sizeof(addr));
00058
00059 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00060 inet_aton(host.c_str(), &addr);
00061 else
00062 {
00063 hostent_sp = gethostbyname(host.c_str());
00064 if (!hostent_sp)
00065 {
00066 perror("gethostbyname");
00067 return (-1);
00068 }
00069 addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00070 }
00071 return 0;
00072 }
00073
00074
00075 int GetInterfaceForNetwork(char const* host_in, in_addr& addr)
00076 {
00077 std::string host;
00078 struct hostent* hostent_sp;
00079 std::cmatch mm;
00080 int sts = 0;
00081
00082
00083 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00084 {
00085 host = mm[1].str();
00086 }
00087 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00088 {
00089 host = std::string("127.0.0.1");
00090 }
00091 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00092 {
00093 host = mm[1].str().c_str();
00094 }
00095 else
00096 {
00097 host = std::string("127.0.0.1");
00098 }
00099 TLOG(TLVL_INFO) << "Resolving ip " << host;
00100
00101 bzero((char *)&addr, sizeof(addr));
00102
00103 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00104 {
00105 in_addr desired_host;
00106 inet_aton(host.c_str(), &desired_host);
00107 struct ifaddrs *ifaddr, *ifa;
00108
00109 if (getifaddrs(&ifaddr) == -1)
00110 {
00111 perror("getifaddrs");
00112 return -1;
00113 }
00114
00115
00116
00117
00118 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
00119 {
00120 if (ifa->ifa_addr == NULL)
00121 continue;
00122
00123
00124
00125 if (ifa->ifa_addr->sa_family == AF_INET)
00126 {
00127 auto if_addr = (struct sockaddr_in*) ifa->ifa_addr;
00128 auto sa = (struct sockaddr_in *) ifa->ifa_netmask;
00129
00130 TLOG(15) << "IF: " << ifa->ifa_name << " Desired: " << desired_host.s_addr << " netmask: " << sa->sin_addr.s_addr << " this interface: " << if_addr->sin_addr.s_addr;
00131
00132 if ((if_addr->sin_addr.s_addr & sa->sin_addr.s_addr) == (desired_host.s_addr & sa->sin_addr.s_addr))
00133 {
00134 TLOG(TLVL_INFO) << "Using interface " << ifa->ifa_name;
00135 memcpy(&addr, &if_addr->sin_addr, sizeof(addr));
00136 break;
00137 }
00138 }
00139 }
00140 if (ifa == NULL)
00141 {
00142 TLOG(TLVL_WARNING) << "No matches for ip " << host << ", using 0.0.0.0";
00143 inet_aton("0.0.0.0", &addr);
00144 sts = 2;
00145 }
00146
00147 freeifaddrs(ifaddr);
00148 }
00149 else
00150 {
00151 hostent_sp = gethostbyname(host.c_str());
00152 if (!hostent_sp)
00153 {
00154 perror("gethostbyname");
00155 return (-1);
00156 }
00157 addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00158 }
00159 return sts;
00160 }
00161
00162
00163 int ResolveHost(char const* host_in, int dflt_port, sockaddr_in& sin)
00164 {
00165 int port;
00166 std::string host;
00167 struct hostent* hostent_sp;
00168 std::cmatch mm;
00169
00170
00171 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00172 {
00173 host = mm[1].str();
00174 port = strtoul(mm[2].str().c_str(), NULL, 0);
00175 }
00176 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00177 {
00178 host = std::string("127.0.0.1");
00179 port = strtoul(mm[1].str().c_str(), NULL, 0);
00180 }
00181 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00182 {
00183 host = mm[1].str().c_str();
00184 port = dflt_port;
00185 }
00186 else
00187 {
00188 host = std::string("127.0.0.1");
00189 port = dflt_port;
00190 }
00191 TLOG(TLVL_INFO) << "Resolving host " << host << ", on port " << std::to_string(port);
00192
00193 if (host == "localhost") host = "127.0.0.1";
00194
00195 bzero((char *)&sin, sizeof(sin));
00196 sin.sin_family = AF_INET;
00197 sin.sin_port = htons(port);
00198
00199 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00200 inet_aton(host.c_str(), &sin.sin_addr);
00201 else
00202 {
00203 hostent_sp = gethostbyname(host.c_str());
00204 if (!hostent_sp)
00205 {
00206 perror("gethostbyname");
00207 return (-1);
00208 }
00209 sin.sin_addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00210 }
00211 return 0;
00212 }
00213
00214
00215 int TCPConnect(char const* host_in
00216 , int dflt_port
00217 , long flags
00218 , int sndbufsiz)
00219 {
00220 int s_fd, sts;
00221 struct sockaddr_in sin;
00222
00223
00224 s_fd = socket(PF_INET, SOCK_STREAM, 0);
00225
00226 if (s_fd == -1)
00227 {
00228 perror("socket error");
00229 return (-1);
00230 }
00231
00232 sts = ResolveHost(host_in, dflt_port, sin);
00233 if (sts == -1)
00234 {
00235 close(s_fd);
00236 return -1;
00237 }
00238
00239 sts = connect(s_fd, (struct sockaddr *)&sin, sizeof(sin));
00240 if (sts == -1)
00241 {
00242
00243 close(s_fd);
00244 return (-1);
00245 }
00246
00247 if (flags)
00248 {
00249 sts = fcntl(s_fd, F_SETFL, flags);
00250 TLOG(TLVL_TRACE) << "TCPConnect fcntl(fd=" << s_fd << ",flags=0x" << std::hex << flags << std::dec << ") =" << sts;
00251 }
00252
00253 if (sndbufsiz > 0)
00254 {
00255 int len;
00256 socklen_t lenlen = sizeof(len);
00257 len = 0;
00258 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
00259 TLOG(TLVL_DEBUG) << "TCPConnect SNDBUF initial: " << len << " sts/errno=" << sts << "/" << errno << " lenlen=" << lenlen;
00260 len = sndbufsiz;
00261 sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen);
00262 if (sts == -1)
00263 TLOG(TLVL_ERROR) << "Error with setsockopt SNDBUF " << errno;
00264 len = 0;
00265 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
00266 if (len < (sndbufsiz * 2))
00267 TLOG(TLVL_WARNING) << "SNDBUF " << len << " not expected (" << sndbufsiz << " sts/errno=" << sts << "/" << errno;
00268 else
00269 TLOG(TLVL_DEBUG) << "SNDBUF " << len << " sts/errno=" << sts << "/" << errno;
00270 }
00271 return (s_fd);
00272 }