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