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