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