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