PageRenderTime 48ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/somanetwork/lossydatareceiver.cc

http://github.com/somaproject/libsomanetwork
C++ | 279 lines | 177 code | 72 blank | 30 comment | 25 complexity | 1c80ad589c955df8afdd9aa6a294bbd8 MD5 | raw file
  1. #include <iostream>
  2. #include <arpa/inet.h>
  3. #include "datareceiver.h"
  4. #include "eventdispatcher.h"
  5. #include "ports.h"
  6. namespace somanetwork {
  7. DataReceiver::DataReceiver(eventDispatcherPtr_t dispatch, int source, datatype_t type,
  8. bool enableReTxReq,
  9. boost::function<void (pDataPacket_t)> rdp)
  10. : source_ (source),
  11. type_ (type),
  12. pktCount_(0),
  13. latestSeq_(0),
  14. dupeCount_(0),
  15. pendingCount_(0),
  16. reTxRxCount_(0),
  17. outOfOrderCount_(0),
  18. putIn_(rdp),
  19. pDispatch_(dispatch)
  20. {
  21. struct sockaddr_in si_me, si_other;
  22. int slen=sizeof(si_other);
  23. socket_ = socket(AF_INET, SOCK_DGRAM, 17);
  24. if (socket_ < 0) {
  25. throw std::runtime_error("could not create socket");
  26. }
  27. bzero((char *) &si_me, sizeof(si_me));
  28. si_me.sin_family = AF_INET;
  29. si_me.sin_port = htons(dataPortLookup(type_, source_));
  30. si_me.sin_addr.s_addr = INADDR_ANY;
  31. int optval = 1;
  32. // confiugre socket for reuse
  33. optval = 1;
  34. int res = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
  35. &optval, sizeof (optval));
  36. if (res < 0) {
  37. throw std::runtime_error("error setting socket to reuse");
  38. }
  39. optval = 1;
  40. res = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
  41. &optval, sizeof (optval));
  42. if (res < 0) {
  43. throw std::runtime_error("error setting the broadcast bit");
  44. }
  45. optval = 500000;
  46. res = setsockopt (socket_, SOL_SOCKET, SO_RCVBUF,
  47. (const void *) &optval, sizeof(optval));
  48. if (res < 0) {
  49. throw std::runtime_error("error settng receive buffer size");
  50. }
  51. res = bind(socket_, (sockaddr*)&si_me, sizeof(si_me));
  52. if (res < 0) {
  53. throw std::runtime_error("error binding socket");
  54. }
  55. // configure the RX dispatch
  56. pDispatch_->addEvent(socket_,
  57. boost::bind(std::mem_fun(&DataReceiver::handleReceive),
  58. this, _1));
  59. }
  60. DataReceiver::~DataReceiver()
  61. {
  62. // remove from epoll
  63. pDispatch_->delEvent(socket_);
  64. close(socket_);
  65. }
  66. void DataReceiver::sendReTxReq(datasource_t src, datatype_t typ, unsigned
  67. int seq, sockaddr_in & sfrom)
  68. {
  69. char * retxbuf = new char[6];
  70. retxbuf[0] = typ;
  71. retxbuf[1] = src;
  72. unsigned int seqn = htonl(seq);
  73. memcpy(&retxbuf[2], &seqn, 4);
  74. sfrom.sin_port = htons(DATARETXPORT);
  75. sendto(socket_, &retxbuf[0], 6, 0, (sockaddr*)&sfrom , sizeof(sfrom));
  76. }
  77. void DataReceiver::handleReceive(int fd)
  78. {
  79. boost::mutex::scoped_lock lock( statusMutex_ );
  80. boost::array<char, BUFSIZE> recvbuffer;
  81. sockaddr_in sfrom;
  82. socklen_t fromlen = sizeof(sfrom);
  83. int error = recvfrom(socket_, &recvbuffer[0], BUFSIZE,
  84. 0, (sockaddr*)&sfrom, &fromlen);
  85. if ( error == -1 )
  86. {
  87. std::cerr << "error in recvfrom" << std::endl;
  88. } else
  89. {
  90. pDataPacket_t prd = newDataPacket(recvbuffer);
  91. if (prd->src != source_ or prd->typ != type_) {
  92. std::cerr << "Incorrect packet header " << std::endl
  93. << "either pkt source " << (int) prd->src
  94. << " != datarx src " << source_ << " or pkt typ "
  95. << (int) prd->typ << " != datarx typ " << type_ << std::endl;
  96. }
  97. if ( pktCount_ == 0 or prd->seq == latestSeq_ + 1)
  98. {
  99. // this is the next packet, append
  100. rawRxQueue_.push(prd);
  101. pendingCount_++;
  102. latestSeq_ = prd->seq;
  103. pktCount_++;
  104. }
  105. else if (prd->seq > latestSeq_ + 1)
  106. {
  107. // we're missing a packet; add in blanks with "missing" set
  108. sequence_t missingSeq;
  109. for (int i = 0; i < (prd->seq - (latestSeq_ +1)); i++)
  110. {
  111. pDataPacket_t missingPkt(new DataPacket_t);
  112. missingSeq = latestSeq_ + i + 1;
  113. missingPkt-> seq = missingSeq;
  114. missingPkt->typ = type_;
  115. missingPkt->src = source_;
  116. missingPkt->missing = true;
  117. rawRxQueue_.push(missingPkt);
  118. pendingCount_++;
  119. // now add missing packets
  120. missingPackets_[missingSeq] = missingPkt;
  121. // now request a retx
  122. sendReTxReq(prd->src, prd->typ,
  123. missingSeq, sfrom);
  124. }
  125. // then add this after that
  126. rawRxQueue_.push(prd);
  127. pendingCount_++;
  128. latestSeq_ = prd->seq;
  129. pktCount_++;
  130. }
  131. else
  132. {
  133. // it's in the past, which means it's either a dupe
  134. // or on our missing list
  135. // check if it's a missing packet
  136. missingPktHash_t::iterator m = missingPackets_.find(prd->seq);
  137. if (m == missingPackets_.end() )
  138. {
  139. // this was a duplicate packet; ignore
  140. dupeCount_++;
  141. }
  142. else
  143. {
  144. // get the iterator
  145. pDataPacket_t pkt((*m).second);
  146. // copy the received packet into the one that's currently in the retx buffer
  147. *pkt = *prd;
  148. missingPackets_.erase(m);
  149. pktCount_++;
  150. if (recvbuffer[6] != 0) {
  151. reTxRxCount_++;
  152. } else {
  153. outOfOrderCount_++;
  154. }
  155. }
  156. }
  157. // push packets out via output queue
  158. updateOutQueue();
  159. }
  160. }
  161. void DataReceiver::updateOutQueue()
  162. {
  163. /* Update output queue pushes new data into the output queue and writes
  164. to the output pipe until
  165. */
  166. int updateCount = 0; // the number of new packets we've added to the queue
  167. // extract out
  168. // if ((*rawRxQueue_.front()).missing == true) {
  169. // if (rawRxQueue_.size() > 10) {
  170. // DataPacket_t * rdp = rawRxQueue_.front();
  171. // //sendReTxReq(rdp->src, rdp->typ, rdp->seq);
  172. // // we should figure out something smart to do here, but right
  173. // // now there's nothing
  174. // }
  175. // }
  176. while (not rawRxQueue_.empty() and
  177. rawRxQueue_.front()->missing == false)
  178. {
  179. pDataPacket_t rdp(rawRxQueue_.front());
  180. putIn_(rdp);
  181. rawRxQueue_.pop();
  182. pendingCount_--;
  183. updateCount++ ;
  184. }
  185. }
  186. DataReceiverStats DataReceiver::getStats()
  187. {
  188. //This is now thread safe thanks to the mutex
  189. boost::mutex::scoped_lock lock( statusMutex_ );
  190. DataReceiverStats st;
  191. st.source = source_;
  192. st.type = type_;
  193. st.pktCount = pktCount_;
  194. st.latestSeq = latestSeq_;
  195. st.dupeCount = dupeCount_;
  196. st.pendingCount = pendingCount_;
  197. st.missingPacketCount = missingPackets_.size();
  198. st.reTxRxCount = reTxRxCount_;
  199. st.outOfOrderCount = outOfOrderCount_;
  200. return DataReceiverStats(st);
  201. }
  202. void DataReceiver::resetStats()
  203. {
  204. }
  205. }