artdaq  v2_03_00
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
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 using namespace std;
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  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, regex("([^:]+):(\\d+)")))
37  {
38  host = mm[1].str();
39  }
40  else if (regex_match(host_in, mm, regex(":{0,1}(\\d+)")))
41  {
42  host = std::string("127.0.0.1");
43  }
44  else if (regex_match(host_in, mm, 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_INFO("TCPConnect") << "Resolving host " << host << TLOG_ENDL;
53 
54  bzero((char *)&addr, sizeof(addr));
55 
56  if (regex_match(host.c_str(), mm, 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  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, 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, 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, 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_INFO("TCPConnect") << "Resolving host " << host << ", on port " << std::to_string(port) << TLOG_ENDL;
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, 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: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:122