Belle II Software  release-05-02-19
TCPSocket.cc
1 #include "daq/slc/system/TCPSocket.h"
2 
3 #include <daq/slc/base/IOException.h>
4 
5 #include <cstdio>
6 #include <cstring>
7 
8 #include <sys/socket.h>
9 #include <arpa/inet.h>
10 
11 #include <unistd.h>
12 #include <netinet/in.h>
13 #include <errno.h>
14 #include <netdb.h>
15 
16 using namespace Belle2;
17 
18 int TCPSocket::connect(const std::string& ip, unsigned short port)
19 {
20  m_ip = ip;
21  m_port = port;
22  return connect();
23 }
24 
25 int TCPSocket::connect()
26 {
27  if (m_fd > 0) {
28  throw (IOException("Socket is working already."));
29  }
30  sockaddr_in addr;
31  memset(&addr, 0, sizeof(sockaddr_in));
32  addr.sin_family = AF_INET;
33  addr.sin_addr.s_addr = INADDR_ANY;
34  addr.sin_port = htons(m_port);
35 
36  if ((m_fd = ::socket(PF_INET, SOCK_STREAM, 0)) < 0) {
37  throw (IOException("Failed to create socket"));
38  }
39  struct hostent* host = NULL;
40  host = gethostbyname(m_ip.c_str());
41  if (host == NULL) {
42  unsigned long ip_address = inet_addr(m_ip.c_str());
43  if ((signed long) ip_address < 0) {
44  throw (IOException("Wrong host name or ip"));
45  } else {
46  host = gethostbyaddr((char*)&ip_address, sizeof(ip_address), AF_INET);
47  }
48  }
49  if (host == NULL) {
50  close();
51  throw (IOException("Failed to connect host %s:%d",
52  m_ip.c_str(), m_port));
53  }
54  addr.sin_addr.s_addr = (*(unsigned long*) host->h_addr_list[0]);
55 
56  if (::connect(m_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
57  close();
58  throw (IOException("Failed to connect host %s:%d",
59  m_ip.c_str(), m_port));
60  }
61 
62  return m_fd;
63 }
64 
65 void TCPSocket::setBufferSize(int size)
66 {
67  if (size > 0) {
68  if (setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) != 0) {
69  throw (IOException("failed to SO_SNDBUF: %s\n", strerror(errno)));
70  }
71  if (setsockopt(m_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) != 0) {
72  throw (IOException("error on SO_RCVBUF: %s\n", strerror(errno)));
73  }
74  }
75 }
76 
77 size_t TCPSocket::write(const void* buf, size_t count)
78 {
79  size_t c = 0;
80  int ret;
81  while (c < count) {
82  errno = 0;
83  ret = send(m_fd, ((unsigned char*)buf + c), (count - c), MSG_NOSIGNAL);
84  if (ret <= 0) {
85  switch (errno) {
86  case EINTR: continue;
87  case ENETUNREACH:
88  case EHOSTUNREACH:
89  case ETIMEDOUT:
90  usleep(500);
91  continue;
92  default:
93  throw (IOException("Error while writing"));
94  }
95  }
96  c += ret;
97  }
98  return c;
99 }
100 
101 size_t TCPSocket::read(void* buf, size_t count)
102 {
103  size_t c = 0;
104  int ret;
105  while (c < count) {
106  errno = 0;
107  ret = recv(m_fd, ((unsigned char*)buf + c), (count - c), 0);
108  if (ret <= 0) {
109  switch (errno) {
110  case EINTR: continue;
111  case EAGAIN: continue;
112  default:
113  throw (IOException("TCPSocket::read Error while reading."));
114  }
115  }
116  c += ret;
117  }
118  return c;
119 }
120 
121 size_t TCPSocket::read_once(void* buf, size_t count)
122 {
123  int ret;
124  errno = 0;
125  while (true) {
126  ret = recv(m_fd, buf, count, 0);
127  if (ret <= 0) {
128  switch (errno) {
129  case EINTR: continue;
130  case EAGAIN: continue;
131  default:
132  throw (IOException("TCPSocket::read_once Error while reading."));
133  }
134  }
135  break;
136  }
137  return ret;
138 }
139 
140 void TCPSocket::print()
141 {
142  sockaddr_in sa;
143  memset(&sa, 0, sizeof(sockaddr_in));
144  socklen_t sa_len = sizeof(sa);
145  if (getsockname(m_fd, (struct sockaddr*)&sa, (socklen_t*)&sa_len) != 0) {
146  perror("getsockname");
147  }
148  printf("Local IP address is: %s\n", inet_ntoa(sa.sin_addr));
149  printf("Local port is: %d\n", (int) ntohs(sa.sin_port));
150 }
151 
152 const std::string TCPSocket::getLocalIP()
153 {
154  sockaddr_in sa;
155  memset(&sa, 0, sizeof(sockaddr_in));
156  socklen_t sa_len = sizeof(sa);
157  if (getsockname(m_fd, (struct sockaddr*)&sa, (socklen_t*)&sa_len) != 0) {
158  return "";
159  }
160  return inet_ntoa(sa.sin_addr);
161 }
162 
163 int TCPSocket::getLocalAddress()
164 {
165  sockaddr_in sa;
166  memset(&sa, 0, sizeof(sockaddr_in));
167  socklen_t sa_len = sizeof(sa);
168  if (getsockname(m_fd, (struct sockaddr*)&sa, (socklen_t*)&sa_len) != 0) {
169  return 0;
170  }
171  return sa.sin_addr.s_addr;
172 }
173 
174 int TCPSocket::getLocalPort()
175 {
176  sockaddr_in sa;
177  memset(&sa, 0, sizeof(sockaddr_in));
178  socklen_t sa_len = sizeof(sa);
179  if (getsockname(m_fd, (struct sockaddr*)&sa, (socklen_t*)&sa_len) != 0) {
180  return 0;
181  }
182  return ntohs(sa.sin_port);
183 }
184 
185 unsigned int TCPSocket::getAddress()
186 {
187  struct hostent* host = NULL;
188  host = gethostbyname(m_ip.c_str());
189  if (host == NULL) {
190  unsigned long ip_address = inet_addr(m_ip.c_str());
191  if ((signed long) ip_address < 0) {
192  throw (std::exception());
193  throw (IOException("Wrong host name or ip"));
194  } else {
195  host = gethostbyaddr((char*)&ip_address, sizeof(ip_address), AF_INET);
196  }
197  }
198  return (*(unsigned long*) host->h_addr_list[0]);
199 }
Belle2::IOException
Definition: IOException.h:12
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19