otsdaq  v2_04_01
ReceiverSocket.cc
1 #include "otsdaq-core/NetworkUtilities/ReceiverSocket.h"
2 #include "otsdaq-core/Macros/CoutMacros.h"
3 #include "otsdaq-core/MessageFacility/MessageFacility.h"
4 #include "otsdaq-core/NetworkUtilities/NetworkConverters.h"
5 
6 #include <iomanip> /* for setfill */
7 #include <iostream>
8 #include <sstream>
9 
10 #include <arpa/inet.h>
11 #include <sys/time.h>
12 
13 using namespace ots;
14 
15 //========================================================================================================================
16 ReceiverSocket::ReceiverSocket(std::string IPAddress, unsigned int port)
17  : Socket(IPAddress, port)
18  , addressLength_(sizeof(fromAddress_))
19  , numberOfBytes_(0)
20  , readCounter_(0)
21 {
22  __COUT__ << "ReceiverSocket constructor " << IPAddress << ":" << port << __E__;
23 }
24 
25 //========================================================================================================================
26 // protected constructor
27 ReceiverSocket::ReceiverSocket(void)
28  : addressLength_(sizeof(fromAddress_)), numberOfBytes_(0), readCounter_(0)
29 {
30  __COUT__ << "ReceiverSocket constructor" << __E__;
31 }
32 
33 //========================================================================================================================
34 ReceiverSocket::~ReceiverSocket(void) {}
35 
36 //========================================================================================================================
37 int ReceiverSocket::receive(std::string& buffer,
38  unsigned int timeoutSeconds,
39  unsigned int timeoutUSeconds,
40  bool verbose)
41 {
42  return receive(
43  buffer, dummyIPAddress_, dummyPort_, timeoutSeconds, timeoutUSeconds, verbose);
44 }
45 
46 //========================================================================================================================
47 // receive ~~
48 // returns 0 on success, -1 on failure
49 // NOTE: must call Socket::initialize before receiving!
50 int ReceiverSocket::receive(std::string& buffer,
51  unsigned long& fromIPAddress,
52  unsigned short& fromPort,
53  unsigned int timeoutSeconds,
54  unsigned int timeoutUSeconds,
55  bool verbose)
56 {
57  // lockout other receivers for the remainder of the scope
58  std::lock_guard<std::mutex> lock(receiveMutex_);
59 
60  // set timeout period for select()
61  timeout_.tv_sec = timeoutSeconds;
62  timeout_.tv_usec = timeoutUSeconds;
63 
64  FD_ZERO(&fileDescriptor_);
65  FD_SET(socketNumber_, &fileDescriptor_);
66  select(socketNumber_ + 1, &fileDescriptor_, 0, 0, &timeout_);
67 
68  if(FD_ISSET(socketNumber_, &fileDescriptor_))
69  {
70  buffer.resize(maxSocketSize_); // NOTE: this is inexpensive according to
71  // Lorenzo/documentation in C++11 (only increases
72  // size once and doesn't decrease size)
73  if((numberOfBytes_ = recvfrom(socketNumber_,
74  &buffer[0],
75  maxSocketSize_,
76  0,
77  (struct sockaddr*)&fromAddress_,
78  &addressLength_)) == -1)
79  {
80  __COUT__ << "At socket with IPAddress: " << getIPAddress()
81  << " port: " << getPort() << std::endl;
82  __SS__ << "Error reading buffer from\tIP:\t";
83  std::string fromIP = inet_ntoa(fromAddress_.sin_addr);
84  fromIPAddress = fromAddress_.sin_addr.s_addr;
85  fromPort = fromAddress_.sin_port;
86  for(int i = 0; i < 4; i++)
87  {
88  ss << ((fromIPAddress << (i * 8)) & 0xff);
89  if(i < 3)
90  ss << ".";
91  }
92  ss << "\tPort\t" << ntohs(fromPort) << " IP " << fromIP << std::endl;
93  __COUT__ << "\n" << ss.str();
94  return -1;
95  }
96  // char address[INET_ADDRSTRLEN];
97  // inet_ntop(AF_INET, &(fromAddress.sin_addr), address, INET_ADDRSTRLEN);
98  fromIPAddress = fromAddress_.sin_addr.s_addr;
99  fromPort = fromAddress_.sin_port;
100 
101  //__COUT__ << __PRETTY_FUNCTION__ << "IP: " << std::hex << fromIPAddress <<
102  // std::dec << " port: " << fromPort << std::endl;
103  //__COUT__ << "Socket Number: " << socketNumber_ << " number of bytes: " <<
104  // nOfBytes << std::endl; gettimeofday(&tvend,NULL);
105  //__COUT__ << "started at" << tvbegin.tv_sec << ":" <<tvbegin.tv_usec <<
106  // std::endl;
107  //__COUT__ << "ended at" << tvend.tv_sec << ":" <<tvend.tv_usec << std::endl;
108 
109  // NOTE: this is inexpensive according to Lorenzo/documentation in C++11 (only
110  // increases size once and doesn't decrease size)
111  buffer.resize(numberOfBytes_);
112  readCounter_ = 0;
113 
114  if(verbose) // debug
115  {
116  std::string fromIP = inet_ntoa(fromAddress_.sin_addr);
117 
118  __COUT__ << "Receiving "
119  << " at: " << getIPAddress() << ":" << getPort()
120  << " from: " << fromIP;
121  std::cout << ":" << ntohs(fromPort) << " size: " << buffer.size()
122  << std::endl;
123 
124  // std::stringstream ss;
125  // ss << "\tRx";
126  // uint32_t begin = 0;
127  // for(uint32_t i=begin; i<buffer.size(); i++)
128  // {
129  // if(i==begin+2) ss << ":::";
130  // else if(i==begin+10) ss << ":::";
131  // ss << std::setfill('0') << std::setw(2) << std::hex <<
132  //(((int16_t) buffer[i]) &0xFF) << "-" << std::dec;
133  // }
134  // ss << std::endl;
135  // std::cout << ss.str();
136  }
137  }
138  else
139  {
140  ++readCounter_;
141 
142  if(verbose)
143  __COUT__ << "No new messages for " << timeoutSeconds + timeoutUSeconds / 1000.
144  << "s (Total "
145  << readCounter_ * (timeoutSeconds + timeoutUSeconds / 1000.)
146  << "s). Read request timed out receiving on "
147  << " " << getIPAddress() << ":" << getPort() << std::endl;
148  return -1;
149  }
150 
151  return 0;
152 }
153 
154 //========================================================================================================================
155 int ReceiverSocket::receive(std::vector<uint32_t>& buffer,
156  unsigned int timeoutSeconds,
157  unsigned int timeoutUSeconds,
158  bool verbose)
159 {
160  return receive(
161  buffer, dummyIPAddress_, dummyPort_, timeoutSeconds, timeoutUSeconds, verbose);
162 }
163 
164 //========================================================================================================================
165 // receive ~~
166 // returns 0 on success, -1 on failure
167 // NOTE: must call Socket::initialize before receiving!
168 int ReceiverSocket::receive(std::vector<uint32_t>& buffer,
169  unsigned long& fromIPAddress,
170  unsigned short& fromPort,
171  unsigned int timeoutSeconds,
172  unsigned int timeoutUSeconds,
173  bool verbose)
174 {
175  // lockout other receivers for the remainder of the scope
176  std::lock_guard<std::mutex> lock(receiveMutex_);
177 
178  // set timeout period for select()
179  timeout_.tv_sec = timeoutSeconds;
180  timeout_.tv_usec = timeoutUSeconds;
181 
182  FD_ZERO(&fileDescriptor_);
183  FD_SET(socketNumber_, &fileDescriptor_);
184  select(socketNumber_ + 1, &fileDescriptor_, 0, 0, &timeout_);
185  __COUT__ << "Is this a successful reeeaaad???" << std::endl;
186 
187  if(FD_ISSET(socketNumber_, &fileDescriptor_))
188  {
189  buffer.resize(maxSocketSize_ / sizeof(uint32_t)); // NOTE: this is inexpensive
190  // according to
191  // Lorezno/documentation in
192  // C++11 (only increases size
193  // once and doesn't decrease
194  // size)
195  if((numberOfBytes_ = recvfrom(socketNumber_,
196  &buffer[0],
197  maxSocketSize_,
198  0,
199  (struct sockaddr*)&fromAddress_,
200  &addressLength_)) == -1)
201  {
202  __COUT__ << "At socket with IPAddress: " << getIPAddress()
203  << " port: " << getPort() << std::endl;
204  __SS__ << "Error reading buffer from\tIP:\t";
205  for(int i = 0; i < 4; i++)
206  {
207  ss << ((fromIPAddress << (i * 8)) & 0xff);
208  if(i < 3)
209  ss << ".";
210  }
211  ss << "\tPort\t" << fromPort << std::endl;
212  __COUT__ << "\n" << ss.str();
213  return -1;
214  }
215  // char address[INET_ADDRSTRLEN];
216  // inet_ntop(AF_INET, &(fromAddress.sin_addr), address, INET_ADDRSTRLEN);
217  fromIPAddress = fromAddress_.sin_addr.s_addr;
218  fromPort = fromAddress_.sin_port;
219 
220  //__COUT__ << __PRETTY_FUNCTION__ << "IP: " << std::hex << fromIPAddress <<
221  // std::dec << " port: " << fromPort << std::endl;
222  //__COUT__ << "Socket Number: " << socketNumber_ << " number of bytes: " <<
223  // nOfBytes << std::endl; gettimeofday(&tvend,NULL);
224  //__COUT__ << "started at" << tvbegin.tv_sec << ":" <<tvbegin.tv_usec <<
225  // std::endl;
226  //__COUT__ << "ended at" << tvend.tv_sec << ":" <<tvend.tv_usec << std::endl;
227 
228  // NOTE: this is inexpensive according to Lorenzo/documentation in C++11 (only
229  // increases size once and doesn't decrease size)
230  buffer.resize(numberOfBytes_ / sizeof(uint32_t));
231  readCounter_ = 0;
232  }
233  else
234  {
235  ++readCounter_;
236  struct sockaddr_in sin;
237  socklen_t len = sizeof(sin);
238  getsockname(socketNumber_, (struct sockaddr*)&sin, &len);
239 
240  if(verbose)
241  __COUT__ << __COUT_HDR_FL__ << "No new messages for "
242  << timeoutSeconds + timeoutUSeconds / 1000. << "s (Total "
243  << readCounter_ * (timeoutSeconds + timeoutUSeconds / 1000.)
244  << "s). Read request timed out for port: " << ntohs(sin.sin_port)
245  << std::endl;
246  return -1;
247  }
248  __COUT__ << "This a successful reeeaaad" << std::endl;
249  return 0;
250 }