From e67af10528ec50214bb3bf6a52293ab0d09c6210 Mon Sep 17 00:00:00 2001 From: crodrigu Date: Tue, 13 Nov 2001 19:22:54 +0000 Subject: ChangeLogTag: Wed Nov 13 14:14:24 2001 Craig Rodrigues --- TAO/ChangeLogs/ChangeLog-02a | 85 ++ TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp | 259 ++++- TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h | 6 +- TAO/orbsvcs/orbsvcs/AV/AV_Core.cpp | 100 +- TAO/orbsvcs/orbsvcs/AV/AV_Core.h | 13 +- TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp | 17 +- TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp | 401 ++++++-- TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h | 43 +- TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i | 86 ++ TAO/orbsvcs/orbsvcs/AV/MCast.cpp | 12 +- TAO/orbsvcs/orbsvcs/AV/MCast.h | 5 +- TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp | 3 +- TAO/orbsvcs/orbsvcs/AV/QoS_UDP.cpp | 61 +- TAO/orbsvcs/orbsvcs/AV/QoS_UDP.h | 12 +- TAO/orbsvcs/orbsvcs/AV/RTCP.cpp | 1258 +++++++++++------------- TAO/orbsvcs/orbsvcs/AV/RTCP.h | 250 ++--- TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp | 361 +++++++ TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.h | 217 ++++ TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.cpp | 1194 ++++++++++++++++++++++ TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.h | 393 ++++++++ TAO/orbsvcs/orbsvcs/AV/RTP.cpp | 589 +++++++++-- TAO/orbsvcs/orbsvcs/AV/RTP.h | 151 ++- TAO/orbsvcs/orbsvcs/AV/TCP.cpp | 18 +- TAO/orbsvcs/orbsvcs/AV/TCP.h | 12 +- TAO/orbsvcs/orbsvcs/AV/Transport.cpp | 546 ++++------ TAO/orbsvcs/orbsvcs/AV/Transport.h | 14 +- TAO/orbsvcs/orbsvcs/AV/UDP.cpp | 446 ++++++--- TAO/orbsvcs/orbsvcs/AV/UDP.h | 50 +- TAO/orbsvcs/orbsvcs/AV/global.h | 31 + TAO/orbsvcs/orbsvcs/AV/md5.h | 49 + TAO/orbsvcs/orbsvcs/AV/md5c.c | 345 +++++++ TAO/orbsvcs/orbsvcs/AV/source.cpp | 541 ---------- TAO/orbsvcs/orbsvcs/AV/source.h | 234 ----- TAO/orbsvcs/orbsvcs/AV/source.i | 491 --------- 34 files changed, 5359 insertions(+), 2934 deletions(-) create mode 100644 TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp create mode 100644 TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.h create mode 100644 TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.cpp create mode 100644 TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.h create mode 100644 TAO/orbsvcs/orbsvcs/AV/global.h create mode 100644 TAO/orbsvcs/orbsvcs/AV/md5.h create mode 100644 TAO/orbsvcs/orbsvcs/AV/md5c.c delete mode 100644 TAO/orbsvcs/orbsvcs/AV/source.cpp delete mode 100644 TAO/orbsvcs/orbsvcs/AV/source.h delete mode 100644 TAO/orbsvcs/orbsvcs/AV/source.i diff --git a/TAO/ChangeLogs/ChangeLog-02a b/TAO/ChangeLogs/ChangeLog-02a index 380e25f8a73..4ebcc637215 100644 --- a/TAO/ChangeLogs/ChangeLog-02a +++ b/TAO/ChangeLogs/ChangeLog-02a @@ -1,3 +1,88 @@ +Wed Nov 13 14:14:24 2001 Craig Rodrigues + + Fixes provided by Rob Ruff : + + * orbsvcs/orbsvcs/AV/AVStreams_i.cpp: + * orbsvcs/orbsvcs/AV/AVStreams_i.i: + * orbsvcs/orbsvcs/AV/AV_Core.cpp: + * orbsvcs/orbsvcs/AV/AV_Core.h: + * orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp: + * orbsvcs/orbsvcs/AV/FlowSpec_Entry.h: + * orbsvcs/orbsvcs/AV/FlowSpec_Entry.i: + * orbsvcs/orbsvcs/AV/QoS_UDP.cpp: + * orbsvcs/orbsvcs/AV/QoS_UDP.h: + * orbsvcs/orbsvcs/AV/TCP.cpp: + * orbsvcs/orbsvcs/AV/TCP.h: + * orbsvcs/orbsvcs/AV/Transport.cpp: + * orbsvcs/orbsvcs/AV/Transport.h: + * orbsvcs/orbsvcs/AV/UDP.cpp: + * orbsvcs/orbsvcs/AV/UDP.h: + The previous implementation used separate flow specifications for the + data and control portions of the same stream. This meant that RTP + could not be used with the light profile of the AV service (since it + only allows one flow between stream endpoints). The code was modified + to allow data and control information to be passed as part of the + same flow. + * orbsvcs/orbsvcs/AV/AVStreams_i.cpp: + Added/renamed several properties defined in the CORBA AV spec. + Implemented the TAO_StreamCtrl::unbind operation. + Fixed several memory leaks. + * orbsvcs/orbsvcs/AV/AV_Core.cpp: + Added code to clean up transport/flow factories (fix memory leak). + Added get_transport_factory(const char *transport_protocol). + Added get_flow_protocol_factory(const char *flow_protocol). + * orbsvcs/orbsvcs/AV/AV_Core.h: + Added get_transport_factory(const char *transport_protocol). + Added get_flow_protocol_factory(const char *flow_protocol). + * orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp: + Added a remove_ref call to activate_mediactrl. + * orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp: + Changed the flow specification to better conform to the AV Service + spec. + * orbsvcs/orbsvcs/AV/MCast.cpp: + TAO_AV_UDP_MCast_Flow_Handler::handle_input now returns the value + returned by protocol_object->handle_input rather than 0. + * orbsvcs/orbsvcs/AV/MCast.h: + Made the TAO_AV_UDP_MCast_Flow_Handler destructor virtual. + * orbsvcs/orbsvcs/AV/RTCP.cpp: + * orbsvcs/orbsvcs/AV/RTCP.h: + Added full RFC compliant RTCP control protocol implementation. + Modified the ssrc allocation operation to use the MD5 algorithm to + more reliably choose a unique id. + * orbsvcs/orbsvcs/AV/RTCP_Channel.h: (added) + * orbsvcs/orbsvcs/AV/RTCP_Channel.cpp: (added) + These files contain two classes, one used to represent incoming RTP + streams and one to represent outgoing streams. They keep track of + transmission/reception statistics. + * orbsvcs/orbsvcs/AV/RTCP_Packet.h: (added) + * orbsvcs/orbsvcs/AV/RTCP_Packet.cpp: (added) + These files contain classes to represent each of the control packet + message types. + * orbsvcs/orbsvcs/AV/RTP.cpp: + * orbsvcs/orbsvcs/AV/RTP.h: + Made several changes to support the RTCP implementation. + Added a class to represent an RTP packet. + * orbsvcs/orbsvcs/AV/Transport.cpp: + Modified code to use the get_xxx_factory routines added to AV_Core + rather than doing the search in this file. + * orbsvcs/orbsvcs/AV/UDP.cpp: + When the protocol is RTP/UDP, an even/odd port pair will be reserved + as is called out in the RTP RFC. + The class TAO_AV_UDP_Connection_Setup was added to replace duplicated + code used for both the TAO_AV_UDP_Acceptor and TAO_AV_UDP_Connector. + * orbsvcs/orbsvcs/AV/global.h: (added) + * orbsvcs/orbsvcs/AV/md5.h: (added) + * orbsvcs/orbsvcs/AV/md5c.c: (added) + Used by the operation to allocate ssrc's in RTCP.cpp to help guarantee + a unique id. + * orbsvcs/orbsvcs/AV/source.cpp: (removed) + * orbsvcs/orbsvcs/AV/source.h: (removed) + * orbsvcs/orbsvcs/AV/source.i: (removed) + The functionality contained in these files is now implemented in the + RTCP*.* files. + * orbsvcs/orbsvcs/Makefile.av: (updated) + * orbsvcs/orbsvcs/AV.bor: (updated) + Tue Nov 13 08:58:13 2001 Ossama Othman * orbsvcs/orbsvcs/Notify/Notify_ProxyPushSupplier_i.cpp diff --git a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp index cebba6f5191..5c289498b2d 100644 --- a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp @@ -96,7 +96,7 @@ TAO_Basic_StreamCtrl::stop (const AVStreams::flowSpec &flow_spec, } else { - // call start on all the flows. + // call stop on all the flows. FlowConnection_Map_Iterator iterator (this->flow_connection_map_); FlowConnection_Map_Entry *entry = 0; for (;iterator.next (entry) != 0;iterator.advance ()) @@ -182,6 +182,7 @@ TAO_Basic_StreamCtrl::destroy (const AVStreams::flowSpec &flow_spec, if (this->flow_connection_map_.current_size () > 0) { if (flow_spec.length () > 0) + { for (u_int i=0;iflow_connection_map_); FlowConnection_Map_Entry *entry = 0; for (;iterator.next (entry) != 0;iterator.advance ()) @@ -236,10 +238,10 @@ TAO_Basic_StreamCtrl::modify_QoS (AVStreams::streamQoS & new_qos, in_flowspec.length (0); out_flowspec.length (0); - + int in_index = 0; int out_index = 0; - + for (u_int i=0;i < flowspec.length ();i++) { TAO_Forward_FlowSpec_Entry entry; @@ -609,6 +611,7 @@ TAO_StreamCtrl::destroy (const AVStreams::flowSpec &flow_spec, ACE_TRY_CHECK; if (this->flow_connection_map_.current_size () > 0) return; + MMDevice_Map_Iterator a_iterator (this->mmdevice_a_map_); MMDevice_Map::ENTRY *entry = 0; for (;a_iterator.next (entry)!= 0;a_iterator.advance ()) @@ -625,7 +628,7 @@ TAO_StreamCtrl::destroy (const AVStreams::flowSpec &flow_spec, } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "TAO_Basic_StreamCtrl::destroy"); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "TAO_StreamCtrl::destroy"); return; } ACE_ENDTRY; @@ -703,13 +706,29 @@ TAO_StreamCtrl::bind_devs (AVStreams::MMDevice_ptr a_party, ACE_TRY_ENV); ACE_TRY_CHECK; + CORBA::Any vdev_a_any; + vdev_a_any <<= this->vdev_a_.in (); + this->sep_a_->define_property ("Related_VDev", + vdev_a_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + CORBA::Any streamendpoint_a_any; streamendpoint_a_any <<= this->sep_a_.in (); - this->vdev_a_->define_property ("Related_StreamEndpoint_A", + this->vdev_a_->define_property ("Related_StreamEndpoint", streamendpoint_a_any, ACE_TRY_ENV); - - ACE_TRY_CHECK; + + ACE_TRY_CHECK; + + AVStreams::MMDevice_ptr a_party_copy = AVStreams::MMDevice::_duplicate(a_party); + + CORBA::Any mmdevice_a_any; + mmdevice_a_any <<= a_party_copy; + this->vdev_a_->define_property ("Related_MMDevice", + mmdevice_a_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; // add the mmdevice, sep and vdev to the map. MMDevice_Map_Entry map_entry; @@ -765,14 +784,29 @@ TAO_StreamCtrl::bind_devs (AVStreams::MMDevice_ptr a_party, ACE_TRY_ENV); ACE_TRY_CHECK; - CORBA::Any streamendpoint_b_any; + CORBA::Any vdev_b_any; + vdev_b_any <<= this->vdev_b_.in (); + this->sep_b_->define_property ("Related_VDev", + vdev_b_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::Any streamendpoint_b_any; streamendpoint_b_any <<= this->sep_b_.in (); - this->vdev_b_->define_property ("Related_StreamEndpoint_B", + this->vdev_b_->define_property ("Related_StreamEndpoint", streamendpoint_b_any, ACE_TRY_ENV); - + ACE_TRY_CHECK; + AVStreams::MMDevice_ptr b_party_copy = AVStreams::MMDevice::_duplicate(b_party); + + CORBA::Any mmdevice_b_any; + mmdevice_b_any <<= b_party_copy; + this->vdev_b_->define_property ("Related_MMDevice", + mmdevice_b_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; // add the mmdevice, sep and vdev to the map. MMDevice_Map_Entry map_entry; MMDevice_Map_Hash_Key key (b_party); @@ -787,6 +821,30 @@ TAO_StreamCtrl::bind_devs (AVStreams::MMDevice_ptr a_party, } } + // Tell the endpoints about each other. + if ((!CORBA::is_nil (a_party)) && (!CORBA::is_nil (b_party))) + { + AVStreams::StreamEndPoint_A_var sep_b_peer; + AVStreams::StreamEndPoint_B_var sep_a_peer; + CORBA::Any sep_a_peer_any; + CORBA::Any sep_b_peer_any; + + sep_a_peer = AVStreams::StreamEndPoint_B::_duplicate(this->sep_b_.in()); + sep_b_peer = AVStreams::StreamEndPoint_A::_duplicate(this->sep_a_.in()); + + sep_a_peer_any <<= sep_a_peer.in(); + sep_b_peer_any <<= sep_b_peer.in(); + this->sep_a_->define_property ("PeerAdapter", + sep_a_peer_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + this->sep_b_->define_property ("PeerAdapter", + sep_b_peer_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + // In the full profile case there's no VDev. if (CORBA::is_nil (b_party) && (!CORBA::is_nil (this->vdev_a_.in ()))) { @@ -1267,7 +1325,7 @@ TAO_StreamCtrl::bind (AVStreams::StreamEndPoint_A_ptr sep_a, } ACE_ENDTRY; ACE_CHECK_RETURN (0); - } + } ACE_CATCHANY { // error was thrown because one of the streamendpoints is light profile. @@ -1284,10 +1342,39 @@ TAO_StreamCtrl::bind (AVStreams::StreamEndPoint_A_ptr sep_a, } void -TAO_StreamCtrl::unbind (CORBA::Environment &/* ACE_TRY_ENV */) +TAO_StreamCtrl::unbind (CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpFailed)) { + ACE_TRY + { + if (this->flow_connection_map_.current_size () > 0) + return; + + AVStreams::flowSpec flow_spec; + flow_spec.length(0); + + MMDevice_Map_Iterator a_iterator (this->mmdevice_a_map_); + MMDevice_Map::ENTRY *entry = 0; + for (;a_iterator.next (entry)!= 0;a_iterator.advance ()) + { + entry->int_id_.sep_->destroy (flow_spec, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + MMDevice_Map_Iterator b_iterator (this->mmdevice_b_map_); + for (;b_iterator.next (entry)!= 0;b_iterator.advance ()) + { + entry->int_id_.sep_->destroy (flow_spec, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "TAO_StreamCtrl::unbind"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } void @@ -1615,7 +1702,17 @@ TAO_Base_StreamEndPoint::set_flow_handler (const char *flowname, ACE_CString flow_name_key (flowname); if (this->flow_handler_map_.bind (flow_name_key, handler) != 0) ACE_ERROR ((LM_ERROR, - "Error in storing flow handler\n")); + "Error in storing flow handler\n")); +} + +void +TAO_Base_StreamEndPoint::set_control_flow_handler (const char *flowname, + TAO_AV_Flow_Handler *handler) +{ + ACE_CString flow_name_key (flowname); + if (this->control_flow_handler_map_.bind (flow_name_key, handler) != 0) + ACE_ERROR ((LM_ERROR, + "Error in storing control flow handler\n")); } // ---------------------------------------------------------------------- @@ -1721,11 +1818,11 @@ TAO_StreamEndPoint::connect (AVStreams::StreamEndPoint_ptr responder, ACE_DEBUG ((LM_DEBUG, "QoS is Specified\n")); - int result = this->translate_qos (qos, + int result = this->translate_qos (qos, network_qos); if (result != 0) if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, + ACE_DEBUG ((LM_DEBUG, "QoS translation failed\n")); this->qos ().set (network_qos); @@ -1746,14 +1843,16 @@ TAO_StreamEndPoint::connect (AVStreams::StreamEndPoint_ptr responder, ACE_NEW_RETURN (entry, TAO_Forward_FlowSpec_Entry, 0); + if (entry->parse (flow_spec[i]) == -1) return 0; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "TAO_StreamEndPoint::Connect: %s\n", entry->entry_to_string ())); + this->forward_flow_spec_set.insert (entry); } - int result =TAO_AV_CORE::instance ()->init_forward_flows (this, this->forward_flow_spec_set, TAO_AV_Core::TAO_AV_ENDPOINT_A, @@ -1786,13 +1885,13 @@ TAO_StreamEndPoint::connect (AVStreams::StreamEndPoint_ptr responder, TAO_Reverse_FlowSpec_Entry, 0); if (entry->parse (flow_spec[i].in ()) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "Reverse_Flow_Spec_Set::parse failed\n"), + ACE_ERROR_RETURN ((LM_ERROR, + "Reverse_Flow_Spec_Set::parse failed\n"), 0); if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, - "TAO_StreamEndPoint::Connect: Reverse Flow Spec %s\n", + ACE_DEBUG ((LM_DEBUG, + "TAO_StreamEndPoint::Connect: Reverse Flow Spec %s\n", entry->entry_to_string ())); this->reverse_flow_spec_set.insert (entry); @@ -1803,8 +1902,8 @@ TAO_StreamEndPoint::connect (AVStreams::StreamEndPoint_ptr responder, this->reverse_flow_spec_set, TAO_AV_Core::TAO_AV_ENDPOINT_A); if (result < 0) - ACE_ERROR_RETURN ((LM_ERROR, - "TAO_AV_Core::init_reverse_flows failed\n"), + ACE_ERROR_RETURN ((LM_ERROR, + "TAO_AV_Core::init_reverse_flows failed\n"), 0); // Make the upcall to the app @@ -1861,6 +1960,8 @@ TAO_StreamEndPoint::stop (const AVStreams::flowSpec &flow_spec, TAO_FlowSpec_Entry *entry = *begin; // (*begin)->protocol_object ()->stop (); entry->handler ()->stop (entry->role ()); + if (entry->control_handler () != 0) + entry->control_handler ()->stop (entry->role ()); break; } } @@ -1875,6 +1976,8 @@ TAO_StreamEndPoint::stop (const AVStreams::flowSpec &flow_spec, TAO_FlowSpec_Entry *entry = *begin; // entry->protocol_object ()->stop (); entry->handler ()->stop (entry->role ()); + if (entry->control_handler () != 0) + entry->control_handler ()->stop (entry->role ()); } } } @@ -1906,7 +2009,13 @@ TAO_StreamEndPoint::start (const AVStreams::flowSpec &flow_spec, { // entry->protocol_object ()->start (); if (entry->handler () != 0) + { entry->handler ()->start (entry->role ()); + } + if (entry->control_handler () != 0) + { + entry->control_handler ()->start (entry->role ()); + } } } @@ -1919,7 +2028,13 @@ TAO_StreamEndPoint::start (const AVStreams::flowSpec &flow_spec, { // entry->protocol_object ()->start (); if (entry->handler () != 0) + { entry->handler ()->start (entry->role ()); + } + if (entry->control_handler () != 0) + { + entry->control_handler ()->start (entry->role ()); + } } } } @@ -1935,6 +2050,10 @@ TAO_StreamEndPoint::start (const AVStreams::flowSpec &flow_spec, { entry->handler ()->start (entry->role ()); } + if (entry->control_handler () != 0) + { + entry->control_handler ()->start (entry->role ()); + } } end = this->reverse_flow_spec_set.end (); @@ -1947,9 +2066,11 @@ TAO_StreamEndPoint::start (const AVStreams::flowSpec &flow_spec, { entry->handler ()->start (entry->role ()); } - + if (entry->control_handler () != 0) + { + entry->control_handler ()->start (entry->role ()); + } } - } } @@ -1974,10 +2095,13 @@ TAO_StreamEndPoint::destroy (const AVStreams::flowSpec &flow_spec, begin != end; ++begin) { TAO_FlowSpec_Entry *entry = *begin; - if (ACE_OS::strcmp (entry->flowname (), flow_spec [i]) == 0) + TAO_Tokenizer flow_name (flow_spec [i], '\\'); + if (ACE_OS::strcmp (entry->flowname (), flow_name[0]) == 0) { if (entry->protocol_object ()) - entry->protocol_object ()->destroy (); + { + entry->protocol_object ()->destroy (); + } break; } } @@ -1988,10 +2112,13 @@ TAO_StreamEndPoint::destroy (const AVStreams::flowSpec &flow_spec, begin != end; ++begin) { TAO_FlowSpec_Entry *entry = *begin; - if (ACE_OS::strcmp (entry->flowname (), flow_spec [i]) == 0) + TAO_Tokenizer flow_name (flow_spec [i], '\\'); + if (ACE_OS::strcmp (entry->flowname (), flow_name[0]) == 0) { if (entry->protocol_object ()) - entry->protocol_object ()->destroy (); + { + entry->protocol_object ()->destroy (); + } break; } } @@ -2007,7 +2134,9 @@ TAO_StreamEndPoint::destroy (const AVStreams::flowSpec &flow_spec, { TAO_FlowSpec_Entry *entry = *begin; if (entry->protocol_object ()) - entry->protocol_object ()->destroy (); + { + entry->protocol_object ()->destroy (); + } } } { @@ -2017,7 +2146,9 @@ TAO_StreamEndPoint::destroy (const AVStreams::flowSpec &flow_spec, { TAO_FlowSpec_Entry *entry = *begin; if (entry->protocol_object ()) - entry->protocol_object ()->destroy (); + { + entry->protocol_object ()->destroy (); + } } } } @@ -2043,7 +2174,7 @@ TAO_StreamEndPoint::request_connection (AVStreams::StreamEndPoint_ptr /*initiato { if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, + ACE_DEBUG ((LM_DEBUG, "\n(%P|%t) TAO_StreamEndPoint::request_connection called")); @@ -2090,14 +2221,13 @@ TAO_StreamEndPoint::request_connection (AVStreams::StreamEndPoint_ptr /*initiato return 0; } if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, - "TAO_StreamEndPoint::request_connection Flow Spec %s", + ACE_DEBUG ((LM_DEBUG, + "TAO_StreamEndPoint::request_connection Flow Spec %s", entry->entry_to_string ())); this->forward_flow_spec_set.insert (entry); } - result = TAO_AV_CORE::instance ()->init_forward_flows (this, this->forward_flow_spec_set, TAO_AV_Core::TAO_AV_ENDPOINT_B, @@ -2129,7 +2259,7 @@ TAO_StreamEndPoint::change_qos (AVStreams::streamQoS &new_qos, if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "TAO_StreamEndPoint::change_qos\n")); - + TAO_AV_QoS qos (new_qos); for (int i = 0; (unsigned) i < the_flows.length (); i++) { @@ -2470,6 +2600,7 @@ TAO_StreamEndPoint::~TAO_StreamEndPoint (void) //this->handle_close (); TAO_AV_FlowSpecSetItor begin = this->forward_flow_spec_set.begin (); TAO_AV_FlowSpecSetItor end = this->forward_flow_spec_set.end (); + int i=0; // @@ Naga: Will the iterator always give the entries in the order of insertion. // or is it an implementation fact of ACE containers. @@ -2663,6 +2794,7 @@ TAO_StreamEndPoint_A::multiconnect (AVStreams::streamQoS &stream_qos, 0); flow_spec[i] = CORBA::string_dup (new_entry->entry_to_string ()); //new_entry->is_multicast (1); + this->forward_flow_spec_set.insert (new_entry); TAO_AV_Acceptor_Registry *acceptor_registry = TAO_AV_CORE::instance ()->acceptor_registry (); result = acceptor_registry->open (this, @@ -2963,9 +3095,16 @@ TAO_VDev::set_media_ctrl (CORBA::Object_ptr media_ctrl, CORBA::Environment &ACE_TRY_ENV) { - ACE_UNUSED_ARG (media_ctrl); +// ACE_UNUSED_ARG (media_ctrl); ACE_UNUSED_ARG (ACE_TRY_ENV); ACE_CHECK_RETURN (0); + + // FIX MEMORY LEAK: + // since the media ctrl is not stored or used, delete it. + // cleaned up several memory leaks (according to BoundsChecker) + + delete media_ctrl; + return 1; } @@ -3070,7 +3209,7 @@ TAO_VDev::modify_QoS (AVStreams::streamQoS &the_qos, if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "TAO_VDev::modify_QoS\n")); - + if (flowspec.length () != 0) { TAO_Forward_FlowSpec_Entry entry; @@ -3079,12 +3218,12 @@ TAO_VDev::modify_QoS (AVStreams::streamQoS &the_qos, if (direction == 0) { AVStreams::StreamEndPoint_A_ptr sep_a; - + CORBA::Any_ptr streamendpoint_a_any = - this->get_property_value ("Related_StreamEndpoint_A", + this->get_property_value ("Related_StreamEndpoint", ACE_TRY_ENV); ACE_CHECK_RETURN (0); - + *streamendpoint_a_any >>= sep_a; if (sep_a != 0) { @@ -3099,13 +3238,13 @@ TAO_VDev::modify_QoS (AVStreams::streamQoS &the_qos, AVStreams::StreamEndPoint_B_ptr sep_b; CORBA::Any_ptr streamendpoint_b_any = - this->get_property_value ("Related_StreamEndpoint_B", + this->get_property_value ("Related_StreamEndpoint", ACE_TRY_ENV); ACE_CHECK_RETURN (0); *streamendpoint_b_any >>= sep_b; sep_b->modify_QoS (the_qos, flowspec, ACE_TRY_ENV); ACE_CHECK_RETURN (0); - } + } } return 1; } @@ -3395,12 +3534,16 @@ TAO_MMDevice::create_A (AVStreams::StreamCtrl_ptr streamctrl, ACE_CHECK_RETURN (0); AVStreams::StreamEndPoint_A_ptr sep_a = 0; - AVStreams::StreamEndPoint_ptr sep = 0; + // FIX MEMORY LEAK: + // if this causes a problem it will have to be changed back. None were found + // during testing. This cleaned up many memory leaks according to BoundsChecker +// AVStreams::StreamEndPoint_ptr sep; + AVStreams::StreamEndPoint_var sep; ACE_TRY { sep = this->create_A_B (MMDEVICE_A, streamctrl, the_vdev, stream_qos, met_qos, named_vdev, flow_spec, ACE_TRY_ENV); ACE_TRY_CHECK; - sep_a = AVStreams::StreamEndPoint_A::_narrow (sep, ACE_TRY_ENV); + sep_a = AVStreams::StreamEndPoint_A::_narrow (sep.in(), ACE_TRY_ENV); ACE_TRY_CHECK; } ACE_CATCHANY @@ -3430,12 +3573,18 @@ TAO_MMDevice::create_B (AVStreams::StreamCtrl_ptr streamctrl, AVStreams::noSuchFlow)) { AVStreams::StreamEndPoint_B_ptr sep_b = AVStreams::StreamEndPoint_B::_nil (); - AVStreams::StreamEndPoint_ptr sep; + + // FIX MEMORY LEAK: + // if this causes a problem it will have to be changed back. None were found + // during testing. This cleaned up many memory leaks according to BoundsChecker +// AVStreams::StreamEndPoint_ptr sep; + AVStreams::StreamEndPoint_var sep; + ACE_TRY { sep = this->create_A_B (MMDEVICE_B, streamctrl, the_vdev, stream_qos, met_qos, named_vdev, flow_spec, ACE_TRY_ENV); ACE_TRY_CHECK; - sep_b = AVStreams::StreamEndPoint_B::_narrow (sep, ACE_TRY_ENV); + sep_b = AVStreams::StreamEndPoint_B::_narrow (sep.in(), ACE_TRY_ENV); ACE_TRY_CHECK; } ACE_CATCHANY @@ -4017,7 +4166,6 @@ TAO_FlowConnection::add_producer (AVStreams::FlowProducer_ptr producer, char buf [BUFSIZ]; mcast_addr.addr_to_string (buf, BUFSIZ); ACE_OS::sprintf (mcast_address, "%s=%s", this->protocol_.in (), buf); - } else { @@ -4028,6 +4176,7 @@ TAO_FlowConnection::add_producer (AVStreams::FlowProducer_ptr producer, mcast_address, this->fp_name_.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; if (this->producer_address_.in () == 0) { @@ -4778,7 +4927,14 @@ TAO_FlowProducer::start (CORBA::Environment &/*ACE_TRY_ENV*/) begin != end; ++begin) { TAO_FlowSpec_Entry *entry = (*begin); - entry->handler ()->start (TAO_FlowSpec_Entry::TAO_AV_PRODUCER); + if (entry->handler () != 0) + { + entry->handler ()->start (TAO_FlowSpec_Entry::TAO_AV_PRODUCER); + } + if (entry->control_handler () != 0) + { + entry->control_handler ()->start (TAO_FlowSpec_Entry::TAO_AV_PRODUCER); + } } } @@ -4931,7 +5087,9 @@ TAO_FlowConsumer::start (CORBA::Environment &/*ACE_TRY_ENV*/) TAO_AV_FlowSpecSetItor end = this->flow_spec_set_.end (); for (TAO_AV_FlowSpecSetItor begin = this->flow_spec_set_.begin (); begin != end; ++begin) - (*begin)->handler ()->start (TAO_FlowSpec_Entry::TAO_AV_CONSUMER); + { + (*begin)->handler ()->start (TAO_FlowSpec_Entry::TAO_AV_CONSUMER); + } } char * @@ -5075,6 +5233,7 @@ TAO_Tokenizer::operator [] (size_t index) const } + #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) diff --git a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h index c85a2989177..0de8277fc7e 100644 --- a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h +++ b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h @@ -527,12 +527,16 @@ public: virtual void set_flow_handler (const char *flowname, TAO_AV_Flow_Handler *handler); + virtual void set_control_flow_handler (const char *flowname, + TAO_AV_Flow_Handler *handler); + TAO_AV_QoS &qos (void); - + protected: TAO_AV_QoS qos_; Flow_Handler_Map flow_handler_map_; + Flow_Handler_Map control_flow_handler_map_; }; diff --git a/TAO/orbsvcs/orbsvcs/AV/AV_Core.cpp b/TAO/orbsvcs/orbsvcs/AV/AV_Core.cpp index 92d501b3133..9cf546235b4 100644 --- a/TAO/orbsvcs/orbsvcs/AV/AV_Core.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/AV_Core.cpp @@ -40,6 +40,28 @@ TAO_AV_Core::~TAO_AV_Core (void) { delete this->connector_registry_; delete this->acceptor_registry_; + + TAO_AV_TransportFactorySetItor transport_iter = + this->transport_factories_.begin(); + + while (transport_iter != this->transport_factories_.end()) + { + delete (*transport_iter)->factory(); + delete (*transport_iter); + + transport_iter++; + } + + TAO_AV_Flow_ProtocolFactorySetItor flow_iter = + this->flow_protocol_factories_.begin(); + + while (flow_iter != this->flow_protocol_factories_.end()) + { + delete (*flow_iter)->factory(); + delete (*flow_iter); + + flow_iter++; + } } CORBA::ORB_ptr @@ -139,7 +161,7 @@ TAO_AV_Core::init_forward_flows (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core::EndPoint direction, AVStreams::flowSpec &flow_spec) { - if (TAO_debug_level > 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "TAO_AV_Core::init_forward_flows\n")); @@ -188,7 +210,7 @@ TAO_AV_Core::init_forward_flows (TAO_Base_StreamEndPoint *endpoint, ACE_Addr *address = entry->address (); if (address != 0) { - if (TAO_debug_level > 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "address given for flow %s", entry->flowname ())); @@ -231,7 +253,7 @@ TAO_AV_Core::init_forward_flows (TAO_Base_StreamEndPoint *endpoint, result = event_handler->reactor ()->remove_handler (event_handler, ACE_Event_Handler::READ_MASK); if (result < 0) - if (TAO_debug_level > 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "TAO_AV_Core::init_forward_flows: remove_handler failed\n")); #endif /*ACE_HAS_RAPI*/ @@ -344,15 +366,18 @@ TAO_AV_Core::init_forward_flows (TAO_Base_StreamEndPoint *endpoint, for (;connect != connect_end; ++connect) { ACE_Addr *local_addr; + ACE_Addr *local_control_addr; local_addr = (*connect)->get_local_addr (); - if (result == 0) + local_control_addr = (*connect)->get_local_control_addr (); + if (local_addr != 0) { TAO_Reverse_FlowSpec_Entry entry ((*connect)->flowname (), (*connect)->direction_str (), (*connect)->format (), (*connect)->flow_protocol_str (), (*connect)->carrier_protocol_str (), - local_addr); + local_addr, + local_control_addr); int len = new_flowspec.length (); if (i == len) @@ -367,16 +392,18 @@ TAO_AV_Core::init_forward_flows (TAO_Base_StreamEndPoint *endpoint, connect != connect_end; ++connect) { ACE_Addr *local_addr; + ACE_Addr *local_control_addr; local_addr = (*connect)->get_local_addr (); - if (result == 0) + local_control_addr = (*connect)->get_local_control_addr (); + if (local_addr != 0) { - TAO_Reverse_FlowSpec_Entry entry ((*connect)->flowname (), (*connect)->direction_str (), (*connect)->format (), (*connect)->flow_protocol_str (), (*connect)->carrier_protocol_str (), - local_addr); + local_addr, + local_control_addr); int len = new_flowspec.length (); if (i == len) @@ -472,7 +499,7 @@ TAO_AV_Core::init_reverse_flows (TAO_Base_StreamEndPoint *endpoint, int result = -1; switch (direction) { - + case TAO_AV_Core::TAO_AV_ENDPOINT_A: { result = this->connector_registry_->open (endpoint, @@ -547,6 +574,49 @@ TAO_AV_Core::get_connector (const char *flowname) return 0; } +TAO_AV_Flow_Protocol_Factory * +TAO_AV_Core::get_flow_protocol_factory(const char *flow_protocol) +{ + if (flow_protocol == 0) + return 0; + + for (TAO_AV_Flow_ProtocolFactorySetItor control_flow_factory = + this->flow_protocol_factories_.begin (); + control_flow_factory != + this->flow_protocol_factories_.end (); + ++control_flow_factory) + { + if ((*control_flow_factory)->factory ()->match_protocol (flow_protocol)) + { + return (*control_flow_factory)->factory (); + } + } + + // Not found. + return 0; +} + +TAO_AV_Transport_Factory * +TAO_AV_Core::get_transport_factory(const char *transport_protocol) +{ + if (transport_protocol == 0) + return 0; + + for (TAO_AV_TransportFactorySetItor transport_factory = + this->transport_factories_.begin (); + transport_factory != this->transport_factories_.end (); + ++transport_factory) + { + if ((*transport_factory)->factory ()->match_protocol (transport_protocol)) + { + return (*transport_factory)->factory (); + } + } + + // Not found. + return 0; +} + int TAO_AV_Core::load_default_transport_factories (void) { @@ -555,7 +625,7 @@ TAO_AV_Core::load_default_transport_factories (void) TAO_AV_Transport_Factory *udp_factory = 0; TAO_AV_Transport_Item *udp_item = 0; - + udp_factory = ACE_Dynamic_Service::instance (udp_factory_str); if (udp_factory == 0) @@ -565,7 +635,7 @@ TAO_AV_Core::load_default_transport_factories (void) "(%P|%t) WARNING - No %s found in Service Repository." " Using default instance.\n", "UDP Factory")); - + ACE_NEW_RETURN (udp_factory, TAO_AV_UDP_Factory, -1); @@ -588,7 +658,7 @@ TAO_AV_Core::load_default_transport_factories (void) "(%P|%t) WARNING - No %s found in Service Repository." " Using default instance.\n", "TCP Factory")); - + ACE_NEW_RETURN (tcp_factory, TAO_AV_TCP_Factory, -1); @@ -713,7 +783,7 @@ TAO_AV_Core::load_default_flow_protocol_factories (void) this->flow_protocol_factories_.insert (udp_item); #ifdef ACE_HAS_RAPI - + const char *udp_qos_flow = "UDP_QoS_Flow_Factory"; TAO_AV_Flow_Protocol_Factory *udp_qos_flow_factory = 0; TAO_AV_Flow_Protocol_Item *udp_qos_flow_item = 0; @@ -845,7 +915,7 @@ TAO_AV_Core::init_flow_protocol_factories (void) { ACE_DEBUG ((LM_DEBUG, "Loading default flow protocol factories\n")); - + this->load_default_flow_protocol_factories (); } else @@ -857,7 +927,7 @@ TAO_AV_Core::init_flow_protocol_factories (void) ACE_DEBUG ((LM_DEBUG, "%s \n", name.c_str ())); - + (*factory)->factory ( ACE_Dynamic_Service::instance (name.c_str ())); if ((*factory)->factory () == 0) diff --git a/TAO/orbsvcs/orbsvcs/AV/AV_Core.h b/TAO/orbsvcs/orbsvcs/AV/AV_Core.h index 2e12c35b9a3..e6714f92db1 100644 --- a/TAO/orbsvcs/orbsvcs/AV/AV_Core.h +++ b/TAO/orbsvcs/orbsvcs/AV/AV_Core.h @@ -27,7 +27,9 @@ class TAO_AV_Acceptor; class TAO_AV_Connector; class TAO_FlowSpec_Entry; class TAO_AV_Transport_Item; +class TAO_AV_Transport_Factory; class TAO_AV_Flow_Protocol_Item; +class TAO_AV_Flow_Protocol_Factory; typedef ACE_Unbounded_Set TAO_AV_FlowSpecSet; typedef ACE_Unbounded_Set_Iterator TAO_AV_FlowSpecSetItor; @@ -41,7 +43,7 @@ typedef ACE_Unbounded_Set_Iterator TAO_AV_Flow_Proto /** * @class TAO_AV_Core - * @brief This class encapsulates access to the TAO AV Core's resources + * @brief This class encapsulates access to the TAO AV Core's resources * and its state. */ class TAO_AV_Export TAO_AV_Core @@ -67,6 +69,13 @@ public: TAO_AV_QOS_UDP = 12 }; + enum Flow_Component + { + TAO_AV_DATA = 1, + TAO_AV_CONTROL = 2, + TAO_AV_BOTH = 3 + }; + /// Default constructor. TAO_AV_Core (void); @@ -102,6 +111,8 @@ public: // = Get the protocol factories /// = Set/get the . + TAO_AV_Flow_Protocol_Factory *get_flow_protocol_factory(const char *flow_protocol); + TAO_AV_Transport_Factory *get_transport_factory(const char *transport_protocol); TAO_AV_Flow_ProtocolFactorySet *flow_protocol_factories (void); TAO_AV_TransportFactorySet *transport_factories (void); void reactor (ACE_Reactor *r); diff --git a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp index a5daa017629..dbeadcf634a 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp @@ -129,7 +129,7 @@ TAO_AV_Endpoint_Reactive_Strategy ::activ // Activate the mediactrl object under the root poa. CORBA::String_var mediactrl_ior = this->activate_with_poa (media_ctrl, ACE_TRY_ENV); - + ACE_TRY_CHECK; if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activate_mediactrl , media_ctrl ior is :%s\n", mediactrl_ior.in ())); @@ -137,17 +137,20 @@ TAO_AV_Endpoint_Reactive_Strategy ::activ // Associate the media controller object reference with the vdev, as per the OMG spec CORBA::Any anyval; - CORBA::Object_var media_ctrl_obj + CORBA::Object_var media_ctrl_obj = media_ctrl->_this (ACE_TRY_ENV); ACE_TRY_CHECK; - + media_ctrl->_remove_ref (ACE_TRY_ENV); + ACE_TRY_CHECK; + anyval <<= this->orb_->object_to_string (media_ctrl_obj.in (), ACE_TRY_ENV); ACE_TRY_CHECK; - - this->vdev_->define_property ("Related_MediaCtrl", - anyval, - ACE_TRY_ENV); + + this->vdev_->define_property ("Related_MediaCtrl", + anyval, + ACE_TRY_ENV); + ACE_TRY_CHECK; } ACE_CATCHANY diff --git a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp index 1c853386025..27afeee6e72 100644 --- a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp @@ -5,6 +5,7 @@ //------------------------------------------------------------ #include "FlowSpec_Entry.h" +#include "Protocol_Factory.h" #include "tao/debug.h" @@ -17,9 +18,12 @@ // constructor. TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (void) :address_ (0), + control_address_ (0), address_str_ (), format_ (), direction_ (TAO_AV_INVALID), + direction_str_ (), + flowname_ (), protocol_ (TAO_AV_Core::TAO_AV_NOPROTOCOL), carrier_protocol_ (), flow_protocol_ (), @@ -27,10 +31,15 @@ TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (void) entry_ (), is_multicast_ (0), peer_addr_ (0), + peer_control_addr_ (0), local_addr_ (0), + local_control_addr_ (0), transport_ (0), + control_transport_ (0), handler_ (0), + control_handler_ (0), protocol_object_ (0), + control_protocol_object_ (0), role_ (TAO_AV_INVALID_ROLE) { } @@ -41,8 +50,10 @@ TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (const char *flowname, const char *format_name, const char *flow_protocol, const char *carrier_protocol, - ACE_Addr *address) + ACE_Addr *address, + ACE_Addr *control_address) :address_ (address), + control_address_ (control_address), address_str_ (), format_ (format_name), direction_str_ (direction ), @@ -53,10 +64,15 @@ TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (const char *flowname, entry_ (), is_multicast_ (0), peer_addr_ (0), + peer_control_addr_ (0), local_addr_ (0), + local_control_addr_ (0), transport_ (0), + control_transport_ (0), handler_ (0), + control_handler_ (0), protocol_object_ (0), + control_protocol_object_ (0), role_ (TAO_AV_INVALID_ROLE) { this->set_protocol (); @@ -70,6 +86,7 @@ TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (const char *flowname, const char *flow_protocol, const char *address) :address_ (0), + control_address_ (0), address_str_ ( address ), format_ ( format_name ), direction_str_ ( direction ), @@ -80,25 +97,43 @@ TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (const char *flowname, entry_ (), is_multicast_ (0), peer_addr_ (0), + peer_control_addr_ (0), local_addr_ (0), + local_control_addr_ (0), transport_ (0), + control_transport_ (0), handler_ (0), + control_handler_ (0), protocol_object_ (0), + control_protocol_object_ (0), role_ (TAO_AV_INVALID_ROLE) { - ACE_CString cstring(this->address_str_); - int colon_pos = cstring.find (':'); - if (colon_pos != cstring.npos) - cstring[colon_pos] = ';'; - this->address_str_ = cstring; this->parse_flow_protocol_string (this->flow_protocol_.c_str() ); - this->parse_address (this->address_str_.c_str() ); + this->parse_address (this->address_str_.c_str(), TAO_AV_Core::TAO_AV_DATA ); this->set_direction (this->direction_str_.c_str() ); } // Destructor. TAO_FlowSpec_Entry::~TAO_FlowSpec_Entry (void) { + if (this->address_) + delete this->address_; + + if (this->control_address_) + delete this->control_address_; + + if (this->protocol_object_) + delete this->protocol_object_; + + if (this->control_protocol_object_) + delete this->control_protocol_object_; + + if (this->handler_) + delete this->handler_; + + if (this->control_handler_) + delete this->control_handler_; + } int @@ -156,8 +191,6 @@ TAO_FlowSpec_Entry::set_protocol (void) ACE_DEBUG ((LM_DEBUG,"TAO_FlowSpec_Entry::set_protocol:%s %x\n",buf, inet_addr->get_ip_address ())); if (IN_CLASSD (inet_addr->get_ip_address ())) { - - this->is_multicast_ = 1; switch (this->protocol_) { @@ -179,13 +212,15 @@ TAO_FlowSpec_Entry::set_protocol (void) } int -TAO_FlowSpec_Entry::parse_address (const char *address) +TAO_FlowSpec_Entry::parse_address (const char *address, + TAO_AV_Core::Flow_Component flow_comp) { if (address == 0) return 0; if (ACE_OS::strcmp (address,"") == 0) return 0; TAO_Tokenizer protocol_tokenizer (address,'='); + this->carrier_protocol_ = protocol_tokenizer[0]; int result = this->set_protocol (); @@ -194,56 +229,140 @@ TAO_FlowSpec_Entry::parse_address (const char *address) if (protocol_tokenizer [1] != 0) { - TAO_Tokenizer address_tokenizer (protocol_tokenizer[1],';'); - ACE_CString addr; - // convert to the ACE_Addr format. - addr = address_tokenizer[0]; - addr += ":"; - addr += address_tokenizer[1]; + if ( (flow_comp == TAO_AV_Core::TAO_AV_DATA) || + (flow_comp == TAO_AV_Core::TAO_AV_CONTROL) ) + { + ACE_CString addr; + addr += protocol_tokenizer[1]; - switch (this->protocol_) + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_SFP_UDP: + case TAO_AV_Core::TAO_AV_RTP_UDP: + case TAO_AV_Core::TAO_AV_TCP: + case TAO_AV_Core::TAO_AV_UDP: + case TAO_AV_Core::TAO_AV_QOS_UDP: + { + if (flow_comp == TAO_AV_Core::TAO_AV_DATA) + this->address_str_ = addr; + ACE_INET_Addr *inet_addr; + ACE_NEW_RETURN (inet_addr, + ACE_INET_Addr (addr.c_str() ), + -1); + if (flow_comp == TAO_AV_Core::TAO_AV_DATA) + this->address_ = inet_addr; + else + this->control_address_ = inet_addr; + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "TAO_FlowSpec_Entry::parse_address %s %x\n", address,inet_addr->get_ip_address () )); + + if (IN_CLASSD (inet_addr->get_ip_address ())) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "TAO_FlowSpec_Entry::parse_address is multicast\n")); + + this->is_multicast_ = 1; + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_UDP: + this->protocol_ = TAO_AV_Core::TAO_AV_UDP_MCAST; + break; + case TAO_AV_Core::TAO_AV_RTP_UDP: + this->protocol_ = TAO_AV_Core::TAO_AV_RTP_UDP_MCAST; + break; + case TAO_AV_Core::TAO_AV_SFP_UDP: + this->protocol_ = TAO_AV_Core::TAO_AV_SFP_UDP_MCAST; + break; + default: + break; + } + } + } + break; + default: + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"ATM support not added yet\n")); + } + } + else { - case TAO_AV_Core::TAO_AV_SFP_UDP: - case TAO_AV_Core::TAO_AV_RTP_UDP: - case TAO_AV_Core::TAO_AV_TCP: - case TAO_AV_Core::TAO_AV_UDP: - case TAO_AV_Core::TAO_AV_QOS_UDP: - { - this->address_str_ = addr; - ACE_INET_Addr *inet_addr; - ACE_NEW_RETURN (inet_addr, - ACE_INET_Addr (addr.c_str() ), - -1); - this->address_ = inet_addr; - if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, "TAO_FlowSpec_Entry::parse_address %s %x\n", address,inet_addr->get_ip_address () )); - - if (IN_CLASSD (inet_addr->get_ip_address ())) + TAO_Tokenizer address_tokenizer (protocol_tokenizer[1], ':'); + TAO_Tokenizer port_tokenizer (address_tokenizer[1], ';'); + ACE_CString addr; + addr += address_tokenizer[0]; + addr += ":"; + addr += port_tokenizer[0]; + + short control_port = ACE_OS::atoi(port_tokenizer[0]) + 1; + char control_port_str[6]; + sprintf (control_port_str, "%d", control_port); + + ACE_CString control_addr = ""; + if (ACE_OS::strcasecmp (this->carrier_protocol_.c_str(),"RTP/UDP") == 0) + { + control_addr += address_tokenizer[0]; + control_addr += ":"; + if (port_tokenizer[1] != 0) + control_addr += port_tokenizer[1]; + else + control_addr += control_port_str; + } + + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_SFP_UDP: + case TAO_AV_Core::TAO_AV_RTP_UDP: + case TAO_AV_Core::TAO_AV_TCP: + case TAO_AV_Core::TAO_AV_UDP: + case TAO_AV_Core::TAO_AV_QOS_UDP: { + this->address_str_ = addr; + ACE_INET_Addr *inet_addr; + ACE_NEW_RETURN (inet_addr, + ACE_INET_Addr (addr.c_str() ), + -1); + this->address_ = inet_addr; if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG, "TAO_FlowSpec_Entry::parse_address is multicast\n")); + ACE_DEBUG ((LM_DEBUG, "TAO_FlowSpec_Entry::parse_address %s %x\n", address,inet_addr->get_ip_address () )); - this->is_multicast_ = 1; - switch (this->protocol_) + if (ACE_OS::strcasecmp (this->carrier_protocol_.c_str(),"RTP/UDP") == 0) { - case TAO_AV_Core::TAO_AV_UDP: - this->protocol_ = TAO_AV_Core::TAO_AV_UDP_MCAST; - break; - case TAO_AV_Core::TAO_AV_RTP_UDP: - this->protocol_ = TAO_AV_Core::TAO_AV_RTP_UDP_MCAST; - break; - case TAO_AV_Core::TAO_AV_SFP_UDP: - this->protocol_ = TAO_AV_Core::TAO_AV_SFP_UDP_MCAST; - break; - default: - break; + ACE_INET_Addr *control_inet_addr; + ACE_NEW_RETURN (control_inet_addr, + ACE_INET_Addr (control_addr.c_str() ), + -1); + this->control_address_ = control_inet_addr; + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "TAO_FlowSpec_Entry::parse_address %s %x\n", address,control_inet_addr->get_ip_address () )); + } + + if (IN_CLASSD (inet_addr->get_ip_address ())) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "TAO_FlowSpec_Entry::parse_address is multicast\n")); + + this->is_multicast_ = 1; + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_UDP: + this->protocol_ = TAO_AV_Core::TAO_AV_UDP_MCAST; + break; + case TAO_AV_Core::TAO_AV_RTP_UDP: + this->protocol_ = TAO_AV_Core::TAO_AV_RTP_UDP_MCAST; + break; + case TAO_AV_Core::TAO_AV_SFP_UDP: + this->protocol_ = TAO_AV_Core::TAO_AV_SFP_UDP_MCAST; + break; + default: + break; + } } } - } - break; - default: - if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"ATM support not added yet\n")); + break; + default: + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"ATM support not added yet\n")); + } } } return 0; @@ -267,9 +386,7 @@ TAO_FlowSpec_Entry::get_local_addr_str (void) ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr *,this->local_addr_); inet_addr->addr_to_string (buf,BUFSIZ); ACE_CString cstring (buf, 0, 0); - int colon_pos = cstring.find (':'); - if (colon_pos != cstring.npos) - cstring[colon_pos] = ';'; + return cstring.rep (); } default: @@ -284,6 +401,7 @@ TAO_FlowSpec_Entry::get_local_addr_str (void) // default constructor. TAO_Forward_FlowSpec_Entry::TAO_Forward_FlowSpec_Entry (void) { + // no-op. } // constructor to construct the entry from the arguments. @@ -292,14 +410,17 @@ TAO_Forward_FlowSpec_Entry::TAO_Forward_FlowSpec_Entry (const char *flowname, const char *format_name , const char *flow_protocol , const char *carrier_protocol , - ACE_Addr *address ) + ACE_Addr *address, + ACE_Addr *control_address ) :TAO_FlowSpec_Entry (flowname, direction, format_name, flow_protocol, carrier_protocol, - address) + address, + control_address) { + // no-op. } // constructor to construct the entry from the arguments. @@ -314,6 +435,12 @@ TAO_Forward_FlowSpec_Entry::TAO_Forward_FlowSpec_Entry (const char *flowname, flow_protocol, address) { + // no-op. +} + +TAO_Forward_FlowSpec_Entry::~TAO_Forward_FlowSpec_Entry (void) +{ + // no-op. } int @@ -323,6 +450,11 @@ TAO_Forward_FlowSpec_Entry::parse (const char *flowSpec_entry) this->flowname_ = tokenizer [TAO_AV_FLOWNAME]; + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + "TAO_Forward_FlowSpec_Entry::parse %s\n", + flowSpec_entry)); + if (tokenizer [TAO_AV_DIRECTION] != 0) this->set_direction (tokenizer [TAO_AV_DIRECTION]); @@ -330,7 +462,7 @@ TAO_Forward_FlowSpec_Entry::parse (const char *flowSpec_entry) this->format_ = tokenizer [TAO_AV_FORMAT]; if (tokenizer [TAO_AV_ADDRESS] != 0) - if (this->parse_address (tokenizer [TAO_AV_ADDRESS]) < 0) + if (this->parse_address (tokenizer [TAO_AV_ADDRESS], TAO_AV_Core::TAO_AV_BOTH) < 0) return -1; if (tokenizer [TAO_AV_FLOW_PROTOCOL] != 0) @@ -363,10 +495,11 @@ const char * TAO_Forward_FlowSpec_Entry::entry_to_string (void) { if (this->flowname_.length() == 0) - return 0; + return ""; char address [BUFSIZ]; ACE_CString address_str; + if (this->address_ != 0) { switch (this->protocol_) @@ -388,19 +521,76 @@ TAO_Forward_FlowSpec_Entry::entry_to_string (void) break; } ACE_CString cstring (address); - int colon_pos = cstring.find (':'); - if (colon_pos != cstring.npos) - cstring[colon_pos] = ';'; - address_str = this->carrier_protocol_; address_str += "="; address_str += cstring; } - else{ - address_str = this->carrier_protocol_; - } + else + { + address_str = this->carrier_protocol_; + } + + if ( (this->address_ != 0) && + (this->control_address_ == 0) && + (ACE_OS::strncasecmp (this->flow_protocol_.c_str(), "RTP", 3) == 0)) + { + u_short control_port; + + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_SFP_UDP: + case TAO_AV_Core::TAO_AV_SFP_UDP_MCAST: + case TAO_AV_Core::TAO_AV_RTP_UDP: + case TAO_AV_Core::TAO_AV_RTP_UDP_MCAST: + case TAO_AV_Core::TAO_AV_UDP: + case TAO_AV_Core::TAO_AV_QOS_UDP: + case TAO_AV_Core::TAO_AV_UDP_MCAST: + case TAO_AV_Core::TAO_AV_TCP: + { + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,this->address_); + control_port = inet_addr->get_port_number() + 1; + ACE_INET_Addr *inet_control_addr; + ACE_NEW_RETURN (inet_control_addr, + ACE_INET_Addr (control_port, inet_addr->get_host_addr ()), + ""); + this->control_address_ = inet_control_addr; + } + break; + default: + break; + } + } + + if (this->control_address_ != 0) + { + u_short control_port; + + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_SFP_UDP: + case TAO_AV_Core::TAO_AV_SFP_UDP_MCAST: + case TAO_AV_Core::TAO_AV_RTP_UDP: + case TAO_AV_Core::TAO_AV_RTP_UDP_MCAST: + case TAO_AV_Core::TAO_AV_UDP: + case TAO_AV_Core::TAO_AV_QOS_UDP: + case TAO_AV_Core::TAO_AV_UDP_MCAST: + case TAO_AV_Core::TAO_AV_TCP: + { + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,this->control_address_); + control_port = inet_addr->get_port_number(); + } + break; + default: + break; + } + + address_str += ";"; + char port_str[10]; + sprintf(port_str, "%u", control_port); + address_str += port_str; + } this->entry_ = this->flowname_; this->entry_ += "\\"; @@ -423,6 +613,7 @@ TAO_Forward_FlowSpec_Entry::entry_to_string (void) //default constructor. TAO_Reverse_FlowSpec_Entry::TAO_Reverse_FlowSpec_Entry (void) { + // no-op } // constructor to construct an entry from the arguments. @@ -431,14 +622,17 @@ TAO_Reverse_FlowSpec_Entry::TAO_Reverse_FlowSpec_Entry (const char *flowname, const char *format_name , const char *flow_protocol , const char *carrier_protocol, - ACE_Addr *address) + ACE_Addr *address, + ACE_Addr *control_address ) :TAO_FlowSpec_Entry (flowname, direction, format_name, flow_protocol, carrier_protocol, - address) + address, + control_address) { + // no-op } // constructor to construct an entry from the arguments. @@ -453,6 +647,12 @@ TAO_Reverse_FlowSpec_Entry::TAO_Reverse_FlowSpec_Entry (const char *flowname, flow_protocol, address) { + // no-op. +} + +TAO_Reverse_FlowSpec_Entry::~TAO_Reverse_FlowSpec_Entry (void) +{ + // no-op. } TAO_FlowSpec_Entry::Role @@ -479,19 +679,24 @@ TAO_Reverse_FlowSpec_Entry::parse (const char *flowSpec_entry) TAO_Tokenizer tokenizer (flowSpec_entry,'\\'); this->flowname_ = tokenizer [TAO_AV_FLOWNAME]; + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + "TAO_Reverse_FlowSpec_Entry::parse %s\n", + flowSpec_entry)); + if (tokenizer [TAO_AV_ADDRESS] != 0) - if (this->parse_address (tokenizer [TAO_AV_ADDRESS]) < 0) + if (this->parse_address (tokenizer [TAO_AV_ADDRESS], TAO_AV_Core::TAO_AV_BOTH) < 0) return -1; if (tokenizer [TAO_AV_FLOW_PROTOCOL] != 0) if (this->parse_flow_protocol_string (tokenizer [TAO_AV_FLOW_PROTOCOL]) < 0) return -1; - if (tokenizer [TAO_AV_DIRECTION] != 0) - this->set_direction (tokenizer [TAO_AV_DIRECTION]); +// if (tokenizer [TAO_AV_DIRECTION] != 0) +// this->set_direction (tokenizer [TAO_AV_DIRECTION]); - if (tokenizer [TAO_AV_FORMAT] != 0) - this->format_ = tokenizer [TAO_AV_FORMAT]; +// if (tokenizer [TAO_AV_FORMAT] != 0) +// this->format_ = tokenizer [TAO_AV_FORMAT]; return 0; } @@ -501,13 +706,12 @@ const char * TAO_Reverse_FlowSpec_Entry::entry_to_string (void) { if (this->flowname_.length() == 0) - return 0; + return ""; char address [BUFSIZ]; ACE_CString address_str; if (this->address_ != 0) { - switch (this->protocol_) { case TAO_AV_Core::TAO_AV_RTP_UDP: @@ -525,28 +729,57 @@ TAO_Reverse_FlowSpec_Entry::entry_to_string (void) break; } ACE_CString cstring (address); - int colon_pos = cstring.find (':'); - if (colon_pos != cstring.npos) - cstring[colon_pos] = ';'; address_str = this->carrier_protocol_; address_str += "="; address_str += cstring; } - else{ - address_str = ""; - } + else + { + address_str = ""; + } + + if (this->control_address_ != 0) + { + u_short control_port; + + + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_SFP_UDP: + case TAO_AV_Core::TAO_AV_SFP_UDP_MCAST: + case TAO_AV_Core::TAO_AV_RTP_UDP: + case TAO_AV_Core::TAO_AV_RTP_UDP_MCAST: + case TAO_AV_Core::TAO_AV_UDP: + case TAO_AV_Core::TAO_AV_QOS_UDP: + case TAO_AV_Core::TAO_AV_UDP_MCAST: + case TAO_AV_Core::TAO_AV_TCP: + { + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,this->control_address_); + control_port = inet_addr->get_port_number(); + } + break; + default: + break; + } + + address_str += ";"; + char port_str[10]; + sprintf(port_str, "%u", control_port); + address_str += port_str; + + } this->entry_ = this->flowname_; this->entry_ += "\\"; this->entry_ += address_str; this->entry_ += "\\"; this->entry_ += this->flow_protocol_; - this->entry_ += "\\"; - this->entry_ += this->direction_str_; - this->entry_ += "\\"; - this->entry_ += format_; +// this->entry_ += "\\"; +// this->entry_ += this->direction_str_; +// this->entry_ += "\\"; +// this->entry_ += format_; if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"entry_to_string: entry = %s\n",this->entry_.c_str() )); return this->entry_.c_str(); diff --git a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h index 3fc8cf1d652..adb0ec1cb27 100644 --- a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h +++ b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h @@ -89,7 +89,8 @@ public: const char *format_name, const char *flow_protocol, const char *carrier_protocol, - ACE_Addr *address); + ACE_Addr *address, + ACE_Addr *control_address = 0); TAO_FlowSpec_Entry (const char *flowname, const char *direction, @@ -119,6 +120,9 @@ public: /// accessor to address of the carrier protocol. ACE_Addr *address (void); + ACE_Addr *control_address (void); + void address (ACE_Addr *address); + void control_address (ACE_Addr *address); /// Address in string format i. hostname:port. const char * address_str (void) const; @@ -140,18 +144,34 @@ public: int set_peer_addr (ACE_Addr *peer_addr); ACE_Addr *get_peer_addr (void); - int set_local_addr (ACE_Addr *peer_addr); + int set_peer_control_addr (ACE_Addr *peer_control_addr); + ACE_Addr *get_peer_control_addr (void); + + int set_local_addr (ACE_Addr *local_addr); ACE_Addr *get_local_addr (void); char *get_local_addr_str (void); + int set_local_control_addr (ACE_Addr *local_control_addr); + ACE_Addr *get_local_control_addr (void); + char *get_local_control_addr_str (void); + TAO_AV_Transport *transport (void); void transport (TAO_AV_Transport *transport); + TAO_AV_Transport *control_transport (void); + void control_transport (TAO_AV_Transport *control_transport); + TAO_AV_Flow_Handler* handler (void); void handler (TAO_AV_Flow_Handler *handler); + TAO_AV_Flow_Handler* control_handler (void); + void control_handler (TAO_AV_Flow_Handler *control_handler); + TAO_AV_Protocol_Object* protocol_object (void); void protocol_object (TAO_AV_Protocol_Object *object); + TAO_AV_Protocol_Object* control_protocol_object (void); + void control_protocol_object (TAO_AV_Protocol_Object *object); /// sets the address for this flow. - int parse_address (const char *format_string); + int parse_address (const char *format_string, + TAO_AV_Core::Flow_Component flow_component); /// returns true for a multicast address. int is_multicast (void); @@ -169,6 +189,7 @@ protected: /// Addr information for the carrier protocol. ACE_Addr *address_; + ACE_Addr *control_address_; /// Addr in string format i.e hostname:port. ACE_CString address_str_; @@ -201,13 +222,19 @@ protected: int is_multicast_; ACE_Addr *peer_addr_; + ACE_Addr *peer_control_addr_; ACE_Addr *local_addr_; + ACE_Addr *local_control_addr_; TAO_AV_Transport *transport_; + TAO_AV_Transport *control_transport_; TAO_AV_Flow_Handler *handler_; + TAO_AV_Flow_Handler *control_handler_; TAO_AV_Protocol_Object *protocol_object_; + TAO_AV_Protocol_Object *control_protocol_object_; Role role_; }; + /** * @class TAO_Forward_FlowSpec_Entry * @brief @@ -231,7 +258,8 @@ public: const char *format_name, const char *flow_protocol, const char *carrier_protocol, - ACE_Addr *address); + ACE_Addr *address, + ACE_Addr *control_address = 0); TAO_Forward_FlowSpec_Entry (const char *flowname, const char *direction, @@ -239,6 +267,8 @@ public: const char *flow_protocol, const char *address); + virtual ~TAO_Forward_FlowSpec_Entry (void); + /// converts the entry to a string. virtual const char *entry_to_string (void); @@ -271,7 +301,8 @@ public: const char *format_name, const char *flow_protocol, const char *carrier_protocol, - ACE_Addr *address); + ACE_Addr *address, + ACE_Addr *control_address = 0); // Takes the address in protocol=endpoint form. TAO_Reverse_FlowSpec_Entry (const char *flowname, @@ -280,6 +311,8 @@ public: const char *flow_protocol, const char *address); + virtual ~TAO_Reverse_FlowSpec_Entry (void); + /// converts the entry to a string. virtual const char *entry_to_string (void); diff --git a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i index 110a4e40f9c..a15fbb6f00d 100644 --- a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i +++ b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i @@ -30,6 +30,13 @@ TAO_FlowSpec_Entry::parse_flow_protocol_string (const char *flow_string) { this->use_flow_protocol_ = 1; // do some flow protocol processing. + this->flow_protocol_ = flow_string; + } + if (ACE_OS::strncasecmp (flow_string,"rtp",3) == 0) + { + // TODO: this makes it work but should probably change +// this->use_flow_protocol_ = 1; + this->flow_protocol_ = flow_string; } return 0; @@ -84,6 +91,27 @@ TAO_FlowSpec_Entry::address (void) return this->address_; } +ACE_INLINE +void +TAO_FlowSpec_Entry::address (ACE_Addr *addr) +{ + this->address_ = addr; +} + +ACE_INLINE +ACE_Addr * +TAO_FlowSpec_Entry::control_address (void) +{ + return this->control_address_; +} + +ACE_INLINE +void +TAO_FlowSpec_Entry::control_address (ACE_Addr *addr) +{ + this->control_address_ = addr; +} + ACE_INLINE const char * TAO_FlowSpec_Entry::address_str (void) const @@ -131,6 +159,14 @@ TAO_FlowSpec_Entry::set_local_addr (ACE_Addr *local_addr) return 0; } +ACE_INLINE +int +TAO_FlowSpec_Entry::set_local_control_addr (ACE_Addr *local_addr) +{ + this->local_control_addr_ = local_addr; + return 0; +} + ACE_INLINE ACE_Addr* TAO_FlowSpec_Entry::get_local_addr (void) @@ -138,6 +174,13 @@ TAO_FlowSpec_Entry::get_local_addr (void) return this->local_addr_; } +ACE_INLINE +ACE_Addr* +TAO_FlowSpec_Entry::get_local_control_addr (void) +{ + return this->local_control_addr_; +} + ACE_INLINE TAO_AV_Transport* TAO_FlowSpec_Entry::transport (void) @@ -152,6 +195,20 @@ TAO_FlowSpec_Entry::transport (TAO_AV_Transport *transport) this->transport_ = transport; } +ACE_INLINE +TAO_AV_Transport* +TAO_FlowSpec_Entry::control_transport (void) +{ + return this->control_transport_; +} + +ACE_INLINE +void +TAO_FlowSpec_Entry::control_transport (TAO_AV_Transport *control_transport) +{ + this->control_transport_ = control_transport; +} + ACE_INLINE TAO_AV_Flow_Handler * TAO_FlowSpec_Entry::handler (void) @@ -159,11 +216,19 @@ TAO_FlowSpec_Entry::handler (void) return this->handler_; } +ACE_INLINE +TAO_AV_Flow_Handler * +TAO_FlowSpec_Entry::control_handler (void) +{ + return this->control_handler_; +} + ACE_INLINE void TAO_FlowSpec_Entry::handler (TAO_AV_Flow_Handler *handler) { this->handler_ = handler; + // // Now remove the handler from the reactor if the handler is for a producer. // switch (this->role ()) // { @@ -179,6 +244,13 @@ TAO_FlowSpec_Entry::handler (TAO_AV_Flow_Handler *handler) // } } +ACE_INLINE +void +TAO_FlowSpec_Entry::control_handler (TAO_AV_Flow_Handler *handler) +{ + this->control_handler_ = handler; +} + ACE_INLINE TAO_AV_Protocol_Object* TAO_FlowSpec_Entry::protocol_object (void) @@ -193,6 +265,20 @@ TAO_FlowSpec_Entry::protocol_object (TAO_AV_Protocol_Object *object) this->protocol_object_ = object; } +ACE_INLINE +TAO_AV_Protocol_Object* +TAO_FlowSpec_Entry::control_protocol_object (void) +{ + return this->control_protocol_object_; +} + +ACE_INLINE +void +TAO_FlowSpec_Entry::control_protocol_object (TAO_AV_Protocol_Object *object) +{ + this->control_protocol_object_ = object; +} + ACE_INLINE int TAO_FlowSpec_Entry::is_multicast (void) diff --git a/TAO/orbsvcs/orbsvcs/AV/MCast.cpp b/TAO/orbsvcs/orbsvcs/AV/MCast.cpp index 080db22025f..f6a6ab6a4dd 100644 --- a/TAO/orbsvcs/orbsvcs/AV/MCast.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/MCast.cpp @@ -5,7 +5,7 @@ #include "AVStreams_i.h" #include "tao/debug.h" -#if !defined(__ACE_INLINE__) +#if !defined (__ACE_INLINE__) #include "MCast.i" #endif /* __ACE_INLINE__ */ @@ -31,8 +31,8 @@ TAO_AV_UDP_MCast_Flow_Handler::~TAO_AV_UDP_MCast_Flow_Handler (void) int TAO_AV_UDP_MCast_Flow_Handler::handle_input (ACE_HANDLE /*fd*/) { - this->protocol_object_->handle_input (); - return 0; + return this->protocol_object_->handle_input (); +// return 0; } int @@ -49,6 +49,11 @@ TAO_AV_UDP_MCast_Flow_Handler::get_handle (void) const return this->get_mcast_socket ()->get_handle () ; } +void +TAO_AV_UDP_MCast_Flow_Handler::set_peer_addr (ACE_INET_Addr *peer_addr) +{ + this->peer_addr_ = peer_addr; +} //------------------------------------------------------------ // TAO_AV_UDP_MCast_Transport @@ -161,6 +166,7 @@ TAO_AV_UDP_MCast_Transport::send (const char *buf, // if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"to %s\n",addr)); return this->handler_->get_mcast_socket ()->send (buf, len); + } ssize_t diff --git a/TAO/orbsvcs/orbsvcs/AV/MCast.h b/TAO/orbsvcs/orbsvcs/AV/MCast.h index 745aaa517b4..1f5330ff8c1 100644 --- a/TAO/orbsvcs/orbsvcs/AV/MCast.h +++ b/TAO/orbsvcs/orbsvcs/AV/MCast.h @@ -94,14 +94,15 @@ public: /// Ctor /// Dtor TAO_AV_UDP_MCast_Flow_Handler (void); - ~TAO_AV_UDP_MCast_Flow_Handler (void); + virtual ~TAO_AV_UDP_MCast_Flow_Handler (void); virtual ACE_HANDLE get_handle (void) const; virtual int handle_input (ACE_HANDLE fd); virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0); ACE_SOCK_Dgram_Mcast *get_mcast_socket (void) const; virtual ACE_Event_Handler* event_handler (void){ return this; } + void set_peer_addr (ACE_INET_Addr *peer_addr); protected: - ACE_INET_Addr peer_addr_; + ACE_INET_Addr *peer_addr_; ACE_SOCK_Dgram_Mcast *dgram_mcast_; }; diff --git a/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp b/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp index 9f491217f05..56379f64ac2 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp @@ -49,6 +49,7 @@ TAO_AV_Protocol_Object::TAO_AV_Protocol_Object (void) :transport_ (0), callback_ (0) { + // no-op. } TAO_AV_Protocol_Object::TAO_AV_Protocol_Object (TAO_AV_Callback *callback, @@ -56,6 +57,7 @@ TAO_AV_Protocol_Object::TAO_AV_Protocol_Object (TAO_AV_Callback *callback, :transport_ (transport), callback_ (callback) { + // no-op. } int @@ -69,7 +71,6 @@ TAO_AV_Protocol_Object::open (TAO_AV_Callback *callback, TAO_AV_Protocol_Object::~TAO_AV_Protocol_Object (void) { - //no-op } int diff --git a/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.cpp b/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.cpp index d41fa1d5a16..dcf151a4691 100644 --- a/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.cpp @@ -76,7 +76,7 @@ TAO_AV_UDP_QoS_Session_Helper::set_qos (ACE_Flow_Spec &ace_flow_spec, if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "Filled up the Receiver QoS parameters\n")); - + } ACE_QoS_Manager qos_manager = handler->get_socket ()->qos_manager (); @@ -127,13 +127,13 @@ TAO_AV_UDP_QoS_Session_Helper::open_qos_session (TAO_AV_UDP_QoS_Flow_Handler *ha // A QoS session is defined by the 3-tuple [DestAddr, DestPort, // Protocol]. Initialize the QoS session. if (qos_session->open (dest_addr, - IPPROTO_UDP) == -1) + IPPROTO_UDP) == -1) ACE_ERROR_RETURN ((LM_ERROR, - "Error in opening the QoS session\n"), - 0); + "Error in opening the QoS session\n"), + 0); else ACE_DEBUG ((LM_DEBUG, - "QoS session opened successfully\n")); + "QoS session opened successfully\n")); if (handler->flowspec_entry ()->role () == TAO_FlowSpec_Entry::TAO_AV_PRODUCER) { @@ -274,7 +274,7 @@ TAO_AV_UDP_QoS_Flow_Handler::translate (CosPropertyService::Properties &qos_para ace_flow_spec->priority (priority); } } - + return 0; } @@ -343,13 +343,13 @@ TAO_AV_UDP_QoS_Flow_Handler::handle_qos (ACE_HANDLE /*fd*/) { resv_confirm = 1; } - + if (this->qos_session_->flags () == ACE_QoS_Session::ACE_QOS_SENDER) { if (this->qos_session_->rsvp_event_type () == ACE_QoS_Session::RSVP_RESV_EVENT) { if( TAO_debug_level > 0 ) - { + { ACE_DEBUG ((LM_DEBUG, "(%N,%l) Resv Event Received\n")); } @@ -371,7 +371,7 @@ TAO_AV_UDP_QoS_Flow_Handler::handle_qos (ACE_HANDLE /*fd*/) this->translate (ace_flow_spec, new_qos [0].QoSParams); } - + AVStreams::Negotiator_var remote_negotiator; this->negotiator_->negotiate (remote_negotiator.in (), new_qos, @@ -392,7 +392,7 @@ TAO_AV_UDP_QoS_Flow_Handler::handle_qos (ACE_HANDLE /*fd*/) &qos_manager, ace_qos); } - } + } return 0; } @@ -511,12 +511,12 @@ TAO_AV_UDP_QoS_Flow_Handler::set_remote_address (ACE_Addr *address) ACE_ERROR_RETURN ((LM_ERROR, "QoS Session Open Failed (%N|%l)\n"), -1); - + ACE_INET_Addr local_addr; this->get_socket ()->get_local_addr (local_addr); this->qos_session_->source_port (local_addr.get_port_number ()); - + if (helper.activate_qos_handler (this->qos_session_, this) == -1) ACE_ERROR_RETURN ((LM_ERROR, @@ -648,7 +648,7 @@ TAO_AV_UDP_QoS_Transport::send (const ACE_Message_Block *mblk, } size_t bytes_sent = 0; - + // Check for remaining buffers to be sent! if (iovcnt != 0) { @@ -670,7 +670,7 @@ TAO_AV_UDP_QoS_Transport::send (const ACE_Message_Block *mblk, if (n < 1) return n; - + nbytes += bytes_sent; } @@ -682,7 +682,7 @@ TAO_AV_UDP_QoS_Transport::send (const char *buf, size_t len, ACE_Time_Value *) { - if (TAO_debug_level > 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%N,%l) TAO_AV_UDP_QoS_Transport::send ")); @@ -796,8 +796,11 @@ int TAO_AV_UDP_QoS_Acceptor::open (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) { + ACE_UNUSED_ARG (flow_comp); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%N,%l) TAO_AV_UDP_QoS_Acceptor::open ")); @@ -832,8 +835,11 @@ int TAO_AV_UDP_QoS_Acceptor::open_default (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) { + ACE_UNUSED_ARG (flow_comp); + this->av_core_ = av_core; this->endpoint_ = endpoint; this->entry_ = entry; @@ -884,7 +890,7 @@ TAO_AV_UDP_QoS_Acceptor::open_i (ACE_INET_Addr *inet_addr) FillQoSParams (qos_params, 0, ace_qos); - + TAO_AV_UDP_QoS_Flow_Handler* handler; ACE_NEW_RETURN (handler, @@ -937,7 +943,7 @@ TAO_AV_UDP_QoS_Acceptor::open_i (ACE_INET_Addr *inet_addr) char dest_buf [BUFSIZ]; dest_addr.addr_to_string (dest_buf, BUFSIZ); - + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "Session Address is %s\n", @@ -950,7 +956,7 @@ TAO_AV_UDP_QoS_Acceptor::open_i (ACE_INET_Addr *inet_addr) ACE_ERROR_RETURN ((LM_ERROR, "QoS Session Open Failed (%N|%l)\n"), -1); - + handler->qos_session (this->qos_session_); if (this->activate_svc_handler (handler) == -1) @@ -972,7 +978,7 @@ TAO_AV_UDP_QoS_Acceptor::open_i (ACE_INET_Addr *inet_addr) handler->translate (qos.QoSParams, ace_flow_spec); - + if (helper.set_qos (*ace_flow_spec, handler) == -1) @@ -1016,7 +1022,7 @@ TAO_AV_UDP_QoS_Acceptor::open_i (ACE_INET_Addr *inet_addr) this->endpoint_->get_property_value ("Negotiator", ACE_TRY_ENV); ACE_TRY_CHECK_EX (negotiator); - + *negotiator_any >>= negotiator; handler->negotiator (negotiator); } @@ -1139,8 +1145,11 @@ TAO_AV_UDP_QoS_Connector::open (TAO_Base_StreamEndPoint *endpoint, int TAO_AV_UDP_QoS_Connector::connect (TAO_FlowSpec_Entry *entry, - TAO_AV_Transport *&transport) + TAO_AV_Transport *&transport, + TAO_AV_Core::Flow_Component flow_comp) { + ACE_UNUSED_ARG (flow_comp); + ACE_DECLARE_NEW_CORBA_ENV; int result = 0; this->entry_ = entry; @@ -1167,7 +1176,7 @@ TAO_AV_UDP_QoS_Connector::connect (TAO_FlowSpec_Entry *entry, ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*, entry->address ()); - + ACE_QoS_Params qos_params; ACE_QoS* ace_qos = 0; @@ -1255,7 +1264,7 @@ TAO_AV_UDP_QoS_Connector::connect (TAO_FlowSpec_Entry *entry, qos); if (qos_available == 0) { - + ACE_Flow_Spec* ace_flow_spec; ACE_NEW_RETURN (ace_flow_spec, ACE_Flow_Spec, @@ -1284,7 +1293,7 @@ TAO_AV_UDP_QoS_Connector::connect (TAO_FlowSpec_Entry *entry, flow_handler->transport ()); AVStreams::Negotiator_ptr negotiator; - + ACE_TRY_EX (negotiator) { CORBA::Any_ptr negotiator_any = diff --git a/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.h b/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.h index 981f1c5a2da..7b60c2fa503 100644 --- a/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.h +++ b/TAO/orbsvcs/orbsvcs/AV/QoS_UDP.h @@ -161,12 +161,16 @@ public: virtual int open (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory); + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp = + TAO_AV_Core::TAO_AV_DATA); virtual int open_default (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory); + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp = + TAO_AV_Core::TAO_AV_DATA); virtual int open_i (ACE_INET_Addr *address); @@ -194,7 +198,9 @@ public: TAO_AV_Flow_Protocol_Factory *factory); virtual int connect (TAO_FlowSpec_Entry *entry, - TAO_AV_Transport *&transport); + TAO_AV_Transport *&transport, + TAO_AV_Core::Flow_Component flow_comp = + TAO_AV_Core::TAO_AV_DATA); virtual int activate_svc_handler (TAO_AV_UDP_QoS_Flow_Handler *handler); virtual int close (void); diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP.cpp b/TAO/orbsvcs/orbsvcs/AV/RTCP.cpp index cd661516434..7f2197c0622 100644 --- a/TAO/orbsvcs/orbsvcs/AV/RTCP.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP.cpp @@ -37,543 +37,303 @@ #include "RTCP.h" #include "media-timer.h" #include "tao/debug.h" +#include "global.h" +#include "md5.h" +#include "RTCP_Packet.h" -// TAO_AV_RTP_State -TAO_AV_RTP_State::TAO_AV_RTP_State (void) - :bad_version_(0), - badoptions_(0), - badfmt_(0), - badext_(0), - nrunt_(0), - last_np_(0), - sdes_seq_(0), - rtcp_inv_bw_(0.), - rtcp_avg_size_(128.), - confid_(-1) -{ - ACE_NEW (pktbuf_, - u_char [2 * RTP_MTU]); -} - -//------------------------------------------------------------ -// TAO_AV_RTCP -//------------------------------------------------------------ -u_char* -TAO_AV_RTCP::build_sdes_item (u_char* p, - int code, - TAO_AV_Source& s) +int +TAO_AV_RTCP_Callback::receive_control_frame (ACE_Message_Block *data, + const ACE_Addr &peer_address) { - const char* value = s.sdes (code); - if (value != 0) - { - int len = strlen (value); - *p++ = code; - *p++ = len; - memcpy (p, value, len); - p += len; - } - return (p); -} + int length = data->length (); + int more = length; + char *buf_ptr = data->rd_ptr (); + char first_rtcp_packet = 1; + RTCP_Channel_In *c; -int -TAO_AV_RTCP::build_sdes (rtcphdr* rh, - TAO_AV_Source& ls, - TAO_AV_RTP_State *state) -{ - int flags = RTP_VERSION << 14 | 1 << 8 | RTCP_PT_SDES; - rh->rh_flags = htons (flags); - rh->rh_ssrc = ls.srcid (); - u_char* p = (u_char*) (rh + 1); - p = build_sdes_item (p, RTCP_SDES_CNAME, ls); - - /* - * We always send a cname plus one other sdes - * There's a schedule for what we send sequenced by sdes_seq_: - * - send 'email' every 0th & 4th packet - * - send 'note' every 2nd packet - * - send 'tool' every 6th packet - * - send 'name' in all the odd slots - * (if 'note' is not the empty string, we switch the roles - * of name & note) - */ - int nameslot, noteslot; - const char* note = ls.sdes (RTCP_SDES_NOTE); - if (note) + // This code performs the RTCP Header validity checks detailed in RFC 1889 + // Appendix A.2 + + while (more > 0) { - if (*note) - { - nameslot = RTCP_SDES_NOTE; - noteslot = RTCP_SDES_NAME; - } else + // the second byte of the control packet is the type + switch ((unsigned char)buf_ptr[length - more + 1]) + { + case RTCP_PT_SR: { - nameslot = RTCP_SDES_NAME; - noteslot = RTCP_SDES_NOTE; + RTCP_SR_Packet sr(&buf_ptr[length-more], + &more); + + if (!sr.is_valid(first_rtcp_packet)) + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTCP_Callback::receive_control_frame - " + "warning invalid rtcp packet\n")); + + if (this->inputs_.find (sr.ssrc (), c) == -1) + { + ACE_NEW_RETURN (c, + RTCP_Channel_In (sr.ssrc (), + &peer_address), + -1); + this->inputs_.bind (sr.ssrc (), c); + } + c->updateStatistics (&sr); + + if (TAO_debug_level > 0) + sr.dump (); + break; } - } - else - { - nameslot = RTCP_SDES_NAME; - noteslot = RTCP_SDES_NAME; - } - u_int seq = (++state->sdes_seq_) & 0x7; - switch (seq) - { - case 0: - case 4: - p = build_sdes_item (p, RTCP_SDES_EMAIL, ls); - break; - case 2: - p = build_sdes_item (p, noteslot, ls); - break; - case 6: - p = build_sdes_item (p, RTCP_SDES_TOOL, ls); - break; - default: - p = build_sdes_item (p, nameslot, ls); - } - - int len = p - (u_char*)rh; - int pad = 4 - (len & 3); - len += pad; - rh->rh_len = htons ( (len >> 2) - 1); - while (--pad >= 0) - *p++ = 0; - - return (len); -} - -int -TAO_AV_RTCP::build_bye (rtcphdr* rh, - TAO_AV_Source& ls) -{ - int flags = - RTP_VERSION << 14 | 1 << 8 | RTCP_PT_BYE; - rh->rh_flags = ntohs (flags); - rh->rh_len = htons (1); - rh->rh_ssrc = ls.srcid (); - return (8); -} + case RTCP_PT_RR: + { + RTCP_RR_Packet rr(&buf_ptr[length-more], + &more); + + if (!rr.is_valid(first_rtcp_packet)) + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTCP_Callback::receive_control_frame - " + "warning invalid rtcp packet\n")); + + if (this->inputs_.find (rr.ssrc (), c) == -1) + { + ACE_NEW_RETURN (c, + RTCP_Channel_In (rr.ssrc (), + &peer_address), + -1); + this->inputs_.bind (rr.ssrc (), c); + } + + c->updateStatistics (&rr); + + if (TAO_debug_level > 0) + rr.dump (); + break; + } + case RTCP_PT_SDES: + { + RTCP_SDES_Packet sdes (&buf_ptr[length-more], + &more); -void -TAO_AV_RTCP::parse_rr_records (ACE_UINT32, - rtcp_rr*, - int, - const u_char*, - ACE_UINT32) -{ - if (TAO_debug_level > 0) ACE_DEBUG ( (LM_DEBUG,"TAO_AV_RTCP::parse_rr_records\n")); -} + if (!sdes.is_valid(first_rtcp_packet)) + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTCP_Callback::receive_control_frame - " + "warning invalid rtcp packet\n")); -void -TAO_AV_RTCP::parse_sr (rtcphdr* rh, - int flags, - u_char*ep, - TAO_AV_Source* ps, - ACE_UINT32 addr, - TAO_AV_SourceManager *source_manager) -{ - rtcp_sr* sr = ACE_reinterpret_cast (rtcp_sr*, (rh + 1)); - TAO_AV_Source* s; - ACE_UINT32 ssrc = rh->rh_ssrc; - if (ps->srcid () != ssrc) - s = source_manager->lookup (ssrc, ssrc, addr); - else - s = ps; + if (TAO_debug_level > 0) + sdes.dump (); + break; + } + case RTCP_PT_BYE: + { + RTCP_BYE_Packet bye (&buf_ptr[length-more], + &more); - s->lts_ctrl (ACE_OS::gettimeofday ()); - s->sts_ctrl (ntohl (sr->sr_ntp.upper) << 16 | - ntohl (sr->sr_ntp.lower) >> 16); + if (!bye.is_valid(first_rtcp_packet)) + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTCP_Callback::receive_control_frame - " + "warning invalid rtcp packet\n")); - int cnt = flags >> 8 & 0x1f; - parse_rr_records (ssrc, ACE_reinterpret_cast (rtcp_rr*, (sr + 1)), cnt, ep, addr); -} + // Inform the listener that a source(s) has left the session + ACE_UINT32 *ssrc_list; + unsigned char length; -void -TAO_AV_RTCP::parse_rr (rtcphdr* rh, - int flags, - u_char* ep, - TAO_AV_Source* ps, - ACE_UINT32 addr, - TAO_AV_SourceManager *source_manager) -{ - TAO_AV_Source* s; - ACE_UINT32 ssrc = rh->rh_ssrc; - if (ps->srcid () != ssrc) - s = source_manager->lookup (ssrc, ssrc, addr); - else - s = ps; + bye.ssrc_list(&ssrc_list, length); - s->lts_ctrl (ACE_OS::gettimeofday ()); - int cnt = flags >> 8 & 0x1f; - parse_rr_records (ssrc, ACE_reinterpret_cast (rtcp_rr*, (rh + 1)), cnt, ep, addr); -} + for (int i=0; isrcid () != srcid) - s = source_manager->lookup (srcid, ssrc, addr); - else - s = ps; - if (s == 0) - return (0); - /* - * Note ctrl packet since we will never see any direct ctrl packets - * from a TAO_AV_Source through a mixer (and we don't want the TAO_AV_Source to - * time out). - */ - s->lts_ctrl (ACE_OS::gettimeofday ()); + // remove the channel from the list + this->inputs_.unbind(ssrc_list[i], c); - u_char* cp = (u_char*) (p + 1); - while (cp < ep) - { - char buf[256]; + if (c != 0) + delete c; + } - u_int type = cp[0]; - if (type == 0) - { - /* end of chunk */ - return ( ( (cp - (u_char*)p) >> 2) + 1); - } - u_int len = cp[1]; - u_char* eopt = cp + len + 2; - if (eopt > ep) - return (0); + if (TAO_debug_level > 0) + bye.dump (); - if (type >= RTCP_SDES_MIN && type <= RTCP_SDES_MAX) - { - memcpy (buf, (char*)&cp[2], len); - buf[len] = 0; - s->sdes (type, buf); - } - else - /*XXX*/; + break; + } + case RTCP_PT_APP: + // If we receive one of these, ignore it. + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTCP_Callback::receive_control_frame - " + "APP packet - ignore\n")); + more -= (4 + (ACE_UINT16)buf_ptr[length - more + 2]); + break; + default: + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTCP_Callback::receive_control_frame - " + "UNKNOWN packet type %u; ignore the rest\n", + (int)buf_ptr[length - more + 1])); + more = 0; + } + + first_rtcp_packet = 0; - cp = eopt; } - return (0); -} -void -TAO_AV_RTCP::parse_sdes (rtcphdr* rh, - int flags, - u_char* ep, - TAO_AV_Source* ps, - ACE_UINT32 addr, - ACE_UINT32 ssrc, - TAO_AV_SourceManager *source_manager) -{ - int cnt = flags >> 8 & 0x1f; - ACE_UINT32* p = (ACE_UINT32*)&rh->rh_ssrc; - while (--cnt >= 0) - { - int n = TAO_AV_RTCP::sdesbody (p, ep, ps, addr, ssrc, source_manager); - if (n == 0) - break; - p += n; - } - if (cnt >= 0) - ps->badsdes (1); + if (more != 0) + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTCP_Callback::receive_control_frame - " + "Error in overall packet length\n")); + return 0; } -void -TAO_AV_RTCP::parse_bye (rtcphdr* rh, - int flags, - u_char* ep, - TAO_AV_Source* ps, - TAO_AV_SourceManager *source_manager) -{ - int cnt = flags >> 8 & 0x1f; - ACE_UINT32* p = (ACE_UINT32*)&rh->rh_ssrc; +ACE_INT32 random32 (int); - while (--cnt >= 0) +ACE_UINT32 +TAO_AV_RTCP::alloc_srcid (ACE_UINT32 addr) +{ + struct { - if (p >= (ACE_UINT32*)ep) - { - ps->badbye (1); - return; - } - TAO_AV_Source* s; - if (ps->srcid () != rh->rh_ssrc) - s = source_manager->consult (*p); - else - s = ps; - if (s != 0) - s->lts_done (ACE_OS::gettimeofday ()); - ++p; - } + int type; + ACE_Time_Value tv; + pid_t pid; + pid_t pgid; + pid_t ppid; + uid_t uid; + gid_t gid; + } s; + + s.type = addr; + s.tv = ACE_OS::gettimeofday (); + s.pid = ACE_OS::getpid(); + s.pgid = ACE_OS::getpgid(s.pid); + s.ppid = ACE_OS::getppid(); + s.uid = ACE_OS::getuid(); + s.gid = ACE_OS::getgid(); + + unsigned char *string_val = (unsigned char *) &s; + int length = sizeof(s); + + MD5_CTX context; + union + { + char c[16]; + u_long x[4]; + } digest; + ACE_UINT32 r; + int i; + + MD5Init (&context); + MD5Update (&context, string_val, length); + MD5Final ((unsigned char*)&digest, &context); + r=0; + for (i=0; i<3; i++) + r ^= digest.x[i]; + + return r; + +/* used to be this + ACE_Time_Value tv = ACE_OS::gettimeofday (); + ACE_UINT32 srcid = ACE_UINT32 (tv.sec () + tv.usec ()); + srcid += (ACE_UINT32)ACE_OS::getuid(); + srcid += (ACE_UINT32)ACE_OS::getpid(); + srcid += addr; + return (srcid); +*/ } -/*XXX check for buffer overflow*/ -/* - * Send an RTPv2 report packet. - */ -void -TAO_AV_RTCP::send_report (int bye, - TAO_AV_Protocol_Object *protocol_object, - TAO_AV_SourceManager *source_manager, - TAO_AV_RTP_State *state, - TAO_AV_RTCP_Callback *callback) -{ - if (source_manager->localsrc () == 0) - return; - TAO_AV_Source& s = *source_manager->localsrc (); - rtcphdr* rh = (rtcphdr*)state->pktbuf_; - rh->rh_ssrc = s.srcid (); - int flags = RTP_VERSION << 14; - timeval now = ACE_OS::gettimeofday (); - s.lts_ctrl (now); - int we_sent = 0; - rtcp_rr* rr; - /* - * If we've sent data since our last sender report send a - * new report. The MediaTimer check is to make sure we still - * have a grabber -- if not, we won't be able to interpret the - * media timestamps so there's no point in sending an SR. - */ - MediaTimer* mt = MediaTimer::instance (); - if (s.np () != state->last_np_ && mt) { - state->last_np_ = s.np (); - we_sent = 1; - flags |= RTCP_PT_SR; - rtcp_sr* sr = ACE_reinterpret_cast (rtcp_sr*, (rh + 1)); - sr->sr_ntp = ntp64time (now); - sr->sr_ntp.upper = ACE_HTONL (sr->sr_ntp.upper); - sr->sr_ntp.lower = ACE_HTONL (sr->sr_ntp.lower); - sr->sr_ts = htonl (mt->ref_ts ()); - sr->sr_np = htonl (s.np ()); - sr->sr_nb = htonl (s.nb ()); - rr = ACE_reinterpret_cast (rtcp_rr*, (sr + 1)); - } else { - flags |= RTCP_PT_RR; - rr = ACE_reinterpret_cast (rtcp_rr*, (rh + 1)); - } - int nrr = 0; - int nsrc = 0; - /* - * we don't want to inflate report interval if user has set - * the flag that causes all TAO_AV_Sources to be 'kept' so we - * consider TAO_AV_Sources 'inactive' if we haven't heard a control - * msg from them for ~32 reporting intervals. - */ - u_int inactive = u_int (state->rint_ * (32./1000.)); - if (inactive < 2) - inactive = 2; - for (TAO_AV_Source* sp = source_manager->sources (); sp != 0; sp = sp->next_) { - ++nsrc; - int received = sp->np () - sp->snp (); - if (received == 0) { - if (u_int (now.tv_sec - sp->lts_ctrl ().tv_sec) > inactive) - --nsrc; - continue; - } - sp->snp (sp->np ()); - rr->rr_srcid = sp->srcid (); - int expected = sp->ns () - sp->sns (); - sp->sns (sp->ns ()); - ACE_UINT32 v; - int lost = expected - received; - if (lost <= 0) - v = 0; - else - /* expected != 0 if lost > 0 */ - v = ( (lost << 8) / expected) << 24; - /* XXX should saturate on over/underflow */ - v |= (sp->ns () - sp->np ()) & 0xffffff; - rr->rr_loss = htonl (v); - rr->rr_ehsr = htonl (sp->ehs ()); - rr->rr_dv = sp->delvar (); - rr->rr_lsr = htonl (sp->sts_ctrl ()); - if (sp->lts_ctrl ().tv_sec == 0) - rr->rr_dlsr = 0; - else { - ACE_UINT32 ntp_now = ntptime (now); - ACE_UINT32 ntp_then = ntptime (sp->lts_ctrl ()); - rr->rr_dlsr = htonl (ntp_now - ntp_then); - } - ++rr; - if (++nrr >= 31) - break; - } - flags |= nrr << 8; - rh->rh_flags = htons (flags); - int len = (u_char*)rr - state->pktbuf_; - rh->rh_len = htons ( (len >> 2) - 1); - - if (bye) - len += build_bye ( ACE_reinterpret_cast (rtcphdr*,rr), s); - else - len += build_sdes ( ACE_reinterpret_cast (rtcphdr*, rr), s,state); - - ACE_Message_Block mb ((char *)state->pktbuf_, len); - mb.wr_ptr (len); - protocol_object->send_frame (&mb); - - state->rtcp_avg_size_ += RTCP_SIZE_GAIN * (double (len + 28) - state->rtcp_avg_size_); - - /* - * compute the time to the next report. we do this here - * because we need to know if there were any active TAO_AV_Sources - * during the last report period (nrr above) & if we were - * a TAO_AV_Source. The bandwidth limit for rtcp traffic was set - * on startup from the session bandwidth. It is the inverse - * of bandwidth (ie., ms/byte) to avoid a divide below. - */ - double ibw = state->rtcp_inv_bw_; - if (nrr) { - /* there were active TAO_AV_Sources */ - if (we_sent) { - ibw *= 1./RTCP_SENDER_BW_FRACTION; - nsrc = nrr; - } else { - ibw *= 1./RTCP_RECEIVER_BW_FRACTION; - nsrc -= nrr; - } - } - double rint = state->rtcp_avg_size_ * double (nsrc) * ibw; - if (rint < RTCP_MIN_RPT_TIME * 1000.) - rint = RTCP_MIN_RPT_TIME * 1000.; - state->rint_ = rint; - callback->schedule (int (TAO_AV_RTCP::fmod (double (ACE_OS::rand ()), rint) + rint * .5 + .5)); - - source_manager->CheckActiveSources (rint); -} -int -TAO_AV_RTCP::handle_input (ACE_Message_Block *data, - const ACE_Addr &peer_address, - rtcphdr &header, - TAO_AV_SourceManager *source_manager, - TAO_AV_RTP_State *state) -{ - int cc = data->length (); - int size_phdr = ACE_static_cast (int, sizeof (rtcphdr)); - if (cc < size_phdr) - { - state->nrunt_++; - ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:invalid header\n"),-1); - } - if (peer_address == ACE_Addr::sap_any) - ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:get_peer_addr failed\n"),-1); - // @@ We need to be careful of this. - u_long addr = peer_address.hash (); - header = * (rtcphdr*) (data->rd_ptr ()); - rtcphdr *rh = (rtcphdr *)data->rd_ptr (); - /* - * try to filter out junk: first thing in packet must be - * sr, rr or bye & version number must be correct. - */ - switch (ntohs (rh->rh_flags) & 0xc0ff) +double +TAO_AV_RTCP::rtcp_interval (int members, + int senders, + double rtcp_bw, + int we_sent, + int packet_size, + int *avg_rtcp_size, + int initial) +{ + // Minimum time between RTCP packets from this site (in sec.). + // This time prevents the reports from 'clumping' when sessions + // are small and the law of large numbers isn't helping to smooth + // out the traffic. It also keeps the report interval from + // becoming ridiculously small during transient outages like a + // network partition. +// double const RTCP_MIN_TIME = 5.0; (from RTP.h) + + // Fraction of the RTCP bandwidth to be shared among active + // senders. (This fraction was chosen so that in a typical + // session with one or two active senders, the computed report + // time would be roughly equal to the minimum report time so that + // we don't unnecessarily slow down receiver reports.) The + // receiver fraction must be 1 - the sender fraction. +// double const RTCP_SENDER_BW_FRACTION = 0.25; (from RTP.h) +// double const RTCP_RCVR_BW_FRACTION = (1-RTCP_SENDER_BW_FRACTION); (from RTP.h) + + // Gain (smoothing constant) for the low-pass filter that + // estimates the average RTCP packet size +// double const RTCP_SIZE_GAIN = (1.0/16.0); (from RTP.h) + + double t; + double rtcp_min_time = RTCP_MIN_RPT_TIME; + int n; // number of members for computation + + // Very first call at application start-up uses half the min + // delay for quicker notification while still allowing some time + // before reporting for randomization and to learn about other + // sources so the report interval will converge to the correct + // interval more quickly. The average RTCP size is initialized + // to 128 octets which is conservative (it assumes everyone else + // is generating SRs instead of RRs: 20 IP + 8 UDP + 52 SR + 48 + // SDES CNAME). + if (initial) { - case RTP_VERSION << 14 | RTCP_PT_SR: - case RTP_VERSION << 14 | RTCP_PT_RR: - case RTP_VERSION << 14 | RTCP_PT_BYE: - break; - default: - /* - * XXX should further categorize this error -- it is - * likely that people mis-implement applications that - * don't put something other than SR,RR,BYE first. - */ - ++state->bad_version_; - return -1; - } - /* - * at this point we think the packet's valid. Update our average - * size estimator. Also, there's valid ssrc so charge errors to it - */ - - - double tmp = (cc + 28) - state->rtcp_avg_size_; - tmp *= RTCP_SIZE_GAIN; - state->rtcp_avg_size_ += ACE_static_cast (int, tmp); - /* - * First record in compound packet must be the ssrc of the - * sender of the packet. Pull it out here so we can use - * it in the sdes parsing, since the sdes record doesn't - * contain the ssrc of the sender (in the case of mixers). - */ - ACE_UINT32 ssrc = rh->rh_ssrc; - TAO_AV_Source* ps = source_manager->lookup (ssrc, ssrc, addr); - if (ps == 0) - return 0; + // initialize the random number generator + ACE_OS::srand((unsigned int)avg_rtcp_size); - /* - * Outer loop parses multiple RTCP records of a "compound packet". - * There is no framing between records. Boundaries are implicit - * and the overall length comes from UDP. - */ - u_char* epack = (u_char*)rh + cc; - while ( (u_char*)rh < epack) { - u_int len = (ntohs (rh->rh_len) << 2) + 4; - u_char* ep = (u_char*)rh + len; - if (ep > epack) { - ps->badsesslen (1); - return 0; - } - u_int flags = ntohs (rh->rh_flags); - if (flags >> 14 != RTP_VERSION) { - ps->badsessver (1); - return 0; + rtcp_min_time /= 2; + *avg_rtcp_size = 128; } - switch (flags & 0xff) { - case RTCP_PT_SR: - TAO_AV_RTCP::parse_sr (rh, flags, ep, ps, addr, source_manager); - break; + // If there were active senders, give them at least a minimum + // share of the RTCP bandwidth. Otherwise all participants share + // the RTCP bandwidth equally. + n = members; + if ((senders > 0) && (senders < members*RTCP_SENDER_BW_FRACTION)) + { + if (we_sent) + { + rtcp_bw *= RTCP_SENDER_BW_FRACTION; + n = senders; + } + else + { + rtcp_bw *= RTCP_RECEIVER_BW_FRACTION; + n -= senders; + } + } - case RTCP_PT_RR: - TAO_AV_RTCP::parse_rr (rh, flags, ep, ps, addr, source_manager); - break; + // Update the average size estimate by the size of the report + // packet we just sent. + *avg_rtcp_size += (int)((packet_size - *avg_rtcp_size)*RTCP_SIZE_GAIN); - case RTCP_PT_SDES: - TAO_AV_RTCP::parse_sdes (rh, flags, ep, ps, addr, ssrc, source_manager); - break; + // The effective number of sites times the average packet size is + // the total number of octets sent when each site sends a report. + // Dividing this by the effective bandwidth gives the time + // interval over which those packets must be sent in order to + // meet the bandwidth target, with a minimum enforced. In that + // time interval we send one report so this time is also our + // average time between reports. + t = (*avg_rtcp_size) * n / rtcp_bw; + if (t < rtcp_min_time) + t = rtcp_min_time; - case RTCP_PT_BYE: - TAO_AV_RTCP::parse_bye (rh, flags, ep, ps, source_manager); - break; + // To avoid traffic bursts from unintended synchronization with + // other sites, we then pick our actual next report interval as a + // random number uniformly distributed between 0.5*t and 1.5*t. - default: - ps->badsessopt (1); - break; - } - rh = (rtcphdr*)ep; - } - return 0; -} + // TODO: this may not be right. need a random number between 0 and 1 + int max_rand = 32768; -ACE_UINT32 -TAO_AV_RTCP::alloc_srcid (ACE_UINT32 addr) -{ - ACE_Time_Value tv = ACE_OS::gettimeofday (); - ACE_UINT32 srcid = ACE_UINT32 (tv.sec () + tv.usec ()); - srcid += (ACE_UINT32)ACE_OS::getuid(); - srcid += (ACE_UINT32)ACE_OS::getpid(); - srcid += addr; - return (srcid); + return t * ((double)ACE_OS::rand()/max_rand + 0.5); +// return t * (drand48() + 0.5); } -double -TAO_AV_RTCP::fmod (double dividend, double divisor) -{ - //Method to calculate the fmod (x,y) - int quotient = ACE_static_cast (int, (dividend / divisor)); - double product = quotient * divisor; - double remainder = dividend - product; - return remainder; -} - // TAO_AV_RTCP_Flow_Factory TAO_AV_RTCP_Flow_Factory::TAO_AV_RTCP_Flow_Factory (void) @@ -588,7 +348,8 @@ int TAO_AV_RTCP_Flow_Factory::match_protocol (const char *flow_string) { if (ACE_OS::strncasecmp (flow_string,"RTCP",4) == 0) - return 1; + return 1; + return 0; } @@ -600,25 +361,27 @@ TAO_AV_RTCP_Flow_Factory::init (int /* argc */, } TAO_AV_Protocol_Object* -TAO_AV_RTCP_Flow_Factory::make_protocol_object (TAO_FlowSpec_Entry *entry, - TAO_Base_StreamEndPoint *endpoint, +TAO_AV_RTCP_Flow_Factory::make_protocol_object (TAO_FlowSpec_Entry */*entry*/, + TAO_Base_StreamEndPoint */*endpoint*/, TAO_AV_Flow_Handler *handler, TAO_AV_Transport *transport) { - TAO_AV_Callback *callback = 0; - endpoint->get_control_callback (entry->flowname (), - callback); - if (callback == 0) - ACE_NEW_RETURN (callback, - TAO_AV_RTCP_Callback, - 0); + TAO_AV_Callback *client_cb = 0; + TAO_AV_RTCP_Callback *rtcp_cb = 0; + + // TODO: need to handle a client callback at some point +// endpoint->get_control_callback (entry->flowname (), +// client_cb); + TAO_AV_Protocol_Object *object = 0; ACE_NEW_RETURN (object, - TAO_AV_RTCP_Object (callback, + TAO_AV_RTCP_Object (client_cb, + rtcp_cb, transport), 0); - callback->open (object, - handler); + + rtcp_cb->open (object, handler); + return object; } @@ -626,19 +389,17 @@ TAO_AV_RTCP_Flow_Factory::make_protocol_object (TAO_FlowSpec_Entry *entry, int TAO_AV_RTCP_Object::handle_input (void) { - ACE_Message_Block *data; size_t bufsiz = 2*this->transport_->mtu (); - ACE_NEW_RETURN (data, - ACE_Message_Block (bufsiz), - -1); - int n = this->transport_->recv (data->rd_ptr (),bufsiz); + ACE_Message_Block data (bufsiz); + + int n = this->transport_->recv (data.rd_ptr (),bufsiz); if (n == 0) ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:connection closed\n"),-1); if (n < 0) ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:recv error\n"),-1); - data->wr_ptr (n); + data.wr_ptr (n); ACE_Addr *peer_addr = this->transport_->get_peer_addr (); - this->callback_->receive_control_frame (data,*peer_addr); + this->callback_->receive_control_frame (&data,*peer_addr); return 0; } @@ -665,10 +426,14 @@ TAO_AV_RTCP_Object::send_frame (const char*, return 0; } -TAO_AV_RTCP_Object::TAO_AV_RTCP_Object (TAO_AV_Callback *callback, +TAO_AV_RTCP_Object::TAO_AV_RTCP_Object (TAO_AV_Callback *client_cb, + TAO_AV_RTCP_Callback *&rtcp_cb, TAO_AV_Transport *transport) - :TAO_AV_Protocol_Object (callback,transport) + :TAO_AV_Protocol_Object (&rtcp_cb_, transport) { + rtcp_cb = &this->rtcp_cb_; + this->client_cb_ = client_cb; + } TAO_AV_RTCP_Object::~TAO_AV_RTCP_Object (void) @@ -678,6 +443,11 @@ TAO_AV_RTCP_Object::~TAO_AV_RTCP_Object (void) int TAO_AV_RTCP_Object::destroy (void) { + TAO_AV_UDP_Transport *my_transport = ACE_dynamic_cast (TAO_AV_UDP_Transport*, + this->transport_); + + my_transport->handler ()->cancel_timer (); + this->callback_->handle_destroy (); return 0; } @@ -704,51 +474,45 @@ int TAO_AV_RTCP_Object::handle_control_input (ACE_Message_Block *frame, const ACE_Addr &peer_address) { -// frame->rd_ptr ((size_t)0); -// // Since the rd_ptr would have been moved ahead. return this->callback_->receive_frame (frame, 0, peer_address); } -// TAO_AV_RTCP_Callback -TAO_AV_RTCP_Callback::TAO_AV_RTCP_Callback (void) +int +TAO_AV_RTCP_Object::handle_control_output (ACE_Message_Block *frame) { - ACE_NEW (source_manager_, - TAO_AV_SourceManager (this)); + TAO_AV_RTCP_Callback *cb = ACE_dynamic_cast (TAO_AV_RTCP_Callback*, + this->callback_); - ACE_NEW (this->state_, - TAO_AV_RTP_State); + return cb->send_frame (frame); } -TAO_AV_RTCP_Callback::~TAO_AV_RTCP_Callback (void) +void +TAO_AV_RTCP_Object::ts_offset (ACE_UINT32 ts_offset) { + TAO_AV_RTCP_Callback *cb = ACE_dynamic_cast (TAO_AV_RTCP_Callback*, + this->callback_); + return cb->ts_offset (ts_offset); } -TAO_AV_SourceManager* -TAO_AV_RTCP_Callback::source_manager (void) +// TAO_AV_RTCP_Callback +TAO_AV_RTCP_Callback::TAO_AV_RTCP_Callback (void) + :is_initial_timeout_(1), + packet_size_(0) { - return this->source_manager_; -} + char cname[256]; + char host[256]; + ACE_OS::hostname(host, sizeof(host)); -TAO_AV_RTP_State* -TAO_AV_RTCP_Callback::state (void) -{ - return this->state_; + // TODO: determine username auto-magically? + ACE_OS::sprintf(cname, "username@%s", host); + + this->output_.cname(cname); } -int -TAO_AV_RTCP_Callback::get_rtp_source (TAO_AV_Source *&source, - ACE_UINT32 srcid, - ACE_UINT32 ssrc, - ACE_UINT32 addr) -{ - ACE_NEW_RETURN (source, - TAO_AV_Source (srcid, - ssrc, - addr), - -1); - return 0; +TAO_AV_RTCP_Callback::~TAO_AV_RTCP_Callback (void) +{ } void @@ -757,25 +521,9 @@ TAO_AV_RTCP_Callback::schedule (int ms) this->timeout_ = ms; } - int TAO_AV_RTCP_Callback::handle_start (void) { - // - /* - * schedule a timer for our first report using half the - * min rtcp interval. This gives us some time before - * our first report to learn about other sources so our - * next report interval will account for them. The avg - * rtcp size was initialized to 128 bytes which is - * conservative (it assumes everyone else is generating - * SRs instead of RRs). - */ - double rint = this->state_->rtcp_avg_size_ * this->state_->rtcp_inv_bw_; - if (rint < RTCP_MIN_RPT_TIME / 2. * 1000.) - rint = RTCP_MIN_RPT_TIME / 2. * 1000.; - this->state_->rint_ = rint; - this->timeout_ = int(TAO_AV_RTCP::fmod(double(ACE_OS::rand ()), rint) + rint * .5 + .5); return 0; } @@ -788,34 +536,244 @@ TAO_AV_RTCP_Callback::handle_stop (void) int TAO_AV_RTCP_Callback::handle_timeout (void * /*arg*/) { - // Here we do the send_report. - TAO_AV_RTCP::send_report (0, - this->protocol_object_, - this->source_manager_, - this->state_, - this); + return this->send_report(0); +} + +int +TAO_AV_RTCP_Callback::send_report (int bye) +{ + // get the RTCP control object in order to get the ssrc + TAO_AV_RTCP_Object *rtcp_prot_obj = ACE_dynamic_cast (TAO_AV_RTCP_Object*, + this->protocol_object_); + ACE_UINT32 my_ssrc = rtcp_prot_obj->ssrc (); + + RTCP_Packet *cp; + RTCP_SDES_Packet sdes; + ACE_CString value = ""; + ACE_CString note = ""; + ACE_UINT16 sdes_type = 0; + RTCP_BYE_Packet *bye_packet = 0; // only used for bye + ACE_UINT32 ssrc_list[1]; // only used for bye + + // get an iterator for the incoming channels. + ACE_Hash_Map_Iterator iter (this->inputs_); + iter = this->inputs_.begin(); + + // first send an SR/RR + RR_Block *blocks = 0; + RR_Block *b_iter = 0; + RR_Block *b_ptr = 0; + + while (iter != this->inputs_.end() ) + { + if (!b_iter) + { + b_ptr = (*iter).int_id_->getRRBlock (); + if (b_ptr) + { + blocks = b_ptr; + b_iter = b_ptr; + } + } + else + { + b_ptr = (*iter).int_id_->getRRBlock (); + if (b_ptr) + { + b_iter->next_ = b_ptr; + } + } + + iter++; + } + + if (b_iter) + b_iter->next_ = 0; + + if (this->output_.active ()) + { + // get the NTP timestamp + ACE_Time_Value unix_now = ACE_OS::gettimeofday (); + TAO_AV_RTCP::ntp64 ntp_now = ntp64time (unix_now); + ACE_UINT32 rtp_ts = unix_now.sec () * 8000 + unix_now.usec () / 125 + + this->timestamp_offset_; + ACE_NEW_RETURN(cp, + RTCP_SR_Packet (my_ssrc, + ntp_now.upper, + ntp_now.lower, + rtp_ts, + this->output_.packets_sent (), + this->output_.octets_sent (), + blocks), + -1); + } + else + { + ACE_NEW_RETURN(cp, + RTCP_RR_Packet (my_ssrc, + blocks), + -1); + } + + /* + * We always send a cname plus one other sdes + * There's a schedule for what we send sequenced by sdes_seq_: + * - send 'email' every 0th & 4th packet + * - send 'note' every 2nd packet + * - send 'tool' every 6th packet + * - send 'name' in all the odd slots + * (if 'note' is not the empty string, we switch the roles + * of name & note) + */ + + // TODO: need capability to change these settings + switch (this->sdes_count_%8) + { + case 0: + case 4: + value = "tao-users@wustl.edu"; + sdes_type = RTCP_SDES_EMAIL; + break; + case 2: + if (note.length () > 0) + { + value = "Joe User"; + sdes_type = RTCP_SDES_NAME; + } + else + { + value = note; + sdes_type = RTCP_SDES_NOTE; + } + break; + case 6: + value = "TAO A/V Service"; + sdes_type = RTCP_SDES_TOOL; + break; + case 1: + case 3: + case 5: + case 7: + if (note.length () == 0) + { + value = "Joe User"; + sdes_type = RTCP_SDES_NAME; + } + else + { + value = "An important note..."; + sdes_type = RTCP_SDES_NOTE; + } + break; + } + + ++this->sdes_count_; + + sdes.add_item (my_ssrc, + RTCP_SDES_CNAME, + strlen(this->output_.cname()), + this->output_.cname()); + if (bye) + { + ssrc_list[0] = rtcp_prot_obj->ssrc (); + + ACE_NEW_RETURN (bye_packet, + RTCP_BYE_Packet(ssrc_list, + sizeof(ssrc_list)/sizeof(ssrc_list[0]), + "Got bored."), + -1); + } + else + sdes.add_item (my_ssrc, sdes_type, value.length (), value.c_str ()); + + // create the message block + char *cp_ptr; + char *sdes_ptr; + char *bye_ptr = 0; + ACE_UINT16 cp_length; + ACE_UINT16 sdes_length; + ACE_UINT16 bye_length = 0; + cp->get_packet_data (&cp_ptr, cp_length); + sdes.get_packet_data (&sdes_ptr, sdes_length); + if (bye_packet) + bye_packet->get_packet_data(&bye_ptr, bye_length); + + ACE_Message_Block mb (cp_length + sdes_length + bye_length); + + memcpy (mb.wr_ptr (), cp_ptr, cp_length); + mb.wr_ptr (cp_length); + memcpy (mb.wr_ptr (), sdes_ptr, sdes_length); + mb.wr_ptr (sdes_length); + if (bye_length) + { + memcpy (mb.wr_ptr (), bye_ptr, bye_length); + mb.wr_ptr (bye_length); + } + + // send the report + this->protocol_object_->send_frame (&mb); + + this->packet_size_ = cp_length + sdes_length + bye_length; + + delete cp; + if (bye_packet) + delete bye_packet; + return 0; } void +//TAO_AV_RTCP_Callback::get_timeout (ACE_Time_Value *tv, TAO_AV_RTCP_Callback::get_timeout (ACE_Time_Value *&tv, void *& /*arg*/) { + int senders = 0; + int members = 1; // count self as member + + // TODO: this should be 5% of the session bw + double rtcp_bw = 1000; + double interval; + + ACE_Hash_Map_Iterator iter (this->inputs_); + iter = this->inputs_.begin(); + + if (this->output_.active ()) + senders++; + + // determine the number of senders and members of this session + while (iter != this->inputs_.end ()) + { + if ((*iter).int_id_->active ()) + { + if ((*iter).int_id_->sender ()) + senders++; + members++; + } + iter++; + } + // Here we do the RTCP timeout calculation. + interval = TAO_AV_RTCP::rtcp_interval (members, // members + senders, // senders + rtcp_bw, // rtcp_bw + this->output_.active (), // we_sent + this->packet_size_, // packet_size + &this->avg_rtcp_size_, // avg_rtcp_size + this->is_initial_timeout_); // initial) + + this->is_initial_timeout_ = 0; + ACE_NEW (tv, - ACE_Time_Value (0,this->timeout_*ACE_ONE_SECOND_IN_MSECS)); + ACE_Time_Value); + + tv->sec ((int)interval); + tv->usec ((int)((interval - (int)interval) * 1000000)); } int TAO_AV_RTCP_Callback::handle_destroy (void) { - // Here we do the send_bye. - TAO_AV_RTCP::send_report (1, - this->protocol_object_, - this->source_manager_, - this->state_, - this); - return 0; + return this->send_report(1); } int @@ -823,122 +781,40 @@ TAO_AV_RTCP_Callback::receive_frame (ACE_Message_Block *frame, TAO_AV_frame_info *, const ACE_Addr &peer_address) { - char *buf = frame->rd_ptr (); - TAO_AV_RTP::rtphdr *rh = (TAO_AV_RTP::rtphdr *)buf; + RTCP_Channel_In *c; - frame->rd_ptr (sizeof (TAO_AV_RTP::rtphdr)); - int result = this->demux (rh, - frame, - peer_address); - frame->rd_ptr (buf); + RTP_Packet packet (frame->rd_ptr(), frame->length()); - if (result < 0) - return result; + if (this->inputs_.find (packet.ssrc(), c) < 0) + { + ACE_NEW_RETURN (c, + RTCP_Channel_In (packet.ssrc(), + &peer_address), + -1); + + this->inputs_.bind (packet.ssrc(), c); + } + c->recv_rtp_packet (frame, &peer_address); return 0; } - int -TAO_AV_RTCP_Callback::receive_control_frame (ACE_Message_Block *frame, - const ACE_Addr &peer_address) +TAO_AV_RTCP_Callback::send_frame (ACE_Message_Block *frame) { - // Here we do the processing of the RTCP frames. - TAO_AV_RTCP::rtcphdr header; - int result = TAO_AV_RTCP::handle_input (frame, - peer_address, - header, - this->source_manager_, - this->state_); - if (result < 0) - ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_RTCP::handle_input failed\n"),-1); + RTP_Packet packet (frame->rd_ptr(), frame->length()); + this->output_.updateStatistics (&packet); + return 0; } -int -TAO_AV_RTCP_Callback::demux (TAO_AV_RTP::rtphdr* rh, - ACE_Message_Block *data, - const ACE_Addr &address) +void +TAO_AV_RTCP_Callback::ts_offset (ACE_UINT32 offset) { - char *bp = data->rd_ptr (); - int cc = data->length (); - if (cc < 0) - { - ++this->state_->nrunt_; - return -1; - } - ACE_UINT32 srcid = rh->rh_ssrc; - int flags = ntohs (rh->rh_flags); - if ( (flags & RTP_X) != 0) - { - /* - * the minimal-control audio/video profile - * explicitly forbids extensions - */ - ++this->state_->badext_; - return -1; - } - - // @@Naga:Maybe the framework itself could check for formats making use of - // the property service to query the formats supported for this flow. - /* - * Check for illegal payload types. Most likely this is - * a session packet arriving on the data port. - */ -// int fmt = flags & 0x7f; -// if (!check_format (fmt)) -// { -// ++state->badfmt_; -// return; -// } - - u_long addr = address.hash (); - ACE_UINT16 seqno = ntohs (rh->rh_seqno); - TAO_AV_Source* s = this->source_manager_->demux (srcid, addr, seqno); - if (s == 0) - /* - * Takes a pair of validated packets before we will - * believe the source. This prevents a runaway - * allocation of Source data structures for a - * stream of garbage packets. - */ - return -1; - - ACE_Time_Value now = ACE_OS::gettimeofday (); - s->lts_data (now); - s->sts_data (rh->rh_ts); - - long cnt = (flags >> 8) & 0xf; - if (cnt > 0) - { - u_char* nh = (u_char*)rh + (cnt << 2); - while (--cnt >= 0) - { - ACE_UINT32 csrc = * (ACE_UINT32*)bp; - bp += 4; - TAO_AV_Source* cs = this->source_manager_->lookup (csrc, srcid, addr); - cs->lts_data (now); - cs->action (); - } - /*XXX move header up so it's contiguous with data*/ - TAO_AV_RTP::rtphdr hdr = *rh; - rh = (TAO_AV_RTP::rtphdr*)nh; - *rh = hdr; - } - else - s->action (); - - return 0; - /* - * This is a data packet. If the source needs activation, - * or the packet format has changed, deal with this. - * Then, hand the packet off to the packet handler. - * XXX might want to be careful about flip-flopping - * here when format changes due to misordered packets - * (easy solution -- keep rtp seqno of last fmt change). - */ + this->timestamp_offset_ = offset; } + ACE_FACTORY_DEFINE (TAO_AV, TAO_AV_RTCP_Flow_Factory) ACE_STATIC_SVC_DEFINE (TAO_AV_RTCP_Flow_Factory, ACE_TEXT ("RTCP_Flow_Factory"), @@ -949,4 +825,26 @@ ACE_STATIC_SVC_DEFINE (TAO_AV_RTCP_Flow_Factory, 0) +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +template class ACE_Hash_Map_Entry; +template class ACE_Hash_Map_Manager; +template class ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator; +template class ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator; +template class ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate ACE_Hash_Map_Entry +#pragma instantiate ACE_Hash_Map_Manager +#pragma instantiate ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator +#pragma instantiate ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP.h b/TAO/orbsvcs/orbsvcs/AV/RTCP.h index 8f8fba09a6c..aa54c808d6e 100644 --- a/TAO/orbsvcs/orbsvcs/AV/RTCP.h +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP.h @@ -50,41 +50,20 @@ // FUZZ: disable check_for_math_include #include "ace/OS.h" -#include "orbsvcs/AV/source.h" +#include "ace/Hash_Map_Manager.h" #include "orbsvcs/AV/AVStreams_i.h" #include "orbsvcs/AV/UDP.h" #include #include #include "orbsvcs/AV/RTP.h" -/** - * @class TAO_AV_RTP_State - * @brief Encapsulate the state of an RTP session - */ -class TAO_AV_Export TAO_AV_RTP_State -{ -public: - TAO_AV_RTP_State (void); - int bad_version_; - u_int badoptions_; - u_int badfmt_; - u_int badext_; - u_int nrunt_; - ACE_UINT32 last_np_; - ACE_UINT32 sdes_seq_; - double rtcp_inv_bw_; - double rtcp_avg_size_; /* (estimated) average size of rtcp packets */ - double rint_; /* current session report rate (in ms) */ - int confid_; - u_char* pktbuf_; -}; +#include "RTCP_Channel.h" class TAO_AV_RTCP_Callback; -class TAO_AV_SourceManager; /** * @class TAO_AV_RTCP - * @brief Encapsulate the header format for the Real Time Control + * @brief Encapsulate the header format for the Real Time Control * Protocol (RTCP) */ class TAO_AV_Export TAO_AV_RTCP @@ -101,143 +80,22 @@ public: { ACE_UINT32 upper; /* more significant 32 bits */ ACE_UINT32 lower; /* less significant 32 bits */ - }; - - /* - * Sender report. - */ - struct rtcp_sr { - ntp64 sr_ntp; /* 64-bit ntp timestamp */ - ACE_UINT32 sr_ts; /* reference media timestamp */ - ACE_UINT32 sr_np; /* no. packets sent */ - ACE_UINT32 sr_nb; /* no. bytes sent */ }; - /* - * Receiver report. - * Time stamps are middle 32-bits of ntp timestamp. - */ - struct rtcp_rr { - ACE_UINT32 rr_srcid; /* sender being reported */ - ACE_UINT32 rr_loss; /* loss stats (8:fraction, 24:cumulative)*/ - ACE_UINT32 rr_ehsr; /* ext. highest seqno received */ - ACE_UINT32 rr_dv; /* jitter (delay variance) */ - ACE_UINT32 rr_lsr; /* orig. ts from last rr from this src */ - ACE_UINT32 rr_dlsr; /* time from recpt of last rr to xmit time */ - }; - - static int handle_input (ACE_Message_Block *data, - const ACE_Addr &peer_address, - rtcphdr &header, - TAO_AV_SourceManager *source_manager, - TAO_AV_RTP_State *state); - - static int build_bye (rtcphdr* rh, - TAO_AV_Source& local); - - static int build_sdes (rtcphdr* rh, - TAO_AV_Source& s, - TAO_AV_RTP_State *state); - - static u_char* build_sdes_item (u_char* p, - int code, - TAO_AV_Source&); - - static void parse_sr (rtcphdr* rh, - int flags, - u_char* ep, - TAO_AV_Source* ps, - ACE_UINT32 addr, - TAO_AV_SourceManager *source_manager); - - static void parse_rr (rtcphdr* rh, - int flags, - u_char* ep, - TAO_AV_Source* ps, - ACE_UINT32 addr, - TAO_AV_SourceManager *source_manager); - - static void parse_rr_records (ACE_UINT32 ssrc, - rtcp_rr* r, - int cnt, - const u_char* ep, - ACE_UINT32 addr); - - static int sdesbody (ACE_UINT32* p, - u_char* ep, - TAO_AV_Source* ps, - ACE_UINT32 addr, - ACE_UINT32 ssrc, - TAO_AV_SourceManager *source_manager); - - static void parse_sdes (rtcphdr* rh, - int flags, - u_char* ep, - TAO_AV_Source* ps, - ACE_UINT32 addr, - ACE_UINT32 ssrc, - TAO_AV_SourceManager *source_manager); - - static void parse_bye (rtcphdr* rh, - int flags, - u_char* ep, - TAO_AV_Source* ps, - TAO_AV_SourceManager *source_manager); - - static void send_report (int bye, - TAO_AV_Protocol_Object *object, - TAO_AV_SourceManager *source_manager, - TAO_AV_RTP_State *state, - TAO_AV_RTCP_Callback *callback); + static void send_report (ACE_Message_Block *mb); static ACE_UINT32 alloc_srcid (ACE_UINT32 addr); - static double fmod (double dividend, double divisor); + static double rtcp_interval (int members, + int senders, + double rtcp_bw, + int we_sent, + int packet_size, + int *avg_rtcp_size, + int initial); }; -class TAO_AV_Callback; - -/** - * @class TAO_AV_RTCP_Object - * @brief TAO_AV_Protocol_Object for RTCP protocol - */ -class TAO_AV_Export TAO_AV_RTCP_Object - : public TAO_AV_Protocol_Object -{ -public: - /// constructor. - TAO_AV_RTCP_Object (TAO_AV_Callback *callback, - TAO_AV_Transport *transport = 0); - - /// Destructor - virtual ~TAO_AV_RTCP_Object (void); - - virtual int handle_input (void); - virtual int handle_control_input (ACE_Message_Block *frame, - const ACE_Addr &peer_address); - - /// set/get policies. - virtual int set_policies (const TAO_AV_PolicyList &policy_list); - - /// start/stop the flow. - virtual int start (void); - virtual int stop (void); - - /// send a data frame. - virtual int send_frame (ACE_Message_Block *frame, - TAO_AV_frame_info *frame_info = 0); - - /// send a frame in iovecs. - virtual int send_frame (const iovec *iov, - int iovcnt, - TAO_AV_frame_info *frame_info = 0); - virtual int send_frame (const char*buf, - size_t len); - - /// end the stream. - virtual int destroy (void); -}; /** * @class TAO_AV_Flow_Protocol_Factory @@ -257,6 +115,9 @@ public: TAO_AV_Transport *transport); }; +class TAO_AV_Callback; + + /** * @class TAO_AV_RTCP_Callback * @brief TAO_AV_Callback for RTCP protocol @@ -283,6 +144,7 @@ public: virtual int receive_frame (ACE_Message_Block *frame, TAO_AV_frame_info *frame_info = 0, const ACE_Addr &peer_address = ACE_Addr::sap_any); + int send_frame (ACE_Message_Block *frame); virtual int receive_control_frame (ACE_Message_Block *frame, const ACE_Addr &peer_address = ACE_Addr::sap_any); @@ -296,23 +158,83 @@ public: virtual void get_timeout (ACE_Time_Value *&tv, void *&arg); - int demux (TAO_AV_RTP::rtphdr* rh, - ACE_Message_Block *data, - const ACE_Addr &peer_address); - - virtual int get_rtp_source (TAO_AV_Source *&source, - ACE_UINT32 srcid, - ACE_UINT32 ssrc, - ACE_UINT32 addr); + int send_report(int bye); void schedule (int ms); - TAO_AV_SourceManager *source_manager (void); TAO_AV_RTP_State *state (void); + void ts_offset (ACE_UINT32 offset); + protected: - TAO_AV_SourceManager *source_manager_; - TAO_AV_RTP_State *state_; + ACE_Hash_Map_Manager inputs_; + RTCP_Channel_Out output_; int timeout_; + int timestamp_offset_; + int sdes_count_; + + int is_initial_timeout_; + int avg_rtcp_size_; + int packet_size_; +}; + +class RTP_Packet; + + +/** + * @class TAO_AV_RTCP_Object + * @brief TAO_AV_Protocol_Object for RTCP protocol + */ +class TAO_AV_Export TAO_AV_RTCP_Object + : public TAO_AV_Protocol_Object +{ +public: + /// constructor. + TAO_AV_RTCP_Object (TAO_AV_Callback *client_cb, + TAO_AV_RTCP_Callback *&rtcp_cb, + TAO_AV_Transport *transport = 0); + + /// Destructor + virtual ~TAO_AV_RTCP_Object (void); + + virtual int handle_input (void); + virtual int handle_control_input (ACE_Message_Block *frame, + const ACE_Addr &peer_address); + virtual int handle_control_output (ACE_Message_Block *frame); + + /// set/get policies. + virtual int set_policies (const TAO_AV_PolicyList &policy_list); + + /// start/stop the flow. + virtual int start (void); + virtual int stop (void); + + /// send a data frame. + virtual int send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0); + + /// send a frame in iovecs. + virtual int send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info = 0); + + virtual int send_frame (const char*buf, + size_t len); + + /// end the stream. + virtual int destroy (void); + + void ssrc (ACE_UINT32 ssrc) {this->ssrc_ = ssrc; } + ACE_UINT32 ssrc (void) { return this->ssrc_; } + + void ts_offset (ACE_UINT32 ts_offset); + + +private: + TAO_AV_Callback *client_cb_; + TAO_AV_RTCP_Callback rtcp_cb_; + ACE_UINT32 ssrc_; }; + + ACE_STATIC_SVC_DECLARE (TAO_AV_RTCP_Flow_Factory) ACE_FACTORY_DECLARE (TAO_AV, TAO_AV_RTCP_Flow_Factory) diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp b/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp new file mode 100644 index 00000000000..9aaebbdf2d9 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp @@ -0,0 +1,361 @@ +// $Id$ +#include "ace/OS.h" + +#include "RTCP_Channel.h" +#include "RTP.h" + +RTCP_Channel_In::RTCP_Channel_In (ACE_UINT32 ssrc, + const ACE_Addr *peer_addr) + : remote_ssrc_ (ssrc), + cname_ (""), + transit_ (0), + jitter_ (0.0), + first_data_packet_ (1), + ntp_ts_msw_ (0), + ntp_ts_lsw_ (0), + last_sr_time_ (0), + active_ (0), + no_data_counter_ (0), + data_since_last_report_ (0) +{ + const ACE_INET_Addr *const_inet_addr = ACE_dynamic_cast (const ACE_INET_Addr*, + peer_addr); + + ACE_INET_Addr *inet_addr; + ACE_NEW (inet_addr, + ACE_INET_Addr (*const_inet_addr)); + + this->peer_address_ = inet_addr; +} + +RTCP_Channel_In::~RTCP_Channel_In(void) +{ + delete this->peer_address_; +} + +void +RTCP_Channel_In::updateStatistics(RTP_Packet* dataPkt) +{ + ACE_Time_Value current_time; + ACE_UINT32 arrival; + int transit, d; + + this->active_ = 0; + + // determine if the source has been declared valid + if (update_seq(dataPkt->sn ()) == 0) + return; + + // Set initial values if this is the first data packet. + if (this->first_data_packet_) + { + // store the initial timestamp + this->init_time_stamp_ = dataPkt->ts (); + this->init_local_time_ = ACE_OS::gettimeofday (); + this->first_data_packet_ = 0; + } + + // Get the current time. + current_time = ACE_OS::gettimeofday (); + + unsigned int samples_per_sec; + double samples_per_usec; + + + switch (dataPkt->pt()) + { + case RTP_PT_PCMU: + case RTP_PT_CELP: + case RTP_PT_G721: + case RTP_PT_GSM: + case RTP_PT_DVI: + case RTP_PT_LPC: + case RTP_PT_PCMA: + case RTP_PT_G722: + samples_per_sec = 8000; + break; + case RTP_PT_L16_STEREO: + case RTP_PT_L16_MONO: + samples_per_sec = 44100; + break; + default: + samples_per_sec = 1000000; + }; + + samples_per_usec = samples_per_sec/1000000.0; + + // Calculate the current timestamp. + arrival = (ACE_UINT32)((current_time.sec () - + this->init_local_time_.sec ()) * samples_per_sec + + ((double)(current_time.usec () - + (double)this->init_local_time_.usec ()) * samples_per_usec) + + this->init_time_stamp_); + + + // jitter calc from RFC 1889 app a.8 + transit = arrival - dataPkt->ts (); + d = transit - this->transit_; + this->transit_ = transit; + if (d < 0) + d = -d; + + // Calculate the inter-arrival jitter. + this->jitter_ += (1./16.)*((double)d - this->jitter_); + + // Indicate that data has been received since the last report. + this->data_since_last_report_ = 1; + + // Store the payload type. + this->payload_type_ = dataPkt->pt (); +} + +int +RTCP_Channel_In::updateStatistics(RTCP_SR_Packet *sr) +{ + // calculate the last SR time in 1/65536 sec. + ACE_Time_Value now = ACE_OS::gettimeofday (); + this->last_sr_time_ = (ACE_UINT32) + (now.sec () * 65536 + + now.usec () * 0.065536); + + this->ntp_ts_msw_ = sr->ntp_ts_msw (); + this->ntp_ts_lsw_ = sr->ntp_ts_lsw (); + + return 0; +} + +int +RTCP_Channel_In::updateStatistics(RTCP_RR_Packet */*rr*/) +{ + return 0; +} + +void +RTCP_Channel_In::init_seq(ACE_UINT16 seq) +{ + this->base_seq_ = seq - 1; + this->max_seq_ = seq; + this->bad_seq_ = RTP_SEQ_MOD + 1; + this->cycles_ = 0; + this->received_ = 0; + this->received_prior_ = 0; + this->expected_prior_ = 0; +} + +int +RTCP_Channel_In::update_seq(ACE_UINT16 seq) +{ + // The following is taken from RFC 1889 Appendix A.1 + ACE_UINT16 udelta = seq - this->max_seq_; + const int MAX_DROPOUT = 3000; + const int MAX_MISORDER = 100; + const int MIN_SEQUENTIAL = 2; + + // Source is not valid until MIN_SEQUENTIAL packets with + // sequential sequence numbers have been received. + if (this->probation_) + { + // packet is in sequence + if (seq == this->max_seq_ + (ACE_UINT16)1) + { + this->probation_ --; + this->max_seq_ = seq; + if (this->probation_ == 0) + { + this->init_seq(seq); + this->received_++; + return 1; + } + } + else + { + this->probation_ = MIN_SEQUENTIAL - 1; + this->max_seq_ = seq; + } + return 0; + } + else if (udelta < MAX_DROPOUT) + { + // in order, with permissible gap + if (seq < this->max_seq_) + { + // seq number wrapped - count another 64k cycle + this->cycles_+=RTP_SEQ_MOD; + } + this->max_seq_ = seq; + } + else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) + { + // the sequence number made a large jump + ACE_UINT32 temp = seq; // Borland reports a warning on the next line + // without this line. + if (temp == this->bad_seq_) + { + // two sequential packets, assume the other side restarted without + // telling us so just re-sync + // (i.e., pretend this was the first packet). + this->init_seq (seq); + + ACE_DEBUG ((LM_DEBUG, + "RTCP_Channel_In: large jump in sequence number", + "; init seq\n")); + } + else + { + this->bad_seq_ = (seq+1)&(RTP_SEQ_MOD-1); + return 0; + } + } + else + { + // dup or reordered packet + } + this->received_++; + + return 1; +} + +void +RTCP_Channel_In::recv_rtp_packet(ACE_Message_Block *mb, + const ACE_Addr *peer_address) +{ + if (*peer_address != *this->peer_address_) + ACE_DEBUG ((LM_DEBUG, + "RTCP_Channel_In::recv_rtp_packet - possible loop/collision detected")); + + RTP_Packet data_packet(mb->rd_ptr (), mb->length ()); + + // make sure the packet is valid + if (data_packet.is_valid ()) + this->updateStatistics(&data_packet); + else + ACE_DEBUG ((LM_DEBUG, + "RTCP_Channel_In::recvDataPacket - invalid RTP packet\n")); +} + + +RR_Block * +RTCP_Channel_In::getRRBlock(void) +{ + // If no data has been received since the last report, don't create a block. + if (!this->data_since_last_report_) + { + this->no_data_counter_++; + + // make the source inactive if significant time has passed since last report + if (this->no_data_counter_ == 32) + this->active_ = 0; + + return 0; + } + + this->no_data_counter_ = 0; + + RR_Block *local_block_ptr = 0; + + ACE_NEW_RETURN (local_block_ptr, + RR_Block, + 0); + + ACE_OS::memset(local_block_ptr, 0, sizeof(RR_Block)); + + // Set the ssrc of the source this report is for. + local_block_ptr->ssrc_ = this->remote_ssrc_; + + // Calculate packets expected/lost (from RFC 1889 Appendix A.3) + ACE_UINT32 extended_max; + ACE_UINT32 expected; + ACE_UINT32 expected_interval; + ACE_UINT32 received_interval; + int lost_interval; + + extended_max = this->cycles_ + this->max_seq_; + expected = extended_max - this->base_seq_ + 1; + + local_block_ptr->lost_ = expected - this->received_; + expected_interval = expected - this->expected_prior_; + this->expected_prior_ = expected; + received_interval = this->received_ - this->received_prior_; + this->received_prior_ = this->received_; + lost_interval = expected_interval - received_interval; + + if ((expected_interval == 0) || (lost_interval <= 0)) + local_block_ptr->fraction_ = 0; + else + local_block_ptr->fraction_ = (lost_interval << 8) / expected_interval; + + + local_block_ptr->last_seq_ = extended_max; + + // taken from RFC 1889 App A.8 + local_block_ptr->jitter_ = (ACE_UINT32)this->jitter_; + + // calculate the last SR timestamp (lsr) + local_block_ptr->lsr_ = ((this->ntp_ts_msw_ & 0xFFFF) << 16) | + ((this->ntp_ts_lsw_ & 0xFFFF0000) >> 16); + + // calculate the delay since last SR (dlsr) + ACE_Time_Value now = ACE_OS::gettimeofday (); + ACE_UINT32 now32 = (ACE_UINT32) + (now.sec () * 65536 + + now.usec () * 0.065536); + + local_block_ptr->dlsr_ = now32 - this->last_sr_time_; + + // indicate that no data has been received since the last report + this->data_since_last_report_ = 0; + + return local_block_ptr; +} + +RTCP_Channel_Out::RTCP_Channel_Out(void) + :cname_ ("cname"), + active_ (0), + timestamp_ (0), + timestamp_offset_ (0), + packets_sent_ (0), + octets_sent_ (0) +{ +} + +RTCP_Channel_Out::~RTCP_Channel_Out(void) +{ +} + +void +RTCP_Channel_Out::updateStatistics (RTP_Packet *data_packet) +{ + // indicate that this source is active + this->active_ = 1; + + // Update various counters. + this->octets_sent_ += data_packet->payload_size(); + this->packets_sent_ ++; + this->seq_num_ = data_packet->sn (); + this->timestamp_ = data_packet->ts (); +} + +ACE_UINT32 +RTCP_Channel_Out::timestamp (void) +{ + return this->timestamp_; +} + +ACE_UINT32 +RTCP_Channel_Out::packets_sent (void) +{ + return this->packets_sent_; +} + +ACE_UINT32 +RTCP_Channel_Out::octets_sent (void) +{ + return this->octets_sent_; +} + +char +RTCP_Channel_Out::active (void) +{ + return this->active_; +} + diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.h b/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.h new file mode 100644 index 00000000000..66a63372f0f --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.h @@ -0,0 +1,217 @@ +// $Id$ + +#ifndef RTCP_CHANNEL_INCLUDE +#define RTCP_CHANNEL_INCLUDE + +#include "ace/OS.h" +#include "ace/Message_Block.h" +#include "ace/SString.h" + +#include "RTP.h" +#include "RTCP_Packet.h" + +/** + * @class RTCP_Channel_In + * @brief The RTCP_Channel_In class represents a single incoming data channel, + * or stream. The class has several responsibilities. When the class is + * instantiated, the incoming RTP traffic must be declared a valid source based + * on the RTP packets received. Once declared valie, this class is responsible + * for keeping up with reception statistics and other information. When an SR + * or RR is created (outside of this class), this class is used to get the + * Receiver Report block for this particular stream. + */ + +class RTCP_Channel_In +{ +public: + /// Constructor for an incoming channel. Requires the synchronization source + /// id and address of the sender. + RTCP_Channel_In(ACE_UINT32 ssrc, + const ACE_Addr *addr); + + /// Destructor + ~RTCP_Channel_In(void); + + /// This operation takes the incoming ACE_Message_Block, converts it to an + /// RTP_Packet and calls updateStatistics. It also uses compares the peer_addr + /// to the stored peer_address_ to check for loops. + void recv_rtp_packet (ACE_Message_Block *mb, + const ACE_Addr *peer_addr); + + /// Takes statistics of incoming RTP traffic and creates a receiver report block. + RR_Block *getRRBlock(void); + + /// Returns the delay since last sender report. + ACE_UINT32 dlsr (void); + + /// Returns the last sender report timestamp. + ACE_UINT32 lsr (void); + + /// Updates channel information with incoming sender report. + int updateStatistics(RTCP_SR_Packet *sr); + + /// Updates channel information with incoming receiver report. + int updateStatistics(RTCP_RR_Packet *rr); + + /// Returns 1 if data has been sent since the last report, 0 if not. + int sender (void) { return this->data_since_last_report_; } + + /// Returns 1 if this is an active source, 0 if not. + int active (void) { return this->active_; } + +private: + /// Don't want default constructor. + RTCP_Channel_In(void); + + /// Don't want copy constructor. + RTCP_Channel_In(const RTCP_Channel_In &ch); + + /// The synchronization source id of the source this channel represents. + ACE_UINT32 remote_ssrc_; + + /// The canonical name of the source this channel represents. + ACE_CString cname_; + + // Used to declare a source valid + /// The highest sequence number seen. + ACE_UINT16 max_seq_; + + /// The shifted count of sequence number cycles (ie when sequence number wraps) + ACE_UINT32 cycles_; + + /// The first sequence number received. + ACE_UINT32 base_seq_; + + /// last 'bad' sequence number + 1 + ACE_UINT32 bad_seq_; + + /// The number of in sequence packets until a source is declared valid. + ACE_UINT32 probation_; + + /// The number of packets received. + ACE_UINT32 received_; + + /// The packet expected at last interval. + ACE_UINT32 expected_prior_; + + /// The packet received at last interval. + ACE_UINT32 received_prior_; + + /// The last transit time. + ACE_UINT32 transit_; + + /// The inter-arrival jitter measured in timestamp units. + double jitter_; + + // Used for jitter calculations + /// Flag to indicate the first data packet received. + char first_data_packet_; + + /// The first timestamp received. + ACE_UINT32 init_time_stamp_; + + /// The local time that the initial packet was received. + ACE_Time_Value init_local_time_; + + /// The address that the first RTP packet was received from. + ACE_Addr *peer_address_; + + /// The most significant word of the last sender report NTP timestamp. + ACE_UINT32 ntp_ts_msw_; + + /// The least significant word of the last sender report NTP timestamp. + ACE_UINT32 ntp_ts_lsw_; + + /// The last sender report RTP timestamp. + ACE_UINT32 rtp_ts_; + + /// The last time a sender report was received in 1/65536 seconds. + /// Used to calculate DLSR. + ACE_UINT32 last_sr_time_; + + /// Flag to indicate whether or not the source is active. + int active_; + + /// This is a counter to indicate the number of reporting intervals that have + /// passed since data has been received. After 32, declare the source inactive. + int no_data_counter_; + + /// This flag indicates that data has been received since the last report was + /// sent. + char data_since_last_report_; + + /// The RTP payload type. + int payload_type_; + + /// This operation is used update statistics for the incoming RTP packet. + void updateStatistics(RTP_Packet *pkt); + + /// This is called when the first RTP packet is received. + void init_seq(ACE_UINT16 seq); + + /// This is called when each RTP packet is received. It is used to declare + /// a source as valid. + int update_seq(ACE_UINT16 seq); +}; + +/** + * @class RTCP_Channel_Out + * @brief The RTCP_Channel_Out class represents a single outgoing data channel, + * or stream. It keeps track of statistics such as number of packets sent and + * number of bytes sent. + */ + +class RTCP_Channel_Out +{ +public: + /// Constructor. + RTCP_Channel_Out(void); + + /// Destructor. + ~RTCP_Channel_Out(void); + + /// Update the channel statistics each time an RTP packet is sent. + void updateStatistics (RTP_Packet *pkt); + + /// Returns the timestamp of the last RTP packet sent. + ACE_UINT32 timestamp (void); + + /// Returns the number of packets sent. + ACE_UINT32 packets_sent (void); + + /// Returns the number of octets sent. + ACE_UINT32 octets_sent (void); + + /// Sets the canonical name of the source. + void cname (const char *cname) { this->cname_ = cname; } + + /// Returns the canonical name of the source. + const char *cname (void) { return this->cname_.c_str(); } + + /// Returns whether or not this source is active. + char active (void); + +private: + /// Holds the canonical name for this channel. + ACE_CString cname_; + + /// Flag to indicate whether or not this channel is active. + char active_; + + /// The sequence number of the last RTP packet sent. + unsigned int seq_num_; + + /// The timestamp of the last RTP packet sent. + unsigned int timestamp_; + + /// The initial offset of the timestamp. + unsigned int timestamp_offset_; + + /// The total number of packets sent. + unsigned int packets_sent_; + + /// The total numbef of octets sent. + unsigned int octets_sent_; +}; + +#endif diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.cpp b/TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.cpp new file mode 100644 index 00000000000..0d1d802ff73 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.cpp @@ -0,0 +1,1194 @@ +// $Id$ +#include "RTCP_Packet.h" +#include "RTP.h" + +RTCP_Packet::RTCP_Packet(void) +{ + this->chd_.ver_ = 2; + this->chd_.count_ = 0; + this->chd_.pad_ = 0; + this->chd_.length_ = 0; + this->packet_data_ = 0; +} + +RTCP_Packet::RTCP_Packet(char* buffer) +{ + // Parse the common part of the control packet header. + this->chd_.ver_ = (buffer[0] & 0xC0) >> 6; + + if (this->chd_.ver_ != RTP_VERSION) + ACE_DEBUG ((LM_DEBUG, + "RTCP_Packet::RTCP_Packet version incorrect")); + + this->chd_.pad_ = (buffer[0] & 0x20) >> 5; + this->chd_.count_ = buffer[0] & 0x1F; + this->chd_.pt_ = buffer[1]; + this->chd_.length_ = ntohs(*(ACE_UINT16*)&buffer[2]); + this->packet_data_ = 0; +} + +RTCP_Packet::~RTCP_Packet(void) +{ +} + +void +RTCP_Packet::get_packet_data(char **buffer, ACE_UINT16 &length) +{ + length = this->packet_size(); + + // buiidPacket is defined for each child of RTCP_Packet + // buildPacket creates a snapshot of the RTCP packet in the buffer pktData + this->build_packet (); + + *buffer = this->packet_data_; +} + +int +RTCP_Packet::is_valid (char is_first) +{ + // make sure the RTP version is correct + if (this->chd_.ver_ != RTP_VERSION) + return 0; + + // these checks are only for the first RTCP packet in a compound packet + if (is_first) + { + // the payload type must be RR or SR + if ((this->chd_.pt_ != RTCP_PT_SR) && (this->chd_.pt_ != RTCP_PT_RR)) + return 0; + + // the padding bit must not be set + if (this->chd_.pad_ != 0) + return 0; + } + + return 1; + +} + +/* + * RTCP_BYE_Packet + */ + +RTCP_BYE_Packet::RTCP_BYE_Packet(ACE_UINT32 *ssrc_list, + unsigned char length, + const char *text) +{ + this->chd_.ver_ = 2; + this->chd_.count_ = length; + this->chd_.pt_ = RTCP_PT_BYE; + + if (length) + { + ACE_NEW (this->ssrc_list_, + ACE_UINT32[length]); + + this->ssrc_list_length_ = length; + + for (int i=0; issrc_list_[i] = ssrc_list[i]; + } + + // Optional - if there is a reason for leaving, store it. + // The reason is padded with extra zeros because the packet must + // end on an even 32-bit boundary. + memset(this->reason_, 0, sizeof(this->reason_)); + if (text) + { + int text_length = ACE_OS::strlen(text); + memcpy(this->reason_, text, text_length); + this->reason_length_ = text_length; + } + else + this->reason_length_ = 0; + + // Set the packet length + this->chd_.length_ = this->chd_.count_ + (this->reason_length_+1)/4; + if ((this->reason_length_+1)%4) + this->chd_.length_++; + + this->packet_data_ = 0; +} + +//============================================================================== + +RTCP_BYE_Packet::RTCP_BYE_Packet(char* buffer, int *len) + : RTCP_Packet(buffer) +{ + unsigned int index = 0; + unsigned int j; + + // The common part of the header is initialized in the parent. + index=4; + + ACE_NEW (this->ssrc_list_, + ACE_UINT32[this->chd_.count_]); + this->ssrc_list_length_ = this->chd_.count_; + + // Store the source ids of the sources leaving the session + for (j=0; jchd_.count_; j++) + { + this->ssrc_list_[j] = ntohl(*(ACE_UINT32*)&buffer[index]); + index+=4; + } + + // Optional - store the reason for leaving + unsigned int temp = this->chd_.length_; // Borland reports a warning on the + // following line with out this. + memset(this->reason_, 0, sizeof(this->reason_)); + if (temp > this->chd_.count_) + { + this->reason_length_ = buffer[index]; + index++; + memcpy(this->reason_, &buffer[index], this->reason_length_); + index+=this->reason_length_; + + } + else + this->reason_length_ = 0; + + // Decrement the length by the size of this message. This is necessary + // because multiple RTCP packets may be contained in a single UDP packet. + *len-=(chd_.length_+1)*4; + + this->packet_data_ = 0; +} + +//============================================================================== + +RTCP_BYE_Packet::~RTCP_BYE_Packet(void) +{ + if (this->ssrc_list_) + delete []this->ssrc_list_; + if (this->packet_data_) + delete []this->packet_data_; +} + +//============================================================================== + +unsigned int +RTCP_BYE_Packet::packet_size(void) +{ + ACE_UINT16 size = (1+chd_.count_) * 4; + + if (this->reason_length_ > 0) + { + size += this->reason_length_ + 1; + if (size%4) + size += 4 - size%4; // pad with zeros to even 32 bit bound + } + + return size; +} + +//============================================================================== + +void +RTCP_BYE_Packet::ssrc_list(ACE_UINT32 **ssrc_list, unsigned char &length) +{ + *ssrc_list = this->ssrc_list_; + length = this->ssrc_list_length_; +} + +//============================================================================== + +const char * +RTCP_BYE_Packet::reason (void) +{ + ACE_CString reason = (const char *)this->reason_; + + return reason.c_str(); +} + +//============================================================================== + +void +RTCP_BYE_Packet::build_packet(void) +{ + unsigned int index; + unsigned int i; + + if (this->packet_data_) + delete []this->packet_data_; + + ACE_NEW (this->packet_data_, + char[this->packet_size()]); + + index = 0; + this->packet_data_[index] = (this->chd_.ver_ << 6) | + (this->chd_.pad_ << 5) | + this->chd_.count_; + index++; + this->packet_data_[index] = this->chd_.pt_; + index++; + *((ACE_UINT16*)&this->packet_data_[index]) = htons(this->chd_.length_); + index+=2; + + for (i=0; ichd_.count_; i++) + { + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->ssrc_list_[i]); + index+=4; + } + + if (this->reason_) + { + this->packet_data_[index] = this->reason_length_; + index++; + memcpy(&this->packet_data_[index], this->reason_, this->reason_length_); + index += this->reason_length_; + while (index < this->packet_size()) + { + this->packet_data_[index] = 0; + index ++; + } + } +} + +void +RTCP_BYE_Packet::dump (void) +{ + ACE_DEBUG ((LM_DEBUG, + "\nRTCP_BYE_Packet:: from ssrc(s) ")); + for (int i=0; i< this->ssrc_list_length_; i++) + ACE_DEBUG ((LM_DEBUG, + "%u ", + this->ssrc_list_[i])); + ACE_DEBUG ((LM_DEBUG, + "\n Reason '%s'\n", + this->reason_)); +} + +RTCP_RR_Packet::RTCP_RR_Packet(ACE_UINT32 ssrc, RR_Block *blocks) +{ + RR_Block *block_ptr = blocks; + + this->chd_.count_ = 0; + this->chd_.ver_ = 2; + this->chd_.pt_ = RTCP_PT_RR; + this->ssrc_ = ssrc; + this->rr_ = blocks; + + while (block_ptr) + { + this->chd_.count_++; + + // Can only have 31 receiver reports + if (this->chd_.count_ == 31) + { + block_ptr->next_ = 0; + break; + } + + block_ptr = block_ptr->next_; + } + + this->chd_.length_ = 1+6*this->chd_.count_; // + profile specific extensions ?? + + this->packet_data_ = 0; +} + +//============================================================================== + +RTCP_RR_Packet::RTCP_RR_Packet (char* buffer, + int *len) + :RTCP_Packet (buffer) +{ + unsigned int i = 0; + RR_Block *local_block_ptr; + + this->rr_ = 0; + + // The common part of the header is initialized in the parent. + i=4; + this->ssrc_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + for (unsigned int j=0; jchd_.count_; j++) + { + if (j==0) + { + ACE_NEW (this->rr_, + RR_Block); + local_block_ptr = this->rr_; + } + else + { + ACE_NEW (local_block_ptr->next_, + RR_Block); + local_block_ptr = local_block_ptr->next_; + } + + local_block_ptr->next_ = 0; + local_block_ptr->ssrc_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + ACE_UINT32 temp = ntohl(*(ACE_UINT32*)&buffer[i]); + local_block_ptr->fraction_ = (temp&0xff000000) >> 24; + local_block_ptr->lost_ = temp & 0x00ffffff; + i+=4; + local_block_ptr->last_seq_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + local_block_ptr->jitter_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + local_block_ptr->lsr_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + local_block_ptr->dlsr_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + } + + *len-=(this->chd_.length_+1)*4; + + this->packet_data_ = 0; +} + +//============================================================================== + +RTCP_RR_Packet::~RTCP_RR_Packet(void) +{ + RR_Block *prev; + + if (this->rr_) + { + while (this->rr_) + { + prev = this->rr_; + this->rr_ = this->rr_->next_; + delete prev; + } + } + + if (this->packet_data_) + delete []this->packet_data_; +} + +//============================================================================== + +unsigned int +RTCP_RR_Packet::packet_size(void) +{ + ACE_UINT16 size = (2+this->chd_.count_*6) * 4; + return size; +} + +//============================================================================== + +void +RTCP_RR_Packet::build_packet(void) +{ + int index; + RR_Block *local_block_ptr; + + if (this->packet_data_) + delete []this->packet_data_; + + ACE_NEW (this->packet_data_, + char [this->packet_size ()]); + + index = 0; + this->packet_data_[index] = (this->chd_.ver_ << 6) | + (this->chd_.pad_ << 5) | + this->chd_.count_; + index++; + this->packet_data_[index] = chd_.pt_; + index++; + *((ACE_UINT16*)&this->packet_data_[index]) = htons(chd_.length_); + index+=2; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->ssrc_); + index+=4; + + local_block_ptr = this->rr_; + while (local_block_ptr) + { + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->ssrc_); + index+=4; + ACE_UINT32 temp = htonl((local_block_ptr->fraction_&0xff) << 24) & + local_block_ptr->lost_; + *((ACE_UINT32*)&this->packet_data_[index]) = temp; + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->last_seq_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->jitter_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->lsr_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->dlsr_); + index+=4; + local_block_ptr = local_block_ptr->next_; + } +} + +void +RTCP_RR_Packet::dump (void) +{ + RR_Block *b = this->rr_; + int count = 1; + + ACE_DEBUG ((LM_DEBUG, + "\nRTCP_RR_Packet:: from %u - %d rr blocks follow.\n", + this->ssrc_, + this->chd_.count_)); + + while (b) + { + ACE_DEBUG ((LM_DEBUG, + " Block %d: ssrc %u; frac %u; lost %u; last seq %u\n", + count, + b->ssrc_, + b->fraction_, + b->lost_, + b->last_seq_)); + ACE_DEBUG ((LM_DEBUG, + " jitter %u; lsr %u; dlsr %u;\n", + b->jitter_, + b->lsr_, + b->dlsr_)); + + b = b->next_; + ++count; + } +} + + +RTCP_SDES_Packet::RTCP_SDES_Packet(void) : + RTCP_Packet () +{ + this->chd_.pt_ = RTCP_PT_SDES; + this->chunk_ = 0; + this->packet_data_ = 0; + this->num_chunks_ = 0; +// this->num_items_ = 0; +} + +//============================================================================== + +RTCP_SDES_Packet::RTCP_SDES_Packet(char* buffer, int *len): + RTCP_Packet (buffer) +{ + unsigned int i; + sdesChunk_t *cp; // pointer to chunk + sdesItem_t *ip; // pointer to item + + // The common part of the control packet header is processed + // in the parent. It is 4 bytes long. + + i=4; + for (unsigned int j=0; jchd_.count_; j++) + { + if (j==0) + { + ACE_NEW (this->chunk_, + sdesChunk_t); + cp = this->chunk_; + + this->num_chunks_ = 1; + } + else + { + ACE_NEW (cp->next_, + sdesChunk_t); + cp = cp->next_; + + this->num_chunks_++; + } + cp->next_ = 0; + cp->item_ = 0; + cp->ssrc_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + + while (buffer[i]!=RTCP_SDES_END) + { + if (!cp->item_) + { + ACE_NEW (cp->item_, + sdesItem_t); + ip = cp->item_; + +// this->num_items_ = 1; + } + else + { + ACE_NEW (ip->next_, + sdesItem_t); + ip = ip->next_; + +// this->num_items_++; + } + ip->next_ = 0; + ip->type_ = buffer[i]; + i++; + if (ip->type_ != RTCP_SDES_PRIV) + { + ip->info_.standard_.length_ = buffer[i]; + i++; + ACE_NEW (ip->info_.standard_.data_, + char[ip->info_.standard_.length_+1]); + memcpy(ip->info_.standard_.data_, + &buffer[i], + ip->info_.standard_.length_); + ip->info_.standard_.data_[ip->info_.standard_.length_] = 0; + i+=ip->info_.standard_.length_; + } + else + { + ip->info_.priv_.name_length_ = buffer[i]; + i++; + ip->info_.priv_.data_length_ = buffer[i]; + i++; + ACE_NEW (ip->info_.priv_.name_, + char[ip->info_.priv_.name_length_+1]); + memcpy(ip->info_.priv_.name_, + &buffer[i], + ip->info_.priv_.name_length_); + ip->info_.priv_.name_[ip->info_.priv_.name_length_] = 0; + i+=ip->info_.priv_.name_length_; + ACE_NEW (ip->info_.priv_.data_, + char[ip->info_.priv_.data_length_+1]); + memcpy(ip->info_.priv_.data_, + &buffer[i], + ip->info_.priv_.data_length_); + ip->info_.priv_.data_[ip->info_.priv_.data_length_] = 0; + i+=ip->info_.priv_.data_length_; + } + } + i++; // each chunk ends with a zero (END) item + // each chunk must end on an even 32 bit boundary + while (i%4) i++; + } + + *len-=(this->chd_.length_+1)*4; + + this->packet_data_ = 0; +} + +//============================================================================== + +RTCP_SDES_Packet::~RTCP_SDES_Packet(void) +{ + sdesChunk_t *cp; // pointer to chunk + sdesChunk_t *cpprev; + sdesItem_t *ip; // pointer to item + sdesItem_t *ipprev; + + cp = this->chunk_; + while (cp) + { + ip = cp->item_; + while (ip) + { + ipprev = ip; + ip = ip->next_; + if (ipprev->type_ != RTCP_SDES_PRIV) + { + delete []ipprev->info_.standard_.data_; + } + else + { + delete []ipprev->info_.priv_.name_; + delete []ipprev->info_.priv_.data_; + } + + delete ipprev; + } + cpprev = cp; + cp = cp->next_; + delete cpprev; + } + + if (this->packet_data_) + delete []this->packet_data_; +} + +//============================================================================== + +void +RTCP_SDES_Packet::add_chunk(ACE_UINT32 ssrc) +{ + sdesChunk_t *cp; // pointer to chunk + + // If this is the first chunk. + if (chd_.count_ == 0) + { + ACE_NEW (this->chunk_, + sdesChunk_t); + this->chunk_->next_ = 0; + this->chunk_->item_ = 0; + cp = this->chunk_; + } + else + { + cp = this->chunk_; + while (cp->next_) + cp = cp->next_; + + ACE_NEW (cp->next_, + sdesChunk_t); + cp = cp->next_; + cp->next_ = 0; + cp->item_ = 0; + } + cp->ssrc_ = ssrc; // store the source + chd_.count_++; // increment the source count +} + +//============================================================================== + +void +RTCP_SDES_Packet::add_item(ACE_UINT32 ssrc, + unsigned char type, + unsigned char length, + const char *data) +{ + sdesChunk_t *cp; // pointer to chunk + sdesItem_t *ip; // pointer to item + + if (this->chunk_ == 0) + { + this->add_chunk(ssrc); + } + cp = this->chunk_; + + while (cp != 0) + { + if (cp->ssrc_ == ssrc) + break; + + if (!cp->next_) + { + this->add_chunk(ssrc); + cp = cp->next_; + break; + } + cp = cp->next_; + } + + ip = cp->item_; + if (ip == 0) + { + ACE_NEW (cp->item_, + sdesItem_t); + ip = cp->item_; + ip->next_= 0; + } + else + { + while (ip->next_) + ip = ip->next_; + + ACE_NEW (ip->next_, + sdesItem_t); + ip = ip->next_; + ip->next_ = 0; + } + ip->type_ = type; + if (length > 255) + { + length = 255; + ACE_DEBUG ((LM_DEBUG, + "RTCP_SDES_Packet::add_item - item too long")); + } + ip->info_.standard_.length_ = length; + ACE_NEW (ip->info_.standard_.data_, + char[length]); + memcpy(ip->info_.standard_.data_, data, length); +} + +//============================================================================== + +void +RTCP_SDES_Packet::add_priv_item(ACE_UINT32 ssrc, + unsigned char nameLength, const char* name, + unsigned char dataLength, const char* data) +{ + sdesChunk_t *cp; // pointer to chunk + sdesItem_t *ip; // pointer to item + + if (this->chunk_ == 0) + { + this->add_chunk(ssrc); + } + cp = this->chunk_; + + while (cp != 0) + { + if (cp->ssrc_ == ssrc) + break; + + if (!cp->next_) + { + this->add_chunk(ssrc); + cp = cp->next_; + break; + } + cp = cp->next_; + } + + ip = cp->item_; + if (ip == 0) + { + ACE_NEW (cp->item_, + sdesItem_t); + ip = cp->item_; + ip->next_ = 0; + } + else + { + while (ip->next_) + ip = ip->next_; + + ACE_NEW (ip->next_, + sdesItem_t); + ip = ip->next_; + ip->next_ = 0; + } + + ip->type_ = RTCP_SDES_PRIV; + if (nameLength > 255) + { + nameLength = 255; + ACE_DEBUG ((LM_DEBUG, + "RTCP_SDES_Packet::add_priv_item - name too long")); + } + if (dataLength > 255) + { + dataLength = 255; + ACE_DEBUG ((LM_DEBUG, + "RTCP_SDES_Packet::add_priv_item - data too long")); + } + ip->info_.priv_.name_length_ = nameLength; + ip->info_.priv_.data_length_ = dataLength; + ACE_NEW (ip->info_.priv_.name_, + char[nameLength]); + ACE_NEW (ip->info_.priv_.data_, + char[dataLength]); + memcpy(ip->info_.priv_.name_, name, nameLength); + memcpy(ip->info_.priv_.data_, data, dataLength); +} + +//============================================================================== + +unsigned int +RTCP_SDES_Packet::packet_size(void) +{ + int size; + sdesChunk_t *cp; // pointer to chunk + sdesItem_t *ip; // pointer to item + + // Determine the size of the packet. + size = 4; // size of common header data in octets + + cp = this->chunk_; + while (cp) + { + size += 4; // size of ssrc + ip = cp->item_; + + while (ip && (ip->type_ != 0)) + { + if (ip->type_ != RTCP_SDES_PRIV) + { + size += 2 + ip->info_.standard_.length_; // size of item + } + else + { + size += 3 + ip->info_.priv_.name_length_ + ip->info_.priv_.data_length_; + } + ip = ip->next_; + } + size += 4 - size%4; // pad with zeros to even 32 bit bound + cp = cp->next_; + } + + chd_.length_ = size/4 - 1; + + return size; +} + +//============================================================================== + +void +RTCP_SDES_Packet::build_packet(void) +{ + sdesChunk_t *cp; // pointer to chunk + sdesItem_t *ip; // pointer to item + int index, i; + + if (this->packet_data_) + delete this->packet_data_; + + ACE_NEW (this->packet_data_, + char[this->packet_size()]); + + index = 0; + this->packet_data_[index] = (chd_.ver_ << 6) | (chd_.pad_ << 5) | chd_.count_; + index++; + this->packet_data_[index] = chd_.pt_; + index++; + *((ACE_UINT16*)&this->packet_data_[index]) = htons(chd_.length_); + index+=2; + + cp = this->chunk_; + while (cp) + { + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(cp->ssrc_); + index+=4; + + ip = cp->item_; + while (ip && (ip->type_ != 0)) + { + this->packet_data_[index] = ip->type_; + index++; + if (ip->type_ != RTCP_SDES_PRIV) + { + this->packet_data_[index] = ip->info_.standard_.length_; + index++; + for (i=0; iinfo_.standard_.length_; i++) + { + this->packet_data_[index] = ip->info_.standard_.data_[i]; + index++; + } + } + else + { + this->packet_data_[index] = ip->info_.priv_.name_length_; + index++; + this->packet_data_[index] = ip->info_.priv_.data_length_; + index++; + for (i=0; iinfo_.priv_.name_length_; i++) + { + this->packet_data_[index] = ip->info_.priv_.name_[i]; + index++; + } + for (i=0; iinfo_.priv_.data_length_; i++) + { + this->packet_data_[index] = ip->info_.priv_.data_[i]; + index++; + } + } + + ip = ip->next_; + } + + this->packet_data_[index] = 0; + index++; + + i=1; + while ((index)%4) + { // pad chunk with zeros to 32 bit bound + this->packet_data_[index] = 0; + index++; + i++; + } + + // Store the number of bytes added. TODO: do we need this + // this->packet_data_[index - 1] = i; + + cp = cp->next_; + } +} + +void +RTCP_SDES_Packet::dump (void) +{ + sdesItem_t *ip; + + ACE_DEBUG ((LM_DEBUG, + "\nRTCP_SDES_Packet:: ")); + + if (this->num_chunks_ != 1) + { + ACE_DEBUG ((LM_DEBUG, + "Mixers not currently supported.\n")); + return; + } + + ACE_DEBUG ((LM_DEBUG, + "from ssrc %u\n", + this->chunk_->ssrc_)); + + // Loop through all of the items. + ip = this->chunk_->item_; + + while (ip) + { + // If there is no data to store, continue. + if (ip->info_.standard_.length_ == 0) + { + ip = ip->next_; + continue; + } + + switch (ip->type_) + { + case RTCP_SDES_END: + break; + case RTCP_SDES_CNAME: + ACE_DEBUG ((LM_DEBUG, + " CNAME '%s'\n", + ip->info_.standard_.data_)); + break; + case RTCP_SDES_NAME: + ACE_DEBUG ((LM_DEBUG, + " NAME '%s'\n", + ip->info_.standard_.data_)); + break; + case RTCP_SDES_EMAIL: + ACE_DEBUG ((LM_DEBUG, + " EMAIL '%s'\n", + ip->info_.standard_.data_)); + break; + case RTCP_SDES_PHONE: + ACE_DEBUG ((LM_DEBUG, + " PHONE '%s'\n", + ip->info_.standard_.data_)); + break; + case RTCP_SDES_LOC: + ACE_DEBUG ((LM_DEBUG, + " LOC '%s'\n", + ip->info_.standard_.data_)); + break; + case RTCP_SDES_TOOL: + ACE_DEBUG ((LM_DEBUG, + " TOOL '%s'\n", + ip->info_.standard_.data_)); + break; + case RTCP_SDES_NOTE: + ACE_DEBUG ((LM_DEBUG, + " NOTE '%s'\n", + ip->info_.standard_.data_)); + break; + case RTCP_SDES_PRIV: + ACE_DEBUG ((LM_DEBUG, + " '%s' '%s'\n", + ip->info_.priv_.name_, + ip->info_.priv_.data_)); + break; + } + ip = ip->next_; + } + +} + +RTCP_SR_Packet::RTCP_SR_Packet(ACE_UINT32 ssrc, + ACE_UINT32 ntp_ts_msw, + ACE_UINT32 ntp_ts_lsw, + ACE_UINT32 timestamp, + ACE_UINT32 packets_sent, + ACE_UINT32 octets_sent, + RR_Block *blocks) +{ + RR_Block *block_ptr= 0; + chd_.count_ = 0; + chd_.ver_ = 2; + chd_.pt_ = RTCP_PT_SR; + + this->ssrc_ = ssrc; + this->ntp_ts_msw_ = ntp_ts_msw; + this->ntp_ts_lsw_ = ntp_ts_lsw; + this->rtp_ts_ = timestamp; + this->psent_ = packets_sent; + this->osent_ = octets_sent; + this->rr_ = blocks; + + block_ptr = blocks; + + while (block_ptr) + { + chd_.count_++; + + // Can only have 31 receiver reports + if (this->chd_.count_ == 31) + { + block_ptr->next_ = 0; + break; + } + + block_ptr = block_ptr->next_; + } + + this->chd_.length_ = 6 + 6*chd_.count_; //+profile specific extensions ?? + + this->packet_data_ = 0; +} + +//============================================================================== + +RTCP_SR_Packet::RTCP_SR_Packet (char* buffer, + int *len) + : RTCP_Packet (buffer) +{ + unsigned int i = 0; + RR_Block *local_block_ptr; + + this->rr_ = 0; + + // The common part of the header is initialized in the parent. + i=4; + this->ssrc_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + this->ntp_ts_msw_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + this->ntp_ts_lsw_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + this->rtp_ts_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + this->psent_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + this->osent_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + for (unsigned int j=0; jchd_.count_; j++) + { + if (j==0) + { + ACE_NEW (local_block_ptr, + RR_Block); + this->rr_ = local_block_ptr; + } + else + { + ACE_NEW (local_block_ptr->next_, + RR_Block); + local_block_ptr = local_block_ptr->next_; + } + + local_block_ptr->next_ = 0; + local_block_ptr->ssrc_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + ACE_UINT32 temp = ntohl(*(ACE_UINT32*)&buffer[i]); + local_block_ptr->fraction_ = (temp&0xff000000) >> 24; + local_block_ptr->lost_ = temp & 0x00ffffff; + i+=4; + local_block_ptr->last_seq_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + local_block_ptr->jitter_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + local_block_ptr->lsr_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + local_block_ptr->dlsr_ = ntohl(*(ACE_UINT32*)&buffer[i]); + i+=4; + } + + *len-=(this->chd_.length_+1)*4; + + this->packet_data_ = 0; +} + +//============================================================================== + +RTCP_SR_Packet::~RTCP_SR_Packet(void) +{ + RR_Block *prev; + + if (this->rr_) + { + while (this->rr_) + { + prev = this->rr_; + this->rr_ = this->rr_->next_; + delete prev; + } + } + + if (this->packet_data_) + delete []this->packet_data_; +} + +//============================================================================== + +unsigned int RTCP_SR_Packet::packet_size (void) +{ + ACE_UINT16 size = (2+chd_.count_*6) * 4; // + profile specific extensions ? + size += 20; // the first line is the same as RR; 20 more bytes for SR + + return size; +} + +//============================================================================== + +void RTCP_SR_Packet::build_packet(void) +{ + int index = 0; + RR_Block *local_block_ptr; + + if (this->packet_data_) + delete []this->packet_data_; + + ACE_NEW (this->packet_data_, + char[this->packet_size()]); + + this->packet_data_[index] = (this->chd_.ver_ << 6) | (this->chd_.pad_ << 5) | this->chd_.count_; + index++; + this->packet_data_[index] = this->chd_.pt_; + index++; + *((ACE_UINT16*)&this->packet_data_[index]) = htons(this->chd_.length_); + index+=2; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->ssrc_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->ntp_ts_msw_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->ntp_ts_lsw_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->rtp_ts_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->psent_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(this->osent_); + index+=4; + + local_block_ptr = this->rr_; + while (local_block_ptr) + { + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->ssrc_); + index+=4; + ACE_UINT32 temp = htonl((local_block_ptr->fraction_&0xff) << 24) & + local_block_ptr->lost_; + *((ACE_UINT32*)&this->packet_data_[index]) = temp; + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->last_seq_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->jitter_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->lsr_); + index+=4; + *((ACE_UINT32*)&this->packet_data_[index]) = htonl(local_block_ptr->dlsr_); + index+=4; + local_block_ptr = local_block_ptr->next_; + } +} + +void +RTCP_SR_Packet::dump (void) +{ + RR_Block *b = this->rr_; + int count = 1; + + ACE_DEBUG ((LM_DEBUG, + "\nRTCP_SR_Packet:: from %u - %d rr blocks follow.\n", + this->ssrc_, + this->chd_.count_)); + ACE_DEBUG ((LM_DEBUG, + " NTP(sec) %u.%u; RTP ts %u\n", + this->ntp_ts_msw_, + this->ntp_ts_lsw_, + this->rtp_ts_)); + ACE_DEBUG ((LM_DEBUG, + " packets sent %u; octets sent %u\n", + this->psent_, + this->osent_)); + + while (b) + { + ACE_DEBUG ((LM_DEBUG, + " Block %d: ssrc %u; frac %u; lost %u; last seq %u\n", + count, + b->ssrc_, + b->fraction_, + b->lost_, + b->last_seq_)); + ACE_DEBUG ((LM_DEBUG, + " jitter %u; lsr %u; dlsr %u;\n", + b->jitter_, + b->lsr_, + b->dlsr_)); + + b = b->next_; + ++count; + } +} diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.h b/TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.h new file mode 100644 index 00000000000..32163374aca --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP_Packet.h @@ -0,0 +1,393 @@ +// $Id$ +#ifndef RTCP_PACKET_INCLUDE +#define RTCP_PACKET_INCLUDE + +#include "ace/OS.h" + +/** + * @struct RTCP_Common_Header + * @brief This is the header data that is common to all RTCP messages. + */ +typedef struct +{ + /// the RTP version being used + unsigned int ver_:2; + + /// indicates whether or not the end of the packet is padded with zeros + unsigned int pad_:1; + + /// this value varies by packet type + unsigned int count_:5; + + /// RTCP packet type (eg BYE, SR, RR, SDES) + unsigned int pt_:8; + + /// packet length in words without this word + ACE_UINT16 length_; +} RTCP_Common_Header; + +/** + * @class RTCP_Packet + * @brief This is an abstract class from which all RTCP packet types are derived. + * It contains code used to validate the RTCP packet. + */ + +class RTCP_Packet +{ +public: + /// Constructor for outgoing RTCP packets. + RTCP_Packet(void); + + /// Constructor for incoming RTCP packets. + RTCP_Packet(char *buffer); + + /// Destructor + virtual ~RTCP_Packet() = 0; + + /// Returns a pointer to a local buffer containing the packet. + void get_packet_data(char **buffer, ACE_UINT16 &length); + + /// Returns the size of the packet. + /// Defined in child class. + virtual unsigned int packet_size(void) = 0; + + /// Checks the validity of an RTCP packet. RTCP packets can be sent + /// together in a compound packet and is_first indicates the first packet + /// in a compound packet + int is_valid (char is_first); + +protected: + /// Header data common to all RTCP packets. + RTCP_Common_Header chd_; + + /// Buffer to hold byte representation of the RTCP packet. + char *packet_data_; + + /// Used to create the byte representation of the RTCP packet. + /// Defined in child class. + virtual void build_packet(void) = 0; +}; + +/** + * @class RTCP_BYE_Packet + * @brief The BYE RTCP packet is sent by a party when leaving an RTP session. + */ + +class RTCP_BYE_Packet : public RTCP_Packet +{ +public: + /// Constructor for outgoing BYE RTCP packets. + /// Takes a synchronization source id list, the list length (1 for non-mixers), + /// and an optional reason for leaving the session. + RTCP_BYE_Packet (ACE_UINT32 *srcList, + unsigned char length, + const char* text=0); + + /// Constructor for incoming BYE RTCP packets. + RTCP_BYE_Packet (char *buffer, + int *len); + + /// Destructor. + virtual ~RTCP_BYE_Packet (void); + + /// Returns the size of the packet in bytes. + unsigned int packet_size (void); + + /// Returns a pointer to a local list of synchronization source ids that are + /// leaving the session. + void ssrc_list (ACE_UINT32 **ssrc_list, + unsigned char &length); + + /// Returns the reason for leaving the session. + const char *reason (void); + + /// Prints the contents of the packet. + void dump (void); + +private: + /// Used to create the byte representation of the RTCP packet. + void build_packet(); + + /// List of synchronization source ids that are leaving the session. + ACE_UINT32 *ssrc_list_; + + /// The number of ssrc's that are leaving the session (1 for non-mixers). + unsigned char ssrc_list_length_; + + /// An optional reason for leaving the session. + char reason_[256]; + + /// The number of bytes in the reason for leaving the session. + unsigned char reason_length_; +}; + +/** + * @struct RR_Block + * @brief The receiver report block encapsulates the data that represents the + * reception statistics for a particular stream. + */ + +struct RR_Block +{ + /// The synchronization source id of the source of the data. + ACE_UINT32 ssrc_; + + /// The fraction of RTP data packets lost since the previous SR or RR was sent. + unsigned int fraction_:8; + + /// The cumulative number of packets lost. + int lost_:24; + + /// The highest extended sequence number received in an RTP packet. + ACE_UINT32 last_seq_; + + /// An estimate of the statistical variance of the RTP data packet interarrival + /// time measured in timestamp units. + ACE_UINT32 jitter_; + + /// The middle 32 bits of the NTP timestamp received in the most recent sender + /// report. + ACE_UINT32 lsr_; + + /// The delay in 1/65536 seconds since receiving the last sender report. + ACE_UINT32 dlsr_; + + /// Link to the next receiver report block. + RR_Block *next_; +}; + +/** + * @class RTCP_RR_Packet + * @brief The Receiver Report packet is sent by all members of a session that + * are not sending data. It contains a list of RR_Block to represent each + * source this party is receiving data from. + */ + +class RTCP_RR_Packet : public RTCP_Packet +{ +public: + /// Constructor for incoming receiver reports. + RTCP_RR_Packet (char *buffer, int* len); + + /// Constructor for outgoing receiver reports. + RTCP_RR_Packet (ACE_UINT32 ssrc, RR_Block *blocks); + + /// Destructor. + virtual ~RTCP_RR_Packet (void); + + /// Returns the size of the packet in bytes. + unsigned int packet_size(void); + + /// Returns the synchronization source id of the source sending this packet. + ACE_INT32 ssrc (void) { return this->ssrc_; } + + /// Prints the contents of the packet. + void dump (void); + +private: + /// Used to create the byte representation of the RTCP packet. + void build_packet(void); + + /// The synchronization source id of the sender of this report. + ACE_UINT32 ssrc_; + + /// A linked list of the receiver report block(s) being sent. + RR_Block *rr_; +}; + +typedef struct sdesItem_s sdesItem_t; + +/** + * @struct sdesItem_s + * @brief This is a linked list of structures containing source description + * 'items' such as canonical name, email, location etc. + */ + +struct sdesItem_s +{ + /// link to next item. + sdesItem_t *next_; + + /// Type of item (eg canonical name). + unsigned char type_; + + union + { + struct + { + /// Length of an item (in octets). + unsigned char length_; + + /// Item text, not null-terminated. + char *data_; + } standard_; + struct + { + /// Length of the name of an item (in octets). + unsigned char name_length_; + + /// Length of the item data (in octets). + unsigned char data_length_; + + /// The name of the item, not null-terminated. + char *name_; + + /// Item data, not null-terminated. + char *data_; + } priv_; + } info_; +}; + +typedef struct sdesChunk_s sdesChunk_t; + +/** + * @struct sdesChunk_s + * @brief This is a linked list of structures containing groups of source + * description items. A group of items for a particular synchronization source + * id is referred to as a 'chunk'. + */ +struct sdesChunk_s +{ + /// Link to next item. + sdesChunk_t *next_; + + /// The synchronization source id that this chunk describes. + ACE_UINT32 ssrc_; + + /// A linked list of items to describe this source. + sdesItem_t *item_; +}; + +/** + * @class RTCP_SDES_Packet + * @brief The Source Description packet is sent by all members of a session. + * At a minimum, the canonical name (or CNAME) is sent with each RTCP packet. + * Other items such as name, email, or location are included less frequently. + */ +class RTCP_SDES_Packet : public RTCP_Packet +{ +public: + /// Constructor for incoming SDES packets. + RTCP_SDES_Packet(char* buffer, int *len); + + /// Constructor for outgoing SDES packets. + RTCP_SDES_Packet(void); + + /// Destructor. + virtual ~RTCP_SDES_Packet(void); + + /// This will add a standard item of type and length for the ssrc specified. + /// When the first item for a ssrc is added, a chunk is created. Subsequent + /// items for that ssrc are added to the same chunk. New chunks are created + /// for each unique ssrc. + void add_item(ACE_UINT32 ssrc, + unsigned char type, + unsigned char length, + const char* data); + + /// This will add a private item using the name and data for the ssrc specified. + /// When the first item for a ssrc is added, a chunk is created. Subsequent + /// items for that ssrc are added to the same chunk. New chunks are created + /// for each unique ssrc. + void add_priv_item(ACE_UINT32 ssrc, + unsigned char nameLength, + const char *name, + unsigned char dataLength, + const char *data); + + /// Returns the size of the packet in bytes. + unsigned int packet_size(void); + + /// Prints the contents of the packet. + void dump (void); + + /// This returns the synchronization source id for this packet. This assumes + /// that this source is only receiving messages from end systems (i.e. only + /// one source id per SDES) + ACE_UINT32 ssrc (void) { return this->chunk_->ssrc_; } + +private: + /// Used to create the byte representation of the RTCP packet. + void build_packet(void); + + /// Add a chunk to the packet. + void add_chunk(ACE_UINT32 ssrc); + + /// The number of chunks contained in this packet. + /// 1 for end systems, 1+ for mixers + unsigned long num_chunks_; + +// unsigned long num_items_; + + /// A linked list of chunks for this packet (only 1 for non-mixers). + sdesChunk_t *chunk_; +}; + +/** + * @class RTCP_SR_Packet + * @brief The Sender Report packet is sent by all members of a session that + * are sending data. It contains statistics on the data being sent out. It + * also contains a list of RR_Block to represent each source this party is + * receiving data from. + */ + +class RTCP_SR_Packet : public RTCP_Packet +{ +public: + /// Constructor for incoming SR packets. + RTCP_SR_Packet(char *buffer, int *len); + + /// Constructor for outgoing SR packets. + RTCP_SR_Packet(ACE_UINT32 ssrcVal, + ACE_UINT32 ntpMSByte, + ACE_UINT32 ntpLSByte, + ACE_UINT32 timestamp, + ACE_UINT32 pktsSent, + ACE_UINT32 octetsSent, + RR_Block *rrBlocks); + + /// Destructor + virtual ~RTCP_SR_Packet(void); + + /// Returns the size of the packet in bytes. + unsigned int packet_size(void); + + /// Returns the synchronization source id for the sender of this packet. + ACE_UINT32 ssrc (void) { return this->ssrc_; } + + /// Returns the most significant word of the NTP timestamp. + ACE_UINT32 ntp_ts_msw (void) { return this->ntp_ts_msw_; } + + /// Returns the least significant word of the NTP timestamp. + ACE_UINT32 ntp_ts_lsw (void) { return this->ntp_ts_lsw_; } + + /// Prints the contents of the packet. + void dump (void); + +private: + /// Used to create the byte representation of the RTCP packet. + void build_packet(void); + + /// The synchronization source id of the sender generating this report. + ACE_UINT32 ssrc_; + + /// The most significant word of the NTP timestamp. + ACE_UINT32 ntp_ts_msw_; + + /// The least significant word of the NTP timestamp. + ACE_UINT32 ntp_ts_lsw_; + + /// The RTP timestamp + ACE_UINT32 rtp_ts_; + + /// The total number of packets sent. + ACE_UINT32 psent_; + + /// The total number of octets sent. + ACE_UINT32 osent_; + + /// A linked list of receiver report blocks. + RR_Block *rr_; +}; + +#endif diff --git a/TAO/orbsvcs/orbsvcs/AV/RTP.cpp b/TAO/orbsvcs/orbsvcs/AV/RTP.cpp index 86004989792..ba4ffe21a8a 100644 --- a/TAO/orbsvcs/orbsvcs/AV/RTP.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/RTP.cpp @@ -38,89 +38,310 @@ #include "RTCP.h" #include "Nil.h" -int -TAO_AV_RTP::handle_input (ACE_Message_Block *&data, - TAO_AV_frame_info *&frame_info) -{ - int n = data->length (); - int size_phdr = ACE_static_cast (int, sizeof (rtphdr)); - if (n < size_phdr) - ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:invalid header\n"),-1); - rtphdr* rh = (rtphdr*)data->rd_ptr (); - int version = * (u_char*)rh >> 6; - if (version != 2) +// RTP_Packet + +// Constructor for RTP packets received +RTP_Packet::RTP_Packet(char* buffer, int length) +{ + // skip the standard header info + int index = 12; + + memcpy(this->packet_, buffer, length); + + for (int j=0; j<(int)this->cc(); j++) { - // state->bad_version_++; - ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP:bad version\n"),-1); + this->host_byte_order_csrc_list_[j] = ntohl(*(ACE_UINT32*)&buffer[index]); + index+=4; } - TAO_AV_RTP::rtphdr header; - header = *rh; - // data->rd_ptr (sizeof (rtphdr)); - ACE_NEW_RETURN (frame_info, - TAO_AV_frame_info, - -1); - frame_info->boundary_marker = header.rh_flags & RTP_M; - frame_info->timestamp = header.rh_ts; - frame_info->ssrc = header.rh_ssrc; - frame_info->sequence_num = header.rh_seqno; - frame_info->format = header.rh_flags & 0x7f; - return 0; + + // ignore the header extension if there is one + if (this->ext()) + { + index+=2; + int extension_data_size = ntohs(*(ACE_UINT16*)&buffer[index]); + index+=2; + index+=extension_data_size; + + this->extension_bytes_ = 4 + extension_data_size; + } + else + this->extension_bytes_ = 0; + + this->packet_size_ = length; + this->payload_size_ = length-index; + + // This is necessary only for payload types that have 16 bit values to correct + // the network byte ordering. + if ((this->pt() == RTP_PT_L16_OTHER) || + (this->pt() == RTP_PT_L16_STEREO) || + (this->pt() == RTP_PT_L16_MONO)) + { + for (int i=0; i < payload_size_; i+=2) + { + *(ACE_UINT16*)&this->host_byte_order_payload_[i] = ntohs(*(ACE_UINT16*)&this->packet_[index]); + index+=2; + } + } +} + +RTP_Packet::RTP_Packet(unsigned char padding, + unsigned char marker, + unsigned char payload_type, + ACE_UINT32 seq_num, + ACE_UINT32 timestamp, + ACE_UINT32 ssrc, + unsigned char csrc_count, + ACE_UINT32 *csrc_list, + char *data, + ACE_UINT16 data_size) + :extension_bytes_(0) +{ + //size of header (in octets) without contributing sources + ACE_UINT16 size = 3*4; + int index = 0; + + if (data_size > RTP_MTU-12) + { + data_size = RTP_MTU-12; + ACE_DEBUG ((LM_DEBUG, "\n(%N,%l) RTP_Packet: Warning - packet truncated\n")); + } + + if (csrc_count > 15) + csrc_count = 15; // Only 15 contributing sources can be specified. + + if (csrc_list != 0) + for (unsigned char i=0; ihost_byte_order_csrc_list_[i] = csrc_list[i]; + } + + this->packet_size_ = size + data_size; + + index = 0; + this->packet_[index] = ((RTP_VERSION & 0x3) << 6) | + ((padding & 0x1) << 5) | + ((0 & 0x1) << 4) | // extension bit + ((csrc_count & 0xf)); + + index++; + this->packet_[index] = ((marker & 0x1) << 7 ) | + ((payload_type & 0x7f)); + index++; + *((ACE_UINT16*)&this->packet_[index]) = (ACE_UINT16)htons(seq_num); + index+=2; + *((ACE_UINT32*)&this->packet_[index]) = (ACE_UINT32)htonl(timestamp); + index+=4; + *((ACE_UINT32*)&this->packet_[index]) = htonl(ssrc); + index+=4; + + for (int i=0; ipacket_[index]) = htonl(this->host_byte_order_csrc_list_[i]); + index+=4; + } + + memcpy (this->host_byte_order_payload_, data, data_size); + + this->payload_size_ = data_size; + + // Correct byte ordering for multi-byte payload types. + if ((this->pt() == RTP_PT_L16_OTHER) || + (this->pt() == RTP_PT_L16_STEREO) || + (this->pt() == RTP_PT_L16_MONO)) + { + for (int i=0; ipayload_size_; i+=2) + { + *(ACE_UINT16*)&this->packet_[index] = htons(*(ACE_UINT16*)&data[i]); + index+=2; + } + } + else + for (int i=0; ipayload_size_; i++) + { + this->packet_[index] = data[i]; + index++; + } +} + +RTP_Packet::~RTP_Packet(void) +{ +} + +ACE_UINT16 +RTP_Packet::packet_size(void) +{ + return this->packet_size_; +} + +ACE_UINT16 +RTP_Packet::payload_size(void) +{ + return this->payload_size_; +} + +unsigned int +RTP_Packet::ver (void) +{ + return ( this->packet_[0] & 0xC0 ) >> 6; +} + +unsigned int +RTP_Packet::pad (void) +{ + return ( this->packet_[0] & 0x20 ) >> 5; +} + +unsigned int +RTP_Packet::ext (void) +{ + return ( this->packet_[0] & 0x10 ) >> 4; +} + +unsigned int +RTP_Packet::cc (void) +{ + return ( this->packet_[0] & 0x0F ) ; +} + +unsigned int +RTP_Packet::mrk (void) +{ + return ( this->packet_[1] & 0x80 ) >> 7; +} + +unsigned int +RTP_Packet::pt (void) +{ + return ( this->packet_[1] & 0x7F ) ; +} + +ACE_UINT16 +RTP_Packet::sn (void) +{ + return ntohs(*(ACE_UINT16*)(&this->packet_[2])) ; +} + +ACE_UINT32 +RTP_Packet::ts (void) +{ + return ntohl(*(ACE_UINT32*)(&this->packet_[4])) ; +} + +ACE_UINT32 +RTP_Packet::ssrc (void) +{ + return ntohl(*(ACE_UINT32*)(&this->packet_[8])) ; } +unsigned int +RTP_Packet::ext_bytes (void) +{ + return this->extension_bytes_; +} + +void +RTP_Packet::get_frame_info (TAO_AV_frame_info *frame_info) +{ + frame_info->timestamp = this->mrk(); + frame_info->timestamp = this->ts(); + frame_info->ssrc = this->ssrc(); + frame_info->sequence_num = this->sn(); + frame_info->format = this->pt(); +} int -TAO_AV_RTP::write_header (rtphdr &header, - int format, - ACE_UINT16 &sequence_num, - ACE_UINT32 ts, - ACE_UINT32 ssrc, - CORBA::Boolean boundary_marker) -{ - int flags = RTP_VERSION << 14 | format; - if (boundary_marker) - flags |= RTP_M; - header.rh_flags = ntohs (flags); - header.rh_seqno = htons (sequence_num); - sequence_num++; - header.rh_ts = htonl (ts); - header.rh_ssrc = ssrc; - return 0; +RTP_Packet::is_valid (void) +{ + // taken from RFC 1889 - Appendix A.1 + + // make sure the RTP version is correct + if (this->ver() != RTP_VERSION) + return 0; + + // make sure the payload type is not SR or RR + if ((this->pt() == RTCP_PT_SR) || (this->pt() == RTCP_PT_RR)) + return 0; + + // if the p bit is set, the last octet of the packet must contain a valid + // octet count, in particular, less than the total packet length minus + // the header size. + if (this->pad() != 0) + if ((unsigned int)this->packet_[this->packet_size_] >= + (this->packet_size_ - (12 + this->cc() + this->extension_bytes_))) + return 0; + + // If there is an extension, it is ignored (taken care of in constructor) + + // The length of the packet must be consistent with CC and payload type (if + // payloads have a known length) + + return 1; } +void +RTP_Packet::get_csrc_list (ACE_UINT32 **csrc_list, ACE_UINT16 &length) +{ + *csrc_list = this->host_byte_order_csrc_list_; + length = this->cc (); +} + +void +RTP_Packet::get_payload (char **payload, ACE_UINT16 &length) +{ + *payload = this->host_byte_order_payload_ ; + length = this->payload_size_; +} + +void +RTP_Packet::get_packet_data (char **packet, ACE_UINT16 &length) +{ + *packet = this->packet_; + length = this->packet_size_; +} + + // TAO_AV_RTP_Object int TAO_AV_RTP_Object::handle_input (void) { - TAO_AV_frame_info *frame_info = 0; + TAO_AV_frame_info frame_info; - // Handles the incoming RTP packet input. + if (TAO_debug_level > 1) + ACE_DEBUG ((LM_DEBUG, + "\nTAO_AV_RTP_Object::handle_input\n")); + // Handles the incoming RTP packet input. this->frame_.rd_ptr (this->frame_.base ()); + int n = this->transport_->recv (this->frame_.rd_ptr (), this->frame_.size ()); if (n == 0) ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:connection closed\n"),-1); if (n < 0) ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:recv error\n"),-1); + this->frame_.wr_ptr (this->frame_.rd_ptr () + n); ACE_Addr *addr = this->transport_->get_peer_addr (); - ACE_Message_Block* data = &this->frame_; - int result = TAO_AV_RTP::handle_input (data, - frame_info); - if (result < 0) - return 0; - if(this->control_object_) - this->control_object_->handle_control_input (data, - *addr); + this->control_object_->handle_control_input (&this->frame_, *addr); - this->frame_.rd_ptr (sizeof(TAO_AV_RTP::rtphdr)); - result = this->callback_->receive_frame (&this->frame_, - frame_info, - *addr); + // Get payload that has been converted to host byte order + char *data_ptr; + ACE_UINT16 length; + RTP_Packet rtp_packet(this->frame_.rd_ptr (), this->frame_.length ()); + + rtp_packet.get_frame_info (&frame_info); + rtp_packet.get_payload(&data_ptr, length); + + this->frame_.rd_ptr (this->frame_.base ()); + memcpy (this->frame_.rd_ptr (), data_ptr, length); + this->frame_.wr_ptr (this->frame_.rd_ptr() + length); + + this->callback_->receive_frame (&this->frame_, &frame_info, *addr); return 0; } @@ -129,38 +350,116 @@ int TAO_AV_RTP_Object::send_frame (ACE_Message_Block *frame, TAO_AV_frame_info *frame_info) { - TAO_AV_RTP::rtphdr header; +// ACE_Addr *addr = this->transport_->get_peer_addr (); + int result = -1; + RTP_Packet *rtp_packet; + ACE_UINT32 csrc_count = 0; // Assume for now no mixers/translators + ACE_UINT32 *csrc_list = 0; + if (frame_info != 0) { - result = TAO_AV_RTP::write_header (header, - frame_info->format, - this->sequence_num_, - frame_info->timestamp, - frame_info->ssrc, - frame_info->boundary_marker); - frame_info->sequence_num = this->sequence_num_; + if (frame_info->format != this->format_) + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTP_Object::send_frame - error: format type mismatch")); + if (frame_info->ssrc != 0) + this->ssrc_ = frame_info->ssrc; + + TAO_AV_RTCP_Object *rtcp_prot_obj = ACE_dynamic_cast (TAO_AV_RTCP_Object*, + this->control_object_); + // set the ssrc on the control object so the RTCP traffic can be matched + // to the RTP traffic + rtcp_prot_obj->ssrc(this->ssrc_); + + ACE_NEW_RETURN (rtp_packet, + RTP_Packet (0, // padding + frame_info->boundary_marker, // marker + this->format_, // payload type + frame_info->sequence_num, // sequence num + frame_info->timestamp, // time stamp + this->ssrc_, // ssrc + csrc_count, // csrc count + csrc_list, // csrc list + frame->rd_ptr (), // data + frame->length ()), // data size + -1); + + frame_info->sequence_num ++; } else { - ACE_Time_Value ts = ACE_OS::gettimeofday(); - result = TAO_AV_RTP::write_header (header, - 0, - this->sequence_num_, - (ACE_UINT32)ts.msec(), - 0, - 0); + // TODO: For periodic RTP packets (constant rate), the RFC suggests + // increasing the clock by the number of samples each frame rather + // than relying on the system time + + // The RFC specifies at least one timestamp unit per sample as well as a + // random offset. It used to be in milliseconds so I left it that way + // for non-audio streams. + unsigned int samples_per_sec; + double samples_per_usec; + + switch (this->format_) + { + case RTP_PT_PCMU: + case RTP_PT_CELP: + case RTP_PT_G721: + case RTP_PT_GSM: + case RTP_PT_DVI: + case RTP_PT_LPC: + case RTP_PT_PCMA: + case RTP_PT_G722: + samples_per_sec = 8000; + break; + case RTP_PT_L16_STEREO: + case RTP_PT_L16_MONO: + samples_per_sec = 44100; + break; + default: + samples_per_sec = 1000000; + }; + + samples_per_usec = samples_per_sec/1000000.0; + + ACE_Time_Value now = ACE_OS::gettimeofday(); + + ACE_UINT32 ts = (ACE_UINT32) + (now.sec () * samples_per_sec + + ((double)now.usec () * samples_per_usec) + + this->timestamp_offset_); + + ACE_NEW_RETURN (rtp_packet, + RTP_Packet (0, // padding + 0, // marker + this->format_, // payload type + this->sequence_num_, // sequence num + ts, // time stamp + this->ssrc_, // ssrc + csrc_count, // csrc count + csrc_list, // csrc list + frame->rd_ptr (), // data + frame->length ()), // data size + -1); + + this->sequence_num_ ++; } - if (result < 0) - return result; - ACE_Message_Block mb ((char *)&header, - sizeof (header)); - mb.wr_ptr (sizeof (header)); - mb.cont (frame); + char *data_ptr; + ACE_UINT16 data_length; + rtp_packet->get_packet_data (&data_ptr, data_length); + ACE_Message_Block mb (data_ptr, data_length); + mb.wr_ptr (data_length); + result = this->transport_->send (&mb); if (result < 0) ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::send_frame failed\n"),result); + + TAO_AV_RTCP_Object *rtcp_prot_obj = ACE_dynamic_cast (TAO_AV_RTCP_Object*, + this->control_object_); + rtcp_prot_obj->handle_control_output (&mb); +// rtcp_prot_obj->handle_control_output (rtp_packet); + + delete rtp_packet; + return 0; } @@ -169,40 +468,116 @@ TAO_AV_RTP_Object::send_frame (const iovec *iov, int iovcnt, TAO_AV_frame_info *frame_info) { - TAO_AV_RTP::rtphdr header; - // int format = 0; int result = -1; + RTP_Packet *rtp_packet = 0; + ACE_UINT32 csrc_count = 0; // Assume for now no mixers/translators + ACE_UINT32 *csrc_list = 0; + if (frame_info != 0) { - result = TAO_AV_RTP::write_header (header, - frame_info->format, - this->sequence_num_, - frame_info->timestamp, - frame_info->ssrc, - frame_info->boundary_marker); - frame_info->sequence_num = this->sequence_num_; + if (frame_info->format != this->format_) + ACE_DEBUG ((LM_DEBUG, + "TAO_AV_RTP_Object::send_frame - error: format type mismatch")); + this->sequence_num_ = frame_info->sequence_num; + if (frame_info->ssrc != 0) + this->ssrc_ = frame_info->ssrc; + + TAO_AV_RTCP_Object *rtcp_prot_obj = ACE_dynamic_cast (TAO_AV_RTCP_Object*, + this->control_object_); + // set the ssrc on the control object so the RTCP traffic can be matched + // to the RTP traffic + rtcp_prot_obj->ssrc(this->ssrc_); + + + ACE_NEW_RETURN (rtp_packet, + RTP_Packet (0, // padding + frame_info->boundary_marker, // marker + this->format_, // payload type + frame_info->sequence_num, // sequence num + frame_info->timestamp, // time stamp + this->ssrc_, // ssrc + csrc_count, // csrc count + csrc_list, // csrc list + (char *)iov[0].iov_base, // data + iov[0].iov_len), // data size + -1); + + frame_info->sequence_num ++; } else { - result = TAO_AV_RTP::write_header (header, - 0, - this->sequence_num_, - 0, - 0, - 0); + // TODO: For periodic RTP packets (constant rate), the RFC suggests + // increasing the clock by the number of samples each frame rather + // than relying on the system time + + // The RFC specifies at least one timestamp unit per sample as well as a + // random offset. It used to be in milliseconds so I left it that way + // for non-audio streams. + + unsigned int samples_per_sec; + double samples_per_usec; + + switch (this->format_) + { + case RTP_PT_PCMU: + case RTP_PT_CELP: + case RTP_PT_G721: + case RTP_PT_GSM: + case RTP_PT_DVI: + case RTP_PT_LPC: + case RTP_PT_PCMA: + case RTP_PT_G722: + samples_per_sec = 8000; + break; + case RTP_PT_L16_STEREO: + case RTP_PT_L16_MONO: + samples_per_sec = 44100; + break; + default: + samples_per_sec = 1000000; + }; + + samples_per_usec = samples_per_sec/1000000.0; + + ACE_Time_Value now = ACE_OS::gettimeofday(); + + ACE_UINT32 ts = (ACE_UINT32) + (now.sec () * samples_per_sec + + ((double)now.usec () * samples_per_usec) + + this->timestamp_offset_); + + ACE_NEW_RETURN (rtp_packet, + RTP_Packet (0, // padding + 0, // marker + this->format_, // payload type + this->sequence_num_, // sequence num + ts, // time stamp + this->ssrc_, // ssrc + csrc_count, // csrc count + csrc_list, // csrc list + (char *)iov[0].iov_base, // data + iov[0].iov_len), // data size + -1); + + this->sequence_num_ ++; } - if (result < 0) - return result; + + char *data_ptr; + ACE_UINT16 data_length; + rtp_packet->get_packet_data (&data_ptr, data_length); iovec send_iov[IOV_MAX]; - send_iov [0].iov_base = (char *)&header; - send_iov [0].iov_len = sizeof(header); - for (int i=1;i<=iovcnt; i++) - send_iov [i] = iov [i-1]; - result = this->transport_->send (send_iov, - iovcnt+1); + send_iov [0].iov_base = data_ptr; + send_iov [0].iov_len = data_length; + for (int i=1;itransport_->send (send_iov, iovcnt); + + delete rtp_packet; + if (result < 0) ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_RTP::send_frame failed\n"),result); + return 0; } @@ -217,10 +592,11 @@ TAO_AV_RTP_Object::send_frame (const char*, TAO_AV_RTP_Object::TAO_AV_RTP_Object (TAO_AV_Callback *callback, TAO_AV_Transport *transport) :TAO_AV_Protocol_Object (callback,transport), - sequence_num_ (0), control_object_ (0) { this->sequence_num_ = ACE_OS::rand (); + this->timestamp_offset_ = ACE_OS::rand (); + this->ssrc_ = TAO_AV_RTCP::alloc_srcid ((unsigned int)this); this->frame_.size (2 * this->transport_->mtu ()); } @@ -245,6 +621,7 @@ TAO_AV_RTP_Object::set_policies (const TAO_AV_PolicyList &policy_list) this->policy_list_ = policy_list; u_int num_policies = this->policy_list_.length (); TAO_AV_Policy *policy = 0; + for (u_int i=0; i< num_policies;i++) { policy = this->policy_list_ [i]; @@ -280,6 +657,10 @@ void TAO_AV_RTP_Object::control_object (TAO_AV_Protocol_Object *object) { this->control_object_ = object; + TAO_AV_RTCP_Object *rtcp_prot_obj = ACE_dynamic_cast (TAO_AV_RTCP_Object*, + this->control_object_); + rtcp_prot_obj->ssrc (this->ssrc_); + rtcp_prot_obj->ts_offset (this->timestamp_offset_); } int @@ -319,6 +700,7 @@ TAO_AV_RTP_Flow_Factory::make_protocol_object (TAO_FlowSpec_Entry *entry, TAO_AV_Transport *transport) { TAO_AV_Callback *callback = 0; + endpoint->get_callback (entry->flowname (), callback); @@ -331,6 +713,7 @@ TAO_AV_RTP_Flow_Factory::make_protocol_object (TAO_FlowSpec_Entry *entry, handler); endpoint->set_protocol_object (entry->flowname (), object); + return object; } @@ -338,7 +721,9 @@ int TAO_AV_RTP_Flow_Factory::match_protocol (const char *flow_string) { if (ACE_OS::strncasecmp (flow_string,"RTP",3) == 0) - return 1; + { + return 1; + } return 0; } @@ -356,3 +741,5 @@ ACE_STATIC_SVC_DEFINE (TAO_AV_RTP_Flow_Factory, ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, 0) + + diff --git a/TAO/orbsvcs/orbsvcs/AV/RTP.h b/TAO/orbsvcs/orbsvcs/AV/RTP.h index a3409f8bb6a..cc280e12f63 100644 --- a/TAO/orbsvcs/orbsvcs/AV/RTP.h +++ b/TAO/orbsvcs/orbsvcs/AV/RTP.h @@ -72,12 +72,21 @@ #define RTP_PT_H261_COMPAT 127 /* RTP standard content encodings for audio */ -#define RTP_PT_PCMU 0 -#define RTP_PT_CELP 1 -#define RTP_PT_GSM 3 -#define RTP_PT_DVI 5 -#define RTP_PT_LPC 7 - +#define RTP_PT_PCMU 0 /* 8k */ +#define RTP_PT_CELP 1 /* 8k */ +#define RTP_PT_G721 2 /* 8k */ +#define RTP_PT_GSM 3 /* 8k */ +#define RTP_PT_DVI 5 /* 8k */ +#define RTP_PT_LPC 7 /* 8k */ +#define RTP_PT_PCMA 8 /* 8k */ +#define RTP_PT_G722 9 /* 8k */ +#define RTP_PT_L16_STEREO 10 /* 44.1k */ +#define RTP_PT_L16_MONO 11 /* 44.1k */ + +/* TODO: keep?? + non-standard encodings for audio + */ +#define RTP_PT_L16_OTHER 23 /* */ /* Offset from UNIX's epoch to the NTP epoch in seconds (NTP's JAN_1970) */ #define RTP_EPOCH_OFFSET 2208988800UL @@ -91,6 +100,7 @@ #define RTCP_PT_SR 200 /* sender report */ #define RTCP_PT_RR 201 /* receiver report */ #define RTCP_PT_SDES 202 /* source description */ +#define RTCP_SDES_END 0 /* indicates the end of the sdes message */ #define RTCP_SDES_CNAME 1 /* official name (mandatory) */ #define RTCP_SDES_NAME 2 /* personal name (optional) */ #define RTCP_SDES_EMAIL 3 /* e-mail addr (optional) */ @@ -104,6 +114,8 @@ #define RTCP_SDES_MIN 1 +#define RTP_SEQ_MOD (1<<16) + /* * Parameters controling the RTCP report rate timer. @@ -118,21 +130,13 @@ * Largest (user-level) packet size generated by our rtp applications. * Individual video formats may use smaller mtu's. */ -#define RTP_MTU 1024 +#define RTP_MTU 2*ACE_MAX_DGRAM_SIZE #define MAXHDR 24 #include "Policy.h" #include "FlowSpec_Entry.h" #include "MCast.h" -//------------------------------------------------------------ -// TAO_AV_RTP_UDP -//------------------------------------------------------------ - - -class TAO_AV_SourceManager; -class TAO_AV_RTCP_UDP_Flow_Handler; -class TAO_AV_RTP_State; //------------------------------------------------------------ // TAO_AV_RTP @@ -234,16 +238,112 @@ public: ACE_UINT16 blkno; }; - static int handle_input (ACE_Message_Block *&data, - TAO_AV_frame_info *&frame_info); +}; + +/** + * @class RTP_Packet + * @brief This class encapsulates all the necessary information to break down + * or build up an RTP data packet as well as operations to access all data + * items in the packet. + */ +class RTP_Packet +{ +public: + /// Constructor for incoming RTP packets. + RTP_Packet(char* buffer, + int length); + + /// Constructor for outgoing RTP packets + RTP_Packet(unsigned char padding, + unsigned char marker, + unsigned char payloadType, + ACE_UINT32 sequenceNumber, + ACE_UINT32 timeStamp, + ACE_UINT32 syncSource, + unsigned char contribSourcCount, + ACE_UINT32 contribSourceList[], + char *data, + ACE_UINT16 dataSize); + + /// Destructor + ~RTP_Packet(void); + + /// Returns the size of the RTP packet in bytes. + ACE_UINT16 packet_size(void); + + /// Returns the size of the payload in bytes. + ACE_UINT16 payload_size(void); + + /// Populates the passed in frame_info. + void get_frame_info (TAO_AV_frame_info *frame_info); + + /// Returns 1 if packet is valid and 0 if not. + int is_valid (void); + + /// Returns the RTP version of the packet. + unsigned int ver (void); - static int write_header (rtphdr &header, - int format, - ACE_UINT16 &sequence_num, - ACE_UINT32 ts, - ACE_UINT32 ssrc, - CORBA::Boolean boundary_marker); + /// Returns 1 if the padding bit is set, 0 if not. + unsigned int pad (void); + /// Returns 1 if the header extension bit is set, 0 if not. + unsigned int ext (void); + + /// Returns the number of bytes in the header extension or 0 if no extension. + unsigned int ext_bytes (void); + + /// Returns the contributing source count. + /// This should only be non-zero for mixers. + unsigned int cc (void); + + /// Returns 1 if the marker bit is set, 0 if not. + unsigned int mrk (void); + + /// Returns the payload type of the packet. + unsigned int pt (void); + + /// Returns the sequence number of the packet. + ACE_UINT16 sn (void); + + /// Returns the timestamp of the packet. + ACE_UINT32 ts (void); + + /// Returns the synchronization source id of the packet. + ACE_UINT32 ssrc (void); + + /// Returns a pointer to the local contributing source list and its length. + /// This should be empty except for mixers. + /// RTP_Packet retains ownership. + void get_csrc_list (ACE_UINT32 **csrc_list, ACE_UINT16 &length); + + /// Returns a pointer to the locally stored payload and its size in bytes. + /// The payload is returned in host byte order. + /// RTP_Packet retains ownership. + void get_payload (char **payload, ACE_UINT16 &size); + + /// Returns a pointer to the locally stored rtp packet and its size in bytes. + /// RTP_Packet retains ownership. + void get_packet_data (char **packet, ACE_UINT16 &size); + +private: + /// Local buffer to hold the RTP packet. + char packet_[RTP_MTU]; + + /// Local buffer to hold the contributing source list with the values stored + /// in host byte order. + ACE_UINT32 host_byte_order_csrc_list_[15]; + + /// Local buffer to hold the payload with the values stored in host byte order. + char host_byte_order_payload_[RTP_MTU]; + + /// The number of bytes in the header extension - 0 if no extension. + unsigned int extension_bytes_; + + /// The size of the overall data packet. + ACE_UINT16 packet_size_; + + /// The size of the payload portion of the packet. + ACE_UINT16 payload_size_; }; /** @@ -277,14 +377,17 @@ public: protected: ACE_UINT16 sequence_num_; + ACE_UINT32 timestamp_offset_; int format_; - CORBA::ULong ssrc_; + ACE_UINT32 ssrc_; TAO_AV_Protocol_Object *control_object_; /// Pre-allocated memory to receive the data... ACE_Message_Block frame_; }; + + /** * @class TAO_AV_RTP_Flow_Factory * @brief diff --git a/TAO/orbsvcs/orbsvcs/AV/TCP.cpp b/TAO/orbsvcs/orbsvcs/AV/TCP.cpp index 06a7d21701d..9abda9f89c2 100644 --- a/TAO/orbsvcs/orbsvcs/AV/TCP.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/TCP.cpp @@ -400,8 +400,11 @@ TAO_AV_TCP_Connector::open (TAO_Base_StreamEndPoint *endpoint, int TAO_AV_TCP_Connector::connect (TAO_FlowSpec_Entry *entry, - TAO_AV_Transport *&transport) + TAO_AV_Transport *&transport, + TAO_AV_Core::Flow_Component flow_comp) { + ACE_UNUSED_ARG (flow_comp); + this->entry_ = entry; this->flowname_ = entry->flowname (); ACE_Addr *remote_addr = entry->address (); @@ -410,7 +413,7 @@ TAO_AV_TCP_Connector::connect (TAO_FlowSpec_Entry *entry, int result = this->connector_.connector_connect (handler, *inet_addr); if (result < 0) - ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_connector::open failed\n"),-1); + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_connector::connect failed\n"),-1); entry->handler (handler); transport = handler->transport (); return 0; @@ -499,8 +502,11 @@ int TAO_AV_TCP_Acceptor::open (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) { + ACE_UNUSED_ARG (flow_comp); + this->flow_protocol_factory_ = factory; if (TAO_debug_level > 0) @@ -546,8 +552,11 @@ int TAO_AV_TCP_Acceptor::open_default (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) { + ACE_UNUSED_ARG (flow_comp); + this->flow_protocol_factory_ = factory; this->av_core_ = av_core; this->endpoint_ = endpoint; @@ -713,4 +722,3 @@ ACE_STATIC_SVC_DEFINE (TAO_AV_TCP_Factory, 0) ACE_FACTORY_DEFINE (TAO_AV, TAO_AV_TCP_Factory) - diff --git a/TAO/orbsvcs/orbsvcs/AV/TCP.h b/TAO/orbsvcs/orbsvcs/AV/TCP.h index 44b16755b18..72ebf9dc14a 100644 --- a/TAO/orbsvcs/orbsvcs/AV/TCP.h +++ b/TAO/orbsvcs/orbsvcs/AV/TCP.h @@ -146,12 +146,16 @@ public: virtual int open (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory); + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_component = + TAO_AV_Core::TAO_AV_DATA); virtual int open_default (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory); + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_component = + TAO_AV_Core::TAO_AV_DATA); virtual int close (void); virtual int make_svc_handler (TAO_AV_TCP_Flow_Handler *&handler); @@ -197,7 +201,9 @@ public: TAO_AV_Flow_Protocol_Factory *factory); virtual int connect (TAO_FlowSpec_Entry *entry, - TAO_AV_Transport *&transport); + TAO_AV_Transport *&transport, + TAO_AV_Core::Flow_Component flow_comp = + TAO_AV_Core::TAO_AV_DATA); virtual int close (void); virtual int make_svc_handler (TAO_AV_TCP_Flow_Handler *&handler); protected: diff --git a/TAO/orbsvcs/orbsvcs/AV/Transport.cpp b/TAO/orbsvcs/orbsvcs/AV/Transport.cpp index ce002056426..b9a04fd0598 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Transport.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/Transport.cpp @@ -23,7 +23,6 @@ #include "Transport.i" #endif /* __ACE_INLINE__ */ - //------------------------------------------------------------ // TAO_AV_Transport_Item //------------------------------------------------------------ @@ -81,149 +80,81 @@ TAO_AV_Connector_Registry::open (TAO_Base_StreamEndPoint *endpoint, ACE_ERROR_RETURN ((LM_ERROR, "Protocol was specified without an endpoint\n"), -1); - } else { - TAO_AV_Flow_ProtocolFactorySetItor flow_factory_end = - av_core->flow_protocol_factories ()->end (); + TAO_AV_Flow_Protocol_Factory *flow_factory = + av_core->get_flow_protocol_factory (flow_protocol); + TAO_AV_Transport_Factory *transport_factory = + av_core->get_transport_factory (transport_protocol); - for (TAO_AV_Flow_ProtocolFactorySetItor flow_factory = - av_core->flow_protocol_factories ()->begin (); - flow_factory != flow_factory_end; - ++flow_factory) + if ((flow_factory != 0) && (transport_factory != 0)) { - if ((*flow_factory)->factory ()->match_protocol (flow_protocol)) - { - // @@Naga:Instead of making a new connector every time we should try and see if a connector exists - // for this transport already and hence we can reuse it. - TAO_AV_TransportFactorySetItor transport_factory_end = - av_core->transport_factories ()->end (); - - for (TAO_AV_TransportFactorySetItor transport_factory = - av_core->transport_factories ()->begin (); - transport_factory != transport_factory_end; - ++transport_factory) - { + // @@Naga:Instead of making a new connector every time we should try and see if a connector exists + // for this transport already and hence we can reuse it. - if ((*transport_factory)->factory ()->match_protocol (transport_protocol)) - { - TAO_AV_Connector *connector = - (*transport_factory)->factory ()->make_connector (); - if (connector != 0) - { - // add connector to list. - this->connectors_.insert (connector); + TAO_AV_Connector *connector = transport_factory->make_connector (); - if (connector->open (endpoint, - av_core, - (*flow_factory)->factory ()) == -1) - return -1; + if (connector != 0) + { + // add connector to list. + this->connectors_.insert (connector); + + if (connector->open (endpoint, + av_core, + flow_factory) == -1) + return -1; + + TAO_AV_Transport *transport = 0; + if (connector->connect (entry, + transport, + TAO_AV_Core::TAO_AV_DATA) == -1) + return -1; + entry->transport (transport); + } + else + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Unable to create an " + "connector for <%s>\n", + entry->flowname ()), + -1); - TAO_AV_Transport *transport = 0; - if (connector->connect (entry, - transport) == -1) - return -1; - entry->transport (transport); - break; - } - else - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Unable to create an " - "connector for <%s>\n", - entry->flowname ()), - -1); - } - else - continue; - } - // Now check if the flow factory has a control flow factory. - const char *control_factory_name - = (*flow_factory)->factory ()->control_flow_factory (); + // Now see if the flow factory has a control flow factory. + TAO_AV_Flow_Protocol_Factory *control_flow_factory = + av_core->get_flow_protocol_factory(flow_factory->control_flow_factory ()); - if (control_factory_name != 0) - { + if (control_flow_factory != 0) + { + TAO_AV_Connector *control_connector = + transport_factory->make_connector (); - TAO_AV_Flow_ProtocolFactorySetItor control_factory_end = - av_core->flow_protocol_factories ()->end (); + if (control_connector != 0) + { + // add connector to list. + this->connectors_.insert (control_connector); - for (TAO_AV_Flow_ProtocolFactorySetItor control_flow_factory = - av_core->flow_protocol_factories ()->begin (); - control_flow_factory != control_factory_end; - ++control_flow_factory) - { - if ((*control_flow_factory)->factory ()->match_protocol (control_factory_name)) - { - char control_flowname [BUFSIZ]; - ACE_OS::sprintf (control_flowname,"%s_control",entry->flowname ()); - // Address will be one port number above the data port. - // @@ This requires a more generic solution. This is a hack. - TAO_Tokenizer address_str (CORBA::string_dup (entry->address_str ()),':'); - int port = ACE_OS::atoi (address_str [1]); - // Increment the port. - port++; - char control_addr [BUFSIZ]; - ACE_OS::sprintf (control_addr,"%s=%s:%d", - entry->carrier_protocol_str (), - address_str[0],port); - TAO_Forward_FlowSpec_Entry *control_entry = 0; - // We want to have the control entry as producer - // so timeout events will happen. - ACE_NEW_RETURN (control_entry, - TAO_Forward_FlowSpec_Entry (control_flowname, - "IN", - entry->format (), - entry->flow_protocol_str (), - control_addr), - -1); - // Add the control entry to the flow_spec_set that's passed so that the control entry - // will also be called during flow starts and stops. except that if the user specifies - // a flowspec in start then the control entry may not be in that but it has to be started - // if the flowspec has the associated data flow entry. @@ We'll leave this matter for now. - flow_spec_set.insert (control_entry); - for (TAO_AV_TransportFactorySetItor transport_factory = - av_core->transport_factories ()->begin (); - transport_factory != transport_factory_end; - ++transport_factory) - { - if ((*transport_factory)->factory ()->match_protocol (transport_protocol)) - { - TAO_AV_Connector *connector = - (*transport_factory)->factory ()->make_connector (); - if (connector != 0) - { - // add connector to list. - this->connectors_.insert (connector); - - if (connector->open (endpoint, - av_core, - (*control_flow_factory)->factory ()) == -1) - return -1; - TAO_AV_Transport *transport = 0; - if (connector->connect (control_entry, - transport) == -1) - return -1; - control_entry->transport (transport); - break; - } - else - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Unable to create an " - "connector for <%s>\n", - control_entry->flowname ()), - -1); - } - else - continue; - } - // Now set the control object on the data flow object. - entry->protocol_object ()->control_object (control_entry->protocol_object ()); - } - } + if (control_connector->open (endpoint, + av_core, + control_flow_factory) == -1) + return -1; + + TAO_AV_Transport *control_transport = 0; + if (control_connector->connect (entry, + control_transport, + TAO_AV_Core::TAO_AV_CONTROL) == -1) + return -1; + entry->control_transport (control_transport); + + // Now set the control object on the data flow object. + entry->protocol_object ()->control_object (entry->control_protocol_object ()); } + else + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Unable to create an " + "connector for <%s>\n", + entry->flowname ()), + -1); } - else - continue; } } } @@ -267,6 +198,7 @@ TAO_AV_Acceptor_Registry::TAO_AV_Acceptor_Registry (void) TAO_AV_Acceptor_Registry::~TAO_AV_Acceptor_Registry (void) { + this->close_all(); } int @@ -303,145 +235,72 @@ TAO_AV_Acceptor_Registry::open (TAO_Base_StreamEndPoint *endpoint, if (address == 0) { retv = this->open_default (endpoint, - av_core, - entry); + av_core, + entry); if(retv < 0) return retv; continue; } else { - // Now get the list of avaliable protocol factories. - TAO_AV_Flow_ProtocolFactorySetItor flow_factory_end = - av_core->flow_protocol_factories ()->end (); - - for (TAO_AV_Flow_ProtocolFactorySetItor flow_factory = - av_core->flow_protocol_factories ()->begin (); - flow_factory != flow_factory_end; - ++flow_factory) + TAO_AV_Flow_Protocol_Factory *flow_factory = + av_core->get_flow_protocol_factory (flow_protocol); + + if (flow_protocol != 0) { - if ((*flow_factory)->factory ()->match_protocol (flow_protocol)) + TAO_AV_Transport_Factory *transport_factory = + av_core->get_transport_factory (transport_protocol); + + if (transport_protocol != 0) { - TAO_AV_TransportFactorySetItor transport_factory_end = - av_core->transport_factories ()->end (); - - //int i = 1; - for (TAO_AV_TransportFactorySetItor transport_factory = - av_core->transport_factories ()->begin (); - transport_factory != transport_factory_end; - ++transport_factory) + TAO_AV_Acceptor *acceptor = transport_factory->make_acceptor (); + if (acceptor != 0) { + // add acceptor to list. + this->acceptors_.insert (acceptor); + + if (acceptor->open (endpoint, + av_core, + entry, + flow_factory, + TAO_AV_Core::TAO_AV_DATA) == -1) + return -1; - if ((*transport_factory)->factory ()->match_protocol (transport_protocol)) + TAO_AV_Flow_Protocol_Factory *control_flow_factory = + av_core->get_flow_protocol_factory (flow_factory->control_flow_factory ()); + + if (control_flow_factory != 0) { - TAO_AV_Acceptor *acceptor = - (*transport_factory)->factory ()->make_acceptor (); + TAO_AV_Acceptor *acceptor = transport_factory->make_acceptor (); if (acceptor != 0) { - // add acceptor to list. - this->acceptors_.insert (acceptor); - if (acceptor->open (endpoint, av_core, entry, - (*flow_factory)->factory ()) == -1) + control_flow_factory, + TAO_AV_Core::TAO_AV_CONTROL) == -1) return -1; - break; - } - else - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Unable to create an " - "acceptor for <%s>\n", - entry->flowname ()), - -1); - } - else - continue; - } - // Now check if the flow factory has a control flow factory. - const char *control_factory_name - = (*flow_factory)->factory ()->control_flow_factory (); + // add acceptor to list. + this->acceptors_.insert (acceptor); - if (control_factory_name != 0) - { - TAO_AV_Flow_ProtocolFactorySetItor control_factory_end = - av_core->flow_protocol_factories ()->end (); + entry->protocol_object ()->control_object (entry->control_protocol_object ()); - for (TAO_AV_Flow_ProtocolFactorySetItor control_flow_factory = - av_core->flow_protocol_factories ()->begin (); - control_flow_factory != control_factory_end; - ++control_flow_factory) - { - if ((*control_flow_factory)->factory ()->match_protocol (control_factory_name)) - { - char control_flowname [BUFSIZ]; - ACE_OS::sprintf (control_flowname,"%s_control",entry->flowname ()); - // Address will be one port number above the data port. - // @@ This requires a more generic solution. This is a hack. - TAO_Tokenizer address_str (CORBA::string_dup (entry->address_str ()),':'); - int port = ACE_OS::atoi (address_str [1]); - // Increment the port. - port++; - char control_addr [BUFSIZ]; - ACE_OS::sprintf (control_addr,"%s=%s:%d", - entry->carrier_protocol_str (), - address_str[0],port); - TAO_Forward_FlowSpec_Entry *control_entry = 0; - // We want to have the control entry as producer - // so timeout events will happen. - ACE_NEW_RETURN (control_entry, - TAO_Forward_FlowSpec_Entry (control_flowname, - "IN", - entry->format (), - entry->flow_protocol_str (), - control_addr), - -1); - // Add the control entry to the flow_spec_set that's passed so that the control entry - // will also be called during flow starts and stops. except that if the user specifies - // a flowspec in start then the control entry may not be in that but it has to be started - // if the flowspec has the associated data flow entry. @@ We'll leave this matter for now. - flow_spec_set.insert (control_entry); - TAO_AV_TransportFactorySetItor transport_factory_end = - av_core->transport_factories ()->end (); - for (TAO_AV_TransportFactorySetItor transport_factory = - av_core->transport_factories ()->begin (); - transport_factory != transport_factory_end; - ++transport_factory) - { - if ((*transport_factory)->factory ()->match_protocol (transport_protocol)) - { - TAO_AV_Acceptor *acceptor = - (*transport_factory)->factory ()->make_acceptor (); - if (acceptor != 0) - { - // add acceptor to list. - this->acceptors_.insert (acceptor); - - if (acceptor->open (endpoint, - av_core, - control_entry, - (*control_flow_factory)->factory ()) == -1) - return -1; - break; - } - else - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Unable to create an " - "acceptor for <%s>\n", - entry->flowname ()), - -1); - } - else - continue; - } - // Now set the control object on the data flow object. - entry->protocol_object ()->control_object (control_entry->protocol_object ()); - } + } + else + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Unable to create an " + "acceptor for <%s>\n", + entry->flowname ()), + -1); } } + else + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Unable to create an " + "acceptor for <%s>\n", + entry->flowname ()), + -1); } - else - continue; } } } @@ -460,102 +319,100 @@ TAO_AV_Acceptor_Registry::open_default (TAO_Base_StreamEndPoint *endpoint, // No endpoints were specified, we let each protocol pick its own // default... - TAO_AV_Flow_ProtocolFactorySetItor flow_factory_end = - av_core->flow_protocol_factories ()->end (); - const char *flow_protocol = entry->flow_protocol_str (); const char *transport_protocol = entry->carrier_protocol_str (); if (ACE_OS::strcmp (flow_protocol,"") == 0) flow_protocol = transport_protocol; - // loop through loaded protocols looking for protocol_prefix - TAO_AV_Flow_ProtocolFactorySetItor flow_factory - = av_core->flow_protocol_factories ()->begin (); + TAO_AV_Flow_Protocol_Factory *flow_factory = + av_core->get_flow_protocol_factory (flow_protocol); - TAO_AV_TransportFactorySetItor transport_factory - = av_core->transport_factories ()->begin (); + // No matching flow protocol. + if (flow_factory == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO (%P|%t) Unable to match protocol prefix " + "for <%s>\n", + flow_protocol), + -1); - for (; - flow_factory != flow_factory_end; - ++flow_factory) - { - if (!(*flow_factory)->factory ()->match_protocol (flow_protocol)) - { - // If we have no matching protocol then keep searching - // for one until the entire list of protocols has been - // searched. + if (TAO_debug_level > 0) + ACE_DEBUG((LM_DEBUG, "(%N,%l) Matched flow_protocol: %s, Looking for transport protocol: %s\n", flow_protocol, transport_protocol)); + + TAO_AV_Transport_Factory *transport_factory = + av_core->get_transport_factory (transport_protocol); - if (TAO_debug_level > 0) - ACE_ERROR ((LM_ERROR, + if (transport_factory == 0) + ACE_ERROR_RETURN ((LM_ERROR, "TAO (%P|%t) Unable to match protocol prefix " "for <%s>\n", - flow_protocol)); - continue; - } - else - { - if (TAO_debug_level > 0) - ACE_DEBUG((LM_DEBUG, "(%N,%l) Matched flow_protocol: %s, Looking for transport protocol: %s\n", flow_protocol, transport_protocol)); - TAO_AV_TransportFactorySetItor transport_factory_end = - av_core->transport_factories ()->end (); - - int matched_transport = 0; - for (;transport_factory != transport_factory_end; - ++transport_factory) - { - if (!(*transport_factory)->factory ()->match_protocol (transport_protocol)) - { - // If we have no matching protocol then keep searching - // for one until the entire list of protocols has been - // searched. - - if (TAO_debug_level > 0) - ACE_ERROR ((LM_ERROR, - "TAO (%P|%t) Unable to match protocol prefix " - "for <%s>\n", - transport_protocol)); - continue; - } + transport_protocol), + -1); + + // make an acceptor + TAO_AV_Acceptor *acceptor = + transport_factory->make_acceptor(); + + if (acceptor == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO (%P|%t) unable to create " + "an acceptor for <%d>\n", + transport_protocol), + -1); + + if (acceptor->open_default (endpoint, + av_core, + entry, + flow_factory, + TAO_AV_Core::TAO_AV_DATA) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO (%P|%t) unable to open " + "default acceptor for <%s>%p\n", + flow_protocol), + -1); + + this->acceptors_.insert (acceptor); + + const char *control_flow_factory_name = flow_factory->control_flow_factory (); + + if (control_flow_factory_name != 0) + { - matched_transport = 1; + TAO_AV_Flow_Protocol_Factory *control_flow_factory = + av_core->get_flow_protocol_factory (control_flow_factory_name); - // got it, make an acceptor - TAO_AV_Acceptor *acceptor = - (*transport_factory)->factory ()->make_acceptor (); + if (control_flow_factory == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO (%P|%t) Unable to match control flow " + "for <%s>\n", + control_flow_factory_name), + -1); - if (acceptor == 0) - { - if (TAO_debug_level > 0) - ACE_ERROR ((LM_ERROR, - "TAO (%P|%t) unable to create " - "an acceptor for <%d>\n", - transport_protocol)); - continue; - } + TAO_AV_Acceptor *control_acceptor = transport_factory->make_acceptor (); + + if (control_acceptor == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO (%P|%t) unable to create " + "an acceptor for <%d>\n", + transport_protocol), + -1); - if (acceptor->open_default (endpoint, + if (control_acceptor->open_default (endpoint, av_core, entry, - (*flow_factory)->factory ()) == -1) - { - if (TAO_debug_level > 0) - ACE_ERROR ((LM_ERROR, - "TAO (%P|%t) unable to open " - "default acceptor for <%s>%p\n", - (*transport_factory)->name ().c_str (), "")); - continue; - } + control_flow_factory, + TAO_AV_Core::TAO_AV_CONTROL) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO (%P|%t) unable to open " + "default acceptor for <%s>%p\n", + transport_protocol), + -1); - this->acceptors_.insert (acceptor); - } - if( matched_transport == 0 ){ - ACE_ERROR ((LM_ERROR, "(%P|%t), %N:%l could not match transport protocol: %s\n", - transport_protocol)); - return -1; - } - } + this->acceptors_.insert (control_acceptor); + + entry->protocol_object ()->control_object (entry->control_protocol_object ()); } + if (this->acceptors_.size () == 0) { if (TAO_debug_level > 0) @@ -620,6 +477,10 @@ TAO_AV_Flow_Handler::TAO_AV_Flow_Handler (void) { } +TAO_AV_Flow_Handler::~TAO_AV_Flow_Handler(void) +{ +} + int TAO_AV_Flow_Handler::set_remote_address (ACE_Addr * /* address */) { @@ -649,19 +510,36 @@ TAO_AV_Flow_Handler::schedule_timer (void) { ACE_Event_Handler *event_handler = this->event_handler (); ACE_Time_Value *tv = 0; - this->callback_->get_timeout (tv, - this->timeout_arg_); + + this->callback_->get_timeout (tv, this->timeout_arg_); if (tv == 0) return 0; - this->timer_id_ = event_handler->reactor ()->schedule_timer (event_handler, - 0, - *tv); + +// this->timer_id_ = event_handler->reactor ()->schedule_timer (event_handler, + this->timer_id_ = + TAO_AV_CORE::instance()->reactor ()->schedule_timer (event_handler, + 0, + *tv); + + delete tv; + if (this->timer_id_ < 0) return -1; return 0; } + +int +TAO_AV_Flow_Handler::cancel_timer (void) +{ + ACE_Event_Handler *event_handler = this->event_handler (); + TAO_AV_CORE::instance()->reactor ()->cancel_timer (this->timer_id_); + + return 0; +} + + int TAO_AV_Flow_Handler::stop (TAO_FlowSpec_Entry::Role role) { @@ -688,13 +566,17 @@ TAO_AV_Flow_Handler::handle_timeout (const ACE_Time_Value & /*tv*/, this->callback_->handle_timeout (this->timeout_arg_); ACE_Event_Handler *event_handler = this->event_handler (); ACE_Time_Value *timeout = 0; - this->callback_->get_timeout (timeout, - this->timeout_arg_); + + this->callback_->get_timeout (timeout, this->timeout_arg_); if (timeout == 0) return 0; + this->timer_id_ = event_handler->reactor ()->schedule_timer (event_handler, 0, *timeout); + + delete timeout; + return 0; } diff --git a/TAO/orbsvcs/orbsvcs/AV/Transport.h b/TAO/orbsvcs/orbsvcs/AV/Transport.h index b418638e038..767cf800fb0 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Transport.h +++ b/TAO/orbsvcs/orbsvcs/AV/Transport.h @@ -24,6 +24,7 @@ #include "ace/SOCK_Dgram.h" #include "orbsvcs/AV/AV_export.h" #include "FlowSpec_Entry.h" +#include "AV_Core.h" // Forward declarations. class TAO_AV_Core; @@ -106,12 +107,14 @@ public: /// Constructor. TAO_AV_Flow_Handler (void); + virtual ~TAO_AV_Flow_Handler (void); /// Start/stop the flow handler. virtual int start (TAO_FlowSpec_Entry::Role role); virtual int stop (TAO_FlowSpec_Entry::Role role); /// Schedule timer. Uses the get_timeout method on the callback. virtual int schedule_timer (void); + virtual int cancel_timer (void); /// get the transport. TAO_AV_Transport *transport (void); @@ -124,7 +127,7 @@ public: void callback (TAO_AV_Callback *callback); /// Handle timeout. called from reactor. - int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0); + virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0); /// set the remote address. virtual int set_remote_address (ACE_Addr *address); @@ -212,12 +215,14 @@ public: virtual int open (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) = 0; + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) = 0; virtual int open_default (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) = 0; + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) = 0; const char *flowname (); virtual int close (void) = 0; @@ -243,7 +248,8 @@ public: TAO_AV_Flow_Protocol_Factory *factory) = 0; virtual int connect (TAO_FlowSpec_Entry *entry, - TAO_AV_Transport *&transport) = 0; + TAO_AV_Transport *&transport, + TAO_AV_Core::Flow_Component flow_component) = 0; virtual int close (void) = 0; protected: diff --git a/TAO/orbsvcs/orbsvcs/AV/UDP.cpp b/TAO/orbsvcs/orbsvcs/AV/UDP.cpp index fcee016b6f4..6416a1eef3a 100644 --- a/TAO/orbsvcs/orbsvcs/AV/UDP.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/UDP.cpp @@ -34,8 +34,7 @@ TAO_AV_UDP_Flow_Handler::transport (void) int TAO_AV_UDP_Flow_Handler::handle_input (ACE_HANDLE /*fd*/) { - this->protocol_object_->handle_input (); - return 0; + return this->protocol_object_->handle_input (); } int @@ -98,7 +97,7 @@ TAO_AV_UDP_Flow_Handler::change_qos(AVStreams::QoS qos) if(!((dscp >= 0) && (dscp <= 63))) { dscp_flag = 0; - ACE_DEBUG((LM_DEBUG, "(%N,%l) ECN value can only be (0-3) not %d\n", ecn)); + ACE_DEBUG((LM_DEBUG, "(%N,%l) ECN value can only be (0-3) not %d\n", ecn)); return -1; } } @@ -225,7 +224,7 @@ TAO_AV_UDP_Transport::send (const ACE_Message_Block *mblk, ACE_Time_Value *) // we should set IOV_MAX to that limit. if (iovcnt == IOV_MAX) { - n = this->handler_->get_socket ()->send ((const iovec *) iov, + n = this->handler_->get_socket ()->send ((const iovec *) iov, iovcnt, this->peer_addr_); @@ -326,22 +325,32 @@ TAO_AV_UDP_Acceptor::activate_svc_handler (TAO_AV_Flow_Handler *handler) ACE_Event_Handler *event_handler = handler->event_handler (); int result = this->av_core_->reactor ()->register_handler (event_handler, ACE_Event_Handler::READ_MASK); - return result; + + if (this->flow_component_ == TAO_AV_Core::TAO_AV_CONTROL) + handler->schedule_timer (); + + return result; } int TAO_AV_UDP_Acceptor::open (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) { if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Acceptor::open ")); this->av_core_ = av_core; this->endpoint_ = endpoint; this->entry_ = entry; + this->flow_component_ = flow_comp; this->flow_protocol_factory_ = factory; this->flowname_ = entry->flowname (); - ACE_INET_Addr *inet_addr = (ACE_INET_Addr *) entry->address (); + ACE_INET_Addr *inet_addr; + if (flow_comp == TAO_AV_Core::TAO_AV_DATA) + inet_addr = (ACE_INET_Addr *) entry->address (); + else + inet_addr = (ACE_INET_Addr *) entry->control_address (); char buf[BUFSIZ]; inet_addr->addr_to_string (buf, @@ -352,7 +361,7 @@ TAO_AV_UDP_Acceptor::open (TAO_Base_StreamEndPoint *endpoint, "TAO_AV_UDP_Acceptor::open: %s", buf)); - int result = this->open_i (inet_addr); + int result = this->open_i (inet_addr, 0); if (result < 0) return result; @@ -363,121 +372,141 @@ int TAO_AV_UDP_Acceptor::open_default (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory) + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp) { this->av_core_ = av_core; this->endpoint_ = endpoint; this->entry_ = entry; + this->flow_component_ = flow_comp; this->flow_protocol_factory_ = factory; this->flowname_ = entry->flowname (); - ACE_INET_Addr *address; - ACE_NEW_RETURN (address, - ACE_INET_Addr ("0"), - -1); - int result = this->open_i (address); + ACE_INET_Addr *address = 0; + if (flow_comp == TAO_AV_Core::TAO_AV_DATA) + ACE_NEW_RETURN (address, + ACE_INET_Addr ("0"), + -1); + int result = this->open_i (address, 1); if (result < 0) return result; + return 0; } int -TAO_AV_UDP_Acceptor::open_i (ACE_INET_Addr *inet_addr) +TAO_AV_UDP_Acceptor::open_i (ACE_INET_Addr *inet_addr, + int is_default_addr) { int result = -1; ACE_INET_Addr *local_addr; TAO_AV_Flow_Handler *flow_handler = 0; - if (this->entry_->is_multicast ()) + // if using a default address and this is the control flow component, the + // handler and local address are already set in the flow spec entry + if (is_default_addr && + (this->flow_component_ == TAO_AV_Core::TAO_AV_CONTROL) && + (ACE_OS::strcasecmp(this->entry_->flow_protocol_str (), "RTP") == 0)) { - TAO_AV_UDP_MCast_Flow_Handler *handler; - ACE_NEW_RETURN (handler, - TAO_AV_UDP_MCast_Flow_Handler, - -1); - - flow_handler = handler; - result = handler->get_mcast_socket ()->subscribe (*inet_addr); - - if (result < 0) - ACE_ERROR_RETURN ((LM_ERROR, - "TAO_AV_UDP_MCast_connector::subscribe failed\n"), - -1); + flow_handler = this->entry_->control_handler (); - // Now disable Multicast loopback. - // @@Should we make this a policy? -#ifdef ACE_HAS_IP_MULTICAST - if (handler->get_mcast_socket ()->set_option (IP_MULTICAST_LOOP, - 0) < 0) - if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_MCast_Acceptor::multicast loop disable failed\n")); - // @@ This should also be policies. -#endif /*ACE_HAS_IP_MULTICAST*/ - int bufsize = 80 * 1024; - if (handler->get_mcast_socket ()->ACE_SOCK::set_option (SOL_SOCKET, - SO_RCVBUF, - (char *)&bufsize, - sizeof(bufsize)) < 0) - { - bufsize = 32 * 1024; - if (handler->get_mcast_socket ()->ACE_SOCK::set_option (SOL_SOCKET, - SO_RCVBUF, - (char *)&bufsize, - sizeof(bufsize)) < 0) - perror("SO_RCVBUF"); - } - ACE_NEW_RETURN (local_addr, - ACE_INET_Addr (*inet_addr), - -1); + local_addr = ACE_dynamic_cast (ACE_INET_Addr*, + this->entry_->get_local_control_addr ()); } else { - TAO_AV_UDP_Flow_Handler *handler; - ACE_NEW_RETURN (handler, - TAO_AV_UDP_Flow_Handler, - -1); - flow_handler = handler; - int result = handler->open (*inet_addr); - if (result < 0) - ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_UDP_Acceptor::handler_open failed\n"),-1); - // set the socket buffer sizes to 64k. - int sndbufsize = ACE_DEFAULT_MAX_SOCKET_BUFSIZ; - int rcvbufsize = ACE_DEFAULT_MAX_SOCKET_BUFSIZ; + // this variable is only used for RTP/UDP; RFC 1889 requires an even/odd + // consecutive port pair + int get_new_port = 1; - if (handler->get_socket ()->set_option (SOL_SOCKET, - SO_SNDBUF, - (void *) &sndbufsize, - sizeof (sndbufsize)) == -1 - && errno != ENOTSUP) - return 0; + while (get_new_port) + { + // assume the ports will be OK + get_new_port = 0; - else if (handler->get_socket ()->set_option (SOL_SOCKET, - SO_RCVBUF, - (void *) &rcvbufsize, - sizeof (rcvbufsize)) == -1 - && errno != ENOTSUP) - return 0; + result = TAO_AV_UDP_Connection_Setup::setup (flow_handler, + inet_addr, + local_addr, + this->entry_->is_multicast (), + TAO_AV_UDP_Connection_Setup::ACCEPTOR); - if (result < 0) - ACE_ERROR_RETURN ((LM_ERROR,"SOCK_Dgram::open failed\n"),-1); - ACE_NEW_RETURN (local_addr, - ACE_INET_Addr, - -1); - result = handler->get_socket ()->get_local_addr (*local_addr); - if (result < 0) - ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_Dgram_Connector::open: get_local_addr failed\n"),result); - local_addr->set (local_addr->get_port_number (), - local_addr->get_host_name ()); + local_addr->set (local_addr->get_port_number (), + local_addr->get_host_name ()); + + if (is_default_addr) + { + if ((ACE_OS::strcasecmp(this->entry_->flow_protocol_str (), "RTP") == 0) && + (this->flow_component_ == TAO_AV_Core::TAO_AV_DATA)) + { + if (is_default_addr && local_addr->get_port_number ()%2 != 0) + { + // RTP port should be even + delete local_addr; + delete flow_handler; + get_new_port = 1; + } + else + { + ACE_INET_Addr *local_control_addr; + ACE_INET_Addr *control_inet_addr; + TAO_AV_Flow_Handler *control_flow_handler = 0; + + ACE_NEW_RETURN (control_inet_addr, + ACE_INET_Addr ("0"), + -1); + + TAO_AV_UDP_Connection_Setup::setup(control_flow_handler, + control_inet_addr, + local_control_addr, + this->entry_->is_multicast (), + TAO_AV_UDP_Connection_Setup::ACCEPTOR); + + if (local_control_addr->get_port_number () != + local_addr->get_port_number () +1) + { + delete control_inet_addr; + delete local_addr; + delete flow_handler; + delete local_control_addr; + delete control_flow_handler; + get_new_port = 1; + } + else + { + this->entry_->control_address (control_inet_addr); + this->entry_->set_local_control_addr (local_control_addr); + this->entry_->control_handler (control_flow_handler); + } + } + } + } + } } + TAO_AV_Protocol_Object *object = this->flow_protocol_factory_->make_protocol_object (this->entry_, this->endpoint_, flow_handler, flow_handler->transport ()); flow_handler->protocol_object (object); - // callback->protocol_object (object); -// this->endpoint_->set_protocol_object (this->flowname_.c_str (), -// object); - this->endpoint_->set_flow_handler (this->flowname_.c_str (),flow_handler); - this->entry_->protocol_object (object); + + if (this->flow_component_ == TAO_AV_Core::TAO_AV_DATA) + { + this->endpoint_->set_flow_handler (this->flowname_.c_str (),flow_handler); + + this->entry_->protocol_object (object); + this->entry_->set_local_addr (local_addr); + this->entry_->handler (flow_handler); + this->entry_->address (inet_addr); + } + else + { + this->endpoint_->set_control_flow_handler (this->flowname_.c_str (),flow_handler); + + this->entry_->control_protocol_object (object); + this->entry_->set_local_control_addr (local_addr); + this->entry_->control_handler (flow_handler); + } char buf[BUFSIZ]; local_addr->addr_to_string (buf,BUFSIZ); @@ -486,10 +515,7 @@ TAO_AV_UDP_Acceptor::open_i (ACE_INET_Addr *inet_addr) "TAO_AV_UDP_ACCEPTOR::open:%s \n", buf)); - this->entry_->set_local_addr (local_addr); - this->entry_->handler (flow_handler); - -// call activate svc handler. + // call activate svc handler. return this->activate_svc_handler (flow_handler); } @@ -525,21 +551,175 @@ TAO_AV_UDP_Connector::open (TAO_Base_StreamEndPoint *endpoint, int TAO_AV_UDP_Connector::connect (TAO_FlowSpec_Entry *entry, - TAO_AV_Transport *&transport) + TAO_AV_Transport *&transport, + TAO_AV_Core::Flow_Component flow_component) { - ACE_INET_Addr *local_addr; int result = -1; this->entry_ = entry; this->flowname_ = entry->flowname (); + this->flow_component_ = flow_component; - ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*, - entry->address ()); + ACE_INET_Addr *inet_addr; + + if (flow_component == TAO_AV_Core::TAO_AV_DATA) + inet_addr = ACE_dynamic_cast (ACE_INET_Addr*, entry->address ()); + else + inet_addr = ACE_dynamic_cast (ACE_INET_Addr*, entry->control_address ()); TAO_AV_Flow_Handler *flow_handler = 0; - if (entry->is_multicast ()) + // if this is the control flow component, the + // handler and local address are already set in the flow spec entry + if ((flow_component == TAO_AV_Core::TAO_AV_CONTROL) && + (ACE_OS::strcasecmp(this->entry_->flow_protocol_str (), "RTP") == 0) && + !entry->is_multicast ()) + { + flow_handler = this->entry_->control_handler (); + flow_handler->set_remote_address (inet_addr); + + local_addr = ACE_dynamic_cast (ACE_INET_Addr*, + this->entry_->get_local_control_addr ()); + } + else + { + // this variable is only used for RTP/UDP; RFC 1889 requires an even/odd + // consecutive port pair + int get_new_port = 1; + + while (get_new_port) + { + // assume the ports will be OK + get_new_port = 0; + + TAO_AV_UDP_Connection_Setup::setup (flow_handler, + inet_addr, + local_addr, + entry->is_multicast (), + TAO_AV_UDP_Connection_Setup::CONNECTOR); + + if ((ACE_OS::strcasecmp(this->entry_->flow_protocol_str (), "RTP") == 0) && + (flow_component == TAO_AV_Core::TAO_AV_DATA) && + !entry->is_multicast ()) + { + if (local_addr->get_port_number ()%2 != 0) + { + // RTP port should be even + delete local_addr; + delete flow_handler; + get_new_port = 1; + } + else + { + ACE_INET_Addr *local_control_addr; + ACE_INET_Addr *control_inet_addr; + TAO_AV_Flow_Handler *control_flow_handler = 0; + + if (entry->is_multicast ()) + control_inet_addr = ACE_dynamic_cast (ACE_INET_Addr*, + entry->control_address ()) ; + + else + ACE_NEW_RETURN (control_inet_addr, + ACE_INET_Addr ("0"), + -1); + + TAO_AV_UDP_Connection_Setup::setup(control_flow_handler, + control_inet_addr, + local_control_addr, + entry->is_multicast (), + TAO_AV_UDP_Connection_Setup::CONNECTOR); + + if (local_control_addr->get_port_number () != + local_addr->get_port_number () +1) + { + delete local_addr; + delete flow_handler; + delete local_control_addr; + delete control_flow_handler; + get_new_port = 1; + } + else + { + this->entry_->set_local_control_addr (local_control_addr); + this->entry_->control_handler (control_flow_handler); + } + } + } + } + } + + TAO_AV_Protocol_Object *object = + this->flow_protocol_factory_->make_protocol_object (this->entry_, + this->endpoint_, + flow_handler, + flow_handler->transport ()); + + flow_handler->protocol_object (object); + + if (flow_component == TAO_AV_Core::TAO_AV_DATA) + { + this->endpoint_->set_flow_handler (this->flowname_.c_str (), + flow_handler); + this->entry_->protocol_object (object); + entry->set_local_addr (local_addr); + entry->handler (flow_handler); + transport = flow_handler->transport (); + } + else + { + this->endpoint_->set_control_flow_handler (this->flowname_.c_str (), + flow_handler); + this->entry_->control_protocol_object (object); + entry->set_local_control_addr (local_addr); + entry->control_handler (flow_handler); + transport = flow_handler->transport (); + } + + char buf[BUFSIZ]; + local_addr->addr_to_string (buf,BUFSIZ); + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_CONNECTOR::connect:%s \n",buf)); + + // call activate svc handler. + return this->activate_svc_handler (flow_handler); +} + +int +TAO_AV_UDP_Connector::activate_svc_handler (TAO_AV_Flow_Handler *handler) +{ + ACE_Event_Handler *event_handler = handler->event_handler (); + int result = this->av_core_->reactor ()->register_handler (event_handler, + ACE_Event_Handler::READ_MASK); + + if (this->flow_component_ == TAO_AV_Core::TAO_AV_CONTROL) + handler->schedule_timer (); + + return result; +} + +int +TAO_AV_UDP_Connector::close (void) +{ + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_UDP_Connection_Setup +//------------------------------------------------------------ + +int +TAO_AV_UDP_Connection_Setup::setup (TAO_AV_Flow_Handler *&flow_handler, + ACE_INET_Addr *inet_addr, + ACE_INET_Addr *&local_addr, + int is_multicast, + ConnectionType ct) +{ + int result; + + if (is_multicast) { TAO_AV_UDP_MCast_Flow_Handler *handler; ACE_NEW_RETURN (handler, @@ -549,15 +729,16 @@ TAO_AV_UDP_Connector::connect (TAO_FlowSpec_Entry *entry, flow_handler = handler; result = handler->get_mcast_socket ()->subscribe (*inet_addr); - if (result < 0) ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_UDP_MCast_connector::open failed\n"),-1); + // Now disable Multicast loopback. // @@Should we make this a policy? #if defined (ACE_HAS_IP_MULTICAST) if (handler->get_mcast_socket ()->set_option (IP_MULTICAST_LOOP, 0) < 0) - if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_MCast_Acceptor::multicast loop disable failed\n")); + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_MCast_Acceptor::multicast loop disable failed\n")); // @@ This should also be policies. #endif /*ACE_HAS_IP_MULTICAST*/ @@ -575,12 +756,23 @@ TAO_AV_UDP_Connector::connect (TAO_FlowSpec_Entry *entry, perror("SO_RCVBUF"); } ACE_NEW_RETURN (local_addr, - ACE_INET_Addr (*inet_addr), +// ACE_INET_Addr ((u_short) 0), + ACE_INET_Addr ("0"), -1); + + if (ct == ACCEPTOR) + { + result = handler->get_mcast_socket ()->get_local_addr (*local_addr); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_Dgram_Connector::open: get_local_addr failed\n"),result); + + local_addr->set (local_addr->get_port_number (), + local_addr->get_host_name ()); + handler->set_peer_addr (local_addr); + } } else { - ACE_NEW_RETURN (local_addr, ACE_INET_Addr ("0"), -1); @@ -593,7 +785,6 @@ TAO_AV_UDP_Connector::connect (TAO_FlowSpec_Entry *entry, flow_handler = handler; result = handler->open (*local_addr); - if (result < 0) ACE_ERROR_RETURN ((LM_ERROR,"handler::open failed\n"),-1); @@ -607,7 +798,6 @@ TAO_AV_UDP_Connector::connect (TAO_FlowSpec_Entry *entry, sizeof (sndbufsize)) == -1 && errno != ENOTSUP) return 0; - else if (handler->get_socket ()->set_option (SOL_SOCKET, SO_RCVBUF, (void *) &rcvbufsize, @@ -618,53 +808,11 @@ TAO_AV_UDP_Connector::connect (TAO_FlowSpec_Entry *entry, handler->set_remote_address (inet_addr); result = handler->get_socket ()->get_local_addr (*local_addr); - if (result < 0) ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_Dgram_Connector::open: get_local_addr failed\n"),result); - - local_addr->set (local_addr->get_port_number (), - local_addr->get_host_name ()); } - TAO_AV_Protocol_Object *object = - this->flow_protocol_factory_->make_protocol_object (this->entry_, - this->endpoint_, - flow_handler, - flow_handler->transport ()); - flow_handler->protocol_object (object); - - this->endpoint_->set_flow_handler (this->flowname_.c_str (), - flow_handler); - - this->entry_->protocol_object (object); - - char buf[BUFSIZ]; - local_addr->addr_to_string (buf,BUFSIZ); - - if (TAO_debug_level > 0) - ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_CONNECTOR::connect:%s \n",buf)); - - entry->set_local_addr (local_addr); - entry->handler (flow_handler); - transport = flow_handler->transport (); - - // call activate svc handler. - return this->activate_svc_handler (flow_handler); -} - -int -TAO_AV_UDP_Connector::activate_svc_handler (TAO_AV_Flow_Handler *handler) -{ - ACE_Event_Handler *event_handler = handler->event_handler (); - int result = this->av_core_->reactor ()->register_handler (event_handler, - ACE_Event_Handler::READ_MASK); - return result; -} - -int -TAO_AV_UDP_Connector::close (void) -{ - return 0; + return 1; } //------------------------------------------------------------ @@ -821,7 +969,6 @@ TAO_AV_UDP_Flow_Factory::make_protocol_object (TAO_FlowSpec_Entry *entry, endpoint->get_callback (entry->flowname (), callback); - TAO_AV_UDP_Object *object = 0; ACE_NEW_RETURN (object, TAO_AV_UDP_Object (callback, @@ -844,7 +991,6 @@ ACE_STATIC_SVC_DEFINE (TAO_AV_UDP_Flow_Factory, 0) ACE_FACTORY_DEFINE (TAO_AV, TAO_AV_UDP_Factory) - ACE_STATIC_SVC_DEFINE (TAO_AV_UDP_Factory, ACE_TEXT ("UDP_Factory"), ACE_SVC_OBJ_T, diff --git a/TAO/orbsvcs/orbsvcs/AV/UDP.h b/TAO/orbsvcs/orbsvcs/AV/UDP.h index d1817e52c02..b070df990a4 100644 --- a/TAO/orbsvcs/orbsvcs/AV/UDP.h +++ b/TAO/orbsvcs/orbsvcs/AV/UDP.h @@ -91,6 +91,8 @@ public: int iovcnt, ACE_Time_Value *s = 0); + TAO_AV_UDP_Flow_Handler *handler (void) { return this->handler_; } + protected: TAO_AV_UDP_Flow_Handler *handler_; ACE_Addr *addr_; @@ -109,7 +111,7 @@ public: ///Ctor /// Dtor TAO_AV_UDP_Flow_Handler (void); - ~TAO_AV_UDP_Flow_Handler (void); + virtual ~TAO_AV_UDP_Flow_Handler (void); int open (ACE_Addr &address); virtual TAO_AV_Transport *transport (void); virtual int set_remote_address (ACE_Addr *address); @@ -119,7 +121,7 @@ public: const ACE_SOCK_Dgram *get_socket (void) const; virtual ACE_Event_Handler* event_handler (void){ return this; } /// Change the QoS - virtual int change_qos (AVStreams::QoS); + virtual int change_qos (AVStreams::QoS); protected: TAO_AV_Core *av_core_; @@ -140,21 +142,30 @@ public: virtual int open (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory); + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp = + TAO_AV_Core::TAO_AV_DATA); virtual int open_default (TAO_Base_StreamEndPoint *endpoint, TAO_AV_Core *av_core, TAO_FlowSpec_Entry *entry, - TAO_AV_Flow_Protocol_Factory *factory); + TAO_AV_Flow_Protocol_Factory *factory, + TAO_AV_Core::Flow_Component flow_comp = + TAO_AV_Core::TAO_AV_DATA); - virtual int open_i (ACE_INET_Addr *address); + virtual int open_i (ACE_INET_Addr *address, int is_default_open); virtual int close (void); virtual int activate_svc_handler (TAO_AV_Flow_Handler *handler); + + protected: TAO_Base_StreamEndPoint *endpoint_; TAO_FlowSpec_Entry *entry_; TAO_AV_Flow_Protocol_Factory *flow_protocol_factory_; + TAO_AV_Core::Flow_Component flow_component_; + + }; /** @@ -172,7 +183,9 @@ public: TAO_AV_Flow_Protocol_Factory *factory); virtual int connect (TAO_FlowSpec_Entry *entry, - TAO_AV_Transport *&transport); + TAO_AV_Transport *&transport, + TAO_AV_Core::Flow_Component flow_comp = + TAO_AV_Core::TAO_AV_DATA); virtual int activate_svc_handler (TAO_AV_Flow_Handler *handler); virtual int close (void); protected: @@ -180,6 +193,29 @@ protected: TAO_AV_Core *av_core_; TAO_FlowSpec_Entry *entry_; TAO_AV_Flow_Protocol_Factory *flow_protocol_factory_; + TAO_AV_Core::Flow_Component flow_component_; + +}; + +/** + * @class TAO_AV_UDP_Connection_Setup + * @brief This class is a helper for the TAO_AV_UDP_Acceptor and + * TAO_AV_UDP_Connector. It basically just reduces duplicate code. It takes + * the address of the peer in the connection, whether or not it is a multicast + * connection, and whether it is a connector or acceptor; and creates the local + * address and flow handler associated with the connection. + */ +class TAO_AV_Export TAO_AV_UDP_Connection_Setup +{ +public: + /// Indicates whether this setup is for a Connector or an Acceptor + enum ConnectionType {CONNECTOR, ACCEPTOR}; + + static int setup (TAO_AV_Flow_Handler *&flow_handler, + ACE_INET_Addr *inet_addr, + ACE_INET_Addr *&local_addr, + int is_multicast, + ConnectionType ct); }; /** @@ -218,7 +254,7 @@ private: /** * @class TAO_AV_UDP_Flow_Factory - * @brief + * @brief */ class TAO_AV_Export TAO_AV_UDP_Flow_Factory : public TAO_AV_Flow_Protocol_Factory { diff --git a/TAO/orbsvcs/orbsvcs/AV/global.h b/TAO/orbsvcs/orbsvcs/AV/global.h new file mode 100644 index 00000000000..2e98cc6315b --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/global.h @@ -0,0 +1,31 @@ +/* $Id$ */ +/* GLOBAL.H - RSAREF types and constants + */ + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 0 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word */ +typedef unsigned long int UINT4; + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif diff --git a/TAO/orbsvcs/orbsvcs/AV/md5.h b/TAO/orbsvcs/orbsvcs/AV/md5.h new file mode 100644 index 00000000000..33b19b52299 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/md5.h @@ -0,0 +1,49 @@ +/* $Id$ */ +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +#ifdef __cplusplus +extern "C" { +#endif + +//void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Init (MD5_CTX *); +//void MD5Update PROTO_LIST +// ((MD5_CTX *, unsigned char *, unsigned int)); +void MD5Update (MD5_CTX *, unsigned char *, unsigned int); +//void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); +void MD5Final (unsigned char [16], MD5_CTX *); + +#ifdef __cplusplus +} +#endif + diff --git a/TAO/orbsvcs/orbsvcs/AV/md5c.c b/TAO/orbsvcs/orbsvcs/AV/md5c.c new file mode 100644 index 00000000000..b13d382289e --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/md5c.c @@ -0,0 +1,345 @@ +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include "global.h" +#include "md5.h" + +/* Constants for MD5Transform routine. + */ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/*static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); +static void Encode PROTO_LIST + ((unsigned char *, UINT4 *, unsigned int)); +static void Decode PROTO_LIST + ((UINT4 *, unsigned char *, unsigned int)); +static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); +static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));*/ +static void MD5Transform (UINT4 [4], unsigned char [64]); +static void Encode (unsigned char *, UINT4 *, unsigned int); +static void Decode (UINT4 *, unsigned char *, unsigned int); +static void MD5_memcpy (POINTER, POINTER, unsigned int); +static void MD5_memset (POINTER, int, unsigned int); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void MD5Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void MD5Update (context, input, inputLen) +MD5_CTX *context; /* context */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)&input[i], + inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void MD5Final (digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. +*/ + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (state, block) +UINT4 state[4]; +unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + +*/ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (output, input, len) +UINT4 *output; +unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +POINTER input; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. + */ +static void MD5_memset (output, value, len) +POINTER output; +int value; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + diff --git a/TAO/orbsvcs/orbsvcs/AV/source.cpp b/TAO/orbsvcs/orbsvcs/AV/source.cpp deleted file mode 100644 index 0f214e70d1d..00000000000 --- a/TAO/orbsvcs/orbsvcs/AV/source.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright (c) 1994-1995 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and the Network Research Group at - * Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -// $Id$ -#include "ace/OS.h" -#include "RTCP.h" -#include "source.h" - -#if !defined (__ACE_INLINE__) -#include "source.i" -#endif /* __ACE_INLINE__ */ - -/* gray out src if no ctrl msgs for this many consecutive update intervals */ -#define CTRL_IDLE 8. - -#define SHASH(a) ((int)((((a) >> 20) ^ ((a) >> 10) ^ (a)) & (TAO_AV_SOURCE_HASH-1))) - -extern "C" int -compare_func (const void* v0, const void* v1) -{ - return TAO_AV_SourceManager::compare (v0, v1); -} - -TAO_AV_Source::TAO_AV_Source (ACE_UINT32 srcid, ACE_UINT32 ssrc, ACE_UINT32 addr) - : next_ (0), - hlink_ (0), - srcid_ (srcid), - ssrc_ (ssrc), - addr_ (addr), - sts_data_ (0), - sts_ctrl_ (0), - fs_ (0), - cs_ (0), - np_ (0), - nf_ (0), - nb_ (0), - nm_ (0), - snp_ (0), - sns_ (0), - ndup_ (0), - nrunt_ (0), - badsesslen_ (0), - badsessver_ (0), - badsessopt_ (0), - badsdes_ (0), - badbye_ (0), - format_ (-1), - mute_ (0), - lost_ (0), - busy_ (0), - ismixer_ (0) -{ - lts_data_.tv_sec = 0; - lts_data_.tv_usec = 0; - lts_ctrl_.tv_sec = 0; - lts_ctrl_.tv_usec = 0; - lts_done_.tv_sec = 0; - lts_done_.tv_usec = 0; - /* - * Put an invalid seqno in each slot to guarantee that - * we don't count any initial dups by mistake. - */ - int i; - for (i = 0; i < TAO_AV_SOURCE_NSEQ; ++i) - seqno_[i] = i + 1; - - for (i = 0; i <= RTCP_SDES_MAX; ++i) - sdes_[i] = 0; -} - -TAO_AV_Source::~TAO_AV_Source () -{ - int i; - for (i = 0; i <= RTCP_SDES_MAX; ++i) - delete sdes_[i]; -} - -void -TAO_AV_Source::sdes (int t, const char* s) -{ - char** p = &sdes_[t]; - if (*p != 0 && strcmp (*p, s) == 0) - /* no change */ - return; - - delete *p; - int n = strlen (s); - if (n > 254) - n = 254; - ACE_NEW (*p, - char[n + 1]); - strncpy (*p, s, n + 1); -} - -char* -onestat (char* cp, const char* name, u_long v) -{ - sprintf (cp, "%s %lu ", name, v); - return (cp + strlen (cp)); -} - -char* -TAO_AV_Source::stats (char* cp) const -{ - cp = onestat (cp, "Kilobits", nb () >> (10-3)); - cp = onestat (cp, "Frames", nf ()); - cp = onestat (cp, "Packets", np ()); - int missing = ns () - np (); - if (missing < 0) - missing = 0; - cp = onestat (cp, "Missing", missing); - cp = onestat (cp, "Misordered", nm ()); - cp = onestat (cp, "Runts", runt ()); - cp = onestat (cp, "Dups", dups ()); - cp = onestat (cp, "Bad-S-Len", badsesslen ()); - cp = onestat (cp, "Bad-S-Ver", badsessver ()); - cp = onestat (cp, "Bad-S-Opt", badsessopt ()); - cp = onestat (cp, "Bad-Sdes", badsdes ()); - cp = onestat (cp, "Bad-Bye", badbye ()); - *--cp = 0; - return (cp); -} - -int -sdes_atoi (const char* s) -{ - if (ACE_OS::strcasecmp (s, "cname") == 0) - return (RTCP_SDES_CNAME); - if (ACE_OS::strcasecmp (s, "name") == 0) - return (RTCP_SDES_NAME); - if (ACE_OS::strcasecmp (s, "email") == 0) - return (RTCP_SDES_EMAIL); - if (ACE_OS::strcasecmp (s, "phone") == 0) - return (RTCP_SDES_PHONE); - if (ACE_OS::strcasecmp (s, "loc") == 0 || ACE_OS::strcasecmp (s, "location") == 0) - return (RTCP_SDES_LOC); - if (ACE_OS::strcasecmp (s, "tool") == 0) - return (RTCP_SDES_TOOL); - if (ACE_OS::strcasecmp (s, "note") == 0) - return (RTCP_SDES_NOTE); - return (-1); -} - -void -TAO_AV_Source::set_busy() -{ - busy_ = 1; -} - -void -TAO_AV_Source::clear_counters () -{ - np_ = 0; - nf_ = 0; - nb_ = 0; - nm_ = 0; - snp_ = 0; - sns_ = 0; - ndup_ = 0; - nrunt_ = 0; - - lts_data_.tv_sec = 0; - lts_data_.tv_usec = 0; - lts_ctrl_.tv_sec = 0; - lts_ctrl_.tv_usec = 0; - lts_done_.tv_sec = 0; - lts_done_.tv_usec = 0; -} - -TAO_AV_SourceManager::TAO_AV_SourceManager (TAO_AV_RTCP_Callback *callback) - :nsources_ (0), - sources_ (0), - clock_ (0), - keep_sites_ (0), - site_drop_time_ (0), - localsrc_ (0), - callback_ (callback) -{ - memset ( (char*)hashtab_, 0, sizeof (hashtab_)); -} - -void -TAO_AV_SourceManager::remove_from_hashtable (TAO_AV_Source* s) -{ - /* delete the TAO_AV_Source from hash table */ - ACE_UINT32 srcid = s->srcid (); - int h = SHASH (srcid); - TAO_AV_Source** p = &hashtab_[h]; - while (*p != s) - p = & (*p)->hlink_; - *p = (*p)->hlink_; -} - -void -TAO_AV_SourceManager::init (ACE_UINT32 localid, ACE_UINT32 localaddr) -{ - /* - * create the local object. remove it from the hash - * table since collision resolution changes local id - * (we special case detection of our own loopbed back packets) - */ - // Make an upcall to get the source. - this->callback_->get_rtp_source (localsrc_, - localid, - localid, - localaddr); - enter (localsrc_); - remove_from_hashtable (localsrc_); - /* - * hack to prevent local TAO_AV_Source from turning gray at startup. - * we don't need to do a similar thing for external TAO_AV_Sources, - * because they are only created when a packet arrives. - */ - localsrc_->lts_ctrl (ACE_OS::gettimeofday ()); -} - -TAO_AV_Source* -TAO_AV_SourceManager::enter (TAO_AV_Source* s) -{ - s->next_ = sources_; - sources_ = s; - - int h = SHASH (s->srcid ()); - s->hlink_ = hashtab_[h]; - hashtab_[h] = s; - - ++nsources_; - - return (s); -} - -TAO_AV_Source* -TAO_AV_SourceManager::consult (ACE_UINT32 srcid) -{ - int h = SHASH (srcid); - for (TAO_AV_Source* s = hashtab_[h]; s != 0; s = s->hlink_) { - /*XXX pulling these values into variable seems - to work around a DEC cpp bug */ - ACE_UINT32 id = s->srcid (); - if (id == srcid) - return (s); - } - return (0); -} - -TAO_AV_Source* -TAO_AV_SourceManager::lookup (ACE_UINT32 srcid, ACE_UINT32 ssrc, ACE_UINT32 addr) -{ - TAO_AV_Source* s = consult (srcid); - if (s == 0) { - if (srcid == ssrc) - /* - * Heuristic: handle application re-starts - * gracefully. We have a new TAO_AV_Source that's - * not via a mixer. Try to find an existing - * entry from the same host. - */ - s = lookup_duplicate (srcid, addr); - - if (s == 0) { - this->callback_->get_rtp_source (s, - srcid, - ssrc, - addr); -// ACE_NEW_RETURN (s, -// TAO_AV_Source (srcid, ssrc, addr), -// 0); - enter (s); - } - } - return (s); -} - -/* - * Demux data packet to its TAO_AV_Source table entry. (We don't want an extra - * SSRC arg here because CSRC's via a mixer don't have their own data - * packets.) If we haven't seen this TAO_AV_Source yet, allocate it but - * wait until we see two in-order packets accepting the flow. - */ -TAO_AV_Source* -TAO_AV_SourceManager::demux (ACE_UINT32 srcid, ACE_UINT32 addr, ACE_UINT16 seq) -{ - TAO_AV_Source* s = consult (srcid); - if (s == 0) { - s = lookup_duplicate (srcid, addr); - if (s == 0) { - /* CSRC=SSRC for data stream */ - - this->callback_->get_rtp_source (s, - srcid, - srcid, - addr); -// ACE_NEW_RETURN (s, -// TAO_AV_Source (srcid, srcid, addr), -// 0); - enter (s); - } - /* it takes two in-seq packets to activate TAO_AV_Source */ - s->fs (seq); - s->cs (seq); - // @@@Naga:We should take care of this using a policy for the - // number of packets to be validated before we accept a source. - return (0); - } else { - /* - * check for a srcid conflict or loop: - * - believe the new guy if the old guy said he's done. - * - otherwise, don't believe the new guy if we've heard - * from the old guy 'recently'. - */ - if (s->addr () != addr) { - ACE_UINT32 t = s->lts_done ().tv_sec; - if (t == 0) { - t = s->lts_data ().tv_sec; - ACE_UINT32 now = ACE_OS::gettimeofday ().sec (); - if (t && int (now - t) <= 2) - return (0); - t = s->lts_ctrl ().tv_sec; - if (t && int (now - t) <= 30) - return (0); - } - s->addr (addr); - s->clear_counters (); - s->lost (0); - } - if (s->np () == 0 && s->nb () == 0) { - /* - * make sure we get 2 in-seq packets before - * accepting TAO_AV_Source. - */ - if ( (ACE_UINT32) ( (ACE_UINT32)seq - s->cs () + 31) > 63) { - s->fs (seq); - s->cs (seq); - return (0); - } - } - } - return (s); -} - -/* - * Try to find an entry in the TAO_AV_Source table with the same network - * address (i.e., a "duplicate entry") but possibly different srcid. - * As a side effect, refile the TAO_AV_Source under the new srcid. - * - * The idea here is to gracefully handle sites that restart (with - * a new srcid). If we assume that it takes a couple seconds to - * restart - * - */ -TAO_AV_Source* -TAO_AV_SourceManager::lookup_duplicate (ACE_UINT32 srcid, ACE_UINT32 addr) -{ - /*XXX - should eventually be conditioned on cname not ipaddr */ - /* - * could use hashing here, but this is rarely called. - */ - register TAO_AV_Source* s; - for (s = sources_; s != 0; s = s->next_) { - /* - * if addresses match, take old entry if: - * - it sent a 'done', or - * - it hasn't sent any data for 2 seconds and - * and any control for 30 seconds. - */ - if (s->addr () == addr) { - if (s->lts_done ().tv_sec != 0) - break; - ACE_UINT32 now = ACE_OS::gettimeofday ().sec (); - ACE_UINT32 t = s->lts_data ().tv_sec; - if (t == 0 || int (now - t) > 2) { - t = s->lts_ctrl ().tv_sec; - if (t == 0 || int (now - t) > 30) - break; - } - } - } - if (s) { - remove_from_hashtable (s); - s->srcid (srcid); - s->ssrc (srcid); - int h = SHASH (srcid); - s->hlink_ = hashtab_[h]; - hashtab_[h] = s; - s->clear_counters (); - s->lost (0); - } - return (s); -} - -void -TAO_AV_SourceManager::remove (TAO_AV_Source* s) -{ - --nsources_; - - remove_from_hashtable (s); - - /* delete the TAO_AV_Source from list */ - TAO_AV_Source** p = &sources_; - while (*p != s) - p = & (*p)->next_; - *p = (*p)->next_; - - delete s; - -} - -/* - * Go through all the TAO_AV_Sources and see if any should be "grayed out" - * or removed altogether. 'msgint' is the current "report interval" - * in ms. - */ -void -TAO_AV_SourceManager::CheckActiveSources (double msgint) -{ - ACE_UINT32 now = ACE_OS::gettimeofday ().sec (); - u_int max_idle = u_int (msgint * (CTRL_IDLE / 1000.)); - if (max_idle == 0) - max_idle = 1; - - TAO_AV_Source* n; - for (TAO_AV_Source* s = sources_; s != 0; s = n) { - n = s->next_; - ACE_UINT32 t = s->lts_done ().tv_sec; - if (t != 0) { - if (keep_sites_) - s->lost (1); - else - remove (s); - continue; - } - t = s->lts_ctrl ().tv_sec; - if (t == 0) - /* - * No session packets? Probably ivs or nv sender. - * Revert to the data time stamp. - */ - t = s->lts_data ().tv_sec; - - if (u_int (now - t) > max_idle) { - if (keep_sites_ || site_drop_time_ == 0 || - u_int (now - t) < site_drop_time_) - s->lost (1); - else - remove (s); - } else - s->lost (0); - } -} - -int -TAO_AV_SourceManager::compare (const void* v0, const void* v1) -{ - const TAO_AV_Source* x = * (TAO_AV_Source**)v0; - const TAO_AV_Source* y = * (TAO_AV_Source**)v1; - - const char* yn = y->sdes (RTCP_SDES_NAME); - if (yn == 0) { - yn = y->sdes (RTCP_SDES_CNAME); - if (yn == 0) - return (-1); - } - const char* xn = x->sdes (RTCP_SDES_NAME); - if (xn == 0) { - xn = x->sdes (RTCP_SDES_CNAME); - if (xn == 0) - return (1); - } - return (strcmp (xn, yn)); -} - -/* - * Sort the sources by name and format a corresponding list - * of ascii srcid's in the input buffer. - */ -void -TAO_AV_SourceManager::sortactive (char* cp) const -{ - static int ntab; - static TAO_AV_Source** srctab; - if (srctab == 0) { - ntab = 2 * nsources_; - if (ntab < 32) - ntab = 32; - ACE_NEW (srctab, - TAO_AV_Source*[ntab]); - } else if (ntab < nsources_) { - ntab = 2 * nsources_; - delete srctab; - ACE_NEW (srctab, - TAO_AV_Source*[ntab]); - } - int n = 0; - for (TAO_AV_Source* s = sources_; s != 0; s = s->next_) - if (s->active () != 0) - /* source is active if it has a PacketHandler */ - srctab[n++] = s; - - if (n == 0) { - *cp = 0; - return; - } - ACE_OS::qsort (srctab, n, sizeof (*srctab), compare_func); - for (int i = 0; i < n; ++i) { - strcpy (cp, srctab[i]->name ()); - cp += strlen (cp); - *cp++ = ' '; - } - /* nuke trailing space */ - cp[-1] = 0; -} diff --git a/TAO/orbsvcs/orbsvcs/AV/source.h b/TAO/orbsvcs/orbsvcs/AV/source.h deleted file mode 100644 index 5b440766f1c..00000000000 --- a/TAO/orbsvcs/orbsvcs/AV/source.h +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- C++ -*- */ -// $Id$ -/* - * Copyright (c) 1994 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and the Network Research Group at - * Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#) $Header$ - */ - -#ifndef TAO_AV_SOURCE_H -#define TAO_AV_SOURCE_H -#include "ace/pre.h" - -#define RTCP_SDES_MAX 7 - -#include "ace/OS.h" -#include "tao/PortableServer/ORB_Manager.h" - -class TAO_AV_SourceManager; - -extern "C" -{ - int compare_func (const void* v0, const void* v1); -} - - -#define TAO_AV_SOURCE_HASH 1024 - -class TAO_AV_Source -{ -public: - TAO_AV_Source (ACE_UINT32 srcid, ACE_UINT32 ssrc, ACE_UINT32 addr); - virtual ~TAO_AV_Source (void); - void deactivate (void); - - void action(); - // @@Naga:My additions. - char *name (); - int active (void); - void active (int active); - virtual void set_busy(); - ACE_UINT32 delvar () const; - void delvar (ACE_UINT32 v); - - void lts_done (const timeval& now); - void lts_data (const timeval& now); - void lts_ctrl (const timeval& now); - void sts_data (ACE_UINT32 now); - void sts_ctrl (ACE_UINT32 now); - - const timeval& lts_ctrl (void) const; - const timeval& lts_data (void) const; - const timeval& lts_done (void) const; - int sts_ctrl (void) const; - int sts_data (void) const; - - const char* sdes (int t) const; - virtual void sdes (int t, const char* value); - ACE_UINT32 addr (void) const; - void addr (ACE_UINT32 a); - ACE_UINT32 srcid (void) const; - void srcid (ACE_UINT32 s); - ACE_UINT32 ssrc (void) const; - void ssrc (ACE_UINT32 s); - void format (int v); - int format (void) const; - void mute (int v); - int mute (void) const; - void ismixer (int v); - int ismixer (void) const; - void clear_counters (void); - - /*XXX should start at random values*/ - ACE_UINT32 nb (void) const; - ACE_UINT32 nf (void) const; - ACE_UINT32 np (void) const; - ACE_UINT32 nm (void) const; - ACE_UINT32 ns (void) const; /* no. expected */ - ACE_UINT32 ehs (void) const; - ACE_UINT32 cs (void) const; - ACE_UINT32 snp (void) const; - ACE_UINT32 sns (void) const; - ACE_UINT32 runt (void) const; - ACE_UINT32 dups (void) const; - ACE_UINT32 badsesslen (void) const; - ACE_UINT32 badsessver (void) const; - ACE_UINT32 badsessopt (void) const; - ACE_UINT32 badsdes (void) const; - ACE_UINT32 badbye (void) const; - void nb (int v); - void nf (int v); - void np (int v); - void nm (int v); - void snp (int v); - void sns (int v); - void fs (int v); - void runt (int v); - void badsesslen (int v); - void badsessver (int v); - void badsessopt (int v); - void badsdes (int v); - void badbye (int v); - int cs (ACE_UINT16 v); - int checkseq (ACE_UINT16 v); - virtual void lost (int); - - TAO_AV_Source* next_; /* link for TAO_AV_SourceManager TAO_AV_Source list */ - TAO_AV_Source* hlink_; /* link for TAO_AV_SourceManager hash table */ -protected: - char* stats (char* cp) const; - - // @@Naga:My additions - int active_; - char *name_; - int delvar_; - ACE_UINT32 srcid_; /* rtp global src id (CSRC), net order */ - ACE_UINT32 ssrc_; /* rtp global sync src id (SSRC), net order) */ - ACE_UINT32 addr_; /* address of sender (net order) */ - - ACE_UINT32 sts_data_; /* sndr ts from last data packet (net order) */ - ACE_UINT32 sts_ctrl_; /* sndr ts from last control packet */ - timeval lts_data_; /* local unix time for last data packet */ - timeval lts_ctrl_; /* local unix time for last control packet */ - timeval lts_done_; /* local unix time for bye packet */ - - ACE_UINT32 fs_; /* first seq. no received */ - ACE_UINT32 cs_; /* current (most recent) seq. no received */ - ACE_UINT32 np_; /* no. packets received */ - ACE_UINT32 nf_; /* no. video frames received */ - ACE_UINT32 nb_; /* no. bytes received */ - ACE_UINT32 nm_; /* no. misordered packets detected */ - ACE_UINT32 snp_; /* last advertised no. pkts received */ - ACE_UINT32 sns_; /* last advertised no. pkts exptected */ - ACE_UINT32 ndup_; /* no. of duplicate packets (via RTP seqno) */ - ACE_UINT32 nrunt_; /* count of packets too small */ - - /* following errors are from session (rtcp) processing */ - ACE_UINT32 badsesslen_; /* bad header length field */ - ACE_UINT32 badsessver_; /* bad header version number */ - ACE_UINT32 badsessopt_; /* unrecognized option */ - ACE_UINT32 badsdes_; /* sdes cnt > available data */ - ACE_UINT32 badbye_; /* bye cnt > available data */ - - int format_; /* RTP packet type */ - int mute_; /* true if Source muted */ - int lost_; /* true when signal lost */ - int busy_; /* nonzero. during talk spurt */ - int ismixer_; /* true if TAO_AV_Source has acted as a 'mixer' */ - -#define TAO_AV_SOURCE_NSEQ 64 - ACE_UINT16 seqno_[TAO_AV_SOURCE_NSEQ]; - char* sdes_[RTCP_SDES_MAX + 1]; -}; - -int sdes_atoi (const char* s); -char* onestat (char* cp, const char* name, u_long v); -class TAO_Base_StreamEndPoint; -class TAO_AV_RTCP_Callback; - -class TAO_AV_SourceManager -{ -public: - TAO_AV_SourceManager (TAO_AV_RTCP_Callback *callback); - void init (ACE_UINT32 localid, ACE_UINT32 localaddr); - TAO_AV_Source* lookup (ACE_UINT32 srcid, ACE_UINT32 ssrc, ACE_UINT32 addr); - TAO_AV_Source* demux (ACE_UINT32 srcid, ACE_UINT32 addr, ACE_UINT16 seq); - TAO_AV_Source* consult (ACE_UINT32 srcid); - int nsources (void) const; - TAO_AV_Source* sources (void) const; - - void CheckActiveSources (double msgint); - void ListSources (void); - - ACE_UINT32 clock (void) const; - TAO_AV_Source* localsrc (void) const; - void localsrc (TAO_AV_Source* src); - - void sortactive (char*) const; - void remove (TAO_AV_Source*); - void keep_sites (int keep); - void site_drop_time (int time); - TAO_AV_Source* enter (TAO_AV_Source* s); - static int compare (const void*, const void*); -protected: - void remove_from_hashtable (TAO_AV_Source* s); - - TAO_AV_Source* lookup_duplicate (ACE_UINT32 srcid, ACE_UINT32 addr); - - int nsources_; - TAO_AV_Source* sources_; - ACE_UINT32 clock_; - int keep_sites_; - u_int site_drop_time_; - TAO_AV_Source* localsrc_; - TAO_AV_Source* hashtab_[TAO_AV_SOURCE_HASH]; - - TAO_AV_RTCP_Callback *callback_; -}; - -#if defined (__ACE_INLINE__) -#include "source.i" -#endif /* __ACE_INLINE__ */ - -#include "ace/post.h" -#endif /* TAO_AV_Source_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/source.i b/TAO/orbsvcs/orbsvcs/AV/source.i deleted file mode 100644 index 23318862f4f..00000000000 --- a/TAO/orbsvcs/orbsvcs/AV/source.i +++ /dev/null @@ -1,491 +0,0 @@ -/* -*- C++ -*- */ -//$Id$ -/*- - * Copyright (c) 1993-1994 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and the Network Research Group at - * Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -ACE_INLINE int -TAO_AV_Source::checkseq (ACE_UINT16 v) -{ - int k = v & (TAO_AV_SOURCE_NSEQ-1); - if (seqno_[k] != v) { - seqno_[k] = v; - return (0); - } else { - ++ndup_; - return (-1); - } -} - -ACE_INLINE int -TAO_AV_Source::cs (ACE_UINT16 v) -{ - /* - * This routine updates a 32 bit sequence number based on - * the rtp packet's 16 bit seq. no. - */ - register int c = cs_; - register int d = v - c; - if (d < -1024 || d > 1024) { - cs_ = v; - if (v < 512 && c > 0x10000-512) { - /* - * seq no. wrapped - subtract 64k from fs to - * account for it. - */ - fs_ -= 0x10000; - } else { - /* - * the seq. no made a very large jump. assume - * that the other side restarted without telling - * us about it so just re-sync (i.e., pretend - * this was the first packet). - */ - fs_ = v - 1; - np_ = 0; - nf_ = 0; - nb_ = 0; - snp_ = 0; - nm_ = 0; - } - } else if (d > 0) { - /* d <= 0 means duplicate or reordered packet - ignore */ - cs_ = v; - if (d < 0) - /* out of order */ - ++nm_; - } - return (checkseq (v)); -} - -ACE_INLINE void -TAO_AV_Source::action (void) -{ - if (!busy_) set_busy(); -} - -ACE_INLINE char* -TAO_AV_Source::name (void) -{ - return ACE_OS::strdup (""); -} - -ACE_INLINE int -TAO_AV_Source::active (void) -{ - return this->active_; -} - -ACE_INLINE void -TAO_AV_Source::active (int active) -{ - this->active_ = active; -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::delvar (void) const -{ - return this->delvar_; -} - -ACE_INLINE void -TAO_AV_Source::delvar (ACE_UINT32 v) -{ - this->delvar_ = v; -} - -ACE_INLINE const timeval& -TAO_AV_Source::lts_ctrl (void) const -{ - return (lts_ctrl_); -} - -ACE_INLINE void -TAO_AV_Source::lts_ctrl (const timeval& now) -{ - this->lts_ctrl_ = now; -} - -ACE_INLINE const timeval& -TAO_AV_Source::lts_data (void) const -{ - return (lts_data_); -} - -ACE_INLINE void -TAO_AV_Source::lts_data (const timeval& now) -{ - this->lts_data_ = now; -} - -ACE_INLINE const timeval& -TAO_AV_Source::lts_done (void) const -{ - return (lts_done_); -} - -ACE_INLINE void -TAO_AV_Source::lts_done (const timeval &now) -{ - this->lts_done_ = now; -} - -ACE_INLINE int -TAO_AV_Source::sts_ctrl (void) const -{ - return (sts_ctrl_); -} - -ACE_INLINE void -TAO_AV_Source::sts_ctrl (ACE_UINT32 now) -{ - this->sts_ctrl_ = now; -} - -ACE_INLINE int -TAO_AV_Source::sts_data (void) const -{ - return (sts_data_); -} - -ACE_INLINE void -TAO_AV_Source::sts_data (ACE_UINT32 now) -{ - this->sts_data_ = now; -} - -ACE_INLINE const char* -TAO_AV_Source::sdes (int t) const -{ - return (sdes_[t]); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::addr (void) const -{ - return (addr_); -} -ACE_INLINE void -TAO_AV_Source::addr (ACE_UINT32 a) -{ - addr_ = a; -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::srcid (void) const -{ - return (srcid_); -} - -ACE_INLINE void -TAO_AV_Source::srcid (ACE_UINT32 s) -{ - srcid_ = s; -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::ssrc (void) const -{ - return (ssrc_); -} - -ACE_INLINE void -TAO_AV_Source::ssrc (ACE_UINT32 s) -{ - ssrc_ = s; -} - -ACE_INLINE void -TAO_AV_Source::format (int v) -{ - format_ = v; -} - -ACE_INLINE int -TAO_AV_Source::format (void) const -{ - return (format_); -} - -ACE_INLINE void -TAO_AV_Source::mute (int v) -{ - mute_ = v; -} - -ACE_INLINE int -TAO_AV_Source::mute (void) const -{ - return (mute_); -} - -ACE_INLINE void -TAO_AV_Source::ismixer (int v) -{ - ismixer_ = v; -} - -ACE_INLINE int -TAO_AV_Source::ismixer (void) const -{ - return (ismixer_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::nb (void) const -{ - return (nb_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::nf (void) const -{ - return (nf_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::np (void) const -{ - return (np_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::nm (void) const -{ - return (nm_); -} - -/* no. expected */ -ACE_INLINE ACE_UINT32 -TAO_AV_Source::ns (void) const -{ - return (cs_ - fs_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::ehs (void) const -{ - return ((fs_ & 0xffff0000) | cs_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::cs (void) const -{ - return (cs_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::snp (void) const -{ - return (snp_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::sns (void) const -{ - return (sns_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::runt (void) const -{ - return (nrunt_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::dups (void) const -{ - return (ndup_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::badsesslen (void) const -{ - return (badsesslen_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::badsessver (void) const -{ - return (badsessver_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::badsessopt (void) const -{ - return (badsessopt_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::badsdes (void) const -{ - return (badsdes_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_Source::badbye (void) const -{ - return (badbye_); -} - -ACE_INLINE void -TAO_AV_Source::nb (int v) -{ - nb_ += v; -} - -ACE_INLINE void -TAO_AV_Source::nf (int v) -{ - nf_ += v; -} - -ACE_INLINE void -TAO_AV_Source::np (int v) -{ - np_ += v; -} - -ACE_INLINE void -TAO_AV_Source::nm (int v) -{ - nm_ += v; -} - -ACE_INLINE void -TAO_AV_Source::snp (int v) -{ - snp_ = v; -} - -ACE_INLINE void -TAO_AV_Source::sns (int v) -{ - sns_ = v; -} - -ACE_INLINE void -TAO_AV_Source::fs (int v) -{ - fs_ = v; -} - -ACE_INLINE void -TAO_AV_Source::runt (int v) -{ - nrunt_ += v; -} - -ACE_INLINE void -TAO_AV_Source::badsesslen (int v) -{ - badsesslen_ += v; -} - -ACE_INLINE void -TAO_AV_Source::badsessver (int v) -{ - badsessver_ += v; -} - -ACE_INLINE void -TAO_AV_Source::badsessopt (int v) -{ - badsessopt_ += v; -} - -ACE_INLINE void -TAO_AV_Source::badsdes (int v) -{ - badsdes_ += v; -} - -ACE_INLINE void -TAO_AV_Source::badbye (int v) -{ - badbye_ += v; -} - -ACE_INLINE void -TAO_AV_Source::lost (int v) -{ - if (lost_ != v) - lost_ = v; -} - -//------------------------------------------------------------ -// TAO_AV_SourceManager -//------------------------------------------------------------ - -ACE_INLINE int -TAO_AV_SourceManager::nsources (void) const -{ - return (this->nsources_); -} - -ACE_INLINE TAO_AV_Source* -TAO_AV_SourceManager::sources (void) const -{ - return (this->sources_); -} - -ACE_INLINE ACE_UINT32 -TAO_AV_SourceManager::clock (void) const -{ - return (clock_); -} - -ACE_INLINE TAO_AV_Source* -TAO_AV_SourceManager::localsrc (void) const -{ - return (localsrc_); -} - -ACE_INLINE void -TAO_AV_SourceManager::localsrc (TAO_AV_Source *src) -{ - this->localsrc_ = src; -} - -ACE_INLINE void -TAO_AV_SourceManager::keep_sites (int keep) -{ - this->keep_sites_ = keep; -} - -ACE_INLINE void -TAO_AV_SourceManager::site_drop_time (int time) -{ - this->site_drop_time_ = time; -} - -- cgit v1.2.1