tdaq-develop-2025-02-12
TCPTransmitterSocket.cc
1 #include "otsdaq/NetworkUtilities/TCPTransmitterSocket.h"
2 #include <string.h>
3 #include <sys/socket.h>
4 #include <unistd.h>
5 #include <stdexcept>
6 #include "otsdaq/NetworkUtilities/TCPPacket.h"
7 // #include <iostream>
8 
9 using namespace ots;
10 
11 //==============================================================================
12 TCPTransmitterSocket::TCPTransmitterSocket(int socketId) : TCPSocket(socketId) {}
13 
14 //==============================================================================
15 TCPTransmitterSocket::~TCPTransmitterSocket(void) {}
16 
17 //==============================================================================
18 void TCPTransmitterSocket::sendPacket(char const* buffer, std::size_t size)
19 {
20  send(TCPPacket::encode(buffer, size));
21 }
22 
23 //==============================================================================
24 void TCPTransmitterSocket::sendPacket(const std::string& buffer)
25 {
26  send(TCPPacket::encode(buffer));
27 }
28 
29 //==============================================================================
30 void TCPTransmitterSocket::send(char const* buffer,
31  std::size_t size,
32  bool forceEmptyPacket)
33 {
34  if(size == 0 && !forceEmptyPacket)
35  {
36  std::cout << __PRETTY_FUNCTION__ << "I am sorry but I won't send an empty packet!"
37  << std::endl;
38  return;
39  }
40  std::size_t sentBytes = ::send(getSocketId(), buffer, size, MSG_NOSIGNAL);
41  if(sentBytes == static_cast<std::size_t>(-1))
42  {
43  switch(errno)
44  {
45  // case EINVAL:
46  // case EBADF:
47  // case ECONNRESET:
48  // case ENXIO:
49  case EPIPE: {
50  // Fatal error. Programming bug
51  throw std::runtime_error(std::string("Write: critical error: ") +
52  strerror(errno));
53  }
54  // case EDQUOT:
55  // case EFBIG:
56  // case EIO:
57  // case ENETDOWN:
58  // case ENETUNREACH:
59  case ENOSPC: {
60  // Resource acquisition failure or device error
61  throw std::runtime_error(std::string("Write: resource failure: ") +
62  strerror(errno));
63  }
64  case EINTR:
65  // TODO: Check for user interrupt flags.
66  // Beyond the scope of this project
67  // so continue normal operations.
68  case EAGAIN: {
69  // Temporary error.
70  throw std::runtime_error(std::string("Write: temporary error: ") +
71  strerror(errno));
72  }
73  default: {
74  throw std::runtime_error(std::string("Write: returned -1: ") +
75  strerror(errno));
76  }
77  }
78  }
79 }
80 
81 //==============================================================================
82 void TCPTransmitterSocket::send(const std::string& buffer)
83 {
84  send(&buffer.at(0), buffer.size());
85 }
86 
87 //==============================================================================
88 void TCPTransmitterSocket::send(const std::vector<char>& buffer)
89 {
90  send(&buffer.at(0), buffer.size());
91 }
92 
93 //==============================================================================
94 void TCPTransmitterSocket::send(const std::vector<uint16_t>& buffer)
95 {
96  send((const char*)&buffer.at(0), buffer.size());
97 }
98 
99 //==============================================================================
100 void TCPTransmitterSocket::setSendTimeout(unsigned int timeoutSeconds,
101  unsigned int timeoutMicroSeconds)
102 {
103  struct timeval tv;
104  tv.tv_sec = timeoutSeconds;
105  tv.tv_usec = timeoutMicroSeconds;
106  setsockopt(getSocketId(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof tv);
107 }