Belle II Software  release-05-02-19
TCPServerSocket.cc
1 #include "daq/slc/system/TCPServerSocket.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 #include <errno.h>
11 
12 #include <netinet/in.h>
13 #include <netdb.h>
14 
15 using namespace Belle2;
16 
17 int TCPServerSocket::open(const std::string& ip, unsigned short port,
18  int nqueue)
19 {
20  m_ip = ip;
21  m_port = port;
22  return open(nqueue);
23 }
24 
25 int TCPServerSocket::open(int nqueue)
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  m_fd = socket(PF_INET, SOCK_STREAM, 0);
37  if (m_fd == -1) {
38  m_fd = 0;
39  throw (IOException("Fail to create a server socket."));
40  }
41  int enable = 1;
42  if (setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == -1) {
43  m_fd = 0;
44  throw (IOException("Fail to set resue address for the socket."));
45  }
46  struct hostent* host = NULL;
47  host = gethostbyname(m_ip.c_str());
48  if (host == NULL) {
49  unsigned long ip_address = inet_addr(m_ip.c_str());
50  if ((signed long) ip_address < 0) {
51  throw (std::exception());
52  throw (IOException("Wrong host name or ip"));
53  } else {
54  host = gethostbyaddr((char*)&ip_address, sizeof(ip_address), AF_INET);
55  }
56  }
57  if (host == NULL) {
58  throw (IOException("Fail to get host ip: %s", m_ip.c_str()));
59  }
60  addr.sin_addr.s_addr = (*(unsigned long*)host->h_addr_list[0]);
61 
62  if (bind(m_fd, (const sockaddr*) & (addr), sizeof(sockaddr_in)) != 0) {
63  throw (IOException("Fail to bind the socket. %s:%d", m_ip.c_str(), m_port));
64  }
65  if (listen(m_fd, nqueue) != 0) {
66  throw (IOException("Fail to listen to the socket."));
67  }
68  return m_fd;
69 }
70 
71 TCPSocket TCPServerSocket::accept()
72 {
73  socklen_t len = sizeof(sockaddr_in);
74  sockaddr_in addr;
75  memset(&addr, 0, sizeof(sockaddr_in));
76  addr.sin_family = AF_INET;
77  addr.sin_addr.s_addr = INADDR_ANY;
78  addr.sin_port = htons(m_port);
79  int fd;
80  errno = 0;
81  while (true) {
82  if ((fd = ::accept(m_fd, (sockaddr*) & (addr), &len)) == -1) {
83  switch (errno) {
84  case EINTR: continue;
85  case EAGAIN: continue;
86  default:
87  perror("accept");
88  throw (IOException("Fail to accept."));
89  }
90  }
91  break;
92  }
93  TCPSocket s(fd);
94  s.m_ip = inet_ntoa(addr.sin_addr);
95  s.m_port = ntohs(addr.sin_port);
96  return s;
97 }
Belle2::IOException
Definition: IOException.h:12
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TCPSocket
Definition: TCPSocket.h:14