otsdaq  v2_05_02_indev
TCPReceiverSocket.cc
1 #include "otsdaq/NetworkUtilities/TCPReceiverSocket.h"
2 #include <sys/socket.h>
3 #include <unistd.h>
4 #include <iostream>
5 #include <sstream>
6 #include <stdexcept>
7 
8 using namespace ots;
9 
10 //==============================================================================
11 TCPReceiverSocket::TCPReceiverSocket(int socketId) : TCPSocket(socketId) { fPacket.reset(); }
12 
13 //==============================================================================
14 TCPReceiverSocket::~TCPReceiverSocket(void) {}
15 
16 //==============================================================================
17 std::string TCPReceiverSocket::receivePacket()
18 {
19  std::string retVal = "";
20  do
21  {
22  //std::cout << __PRETTY_FUNCTION__ << "Receiving..." << fPacket.isEmpty() << std::endl;
23  fPacket += receive<std::string>();
24  //std::cout << __PRETTY_FUNCTION__ << "Received!" << fPacket.isEmpty() << std::endl;
25  }
26  while(!fPacket.isEmpty() && !fPacket.decode(retVal));
27  return retVal;
28 }
29 
30 //==============================================================================
31 std::size_t TCPReceiverSocket::receive(char* buffer, std::size_t bufferSize, int /*timeoutMicroSeconds*/)
32 {
33  std::cout << __PRETTY_FUNCTION__ << "Receiving Message for socket: " << getSocketId() << std::endl;
34  if(getSocketId() == 0)
35  {
36  throw std::logic_error("Bad socket object (this object was moved)");
37  }
38  // std::cout << __PRETTY_FUNCTION__ << "WAITING: " << std::endl;
39  std::size_t dataRead = ::read(getSocketId(), buffer, bufferSize);
40  if(dataRead == static_cast<std::size_t>(-1))
41  {
42  std::stringstream error;
43  switch(errno)
44  {
45  case EBADF:
46  error << "Socket file descriptor " << getSocketId() << " is not a valid file descriptor or is not open for reading...Errno: " << errno;
47  break;
48  case EFAULT:
49  error << "Buffer is outside your accessible address space...Errno: " << errno;
50  break;
51  case ENXIO:
52  {
53  // Fatal error. Programming bug
54  error << "Read critical error caused by a programming bug...Errno: " << errno;
55  throw std::domain_error(error.str());
56  }
57  case EINTR:
58  // TODO: Check for user interrupt flags.
59  // Beyond the scope of this project
60  // so continue normal operations.
61  error << "The call was interrupted by a signal before any data was "
62  "read...Errno: "
63  << errno;
64  break;
65  case EAGAIN:
66  {
67  // recv is non blocking so this error is issued every time there are no messages to read
68  // std::cout << __PRETTY_FUNCTION__ << "Couldn't read any data: " << dataRead << std::endl;
69  // std::this_thread::sleep_for (std::chrono::seconds(1));
70  return dataRead;
71  }
72  case ENOTCONN:
73  {
74  // Connection broken.
75  // Return the data we have available and exit
76  // as if the connection was closed correctly.
77  return dataRead;
78  }
79  default:
80  {
81  error << "Read: returned -1...Errno: " << errno;
82  }
83  }
84  throw std::runtime_error(error.str());
85  }
86  else if(dataRead == static_cast<std::size_t>(0))
87  {
88  std::cout << __PRETTY_FUNCTION__ << "Connection closed!" << std::endl;
89  throw std::runtime_error("Connection closed");
90  }
91  // std::cout << __PRETTY_FUNCTION__ << "Message received with no errors for socket: "
92  // << getSocketId() << std::endl;
93  return dataRead;
94 }
95 
96 //==============================================================================
97 void TCPReceiverSocket::setReceiveTimeout(unsigned int timeoutSeconds, unsigned int timeoutMicroSeconds)
98 {
99  struct timeval tv;
100  tv.tv_sec = timeoutSeconds;
101  tv.tv_usec = timeoutMicroSeconds;
102  setsockopt(getSocketId(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
103 }