/ACE/protocols/ace/RMCast/Link.cpp

https://github.com/DOCGroup/ATCD · C++ · 330 lines · 223 code · 63 blank · 44 comment · 45 complexity · ddd231faed9834f7166843d692587ce7 MD5 · raw file

  1. // author : Boris Kolpackov <boris@kolpackov.net>
  2. #include "ace/Time_Value.h" // ACE_Time_Value
  3. #include "ace/OS_NS_stdio.h"
  4. #include "ace/OS_NS_stdlib.h"
  5. #include "ace/OS_NS_time.h"
  6. #include "ace/OS_NS_sys_socket.h"
  7. #include "Link.h"
  8. namespace ACE_RMCast
  9. {
  10. Link::
  11. ~Link ()
  12. {
  13. ssock_.close ();
  14. rsock_.close ();
  15. }
  16. Link::
  17. Link (Address const& addr, Parameters const& params)
  18. : params_ (params),
  19. addr_ (addr),
  20. ssock_ (Address (static_cast<unsigned short> (0),
  21. static_cast<ACE_UINT32> (INADDR_ANY)),
  22. AF_INET,
  23. IPPROTO_UDP,
  24. 1),
  25. stop_ (false)
  26. {
  27. ACE_OS::srand ((unsigned int) ACE_OS::time (0));
  28. rsock_.set_option (IP_MULTICAST_LOOP, 0);
  29. // rsock_.set_option (IP_MULTICAST_TTL, 0);
  30. // Set recv/send buffers.
  31. //
  32. {
  33. int r (131070);
  34. int s (sizeof (r));
  35. static_cast<ACE_SOCK&> (rsock_).set_option (
  36. SOL_SOCKET, SO_RCVBUF, &r, s);
  37. static_cast<ACE_SOCK&> (ssock_).set_option (
  38. SOL_SOCKET, SO_RCVBUF, &r, s);
  39. rsock_.get_option (SOL_SOCKET, SO_RCVBUF, &r, &s);
  40. //cerr << 5 << "recv buffer size: " << r << endl;
  41. ssock_.get_option (SOL_SOCKET, SO_RCVBUF, &r, &s);
  42. //cerr << 5 << "send buffer size: " << r << endl;
  43. }
  44. // Bind address and port.
  45. //
  46. if (ACE_OS::connect (ssock_.get_handle (),
  47. reinterpret_cast<sockaddr*> (addr_.get_addr ()),
  48. addr_.get_addr_size ()) == -1)
  49. {
  50. ACE_OS::perror ("connect: ");
  51. ACE_OS::abort ();
  52. }
  53. ssock_.get_local_addr (self_);
  54. //cerr << 5 << "self: " << self_ << endl;
  55. }
  56. void Link::
  57. in_start (In_Element* in)
  58. {
  59. Element::in_start (in);
  60. rsock_.join (addr_);
  61. // Start receiving thread.
  62. //
  63. recv_mgr_.spawn (recv_thunk, this);
  64. }
  65. void Link::
  66. out_start (Out_Element* out)
  67. {
  68. Element::out_start (out);
  69. }
  70. void Link::
  71. in_stop ()
  72. {
  73. // Stop receiving thread.
  74. //
  75. {
  76. Lock l (mutex_);
  77. stop_ = true;
  78. }
  79. recv_mgr_.wait ();
  80. Element::in_stop ();
  81. }
  82. void Link::send (Message_ptr m)
  83. {
  84. // Simulate message loss and reordering.
  85. //
  86. if (params_.simulator ())
  87. {
  88. if ((ACE_OS::rand () % 17) != 0)
  89. {
  90. Lock l (mutex_);
  91. if (hold_.get ())
  92. {
  93. send_ (m);
  94. send_ (hold_);
  95. hold_ = Message_ptr (0);
  96. }
  97. else
  98. {
  99. if ((ACE_OS::rand () % 17) != 0)
  100. {
  101. send_ (m);
  102. }
  103. else
  104. {
  105. hold_ = m;
  106. // Make a copy in M so that the reliable loop below
  107. // won't add FROM and TO to HOLD_.
  108. //
  109. m = hold_->clone ();
  110. }
  111. }
  112. }
  113. }
  114. else
  115. send_ (m);
  116. // Reliable loop.
  117. //
  118. m->add (Profile_ptr (new From (self_)));
  119. m->add (Profile_ptr (new To (self_)));
  120. in_->recv (m);
  121. }
  122. void Link::
  123. send_ (Message_ptr m)
  124. {
  125. ostream os (m->size (), 1); // Always little-endian.
  126. os << *m;
  127. if (os.length () > size_t (params_.max_packet_size ()))
  128. {
  129. ACE_ERROR ((LM_ERROR,
  130. "packet length (%d) exceeds max_poacket_size (%d)\n",
  131. os.length (), params_.max_packet_size ()));
  132. for (Message::ProfileIterator i (m->begin ()); !i.done (); i.advance ())
  133. {
  134. ACE_ERROR ((LM_ERROR,
  135. "profile id: %d; size: %d\n",
  136. (*i).ext_id_, (*i).int_id_->size ()));
  137. }
  138. ACE_OS::abort ();
  139. }
  140. ssock_.send (os.buffer (), os.length (), addr_);
  141. /*
  142. if (m->find (nrtm::id))
  143. {
  144. ACE_OS::write (1, os.buffer (), os.length ());
  145. ACE_OS::exit (1);
  146. }
  147. */
  148. }
  149. void Link::recv ()
  150. {
  151. size_t max_packet_size (params_.max_packet_size ());
  152. ACE_Auto_Array_Ptr<char> holder (new char[max_packet_size + ACE_CDR::MAX_ALIGNMENT]);
  153. char* data = ACE_ptr_align_binary (holder.get (), ACE_CDR::MAX_ALIGNMENT);
  154. size_t size (0);
  155. while (true)
  156. {
  157. //@@ Should I lock here?
  158. //
  159. Address addr;
  160. // Block for up to one tick waiting for an incomming message.
  161. //
  162. for (;;)
  163. {
  164. ACE_Time_Value t (params_.tick ());
  165. ssize_t r = rsock_.recv (data, 4, addr, MSG_PEEK, &t);
  166. // Check for cancellation request.
  167. //
  168. {
  169. Lock l (mutex_);
  170. if (stop_)
  171. return;
  172. }
  173. if (r == -1)
  174. {
  175. if (errno != ETIME)
  176. ACE_OS::abort ();
  177. }
  178. else
  179. {
  180. size = static_cast<size_t> (r);
  181. break;
  182. }
  183. }
  184. if (size != 4 || addr == self_)
  185. {
  186. // Discard bad messages and ones from ourselvs since
  187. // we are using reliable loopback.
  188. //
  189. rsock_.recv (data, 0, addr);
  190. continue;
  191. }
  192. u32 msg_size;
  193. {
  194. istream is (data, size, 1); // Always little-endian.
  195. is >> msg_size;
  196. }
  197. if (msg_size <= 4 || msg_size > max_packet_size)
  198. {
  199. // Bad message.
  200. //
  201. rsock_.recv (data, 0, addr);
  202. continue;
  203. }
  204. size = rsock_.recv (data, max_packet_size, addr);
  205. if (msg_size != size)
  206. {
  207. // Bad message.
  208. //
  209. continue;
  210. }
  211. //cerr << 6 << "from: " << addr << endl;
  212. Message_ptr m (new Message ());
  213. m->add (Profile_ptr (new From (addr)));
  214. m->add (Profile_ptr (new To (self_)));
  215. istream is (data, size, 1); // Always little-endian.
  216. is >> msg_size;
  217. while (true)
  218. {
  219. u16 id, size;
  220. if (!((is >> id) && (is >> size))) break;
  221. //cerr << 6 << "reading profile with id " << id << " "
  222. // << size << " bytes long" << endl;
  223. Profile::Header hdr (id, size);
  224. if (id == SN::id)
  225. {
  226. m->add (Profile_ptr (new SN (hdr, is)));
  227. }
  228. else if (id == Data::id)
  229. {
  230. m->add (Profile_ptr (new Data (hdr, is)));
  231. }
  232. else if (id == NAK::id)
  233. {
  234. m->add (Profile_ptr (new NAK (hdr, is)));
  235. }
  236. else if (id == NRTM::id)
  237. {
  238. m->add (Profile_ptr (new NRTM (hdr, is)));
  239. }
  240. else if (id == NoData::id)
  241. {
  242. m->add (Profile_ptr (new NoData (hdr, is)));
  243. }
  244. else if (id == Part::id)
  245. {
  246. m->add (Profile_ptr (new Part (hdr, is)));
  247. }
  248. else
  249. {
  250. //cerr << 0 << "unknown profile id " << hdr.id () << endl;
  251. ACE_OS::abort ();
  252. }
  253. }
  254. in_->recv (m);
  255. }
  256. }
  257. ACE_THR_FUNC_RETURN Link::
  258. recv_thunk (void* obj)
  259. {
  260. reinterpret_cast<Link*> (obj)->recv ();
  261. return 0;
  262. }
  263. void Link::recv (Message_ptr)
  264. {
  265. ACE_OS::abort ();
  266. }
  267. }