otsdaq  v1_01_03
 All Classes Namespaces Functions
UDPReceiver_generator.cc
1 #include "artdaq-ots/Generators/UDPReceiver.hh"
2 
3 #include "canvas/Utilities/Exception.h"
4 #include "artdaq/Application/GeneratorMacros.hh"
5 #include "cetlib/exception.h"
6 #include "fhiclcpp/ParameterSet.h"
7 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
8 #include "artdaq-ots/Overlays/UDPFragmentWriter.hh"
9 #include "artdaq-ots/Overlays/FragmentType.hh"
10 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
11 
12 
13 #include <fstream>
14 #include <iomanip>
15 #include <iterator>
16 #include <iostream>
17 #include <sys/poll.h>
18 
19 ots::UDPReceiver::UDPReceiver(fhicl::ParameterSet const & ps)
20  : CommandableFragmentGenerator(ps)
21  , rawOutput_(ps.get<bool>("raw_output_enabled",false))
22  , rawPath_(ps.get<std::string>("raw_output_path", "/tmp"))
23  , dataport_(ps.get<int>("port",6343))
24  , ip_(ps.get<std::string>("ip","127.0.0.1"))
25  , expectedPacketNumber_(0)
26  , sendCommands_(ps.get<bool>("send_OtsUDP_commands",false))
27  , fragmentWindow_(ps.get<double>("fragment_time_window_ms", 1000))
28  , lastFrag_(std::chrono::high_resolution_clock::now())
29 {
30  datasocket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
31  if(!datasocket_)
32  {
33  throw art::Exception(art::errors::Configuration) << "UDPReceiver: Error creating socket!" << std::endl;
34  exit(1);
35  }
36 
37  struct sockaddr_in si_me_data;
38  si_me_data.sin_family = AF_INET;
39  si_me_data.sin_port = htons(dataport_);
40  si_me_data.sin_addr.s_addr = htonl(INADDR_ANY);
41  if(bind(datasocket_, (struct sockaddr *)&si_me_data, sizeof(si_me_data)) == -1)
42  {
43  throw art::Exception(art::errors::Configuration) <<
44  "UDPReceiver: Cannot bind data socket to port " << dataport_ << std::endl;
45  exit(1);
46  }
47 
48  si_data_.sin_family = AF_INET;
49  si_data_.sin_port = htons(dataport_);
50  if(inet_aton(ip_.c_str(), &si_data_.sin_addr) == 0)
51  {
52  throw art::Exception(art::errors::Configuration) <<
53  "UDPReceiver: Could not translate provided IP Address: " << ip_ << "\n";
54  exit(1);
55  }
56  mf::LogInfo("UDPReceiver") << "UDP Receiver Construction Complete!" << std::endl;
57 }
58 
59 ots::UDPReceiver::~UDPReceiver()
60 {
61  receiverThread_.join();
62 }
63 
64 void ots::UDPReceiver::start() {
65 
66 
67  std::cout << __COUT_HDR_FL__ << "Start." << std::endl;
68  mf::LogInfo("UDPReceiver") << "Starting..." << std::endl;
69 
70  receiverThread_ = std::thread(&UDPReceiver::receiveLoop_,this);
71 }
72 
73 void ots::UDPReceiver::receiveLoop_() {
74 
75  uint8_t droppedPackets = 0;
76  while(!should_stop()) {
77  struct pollfd ufds[1];
78  ufds[0].fd = datasocket_;
79  ufds[0].events = POLLIN | POLLPRI;
80 
81  int rv = poll(ufds, 1, 1000);
82  if(rv > 0)
83  {
84  std::cout << __COUT_HDR_FL__ << "revents: " << ufds[0].revents << ", " << std::endl;// ufds[1].revents << std::endl;
85  if(ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
86  {
87 
88  //FIXME -> IN THE STIB GENERATOR WE DON'T HAVE A HEADER
89  //FIXME -> IN THE STIB GENERATOR WE DON'T HAVE A HEADER
90  //FIXME -> IN THE STIB GENERATOR WE DON'T HAVE A HEADER
91  uint32_t peekBuffer[6];
92  recvfrom(datasocket_, peekBuffer, sizeof(peekBuffer), MSG_PEEK,
93  (struct sockaddr *) &si_data_, (socklen_t*)sizeof(si_data_));
94 
95  mf::LogInfo("UDPReceiver") << "Received UDP Packet with sequence number " << std::hex << "0x" << (int)peekBuffer[1] << "!" << std::dec;
96  std::cout << __COUT_HDR_FL__ << "peekBuffer[1] == expectedPacketNumber_: " << std::hex << (int)peekBuffer[1] << " =?= " << (int)expectedPacketNumber_ << std::endl;
97 
98  uint32_t seqNum = peekBuffer[5];
99  //ReturnCode dataCode = getReturnCode(peekBuffer[0]);
100  if(seqNum >= expectedPacketNumber_ || (seqNum < 10 && expectedPacketNumber_ > 240) || droppedPackets > 0 || expectedPacketNumber_ - seqNum > 20)
101  {
102  if(seqNum != expectedPacketNumber_ && (seqNum >= expectedPacketNumber_ || (seqNum < 10 && expectedPacketNumber_ > 200)))
103  {
104  int deltaHi = seqNum - expectedPacketNumber_;
105  int deltaLo = 4294967295 + seqNum - expectedPacketNumber_;
106  droppedPackets += deltaLo;// < 255 ? deltaLo : deltaHi;
107  mf::LogWarning("UDPReceiver") << "Dropped/Delayed packets detected: " << std::dec << std::to_string(droppedPackets);
108  expectedPacketNumber_ = seqNum;
109  } else if (seqNum != expectedPacketNumber_) {
110  int delta = expectedPacketNumber_ - seqNum;
111  mf::LogWarning("UDPReceiver") << std::dec << "Sequence Number significantly different than expected! (delta: " << delta << ")";
112  }
113 
114  packetBuffer_t* buffer = new packetBuffer_t();
115  memset(&((*buffer).at(0)),0,sizeof(packetBuffer_t));
116  int DJN= recvfrom(datasocket_, &(*buffer).at(0), sizeof(packetBuffer_t), 0,(struct sockaddr *) &si_data_, (socklen_t*)sizeof(si_data_));
117  mf::LogInfo("DJN UDPReceiver") << "UDP packet recvfrom got Nbytes=" << (int)DJN << " into buffer.";
118 
119  if(droppedPackets == 0) {
120  std::lock_guard<std::mutex> lock(receiveBufferLock_);
121  receiveBuffers_.emplace_back(std::unique_ptr<packetBuffer_t>(buffer));
122  }
123  else {
124  bool found = false;
125  for(packetBuffer_list_t::reverse_iterator it = packetBuffers_.rbegin(); it != packetBuffers_.rend(); ++it) {
126  if(seqNum < (*it)->at(1)) {
127  std::lock_guard<std::mutex> lock(receiveBufferLock_);
128  receiveBuffers_.emplace(it.base(), std::unique_ptr<packetBuffer_t>(buffer));
129  droppedPackets--;
130  expectedPacketNumber_--;
131  found = true;
132  }
133  }
134  if(!found) {
135  std::lock_guard<std::mutex> lock(receiveBufferLock_);
136  receiveBuffers_.emplace_back(std::unique_ptr<packetBuffer_t>(buffer));
137  }
138  }
139  mf::LogInfo("UDPReceiver") << "Now placing UDP packet with sequence number " << std::hex << (int)seqNum << " into buffer." << std::dec;
140  }
141 
142  ++expectedPacketNumber_;
143  }
144  }
145  std::cout << __COUT_HDR_FL__ << "waiting..." << std::endl;
146 
147  }
148  mf::LogInfo("UDPReceiver") << "receive Loop exiting..." << std::endl;
149 }
150 
151 bool ots::UDPReceiver::getNext_(artdaq::FragmentPtrs & output)
152 {
153  if (should_stop()) {
154  return false;
155  }
156 
157  while(receiveBuffers_.size() == 0 && isTimerExpired_()) { usleep(1000); }
158 
159  {
160  std::lock_guard<std::mutex> lock(receiveBufferLock_);
161  std::move(receiveBuffers_.begin(), receiveBuffers_.end(), std::inserter(packetBuffers_,packetBuffers_.end()));
162  receiveBuffers_.clear();
163  }
164  mf::LogInfo("UDPReceiver") << "Calling ProcessData";
165  ProcessData_(output);
166 
167  mf::LogInfo("UDPReceiver") << "Returning output of size " << output.size() << " to TriggeredFragmentGenerator";
168  return true;
169 }
170 
171  void ots::UDPReceiver::ProcessData_(artdaq::FragmentPtrs & output) {
172 
174  metadata.port = dataport_;
175  metadata.address = si_data_.sin_addr.s_addr;
176 
177  std::size_t initial_payload_size = 0;
178 
179  output.emplace_back( artdaq::Fragment::FragmentBytes(initial_payload_size,
180  ev_counter(), fragment_id(),
181  ots::detail::FragmentType::UDP, metadata) );
182  // We now have a fragment to contain this event:
183  ots::UDPFragmentWriter thisFrag(*output.back());
184 
185  std::cout << __COUT_HDR_FL__ << "Received data, now placing data with UDP sequence number "
186  << std::hex << static_cast<int>((*packetBuffers_.front()).at(1))
187  << " into UDPFragment" << std::endl;
188  thisFrag.resize(64050 * packetBuffers_.size() + 1);
189  std::ofstream rawOutput;
190  if(rawOutput_) {
191  std::string outputPath = rawPath_ + "/UDPReceiver-"+ ip_ + ":" + std::to_string(dataport_) + ".bin";
192  rawOutput.open(outputPath, std::ios::out | std::ios::app | std::ios::binary );
193  }
194 
195  DataType dataType = getDataType((*packetBuffers_.front()).at(0));
196  thisFrag.set_hdr_type((int)dataType);
197  int pos = 0;
198  for(auto jj = packetBuffers_.begin(); jj != packetBuffers_.end(); ++jj) {
199  for(int ii = 0; ii < 64050; ++ii) {
200  // Null-terminate string types
201  if((*jj)->at(ii) == 0 && (dataType == DataType::JSON || dataType == DataType::String)) { break; }
202 
203  if(rawOutput_) rawOutput.write((char*)&((*jj)->at(ii)), sizeof(uint8_t));
204  *(thisFrag.dataBegin() + pos) = (*jj)->at(ii);
205  ++pos;
206  }
207  }
208  packetBuffers_.clear();
209 
210  if(dataType == DataType::JSON || dataType == DataType::String) {
211  *(thisFrag.dataBegin() + pos) = 0;
212  char zero =0;
213  if(rawOutput_) rawOutput.write(&zero, sizeof(char));
214  }
215  if(rawOutput_) rawOutput.close();
216 }
217 
218 void ots::UDPReceiver::send(CommandType command)
219 {
220  if(sendCommands_) {
221  CommandPacket packet;
222  packet.type = command;
223  packet.dataSize = 0;
224  sendto(datasocket_,&packet,sizeof(packet),0, (struct sockaddr *) &si_data_, sizeof(si_data_));
225  }
226 }
227 
228 bool ots::UDPReceiver::isTimerExpired_()
229 {
230  auto now = std::chrono::high_resolution_clock::now();
231  auto diff = std::chrono::duration<double, std::milli>(now - lastFrag_).count();
232  return diff > fragmentWindow_;
233 }
234 
235 void ots::UDPReceiver::stop()
236 {
237 #pragma message "Using default implementation of UDPReceiver::stop()"
238 }
239 
240 void ots::UDPReceiver::stopNoMutex()
241 {
242 #pragma message "Using default implementation of UDPReceiver::stopNoMutex()"
243 }
244 
245 // The following macro is defined in artdaq's GeneratorMacros.hh header
246 DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(ots::UDPReceiver)