artdaq  v3_01_00
TCPConnect.cc
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 #define TRACE_NAME "TCPConnect"
9 
10 #include <stdio.h> // printf
11 #include <sys/types.h> // socket, bind, listen, accept
12 #include <sys/socket.h> // socket, bind, listen, accept
13 #include <netinet/in.h> // struct sockaddr_in
14 #include <stdlib.h> // exit
15 #include <unistd.h> // close
16 #include <string.h> // bzero
17 #include <sys/socket.h> // inet_aton
18 #include <netinet/in.h> // inet_aton
19 #include <arpa/inet.h> // inet_aton
20 #include <netdb.h> // gethostbyname
21 
22 #include <string>
23 #include <regex>
24 
25 #include "artdaq/DAQdata/Globals.hh"
27 
28 // Return sts, put result in addr
29 int ResolveHost(char const* host_in, in_addr& addr)
30 {
31  std::string host;
32  struct hostent* hostent_sp;
33  std::cmatch mm;
34  // Note: the regex expression used by regex_match has an implied ^ and $
35  // at the beginning and end respectively.
36  if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
37  {
38  host = mm[1].str();
39  }
40  else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
41  {
42  host = std::string("127.0.0.1");
43  }
44  else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
45  {
46  host = mm[1].str().c_str();
47  }
48  else
49  {
50  host = std::string("127.0.0.1");
51  }
52  TLOG(TLVL_INFO) << "Resolving host " << host;
53 
54  bzero((char *)&addr, sizeof(addr));
55 
56  if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
57  inet_aton(host.c_str(), &addr);
58  else
59  {
60  hostent_sp = gethostbyname(host.c_str());
61  if (!hostent_sp)
62  {
63  perror("gethostbyname");
64  return (-1);
65  }
66  addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
67  }
68  return 0;
69 }
70 
71 // Return sts, put result in sin
72 int ResolveHost(char const* host_in, int dflt_port, sockaddr_in& sin)
73 {
74  int port;
75  std::string host;
76  struct hostent* hostent_sp;
77  std::cmatch mm;
78  // Note: the regex expression used by regex_match has an implied ^ and $
79  // at the beginning and end respectively.
80  if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
81  {
82  host = mm[1].str();
83  port = strtoul(mm[2].str().c_str(), NULL, 0);
84  }
85  else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
86  {
87  host = std::string("127.0.0.1");
88  port = strtoul(mm[1].str().c_str(), NULL, 0);
89  }
90  else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
91  {
92  host = mm[1].str().c_str();
93  port = dflt_port;
94  }
95  else
96  {
97  host = std::string("127.0.0.1");
98  port = dflt_port;
99  }
100  TLOG(TLVL_INFO) << "Resolving host " << host << ", on port " << std::to_string(port);
101 
102  if (host == "localhost") host = "127.0.0.1";
103 
104  bzero((char *)&sin, sizeof(sin));
105  sin.sin_family = AF_INET;
106  sin.sin_port = htons(port); // just a guess at an open port
107 
108  if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
109  inet_aton(host.c_str(), &sin.sin_addr);
110  else
111  {
112  hostent_sp = gethostbyname(host.c_str());
113  if (!hostent_sp)
114  {
115  perror("gethostbyname");
116  return (-1);
117  }
118  sin.sin_addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
119  }
120  return 0;
121 }
122 // return connection fd.
123 //
124 int TCPConnect(char const* host_in
125  , int dflt_port
126  , long flags
127  , int sndbufsiz)
128 {
129  int s_fd, sts;
130  struct sockaddr_in sin;
131 
132 
133  s_fd = socket(PF_INET, SOCK_STREAM/*|SOCK_NONBLOCK*/, 0); // man socket,man TCP(7P)
134 
135  if (s_fd == -1)
136  {
137  perror("socket error");
138  return (-1);
139  }
140 
141  sts = ResolveHost(host_in, dflt_port, sin);
142  if (sts == -1)
143  {
144  close(s_fd);
145  return -1;
146  }
147 
148  sts = connect(s_fd, (struct sockaddr *)&sin, sizeof(sin));
149  if (sts == -1)
150  {
151  //perror( "connect error" );
152  close(s_fd);
153  return (-1);
154  }
155 
156  if (flags)
157  {
158  sts = fcntl(s_fd, F_SETFL, flags);
159  TLOG(TLVL_TRACE) << "TCPConnect fcntl(fd=" << s_fd << ",flags=0x" << std::hex << flags << std::dec << ") =" << sts;
160  }
161 
162  if (sndbufsiz > 0)
163  {
164  int len;
165  socklen_t lenlen = sizeof(len);
166  len = 0;
167  sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
168  TLOG(TLVL_DEBUG) << "TCPConnect SNDBUF initial: "<< len <<" sts/errno="<< sts <<"/"<< errno <<" lenlen="<< lenlen ;
169  len = sndbufsiz;
170  sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen);
171  if (sts == -1)
172  TLOG(TLVL_ERROR) << "Error with setsockopt SNDBUF "<< errno;
173  len = 0;
174  sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
175  if (len < (sndbufsiz * 2))
176  TLOG(TLVL_WARNING) << "SNDBUF "<< len <<" not expected ("<< sndbufsiz <<" sts/errno="<< sts <<"/"<< errno ;
177  else
178  TLOG(TLVL_DEBUG) << "SNDBUF "<< len <<" sts/errno="<< sts <<"/"<< errno ;
179  }
180  return (s_fd);
181 }
int ResolveHost(char const *host_in, in_addr &addr)
Convert a string hostname to a in_addr suitable for socket communication.
Definition: TCPConnect.cc:29
int TCPConnect(char const *host_in, int dflt_port, long flags=0, int sndbufsiz=0)
Connect to a host on a given port.
Definition: TCPConnect.cc:124