00001 #define TRACE_NAME "UDPReceiver"
00002 #include "artdaq/DAQdata/Globals.hh"
00003
00004 #include "artdaq-demo/Generators/UDPReceiver.hh"
00005
00006 #include "canvas/Utilities/Exception.h"
00007
00008 #include "artdaq/Application/GeneratorMacros.hh"
00009 #include "cetlib_except/exception.h"
00010 #include "fhiclcpp/ParameterSet.h"
00011 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
00012 #include "messagefacility/MessageLogger/MessageLogger.h"
00013 #include "artdaq-core-demo/Overlays/UDPFragmentWriter.hh"
00014
00015 #include <fstream>
00016 #include <iomanip>
00017 #include <iterator>
00018 #include <iostream>
00019 #include <sys/poll.h>
00020
00021 demo::UDPReceiver::UDPReceiver(fhicl::ParameterSet const& ps)
00022 : CommandableFragmentGenerator(ps)
00023 , dataport_(ps.get<int>("port", 6343))
00024 , ip_(ps.get<std::string>("ip", "127.0.0.1"))
00025 , expectedPacketNumber_(0)
00026 , sendCommands_(ps.get<bool>("send_CAPTAN_commands", false))
00027 , rawOutput_(ps.get<bool>("raw_output_enabled", false))
00028 , rawPath_(ps.get<std::string>("raw_output_path", "/tmp"))
00029 {
00030 datasocket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00031 if (datasocket_ < 0)
00032 {
00033 throw art::Exception(art::errors::Configuration) << "UDPReceiver: Error creating socket!" << std::endl;
00034 exit(1);
00035 }
00036
00037 struct sockaddr_in si_me_data;
00038 si_me_data.sin_family = AF_INET;
00039 si_me_data.sin_port = htons(dataport_);
00040 si_me_data.sin_addr.s_addr = htonl(INADDR_ANY);
00041 if (bind(datasocket_, (struct sockaddr *)&si_me_data, sizeof(si_me_data)) == -1)
00042 {
00043 throw art::Exception(art::errors::Configuration) <<
00044 "UDPReceiver: Cannot bind data socket to port " << dataport_ << std::endl;
00045 exit(1);
00046 }
00047
00048 si_data_.sin_family = AF_INET;
00049 si_data_.sin_port = htons(dataport_);
00050 if (inet_aton(ip_.c_str(), &si_data_.sin_addr) == 0)
00051 {
00052 throw art::Exception(art::errors::Configuration) <<
00053 "UDPReceiver: Could not translate provided IP Address: " << ip_ << "\n";
00054 exit(1);
00055 }
00056 }
00057
00058
00059 bool demo::UDPReceiver::getNext_(artdaq::FragmentPtrs& frags)
00060 {
00061 if (should_stop())
00062 {
00063 return false;
00064 }
00065
00066 demo::UDPFragment::Metadata metadata;
00067 metadata.port = dataport_;
00068 metadata.address = si_data_.sin_addr.s_addr;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 std::size_t initial_payload_size = 0;
00089
00090 frags.emplace_back(artdaq::Fragment::FragmentBytes(initial_payload_size,
00091 ev_counter(), fragment_id(),
00092 artdaq::Fragment::FirstUserFragmentType, metadata));
00093
00094 demo::UDPFragmentWriter thisFrag(*frags.back());
00095
00096 bool haveData = false;
00097 int16_t burst_end = -1;
00098 uint8_t droppedPackets = 0;
00099 while (!haveData)
00100 {
00101 if (should_stop())
00102 {
00103 return false;
00104 }
00105 struct pollfd ufds[1];
00106 ufds[0].fd = datasocket_;
00107 ufds[0].events = POLLIN | POLLPRI;
00108
00109 int rv = poll(ufds, 1, 1000);
00110 if (rv > 0)
00111 {
00112
00113 if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
00114 {
00115 uint8_t peekBuffer[2];
00116 recvfrom(datasocket_, peekBuffer, sizeof(peekBuffer), MSG_PEEK,
00117 (struct sockaddr *) &si_data_, (socklen_t*)sizeof(si_data_));
00118
00119 TLOG(TLVL_INFO) << "Recieved UDP Packet with sequence number " << std::hex << (int)peekBuffer[1] << "!";
00120
00121
00122 uint8_t seqNum = peekBuffer[1];
00123 ReturnCode dataCode = getReturnCode(peekBuffer[0]);
00124 if (seqNum >= expectedPacketNumber_ || (seqNum < 10 && expectedPacketNumber_ > 200) || droppedPackets > 0 || expectedPacketNumber_ - seqNum > 20)
00125 {
00126 if (seqNum != expectedPacketNumber_ && (seqNum >= expectedPacketNumber_ || (seqNum < 10 && expectedPacketNumber_ > 200)))
00127 {
00128 int deltaHi = seqNum - expectedPacketNumber_;
00129 int deltaLo = 255 + seqNum - expectedPacketNumber_;
00130 droppedPackets += deltaLo < 255 ? deltaLo : deltaHi;
00131 TLOG(TLVL_WARNING) << "Dropped/Delayed packets detected: " << droppedPackets << std::endl;
00132 expectedPacketNumber_ = seqNum;
00133 }
00134 else if (seqNum != expectedPacketNumber_)
00135 {
00136 int delta = expectedPacketNumber_ - seqNum;
00137 TLOG(TLVL_WARNING) << "Sequence Number significantly different than expected! (delta: " << delta << ")";
00138 }
00139
00140 if (dataCode == ReturnCode::Read || dataCode == ReturnCode::First)
00141 {
00142 packetBuffers_.clear();
00143 packetBuffer_t buffer;
00144 memset(&buffer[0], 0, sizeof(packetBuffer_t));
00145 recvfrom(datasocket_, &buffer[0], sizeof(packetBuffer_t), 0, (struct sockaddr *) &si_data_, (socklen_t*)sizeof(si_data_));
00146 packetBuffers_.push_back(buffer);
00147 TLOG(TLVL_DEBUG) << "Now placing UDP packet with sequence number " << std::hex << (int)seqNum << " into buffer.";
00148 if (dataCode == ReturnCode::Read) { haveData = true; }
00149 else
00150 {
00151 droppedPackets = 0;
00152 burst_end = -1;
00153 }
00154 }
00155 else if ((dataCode == ReturnCode::Middle || dataCode == ReturnCode::Last) && packetBuffers_.size() > 0)
00156 {
00157 packetBuffer_t buffer;
00158 memset(&buffer[0], 0, sizeof(packetBuffer_t));
00159 recvfrom(datasocket_, &buffer[0], sizeof(packetBuffer_t), 0, (struct sockaddr *) &si_data_, (socklen_t*)sizeof(si_data_));
00160 if (droppedPackets == 0)
00161 {
00162 packetBuffers_.push_back(buffer);
00163 }
00164 else if (burst_end == -1 || seqNum < burst_end)
00165 {
00166 bool found = false;
00167 for (packetBuffer_list_t::iterator it = packetBuffers_.begin(); it != packetBuffers_.end(); ++it)
00168 {
00169 if (seqNum < (*it)[1])
00170 {
00171 packetBuffers_.insert(it, buffer);
00172 droppedPackets--;
00173 expectedPacketNumber_--;
00174 }
00175 }
00176 if (!found)
00177 {
00178 packetBuffers_.push_back(buffer);
00179 }
00180 }
00181 TLOG(TLVL_DEBUG) << "Now placing UDP packet with sequence number " << std::hex << (int)seqNum << " into buffer.";
00182 if (dataCode == ReturnCode::Last && droppedPackets == 0)
00183 {
00184 while (getReturnCode(packetBuffers_.back()[0]) != ReturnCode::Last) { packetBuffers_.pop_back(); }
00185 haveData = true;
00186 }
00187 else if (dataCode == ReturnCode::Last) { burst_end = seqNum; }
00188 else if (burst_end >= 0 && droppedPackets == 0)
00189 {
00190 while (getReturnCode(packetBuffers_.back()[0]) != ReturnCode::Last) { packetBuffers_.pop_back(); }
00191 haveData = true;
00192 }
00193 }
00194
00195 ++expectedPacketNumber_;
00196 }
00197 else
00198 {
00199 packetBuffer_t discardBuffer;
00200 recvfrom(datasocket_, &discardBuffer[0], sizeof(discardBuffer), 0, (struct sockaddr *) &si_data_, (socklen_t*)sizeof(si_data_));
00201 TLOG(TLVL_WARNING) << "Out-of-sequence packet detected and discarded!";
00202 }
00203 }
00204 }
00205 }
00206
00207 packetBuffer_t& firstPacket = packetBuffers_.front();
00208 TLOG(TLVL_DEBUG) << "Recieved data, now placing data with UDP sequence number " << (int)firstPacket[1] << " into UDPFragment";
00209 thisFrag.resize(1500 * packetBuffers_.size() + 1);
00210 std::ofstream output;
00211 if (rawOutput_)
00212 {
00213 std::string outputPath = rawPath_ + "/UDPReceiver-" + ip_ + ":" + std::to_string(dataport_) + ".bin";
00214 output.open(outputPath, std::ios::out | std::ios::app | std::ios::binary);
00215 }
00216
00217 DataType dataType = getDataType(firstPacket[0]);
00218 thisFrag.set_hdr_type((int)dataType);
00219 int pos = 0;
00220 for (auto jj : packetBuffers_)
00221 {
00222 for (int ii = 2; ii < 1500; ++ii)
00223 {
00224
00225 if (jj[ii] == 0 && (dataType == DataType::JSON || dataType == DataType::String)) { break; }
00226
00227 if (rawOutput_) output.write((char*)&(jj[ii]), sizeof(uint8_t));
00228 *(thisFrag.dataBegin() + pos) = jj[ii];
00229 ++pos;
00230 }
00231 }
00232 if (dataType == DataType::JSON || dataType == DataType::String)
00233 {
00234 *(thisFrag.dataBegin() + pos) = 0;
00235 char zero = 0;
00236 if (rawOutput_) output.write(&zero, sizeof(char));
00237 }
00238 if (rawOutput_) output.close();
00239
00240 return true;
00241 }
00242
00243 void demo::UDPReceiver::start()
00244 {
00245 send(CommandType::Start_Burst);
00246 }
00247
00248 void demo::UDPReceiver::stop()
00249 {
00250 send(CommandType::Stop_Burst);
00251 }
00252
00253 void demo::UDPReceiver::pause()
00254 {
00255 send(CommandType::Stop_Burst);
00256 }
00257
00258 void demo::UDPReceiver::resume()
00259 {
00260 send(CommandType::Start_Burst);
00261 }
00262
00263 void demo::UDPReceiver::send(CommandType command)
00264 {
00265 if (sendCommands_)
00266 {
00267 CommandPacket packet;
00268 packet.type = command;
00269 packet.dataSize = 0;
00270 sendto(datasocket_, &packet, sizeof(packet), 0, (struct sockaddr *) &si_data_, sizeof(si_data_));
00271 }
00272 }
00273
00274
00275 DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(demo::UDPReceiver)