OpenDDS  Snapshot(2023/04/28-20:55)
EndpointManager.cpp
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Distributed under the OpenDDS License.
5  * See: http://www.opendds.org/license.html
6  */
7 
8 #include "EndpointManager.h"
9 
10 #include "AgentImpl.h"
11 #include "Checklist.h"
12 
16 
17 #include <ace/Reverse_Lock_T.h>
18 
20 
21 namespace OpenDDS {
22 namespace ICE {
23 
24 #ifdef OPENDDS_SECURITY
25 
27 
29  agent_impl(a_agent_impl),
30  endpoint(a_endpoint),
31  requesting_(true),
32  send_count_(0),
33  server_reflexive_task_(DCPS::make_rch<ServerReflexiveTask>(rchandle_from(this))),
34  change_password_task_(DCPS::make_rch<ChangePasswordTask>(rchandle_from(this)))
35 {
36 
38 
39  // Set the type.
41 
42  TheSecurityRegistry->builtin_config()->get_utility()->generate_random_bytes(&ice_tie_breaker_, sizeof(ice_tie_breaker_));
43 
46  if (e) {
47  set_host_addresses(e->host_addresses());
48  }
49 }
50 
51 void EndpointManager::start_ice(const DCPS::GUID_t& a_local_guid,
52  const DCPS::GUID_t& a_remote_guid,
53  const AgentInfo& a_remote_agent_info)
54 {
55  // Check for username collision.
56  if (a_remote_agent_info.username == agent_info_.username) {
58  }
59 
60  GuidPair guidp(a_local_guid, a_remote_guid);
61 
62  // Try to find by guid.
63  ChecklistPtr guid_checklist;
64  {
65  GuidPairToChecklistType::const_iterator pos = guid_pair_to_checklist_.find(guidp);
66 
67  if (pos != guid_pair_to_checklist_.end()) {
68  guid_checklist = pos->second;
69  }
70  }
71 
72  // Try to find by username.
73  ChecklistPtr username_checklist;
74  {
75  UsernameToChecklistType::const_iterator pos = username_to_checklist_.find(a_remote_agent_info.username);
76 
77  if (pos != username_to_checklist_.end()) {
78  username_checklist = pos->second;
79  }
80 
81  else {
82  username_checklist = create_checklist(a_remote_agent_info);
83  }
84  }
85 
86  if (guid_checklist != username_checklist) {
87  if (guid_checklist != 0) {
88  guid_checklist->remove_guid(guidp);
89  }
90 
91  username_checklist->add_guid(guidp);
92  }
93 
94  AgentInfo old_remote_agent_info = username_checklist->original_remote_agent_info();
95 
96  if (old_remote_agent_info == a_remote_agent_info) {
97  // No change.
98  return;
99  }
100 
101  old_remote_agent_info.password = a_remote_agent_info.password;
102 
103  if (old_remote_agent_info == a_remote_agent_info) {
104  // Password change.
105  username_checklist->set_remote_password(a_remote_agent_info.password);
106  return;
107  }
108 
109  // The remote agent changed its info without changing its username.
110  GuidSetType const guids = username_checklist->guids();
111  username_checklist->remove_guids();
112  username_checklist = create_checklist(a_remote_agent_info);
113  username_checklist->add_guids(guids);
114 }
115 
116 void EndpointManager::stop_ice(const DCPS::GUID_t& a_local_guid,
117  const DCPS::GUID_t& a_remote_guid)
118 {
119  GuidPair guidp(a_local_guid, a_remote_guid);
120 
121  GuidPairToChecklistType::const_iterator pos = guid_pair_to_checklist_.find(guidp);
122 
123  if (pos != guid_pair_to_checklist_.end()) {
124  ChecklistPtr guid_checklist = pos->second;
125  guid_checklist->remove_guid(guidp);
126  }
127 }
128 
130  const DCPS::GUID_t& a_remote_guid) const
131 {
132  GuidPair guidp(a_local_guid, a_remote_guid);
133  GuidPairToChecklistType::const_iterator pos = guid_pair_to_checklist_.find(guidp);
134 
135  if (pos != guid_pair_to_checklist_.end()) {
136  return pos->second->selected_address();
137  }
138 
139  return ACE_INET_Addr();
140 }
141 
142 void EndpointManager::receive(const ACE_INET_Addr& a_local_address,
143  const ACE_INET_Addr& a_remote_address,
144  const STUN::Message& a_message)
145 {
146  switch (a_message.class_) {
147  case STUN::REQUEST:
148  request(a_local_address, a_remote_address, a_message);
149  return;
150 
151  case STUN::INDICATION:
152  indication(a_local_address, a_remote_address, a_message);
153  return;
154 
156  success_response(a_local_address, a_remote_address, a_message);
157  return;
158 
160  error_response(a_local_address, a_remote_address, a_message);
161  return;
162  }
163 
164  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::receive: WARNING Unknown STUN message class %d\n"), a_message.class_));
165 }
166 
168 {
169  // Generate the username.
170  unsigned char username[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
171  TheSecurityRegistry->builtin_config()->get_utility()->generate_random_bytes(username, sizeof(username));
173  change_password(false);
174 }
175 
176 void EndpointManager::change_password(bool password_only)
177 {
178  if (password_only && guid_pair_to_checklist_.empty()) {
179  return;
180  }
181 
182  unsigned char password[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
183  TheSecurityRegistry->builtin_config()->get_utility()->generate_random_bytes(password, sizeof(password));
185  regenerate_agent_info(password_only);
186 }
187 
188 void EndpointManager::set_host_addresses(const AddressListType& a_host_addresses)
189 {
190  // Section IETF RFC 8445 5.1.1.1
191  AddressListType host_addresses;
192 
193  for (AddressListType::const_iterator pos = a_host_addresses.begin(), limit = a_host_addresses.end();
194  pos != limit; ++pos) {
195  OPENDDS_ASSERT(!pos->is_any());
196 
197  if (pos->is_loopback()) {
198  continue;
199  }
200 
201 #if ACE_HAS_IPV6
202  if (pos->is_ipv4_compat_ipv6()) {
203  continue;
204  }
205 
206  // TODO(jrw972): Include once supported in ACE.
207  // if (pos->is_sitelocal()) {
208  // continue;
209  // }
210 
211 #if !IPV6_V6ONLY
212  if (pos->is_ipv4_mapped_ipv6()) {
213  continue;
214  }
215 #endif
216 #endif
217 
218  host_addresses.push_back(*pos);
219  }
220 
221  if (host_addresses_ != host_addresses) {
222  host_addresses_ = host_addresses;
223  regenerate_agent_info(false);
224  }
225 }
226 
227 void EndpointManager::set_server_reflexive_address(const ACE_INET_Addr& a_server_reflexive_address,
228  const ACE_INET_Addr& a_stun_server_address)
229 {
230  if (server_reflexive_address_ != a_server_reflexive_address ||
231  stun_server_address_ != a_stun_server_address) {
232  server_reflexive_address_ = a_server_reflexive_address;
233  stun_server_address_ = a_stun_server_address;
234  regenerate_agent_info(false);
235  }
236 }
237 
239 {
240  if (!password_only) {
241  // Populate candidates.
242  agent_info_.candidates.clear();
243 
244  for (AddressListType::const_iterator pos = host_addresses_.begin(), limit = host_addresses_.end(); pos != limit; ++pos) {
245  agent_info_.candidates.push_back(make_host_candidate(*pos));
246 
250  }
251  }
252 
253  // Eliminate duplicates.
255  AgentInfo::CandidatesType::iterator last = std::unique(agent_info_.candidates.begin(), agent_info_.candidates.end(), candidates_equal);
256  agent_info_.candidates.erase(last, agent_info_.candidates.end());
257 
258  foundations_.clear();
259  for (AgentInfo::CandidatesType::const_iterator pos = agent_info_.candidates.begin(), limit = agent_info_.candidates.end(); pos != limit; ++pos) {
260  foundations_.insert(pos->foundation);
261  }
262 
263  // Start over.
265 
266  for (UsernameToChecklistType::const_iterator pos = old_checklists.begin(),
267  limit = old_checklists.end();
268  pos != limit; ++pos) {
269  ChecklistPtr old_checklist = pos->second;
270  AgentInfo const remote_agent_info = old_checklist->original_remote_agent_info();
271  GuidSetType const guids = old_checklist->guids();
272  old_checklist->remove_guids();
273  ChecklistPtr new_checklist = create_checklist(remote_agent_info);
274  new_checklist->add_guids(guids);
275  }
276  }
277 
278  {
279  // Propagate changed agent info.
280 
281  // Make a copy.
282  AgentInfoListenersType agent_info_listeners = agent_info_listeners_;
284 
285  // Release the lock.
288 
289  for (AgentInfoListenersType::const_iterator pos = agent_info_listeners.begin(),
290  limit = agent_info_listeners.end(); pos != limit; ++pos) {
291  DCPS::RcHandle<AgentInfoListener> ail = pos->second.lock();
292  if (ail) {
293  ail->update_agent_info(pos->first, agent_info);
294  }
295  }
296  }
297 }
298 
300 {
301  // Request and maintain a server-reflexive address.
303 
304  if (e) {
305  next_stun_server_address_ = e->stun_server_address();
306  }
307 
314 
316 
317  if (!requesting_ && send_count_ == ICE::Configuration::instance()->server_reflexive_indication_count() - 1) {
318  requesting_ = true;
319  }
320 
322  } else {
323  requesting_ = true;
324  send_count_ = 0;
325  }
326 
327  // Remove expired deferred checks.
328  for (DeferredTriggeredChecksType::iterator pos = deferred_triggered_checks_.begin(),
329  limit = deferred_triggered_checks_.end(); pos != limit;) {
330  DeferredTriggeredCheckListType& list = pos->second;
331 
332  while (!list.empty() && list.front().expiration_date < a_now) {
333  list.pop_front();
334  }
335 
336  if (list.empty()) {
337  deferred_triggered_checks_.erase(pos++);
338  } else {
339  ++pos;
340  }
341  }
342 
343  // Repopulate the host addresses.
344  if (e) {
345  set_host_addresses(e->host_addresses());
346  }
347 }
348 
350 {
352  return false;
353  }
354 
355  std::vector<STUN::AttributeType> unknown_attributes = a_message.unknown_comprehension_required_attributes();
356 
357  if (!unknown_attributes.empty()) {
358  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::success_response: WARNING Unknown comprehension required attributes\n")));
359  return true;
360  }
361 
362  ACE_INET_Addr server_reflexive_address;
363 
364  if (a_message.get_mapped_address(server_reflexive_address)) {
365  set_server_reflexive_address(server_reflexive_address, next_stun_server_address_);
366  requesting_ = false;
367  send_count_ = 0;
368  }
369 
370  else {
371  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::success_response: WARNING No (XOR)_MAPPED_ADDRESS attribute\n")));
373  requesting_ = true;
374  send_count_ = 0;
375  }
376 
377  return true;
378 }
379 
381 {
383  return false;
384  }
385 
386  if (a_message.has_error_code()) {
387  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::error_response: WARNING STUN error response code=%d reason=%s\n"), a_message.get_error_code(), a_message.get_error_reason().c_str()));
388 
389  if (a_message.get_error_code() == STUN::UNKNOWN_ATTRIBUTE && a_message.has_unknown_attributes()) {
390  std::vector<STUN::AttributeType> unknown_attributes = a_message.get_unknown_attributes();
391 
392  for (std::vector<STUN::AttributeType>::const_iterator pos = unknown_attributes.begin(),
393  limit = unknown_attributes.end(); pos != limit; ++pos) {
394  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::error_response: WARNING Unknown STUN attribute %d\n"), *pos));
395  }
396  }
397  }
398 
399  else {
400  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::error_response: WARNING STUN error response (no code)\n")));
401  }
402 
403  return true;
404 }
405 
407 {
408  ChecklistPtr checklist = DCPS::make_rch<Checklist>(this, DCPS::ref(agent_info_), DCPS::ref(remote_agent_info), ice_tie_breaker_);
409  // Add the deferred triggered first in case there was a nominating check.
410  DeferredTriggeredChecksType::iterator pos = deferred_triggered_checks_.find(remote_agent_info.username);
411 
412  if (pos != deferred_triggered_checks_.end()) {
413  const DeferredTriggeredCheckListType& list = pos->second;
414 
415  for (DeferredTriggeredCheckListType::const_iterator pos2 = list.begin(), limit2 = list.end(); pos2 != limit2; ++pos2) {
416  checklist->generate_triggered_check(pos2->local_address, pos2->remote_address, pos2->priority, pos2->use_candidate);
417  }
418 
419  deferred_triggered_checks_.erase(pos);
420  }
421 
422  checklist->unfreeze();
423 
424  return checklist;
425 }
426 
428  const std::vector<STUN::AttributeType>& a_unknown_attributes)
429 {
430  STUN::Message response;
431  response.class_ = STUN::ERROR_RESPONSE;
432  response.method = a_message.method;
433  memcpy(response.transaction_id.data, a_message.transaction_id.data, sizeof(a_message.transaction_id.data));
434  response.append_attribute(STUN::make_error_code(STUN::UNKNOWN_ATTRIBUTE, "Unknown Attributes"));
435  response.append_attribute(STUN::make_unknown_attributes(a_unknown_attributes));
437  response.password = agent_info_.password;
439  return response;
440 }
441 
443  const std::string& a_reason)
444 {
445  STUN::Message response;
446  response.class_ = STUN::ERROR_RESPONSE;
447  response.method = a_message.method;
448  memcpy(response.transaction_id.data, a_message.transaction_id.data, sizeof(a_message.transaction_id.data));
451  response.password = agent_info_.password;
453  return response;
454 }
455 
457 {
458  STUN::Message response;
459  response.class_ = STUN::ERROR_RESPONSE;
460  response.method = a_message.method;
461  memcpy(response.transaction_id.data, a_message.transaction_id.data, sizeof(a_message.transaction_id.data));
462  response.append_attribute(STUN::make_error_code(STUN::UNAUTHORIZED, "Unauthorized"));
464  response.password = agent_info_.password;
466  return response;
467 }
468 
469 // STUN Message processing.
470 void EndpointManager::request(const ACE_INET_Addr& a_local_address,
471  const ACE_INET_Addr& a_remote_address,
472  const STUN::Message& a_message)
473 {
474  std::string username;
475 
476  if (!a_message.get_username(username)) {
477  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING No USERNAME attribute\n")));
478  send(a_remote_address,
479  make_bad_request_error_response(a_message, "Bad Request: USERNAME must be present"));
480  return;
481  }
482 
483  if (!a_message.has_message_integrity()) {
484  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING No MESSAGE_INTEGRITY attribute\n")));
485  send(a_remote_address,
486  make_bad_request_error_response(a_message, "Bad Request: MESSAGE_INTEGRITY must be present"));
487  return;
488  }
489 
490  size_t idx = username.find(':');
491 
492  if (idx == std::string::npos) {
493  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING USERNAME does not contain a colon\n")));
494  send(a_remote_address,
495  make_bad_request_error_response(a_message, "Bad Request: USERNAME must be colon-separated"));
496  return;
497  }
498 
499  if (username.substr(0, idx) != agent_info_.username) {
500  // We expect this to happen.
501  send(a_remote_address,
503  return;
504  }
505 
506  const std::string remote_username = username.substr(++idx);
507 
508  // Check the message_integrity.
510  // We expect this to happen.
511  send(a_remote_address,
513  return;
514  }
515 
516  std::vector<STUN::AttributeType> unknown_attributes = a_message.unknown_comprehension_required_attributes();
517 
518  if (!unknown_attributes.empty()) {
519  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING Unknown comprehension required attributes\n")));
520  send(a_remote_address,
521  make_unknown_attributes_error_response(a_message, unknown_attributes));
522  return;
523  }
524 
525  if (!a_message.has_fingerprint()) {
526  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING No FINGERPRINT attribute\n")));
527  send(a_remote_address,
528  make_bad_request_error_response(a_message, "Bad Request: FINGERPRINT must be present"));
529  return;
530  }
531 
532  if (!a_message.has_ice_controlled() && !a_message.has_ice_controlling()) {
533  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING No ICE_CONTROLLED/ICE_CONTROLLING attribute\n")));
534  send(a_remote_address,
535  make_bad_request_error_response(a_message, "Bad Request: Either ICE_CONTROLLED or ICE_CONTROLLING must be present"));
536  return;
537  }
538 
539  bool use_candidate = a_message.has_use_candidate();
540 
541  if (use_candidate && a_message.has_ice_controlled()) {
542  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING USE_CANDIDATE without ICE_CONTROLLED\n")));
543  send(a_remote_address,
544  make_bad_request_error_response(a_message, "Bad Request: USE_CANDIDATE can only be present when ICE_CONTROLLED is present"));
545  return;
546  }
547 
548  ACE_UINT32 priority;
549 
550  if (!a_message.get_priority(priority)) {
551  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING No PRIORITY attribute\n")));
552  send(a_remote_address,
553  make_bad_request_error_response(a_message, "Bad Request: PRIORITY must be present"));
554  return;
555  }
556 
557  switch (a_message.method) {
558  case STUN::BINDING: {
559  // 7.3
560  STUN::Message response;
561  response.class_ = STUN::SUCCESS_RESPONSE;
562  response.method = STUN::BINDING;
563  memcpy(response.transaction_id.data, a_message.transaction_id.data, sizeof(a_message.transaction_id.data));
564  response.append_attribute(STUN::make_mapped_address(a_remote_address));
565  response.append_attribute(STUN::make_xor_mapped_address(a_remote_address));
567  response.password = agent_info_.password;
569  send(a_remote_address, response);
570 
571  // 7.3.1.3
572  UsernameToChecklistType::const_iterator pos = username_to_checklist_.find(remote_username);
573 
574  if (pos != username_to_checklist_.end()) {
575  // We have a checklist.
576  ChecklistPtr checklist = pos->second;
577  checklist->generate_triggered_check(a_local_address, a_remote_address, priority, use_candidate);
578  }
579 
580  else {
581  std::pair<DeferredTriggeredChecksType::iterator, bool> x =
582  deferred_triggered_checks_.insert(std::make_pair(remote_username, DeferredTriggeredCheckListType()));
583  x.first->second.push_back(DeferredTriggeredCheck(
584  a_local_address, a_remote_address, priority, use_candidate,
585  MonotonicTimePoint::now() + ICE::Configuration::instance()->deferred_triggered_check_ttl()));
586  }
587  }
588  break;
589 
590  default:
591  // Unknown method. Stop processing.
592  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::request: WARNING Unknown STUN method\n")));
593  send(a_remote_address,
594  make_bad_request_error_response(a_message, "Bad Request: Unknown method"));
595  break;
596  }
597 }
598 
599 void EndpointManager::indication(const ACE_INET_Addr& /*a_local_address*/,
600  const ACE_INET_Addr& /*a_remote_address*/,
601  const STUN::Message& a_message)
602 {
603  std::string username;
604 
605  if (!a_message.get_username(username)) {
606  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::indication: WARNING No USERNAME attribute\n")));
607  return;
608  }
609 
610  if (!a_message.has_message_integrity()) {
611  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::indication: WARNING No MESSAGE_INTEGRITY attribute\n")));
612  return;
613  }
614 
615  size_t idx = username.find(':');
616 
617  if (idx == std::string::npos) {
618  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::indication: WARNING USERNAME does not contain a colon\n")));
619  return;
620  }
621 
622  if (username.substr(0, idx) != agent_info_.username) {
623  // We expect this to happen.
624  return;
625  }
626 
627  const std::string remote_username = username.substr(++idx);
628 
629  // Check the message_integrity.
631  // We expect this to happen.
632  return;
633  }
634 
635  std::vector<STUN::AttributeType> unknown_attributes = a_message.unknown_comprehension_required_attributes();
636 
637  if (!unknown_attributes.empty()) {
638  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::indication: WARNING Unknown comprehension required attributes\n")));
639  return;
640  }
641 
642  if (!a_message.has_fingerprint()) {
643  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::indication: WARNING No FINGERPRINT attribute\n")));
644  return;
645  }
646 
647  switch (a_message.method) {
648  case STUN::BINDING: {
649  // Section 11
650  UsernameToChecklistType::const_iterator pos = username_to_checklist_.find(remote_username);
651 
652  if (pos != username_to_checklist_.end()) {
653  // We have a checklist.
654  pos->second->indication();
655  }
656  }
657  break;
658 
659  default:
660  // Unknown method. Stop processing.
661  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::indication: WARNING Unknown STUN method\n")));
662  break;
663  }
664 }
665 
667  const ACE_INET_Addr& a_remote_address,
668  const STUN::Message& a_message)
669 {
670  switch (a_message.method) {
671  case STUN::BINDING: {
672  if (success_response(a_message)) {
673  return;
674  }
675 
676  TransactionIdToChecklistType::const_iterator pos = transaction_id_to_checklist_.find(a_message.transaction_id);
677 
678  if (pos == transaction_id_to_checklist_.end()) {
679  // Probably a check that got cancelled.
680  return;
681  }
682 
683  // Checklist is responsible for updating the map.
684  // Checklist also checks for required parameters.
685  pos->second->success_response(a_local_address, a_remote_address, a_message);
686  }
687  break;
688 
689  default:
690  // Unknown method. Stop processing.
691  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::success_response: WARNING Unknown STUN method\n")));
692  break;
693  }
694 }
695 
696 void EndpointManager::error_response(const ACE_INET_Addr& a_local_address,
697  const ACE_INET_Addr& a_remote_address,
698  const STUN::Message& a_message)
699 {
700  switch (a_message.method) {
701  case STUN::BINDING: {
702  if (error_response(a_message)) {
703  return;
704  }
705 
706  TransactionIdToChecklistType::const_iterator pos = transaction_id_to_checklist_.find(a_message.transaction_id);
707 
708  if (pos == transaction_id_to_checklist_.end()) {
709  // Probably a check that got cancelled.
710  return;
711  }
712 
713  // Checklist is responsible for updating the map.
714  // Checklist also checks for required parameters.
715  pos->second->error_response(a_local_address, a_remote_address, a_message);
716  }
717  break;
718 
719  default:
720  // Unknown method. Stop processing.
721  ACE_ERROR((LM_WARNING, ACE_TEXT("(%P|%t) EndpointManager::error_response: WARNING Unknown STUN method\n")));
722  break;
723  }
724 }
725 
727 {
728  for (UsernameToChecklistType::const_iterator pos = username_to_checklist_.begin(),
729  limit = username_to_checklist_.end(); pos != limit; ++pos) {
730  ChecklistPtr checklist = pos->second;
731  checklist->compute_active_foundations(a_active_foundations);
732  }
733 }
734 
736 {
737  // Check for expired deferred checks.
738  for (DeferredTriggeredChecksType::const_iterator pos = deferred_triggered_checks_.begin(),
739  limit = deferred_triggered_checks_.end(); pos != limit; ++pos) {
740  const DeferredTriggeredCheckListType& list = pos->second;
741  ACE_UNUSED_ARG(list);
742  OPENDDS_ASSERT(!list.empty());
744  }
745 
746  for (UsernameToChecklistType::const_iterator pos = username_to_checklist_.begin(),
747  limit = username_to_checklist_.end(); pos != limit; ++pos) {
748  ChecklistPtr checklist = pos->second;
749  OPENDDS_ASSERT(checklist->original_remote_agent_info().username == pos->first);
750  checklist->check_invariants();
751  }
752 
753  for (TransactionIdToChecklistType::const_iterator pos = transaction_id_to_checklist_.begin(),
754  limit = transaction_id_to_checklist_.end(); pos != limit; ++pos) {
755  ChecklistPtr checklist = pos->second;
756  ACE_UNUSED_ARG(checklist);
757  OPENDDS_ASSERT(checklist->has_transaction_id(pos->first));
758  }
759 
760  for (GuidPairToChecklistType::const_iterator pos = guid_pair_to_checklist_.begin(),
761  limit = guid_pair_to_checklist_.end(); pos != limit; ++pos) {
762  ChecklistPtr checklist = pos->second;
763  ACE_UNUSED_ARG(checklist);
764  OPENDDS_ASSERT(checklist->has_guid_pair(pos->first));
765  }
766 }
767 
769 {
770  for (UsernameToChecklistType::const_iterator pos = username_to_checklist_.begin(),
771  limit = username_to_checklist_.end(); pos != limit; ++pos) {
772  pos->second->unfreeze();
773  }
774 }
775 
776 void EndpointManager::unfreeze(const FoundationType& a_foundation)
777 {
778  for (UsernameToChecklistType::const_iterator pos = username_to_checklist_.begin(),
779  limit = username_to_checklist_.end(); pos != limit; ++pos) {
780  pos->second->unfreeze(a_foundation);
781  }
782 }
783 
785  : Task(a_endpoint_manager->agent_impl),
786  endpoint_manager(a_endpoint_manager)
787 {
788  enqueue(MonotonicTimePoint::now());
789 }
790 
792 {
794  if (em) {
795  em->server_reflexive_task(a_now);
796  enqueue(a_now + ICE::Configuration::instance()->server_reflexive_address_period());
797  }
798 }
799 
801  : Task(a_endpoint_manager->agent_impl),
802  endpoint_manager(a_endpoint_manager)
803 {
804  enqueue(MonotonicTimePoint::now() + ICE::Configuration::instance()->change_password_period());
805 }
806 
808 {
810  if (em) {
811  em->change_password(true);
812  enqueue(a_now + ICE::Configuration::instance()->change_password_period());
813  }
814 }
815 
817 {
819  if (e) {
820  set_host_addresses(e->host_addresses());
821  }
822 }
823 
824 void EndpointManager::send(const ACE_INET_Addr& address, const STUN::Message& message)
825 {
827  if (e) {
828  e->send(address, message);
829  }
830 }
831 
833 {
835  for (UsernameToChecklistType::const_iterator pos = checklists.begin(), limit = checklists.end(); pos != limit; ++pos) {
836  pos->second->remove_guids();
837  }
838 
839  for (AgentInfoListenersType::const_iterator pos = agent_info_listeners_.begin(), limit = agent_info_listeners_.end(); pos != limit; ++pos) {
840  DCPS::RcHandle<AgentInfoListener> ail = pos->second.lock();
841  if (ail) {
842  ail->remove_agent_info(pos->first);
843  }
844  }
845 }
846 
847 #endif /* OPENDDS_SECURITY */
848 
849 } // namespace ICE
850 } // namespace OpenDDS
851 
AgentType type
Definition: Ice.h:75
RcHandle< T > rchandle_from(T *pointer)
Definition: RcHandle_T.h:310
#define ACE_ERROR(X)
#define ACE_GUARD(MUTEX, OBJ, LOCK)
bool has_ice_controlled() const
Definition: Stun.cpp:825
GuidPairToChecklistType guid_pair_to_checklist_
void server_reflexive_address_period(const DCPS::TimeDuration &x)
Definition: RTPS/ICE/Ice.h:118
bool get_mapped_address(ACE_INET_Addr &address) const
Definition: Stun.cpp:643
ChangePasswordTask(DCPS::RcHandle< EndpointManager > a_endpoint_manager)
void stop_ice(const DCPS::GUID_t &local_guid, const DCPS::GUID_t &remote_guid)
void start_ice(const DCPS::GUID_t &a_local_guid, const DCPS::GUID_t &a_remote_guid, const AgentInfo &a_remote_agent_info)
void server_reflexive_indication_count(size_t x)
Definition: RTPS/ICE/Ice.h:127
void * memcpy(void *t, const void *s, size_t len)
bool has_message_integrity() const
Definition: Stun.cpp:692
std::pair< std::string, std::string > FoundationType
Definition: Checklist.h:34
RcHandle< T > make_rch()
Definition: RcHandle_T.h:256
bool get_priority(ACE_UINT32 &priority) const
Definition: Stun.cpp:662
#define OPENDDS_ASSERT(C)
Definition: Definitions.h:72
DCPS::WeakRcHandle< Endpoint > const endpoint
const ACE_UINT16 UNAUTHORIZED
Definition: Stun.h:52
TransactionIdToChecklistType transaction_id_to_checklist_
void enqueue(const DCPS::MonotonicTimePoint &release_time)
Definition: Task.cpp:19
reference_wrapper< T > ref(T &r)
Definition: RcHandle_T.h:237
Attribute make_xor_mapped_address(const ACE_INET_Addr &addr)
Definition: Stun.cpp:116
ChecklistPtr create_checklist(const AgentInfo &a_remote_agent_info)
void generate_transaction_id()
Definition: Stun.cpp:606
std::vector< AttributeType > get_unknown_attributes() const
Definition: Stun.cpp:786
const ACE_UINT16 UNKNOWN_ATTRIBUTE
Definition: Stun.h:53
void receive(const ACE_INET_Addr &a_local_address, const ACE_INET_Addr &a_remote_address, const STUN::Message &a_message)
Candidate make_host_candidate(const ACE_INET_Addr &address)
Definition: Ice.cpp:64
std::map< std::string, ChecklistPtr > UsernameToChecklistType
ACE_INET_Addr get_address(const DCPS::GUID_t &a_local_guid, const DCPS::GUID_t &a_remote_guid) const
void compute_active_foundations(ActiveFoundationSet &a_active_foundations) const
STUN::Message make_bad_request_error_response(const STUN::Message &a_message, const std::string &a_reason)
bool has_unknown_attributes() const
Definition: Stun.cpp:775
void execute(const DCPS::MonotonicTimePoint &a_now)
void send(const ACE_INET_Addr &address, const STUN::Message &message)
ACE_UINT8 data[12]
Definition: Stun.h:144
String to_hex_dds_string(const unsigned char *data, const size_t size, const char delim, const size_t delim_every)
const AgentInfo & agent_info() const
DCPS::WeakRcHandle< EndpointManager > endpoint_manager
const ACE_UINT16 BAD_REQUEST
Definition: Stun.h:51
bool candidates_equal(const Candidate &x, const Candidate &y)
Definition: Ice.cpp:34
EndpointManager(AgentImpl *a_agent_impl, DCPS::WeakRcHandle< Endpoint > a_endpoint)
ACE_UINT16 get_error_code() const
Definition: Stun.cpp:753
AgentInfoListenersType agent_info_listeners_
std::string username
Definition: Ice.h:77
CandidatesType candidates
Definition: Ice.h:74
#define TheSecurityRegistry
TimePoint_T< MonotonicClock > MonotonicTimePoint
Definition: TimeTypes.h:51
bool get_username(std::string &username) const
Definition: Stun.cpp:677
void request(const ACE_INET_Addr &a_local_address, const ACE_INET_Addr &a_remote_address, const STUN::Message &a_message)
Attribute make_error_code(ACE_UINT16 code, const std::string &reason)
Definition: Stun.cpp:99
LM_WARNING
Attribute make_message_integrity()
Definition: Stun.cpp:92
void indication(const ACE_INET_Addr &a_local_address, const ACE_INET_Addr &a_remote_address, const STUN::Message &a_message)
bool has_error_code() const
Definition: Stun.cpp:742
bool error_response(const STUN::Message &a_message)
ACE_TEXT("TCP_Factory")
Attribute make_fingerprint()
Definition: Stun.cpp:139
void server_reflexive_task(const DCPS::MonotonicTimePoint &a_now)
DeferredTriggeredChecksType deferred_triggered_checks_
void append_attribute(const Attribute &attribute)
Definition: Stun.h:195
void regenerate_agent_info(bool password_only)
void execute(const DCPS::MonotonicTimePoint &a_now)
std::string get_error_reason() const
Definition: Stun.cpp:764
UsernameToChecklistType username_to_checklist_
DCPS::WeakRcHandle< EndpointManager > endpoint_manager
ServerReflexiveTask(DCPS::RcHandle< EndpointManager > a_endpoint_manager)
Attribute make_unknown_attributes(const std::vector< AttributeType > &unknown_attributes)
Definition: Stun.cpp:108
static Configuration * instance()
Definition: Ice.cpp:109
bool success_response(const STUN::Message &a_message)
STUN::Message make_unauthorized_error_response(const STUN::Message &a_message)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
std::string password
Definition: Stun.h:242
ACE_Recursive_Thread_Mutex mutex
Definition: AgentImpl.h:100
bool verify_message_integrity(const std::string &password) const
Definition: Stun.cpp:703
std::string password
Definition: Ice.h:78
void set_server_reflexive_address(const ACE_INET_Addr &a_server_reflexive_address, const ACE_INET_Addr &a_stun_server_address)
RcHandle< T > lock() const
Definition: RcObject.h:188
Attribute make_mapped_address(const ACE_INET_Addr &addr)
Definition: Stun.cpp:76
Candidate make_server_reflexive_candidate(const ACE_INET_Addr &address, const ACE_INET_Addr &base, const ACE_INET_Addr &server_address)
Definition: Ice.cpp:76
bool has_use_candidate() const
Definition: Stun.cpp:847
void change_password(bool password_only)
bool has_ice_controlling() const
Definition: Stun.cpp:836
std::vector< AttributeType > unknown_comprehension_required_attributes() const
Definition: Stun.cpp:616
TransactionId transaction_id
Definition: Stun.h:186
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
void set_host_addresses(const AddressListType &a_host_addresses)
std::deque< DeferredTriggeredCheck > DeferredTriggeredCheckListType
std::map< DCPS::GUID_t, DCPS::WeakRcHandle< AgentInfoListener >, DCPS::GUID_tKeyLessThan > AgentInfoListenersType
std::set< GuidPair > GuidSetType
Definition: RTPS/ICE/Ice.h:39
bool candidates_sorted(const Candidate &x, const Candidate &y)
Definition: Ice.cpp:21
STUN::Message make_unknown_attributes_error_response(const STUN::Message &a_message, const std::vector< STUN::AttributeType > &a_unknown_attributes)
void clear_transaction_id()
Definition: Stun.cpp:611
bool has_fingerprint() const
Definition: Stun.cpp:797