diff options
author | naga <naga@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-08-31 23:17:58 +0000 |
---|---|---|
committer | naga <naga@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-08-31 23:17:58 +0000 |
commit | 152214d2ee4e33e7e9f9b6529ddd5b56e917ff59 (patch) | |
tree | d65e282fbf3232635b7f6e8e4f1628dab8b39a94 | |
parent | 11d605ef29a0c29f26534cb6b652f681fa83dd2c (diff) | |
download | ATCD-152214d2ee4e33e7e9f9b6529ddd5b56e917ff59.tar.gz |
Tue Aug 31 18:07:35 1999 Nagarajan Surendran <naga@cs.wustl.edu>
73 files changed, 21034 insertions, 2705 deletions
diff --git a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp index 4c0bcdb02ce..6c447753e7c 100644 --- a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.cpp @@ -1,5 +1,4 @@ // $Id$ - // ============================================================================ // // = LIBRARY @@ -16,10 +15,128 @@ // ============================================================================ #include "AVStreams_i.h" -#include "orbsvcs/Trader/Trader.h" +#include "sfp.h" +#include "MCast.h" +#include "RTCP.h" ACE_RCSID(AV, AVStreams_i, "$Id$") +int +deactivate_servant (PortableServer::Servant servant) +{ + // Because of reference counting, the POA + // will automatically delete the servant when all pending requests + // on this servant are complete. + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + PortableServer::POA_var poa = servant->_default_POA (ACE_TRY_ENV); + ACE_TRY_CHECK; + + PortableServer::ObjectId_var id = poa->servant_to_id (servant, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + poa->deactivate_object (id.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"deactivate_servant"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +char * +get_flowname (const char *flow_spec_entry_str) +{ + ACE_CString flow_spec_entry (flow_spec_entry_str); + int slash_pos = flow_spec_entry.find ('\\'); + ACE_CString flow_name; + if (slash_pos != flow_spec_entry.npos) + flow_name = flow_spec_entry.substring (0,slash_pos); + else + flow_name = flow_spec_entry_str; + return CORBA::string_dup (flow_name.c_str ()); +} + +#if !defined (__ACE_INLINE__) +#include "AVStreams_i.i" +#endif /* __ACE_INLINE__ */ + +//------------------------------------------------------------ +// TAO_AV_Qos +//------------------------------------------------------------ + +TAO_AV_QoS::TAO_AV_QoS (void) +{ +} + +TAO_AV_QoS::TAO_AV_QoS (AVStreams::streamQoS &stream_qos) +{ + this->set (stream_qos); +} + +int +TAO_AV_QoS::convert (AVStreams::streamQoS &/*network_qos*/) +{ + return -1; +} + +#if !defined (TAO_ORBSVCS_HAS_Trader) +// = Methods to deal with ACE_Hash_Map_Manager. + +TAO_String_Hash_Key::TAO_String_Hash_Key (void) +{ +} + +TAO_String_Hash_Key::TAO_String_Hash_Key (char * name) + : CORBA_String_var (name) +{ +} + +TAO_String_Hash_Key::TAO_String_Hash_Key (const char * name) + : CORBA_String_var (name) +{ +} + +TAO_String_Hash_Key::TAO_String_Hash_Key (const CORBA::String_var &src) + : CORBA_String_var (src) +{ +} + +int +TAO_String_Hash_Key::operator == (const TAO_String_Hash_Key &hash_key) const +{ + return ACE_OS::strcmp (this->in (), hash_key.in ()) == 0; +} + +int +operator < (const TAO_String_Hash_Key &left, + const TAO_String_Hash_Key &right) +{ + return ACE_OS::strcmp (left.in (), right.in ()) < 0; +} + + +u_long +TAO_String_Hash_Key::hash (void) const +{ + u_long ret = ACE::hash_pjw (this->in ()); + return ret; +} + +TAO_String_Hash_Key::~TAO_String_Hash_Key (void) +{ +} + +#endif /* !TAO_ORBSVCS_HAS_Trader */ + // ---------------------------------------------------------------------- // AV_Null_MediaCtrl // ---------------------------------------------------------------------- @@ -38,24 +155,52 @@ TAO_Basic_StreamCtrl::TAO_Basic_StreamCtrl (void) { } -TAO_Basic_StreamCtrl::~TAO_Basic_StreamCtrl (void) -{ -} - // Stop the transfer of data of the stream // Empty the_spec means apply operation to all flows void -TAO_Basic_StreamCtrl::stop (const AVStreams::flowSpec &the_spec, +TAO_Basic_StreamCtrl::stop (const AVStreams::flowSpec &flow_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)) - { - if (CORBA::is_nil (this->sep_a_.in ())) - return; - - // Make the upcall into the application - this->sep_a_->stop (the_spec, ACE_TRY_ENV); + ACE_TRY + { + // @@Call stop on the Related MediaCtrl. + // call stop on the flow connections. + if (this->flow_connection_map_.current_size () > 0) + { + if (flow_spec.length () > 0) + for (u_int i=0;i<flow_spec.length ();i++) + { + char *flowname = get_flowname (flow_spec[i]); + TAO_String_Hash_Key flow_name_key (flowname); + FlowConnection_Map::ENTRY *flow_connection_entry = 0; + if (this->flow_connection_map_.find (flow_name_key,flow_connection_entry) == 0) + { + flow_connection_entry->int_id_->stop (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + else + { + // call start on all the flows. + FlowConnection_Map_Iterator iterator (this->flow_connection_map_); + FlowConnection_Map_Entry *entry = 0; + for (;iterator.next (entry) != 0;iterator.advance ()) + { + entry->int_id_->stop (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Basic_StreamCtrl::stop"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } // Start the transfer of data in the stream. @@ -66,28 +211,90 @@ TAO_Basic_StreamCtrl::start (const AVStreams::flowSpec &flow_spec, ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)) { - // call start on the flow connections. - if (CORBA::is_nil (this->sep_a_.in ())) - return; + ACE_TRY + { + // @@Call start on the Related MediaCtrl. - // Make the upcall into the application - this->sep_a_->start (flow_spec, ACE_TRY_ENV); + // call start on the flow connections. + if (this->flow_connection_map_.current_size () > 0) + { + if (flow_spec.length () > 0) + for (u_int i=0;i<flow_spec.length ();i++) + { + char *flowname = get_flowname (flow_spec[i]); + TAO_String_Hash_Key flow_name_key (flowname); + FlowConnection_Map::ENTRY *flow_connection_entry = 0; + if (this->flow_connection_map_.find (flow_name_key,flow_connection_entry) == 0) + { + flow_connection_entry->int_id_->start (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + else + { + // call start on all the flows. + FlowConnection_Map_Iterator iterator (this->flow_connection_map_); + FlowConnection_Map_Entry *entry = 0; + for (;iterator.next (entry) != 0;iterator.advance ()) + { + entry->int_id_->start (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Basic_StreamCtrl::start"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } // Tears down the stream. This will close the connection, and delete // the streamendpoint and vdev associated with this stream // Empty the_spec means apply operation to all flows void -TAO_Basic_StreamCtrl::destroy (const AVStreams::flowSpec &the_spec, +TAO_Basic_StreamCtrl::destroy (const AVStreams::flowSpec &flow_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)) { - if (CORBA::is_nil (this->sep_a_.in ())) - return; - - // Make the upcall into the application - this->sep_a_->destroy (the_spec, ACE_TRY_ENV); + ACE_TRY + { + // call stop on the flow connections. + if (this->flow_connection_map_.current_size () > 0) + { + if (flow_spec.length () > 0) + for (u_int i=0;i<flow_spec.length ();i++) + { + char *flowname = get_flowname (flow_spec[i]); + TAO_String_Hash_Key flow_name_key (flowname); + FlowConnection_Map::ENTRY *flow_connection_entry = 0; + if (this->flow_connection_map_.find (flow_name_key,flow_connection_entry) == 0) + flow_connection_entry->int_id_->destroy (ACE_TRY_ENV); + } + else + { + // call start on all the flows. + FlowConnection_Map_Iterator iterator (this->flow_connection_map_); + FlowConnection_Map_Entry *entry = 0; + for (;iterator.next (entry) != 0;iterator.advance ()) + { + entry->int_id_->destroy (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Basic_StreamCtrl::destroy"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } // Changes the QoS associated with the stream @@ -120,27 +327,32 @@ TAO_Basic_StreamCtrl::modify_QoS (AVStreams::streamQoS & new_qos, // Used by StreamEndPoint and VDev to inform StreamCtrl of events. // E.g., loss of flow, reestablishment of flow, etc.. void -TAO_Basic_StreamCtrl::push_event (const struct CosPropertyService::Property & /* the_event */, +TAO_Basic_StreamCtrl::push_event (const struct CosPropertyService::Property &/*the_event*/, CORBA::Environment & /* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException)) { ACE_DEBUG ((LM_DEBUG,"\n(%P|%t) Recieved event \"")); } -// @@ Need to throw not-supported exception here +// Sets the flow protocol status. void -TAO_Basic_StreamCtrl::set_FPStatus (const AVStreams::flowSpec &/* the_spec */, - const char * /* fp_name */, - const CORBA::Any &/* fp_settings */, - CORBA::Environment &/* ACE_TRY_ENV */) +TAO_Basic_StreamCtrl::set_FPStatus (const AVStreams::flowSpec &flow_spec, + const char *fp_name, + const CORBA::Any &fp_settings, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::FPError)) { + if (!CORBA::is_nil (this->sep_a_.in ())) + { + this->sep_a_->set_FPStatus (flow_spec,fp_name,fp_settings,ACE_TRY_ENV); + ACE_CHECK; + } } -// @@ Need to throw not-supported exception here +// Gets the flow connection. CORBA::Object_ptr TAO_Basic_StreamCtrl::get_flow_connection (const char *flow_name, CORBA::Environment &ACE_TRY_ENV) @@ -150,28 +362,49 @@ TAO_Basic_StreamCtrl::get_flow_connection (const char *flow_name, { TAO_String_Hash_Key flow_name_key (flow_name); FlowConnection_Map::ENTRY *flow_connection_entry = 0; - if (this->flow_map_.find (flow_name_key,flow_connection_entry) == 0) - return flow_connection_entry->int_id_; + if (this->flow_connection_map_.find (flow_name_key,flow_connection_entry) == 0) + return AVStreams::FlowConnection::_duplicate (flow_connection_entry->int_id_); else ACE_THROW_RETURN (AVStreams::noSuchFlow (),CORBA::Object::_nil ()); } -// @@ Need to throw not-supported exception here +// Sets the flow connection. void TAO_Basic_StreamCtrl::set_flow_connection (const char *flow_name, - CORBA::Object_ptr flow_connection, + CORBA::Object_ptr flow_connection_obj, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::notSupported)) { + AVStreams::FlowConnection_ptr flow_connection = AVStreams::FlowConnection::_nil (); + ACE_TRY + { + flow_connection = AVStreams::FlowConnection::_narrow (flow_connection_obj,ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Basic_StreamCtrl::set_flow_connection"); + return; + } + ACE_ENDTRY; + ACE_CHECK; // add the flowname and the flowconnection to the hashtable. + this->flows_.length (this->flow_count_ + 1); this->flows_ [this->flow_count_++] = CORBA::string_dup (flow_name); TAO_String_Hash_Key flow_name_key (flow_name); - if (this->flow_map_.bind (flow_name_key,flow_connection) != 0) + if (this->flow_connection_map_.bind (flow_name_key,flow_connection) != 0) ACE_THROW (AVStreams::noSuchFlow ());// is this right? } +TAO_Basic_StreamCtrl::~TAO_Basic_StreamCtrl (void) +{ + FlowConnection_Map_Iterator iterator (this->flow_connection_map_); + FlowConnection_Map_Entry *entry = 0; + for (;iterator.next (entry) != 0;iterator.advance ()) + CORBA::release (entry->int_id_); +} // ---------------------------------------------------------------------- // TAO_Negotiator @@ -187,17 +420,258 @@ TAO_Negotiator::negotiate (AVStreams::Negotiator_ptr /* remote_negotiator */, } // ---------------------------------------------------------------------- +// MMDevice_Map_Hash_Key +// ---------------------------------------------------------------------- + +const int MMDevice_Map_Hash_Key::hash_maximum_ = 10000; + +//default constructor. +MMDevice_Map_Hash_Key::MMDevice_Map_Hash_Key (void) +{ + this->mmdevice_ = AVStreams::MMDevice::_nil (); +} + +// constructor. +MMDevice_Map_Hash_Key::MMDevice_Map_Hash_Key (AVStreams::MMDevice_ptr mmdevice) +{ + this->mmdevice_ = AVStreams::MMDevice::_duplicate (mmdevice); +} + +// copy constructor. +MMDevice_Map_Hash_Key::MMDevice_Map_Hash_Key (const MMDevice_Map_Hash_Key& hash_key) +{ + this->mmdevice_ = AVStreams::MMDevice::_duplicate (hash_key.mmdevice_); +} + +// destructor. +MMDevice_Map_Hash_Key::~MMDevice_Map_Hash_Key (void) +{ + CORBA::release (this->mmdevice_); +} + +int +MMDevice_Map_Hash_Key::operator == (const MMDevice_Map_Hash_Key &hash_key) const +{ + CORBA::Boolean result = 0; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + result = + this->mmdevice_->_is_equivalent (hash_key.mmdevice_,ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"MMDevice_Map_Hash_Key::operator == "); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return result; +} + +int +operator < (const MMDevice_Map_Hash_Key &left, + const MMDevice_Map_Hash_Key &right) +{ + int result = 0; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::ULong left_hash = left.mmdevice_->_hash (left.hash_maximum_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + CORBA::ULong right_hash = right.mmdevice_->_hash (right.hash_maximum_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + result = left_hash < right_hash; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"operator < for MMDevice_Map_Hash_Key"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return result; +} + +u_long +MMDevice_Map_Hash_Key::hash (void) const +{ + u_long result = 0; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + result = this->mmdevice_->_hash (this->hash_maximum_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"MMDevice_Map_Hash_Key::hash"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return result; +} + +// ---------------------------------------------------------------------- // TAO_StreamCtrl // ---------------------------------------------------------------------- TAO_StreamCtrl::TAO_StreamCtrl (void) - :mcastconfigif_ (0), - mcastconfigif_ptr_ (0) + :mcastconfigif_ (0) { + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->streamctrl_ = this->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + char buf [BUFSIZ]; + int result = gethostname (buf,BUFSIZ); + unsigned long ipaddr = 0; + if (result == 0) + ipaddr = ACE_OS::inet_addr (buf); + this->source_id_ = TAO_AV_RTCP::alloc_srcid (ipaddr); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamCtrl::TAO_StreamCtrl"); + } + ACE_ENDTRY; + ACE_CHECK; +} + +TAO_StreamCtrl::TAO_StreamCtrl (TAO_StreamCtrl const &) +{ + //no-op +} + +void +TAO_StreamCtrl::operator= (TAO_StreamCtrl const &) +{ + //no-op } TAO_StreamCtrl::~TAO_StreamCtrl (void) { + delete this->mcastconfigif_; +} + + +// Stop the transfer of data of the stream +// Empty the_spec means apply operation to all flows +void +TAO_StreamCtrl::stop (const AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::noSuchFlow)) +{ + ACE_TRY + { + TAO_Basic_StreamCtrl::stop (flow_spec,ACE_TRY_ENV); + 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 ()) + { + entry->int_id_.sep_->stop (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_->stop (flow_spec, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Basic_StreamCtrl::stop"); + return; + } + ACE_ENDTRY; + ACE_CHECK; +} + +// Start the transfer of data in the stream. +// Empty the_spec means apply operation to all flows +void +TAO_StreamCtrl::start (const AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::noSuchFlow)) +{ + ACE_TRY + { + TAO_Basic_StreamCtrl::start (flow_spec,ACE_TRY_ENV); + 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 ()) + { + entry->int_id_.sep_->start (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_->start (flow_spec, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Basic_StreamCtrl::start"); + return; + } + ACE_ENDTRY; + ACE_CHECK; +} + +// Tears down the stream. This will close the connection, and delete +// the streamendpoint and vdev associated with this stream +// Empty the_spec means apply operation to all flows +void +TAO_StreamCtrl::destroy (const AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::noSuchFlow)) +{ + ACE_TRY + { + TAO_Basic_StreamCtrl::destroy (flow_spec,ACE_TRY_ENV); + 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 ()) + { + 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_Basic_StreamCtrl::destroy"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } // request the two MMDevices to create vdev and stream endpoints. save @@ -215,77 +689,188 @@ TAO_StreamCtrl::bind_devs (AVStreams::MMDevice_ptr a_party, AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)) { - // do a Qos Translation from application level Qos to Network level Qos?? ACE_TRY { if (CORBA::is_nil (a_party) && CORBA::is_nil (b_party)) ACE_ERROR_RETURN ((LM_ERROR,"Both parties are nil\n"),0); // Check to see if we have non-nil parties to bind! - if (CORBA::is_nil (a_party) || - CORBA::is_nil (b_party)) - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) TAO_StreamCtrl::bind_devs: " - "a_party or b_party is null" - "Multicast mode\n")); + if (TAO_debug_level > 0) + if (CORBA::is_nil (a_party) || + CORBA::is_nil (b_party)) + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) TAO_StreamCtrl::bind_devs: " + "a_party or b_party is null" + "Multicast mode\n")); // Request a_party to create the endpoint and vdev CORBA::Boolean met_qos; CORBA::String_var named_vdev; - AVStreams::StreamCtrl_var streamctrl = - this->_this (ACE_TRY_ENV); - ACE_TRY_CHECK; + if (!CORBA::is_nil (a_party)) { - this->sep_a_ = - a_party-> create_A (streamctrl.in (), - this->vdev_a_.out (), - the_qos, - met_qos, - named_vdev.inout (), - the_flows, - ACE_TRY_ENV); - ACE_TRY_CHECK; + MMDevice_Map_Hash_Key find_key (a_party); + MMDevice_Map_Entry find_entry; + int result = + this->mmdevice_a_map_.find (find_key,find_entry); + if (result == 0) + { + if (TAO_debug_level > 0) + { + // Already in the map. + ACE_DEBUG ((LM_DEBUG,"mmdevice a_party is already bound\n")); + } + return 1; + } + else + { + this->sep_a_ = + a_party-> create_A (this->streamctrl_.in (), + this->vdev_a_.out (), + the_qos, + met_qos, + named_vdev.inout (), + the_flows, + ACE_TRY_ENV); + ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) TAO_StreamCtrl::create_A: succeeded\n")); + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG,"(%P|%t) TAO_StreamCtrl::create_A: succeeded\n")); + // Define ourselves as the related_streamctrl property of the sep. + CORBA::Any streamctrl_any; + streamctrl_any <<= this->streamctrl_.in (); + this->sep_a_->define_property ("Related_StreamCtrl", + streamctrl_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 (a_party); + map_entry.sep_ = AVStreams::StreamEndPoint_A::_duplicate (this->sep_a_.in ()); + map_entry.vdev_ = AVStreams::VDev::_duplicate (this->vdev_a_.in ()); + map_entry.flowspec_ = the_flows; + map_entry.qos_ = the_qos; + result = + this->mmdevice_a_map_.bind (key,map_entry); + if (result < 0) + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG,"Error binding mmdevice entry in the a_map")); + } } - // Request b_party to create the endpoint and vdev - if (!CORBA::is_nil (b_party)) { - this->sep_b_ = - b_party-> create_B (streamctrl.in (), - this->vdev_b_.out (), - the_qos, - met_qos, - named_vdev.inout (), - the_flows, - ACE_TRY_ENV); - ACE_TRY_CHECK; + MMDevice_Map_Hash_Key find_key (b_party); + MMDevice_Map_Entry find_entry; + int result = + this->mmdevice_b_map_.find (find_key,find_entry); + if (result == 0) + { + // Already in the map. + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"mmdevice b_party is already bound\n")); + return 1; + } + else + { + this->sep_b_ = + b_party-> create_B (this->streamctrl_.in (), + this->vdev_b_.out (), + the_qos, + met_qos, + named_vdev.inout (), + the_flows, + ACE_TRY_ENV); + ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) TAO_StreamCtrl::create_B: succeeded\n")); - ACE_DEBUG ((LM_DEBUG, - "\n(%P|%t)stream_endpoint_b_ = %s", - TAO_ORB_Core_instance ()->orb ()->object_to_string (this->sep_b_.in (), - ACE_TRY_ENV))); - ACE_TRY_CHECK; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t) TAO_StreamCtrl::create_B: succeeded\n")); + + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, + "\n(%P|%t)stream_endpoint_b_ = %s", + TAO_ORB_Core_instance ()->orb ()->object_to_string (this->sep_b_.in (), + ACE_TRY_ENV))); + ACE_TRY_CHECK; + // Define ourselves as the related_streamctrl property of the sep. + CORBA::Any streamctrl_any; + streamctrl_any <<= this->streamctrl_.in (); + this->sep_b_->define_property ("Related_StreamCtrl", + streamctrl_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); + map_entry.sep_ = AVStreams::StreamEndPoint::_duplicate (this->sep_b_.in ()); + map_entry.vdev_ = AVStreams::VDev::_duplicate(this->vdev_b_.in ()); + map_entry.flowspec_ = the_flows; + map_entry.qos_ = the_qos; + int result = + this->mmdevice_b_map_.bind (key,map_entry); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Error binding mmdevice entry in the b_map")); + } } - if (CORBA::is_nil (b_party)) + // In the full profile case there's no VDev. + if (CORBA::is_nil (b_party) && (!CORBA::is_nil (this->vdev_a_.in ()))) { - if (this->mcastconfigif_ != 0) + // Now set the source id for this A endpoint. + // If the sep contains flow producers then set the source ids for those + // instead. + ACE_TRY_EX (set_source_id) + { + CORBA::Any_ptr flows_any = this->sep_a_->get_property_value ("Flows", + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (set_source_id); + AVStreams::flowSpec_var flows; + *flows_any >>= flows.out (); + for (u_int i=0; i< flows->length ();i++) + { + CORBA::Object_var fep_obj = + this->sep_a_->get_fep (flows [i],ACE_TRY_ENV); + ACE_TRY_CHECK_EX (set_source_id); + ACE_TRY_EX (producer_check) + { + AVStreams::FlowProducer_var producer = + AVStreams::FlowProducer::_narrow (fep_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (producer_check); + producer->set_source_id (this->source_id_++); + } + ACE_CATCHANY + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG," %s ",flows[i].in ())); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"producer_check: not a producer"); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + } + } + ACE_CATCHANY + { + // Since the full profile failed try setting the source id + // for the sep instead. + // @@Naga: What do we do if in the light profile the sep has + // many producers who do not have flow interfaces. Then + // the streamctrl has to give an array of source ids to + // the sep. + this->sep_a_->set_source_id (this->source_id_++, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + if (!this->mcastconfigif_) { ACE_NEW_RETURN (this->mcastconfigif_, TAO_MCastConfigIf, 0); + // @@: Deactivating the object thru poa means calling remove_ref after _this. this->mcastconfigif_ptr_ = this->mcastconfigif_->_this (ACE_TRY_ENV); ACE_TRY_CHECK; } // Multicast source being added. - CORBA::Boolean result = this->vdev_a_->set_Mcast_peer (streamctrl.in (), - this->mcastconfigif_ptr_, + CORBA::Boolean result = this->vdev_a_->set_Mcast_peer (this->streamctrl_.in (), + this->mcastconfigif_ptr_.in (), the_qos, the_flows, ACE_TRY_ENV); @@ -295,49 +880,93 @@ TAO_StreamCtrl::bind_devs (AVStreams::MMDevice_ptr a_party, if (CORBA::is_nil (a_party)) { - // Multicast sink being added. - if (this->mcastconfigif_ != 0) - ACE_ERROR_RETURN ((LM_ERROR,"first add a source and then a sink\n"),0); - this->mcastconfigif_->set_peer (this->vdev_b_.in (), - the_qos, - the_flows, - ACE_TRY_ENV); - ACE_TRY_CHECK; + if (!CORBA::is_nil (this->vdev_b_.in ())) + { + // Multicast sink being added. + if (!this->mcastconfigif_) + ACE_ERROR_RETURN ((LM_ERROR,"first add a source and then a sink\n"),0); + this->mcastconfigif_->set_peer (this->vdev_b_.in (), + the_qos, + the_flows, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } - this->sep_a_->connect_leaf (this->sep_b_.in (), - the_qos, - the_flows, - ACE_TRY_ENV); - ACE_TRY_CHECK; + int connect_leaf_success = 0; + ACE_TRY_EX (connect_leaf) + { + // @@: define null interfaces for Atm so that they can be implemented once + // ACE adds support for ATM multicast. + connect_leaf_success = this->sep_a_->connect_leaf (this->sep_b_.in (), + the_qos, + the_flows, + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (connect_leaf); + connect_leaf_success = 1; + } + ACE_CATCH (AVStreams::notSupported,ex) + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"connect_leaf failed\n")); + connect_leaf_success = 0; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamCtrl::bind_devs"); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + if (!connect_leaf_success) + { + AVStreams::flowSpec connect_flows = the_flows; + this->sep_a_->multiconnect (the_qos,connect_flows,ACE_TRY_ENV); + ACE_TRY_CHECK; + this->sep_b_->multiconnect (the_qos,connect_flows,ACE_TRY_ENV); + ACE_TRY_CHECK; + } } if (!CORBA::is_nil (a_party) && !CORBA::is_nil (b_party)) { - // Tell the 2 VDev's about one another - this->vdev_a_->set_peer (streamctrl.in (), - this->vdev_b_.in (), - the_qos, - the_flows, - ACE_TRY_ENV); - - ACE_TRY_CHECK; - - this->vdev_b_->set_peer (streamctrl.in (), - this->vdev_a_.in (), - the_qos, - the_flows, - ACE_TRY_ENV); + if (!CORBA::is_nil (this->vdev_a_.in ()) && !CORBA::is_nil (this->vdev_b_.in ())) + { + // Tell the 2 VDev's about one another + this->vdev_a_->set_peer (this->streamctrl_.in (), + this->vdev_b_.in (), + the_qos, + the_flows, + ACE_TRY_ENV); - ACE_TRY_CHECK; + ACE_TRY_CHECK; + this->vdev_b_->set_peer (this->streamctrl_.in (), + this->vdev_a_.in (), + the_qos, + the_flows, + ACE_TRY_ENV); + ACE_TRY_CHECK; - // Now connect the streams together. This will - // establish the connection - this->sep_a_->connect (this->sep_b_.in (), - the_qos, - the_flows, - ACE_TRY_ENV); - ACE_TRY_CHECK; + // Now connect the streams together. This will + // establish the connection + CORBA::Boolean result = + this->sep_a_->connect (this->sep_b_.in (), + the_qos, + the_flows, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"sep_a->connect (sep_b) failed\n"),0); + } + else + { + // Its full profile + // we have feps in the sep then dont call connect instead call bind on the streamctrl. + this->bind (this->sep_a_.in (), + this->sep_b_.in (), + the_qos, + the_flows, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } } } ACE_CATCHANY @@ -355,8 +984,8 @@ TAO_StreamCtrl::bind_devs (AVStreams::MMDevice_ptr a_party, CORBA::Boolean TAO_StreamCtrl::bind (AVStreams::StreamEndPoint_A_ptr sep_a, AVStreams::StreamEndPoint_B_ptr sep_b, - AVStreams::streamQoS &the_qos, - const AVStreams::flowSpec &the_flows, + AVStreams::streamQoS &stream_qos, + const AVStreams::flowSpec &flow_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpFailed, @@ -366,6 +995,7 @@ TAO_StreamCtrl::bind (AVStreams::StreamEndPoint_A_ptr sep_a, this->sep_a_ = sep_a; this->sep_b_ = sep_b; + int result = 0; ACE_TRY { if (CORBA::is_nil (sep_a) || @@ -375,114 +1005,294 @@ TAO_StreamCtrl::bind (AVStreams::StreamEndPoint_A_ptr sep_a, "a_party or b_party null!"), 0); + // Define each other as their peers. + CORBA::Any sep_any; + sep_any <<= sep_b; + sep_a->define_property ("PeerAdapter", + sep_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + sep_any <<= sep_a; + sep_b->define_property ("PeerAdapter", + sep_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; // since its full profile we do the viable stream setup algorithm. // get the flows for the A streamendpoint. - if (the_flows.length () == 0) + // the flows spec is empty and hence we do a exhaustive match. + AVStreams::flowSpec a_flows,b_flows; + CORBA::Any_var flows_any; + flows_any = sep_a->get_property_value ("Flows",ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::flowSpec_ptr temp_flows; + flows_any.in () >>= temp_flows; + a_flows = *temp_flows; + flows_any = sep_b->get_property_value ("Flows",ACE_TRY_ENV); + ACE_TRY_CHECK; + flows_any.in () >>= temp_flows; + b_flows = *temp_flows; + u_int i; + FlowEndPoint_Map *a_fep_map; + FlowEndPoint_Map *b_fep_map; + ACE_NEW_RETURN (a_fep_map, + FlowEndPoint_Map, + 0); + ACE_NEW_RETURN (b_fep_map, + FlowEndPoint_Map, + 0); + for (i=0;i<a_flows.length ();i++) { - // the flows spec is empty and hence we do a exhaustive match. - AVStreams::flowSpec *a_flows = 0,*b_flows = 0; - AVStreams::FlowEndPoint_seq a_feps,b_feps; - CORBA::Any_ptr flows_any; - flows_any = sep_a->get_property_value ("Flows",ACE_TRY_ENV); + const char *flowname = a_flows[i]; + // get the flowendpoint references. + CORBA::Object_var fep_obj = + sep_a->get_fep (flowname, + ACE_TRY_ENV); ACE_TRY_CHECK; - *flows_any >>= a_flows; - flows_any = sep_b->get_property_value ("Flows",ACE_TRY_ENV); + AVStreams::FlowEndPoint_ptr fep = + AVStreams::FlowEndPoint::_narrow (fep_obj.in (), + ACE_TRY_ENV); ACE_TRY_CHECK; - *flows_any >>= b_flows; - u_int i; - for (i=0;i<a_flows->length ();i++) - { - // get the flowendpoint references. - CORBA::Object_ptr fep_obj; - fep_obj = sep_a->get_fep ((*a_flows)[i], - ACE_TRY_ENV); - ACE_TRY_CHECK; - AVStreams::FlowEndPoint_ptr fep; - fep = AVStreams::FlowEndPoint::_narrow (fep_obj, - ACE_TRY_ENV); - ACE_TRY_CHECK; - a_feps [i] = fep; - } - // get the flowendpoints for streamendpoint_b - for (i=0;i<b_flows->length ();i++) + TAO_String_Hash_Key fep_key (flowname); + result = a_fep_map->bind (fep_key,fep); + if (result == -1) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamCtrl::bind failed for %s",flowname)); + } + // get the flowendpoints for streamendpoint_b + for (i=0;i<b_flows.length ();i++) + { + const char *flowname = b_flows[i]; + // get the flowendpoint references. + CORBA::Object_var fep_obj = + sep_b->get_fep (flowname, + ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FlowEndPoint_ptr fep = + AVStreams::FlowEndPoint::_narrow (fep_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + TAO_String_Hash_Key fep_key (flowname); + result = b_fep_map->bind (fep_key,fep); + if (result == -1) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamCtrl::bind failed for %s",flowname)); + } + FlowEndPoint_Map *map_a = 0,*map_b = 0; + if (flow_spec.length () == 0) + { + map_a = a_fep_map; + map_b = b_fep_map; + } + else + { + FlowEndPoint_Map *spec_fep_map_a,*spec_fep_map_b; + ACE_NEW_RETURN (spec_fep_map_a, + FlowEndPoint_Map, + 0); + ACE_NEW_RETURN (spec_fep_map_b, + FlowEndPoint_Map, + 0); + for (i=0; i< flow_spec.length ();i++) { - // get the flowendpoint references. - CORBA::Object_ptr fep_obj; - fep_obj = sep_b->get_fep ((*b_flows)[i], - ACE_TRY_ENV); - ACE_TRY_CHECK; + TAO_Forward_FlowSpec_Entry *entry; + ACE_NEW_RETURN (entry, + TAO_Forward_FlowSpec_Entry, + 0); + entry->parse (flow_spec[i].in ()); + TAO_String_Hash_Key fep_key (entry->flowname ()); AVStreams::FlowEndPoint_ptr fep; - fep = AVStreams::FlowEndPoint::_narrow (fep_obj, - ACE_TRY_ENV); - ACE_TRY_CHECK; - b_feps [i] = fep; + result = a_fep_map->find (fep_key,fep); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"Fep not found on A side for flowname: %s",flow_spec[i].in ()),0); + + result = spec_fep_map_a->bind (fep_key,fep); + if (result == -1) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Bind faile for %s",flow_spec[i].in ())); + + result = b_fep_map->find (fep_key,fep); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"Fep not found on B side for flowname: %s",flow_spec[i].in ()),0); + + result = spec_fep_map_b->bind (fep_key,fep); + if (result == -1) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Bind faile for %s",flow_spec[i].in ())); } - // Now go thru the list of flow endpoint and match them. - // uses the first match policy. - for (i=0;i<a_feps.length ();i++) + map_a = spec_fep_map_a; + map_b = spec_fep_map_b; + } + + TAO_AV_QoS qos (stream_qos); + // Now go thru the list of flow endpoint and match them. + // uses the first match policy. + FlowEndPoint_Map_Iterator a_feps_iterator (*map_a); + FlowEndPoint_Map_Entry *a_feps_entry, *b_feps_entry; + ACE_TRY_EX (flow_connect) + { + + for (;a_feps_iterator.next (a_feps_entry) != 0; + a_feps_iterator.advance ()) { - for (u_int j=0;j<b_feps.length ();j++) + AVStreams::FlowEndPoint_ptr fep_a = a_feps_entry->int_id_; + AVStreams::FlowEndPoint_var connected_to = + fep_a->get_connected_fep (ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connect); + + if (!CORBA::is_nil (connected_to.in ())) { - AVStreams::FlowEndPoint_ptr fep_a = - AVStreams::FlowEndPoint::_narrow (a_feps [i],ACE_TRY_ENV); - ACE_TRY_CHECK; - AVStreams::FlowEndPoint_ptr fep_b = - AVStreams::FlowEndPoint::_narrow (b_feps [j],ACE_TRY_ENV); + // Skip this one, it is already connected... + continue; + } - if (fep_b->get_connected_fep () != 0) + FlowEndPoint_Map_Iterator b_feps_iterator (*map_b); + for (;b_feps_iterator.next (b_feps_entry) != 0; + b_feps_iterator.advance ()) + { + AVStreams::FlowEndPoint_ptr fep_b = b_feps_entry->int_id_; + AVStreams::FlowConnection_var flow_connection; + + AVStreams::FlowEndPoint_var connected_to = + fep_b->get_connected_fep (ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connect); + + if (!CORBA::is_nil (connected_to.in ())) + { + // Skip this one, it is already connected... + continue; + } + + if (fep_a->is_fep_compatible (fep_b, + ACE_TRY_ENV) == 1) { - if (fep_a->is_fep_compatible (fep_b, - ACE_TRY_ENV) == 1) + ACE_TRY_CHECK_EX (flow_connect); + // assume that flow names are same so that we + // can use either of them. + CORBA::Object_var flow_connection_obj; + CORBA::Any_var flowname_any = + fep_a->get_property_value ("Flow", + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connect); + char *flowname = 0; + flowname_any.in () >>= flowname; + ACE_TRY_EX (flow_connection) { - // assume that flow names are same so that we - // can use either of them. - CORBA::Object_ptr flow_connection_obj; - AVStreams::FlowConnection_ptr flow_connection; - if ((flow_connection_obj - = this->get_flow_connection ((*a_flows)[i],ACE_TRY_ENV))!= 0) - { - flow_connection = AVStreams::FlowConnection::_narrow (flow_connection_obj,ACE_TRY_ENV); - ACE_TRY_CHECK; - } - else + flow_connection_obj = + this->get_flow_connection (flowname, + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connection); + flow_connection = + AVStreams::FlowConnection::_narrow (flow_connection_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connection); + } + ACE_CATCHANY + { + TAO_FlowConnection *flowConnection; + ACE_NEW_RETURN (flowConnection, + TAO_FlowConnection, + 0); + flow_connection = flowConnection->_this (ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connect); + this->set_flow_connection (flowname, + flow_connection.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connect); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + // make sure that a_feps is flow_producer + // and b_feps is flow_consumer + // There should be a way to find which flow + // endpoint is producer and which is + // consumer. + + AVStreams::FlowProducer_var producer; + AVStreams::FlowConsumer_var consumer; + + ACE_TRY_EX (producer_check) + { + producer = + AVStreams::FlowProducer::_narrow (fep_a, + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (producer_check); + consumer = + AVStreams::FlowConsumer::_narrow (fep_b, + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (producer_check); + + // If the types don't match then try in + // the opposite order + if (CORBA::is_nil (producer.in ())) { - TAO_FlowConnection *flowConnection; - ACE_NEW_RETURN (flowConnection,TAO_FlowConnection,0); - flow_connection = flowConnection->_this (ACE_TRY_ENV); - ACE_TRY_CHECK; + producer = + AVStreams::FlowProducer::_narrow (fep_b, + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (producer_check); + consumer = + AVStreams::FlowConsumer::_narrow (fep_a, + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (producer_check); } - // make sure that a_feps is flow_producer and b_feps is flow_consumer - // There should be a way to find which flow endpoint is producer and which is consumer. - AVStreams::FlowProducer_ptr producer = - AVStreams::FlowProducer::_narrow (fep_a,ACE_TRY_ENV); - ACE_TRY_CHECK; - AVStreams::FlowConsumer_ptr consumer = - AVStreams::FlowConsumer::_narrow (fep_b,ACE_TRY_ENV); - ACE_TRY_CHECK; - // what should be passed to QoS? - flow_connection->connect (producer,consumer,the_qos [0],ACE_TRY_ENV); - fep_a->set_peer (flow_connection,fep_b,the_qos[0],ACE_TRY_ENV); - fep_b->set_peer (flow_connection,fep_a,the_qos[0],ACE_TRY_ENV); + // At this point they should both be + // non-nil + // @@ raise an exception (which one?) if + // this is not true... + ACE_ASSERT (!CORBA::is_nil (producer.in ())); + ACE_ASSERT (!CORBA::is_nil (consumer.in ())); } + ACE_CATCHANY + { + ACE_RETHROW; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + CORBA::String_var fep_a_name,fep_b_name; + CORBA::String temp_name; + flowname_any = fep_a->get_property_value ("FlowName", + ACE_TRY_ENV); + flowname_any.in () >>= temp_name; + fep_a_name = CORBA::string_dup (temp_name); + flowname_any = fep_b->get_property_value ("FlowName", + ACE_TRY_ENV); + flowname_any.in () >>= temp_name; + fep_b_name = CORBA::string_dup (temp_name); + AVStreams::QoS flow_qos; + flow_qos.QoSType = fep_a_name; + flow_qos.QoSParams.length (0); + result = qos.get_flow_qos (fep_a_name.in (),flow_qos); + if (result == -1) + { + flow_qos.QoSType = fep_b_name; + result = qos.get_flow_qos (fep_b_name.in (), + flow_qos); + if (result == -1 && TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + "No QoS Specified for this flow <%s>\n", flowname)); + } + flow_connection->connect (producer.in (), + consumer.in (), + flow_qos, + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connect); } } } } - else + ACE_CATCHANY { - // since the flow spec is not empty we need to query for the - // flows mentioned on both the A and B sides. - // not implemented yet. + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_StreamCtrl::bind:flow_connect block"); + return 0; } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); } ACE_CATCHANY { // error was thrown because one of the streamendpoints is light profile. // Now connect the streams together this->sep_a_->connect (this->sep_b_.in (), - the_qos, - the_flows, - ACE_TRY_ENV); + stream_qos, + flow_spec, + ACE_TRY_ENV); ACE_TRY_CHECK; } ACE_ENDTRY; @@ -491,24 +1301,20 @@ 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_UNUSED_ARG (ACE_TRY_ENV); } void -TAO_StreamCtrl::unbind_party (AVStreams::StreamEndPoint_ptr the_ep, - const AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) +TAO_StreamCtrl::unbind_party (AVStreams::StreamEndPoint_ptr /* the_ep */, + const AVStreams::flowSpec &/* the_spec */, + CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpFailed, AVStreams::noSuchFlow)) { - ACE_UNUSED_ARG (the_ep); - ACE_UNUSED_ARG (the_spec); - ACE_UNUSED_ARG (ACE_TRY_ENV); } void @@ -519,17 +1325,27 @@ TAO_StreamCtrl::unbind_dev (AVStreams::MMDevice_ptr /* dev */, AVStreams::streamOpFailed, AVStreams::noSuchFlow)) { - } AVStreams::VDev_ptr -TAO_StreamCtrl::get_related_vdev (AVStreams::MMDevice_ptr /* adev */, - AVStreams::StreamEndPoint_out /* sep */, +TAO_StreamCtrl::get_related_vdev (AVStreams::MMDevice_ptr adev, + AVStreams::StreamEndPoint_out sep, CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpFailed)) { - return AVStreams::VDev::_nil (); + MMDevice_Map_Hash_Key key (adev); + MMDevice_Map_Entry entry; + int result = -1; + result = this->mmdevice_a_map_.find (key,entry); + if (result < 0) + { + result = this->mmdevice_a_map_.find (key,entry); + if (result < 0) + return AVStreams::VDev::_nil (); + } + sep = AVStreams::StreamEndPoint::_duplicate (entry.sep_.in ()); + return AVStreams::VDev::_duplicate (entry.vdev_.in ()); } CORBA::Boolean @@ -543,7 +1359,7 @@ TAO_StreamCtrl::modify_QoS (AVStreams::streamQoS &the_qos, if (this->mcastconfigif_ != 0) { // call modify_Qos on the root VDev which is the mcast configif. - ACE_DEBUG ((LM_DEBUG,"Cannot Modify the Qos for multipoint streams\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Cannot Modify the Qos for multipoint streams\n")); } else { @@ -556,55 +1372,170 @@ TAO_StreamCtrl::modify_QoS (AVStreams::streamQoS &the_qos, // TAO_MCastConfigIf // ---------------------------------------------------------------------- +TAO_MCastConfigIf::TAO_MCastConfigIf (void) + :peer_list_iterator_ (peer_list_) +{ +} + +TAO_MCastConfigIf::~TAO_MCastConfigIf (void) +{ + //no-op +} + +// In future this should be a multicast message instead of point-to-point unicasts. CORBA::Boolean -TAO_MCastConfigIf::set_peer (CORBA::Object_ptr /* peer */, - AVStreams::streamQoS & /* the_qos */, - const AVStreams::flowSpec & /* the_spec */, - CORBA::Environment &/* ACE_TRY_ENV */) +TAO_MCastConfigIf::set_peer (CORBA::Object_ptr peer, + AVStreams::streamQoS & qos, + const AVStreams::flowSpec & flow_spec, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)) { - return 0; + ACE_TRY + { + Peer_Info *info; + ACE_NEW_RETURN (info, + Peer_Info, + 0); + info->peer_ = AVStreams::VDev::_narrow (peer,ACE_TRY_ENV); + ACE_TRY_CHECK; + info->qos_ = qos; + info->flow_spec_ = flow_spec; + this->peer_list_.insert_tail (info); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MCastConfigIf::set_peer"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; } +// In future this should be a multicast message instead of point-to-point unicasts. void -TAO_MCastConfigIf::configure (const CosPropertyService::Property & /* a_configuration */, - CORBA::Environment &/* ACE_TRY_ENV */) +TAO_MCastConfigIf::configure (const CosPropertyService::Property & a_configuration, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException)) { + Peer_Info *info; + ACE_TRY + { + this->peer_list_iterator_.first (); + info = this->peer_list_iterator_.next (); + while (info != 0) + { + info->peer_->configure (a_configuration,ACE_TRY_ENV); + ACE_TRY_CHECK; + info = this->peer_list_iterator_.next (); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MCastConfigIf::set_configure"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } + void -TAO_MCastConfigIf::set_initial_configuration (const CosPropertyService::Properties & /* initial */, - CORBA::Environment &/* ACE_TRY_ENV */) +TAO_MCastConfigIf::set_initial_configuration (const CosPropertyService::Properties &initial, + CORBA::Environment &/*ACE_TRY_ENV*/) ACE_THROW_SPEC ((CORBA::SystemException)) { + this->initial_configuration_ = initial; } +// In future this should be a multicast message instead of point-to-point unicasts. void -TAO_MCastConfigIf::set_format (const char * /* flowName */, - const char * /* format_name */, - CORBA::Environment &/* ACE_TRY_ENV */) +TAO_MCastConfigIf::set_format (const char * flowName, + const char * format_name, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)) { + Peer_Info *info; + ACE_TRY + { + this->peer_list_iterator_.first (); + info = this->peer_list_iterator_.next (); + while (info != 0) + { + if (this->in_flowSpec (info->flow_spec_,flowName)) + { + info->peer_->set_format (flowName,format_name,ACE_TRY_ENV); + ACE_TRY_CHECK; + } + info = this->peer_list_iterator_.next (); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MCastConfigIf::set_format"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } +// In future this should be a multicast message instead of point-to-point unicasts. void -TAO_MCastConfigIf::set_dev_params (const char * /* flowName */, - const CosPropertyService::Properties & /* new_params */, - CORBA::Environment &/* ACE_TRY_ENV */) +TAO_MCastConfigIf::set_dev_params (const char * flowName, + const CosPropertyService::Properties & new_params, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::PropertyException, AVStreams::streamOpFailed)) { + Peer_Info *info; + ACE_TRY + { + + this->peer_list_iterator_.first (); + info = this->peer_list_iterator_.next (); + while (info != 0) + { + if (this->in_flowSpec (info->flow_spec_,flowName)) + { + info->peer_->set_dev_params (flowName,new_params,ACE_TRY_ENV); + ACE_TRY_CHECK; + } + info = this->peer_list_iterator_.next (); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MCastConfigIf::set_dev_params"); + return; + } + ACE_ENDTRY; + ACE_CHECK; +} + +int +TAO_MCastConfigIf::in_flowSpec (const AVStreams::flowSpec& flow_spec, const char *flow_name) +{ + int len = strlen (flow_name); + for (u_int i=0;i<flow_spec.length ();i++) + if (ACE_OS::strncmp (flow_spec[i],flow_name,len) == 0) + { + return 1; + } + return 0; } // ---------------------------------------------------------------------- // TAO_Base_StreamEndPoint // ---------------------------------------------------------------------- +TAO_Base_StreamEndPoint::TAO_Base_StreamEndPoint (void) +{ +} + TAO_Base_StreamEndPoint::~TAO_Base_StreamEndPoint (void) { } @@ -617,231 +1548,304 @@ TAO_Base_StreamEndPoint::handle_close (void) return -1; } - -// ---------------------------------------------------------------------- -// TAO_Client_StreamEndPoint -// ---------------------------------------------------------------------- - -TAO_Client_StreamEndPoint::TAO_Client_StreamEndPoint (void) +int +TAO_Base_StreamEndPoint::handle_open (void) { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) TAO_Client_StreamEndPoint::TAO_Client_StreamEndPoint: created\n")); + return 0; } -CORBA::Boolean -TAO_Client_StreamEndPoint::connect (AVStreams::StreamEndPoint_ptr responder, - AVStreams::streamQoS &qos_spec, - const AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::streamOpFailed)) +int +TAO_Base_StreamEndPoint::handle_stop (const AVStreams::flowSpec &, + CORBA::Environment &) { - CORBA::Boolean retv = 0; - - ACE_TRY - { - AVStreams::flowSpec flow_spec (the_spec); - this->handle_preconnect (flow_spec); - - AVStreams::StreamEndPoint_var streamendpoint = this->_this (ACE_TRY_ENV); - ACE_TRY_CHECK; - // Use the base class implementation of connect - responder->request_connection (streamendpoint.in (), - 0, - qos_spec, - flow_spec, - ACE_TRY_ENV); + return 0; +} - ACE_TRY_CHECK; +int +TAO_Base_StreamEndPoint::handle_start (const AVStreams::flowSpec &, + CORBA::Environment &) +{ + return 0; +} - // Make the upcall to the app - retv = this->handle_postconnect (flow_spec); - } - ACE_CATCHANY - { - return 0; - } - ACE_ENDTRY; - ACE_CHECK_RETURN (0); - return retv; +int +TAO_Base_StreamEndPoint::handle_destroy (const AVStreams::flowSpec &, + CORBA::Environment &) +{ + return 0; } +// The following function is for backward compatibility. +CORBA::Boolean +TAO_Base_StreamEndPoint::handle_preconnect (AVStreams::flowSpec &) +{ + return 1; +} -// @@ Need to throw not-supported exception here +// The following function is for backward compatibility. CORBA::Boolean -TAO_Client_StreamEndPoint::multiconnect (AVStreams::streamQoS &the_qos, - AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::streamOpFailed)) +TAO_Base_StreamEndPoint::handle_postconnect (AVStreams::flowSpec &) { - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (the_spec); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + return 1; } -// Multicast is not supported yet. +// The following function is for backward compatibility. CORBA::Boolean -TAO_Client_StreamEndPoint::connect_leaf (AVStreams::StreamEndPoint_B_ptr the_ep, - AVStreams::streamQoS &the_qos, - const AVStreams::flowSpec &the_flows, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::notSupported)) +TAO_Base_StreamEndPoint::handle_connection_requested (AVStreams::flowSpec &, + CORBA::Environment &) { - ACE_UNUSED_ARG (the_ep); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (the_flows); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + return 1; } -// Multicast not supported yet. -void -TAO_Client_StreamEndPoint::disconnect_leaf (AVStreams::StreamEndPoint_B_ptr the_ep, - const AVStreams::flowSpec &theSpec, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::noSuchFlow)) +int +TAO_Base_StreamEndPoint::set_protocol_object (const char */*flowname*/, + TAO_AV_Protocol_Object * /*sfp_object*/) { - ACE_UNUSED_ARG (the_ep); - ACE_UNUSED_ARG (theSpec); - ACE_UNUSED_ARG (ACE_TRY_ENV); + return -1; } -TAO_Client_StreamEndPoint::~TAO_Client_StreamEndPoint (void) +int +TAO_Base_StreamEndPoint::get_callback (const char */*flowname*/, + TAO_AV_Callback *&/*sfp_callback*/) { + return -1; } -// ---------------------------------------------------------------------- -// TAO_Server_StreamEndPoint -// ---------------------------------------------------------------------- +int +TAO_Base_StreamEndPoint::get_control_callback (const char */*flowname*/, + TAO_AV_Callback *&/*sfp_callback*/) +{ + return -1; +} -TAO_Server_StreamEndPoint::TAO_Server_StreamEndPoint (void) +void +TAO_Base_StreamEndPoint::set_handler (const char *flowname, + TAO_AV_Flow_Handler *handler) { - ACE_DEBUG ((LM_DEBUG, - "\n(%P|%t) TAO_Server_StreamEndPoint::TAO_Server_StreamEndPoint: created")); } +// ---------------------------------------------------------------------- +// TAO_StreamEndPoint +// ---------------------------------------------------------------------- -// Called by streamctrl, requesting us to call request_connection -// on the responder (to initiate a connection) -CORBA::Boolean -TAO_Server_StreamEndPoint::connect (AVStreams::StreamEndPoint_ptr responder, - AVStreams::streamQoS &qos_spec, - const AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::streamOpFailed)) +// constructor. + +TAO_StreamEndPoint::TAO_StreamEndPoint (void) + :flow_count_ (0), + flow_num_ (0), + mcast_port_ (ACE_DEFAULT_MULTICAST_PORT+1) { - ACE_UNUSED_ARG (responder); - ACE_UNUSED_ARG (qos_spec); - ACE_UNUSED_ARG (the_spec); - ACE_UNUSED_ARG (ACE_TRY_ENV); - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Calling TAO_Server_StreamEndPoint::connect" - " is not compatible with the spec!" - "\n"), - 0); + this->mcast_addr_ = ACE_OS::inet_addr (ACE_DEFAULT_MULTICAST_ADDR); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint::TAO_StreamEndPoint::mcast_addr = %ud",this->mcast_addr_)); + // this->handle_open (); } + CORBA::Boolean -TAO_Server_StreamEndPoint::request_connection (AVStreams::StreamEndPoint_ptr initiator, - CORBA::Boolean is_mcast, - AVStreams::streamQoS &qos, - AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpDenied, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::FPError)) +TAO_StreamEndPoint::connect (AVStreams::StreamEndPoint_ptr responder, + AVStreams::streamQoS &qos, + const AVStreams::flowSpec &the_spec, + CORBA::Environment &ACE_TRY_ENV) { - int result = 0; - ACE_TRY + CORBA::Boolean retv = 0; + this->peer_sep_ = AVStreams::StreamEndPoint::_duplicate (responder); + ACE_TRY_EX (negotiate) { - // Use the base class implementation of request_connection - TAO_StreamEndPoint::request_connection (initiator, - is_mcast, + if (!CORBA::is_nil (this->negotiator_.in ())) + { + CORBA::Any_var negotiator_any = responder->get_property_value ("Negotiator"); + + AVStreams::Negotiator_ptr peer_negotiator; + negotiator_any.in () >>= peer_negotiator; + if (!CORBA::is_nil (peer_negotiator)) + { + CORBA::Boolean result = + this->negotiator_->negotiate (peer_negotiator, qos, - the_spec, ACE_TRY_ENV); + ACE_TRY_CHECK_EX (negotiate); + if (!result) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint::Connect (): negotiate failed\n")); + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamEndPoint::negotiate"); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + ACE_TRY_EX (available_protocols) + { + if (this->protocols_.length () > 0) + { + // choose protocols based on what the remote endpoint can support. + CORBA::Any_var protocols_any = + responder->get_property_value ("AvailableProtocols",ACE_TRY_ENV); + ACE_TRY_CHECK_EX (available_protocols); + AVStreams::protocolSpec peer_protocols; + AVStreams::protocolSpec_ptr temp_protocols; + protocols_any.in () >>= temp_protocols; + peer_protocols = *temp_protocols; + for (u_int i=0;i<peer_protocols.length ();i++) + { + for (u_int j=0;j<this->protocols_.length ();j++) + if (ACE_OS::strcmp (peer_protocols [i], + this->protocols_[j]) == 0) + { + // we'll agree upon the first protocol that matches. + this->protocol_ = CORBA::string_copy (peer_protocols [i]); + break; + } + } + } + } + ACE_CATCHANY + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Availableprotocols property not defined\n")); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + ACE_TRY + { + AVStreams::streamQoS network_qos; + if (qos.length () > 0) + { + int result = this->translate_qos (qos,network_qos); + if (result != 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"QoS translation failed\n")); + } + AVStreams::flowSpec flow_spec (the_spec); + this->handle_preconnect (flow_spec); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint::connect: flow_spec_length = %d", + flow_spec.length ())); + u_int i; + for (i=0;i<flow_spec.length ();i++) + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, + "TAO_StreamEndPoint::connect:%s\n", + flow_spec[i].in ())); + TAO_Forward_FlowSpec_Entry *entry = 0; + // if (i >= FLOWSPEC_MAX) + ACE_NEW_RETURN (entry, + TAO_Forward_FlowSpec_Entry, + 0); +// else +// entry = &this->forward_entries_[i]; + if (entry->parse (flow_spec[i]) == -1) + return 0; + 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, + flow_spec); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_Core::init_forward_flows failed\n"),0); + + AVStreams::StreamEndPoint_var streamendpoint = this->_this (ACE_TRY_ENV); ACE_TRY_CHECK; - // Make the upcall to the app - result = this->handle_connection_requested (the_spec,ACE_TRY_ENV); + retv = responder->request_connection (streamendpoint.in (), + 0, + network_qos, + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (retv == 0) + return retv; + for (i=0;i<flow_spec.length ();i++) + { + TAO_Reverse_FlowSpec_Entry *entry = 0; + // if (i >= FLOWSPEC_MAX) + ACE_NEW_RETURN (entry, + TAO_Reverse_FlowSpec_Entry, + 0); +// else +// entry = &this->reverse_entries_[i]; + if (entry->parse (flow_spec[i].in ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR,"Reverse_Flow_Spec_Set::parse failed\n"),0); + this->reverse_flow_spec_set.insert (entry); + } + result = TAO_AV_CORE::instance ()->init_reverse_flows (this, + this->forward_flow_spec_set, + 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"),0); + // Make the upcall to the app + retv = this->handle_postconnect (flow_spec); } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Server_StreamEndpoint::request_connection"); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamEndPoint::connect"); return 0; } ACE_ENDTRY; - ACE_CHECK_RETURN (1); - return result; + ACE_CHECK_RETURN (0); + return retv; } -CORBA::Boolean -TAO_Server_StreamEndPoint::multiconnect (AVStreams::streamQoS &the_qos, - AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::FPError)) +int +TAO_StreamEndPoint::translate_qos (const AVStreams::streamQoS& application_qos, + AVStreams::streamQoS& network_qos) { - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (the_spec); - ACE_UNUSED_ARG (ACE_TRY_ENV); + u_int len = application_qos.length (); + network_qos.length (len); + for (u_int i=0;i<len;i++) + { + network_qos [i].QoSType = application_qos [i].QoSType; + } return 0; } -TAO_Server_StreamEndPoint::~TAO_Server_StreamEndPoint (void) -{ -} - - -// ---------------------------------------------------------------------- -// TAO_StreamEndPoint -// ---------------------------------------------------------------------- - -// constructor. - -TAO_StreamEndPoint::TAO_StreamEndPoint (void) - :flow_count_ (1) -{ - // this->handle_open (); -} - // Stop the physical flow of data on the stream // Empty the_spec --> apply to all flows void -TAO_StreamEndPoint::stop (const AVStreams::flowSpec &the_spec, +TAO_StreamEndPoint::stop (const AVStreams::flowSpec &flow_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)) { // Make the upcall into the app - this->handle_stop (the_spec, ACE_TRY_ENV); + this->handle_stop (flow_spec, ACE_TRY_ENV); + if (flow_spec.length () > 0) + { + + for (u_int i=0;i<flow_spec.length ();i++) + { + TAO_AV_FlowSpecSetItor end = this->forward_flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor begin = this->forward_flow_spec_set.begin (); + begin != end; ++begin) + { + if (ACE_OS::strcmp ((*begin)->flowname (),flow_spec [i].in ()) == 0) + { + TAO_FlowSpec_Entry *entry = *begin; + // (*begin)->protocol_object ()->stop (); + entry->handler ()->stop (entry->role ()); + break; + } + } + } + } + else + { + TAO_AV_FlowSpecSetItor end = this->forward_flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor begin = this->forward_flow_spec_set.begin (); + begin != end; ++begin) + { + TAO_FlowSpec_Entry *entry = *begin; + // entry->protocol_object ()->stop (); + entry->handler ()->stop (entry->role ()); + } + } } // Start the physical flow of data on the stream // Empty the_spec --> apply to all flows - void TAO_StreamEndPoint::start (const AVStreams::flowSpec &flow_spec, CORBA::Environment &ACE_TRY_ENV) @@ -850,87 +1854,156 @@ TAO_StreamEndPoint::start (const AVStreams::flowSpec &flow_spec, { // Make the upcall into the app this->handle_start (flow_spec, ACE_TRY_ENV); + if (flow_spec.length () > 0) + { + // Now call start on all the flow handlers. + for (u_int i=0;i<flow_spec.length ();i++) + { + TAO_AV_FlowSpecSetItor end = this->forward_flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor begin = this->forward_flow_spec_set.begin (); + begin != end; ++begin) + { + TAO_FlowSpec_Entry *entry = *begin; + if (ACE_OS::strcmp (entry->flowname (),flow_spec [i]) == 0) + { + // entry->protocol_object ()->start (); + entry->handler ()->start (entry->role ()); + break; + } + } + } + } + else + { + TAO_AV_FlowSpecSetItor end = this->forward_flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor begin = this->forward_flow_spec_set.begin (); + begin != end; ++begin) + { + TAO_FlowSpec_Entry *entry = *begin; + // entry->protocol_object ()->start (); + entry->handler ()->start (entry->role ()); + } + } } // Close the connection - void -TAO_StreamEndPoint::destroy (const AVStreams::flowSpec &/* the_spec */, - CORBA::Environment &ACE_TRY_ENV) +TAO_StreamEndPoint::destroy (const AVStreams::flowSpec &flow_spec, + CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)) { -// // Make the upcall into the app -// this->handle_destroy (the_spec, ACE_TRY_ENV); - // - // Remove self from POA. Because of reference counting, the POA - // will automatically delete the servant when all pending requests - // on this servant are complete. - // - PortableServer::POA_var poa = this->_default_POA (ACE_TRY_ENV); - ACE_CHECK; + int result = deactivate_servant (this); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint::destroy failed\n")); - PortableServer::ObjectId_var id = poa->servant_to_id (this, - ACE_TRY_ENV); - ACE_CHECK; + if (flow_spec.length () > 0) + { + for (u_int i=0;i<flow_spec.length ();i++) + { + TAO_AV_FlowSpecSetItor end = this->forward_flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor begin = this->forward_flow_spec_set.begin (); + begin != end; ++begin) + { + TAO_FlowSpec_Entry *entry = *begin; + if (ACE_OS::strcmp (entry->flowname (),flow_spec [i]) == 0) + { + entry->protocol_object ()->destroy (); + break; + } + } + } + } + else + { + TAO_AV_FlowSpecSetItor end = this->forward_flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor begin = this->forward_flow_spec_set.begin (); + begin != end; ++begin) + { + TAO_FlowSpec_Entry *entry = *begin; + entry->protocol_object ()->destroy (); + } + } - poa->deactivate_object (id.in (), - ACE_TRY_ENV); - ACE_CHECK; + // Make the upcall into the app + // this->handle_destroy (the_spec, ACE_TRY_ENV); + // } // Called by our peer endpoint, requesting us to establish // a connection - CORBA::Boolean -TAO_StreamEndPoint::request_connection (AVStreams::StreamEndPoint_ptr initiator, +TAO_StreamEndPoint::request_connection (AVStreams::StreamEndPoint_ptr /*initiator*/, CORBA::Boolean is_mcast, - AVStreams::streamQoS &qos, - AVStreams::flowSpec &the_spec, - CORBA::Environment &) + AVStreams::streamQoS &/*qos*/, + AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpDenied, AVStreams::noSuchFlow, AVStreams::QoSRequestFailed, AVStreams::FPError)) -{ - ACE_UNUSED_ARG (initiator); - ACE_UNUSED_ARG (is_mcast); - ACE_UNUSED_ARG (qos); - - ACE_DEBUG ((LM_DEBUG, "\n(%P|%t) TAO_StreamEndPoint::request_connection called")); - ACE_DEBUG ((LM_DEBUG, - "\n(%P|%t) TAO_StreamEndPoint::request_connection: " - "flowspec has length = %d" - "and the strings are:", - the_spec.length ())); - for (u_int i = 0; i < the_spec.length (); i++) - ACE_DEBUG ((LM_DEBUG, - the_spec [i])); - return 0; +{ + int result = 0; + ACE_TRY + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "\n(%P|%t) TAO_StreamEndPoint::request_connection called")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, + "\n(%P|%t) TAO_StreamEndPoint::request_connection: " + "flowspec has length = %d" + "and the strings are:", + flow_spec.length ())); + u_int i; + for (i = 0; i < flow_spec.length (); i++) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,flow_spec [i])); + + for (i=0;i<flow_spec.length ();i++) + { + TAO_Forward_FlowSpec_Entry *entry = 0; + ACE_NEW_RETURN (entry, + TAO_Forward_FlowSpec_Entry, + 0); + if (entry->parse (flow_spec[i]) == -1) + return 0; + 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, + flow_spec); + if (result < 0) + return 0; + // Make the upcall to the app + result = this->handle_connection_requested (flow_spec,ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamEndpoint::request_connection"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return result; } -// @@ Need to throw not-supported exception here - +// Refers to modification of transport QoS. CORBA::Boolean -TAO_StreamEndPoint::modify_QoS (AVStreams::streamQoS &new_qos, - const AVStreams::flowSpec &the_flows, - CORBA::Environment &ACE_TRY_ENV) +TAO_StreamEndPoint::modify_QoS (AVStreams::streamQoS &/* new_qos */, + const AVStreams::flowSpec &/* the_flows */, + CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)) { - ACE_UNUSED_ARG (new_qos); - ACE_UNUSED_ARG (the_flows); - ACE_UNUSED_ARG (ACE_TRY_ENV); return 0; } -// @@ Need to throw not-supported exception here +// Sets the list of protocols this streamendpoint can understand. CORBA::Boolean -TAO_StreamEndPoint::set_protocol_restriction (const AVStreams::protocolSpec &the_pspec, +TAO_StreamEndPoint::set_protocol_restriction (const AVStreams::protocolSpec &protocols, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException)) { @@ -938,11 +2011,12 @@ TAO_StreamEndPoint::set_protocol_restriction (const AVStreams::protocolSpec &the { CORBA::Any protocol_restriction_any; - protocol_restriction_any <<= the_pspec; + protocol_restriction_any <<= protocols; this->define_property ("ProtocolRestriction", protocol_restriction_any, ACE_TRY_ENV); ACE_TRY_CHECK; + this->protocols_ = protocols; } ACE_CATCHANY { @@ -966,21 +2040,21 @@ TAO_StreamEndPoint::disconnect (const AVStreams::flowSpec &the_spec, ACE_UNUSED_ARG (ACE_TRY_ENV); } -// @@ Need to throw not-supported exception here +// Sets the status of the flow protocol. void -TAO_StreamEndPoint::set_FPStatus (const AVStreams::flowSpec &the_spec, +TAO_StreamEndPoint::set_FPStatus (const AVStreams::flowSpec &/*the_spec*/, const char *fp_name, const CORBA::Any &fp_settings, - CORBA::Environment &ACE_TRY_ENV) + CORBA::Environment &/*ACE_TRY_ENV*/) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::FPError)) { - ACE_UNUSED_ARG (the_spec); - ACE_UNUSED_ARG (fp_name); - ACE_UNUSED_ARG (fp_settings); - ACE_UNUSED_ARG (ACE_TRY_ENV); + if (ACE_OS::strcmp (fp_name,"SFP1.0") != 0) + return; + fp_settings >>= this->sfp_status_; + // @@Naga: We should call set_FPStatus on all the protocol objects. } @@ -1000,19 +2074,19 @@ TAO_StreamEndPoint::get_fep (const char *flow_name, char * -TAO_StreamEndPoint::add_fep (CORBA::Object_ptr the_fep, +TAO_StreamEndPoint::add_fep (CORBA::Object_ptr fep_obj, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported, AVStreams::streamOpFailed)) { char *flow_name = 0; + AVStreams::FlowEndPoint_ptr fep = AVStreams::FlowEndPoint::_nil (); ACE_TRY_EX (flow_name); { ACE_NEW_RETURN (flow_name,char [BUFSIZ],0); CORBA::Any_ptr flow_name_any; - AVStreams::FlowEndPoint_ptr fep = - AVStreams::FlowEndPoint::_narrow (the_fep,ACE_TRY_ENV); + fep = AVStreams::FlowEndPoint::_narrow (fep_obj,ACE_TRY_ENV); ACE_TRY_CHECK_EX (flow_name); flow_name_any = fep->get_property_value ("FlowName",ACE_TRY_ENV); ACE_TRY_CHECK_EX (flow_name); @@ -1022,17 +2096,36 @@ TAO_StreamEndPoint::add_fep (CORBA::Object_ptr the_fep, { // exception implies the flow name is not defined and is system generated. ACE_OS::sprintf (flow_name,"flow%d",flow_num_++); + ACE_TRY_EX (flow) + { + // exception implies the flow name is not defined and is system generated. + ACE_OS::sprintf (flow_name,"flow%d",flow_num_++); + CORBA::Any flowname_any; + flowname_any <<= flow_name; + fep->define_property ("Flow",flowname_any,ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamEndPoint::add_fep"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); } ACE_ENDTRY; - // Add it to the sequence of flowNames supported. - // put the flowname and the flowendpoint in a hashtable. - TAO_String_Hash_Key fep_name_key (flow_name); - if (this->fep_map_.bind (fep_name_key,the_fep) != 0) - { - ACE_THROW_RETURN (AVStreams::streamOpFailed (),0); - } - ACE_TRY_EX (flows) + ACE_CHECK_RETURN (0); + ACE_TRY { + fep->lock (ACE_TRY_ENV); + ACE_TRY_CHECK; + // Add it to the sequence of flowNames supported. + // put the flowname and the flowendpoint in a hashtable. + TAO_String_Hash_Key fep_name_key (CORBA::string_dup (flow_name)); + if (this->fep_map_.bind (fep_name_key,fep) != 0) + { + ACE_THROW_RETURN (AVStreams::streamOpFailed (),0); + } // increment the flow count. this->flow_count_++; this->flows_.length (this->flow_count_); @@ -1043,7 +2136,7 @@ TAO_StreamEndPoint::add_fep (CORBA::Object_ptr the_fep, this->define_property ("Flows", flows_any, ACE_TRY_ENV); - ACE_TRY_CHECK_EX (flows); + ACE_TRY_CHECK; } ACE_CATCHANY { @@ -1066,7 +2159,7 @@ TAO_StreamEndPoint::remove_fep (const char *flow_name, ACE_TRY { TAO_String_Hash_Key fep_name_key (flow_name); - CORBA::Object_ptr fep_entry = 0; + AVStreams::FlowEndPoint_ptr fep_entry = 0; // Remove the fep from the hash table. if (this->fep_map_.unbind (fep_name_key,fep_entry)!= 0) ACE_THROW (AVStreams::streamOpFailed ()); @@ -1092,8 +2185,7 @@ TAO_StreamEndPoint::remove_fep (const char *flow_name, ACE_CHECK; } -// @@ Need to throw not-supported exception here - +// Sets the negotiator object. void TAO_StreamEndPoint::set_negotiator (AVStreams::Negotiator_ptr new_negotiator, CORBA::Environment &ACE_TRY_ENV) @@ -1107,6 +2199,7 @@ TAO_StreamEndPoint::set_negotiator (AVStreams::Negotiator_ptr new_negotiator, negotiator, ACE_TRY_ENV); ACE_TRY_CHECK; + this->negotiator_ = AVStreams::Negotiator::_duplicate (new_negotiator); } ACE_CATCHANY { @@ -1117,7 +2210,6 @@ TAO_StreamEndPoint::set_negotiator (AVStreams::Negotiator_ptr new_negotiator, } // Sets the public key used for this streamendpoint. - void TAO_StreamEndPoint::set_key (const char *flow_name, const AVStreams::key & the_key, @@ -1126,7 +2218,7 @@ TAO_StreamEndPoint::set_key (const char *flow_name, { ACE_TRY { - + this->key_ = the_key; CORBA::Any PublicKey; PublicKey <<= the_key; char PublicKey_property [BUFSIZ]; @@ -1145,7 +2237,6 @@ TAO_StreamEndPoint::set_key (const char *flow_name, } // Set the source id. - void TAO_StreamEndPoint::set_source_id (CORBA::Long source_id, CORBA::Environment &) @@ -1154,10 +2245,405 @@ TAO_StreamEndPoint::set_source_id (CORBA::Long source_id, this->source_id_ = source_id; } +CORBA::Boolean +TAO_StreamEndPoint::multiconnect (AVStreams::streamQoS &/*the_qos*/, + AVStreams::flowSpec &/*flow_spec*/, + CORBA::Environment &/*ACE_TRY_ENV*/) +{ + return 0; +} 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. + for ( ; begin != end; ++begin,++i) + { +// if (i >= FLOWSPEC_MAX) +// { + TAO_FlowSpec_Entry *entry = *begin; + delete entry; + // } + } + begin = this->reverse_flow_spec_set.begin (); + end = this->reverse_flow_spec_set.end (); + i = 0; + for (; begin != end; ++begin) + { +// if (i >= FLOWSPEC_MAX) +// { + TAO_FlowSpec_Entry *entry = *begin; + delete entry; + // } + } +} + + +// ---------------------------------------------------------------------- +// TAO_StreamEndPoint_A +// ---------------------------------------------------------------------- + +TAO_StreamEndPoint_A::TAO_StreamEndPoint_A (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t) TAO_StreamEndPoint_A::TAO_StreamEndPoint_A: created\n")); +} + +// IP Multicast style connect. +CORBA::Boolean +TAO_StreamEndPoint_A::multiconnect (AVStreams::streamQoS &stream_qos, + AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint::multiconnect\n")); + ACE_TRY + { + int result = 0; + TAO_AV_QoS qos (stream_qos); + for (u_int i=0;i< flow_spec.length ();i++) + { + TAO_Forward_FlowSpec_Entry *forward_entry; + ACE_NEW_RETURN (forward_entry, + TAO_Forward_FlowSpec_Entry, + 0); + forward_entry->parse (flow_spec[i]); + TAO_String_Hash_Key mcast_key (forward_entry->flowname ()); + AVStreams::FlowEndPoint_ptr flow_endpoint = AVStreams::FlowEndPoint::_nil (); + // @@Naga: There is a problem in the full profile case for multiconnect. Since + // multiconnect on sep_a is called everytime a sink is added and if called for + // the same flow twice, the following code will just call add producer on the flow connection. + // It is however very hard to find out if the flow producer is already in the flow connection + // since comparing object references will not work and the flowproducer reference is + // generated by _narrow. Our only hope is that _narrow on the same fep will return the same + // pointer for the flowproducer in which case we can find out if the flowproducer exists in + // fep set for that flowconnection. + if (this->fep_map_.find (mcast_key,flow_endpoint) == 0) + { + ACE_TRY_EX (narrow) + { + AVStreams::QoS flow_qos; + result = qos.get_flow_qos (forward_entry->flowname (),flow_qos); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"QoS not found for %s",forward_entry->flowname ())); + // Narrow it to FlowProducer. + AVStreams::FlowProducer_var producer = AVStreams::FlowProducer::_narrow (flow_endpoint,ACE_TRY_ENV); + ACE_TRY_CHECK_EX (narrow); + // Else narrow succeeeded. + if (!CORBA::is_nil (producer.in ())) + { + AVStreams::FlowConnection_var flow_connection; + ACE_TRY_EX (flow_connection) + { + if (CORBA::is_nil (this->streamctrl_.in ())) + { + CORBA::Any_var streamctrl_any; + streamctrl_any = this->get_property_value ("Related_StreamCtrl", + ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::StreamCtrl_ptr streamctrl; + streamctrl_any.in () >>= streamctrl; + this->streamctrl_ = AVStreams::StreamCtrl::_duplicate (streamctrl); + } + + CORBA::Object_var flow_connection_obj = + this->streamctrl_->get_flow_connection (forward_entry->flowname (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connection); + flow_connection = AVStreams::FlowConnection::_narrow (flow_connection_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connection); + } + ACE_CATCHANY + { + TAO_FlowConnection *flowConnection; + ACE_NEW_RETURN (flowConnection, + TAO_FlowConnection, + 0); + //@@ Strategize the multicast address allocation. + flowConnection->set_mcast_addr (this->mcast_addr_,this->mcast_port_); + this->mcast_port_++; + flowConnection->set_protocol (forward_entry->carrier_protocol_str ()); + flow_connection = flowConnection->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + this->streamctrl_->set_flow_connection (forward_entry->flowname (), + flow_connection.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + if (ACE_OS::strcmp (forward_entry->flow_protocol_str (),"") != 0) + { + CORBA::Any fp_settings; + flow_connection->use_flow_protocol (forward_entry->flow_protocol_str (), + fp_settings, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + result = flow_connection->add_producer (producer.in (), + flow_qos, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_StreamEndPoint_A::multiconnect: add_producer failed\n"),0); + } + } + ACE_CATCHANY + { + // Narrow failed and since its not a flowproducer its an error. + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"FlowProducer::_narrow"); + ACE_ERROR_RETURN ((LM_ERROR,"sep_a doesn't contain a flowproducer"),0); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + } + else + { + ACE_INET_Addr *mcast_addr; + TAO_FlowSpec_Entry *entry = 0; + result = this->mcast_entry_map_.find (mcast_key,entry); + if (result == 0) + { + mcast_addr = ACE_dynamic_cast (ACE_INET_Addr *,entry->address ()); + char str_addr [BUFSIZ]; + result = mcast_addr->addr_to_string (str_addr,BUFSIZ); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_StreamEndPoint::multiconnect ::addr_to_string failed\n"),0); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint_A::multiconnect:%s\n",str_addr)); + TAO_Forward_FlowSpec_Entry new_entry (entry->flowname (), + entry->direction_str (), + entry->format (), + entry->flow_protocol_str (), + entry->carrier_protocol_str (), + entry->address ()); + flow_spec[i] = CORBA::string_dup (new_entry.entry_to_string ()); + } + else + { + + switch (forward_entry->direction ()) + { + case TAO_FlowSpec_Entry::TAO_AV_DIR_IN: + { + ACE_NEW_RETURN (mcast_addr, + ACE_INET_Addr, + 0); + mcast_addr->set (this->mcast_port_,this->mcast_addr_); + this->mcast_port_++; + char buf[BUFSIZ]; + mcast_addr->addr_to_string (buf,BUFSIZ); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%s\n",buf)); + TAO_Forward_FlowSpec_Entry *new_entry; + ACE_NEW_RETURN (new_entry, + TAO_Forward_FlowSpec_Entry (forward_entry->flowname (), + forward_entry->direction_str (), + forward_entry->format (), + forward_entry->flow_protocol_str (), + forward_entry->carrier_protocol_str (), + mcast_addr), + 0); + flow_spec[i] = CORBA::string_dup (new_entry->entry_to_string ()); + + 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, + TAO_AV_CORE::instance (), + this->forward_flow_spec_set); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"Acceptor_Registry::open failed\n"),0); + result = this->mcast_entry_map_.bind (mcast_key,new_entry); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"mcast_entry::bind failed"),0); + } + break; + case TAO_FlowSpec_Entry::TAO_AV_DIR_OUT: + // OUT implies we're the sink. + break; + default: + break; + } + } + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamEndPoint_A::multiconnect"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; +} + +// ATM style Multicast is not supported yet. +CORBA::Boolean +TAO_StreamEndPoint_A::connect_leaf (AVStreams::StreamEndPoint_B_ptr /* the_ep */, + AVStreams::streamQoS & /* the_qos */, + const AVStreams::flowSpec & /* the_flows */, + CORBA::Environment &ACE_TRY_ENV) +{ + ACE_THROW_RETURN (AVStreams::notSupported (),0); + return 0; +} + +// Multicast not supported yet. +void +TAO_StreamEndPoint_A::disconnect_leaf (AVStreams::StreamEndPoint_B_ptr /* the_ep */, + const AVStreams::flowSpec & /* theSpec */, + CORBA::Environment &ACE_TRY_ENV) +{ + ACE_THROW (AVStreams::notSupported ()); +} + +TAO_StreamEndPoint_A::~TAO_StreamEndPoint_A (void) +{ +} + +// ---------------------------------------------------------------------- +// TAO_StreamEndPoint_B +// ---------------------------------------------------------------------- + +TAO_StreamEndPoint_B::TAO_StreamEndPoint_B (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, + "\n(%P|%t) TAO_StreamEndPoint_B::TAO_StreamEndPoint_B: created")); +} + +CORBA::Boolean +TAO_StreamEndPoint_B::multiconnect (AVStreams::streamQoS &stream_qos, + AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint_B::multiconnect\n")); + ACE_TRY + { + int result = 0; + TAO_AV_QoS qos (stream_qos); + for (u_int i=0;i< flow_spec.length ();i++) + { + TAO_Forward_FlowSpec_Entry *forward_entry; + ACE_NEW_RETURN (forward_entry, + TAO_Forward_FlowSpec_Entry, + 0); + forward_entry->parse (flow_spec[i]); + TAO_String_Hash_Key mcast_key (forward_entry->flowname ()); + AVStreams::FlowEndPoint_var flow_endpoint; + if (this->fep_map_.find (mcast_key,flow_endpoint.out ()) == 0) + { + AVStreams::FlowConsumer_var consumer; + ACE_TRY_EX (narrow) + { + consumer = AVStreams::FlowConsumer::_narrow (flow_endpoint.in (),ACE_TRY_ENV); + ACE_TRY_CHECK_EX (narrow); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"FlowConsumer::_narrow"); + ACE_ERROR_RETURN ((LM_ERROR,"sep_b doesn't contain a flowconsumer"),0); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + AVStreams::QoS flow_qos; + result = qos.get_flow_qos (forward_entry->flowname (),flow_qos); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"QoS not found for %s",forward_entry->flowname ())); + AVStreams::FlowConnection_var flow_connection; + ACE_TRY_EX (flow_connection) + { + if (CORBA::is_nil (this->streamctrl_.in ())) + { + CORBA::Any_var streamctrl_any; + streamctrl_any = this->get_property_value ("Related_StreamCtrl", + ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::StreamCtrl_ptr streamctrl; + streamctrl_any.in () >>= streamctrl; + this->streamctrl_ = AVStreams::StreamCtrl::_duplicate (streamctrl); + } + CORBA::Object_var flow_connection_obj = + this->streamctrl_->get_flow_connection (forward_entry->flowname (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connection); + flow_connection = AVStreams::FlowConnection::_narrow (flow_connection_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow_connection); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamEndPoint_B::multiconnect::get_flow_connection"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + result = flow_connection->add_consumer (consumer.in (), + flow_qos, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_StreamEndPoint_B::multiconnect:add_consumer failed\n"),0); + } + else + { + TAO_FlowSpec_Entry *mcast_entry = 0; + ACE_INET_Addr *mcast_addr; + mcast_addr = ACE_dynamic_cast (ACE_INET_Addr *,forward_entry->address ()); + if (mcast_addr == 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_StreamEndPoint_B::multiconnect::Address missing in flowspec_entry\n"),0); + result = this->mcast_entry_map_.find (mcast_key,mcast_entry); + if (result == 0) + { + ACE_ERROR_RETURN ((LM_ERROR,"TAO_StreamEndPoint_B::multiconnect::handler already found\n"),0); + } + else + { + switch (forward_entry->direction ()) + { + case TAO_FlowSpec_Entry::TAO_AV_DIR_IN: + { + // IN means we're the sink. + // @@ We have to take care of this. + // result = this->make_dgram_mcast_flow_handler (mcast_dgram); + // if (result < 0) + // return 0; + + this->forward_flow_spec_set.insert (forward_entry); + TAO_AV_Connector_Registry *connector_registry = TAO_AV_CORE::instance ()->connector_registry (); + result = connector_registry->open (this, + TAO_AV_CORE::instance (), + this->forward_flow_spec_set); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"connector_registry::open failed\n"),0); + result = this->mcast_entry_map_.bind (mcast_key,forward_entry); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"dgram_mcast_handler::bind failed"),0); + } + break; + case TAO_FlowSpec_Entry::TAO_AV_DIR_OUT: + // OUT implies we're the source.,which is an error. + break; + default: + break; + } + } + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_StreamEndPoint_B::multiconnect"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; +} + +TAO_StreamEndPoint_B::~TAO_StreamEndPoint_B (void) +{ } // ---------------------------------------------------------------------- @@ -1166,7 +2652,7 @@ TAO_StreamEndPoint::~TAO_StreamEndPoint (void) TAO_VDev::TAO_VDev (void) { - ACE_DEBUG ((LM_DEBUG, + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) TAO_VDev::TAO_VDev: created\n")); } @@ -1179,8 +2665,8 @@ TAO_VDev::set_peer (AVStreams::StreamCtrl_ptr the_ctrl, const AVStreams::flowSpec &the_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, + AVStreams::noSuchFlow, + AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)) { ACE_UNUSED_ARG (the_qos); @@ -1189,7 +2675,7 @@ TAO_VDev::set_peer (AVStreams::StreamCtrl_ptr the_ctrl, CORBA::Boolean result = 0; ACE_TRY { - ACE_DEBUG ((LM_DEBUG, + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) TAO_VDev::set_peer: called")); CORBA::String_var ior = TAO_ORB_Core_instance ()->orb ()->object_to_string (the_peer_dev, @@ -1197,7 +2683,7 @@ TAO_VDev::set_peer (AVStreams::StreamCtrl_ptr the_ctrl, ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG, + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) TAO_VDev::set_peer: my peer is %s\n", ior.in ())); @@ -1209,21 +2695,18 @@ TAO_VDev::set_peer (AVStreams::StreamCtrl_ptr the_ctrl, ACE_TRY_CHECK; - this->streamctrl_ = the_ctrl; - this->peer_ = the_peer_dev; + this->streamctrl_ = AVStreams::StreamCtrl::_duplicate (the_ctrl); + this->peer_ = AVStreams::VDev::_duplicate (the_peer_dev); - CORBA::Any_ptr anyptr; + CORBA::Any_var anyptr; CORBA::String media_ctrl_ior; anyptr = this->peer_->get_property_value ("Related_MediaCtrl", ACE_TRY_ENV); ACE_TRY_CHECK; - if (anyptr != 0) - { - *anyptr >>= media_ctrl_ior; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)The Media Control IOR is %s\n", - media_ctrl_ior)); - } + anyptr.in () >>= media_ctrl_ior; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)The Media Control IOR is %s\n", + media_ctrl_ior)); CORBA::Object_ptr media_ctrl_obj = TAO_ORB_Core_instance ()->orb ()->string_to_object (media_ctrl_ior,ACE_TRY_ENV); @@ -1234,7 +2717,7 @@ TAO_VDev::set_peer (AVStreams::StreamCtrl_ptr the_ctrl, } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_Server_StreamEndpoint::request_connection"); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_VDev::set_peer"); return 0; } ACE_ENDTRY; @@ -1252,36 +2735,30 @@ TAO_VDev::set_media_ctrl (CORBA::Object_ptr media_ctrl, return 1; } -// Multicast is not supported yet. +// Sets the multicast VDev peer. CORBA::Boolean -TAO_VDev::set_Mcast_peer (AVStreams::StreamCtrl_ptr the_ctrl, - AVStreams::MCastConfigIf_ptr a_mcastconfigif, - AVStreams::streamQoS &the_qos, - const AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) +TAO_VDev::set_Mcast_peer (AVStreams::StreamCtrl_ptr /* the_ctrl */, + AVStreams::MCastConfigIf_ptr mcast_peer, + AVStreams::streamQoS &/* the_qos */, + const AVStreams::flowSpec &/* the_spec */, + CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, + AVStreams::noSuchFlow, + AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)) { - ACE_UNUSED_ARG (the_ctrl); - ACE_UNUSED_ARG (a_mcastconfigif); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (the_spec); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + this->mcast_peer_ = AVStreams::MCastConfigIf::_duplicate (mcast_peer); + return 1; } // applications should override this to handle configuration changes. void -TAO_VDev::configure (const CosPropertyService::Property &the_config_mesg, - CORBA::Environment &ACE_TRY_ENV) +TAO_VDev::configure (const CosPropertyService::Property &/*the_config_mesg*/, + CORBA::Environment &/*ACE_TRY_ENV*/) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::PropertyException, + AVStreams::PropertyException, AVStreams::streamOpFailed)) { - ACE_UNUSED_ARG (the_config_mesg); - ACE_UNUSED_ARG (ACE_TRY_ENV); } // sets the media format used for the flowname as a property. @@ -1321,12 +2798,11 @@ TAO_VDev::set_dev_params (const char *flowName, const CosPropertyService::Properties &new_params, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::PropertyException, + AVStreams::PropertyException, AVStreams::streamOpFailed)) { ACE_TRY { - if (flowName == 0) ACE_ERROR ((LM_ERROR,"TAO_VDev::set_dev_params:flowName is null\n")); char devParams_property[BUFSIZ]; @@ -1354,7 +2830,7 @@ TAO_VDev::modify_QoS (AVStreams::streamQoS &the_qos, const AVStreams::flowSpec &the_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, + AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)) { ACE_UNUSED_ARG (the_qos); @@ -1373,10 +2849,19 @@ TAO_VDev::~TAO_VDev (void) TAO_MMDevice::TAO_MMDevice (TAO_AV_Endpoint_Strategy *endpoint_strategy) - : endpoint_strategy_ (endpoint_strategy) + : endpoint_strategy_ (endpoint_strategy), + flow_count_ (0), + flow_num_ (0), + stream_ctrl_ (0) { } +TAO_MMDevice::TAO_MMDevice (TAO_MMDevice const &mm_device) + :TAO_PropertySet (mm_device) +{ + //no-op +} + // create a streamctrl which is colocated with me, use that streamctrl // to bind the peer_device with me. AVStreams::StreamCtrl_ptr @@ -1386,28 +2871,26 @@ TAO_MMDevice::bind (AVStreams::MMDevice_ptr peer_device, const AVStreams::flowSpec &the_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::noSuchFlow, + AVStreams::streamOpFailed, + AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)) { AVStreams::StreamCtrl_ptr streamctrl (AVStreams::StreamCtrl::_nil ()); ACE_TRY { ACE_UNUSED_ARG (is_met); - TAO_StreamCtrl *stream_ctrl; - ACE_NEW_RETURN (stream_ctrl, + ACE_NEW_RETURN (this->stream_ctrl_, TAO_StreamCtrl, 0); - AVStreams::MMDevice_var mmdevice = - this->_this (ACE_TRY_ENV); + AVStreams::MMDevice_var mmdevice = this->_this (ACE_TRY_ENV); ACE_TRY_CHECK; - stream_ctrl->bind_devs (peer_device, - mmdevice.in (), - the_qos, - the_spec, - ACE_TRY_ENV); + this->stream_ctrl_->bind_devs (peer_device, + mmdevice.in (), + the_qos, + the_spec, + ACE_TRY_ENV); ACE_TRY_CHECK; - streamctrl = stream_ctrl->_this (ACE_TRY_ENV); + streamctrl = this->stream_ctrl_->_this (ACE_TRY_ENV); ACE_TRY_CHECK; } ACE_CATCHANY @@ -1428,8 +2911,8 @@ TAO_MMDevice::bind_mcast (AVStreams::MMDevice_ptr first_peer, const AVStreams::flowSpec &the_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::noSuchFlow, + AVStreams::streamOpFailed, + AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)) { ACE_UNUSED_ARG (first_peer); @@ -1440,136 +2923,284 @@ TAO_MMDevice::bind_mcast (AVStreams::MMDevice_ptr first_peer, return 0; } -AVStreams::StreamEndPoint_A_ptr -TAO_MMDevice::create_A (AVStreams::StreamCtrl_ptr the_requester, - AVStreams::VDev_out the_vdev, - AVStreams::streamQoS &the_qos, - CORBA::Boolean_out met_qos, - char *&named_vdev, - const AVStreams::flowSpec &the_spec, - CORBA::Environment &ACE_TRY_ENV) +AVStreams::StreamEndPoint_ptr +TAO_MMDevice::create_A_B (MMDevice_Type type, + AVStreams::StreamCtrl_ptr streamctrl, + AVStreams::VDev_out the_vdev, + AVStreams::streamQoS &the_qos, + CORBA::Boolean_out met_qos, + char *&/*named_vdev*/, + const AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, AVStreams::notSupported, - AVStreams::QoSRequestFailed, + AVStreams::QoSRequestFailed, AVStreams::noSuchFlow)) { - ACE_UNUSED_ARG (the_requester); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (met_qos); - ACE_UNUSED_ARG (named_vdev); - ACE_UNUSED_ARG (the_spec); - - AVStreams::StreamEndPoint_A_ptr ptr (AVStreams::StreamEndPoint_A::_nil ()); + AVStreams::StreamEndPoint_A_ptr sep_a (AVStreams::StreamEndPoint_A::_nil ()); + AVStreams::StreamEndPoint_B_ptr sep_b (AVStreams::StreamEndPoint_B::_nil ()); + AVStreams::StreamEndPoint_ptr sep (AVStreams::StreamEndPoint::_nil ()); ACE_TRY { - // In full profile application can override this to use FDevs. - - if (this->endpoint_strategy_->create_A (ptr, - the_vdev, - ACE_TRY_ENV) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Error in create_A\n"), - 0); + switch (type) + { + case MMDEVICE_A: + { + if (this->endpoint_strategy_->create_A (sep_a, + the_vdev, + ACE_TRY_ENV) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO_MMDevice::create_A_B (%P|%t) - " + "error in create_A\n"), + 0); + sep = sep_a; + } + break; + case MMDEVICE_B: + { + if (this->endpoint_strategy_->create_B (sep_b, + the_vdev, + ACE_TRY_ENV) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "TAO_MMDevice::create_A_B (%P|%t) - " + "error in create_B\n"), + 0); + sep = sep_b; + } + break; + default: + break; + } + ACE_TRY_CHECK; + if (this->fdev_map_.current_size () > 0) + { + // first set the vdev to be a nil pointer. + the_vdev = AVStreams::VDev::_nil (); + TAO_AV_QoS qos (the_qos); + // create flowendpoints from the FDevs. + for (u_int i=0;i<flow_spec.length ();i++) + { + TAO_Forward_FlowSpec_Entry forward_entry; + forward_entry.parse (flow_spec[i]); + TAO_String_Hash_Key flow_key (forward_entry.flowname ()); + AVStreams::FDev_ptr flow_dev; + AVStreams::FlowConnection_var flowconnection = AVStreams::FlowConnection::_nil (); + ACE_TRY_EX (flowconnection) + { + // Get the flowconnection for this flow. + CORBA::Object_var flowconnection_obj = + streamctrl->get_flow_connection (forward_entry.flowname (),ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flowconnection); + if (!CORBA::is_nil (flowconnection_obj.in ())) + { + flowconnection = AVStreams::FlowConnection::_narrow (flowconnection_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flowconnection); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MMDevice::create_a::get_flow_connection"); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + int result = this->fdev_map_.find (flow_key,flow_dev); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"fdev_map::find failed\n"),0); + CORBA::String_var named_fdev; + AVStreams::FlowEndPoint_var flow_endpoint; + AVStreams::QoS flow_qos; + result = qos.get_flow_qos (forward_entry.flowname (),flow_qos); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"get_flow_qos failed for %s\n",forward_entry.flowname ())); + switch (forward_entry.direction ()) + { + case TAO_FlowSpec_Entry::TAO_AV_DIR_IN: + { + switch (type) + { + case MMDEVICE_A: + { + // In implies flow is from A to B and + // hence A is the producer for this flow and B is the consumer for this flow. + // We have to create a producer from the FDev for this flow. + flow_endpoint = + flow_dev->create_producer (flowconnection.in (), + flow_qos, + met_qos, + named_fdev.inout (), + ACE_TRY_ENV); + } + break; + case MMDEVICE_B: + { + flow_endpoint = + flow_dev->create_consumer (flowconnection.in (), + flow_qos, + met_qos, + named_fdev.inout (), + ACE_TRY_ENV); + } + break; + } + ACE_TRY_CHECK; + } + break; + case TAO_FlowSpec_Entry::TAO_AV_DIR_OUT: + { + switch (type) + { + case MMDEVICE_A: + { + // OUT implies flow is from B to A and + // hence B is the producer for this flow and A is the consumer for this flow. + // We have to create a consumer from the FDev for this flow. + flow_endpoint = + flow_dev->create_consumer (flowconnection.in (), + flow_qos, + met_qos, + named_fdev.inout (), + ACE_TRY_ENV); + } + break; + case MMDEVICE_B: + { + // In implies flow is from A to B and + // hence A is the producer for this flow and B is the consumer for this flow. + // We have to create a producer from the FDev for this flow. + flow_endpoint = + flow_dev->create_producer (flowconnection.in (), + flow_qos, + met_qos, + named_fdev.inout (), + ACE_TRY_ENV); + } + break; + } + ACE_TRY_CHECK; + } + break; + default: + break; + } + CORBA::Any flowname_any; + flowname_any <<= forward_entry.flowname (); + flow_endpoint->define_property ("FlowName",flowname_any,ACE_TRY_ENV); + ACE_TRY_CHECK; + sep->add_fep (flow_endpoint.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MMDevice::create_A"); + return sep; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (sep); + return sep; +} +AVStreams::StreamEndPoint_A_ptr +TAO_MMDevice::create_A (AVStreams::StreamCtrl_ptr streamctrl, + AVStreams::VDev_out the_vdev, + AVStreams::streamQoS &stream_qos, + CORBA::Boolean_out met_qos, + char *&named_vdev, + const AVStreams::flowSpec &flow_spec, + CORBA::Environment &ACE_TRY_ENV) +{ + AVStreams::StreamEndPoint_A_ptr sep_a = 0; + AVStreams::StreamEndPoint_ptr sep = 0; + 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); ACE_TRY_CHECK; } ACE_CATCHANY { ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MMDevice::create_A"); - return ptr; + return sep_a; } ACE_ENDTRY; - ACE_CHECK_RETURN (ptr); - return ptr; + ACE_CHECK_RETURN (sep_a); + return sep_a; } AVStreams::StreamEndPoint_B_ptr -TAO_MMDevice::create_B (AVStreams::StreamCtrl_ptr the_requester, +TAO_MMDevice::create_B (AVStreams::StreamCtrl_ptr streamctrl, AVStreams::VDev_out the_vdev, - AVStreams::streamQoS &the_qos, + AVStreams::streamQoS &stream_qos, CORBA::Boolean_out met_qos, char *&named_vdev, - const AVStreams::flowSpec &the_spec, + const AVStreams::flowSpec &flow_spec, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, AVStreams::notSupported, - AVStreams::QoSRequestFailed, + AVStreams::QoSRequestFailed, AVStreams::noSuchFlow)) { - ACE_UNUSED_ARG (the_requester); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (met_qos); - ACE_UNUSED_ARG (named_vdev); - ACE_UNUSED_ARG (the_spec); - - // In full profile application can override this to use FDevs. - AVStreams::StreamEndPoint_B_ptr ptr (AVStreams::StreamEndPoint_B::_nil ()); - + AVStreams::StreamEndPoint_B_ptr sep_b = AVStreams::StreamEndPoint_B::_nil (); + AVStreams::StreamEndPoint_ptr sep; ACE_TRY { - if (this->endpoint_strategy_->create_B (ptr, - the_vdev, - ACE_TRY_ENV) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Error in create_B\n"), - 0); - - ACE_TRY_CHECK; + 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); + ACE_TRY_CHECK; } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MMDevice::create_B"); - return ptr; + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MMDevice::create_A"); + return sep_b; } ACE_ENDTRY; - ACE_CHECK_RETURN (ptr); - return ptr; + ACE_CHECK_RETURN (sep_b); + return sep_b; } + // destroys the streamendpoint and the Vdev. void TAO_MMDevice::destroy (AVStreams::StreamEndPoint_ptr /* the_ep */, const char * /* vdev_name */, - CORBA::Environment &ACE_TRY_ENV) + CORBA::Environment &/*ACE_TRY_ENV*/) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)) { // Remove self from POA. Because of reference counting, the POA // will automatically delete the servant when all pending requests // on this servant are complete. - // - PortableServer::POA_var poa = this->_default_POA (ACE_TRY_ENV); - ACE_CHECK; - - PortableServer::ObjectId_var id = poa->servant_to_id (this, - ACE_TRY_ENV); - ACE_CHECK; - - poa->deactivate_object (id.in (), - ACE_TRY_ENV); - ACE_CHECK; + int result = deactivate_servant (this); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_MMDevice::destroy failed\n")); } // Adds the fdev object to the MMDevice. char * -TAO_MMDevice::add_fdev (CORBA::Object_ptr the_fdev, +TAO_MMDevice::add_fdev (CORBA::Object_ptr fdev_obj, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported, + AVStreams::notSupported, AVStreams::streamOpFailed)) { char *flow_name = 0; + AVStreams::FDev_ptr fdev = AVStreams::FDev::_nil (); ACE_TRY_EX (flow_name) { ACE_NEW_RETURN (flow_name,char [BUFSIZ],0); CORBA::Any_ptr flow_name_any; - AVStreams::FDev_ptr fdev = - AVStreams::FDev::_narrow (the_fdev,ACE_TRY_ENV); + fdev = AVStreams::FDev::_narrow (fdev_obj,ACE_TRY_ENV); ACE_TRY_CHECK_EX (flow_name); flow_name_any = fdev->get_property_value ("Flow",ACE_TRY_ENV); ACE_TRY_CHECK_EX (flow_name); @@ -1577,14 +3208,33 @@ TAO_MMDevice::add_fdev (CORBA::Object_ptr the_fdev, } ACE_CATCHANY { - // exception implies the flow name is not defined and is system generated. - ACE_OS::sprintf (flow_name,"flow%d",flow_num_++); + ACE_TRY_EX (flow) + { + // exception implies the flow name is not defined and is system generated. + ACE_OS::sprintf (flow_name,"flow%d",flow_num_++); + CORBA::Any flowname_any; + flowname_any <<= flow_name; + fdev->define_property ("Flow",flowname_any,ACE_TRY_ENV); + ACE_TRY_CHECK_EX (flow); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_MMDevice::add_fdev"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); } ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + if (CORBA::is_nil (fdev)) + return 0; + // Add it to the sequence of flowNames supported. // put the flowname and the fdev in a hashtable. - TAO_String_Hash_Key fdev_name_key (flow_name); - if (this->fdev_map_.bind (fdev_name_key,the_fdev) != 0) + TAO_String_Hash_Key fdev_name_key (CORBA::string_dup (flow_name)); + if (this->fdev_map_.bind (fdev_name_key,fdev) != 0) ACE_THROW_RETURN (AVStreams::streamOpFailed (),0); // increment the flow count. @@ -1616,7 +3266,7 @@ CORBA::Object_ptr TAO_MMDevice::get_fdev (const char *flow_name, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported, + AVStreams::notSupported, AVStreams::noSuchFlow)) { ACE_UNUSED_ARG (ACE_TRY_ENV); @@ -1624,7 +3274,7 @@ TAO_MMDevice::get_fdev (const char *flow_name, TAO_String_Hash_Key fdev_name_key (flow_name); FDev_Map::ENTRY *fdev_entry = 0; if (this->fdev_map_.find (fdev_name_key,fdev_entry) == 0) - return fdev_entry->int_id_; + return AVStreams::FDev::_duplicate (fdev_entry->int_id_); return 0; } @@ -1633,16 +3283,19 @@ void TAO_MMDevice::remove_fdev (const char *flow_name, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported, + AVStreams::notSupported, AVStreams::noSuchFlow)) { ACE_TRY { TAO_String_Hash_Key fdev_name_key (flow_name); - CORBA::Object_ptr fdev_entry = 0; + AVStreams::FDev_ptr fdev_entry = AVStreams::FDev::_nil (); // Remove the fep from the hash table. - if (this->fdev_map_.unbind (flow_name,fdev_entry)!= 0) - ACE_THROW (AVStreams::noSuchFlow ()); + if (this->fdev_map_.unbind (fdev_name_key,fdev_entry)!= 0) + ACE_THROW (AVStreams::streamOpFailed ()); + + if (!CORBA::is_nil (fdev_entry)) + CORBA::release (fdev_entry); AVStreams::flowSpec new_flows (this->flows_.length ()); for (u_int i=0,j=0 ; i <this->flows_.length (); i++) @@ -1668,6 +3321,11 @@ TAO_MMDevice::remove_fdev (const char *flow_name, // destructor. TAO_MMDevice::~TAO_MMDevice (void) { + delete this->stream_ctrl_; + FDev_Map_Iterator iterator (fdev_map_); + FDev_Map_Entry *entry = 0; + for (;iterator.next (entry) != 0; iterator.advance ()) + CORBA::release (entry->int_id_); } //------------------------------------------------------------------ @@ -1676,10 +3334,23 @@ TAO_MMDevice::~TAO_MMDevice (void) // default constructor. TAO_FlowConnection::TAO_FlowConnection (void) - :producer_ (0), - consumer_ (0), - fp_name_ (0) + :fp_name_ (CORBA::string_dup ("")), + ip_multicast_ (1) +{ +} + +int +TAO_FlowConnection::set_mcast_addr (ACE_UINT32 mcast_addr, u_short mcast_port) +{ + this->mcast_addr_ = mcast_addr; + this->mcast_port_ = mcast_port; + return 0; +} + +void +TAO_FlowConnection::set_protocol (const char *protocol) { + this->protocol_ = protocol; } // stop this flow. @@ -1687,7 +3358,34 @@ void TAO_FlowConnection::stop (CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException)) { - ACE_UNUSED_ARG (ACE_TRY_ENV); + ACE_TRY + { + FlowProducer_SetItor producer_begin = this->flow_producer_set_.begin + (); + for (FlowProducer_SetItor producer_end = + this->flow_producer_set_.end (); + producer_begin != producer_end; ++producer_begin) + { + (*producer_begin)->stop (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + FlowConsumer_SetItor consumer_begin = this->flow_consumer_set_.begin + (); + for (FlowConsumer_SetItor consumer_end = + this->flow_consumer_set_.end (); + consumer_begin != consumer_end; ++consumer_begin) + { + (*consumer_begin)->stop (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowConnection::stop"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } // start this flow. @@ -1695,28 +3393,71 @@ void TAO_FlowConnection::start (CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException)) { - ACE_UNUSED_ARG (ACE_TRY_ENV); + ACE_TRY + { + FlowConsumer_SetItor consumer_begin = this->flow_consumer_set_.begin + (); + for (FlowConsumer_SetItor consumer_end = + this->flow_consumer_set_.end (); + consumer_begin != consumer_end; ++consumer_begin) + { + (*consumer_begin)->start (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + FlowProducer_SetItor producer_begin = this->flow_producer_set_.begin + (); + for (FlowProducer_SetItor producer_end = + this->flow_producer_set_.end (); + producer_begin != producer_end; ++producer_begin) + { + (*producer_begin)->start (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowConnection::start"); + return; + } + ACE_ENDTRY; + ACE_CHECK; } // destroy this flow. void TAO_FlowConnection::destroy (CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException)) { - // Remove self from POA. Because of reference counting, the POA - // will automatically delete the servant when all pending requests - // on this servant are complete. - // - PortableServer::POA_var poa = this->_default_POA (ACE_TRY_ENV); - ACE_CHECK; - - PortableServer::ObjectId_var id = poa->servant_to_id (this, - ACE_TRY_ENV); - ACE_CHECK; - - poa->deactivate_object (id.in (), - ACE_TRY_ENV); + ACE_TRY + { + FlowProducer_SetItor producer_begin = this->flow_producer_set_.begin + (); + for (FlowProducer_SetItor producer_end = + this->flow_producer_set_.end (); + producer_begin != producer_end; ++producer_begin) + { + (*producer_begin)->destroy (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + FlowConsumer_SetItor consumer_begin = this->flow_consumer_set_.begin + (); + for (FlowConsumer_SetItor consumer_end = + this->flow_consumer_set_.end (); + consumer_begin != consumer_end; ++consumer_begin) + { + (*consumer_begin)->destroy (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowConnection::destroy"); + return; + } + ACE_ENDTRY; ACE_CHECK; + int result = deactivate_servant (this); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_FlowConnection::destroy failed\n")); } // modify the QoS for this flow. @@ -1737,12 +3478,31 @@ TAO_FlowConnection::use_flow_protocol (const char * fp_name, const CORBA::Any & fp_settings, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::FPError, + AVStreams::FPError, AVStreams::notSupported)) { - ACE_UNUSED_ARG (fp_settings); - ACE_UNUSED_ARG (ACE_TRY_ENV); - this->fp_name_ = (char *)fp_name; + this->fp_name_ = fp_name; + this->fp_settings_ = fp_settings; + FlowProducer_SetItor producer_begin = this->flow_producer_set_.begin + (); + for (FlowProducer_SetItor producer_end = + this->flow_producer_set_.end (); + producer_begin != producer_end; ++producer_begin) + { + (*producer_begin)->use_flow_protocol + (fp_name,fp_settings,ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + } + FlowConsumer_SetItor consumer_begin = this->flow_consumer_set_.begin + (); + for (FlowConsumer_SetItor consumer_end = + this->flow_consumer_set_.end (); + consumer_begin != consumer_end; ++consumer_begin) + { + (*consumer_begin)->use_flow_protocol + (fp_name,fp_settings,ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + } return 1; } @@ -1758,64 +3518,119 @@ TAO_FlowConnection::push_event (const AVStreams::streamEvent & the_event, CORBA::Boolean TAO_FlowConnection::connect_devs (AVStreams::FDev_ptr a_party, AVStreams::FDev_ptr b_party, - AVStreams::QoS & the_qos, + AVStreams::QoS & flow_qos, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, AVStreams::QoSRequestFailed)) { - ACE_UNUSED_ARG (a_party); - ACE_UNUSED_ARG (b_party); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + CORBA::Boolean result = 0; + ACE_TRY + { + AVStreams::FlowConnection_var flowconnection = this->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + CORBA::Boolean met_qos; + CORBA::String_var named_fdev ((const char *)""); + AVStreams::FlowProducer_var producer = + a_party->create_producer (flowconnection.in (), + flow_qos, + met_qos, + named_fdev.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FlowConsumer_var consumer = + b_party->create_consumer (flowconnection.in (), + flow_qos, + met_qos, + named_fdev.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + result = this->connect (producer.in (), + consumer.in (), + flow_qos, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowConnection::connect_devs"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return result; } // connect the producer and the consumer CORBA::Boolean -TAO_FlowConnection::connect (AVStreams::FlowProducer_ptr flow_producer, - AVStreams::FlowConsumer_ptr flow_consumer, +TAO_FlowConnection::connect (AVStreams::FlowProducer_ptr producer, + AVStreams::FlowConsumer_ptr consumer, AVStreams::QoS & the_qos, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::formatMismatch, - AVStreams::FEPMismatch, + AVStreams::formatMismatch, + AVStreams::FEPMismatch, AVStreams::alreadyConnected)) { ACE_TRY { - this->producer_ = flow_producer; - this->consumer_ = flow_consumer; + AVStreams::FlowProducer_ptr flow_producer = + AVStreams::FlowProducer::_duplicate (producer); + AVStreams::FlowConsumer_ptr flow_consumer = + AVStreams::FlowConsumer::_duplicate (consumer); + + this->flow_producer_set_.insert (flow_producer); + this->flow_consumer_set_.insert (flow_consumer); AVStreams::FlowConnection_var flowconnection = this->_this (ACE_TRY_ENV); - ACE_TRY_CHECK; - this->producer_->set_peer (flowconnection.in (), - this->consumer_, - the_qos, - ACE_TRY_ENV); + flow_producer->set_peer (flowconnection.in (), + flow_consumer, + the_qos, + ACE_TRY_ENV); ACE_TRY_CHECK; - this->consumer_->set_peer (flowconnection.in (), - this->producer_, - the_qos, - ACE_TRY_ENV); + flow_consumer->set_peer (flowconnection.in (), + flow_producer, + the_qos, + ACE_TRY_ENV); ACE_TRY_CHECK; char *consumer_address = - this->consumer_->go_to_listen (the_qos, - 0,// false for is_mcast - this->producer_, - this->fp_name_, - ACE_TRY_ENV); + flow_consumer->go_to_listen (the_qos, + 0,// false for is_mcast + flow_producer, + this->fp_name_.inout (), + ACE_TRY_ENV); ACE_TRY_CHECK; - this->producer_->connect_to_peer (the_qos, - consumer_address, - this->fp_name_, - ACE_TRY_ENV); - ACE_TRY_CHECK; + if (ACE_OS::strcmp (consumer_address,"") == 0) + { + // Consumer is not willing to listen,so try the producer. + consumer_address = flow_producer->go_to_listen (the_qos, + 0,// false for is_mcast + flow_consumer, + this->fp_name_.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + flow_consumer->connect_to_peer (the_qos, + consumer_address, + this->fp_name_.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + // @@ Naga: We have to find means to set the reverse channel for the producer. + // Its broken in the point-to_point case for UDP. + } + else + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_FlowConnection::connect_to_peer addres: %s",consumer_address)); + flow_producer->connect_to_peer (the_qos, + consumer_address, + this->fp_name_.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } } ACE_CATCHANY { @@ -1836,29 +3651,190 @@ TAO_FlowConnection::disconnect (CORBA::Environment &ACE_TRY_ENV) } CORBA::Boolean -TAO_FlowConnection::add_producer (AVStreams::FlowProducer_ptr flow_producer, +TAO_FlowConnection::add_producer (AVStreams::FlowProducer_ptr producer, AVStreams::QoS & the_qos, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::alreadyConnected, AVStreams::notSupported)) { - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (ACE_TRY_ENV); - this->producer_ = flow_producer; + ACE_TRY + { + AVStreams::FlowProducer_ptr flow_producer = + AVStreams::FlowProducer::_duplicate (producer); + // @@Naga:Sometimes the same producer could be added with a different object reference. + // There's no portable way of comparing obj refs. but we have to do this till we find + // a permanent solution.For eg. 2 different flowproducers for the same flow in a + // Multipoint to Multipoint binding will have the same flowname and hence cannot be + // used for resolving ties. + FlowProducer_SetItor begin = this->flow_producer_set_.begin (); + FlowProducer_SetItor end = this->flow_producer_set_.end (); + for (; begin != end; ++begin) + { + if ((*begin)->_is_equivalent (producer, + ACE_TRY_ENV)) + // producer exists in the set, a duplicate. + ACE_ERROR_RETURN ((LM_WARNING,"TAO_FlowConnection::add_producer: producer already exists\n"),1); + } + // We need to check the return value of the insert into the flow producer + // set, since multiconnect could be called many times which will lead to + // a call to add_producer every time a sink is added. If the producer is already + // present in our list we just return immediately. + int result = this->flow_producer_set_.insert (flow_producer); + if (result == 1) + { + // producer exists in the set, a duplicate. + ACE_ERROR_RETURN ((LM_WARNING,"TAO_FlowConnection::add_producer: producer already exists\n"),1); + } + CORBA::Boolean met_qos; + char mcast_address[BUFSIZ]; + if (this->producer_address_.in () == 0) + { + ACE_INET_Addr mcast_addr (this->mcast_port_, + this->mcast_addr_); + char buf [BUFSIZ]; + mcast_addr.addr_to_string (buf,BUFSIZ); + ACE_OS::sprintf (mcast_address,"%s=%s",this->protocol_.in (),buf); + } + else + ACE_OS::strcpy (mcast_address,this->producer_address_.in ()); + char *address = flow_producer->connect_mcast (the_qos, + met_qos, + mcast_address, + this->fp_name_.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (this->producer_address_.in () == 0) + { + TAO_Forward_FlowSpec_Entry entry ("","","","",address); + if (entry.address () != 0) + { + // Internet multicasting is in use. + this->producer_address_ = address; + } + else + { + // ATM Multicasting is in use. + this->ip_multicast_ = 0; + } + } + // set the multicast peer. + if (CORBA::is_nil (this->mcastconfigif_.in ())) + { + ACE_NEW_RETURN (this->mcastconfigif_i_, + TAO_MCastConfigIf, + 0); + this->mcastconfigif_ = this->mcastconfigif_i_->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + AVStreams::FlowConnection_var flowconnection = this->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + flow_producer->set_Mcast_peer (flowconnection.in (), + this->mcastconfigif_.in (), + the_qos, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowConnection::add_producer"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); return 1; } CORBA::Boolean -TAO_FlowConnection::add_consumer (AVStreams::FlowConsumer_ptr flow_consumer, +TAO_FlowConnection::add_consumer (AVStreams::FlowConsumer_ptr consumer, AVStreams::QoS & the_qos, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::alreadyConnected)) { - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (ACE_TRY_ENV); - this->consumer_ = flow_consumer; + ACE_TRY + { + AVStreams::FlowConsumer_ptr flow_consumer = + AVStreams::FlowConsumer::_duplicate (consumer); + FlowConsumer_SetItor begin = this->flow_consumer_set_.begin (); + FlowConsumer_SetItor end = this->flow_consumer_set_.end (); + for (; begin != end; ++begin) + { + if ((*begin)->_is_equivalent (consumer, + ACE_TRY_ENV)) + // Consumer exists in the set, a duplicate. + ACE_ERROR_RETURN ((LM_WARNING,"TAO_FlowConnection::add_Consumer: Consumer already exists\n"),1); + } + int result = this->flow_consumer_set_.insert (flow_consumer); + if (result == 1) + { + // consumer exists in the set, a duplicate. + ACE_ERROR_RETURN ((LM_WARNING,"TAO_FlowConnection::add_consumer: consumer already exists\n"),1); + } + + FlowProducer_SetItor producer_begin = this->flow_producer_set_.begin (); + // @@Lets take that the first entry as the only producer. We're + // not sure if we can have multiple flow producers in a + // flowconnection. We can have multiple producer in the MtM binding, + // in which case the first producer that gets added is the leader. + AVStreams::FlowProducer_ptr flow_producer = (*producer_begin); + + AVStreams::protocolSpec protocols (1); + protocols.length (1); + protocols [0] = CORBA::string_dup (this->producer_address_); + if (!this->ip_multicast_) + { + flow_consumer->set_protocol_restriction (protocols, + ACE_TRY_ENV); + ACE_TRY_CHECK; + char * address = + flow_consumer->go_to_listen (the_qos, + 1, + flow_producer, + this->fp_name_.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + CORBA::Boolean is_met; + flow_producer->connect_mcast (the_qos, + is_met, + address, + this->fp_name_.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + else + { + // The spec says go_to_listen is called with the multicast + // address returned from the connect_mcast call called + // during add_producer. But go_to_listen doesn't have a + // address parameter. I guess it should be connect_to_peer. + // IP Multicasting. + flow_consumer->connect_to_peer (the_qos, + this->producer_address_.in (), + this->fp_name_.inout (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + if (CORBA::is_nil (this->mcastconfigif_.in ())) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_FlowConnection::add_consumer: first add a producer and then a consumer\n"),0); + // @@ Is this the right place to do set_peer? + AVStreams::flowSpec flow_spec; + AVStreams::streamQoS stream_qos (1); + stream_qos.length (1); + stream_qos [0] = the_qos; + this->mcastconfigif_->set_peer (flow_consumer, + stream_qos, + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowConnection::add_consumer"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); return 1; } @@ -1879,11 +3855,77 @@ TAO_FlowConnection::drop (AVStreams::FlowEndPoint_ptr target, //default constructor. TAO_FlowEndPoint::TAO_FlowEndPoint (void) - :related_sep_ (0), - related_flow_connection_ (0) + :lock_ (0) { } +TAO_FlowEndPoint::TAO_FlowEndPoint (const char *flowname, + AVStreams::protocolSpec &protocols, + const char *format) +{ + this->open (flowname,protocols,format); +} + +void +TAO_FlowEndPoint::set_handler (const char *flowname, + TAO_AV_Flow_Handler *handler) +{ +} + +int +TAO_FlowEndPoint::open (const char *flowname, + AVStreams::protocolSpec &protocols, + const char *format) +{ + this->flowname_ = flowname; + this->format_ = format; + + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_FlowEndPoint::open\n")); + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::Any flowname_any; + flowname_any <<= flowname; + this->define_property ("Flow", + flowname_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->set_format (format, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->protocol_addresses_ = protocols; + AVStreams::protocolSpec protocol_spec (protocols.length ()); + protocol_spec.length (protocols.length ()); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%N:%l\n")); + for (u_int i=0;i<protocols.length ();i++) + { + CORBA::String_var address = CORBA::string_dup (protocols [i].in ()); + TAO_Forward_FlowSpec_Entry entry ("","","","",address.in ()); + protocol_spec [i] = CORBA::string_dup (entry.carrier_protocol_str ()); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%s\n",protocol_spec[i].in ())); + } + this->set_protocol_restriction (protocol_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowEndPoint::open"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + + +int +TAO_FlowEndPoint::set_flowname (const char *flowname) +{ + this->flowname_ = flowname; + return 0; +} + // used by one flowconnection so that multiple connections cant use // the same flowendpoint. CORBA::Boolean @@ -1892,7 +3934,10 @@ TAO_FlowEndPoint::lock (CORBA::Environment &ACE_TRY_ENV) { // lock the current flowendpoint ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + if (this->lock_) + return 0; + this->lock_ = 1; + return 1; } // unlocks the flowendpoint ,becomes free to be used in another flow. @@ -1901,66 +3946,44 @@ TAO_FlowEndPoint::unlock (CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException)) { ACE_UNUSED_ARG (ACE_TRY_ENV); + this->lock_ = 0; } -// The start,stop and destroy are to be handled by the application. -void -TAO_FlowEndPoint::stop (CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException)) -{ - ACE_UNUSED_ARG (ACE_TRY_ENV); -} - -void -TAO_FlowEndPoint::start (CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException)) -{ - ACE_UNUSED_ARG (ACE_TRY_ENV); -} void -TAO_FlowEndPoint::destroy (CORBA::Environment &ACE_TRY_ENV) +TAO_FlowEndPoint::destroy (CORBA::Environment &/*ACE_TRY_ENV*/) ACE_THROW_SPEC ((CORBA::SystemException)) { - // Remove self from POA. Because of reference counting, the POA - // will automatically delete the servant when all pending requests - // on this servant are complete. - // - PortableServer::POA_var poa = this->_default_POA (ACE_TRY_ENV); - ACE_CHECK; - - PortableServer::ObjectId_var id = poa->servant_to_id (this, - ACE_TRY_ENV); - ACE_CHECK; - - poa->deactivate_object (id.in (), - ACE_TRY_ENV); - ACE_CHECK; + int result = deactivate_servant (this); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint::destroy failed\n")); + TAO_AV_FlowSpecSetItor end = this->flow_spec_set_.end (); + for (TAO_AV_FlowSpecSetItor begin = this->flow_spec_set_.begin (); + begin != end; ++begin) + (*begin)->protocol_object ()->destroy (); } AVStreams::StreamEndPoint_ptr -TAO_FlowEndPoint::related_sep (CORBA::Environment &ACE_TRY_ENV) +TAO_FlowEndPoint::related_sep (CORBA::Environment &/*ACE_TRY_ENV*/) ACE_THROW_SPEC ((CORBA::SystemException)) { - ACE_UNUSED_ARG (ACE_TRY_ENV); - return this->related_sep_; + + return AVStreams::StreamEndPoint::_duplicate (this->related_sep_.in ()); } void TAO_FlowEndPoint::related_sep (AVStreams::StreamEndPoint_ptr related_sep, - CORBA::Environment &ACE_TRY_ENV) + CORBA::Environment &) ACE_THROW_SPEC ((CORBA::SystemException)) { - ACE_UNUSED_ARG (ACE_TRY_ENV); - this->related_sep_ = related_sep; + this->related_sep_ = AVStreams::StreamEndPoint::_duplicate (related_sep); } AVStreams::FlowConnection_ptr -TAO_FlowEndPoint::related_flow_connection (CORBA::Environment &ACE_TRY_ENV) +TAO_FlowEndPoint::related_flow_connection (CORBA::Environment &) ACE_THROW_SPEC ((CORBA::SystemException)) { - ACE_UNUSED_ARG (ACE_TRY_ENV); - return this->related_flow_connection_; + return AVStreams::FlowConnection::_duplicate (this->related_flow_connection_.in ()); } void @@ -1969,29 +3992,27 @@ TAO_FlowEndPoint::related_flow_connection (AVStreams::FlowConnection_ptr related ACE_THROW_SPEC ((CORBA::SystemException)) { ACE_UNUSED_ARG (ACE_TRY_ENV); - this->related_flow_connection_ = related_flow_connection; + this->related_flow_connection_ = AVStreams::FlowConnection::_duplicate (related_flow_connection); } // returns the connected peer for this flow AVStreams::FlowEndPoint_ptr -TAO_FlowEndPoint::get_connected_fep (CORBA::Environment &ACE_TRY_ENV) +TAO_FlowEndPoint::get_connected_fep (CORBA::Environment &) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notConnected, AVStreams::notSupported)) { - ACE_UNUSED_ARG (ACE_TRY_ENV); - return this->peer_fep_; + return AVStreams::FlowEndPoint::_duplicate (this->peer_fep_.in ()); } CORBA::Boolean TAO_FlowEndPoint::use_flow_protocol (const char * fp_name, - const CORBA::Any & fp_settings, + const CORBA::Any & , CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::FPError, + AVStreams::FPError, AVStreams::notSupported)) { - ACE_UNUSED_ARG (fp_settings); ACE_TRY { // Define the property called FlowProtocol @@ -2018,6 +4039,7 @@ TAO_FlowEndPoint::set_format (const char * format, ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)) { + this->format_ = format; ACE_TRY { // make this a property so that is_fep_compatible can query this and @@ -2041,9 +4063,10 @@ void TAO_FlowEndPoint::set_dev_params (const CosPropertyService::Properties & new_settings, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::PropertyException, + AVStreams::PropertyException, AVStreams::streamOpFailed)) { + this->dev_params_ = new_settings; ACE_TRY { CORBA::Any DevParams_property; @@ -2062,19 +4085,38 @@ TAO_FlowEndPoint::set_dev_params (const CosPropertyService::Properties & new_set } void -TAO_FlowEndPoint::set_protocol_restriction (const AVStreams::protocolSpec & the_spec, +TAO_FlowEndPoint::set_protocol_restriction (const AVStreams::protocolSpec & protocols, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)) { ACE_TRY { + u_int i = 0; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%N:%l\n")); + for (i=0;i<protocols.length ();i++) + { + const char *protocol = (protocols)[i].in (); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%s\n",protocol)); + } CORBA::Any AvailableProtocols_property; - AvailableProtocols_property <<= the_spec; + AvailableProtocols_property <<= protocols; this->define_property ("AvailableProtocols", AvailableProtocols_property, ACE_TRY_ENV); ACE_TRY_CHECK; + AVStreams::protocolSpec *temp_spec; + CORBA::Any_var temp_any = this->get_property_value ("AvailableProtocols", + ACE_TRY_ENV); + ACE_TRY_CHECK; + temp_any.in () >>= temp_spec; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%N:%l\n")); + for (i=0;i<temp_spec->length ();i++) + { + const char *protocol = (*temp_spec)[i].in (); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%s\n",protocol)); + } + this->protocols_ = protocols; } ACE_CATCHANY { @@ -2088,60 +4130,87 @@ CORBA::Boolean TAO_FlowEndPoint::is_fep_compatible (AVStreams::FlowEndPoint_ptr peer_fep, CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::formatMismatch, + AVStreams::formatMismatch, AVStreams::deviceQosMismatch)) { + const char *exception_message = ""; ACE_TRY { // check whether the passed flowendpoint is compatible with this flowendpoint. // should we check for the availableFormats and choose one format. // get my format value - CORBA::Any_ptr format_ptr; - CORBA::String my_format,peer_format; + CORBA::Any_var format_ptr; + CORBA::String_var my_format,peer_format; + CORBA::String temp_format; + + exception_message = "TAO_FlowEndPoint::is_fep_compatible - Format"; format_ptr = this->get_property_value ("Format", ACE_TRY_ENV); ACE_TRY_CHECK; - if (format_ptr != 0) - *format_ptr >>= my_format; - else - // property is not defined - ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) TAO_FlowEndPoint::is_fep_compatible"),0); - + format_ptr.in () >>= temp_format; + my_format = CORBA::string_dup (temp_format); // get my peer's format value - + exception_message = "TAO_FlowEndPoint::is_fep_compatible - Format[2]"; format_ptr = peer_fep->get_property_value ("Format", ACE_TRY_ENV); ACE_TRY_CHECK; - if (format_ptr != 0) - *format_ptr >>= peer_format; - else - // property is not defined - ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) TAO_FlowEndPoint::is_fep_compatible"),0); - - // can we use strcmp?? - if (ACE_OS::strcmp (my_format,peer_format) != 0) + format_ptr.in () >>= temp_format; + peer_format = CORBA::string_dup (temp_format); + if (ACE_OS::strcmp (my_format.in (), + peer_format.in ()) != 0) return 0; + // since formats are same, check for a common protocol - CORBA::Any* AvailableProtocols_ptr; - AVStreams::protocolSpec *my_protocolSpec,*peer_protocolSpec; + CORBA::Any_var AvailableProtocols_ptr; + AVStreams::protocolSpec my_protocol_spec,peer_protocol_spec; + AVStreams::protocolSpec_ptr temp_protocols;; + exception_message = + "TAO_FlowEndPoint::is_fep_compatible - AvailableProtocols"; AvailableProtocols_ptr = this->get_property_value ("AvailableProtocols", ACE_TRY_ENV); ACE_TRY_CHECK; - if (AvailableProtocols_ptr != 0) - *AvailableProtocols_ptr >>= my_protocolSpec; - else - ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) TAO_FlowEndPoint::is_fep_compatible"),0); + AvailableProtocols_ptr.in () >>= temp_protocols; + my_protocol_spec = *temp_protocols; + exception_message = + "TAO_FlowEndPoint::is_fep_compatible - AvailableProtocols[2]"; AvailableProtocols_ptr = peer_fep->get_property_value ("AvailableProtocols", ACE_TRY_ENV); ACE_TRY_CHECK; - if (AvailableProtocols_ptr != 0) - *AvailableProtocols_ptr >>= peer_protocolSpec; + AvailableProtocols_ptr.in () >>= temp_protocols; + peer_protocol_spec = *temp_protocols; + + int protocol_match = 0; + for (u_int i=0;i<my_protocol_spec.length ();i++) + { + CORBA::String_var my_protocol_string; + for (u_int j=0;j<peer_protocol_spec.length ();j++) + { + CORBA::String_var peer_protocol_string; + my_protocol_string = CORBA::string_dup (my_protocol_spec[i]); + peer_protocol_string = CORBA::string_dup (peer_protocol_spec[j]); + if (ACE_OS::strcmp (my_protocol_string,peer_protocol_string) == 0) + { + protocol_match = 1; + break; + } + } + if (protocol_match) + break; + } + if (!protocol_match) + return 0; + } + ACE_CATCH (CosPropertyService::PropertyNotFound, nf) + { + ACE_PRINT_EXCEPTION (nf, + exception_message); } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FlowEndPoint::is_fep_compatible"); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_FlowEndPoint::is_fep_compatible"); return 0; } ACE_ENDTRY; @@ -2150,97 +4219,171 @@ TAO_FlowEndPoint::is_fep_compatible (AVStreams::FlowEndPoint_ptr peer_fep, } CORBA::Boolean -TAO_FlowEndPoint::set_peer (AVStreams::FlowConnection_ptr the_fc, +TAO_FlowEndPoint::set_peer (AVStreams::FlowConnection_ptr /* the_fc */, AVStreams::FlowEndPoint_ptr the_peer_fep, - AVStreams::QoS & the_qos, - CORBA::Environment &ACE_TRY_ENV) + AVStreams::QoS & /* the_qos */, + CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)) { - ACE_UNUSED_ARG (the_fc); - ACE_UNUSED_ARG (the_peer_fep); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (ACE_TRY_ENV); - - this->peer_fep_ = the_peer_fep; + this->peer_fep_ = + AVStreams::FlowEndPoint::_duplicate (the_peer_fep); return 1; } CORBA::Boolean -TAO_FlowEndPoint::set_Mcast_peer (AVStreams::FlowConnection_ptr the_fc, - AVStreams::MCastConfigIf_ptr a_mcastconfigif, - AVStreams::QoS & the_qos, - CORBA::Environment &ACE_TRY_ENV) +TAO_FlowEndPoint::set_Mcast_peer (AVStreams::FlowConnection_ptr /* the_fc */, + AVStreams::MCastConfigIf_ptr mcast_peer, + AVStreams::QoS & /* the_qos */, + CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::QoSRequestFailed)) { - ACE_UNUSED_ARG (the_fc); - ACE_UNUSED_ARG (a_mcastconfigif); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (ACE_TRY_ENV); + this->mcast_peer_ = AVStreams::MCastConfigIf::_duplicate (mcast_peer); return 0; } char * -TAO_FlowEndPoint::go_to_listen (AVStreams::QoS & the_qos, - CORBA::Boolean is_mcast, - AVStreams::FlowProducer_ptr peer, - char *& flowProtocol, - CORBA::Environment &ACE_TRY_ENV) +TAO_FlowEndPoint::go_to_listen_i (TAO_FlowSpec_Entry::Role role, + AVStreams::QoS & /*the_qos*/, + CORBA::Boolean is_mcast, + AVStreams::FlowEndPoint_ptr peer_fep, + char *& flowProtocol, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::failedToListen, - AVStreams::FPError, + AVStreams::failedToListen, + AVStreams::FPError, AVStreams::QoSRequestFailed)) { - return this->handle_go_to_listen (the_qos,is_mcast,peer,flowProtocol,ACE_TRY_ENV); -} - -char * -TAO_FlowEndPoint::handle_go_to_listen (AVStreams::QoS & the_qos, - CORBA::Boolean is_mcast, - AVStreams::FlowProducer_ptr peer, - char *& flowProtocol, - CORBA::Environment &ACE_TRY_ENV) -{ - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (is_mcast); - ACE_UNUSED_ARG (peer); - ACE_UNUSED_ARG (flowProtocol); - ACE_UNUSED_ARG (ACE_TRY_ENV); - + char direction [BUFSIZ]; + switch (role) + { + case TAO_FlowSpec_Entry::TAO_AV_PRODUCER: + ACE_OS::strcpy (direction,"IN"); + break; + case TAO_FlowSpec_Entry::TAO_AV_CONSUMER: + ACE_OS::strcpy (direction,"OUT"); + break; + default: + break; + } + AVStreams::protocolSpec my_protocol_spec,peer_protocol_spec; + AVStreams::protocolSpec_ptr temp_protocols; + CORBA::Any_var AvailableProtocols_ptr = + peer_fep->get_property_value ("AvailableProtocols", + ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + AvailableProtocols_ptr.in () >>= temp_protocols; + peer_protocol_spec = *temp_protocols; + AvailableProtocols_ptr = + this->get_property_value ("AvailableProtocols", + ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + AvailableProtocols_ptr.in () >>= temp_protocols; + my_protocol_spec = *temp_protocols; + int protocol_match = 0; + CORBA::String_var listen_protocol; + u_int i =0; + for (i=0;i<my_protocol_spec.length ();i++) + { + CORBA::String_var my_protocol_string; + for (u_int j=0;j<peer_protocol_spec.length ();j++) + { + CORBA::String_var peer_protocol_string; + my_protocol_string = CORBA::string_dup (my_protocol_spec[i]); + peer_protocol_string = CORBA::string_dup (peer_protocol_spec[j]); + if (ACE_OS::strcmp (my_protocol_string,peer_protocol_string) == 0) + { + listen_protocol = my_protocol_string; + protocol_match = 1; + break; + } + } + if (protocol_match) + break; + } + if (!protocol_match) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_FlowEndPoint::go_to_listen failed: no protoocol match\n"),0); + + for (u_int j=0;j<this->protocol_addresses_.length ();j++) + if (ACE_OS::strncmp (this->protocol_addresses_ [j],listen_protocol,ACE_OS::strlen (listen_protocol)) == 0) + { + // Now listen on that protocol. + TAO_Forward_FlowSpec_Entry *entry; + ACE_NEW_RETURN (entry, + TAO_Forward_FlowSpec_Entry (this->flowname_.in (), + direction, + this->format_.in (), + flowProtocol, + this->protocol_addresses_ [j]), + 0); + + TAO_AV_Acceptor_Registry *acceptor_registry = TAO_AV_CORE::instance ()->acceptor_registry (); + this->flow_spec_set_.insert (entry); + int result = acceptor_registry->open (this, + TAO_AV_CORE::instance (), + this->flow_spec_set_); + if (result < 0) + return 0; + char *listen_address = entry->get_local_addr_str (); + char *address; + ACE_NEW_RETURN (address, + char [BUFSIZ], + 0); + ACE_OS::sprintf (address,"%s=%s",listen_protocol.in (),listen_address); + return address; + } return 0; } + CORBA::Boolean -TAO_FlowEndPoint::connect_to_peer (AVStreams::QoS & the_qos, - const char * address, - const char * use_flow_protocol, - CORBA::Environment &ACE_TRY_ENV) +TAO_FlowEndPoint::connect_to_peer_i (TAO_FlowSpec_Entry::Role role, + AVStreams::QoS & /*the_qos*/, + const char * address, + const char * use_flow_protocol, + CORBA::Environment &/*ACE_TRY_ENV*/) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::failedToConnect, - AVStreams::FPError, + AVStreams::FPError, AVStreams::QoSRequestFailed)) { - // Right now since the A/V framework doesnt bother about the - // protocols we leave it to the application to handle the connection - // to its peer. When A/V Streams implements common protocol - // interaction like UDP and TCP this will be handled by the - // framework. - - return this->handle_connect_to_peer (the_qos,address,use_flow_protocol,ACE_TRY_ENV); + char direction [BUFSIZ]; + switch (role) + { + case TAO_FlowSpec_Entry::TAO_AV_PRODUCER: + ACE_OS::strcpy (direction,"IN"); + break; + case TAO_FlowSpec_Entry::TAO_AV_CONSUMER: + ACE_OS::strcpy (direction,"OUT"); + break; + default: + break; + } + TAO_Forward_FlowSpec_Entry *entry; + ACE_NEW_RETURN (entry, + TAO_Forward_FlowSpec_Entry (this->flowname_.in (), + direction, + this->format_.in (), + use_flow_protocol, + address), + 0); + this->flow_spec_set_.insert (entry); + TAO_AV_Connector_Registry *connector_registry = TAO_AV_CORE::instance ()->connector_registry (); + int result = connector_registry->open (this, + TAO_AV_CORE::instance (), + this->flow_spec_set_); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_FlowEndPoint::connector_registry::open failed\n"),0); + this->reverse_channel_ = entry->get_local_addr_str (); + return 1; } -CORBA::Boolean -TAO_FlowEndPoint::handle_connect_to_peer (AVStreams::QoS & the_qos, - const char * address, - const char * use_flow_protocol, - CORBA::Environment &ACE_TRY_ENV) +int +TAO_FlowEndPoint::set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object) { - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (address); - ACE_UNUSED_ARG (use_flow_protocol); - ACE_UNUSED_ARG (ACE_TRY_ENV); return 0; } @@ -2254,36 +4397,125 @@ TAO_FlowProducer::TAO_FlowProducer (void) { } -// multicast is currently not supported +TAO_FlowProducer::TAO_FlowProducer (const char *flowname, + AVStreams::protocolSpec protocols, + const char *format) +{ + this->open (flowname,protocols,format); +} + +// gets the reverse channel for feedback. char * -TAO_FlowProducer::connect_mcast (AVStreams::QoS & the_qos, - CORBA::Boolean_out is_met, - const char * address, - const char * use_flow_protocol, - CORBA::Environment &ACE_TRY_ENV) +TAO_FlowProducer::get_rev_channel (const char *pcol_name, + CORBA::Environment &/* ACE_TRY_ENV */) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return 0; +} + +// The start,stop and destroy are to be handled by the application. +void +TAO_FlowProducer::stop (CORBA::Environment &/*ACE_TRY_ENV*/) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_AV_FlowSpecSetItor end = this->flow_spec_set_.end (); + for (TAO_AV_FlowSpecSetItor begin = this->flow_spec_set_.begin (); + begin != end; ++begin) + { + TAO_FlowSpec_Entry *entry = (*begin); + entry->handler ()->stop (TAO_FlowSpec_Entry::TAO_AV_PRODUCER); + } +} + +void +TAO_FlowProducer::start (CORBA::Environment &/*ACE_TRY_ENV*/) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_AV_FlowSpecSetItor end = this->flow_spec_set_.end (); + for (TAO_AV_FlowSpecSetItor begin = this->flow_spec_set_.begin (); + begin != end; ++begin) + { + TAO_FlowSpec_Entry *entry = (*begin); + entry->handler ()->start (TAO_FlowSpec_Entry::TAO_AV_PRODUCER); + } +} + +char * +TAO_FlowProducer::go_to_listen (AVStreams::QoS & the_qos, + CORBA::Boolean is_mcast, + AVStreams::FlowEndPoint_ptr peer_fep, + char *& flowProtocol, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::failedToConnect, - AVStreams::notSupported, + AVStreams::failedToListen, AVStreams::FPError, AVStreams::QoSRequestFailed)) { - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (is_met); - ACE_UNUSED_ARG (address); - ACE_UNUSED_ARG (use_flow_protocol); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + return this->go_to_listen_i (TAO_FlowSpec_Entry::TAO_AV_PRODUCER, + the_qos, + is_mcast, + peer_fep, + flowProtocol, + ACE_TRY_ENV); } -// gets the reverse channel for feedback. -char * -TAO_FlowProducer::get_rev_channel (const char * pcol_name, +CORBA::Boolean +TAO_FlowProducer::connect_to_peer (AVStreams::QoS & the_qos, + const char * address, + const char * use_flow_protocol, CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException)) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::failedToConnect, + AVStreams::FPError, + AVStreams::QoSRequestFailed)) { - ACE_UNUSED_ARG (pcol_name); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + return this->connect_to_peer_i (TAO_FlowSpec_Entry::TAO_AV_PRODUCER, + the_qos, + address, + use_flow_protocol, + ACE_TRY_ENV); +} +// Connect to a IP multicast address. +char * +TAO_FlowProducer::connect_mcast (AVStreams::QoS & /* the_qos */, + CORBA::Boolean_out /* is_met */, + const char *address, + const char * use_flow_protocol, + CORBA::Environment &/*ACE_TRY_ENV*/) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::failedToConnect, + AVStreams::notSupported, + AVStreams::FPError, + AVStreams::QoSRequestFailed)) +{ + // The address variable gives the multicast address to subscribe to. + for (u_int i=0;i<this->protocols_.length ();i++) + { + // choose the protocol which supports multicast. + } + TAO_Forward_FlowSpec_Entry *entry; + ACE_NEW_RETURN (entry, + TAO_Forward_FlowSpec_Entry(this->flowname_.in (), + "IN", + this->format_.in (), + use_flow_protocol, + address), + 0); + + this->flow_spec_set_.insert (entry); + TAO_AV_Acceptor_Registry *acceptor_registry = + TAO_AV_CORE::instance ()->acceptor_registry (); + int result = acceptor_registry->open (this, + TAO_AV_CORE::instance (), + this->flow_spec_set_); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_FlowProducer::connect_mcast:acceptor_registry open failed\n"),0); + // Now remove our handler from the reactor since we're a producer and dont want to get called for + // multicast packets. + ACE_Event_Handler *event_handler = entry->handler ()->event_handler (); + event_handler->reactor ()->remove_handler (event_handler, + ACE_Event_Handler::READ_MASK); + return CORBA::string_dup (address); } // sets the key for this flow. @@ -2312,10 +4544,9 @@ TAO_FlowProducer::set_key (const AVStreams::key & the_key, // source id to be used to distinguish this source from others. void TAO_FlowProducer::set_source_id (CORBA::Long source_id, - CORBA::Environment &ACE_TRY_ENV) + CORBA::Environment &/* ACE_TRY_ENV */) ACE_THROW_SPEC ((CORBA::SystemException)) { - ACE_UNUSED_ARG (ACE_TRY_ENV); this->source_id_ = source_id; } @@ -2329,192 +4560,132 @@ TAO_FlowConsumer::TAO_FlowConsumer (void) { } -// ------------------------------------------------------------ -// TAO_FDev -// ------------------------------------------------------------ - -// default constructor -TAO_FDev::TAO_FDev (void) - :producer_ (0), - consumer_ (0) -{ -} - -AVStreams::FlowProducer_ptr -TAO_FDev::create_producer (AVStreams::FlowConnection_ptr the_requester, - AVStreams::QoS & the_qos, - CORBA::Boolean_out met_qos, - char *& named_fdev, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, - AVStreams::notSupported, - AVStreams::QoSRequestFailed)) -{ - // call the bridge method. - this->producer_ = this->make_producer (the_requester, - the_qos, - met_qos, - named_fdev, - ACE_TRY_ENV); - return this->producer_; -} - -// hook for the applications to override the creation process. -AVStreams::FlowProducer_ptr -TAO_FDev::make_producer (AVStreams::FlowConnection_ptr /* the_requester */, - AVStreams::QoS & /* the_qos */, - CORBA::Boolean_out /* met_qos */, - char *& /* named_fdev */, - CORBA::Environment &ACE_TRY_ENV) +TAO_FlowConsumer::TAO_FlowConsumer (const char *flowname, + AVStreams::protocolSpec protocols, + const char *format) { - AVStreams::FlowProducer_ptr flow_producer = AVStreams::FlowProducer::_nil (); - ACE_TRY - { - // memory leak?? - TAO_FlowProducer *producer; - ACE_NEW_RETURN (producer, - TAO_FlowProducer, - 0); - - flow_producer = producer->_this (ACE_TRY_ENV); - ACE_TRY_CHECK; - } - ACE_CATCHANY - { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FDev::make_producer"); - return flow_producer; - } - ACE_ENDTRY; - ACE_CHECK_RETURN (flow_producer); - return flow_producer; + this->open (flowname,protocols,format); } -// hook for the applications to override the consumer creation. -AVStreams::FlowConsumer_ptr -TAO_FDev::make_consumer (AVStreams::FlowConnection_ptr /* the_requester */, - AVStreams::QoS & /* the_qos */, - CORBA::Boolean_out /* met_qos */, - char *& /* named_fdev */, - CORBA::Environment &ACE_TRY_ENV) +// The start,stop and destroy are to be handled by the application. +void +TAO_FlowConsumer::stop (CORBA::Environment &/*ACE_TRY_ENV*/) + ACE_THROW_SPEC ((CORBA::SystemException)) { - AVStreams::FlowConsumer_ptr flow_consumer = AVStreams::FlowConsumer::_nil (); - ACE_TRY - { - - // memory leak?? - TAO_FlowConsumer *consumer; - ACE_NEW_RETURN (consumer, - TAO_FlowConsumer, - 0); - flow_consumer = consumer->_this (ACE_TRY_ENV); - ACE_TRY_CHECK; - } - ACE_CATCHANY - { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FDev::make_consumer"); - return flow_consumer; - } - ACE_ENDTRY; - ACE_CHECK_RETURN (flow_consumer); - return flow_consumer; + TAO_AV_FlowSpecSetItor end = this->flow_spec_set_.end (); + for (TAO_AV_FlowSpecSetItor begin = this->flow_spec_set_.begin (); + begin != end; ++begin) + (*begin)->handler ()->stop (TAO_FlowSpec_Entry::TAO_AV_CONSUMER); } -AVStreams::FlowConsumer_ptr -TAO_FDev::create_consumer (AVStreams::FlowConnection_ptr the_requester, - AVStreams::QoS & the_qos, - CORBA::Boolean_out met_qos, - char *& named_fdev, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, - AVStreams::notSupported, - AVStreams::QoSRequestFailed)) +void +TAO_FlowConsumer::start (CORBA::Environment &/*ACE_TRY_ENV*/) + ACE_THROW_SPEC ((CORBA::SystemException)) { - this->consumer_ = this->make_consumer (the_requester, - the_qos, - met_qos, - named_fdev, - ACE_TRY_ENV); - return this->consumer_; + 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); } -// not implemented yet. -AVStreams::FlowConnection_ptr -TAO_FDev::bind (AVStreams::FDev_ptr peer_device, - AVStreams::QoS & the_qos, - CORBA::Boolean_out is_met, - CORBA::Environment &ACE_TRY_ENV) +char * +TAO_FlowConsumer::go_to_listen (AVStreams::QoS & the_qos, + CORBA::Boolean is_mcast, + AVStreams::FlowEndPoint_ptr peer_fep, + char *& flowProtocol, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, + AVStreams::failedToListen, + AVStreams::FPError, AVStreams::QoSRequestFailed)) { - ACE_UNUSED_ARG (peer_device); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (is_met); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; + return this->go_to_listen_i (TAO_FlowSpec_Entry::TAO_AV_CONSUMER, + the_qos, + is_mcast, + peer_fep, + flowProtocol, + ACE_TRY_ENV); } -// multicast is not supported yet. -AVStreams::FlowConnection_ptr -TAO_FDev::bind_mcast (AVStreams::FDev_ptr first_peer, - AVStreams::QoS & the_qos, - CORBA::Boolean_out is_met, - CORBA::Environment &ACE_TRY_ENV) +CORBA::Boolean +TAO_FlowConsumer::connect_to_peer (AVStreams::QoS & the_qos, + const char * address, + const char * use_flow_protocol, + CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, + AVStreams::failedToConnect, + AVStreams::FPError, AVStreams::QoSRequestFailed)) { - ACE_UNUSED_ARG (first_peer); - ACE_UNUSED_ARG (the_qos); - ACE_UNUSED_ARG (is_met); - ACE_UNUSED_ARG (ACE_TRY_ENV); - return 0; -} - -void -TAO_FDev::destroy (AVStreams::FlowEndPoint_ptr /* the_ep */, - const char * /* fdev_name */, - CORBA::Environment &ACE_TRY_ENV) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported)) -{ - // Remove self from POA. Because of reference counting, the POA - // will automatically delete the servant when all pending requests - // on this servant are complete. - // - PortableServer::POA_var poa = this->_default_POA (ACE_TRY_ENV); - ACE_CHECK; - - PortableServer::ObjectId_var id = poa->servant_to_id (this, - ACE_TRY_ENV); - ACE_CHECK; - - poa->deactivate_object (id.in (), - ACE_TRY_ENV); - ACE_CHECK; + return this->connect_to_peer_i (TAO_FlowSpec_Entry::TAO_AV_CONSUMER, + the_qos, + address, + use_flow_protocol, + ACE_TRY_ENV); } //------------------------------------------------------------ // TAO_Tokenizer //------------------------------------------------------------ -TAO_Tokenizer::TAO_Tokenizer (char *string, char delimiter) +TAO_Tokenizer::TAO_Tokenizer (const char *string, char delimiter) :token_array_ (10), count_ (0) { this->parse (string,delimiter); } -int -TAO_Tokenizer::parse (char *string,char delimiter) +TAO_Tokenizer::~TAO_Tokenizer () { +// ACE_Array_Iterator<char*> iterator (this->token_array_); +// char **entry = 0; +// for (; iterator.next (entry) != 0; iterator.advance ()) +// { +// if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%s\n",*entry)); +// CORBA::string_free (*entry); +// } +} + + +int +TAO_Tokenizer::parse (const char *string,char delimiter) +{ + ACE_CString new_string (string); + u_int pos =0; + int slash_pos = 0; + u_int count = 0; + int result; + while (pos < new_string.length ()) + { + slash_pos = new_string.find (delimiter,pos); + ACE_CString substring; + if (slash_pos != new_string.npos) + { + substring = new_string.substring (pos,slash_pos); + pos += slash_pos+1; + } + else + { + substring = new_string.substring (pos); + pos = new_string.length (); + } + char *token = CORBA::string_dup (substring.c_str ()); + result = this->token_array_.set (token,count); + if (result == -1) + { + this->token_array_.size (this->token_array_.size ()*2); + result = this->token_array_.set (token,count); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_Tokenizer::parse error"),-1); + } + count++; + } + + /* + ACE_OS::strcpy (this->string_ , string); char delimiter_str [2] = {0,0}; delimiter_str [0] = delimiter; - char *token = ACE_OS::strtok (string,delimiter_str); - int count=0,result; + char *token = ACE_OS::strtok (this->string_,delimiter_str); + while (token != 0) { result = this->token_array_.set (token,count); @@ -2525,9 +4696,10 @@ TAO_Tokenizer::parse (char *string,char delimiter) if (result == -1) ACE_ERROR_RETURN ((LM_ERROR,"TAO_Tokenizer::parse error"),-1); } - token = ACE_OS::strtok (string,0); + token = ACE_OS::strtok (0,delimiter_str); count++; } + */ this->num_tokens_ = count; return 0; } @@ -2536,7 +4708,7 @@ char* TAO_Tokenizer::token (void) { if (count_ < num_tokens_) - return this->token_array_[this->count_++]; + return CORBA::string_dup (this->token_array_[this->count_++]); else return 0; } @@ -2552,143 +4724,262 @@ TAO_Tokenizer::operator [] (size_t index) const { if (index >= this->num_tokens_) return 0; - return this->token_array_[index]; -} - -//------------------------------------------------------------ -// TAO_FlowSpec_Entry -//------------------------------------------------------------ - -// constructor. -TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (void) - :sfp_ (0), - address_ (0), - format_ (0), - direction_ (TAO_AV_INVALID) -{ + return CORBA::string_dup (this->token_array_[index]); } -// Destructor. -TAO_FlowSpec_Entry::~TAO_FlowSpec_Entry (void) -{ -} -int -TAO_FlowSpec_Entry::direction (void) -{ - return this->direction_; -} +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -TAO_SFP* -TAO_FlowSpec_Entry::flow_protocol (void) -{ - return this->sfp_; -} +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::FDev_ptr>; +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr>; +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr>; +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key, TAO_FlowSpec_Entry *>; + +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_FlowSpec_Entry *, ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex>; + +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Entry<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry>; +template class ACE_Hash_Map_Manager<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_AV_Acceptor*>; +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_AV_Acceptor*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_AV_Acceptor*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_AV_Acceptor*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*>; +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*>; +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*>; +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::QoS>; +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::QoS,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::QoS,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::QoS,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_FlowSpec_Entry *,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_FlowSpec_Entry *,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_FlowSpec_Entry *,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; + +template class ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>; -ACE_Addr* -TAO_FlowSpec_Entry::carrier_protocol (void) -{ - return address_; -} - -char* -TAO_FlowSpec_Entry::format (void) -{ - return this->format_; -} +template class ACE_Array<char*>; +template class ACE_Array_Base<char*>; +template class ACE_DLList<TAO_MCastConfigIf::Peer_Info>; +template class ACE_DLList_Iterator<TAO_MCastConfigIf::Peer_Info>; +template class ACE_DLList <TAO_FlowProducer>; +template class ACE_DLList_Iterator <TAO_FlowProducer>; +template class ACE_DLList <TAO_FlowConsumer>; +template class ACE_DLList_Iterator <TAO_FlowConsumer>; -int -TAO_Forward_FlowSpec_Entry::parse (char *flowSpec_entry) -{ - TAO_Tokenizer tokenizer (flowSpec_entry,'\\'); - if (this->parse_flow_protocol_string (tokenizer [TAO_AV_FLOW_PROTOCOL]) < 0) - return -1; - this->set_direction (tokenizer [TAO_AV_DIRECTION]); - if (this->parse_address (tokenizer [TAO_AV_ADDRESS]) < 0) - return -1; - this->format_ = tokenizer [TAO_AV_FORMAT]; - this->flowname_ = tokenizer [TAO_AV_FLOWNAME]; - return 0; -} +template class ACE_Node <TAO_FlowSpec_Entry*>; +template class ACE_Unbounded_Set <TAO_FlowSpec_Entry*>; +template class ACE_Unbounded_Set_Iterator <TAO_FlowSpec_Entry*>; -int -TAO_FlowSpec_Entry::set_direction (char *direction) -{ - if (ACE_OS::strcasecmp (direction,"in") == 0) - this->direction_ = TAO_AV_DIR_IN; - else if (ACE_OS::strcasecmp (direction,"out") == 0) - this->direction_ = TAO_AV_DIR_OUT; - else if (ACE_OS::strcasecmp (direction,"inout") == 0) - this->direction_ = TAO_AV_DIR_INOUT; - return 0; -} +template class ACE_Node <TAO_AV_Transport_Item*>; +template class ACE_Unbounded_Set<TAO_AV_Transport_Item*>; +template class ACE_Unbounded_Set_Iterator<TAO_AV_Transport_Item*>; -int -TAO_FlowSpec_Entry::parse_flow_protocol_string (char *flow_string) -{ - if (ACE_OS::strncasecmp (flow_string,"sfp",3) == 0) - { - // do some flow protocol processing. - } - return 0; -} +template class ACE_Node <TAO_AV_Flow_Protocol_Item*>; +template class ACE_Unbounded_Set<TAO_AV_Flow_Protocol_Item*>; +template class ACE_Unbounded_Set_Iterator<TAO_AV_Flow_Protocol_Item*>; -int -TAO_FlowSpec_Entry::parse_address (char *address) -{ - TAO_Tokenizer protocol_tokenizer (address,'='); - this->protocol_ = protocol_tokenizer[0]; - TAO_Tokenizer address_tokenizer (protocol_tokenizer[1],';'); - char addr[BUFSIZ]; - ACE_OS::sprintf (addr,"%s:%s",address_tokenizer[0],address_tokenizer[1]); - if (ACE_OS::strncasecmp (this->protocol_,"AAL",3) == 0) - ACE_DEBUG ((LM_DEBUG,"ATM support not added yet\n")); -// ACE_NEW_RETURN (this->address_, -// ACE_ATM_Addr (addr), -// -1); - else // we assume everything else is INET addr. - { - ACE_NEW_RETURN (this->address_, - ACE_INET_Addr (addr), - -1); - } - return 0; -} +template class ACE_Node<AVStreams::FlowProducer *>; +template class ACE_Unbounded_Set<AVStreams::FlowProducer *>; +template class ACE_Unbounded_Set_Iterator<AVStreams::FlowProducer *>; -int -TAO_Reverse_FlowSpec_Entry::parse (char *flowSpec_entry) -{ - TAO_Tokenizer tokenizer (flowSpec_entry,'\\'); - if (this->parse_flow_protocol_string (tokenizer [TAO_AV_FLOW_PROTOCOL]) < 0) - return -1; - this->set_direction (tokenizer [TAO_AV_DIRECTION]); - if (this->parse_address (tokenizer [TAO_AV_ADDRESS]) < 0) - return -1; - this->format_ = tokenizer [TAO_AV_FORMAT]; - this->flowname_ = tokenizer [TAO_AV_FLOWNAME]; - return 0; -} +template class ACE_Node<AVStreams::FlowConsumer *>; +template class ACE_Unbounded_Set<AVStreams::FlowConsumer *>; +template class ACE_Unbounded_Set_Iterator<AVStreams::FlowConsumer *>; -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Hash_Map_Entry<TAO_String_Hash_Key,CORBA::Object_ptr>; -template class ACE_Hash_Map_Manager<TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex>; -template class ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator<TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex>; -template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex>; -template class ACE_Array<char*>; -template class ACE_Array_Base<char*>; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,CORBA::Object_ptr> -#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, CORBA::Object_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::FDev_ptr> +#pragma instantaite ACE_Hash_Map_Entry<TAO_String_Hash_Key, TAO_FlowSpec_Entry *> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_FlowSpec_Entry *, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FDev_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowConnection_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::FlowEndPoint_ptr, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry> +#pragma instantiate ACE_Hash_Map_Manager<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<MMDevice_Map_Hash_Key,TAO_StreamCtrl::MMDevice_Map_Entry,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<MMDevice_Map_Hash_Key, TAO_StreamCtrl::MMDevice_Map_Entry, ACE_Hash<MMDevice_Map_Hash_Key>, ACE_Equal_To<MMDevice_Map_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_AV_Acceptor*> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_AV_Acceptor*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_AV_Acceptor*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_AV_Acceptor*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_Acceptor*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_Forward_FlowSpec_Entry*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_Forward_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_Reverse_FlowSpec_Entry*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_Reverse_FlowSpec_Entry*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_AV_UDP_MCast_Flow_Handler*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_AV_UDP_MCast_Flow_Handler*, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,AVStreams::QoS> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::QoS,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,AVStreams::QoS,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,AVStreams::QoS,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, AVStreams::QoS, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Entry<TAO_String_Hash_Key,TAO_FlowSpec_Entry *> +#pragma instantiate ACE_Hash_Map_Manager<TAO_String_Hash_Key,TAO_FlowSpec_Entry *,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<TAO_String_Hash_Key,TAO_FlowSpec_Entry *,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<TAO_String_Hash_Key,TAO_FlowSpec_Entry *,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_String_Hash_Key, TAO_FlowSpec_Entry *, ACE_Hash<TAO_String_Hash_Key>, ACE_Equal_To<TAO_String_Hash_Key>, ACE_Null_Mutex> + + +#pragma instantiate ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH> #pragma instantiate ACE_Array<char*> #pragma instantiate ACE_Array_Base<char*> +#pragma instantiate ACE_DLList<TAO_MCastConfigIf::Peer_Info> +#pragma instantiate ACE_DLList_Iterator<TAO_MCastConfigIf::Peer_Info> +#pragma instantiate ACE_DLList <TAO_FlowProducer> +#pragma instantiate ACE_DLList_Iterator <TAO_FlowProducer> +#pragma instantiate ACE_DLList <TAO_FlowConsumer> +#pragma instantiate ACE_DLList_Iterator <TAO_FlowConsumer> + +#pragma instantiate ACE_Node <TAO_FlowSpec_Entry*> +#pragma instantiate ACE_Unbounded_Set <TAO_FlowSpec_Entry*> +#pragma instantiate ACE_Unbounded_Set_Iterator <TAO_FlowSpec_Entry*> + +#pragma instantiate ACE_Node <TAO_AV_Transport_Item*> +#pragma instantiate ACE_Unbounded_Set<TAO_AV_Transport_Item*> +#pragma instantiate ACE_Unbounded_Set_Iterator<TAO_AV_Transport_Item*> + +#pragma instantiate ACE_Node <TAO_AV_Flow_Protocol_Item*> +#pragma instantiate ACE_Unbounded_Set<TAO_AV_Flow_Protocol_Item*> +#pragma instantiate ACE_Unbounded_Set_Iterator<TAO_AV_Transport_Item*> + +#pragma instantiate ACE_Node<AVStreams::FlowProducer *> +#pragma instantiate ACE_Unbounded_Set<AVStreams::FlowProducer *> +#pragma instantiate ACE_Unbounded_Set_Iterator<AVStreams::FlowProducer *> + +#pragma instantiate ACE_Node<AVStreams::FlowConsumer *> +#pragma instantiate ACE_Unbounded_Set<AVStreams::FlowConsumer *> +#pragma instantiate ACE_Unbounded_Set_Iterator<AVStreams::FlowConsumer *> + + #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h index 1a871277da6..405b7b00e92 100644 --- a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h +++ b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.h @@ -5,7 +5,7 @@ // ============================================================================ // // = LIBRARY -// cos +// ORBSVCS (AVStreams) // // = FILENAME // AVStreams_i.h @@ -20,11 +20,20 @@ #ifndef AVSTREAMS_I_H #define AVSTREAMS_I_H +#include "ace/OS.h" #include "ace/SOCK_Dgram_Mcast.h" #include "ace/ATM_Addr.h" #include "ace/Containers_T.h" #include "ace/Process.h" - +#include "ace/SOCK_CODgram.h" +#include "ace/Connector.h" +#include "ace/SOCK_Connector.h" +#include "ace/Acceptor.h" +#include "ace/SOCK_Stream.h" +#include "ace/Svc_Handler.h" +#include "ace/SOCK_Acceptor.h" + +#include "tao/TAO.h" #include "orbsvcs/orbsvcs_export.h" #include "orbsvcs/CosPropertyServiceS.h" #include "orbsvcs/AVStreamsS.h" @@ -32,10 +41,19 @@ #include "orbsvcs/CosNamingC.h" #include "orbsvcs/AV/Endpoint_Strategy.h" #include "orbsvcs/Null_MediaCtrlS.h" + +#if defined (TAO_ORBSVCS_HAS_Trader) #include "orbsvcs/Trader/Trader.h" -// for the Hash_Map helper classes. +#endif /* TAO_ORBSVCS_HAS_Trader */ -#include "sfp.h" +#include "FlowSpec_Entry.h" + +#if defined(sun) || defined(__osf__) +extern "C" int gethostname(char* name, int len); +#endif + +#define FLOWSPEC_MAX 5 +// for the Hash_Map helper classes. // This is to remove "inherits via dominance" warnings from MSVC. // MSVC is being a little too paranoid. @@ -43,6 +61,54 @@ # pragma warning (disable : 4250) #endif /* _MSC_VER */ +#if !defined (TAO_ORBSVCS_HAS_Trader) + +// = Classes to deal with the ACE_Hash_Map_Manager. +class TAO_ORBSVCS_Export TAO_String_Hash_Key : public CORBA::String_var +{ + // = TITLE + // Key for the Hash Table. The EXT_ID of the + // ACE_Hash_Map_Manager. +public: + // = Initialization and termination methods. + TAO_String_Hash_Key (void); + // Default constructor. + + TAO_String_Hash_Key (char * name); + // Constructor from a const string. + + TAO_String_Hash_Key (const char * name); + // Constructor from a const string. + + TAO_String_Hash_Key (const CORBA::String_var &hash_key); + // Copy constructor. + + ~TAO_String_Hash_Key (void); + // Destructor. + + int operator == (const TAO_String_Hash_Key &hash_key) const; + // The operator for hash binding and "find"ing. + + friend int operator < (const TAO_String_Hash_Key &left, + const TAO_String_Hash_Key &right); + // The operator for hash binding and "find"ing. + + u_long hash (void) const; + // The function that computes a hash value. +}; +#endif /* !TAO_ORBSVCS_HAS_Trader */ + +typedef ACE_Hash_Map_Manager <TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex> FlowEndPoint_Map; +typedef ACE_Hash_Map_Entry <TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr> FlowEndPoint_Map_Entry; +typedef ACE_Hash_Map_Iterator <TAO_String_Hash_Key,AVStreams::FlowEndPoint_ptr,ACE_Null_Mutex> FlowEndPoint_Map_Iterator; + +#include "AV_Core.h" + +typedef ACE_Singleton <TAO_AV_Core,ACE_Null_Mutex> TAO_AV_CORE; + +int deactivate_servant (PortableServer::Servant servant); +char *get_flowname (const char *flow_spec_entry_str); + class TAO_ORBSVCS_Export AV_Null_MediaCtrl : public virtual POA_Null_MediaCtrl, public virtual PortableServer::RefCountServantBase @@ -52,7 +118,7 @@ public: }; -class TAO_ORBSVCS_Export TAO_Basic_StreamCtrl +class TAO_ORBSVCS_Export TAO_Basic_StreamCtrl : public virtual POA_AVStreams::Basic_StreamCtrl, public virtual TAO_PropertySet, public virtual PortableServer::RefCountServantBase @@ -65,22 +131,25 @@ public: TAO_Basic_StreamCtrl (void); // Default Constructor + virtual ~TAO_Basic_StreamCtrl (void); + // Destructor. + virtual void stop (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)); // Stop the transfer of data of the stream // Empty the_spec means apply operation to all flows virtual void start (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)); // Start the transfer of data in the stream. // Empty the_spec means apply operation to all flows virtual void destroy (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)); // Tears down the stream. This will close the connection, and delete @@ -89,15 +158,15 @@ public: virtual CORBA::Boolean modify_QoS (AVStreams::streamQoS &new_qos, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)); // Changes the QoS associated with the stream // Empty the_spec means apply operation to all flows - virtual void push_event (const struct CosPropertyService::Property & the_event, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual void push_event (const struct CosPropertyService::Property & the_event, + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // Used by StreamEndPoint and VDev to inform StreamCtrl of events. // E.g., loss of flow, reestablishment of flow, etc.. @@ -105,7 +174,7 @@ public: virtual void set_FPStatus (const AVStreams::flowSpec &the_spec, const char *fp_name, const CORBA::Any &fp_settings, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::FPError)); @@ -128,9 +197,6 @@ public: // Not implemented in the light profile, will raise the notsupported // exception - virtual ~TAO_Basic_StreamCtrl (void); - // Destructor - protected: AVStreams::VDev_var vdev_a_; @@ -141,8 +207,10 @@ protected: AVStreams::StreamEndPoint_B_var sep_b_; // The Endpoints for this stream - typedef ACE_Hash_Map_Manager <TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex> FlowConnection_Map; - FlowConnection_Map flow_map_; + typedef ACE_Hash_Map_Manager <TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex> FlowConnection_Map; + typedef ACE_Hash_Map_Iterator <TAO_String_Hash_Key,AVStreams::FlowConnection_ptr,ACE_Null_Mutex> FlowConnection_Map_Iterator; + typedef ACE_Hash_Map_Entry <TAO_String_Hash_Key,AVStreams::FlowConnection_ptr> FlowConnection_Map_Entry; + FlowConnection_Map flow_connection_map_; // Hash table for the flow names and its corresponding flowconnection object reference. AVStreams::FlowConnection_seq flowConnections_; @@ -158,30 +226,93 @@ class TAO_ORBSVCS_Export TAO_Negotiator public: virtual CORBA::Boolean negotiate (AVStreams::Negotiator_ptr remote_negotiator, const AVStreams::streamQoS &qos_spec, - CORBA::Environment &ACE_TRY_ENV = CORBA::Environment::default_environment ()) + CORBA::Environment &ACE_TRY_ENV = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); }; class TAO_MCastConfigIf; +class MMDevice_Map_Hash_Key +{ +public: + MMDevice_Map_Hash_Key (void); + // default constructor. + + MMDevice_Map_Hash_Key (AVStreams::MMDevice_ptr mmdevice); + // constructor. + + MMDevice_Map_Hash_Key (const MMDevice_Map_Hash_Key&); + // copy constructor. + + ~MMDevice_Map_Hash_Key (void); + // destructor. + + int operator == (const MMDevice_Map_Hash_Key &hash_key) const; + // operator== needed by ACE_Hash_Map_Manager. + + friend int operator < (const MMDevice_Map_Hash_Key &left, + const MMDevice_Map_Hash_Key &right); + // operator== needed by ACE_Hash_Map_Manager. + + u_long hash (void) const; + // hash function for this mmdevice. + + static const int hash_maximum_; +protected: + AVStreams::MMDevice_ptr mmdevice_; +}; + class TAO_ORBSVCS_Export TAO_StreamCtrl : public virtual POA_AVStreams::StreamCtrl, public virtual TAO_Basic_StreamCtrl, public virtual PortableServer::RefCountServantBase -// = DESCRIPTION -// Implementation the A/V StreamCtrl class. this class -// is used to control the stream. It should be subclassed -// by applications that want to provide more control features. { + // = DESCRIPTION + // Implementation the A/V StreamCtrl class. this class + // is used to control the stream. It should be subclassed + // by applications that want to provide more control features. + public: + TAO_StreamCtrl (void); // Default Constructor + TAO_StreamCtrl (TAO_StreamCtrl const &); + // Copy Constructor to fool g++ + + virtual ~TAO_StreamCtrl (void); + // virtual destructor. + + void operator= (TAO_StreamCtrl const &); + // Fooling g++ + + virtual void stop (const AVStreams::flowSpec &the_spec, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::noSuchFlow)); + // Stop the transfer of data of the stream + // Empty the_spec means apply operation to all flows + + virtual void start (const AVStreams::flowSpec &the_spec, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::noSuchFlow)); + // Start the transfer of data in the stream. + // Empty the_spec means apply operation to all flows + + virtual void destroy (const AVStreams::flowSpec &the_spec, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::noSuchFlow)); + // Tears down the stream. This will close the connection, and delete + // the streamendpoint and vdev associated with this stream + // Empty the_spec means apply operation to all flows + virtual CORBA::Boolean bind_devs (AVStreams::MMDevice_ptr a_party, AVStreams::MMDevice_ptr b_party, AVStreams::streamQoS &the_qos, const AVStreams::flowSpec &the_flows, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpFailed, AVStreams::noSuchFlow, @@ -207,7 +338,7 @@ public: virtual void unbind_dev (AVStreams::MMDevice_ptr dev, const AVStreams::flowSpec & the_spec, - CORBA::Environment &ACE_TRY_ENV = CORBA::Environment::default_environment ()) + CORBA::Environment &ACE_TRY_ENV = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpFailed, AVStreams::noSuchFlow)); @@ -220,7 +351,7 @@ public: AVStreams::noSuchFlow)); // Unbind the_ep from the stream. Empty the_spec means apply to all flows. - virtual void unbind (CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual void unbind (CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpFailed)); // unbind the stream. Same effect as Basic_StreamCtrl::destroy () @@ -233,19 +364,32 @@ public: virtual CORBA::Boolean modify_QoS (AVStreams::streamQoS &new_qos, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)); // Changes the QoS associated with the stream // Empty the_spec means apply operation to all flows - virtual ~TAO_StreamCtrl (void); - // Destructor. +protected: + + struct MMDevice_Map_Entry + { + AVStreams::StreamEndPoint_var sep_; + AVStreams::VDev_var vdev_; + AVStreams::flowSpec flowspec_; + AVStreams::streamQoS qos_; + }; + + typedef ACE_Hash_Map_Manager <MMDevice_Map_Hash_Key,MMDevice_Map_Entry,ACE_Null_Mutex> MMDevice_Map; + typedef ACE_Hash_Map_Iterator <MMDevice_Map_Hash_Key,MMDevice_Map_Entry,ACE_Null_Mutex> MMDevice_Map_Iterator; - protected: + MMDevice_Map mmdevice_a_map_; + MMDevice_Map mmdevice_b_map_; TAO_MCastConfigIf *mcastconfigif_; - AVStreams::MCastConfigIf_ptr mcastconfigif_ptr_; + AVStreams::MCastConfigIf_var mcastconfigif_ptr_; + AVStreams::StreamCtrl_var streamctrl_; + CORBA::ULong source_id_; }; class TAO_ORBSVCS_Export TAO_MCastConfigIf @@ -254,6 +398,23 @@ class TAO_ORBSVCS_Export TAO_MCastConfigIf public virtual PortableServer::RefCountServantBase { public: + + enum Peer_Interface {VDEV = 0, FLOWENDPOINT=1}; + struct Peer_Info + { + AVStreams::VDev_var peer_; + AVStreams::FlowEndPoint_var fep_; + AVStreams::streamQoS qos_; + AVStreams::flowSpec flow_spec_; + Peer_Interface interface_; + }; + + TAO_MCastConfigIf (void); + // Default constructor. + + ~TAO_MCastConfigIf (void); + // Dtor + virtual CORBA::Boolean set_peer (CORBA::Object_ptr peer, AVStreams::streamQoS & the_qos, const AVStreams::flowSpec & the_spec, @@ -272,7 +433,7 @@ public: virtual void set_format (const char * flowName, const char * format_name, - CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment &ACE_TRY_ENV = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)); @@ -280,64 +441,95 @@ public: virtual void set_dev_params (const char * flowName, const CosPropertyService::Properties & new_params, CORBA::Environment &ACE_TRY_ENV = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::PropertyException, AVStreams::streamOpFailed)); - + protected: + int in_flowSpec (const AVStreams::flowSpec& flow_spec, const char *flow_name); + // checks whether the flowname is in the flow_spec. + ACE_SOCK_Dgram_Mcast sock_mcast_; // Multicast socket. + + CosPropertyService::Properties initial_configuration_; + // Initial configuration to be distributed to all B parties when they join. + + ACE_DLList<Peer_Info> peer_list_; + ACE_DLList_Iterator<Peer_Info> peer_list_iterator_; }; +// Forward declarations. +class TAO_AV_TCP_Flow_Handler; +class TAO_AV_UDP_Flow_Handler; +class TAO_AV_UDP_MCast_Flow_Handler; +class TAO_AV_Protocol_Object; +class TAO_AV_Callback; +class TAO_AV_SourceManager; +class TAO_AV_Source; +class TAO_AV_RTP_State; +class TAO_AV_Flow_Handler; + class TAO_ORBSVCS_Export TAO_Base_StreamEndPoint { // = DESCRIPTION // Base class for the A/V StreamEndPoint class. this class // is used to control the stream. It should be subclassed // by applications that want to provide more control features. + + // @@Naga: Rename this class to TAO_Base_EndPoint since both stream and flowendpoints derive from it. public: + TAO_Base_StreamEndPoint (void); virtual ~TAO_Base_StreamEndPoint (void); - virtual int handle_open (void) = 0; + virtual int handle_open (void); // called when streamendpoint is instantiated - virtual int handle_close (void) = 0; + virtual int handle_close (void); // called when streamendpoint is being destructed virtual int handle_stop (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) = 0; + CORBA::Environment &env = CORBA::Environment::default_environment ()); // Application needs to define this virtual int handle_start (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) = 0; + CORBA::Environment &env = CORBA::Environment::default_environment ()); // Application needs to define this - virtual int handle_destroy (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) = 0; + CORBA::Environment &env = CORBA::Environment::default_environment ()); // Application needs to define this -}; -class TAO_ORBSVCS_Export TAO_Client_Base_StreamEndPoint - : public virtual TAO_Base_StreamEndPoint -{ -public: - virtual CORBA::Boolean handle_preconnect (AVStreams::flowSpec &the_spec) = 0; + virtual CORBA::Boolean handle_preconnect (AVStreams::flowSpec &the_spec); // Application needs to define this - virtual CORBA::Boolean handle_postconnect (AVStreams::flowSpec &the_spec) = 0; + virtual CORBA::Boolean handle_postconnect (AVStreams::flowSpec &the_spec); // Application needs to define this -}; -class TAO_ORBSVCS_Export TAO_Server_Base_StreamEndPoint - : public virtual TAO_Base_StreamEndPoint -{ -public: virtual CORBA::Boolean handle_connection_requested (AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) = 0; + CORBA::Environment &env = CORBA::Environment::default_environment ()); // Application needs to define this + + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + + virtual int get_control_callback (const char *flowname, + TAO_AV_Callback *&callback); + + virtual int set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object); + + virtual void set_handler (const char *flowname, + TAO_AV_Flow_Handler *handler); }; +// Forward declarations. +class TAO_AV_Acceptor; +class TAO_AV_Connector; +class TAO_Forward_FlowSpec_Entry; +class TAO_Reverse_FlowSpec_Entry; + class TAO_ORBSVCS_Export TAO_StreamEndPoint : public virtual POA_AVStreams::StreamEndPoint, public virtual TAO_Base_StreamEndPoint, @@ -352,7 +544,7 @@ public: // Constructor virtual void stop (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow)); // Stop the stream. Empty the_spec means, for all the flows @@ -372,18 +564,18 @@ public: virtual CORBA::Boolean connect (AVStreams::StreamEndPoint_ptr responder, AVStreams::streamQoS &qos_spec, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::QoSRequestFailed, - AVStreams::streamOpFailed)) = 0; + AVStreams::streamOpFailed)); // Called by StreamCtrl. responder is the peer to connect to virtual CORBA::Boolean request_connection (AVStreams::StreamEndPoint_ptr initiator, CORBA::Boolean is_mcast, AVStreams::streamQoS &qos, AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::streamOpDenied, AVStreams::noSuchFlow, @@ -394,19 +586,19 @@ public: virtual CORBA::Boolean modify_QoS (AVStreams::streamQoS &new_qos, const AVStreams::flowSpec &the_flows, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)); // Change the transport qos on a stream virtual CORBA::Boolean set_protocol_restriction (const AVStreams::protocolSpec &the_pspec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // Used to restrict the set of protocols virtual void disconnect (const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::streamOpFailed)); @@ -415,21 +607,21 @@ public: virtual void set_FPStatus (const AVStreams::flowSpec &the_spec, const char *fp_name, const CORBA::Any &fp_settings, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::noSuchFlow, AVStreams::FPError)); // Used to control the flow virtual CORBA::Object_ptr get_fep (const char *flow_name, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported, AVStreams::noSuchFlow)); // Not implemented in the light profile, throws notsupported virtual char * add_fep (CORBA::Object_ptr the_fep, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported, AVStreams::streamOpFailed)); @@ -443,141 +635,143 @@ public: // Not implemented in the light profile, throws notsupported virtual void set_negotiator (AVStreams::Negotiator_ptr new_negotiator, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // Used to "attach" a negotiator to the endpoint virtual void set_key (const char *flow_name, const AVStreams::key & the_key, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // Used for public key encryption. virtual void set_source_id (CORBA::Long source_id, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // Used to set a unique id for packets sent by this streamendpoint virtual ~TAO_StreamEndPoint (void); // Destructor -private: + CORBA::Boolean multiconnect (AVStreams::streamQoS &the_qos, + AVStreams::flowSpec &the_spec, + CORBA::Environment &ACE_TRY_ENV); +protected: + int translate_qos (const AVStreams::streamQoS& application_qos, + AVStreams::streamQoS& network_qos); + // translate from application level to network level qos. + u_int flow_count_; // Count of the number of flows in this streamendpoint, used to // generate unique names for the flows. + u_int flow_num_; // current flow number used for system generation of flow names. - typedef ACE_Hash_Map_Manager <TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex> - FlowEndPoint_Map; + FlowEndPoint_Map fep_map_; - // hash table for the flownames and its corresponding flowEndpoint - // reference. + // hash table for the flownames and its corresponding flowEndpoint reference. + AVStreams::flowSpec flows_; // sequence of supported flow names. + CORBA::Long source_id_; // source id used for multicast. + + AVStreams::Negotiator_var negotiator_; + // our local negotiator for QoS. + + AVStreams::protocolSpec protocols_; + // Our available list of protocols. + + CORBA::String_var protocol_; + // Chosen protocol for this streamendpoint based on availableprotocols property. + + AVStreams::key key_; + // Key used for encryption. + + u_short mcast_port_; + ACE_UINT32 mcast_addr_; + ACE_Hash_Map_Manager <TAO_String_Hash_Key, TAO_FlowSpec_Entry*,ACE_Null_Mutex> mcast_entry_map_; + TAO_AV_FlowSpecSet forward_flow_spec_set; + TAO_AV_FlowSpecSet reverse_flow_spec_set; + AVStreams::StreamEndPoint_var peer_sep_; + AVStreams::SFPStatus *sfp_status_; + AVStreams::StreamCtrl_var streamctrl_; +// TAO_Forward_FlowSpec_Entry forward_entries_ [FLOWSPEC_MAX]; +// TAO_Reverse_FlowSpec_Entry reverse_entries_ [FLOWSPEC_MAX]; }; -class TAO_ORBSVCS_Export TAO_Client_StreamEndPoint : + +class TAO_ORBSVCS_Export TAO_StreamEndPoint_A : public virtual POA_AVStreams::StreamEndPoint_A, public virtual TAO_StreamEndPoint, - public virtual TAO_Client_Base_StreamEndPoint, public virtual PortableServer::RefCountServantBase { // = DESCRIPTION // The "A" side of a streamendpoint public: - TAO_Client_StreamEndPoint (void); + TAO_StreamEndPoint_A (void); // Constructor - virtual CORBA::Boolean connect (AVStreams::StreamEndPoint_ptr responder, - AVStreams::streamQoS &qos_spec, - const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::streamOpFailed)); - // Called by StreamCtrl. responder is the peer to connect to - virtual CORBA::Boolean multiconnect (AVStreams::streamQoS &the_qos, AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, + AVStreams::noSuchFlow, + AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)); // Used for ATM-style multicast virtual CORBA::Boolean connect_leaf (AVStreams::StreamEndPoint_B_ptr the_ep, AVStreams::streamQoS &the_qos, const AVStreams::flowSpec &the_flows, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, + AVStreams::streamOpFailed, AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, + AVStreams::QoSRequestFailed, AVStreams::notSupported)); // Used for ATM-style multicast virtual void disconnect_leaf (AVStreams::StreamEndPoint_B_ptr the_ep, const AVStreams::flowSpec &theSpec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, + AVStreams::streamOpFailed, AVStreams::noSuchFlow)); // Used to remove a multicast leaf - virtual ~TAO_Client_StreamEndPoint (void); + virtual ~TAO_StreamEndPoint_A (void); // Destructor }; -class TAO_ORBSVCS_Export TAO_Server_StreamEndPoint : +// For backward compatibility. +#define TAO_Client_StreamEndPoint TAO_StreamEndPoint_A +#define TAO_Server_StreamEndPoint TAO_StreamEndPoint_B + +class TAO_ORBSVCS_Export TAO_StreamEndPoint_B : public virtual POA_AVStreams::StreamEndPoint_B, public virtual TAO_StreamEndPoint, - public virtual TAO_Server_Base_StreamEndPoint,// Abstract interface public virtual PortableServer::RefCountServantBase { // = DESCRIPTION // The "B" side of a streamendpoint public: - TAO_Server_StreamEndPoint (void); + TAO_StreamEndPoint_B (void); // Constructor - virtual CORBA::Boolean connect (AVStreams::StreamEndPoint_ptr responder, - AVStreams::streamQoS &qos_spec, - const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::streamOpFailed)); - - virtual CORBA::Boolean request_connection (AVStreams::StreamEndPoint_ptr initiator, - CORBA::Boolean is_mcast, - AVStreams::streamQoS &qos, - AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpDenied, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, - AVStreams::FPError)); - // Called by the peer StreamEndPoint. The flow_spec indicates the - // flows (which contain transport addresses etc.) - virtual CORBA::Boolean multiconnect (AVStreams::streamQoS &the_qos, AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, + AVStreams::streamOpFailed, AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, + AVStreams::QoSRequestFailed, AVStreams::FPError)); // Used for internet-style multicast - virtual ~TAO_Server_StreamEndPoint (void); + virtual ~TAO_StreamEndPoint_B (void); // Destructor }; @@ -585,11 +779,11 @@ class TAO_ORBSVCS_Export TAO_VDev :public virtual TAO_PropertySet, public virtual POA_AVStreams::VDev, public virtual PortableServer::RefCountServantBase -// = DESCRIPTION -// Implements the VDev interface. One of these is created per connection, -// and represents device-specific parameters { - public: + // = DESCRIPTION + // Implements the VDev interface. One of these is created per connection, + // and represents device-specific parameters +public: TAO_VDev (void); // Default Constructor @@ -597,10 +791,10 @@ class TAO_ORBSVCS_Export TAO_VDev AVStreams::VDev_ptr the_peer_dev, AVStreams::streamQoS &the_qos, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, + AVStreams::noSuchFlow, + AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)); // Called to tell the vdev who the streamctrl, peer vdev is @@ -608,47 +802,47 @@ class TAO_ORBSVCS_Export TAO_VDev AVStreams::MCastConfigIf_ptr a_mcastconfigif, AVStreams::streamQoS &the_qos, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, - AVStreams::QoSRequestFailed, + AVStreams::noSuchFlow, + AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)); // Used to set the streamctrl and multicast device virtual void configure (const CosPropertyService::Property &the_config_mesg, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::PropertyException, + AVStreams::PropertyException, AVStreams::streamOpFailed)); // Called by the peer VDev to configure the device (catch all) virtual void set_format (const char *flowName, const char *format_name, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)); // Used to set a format on a flowname virtual void set_dev_params (const char *flowName, const CosPropertyService::Properties &new_params, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::PropertyException, + AVStreams::PropertyException, AVStreams::streamOpFailed)); // Used to set device parameters virtual CORBA::Boolean modify_QoS (AVStreams::streamQoS &the_qos, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::noSuchFlow, + AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)); // Called to change QoS of the device virtual ~TAO_VDev (void); // Destructor - protected: +protected: virtual CORBA::Boolean set_media_ctrl (CORBA::Object_ptr media_ctrl, CORBA::Environment &env = CORBA::Environment::default_environment ()); // hook called after set_peer is done to set the media ctrl of the peer vdev. @@ -658,6 +852,9 @@ class TAO_ORBSVCS_Export TAO_VDev AVStreams::VDev_var peer_; // My peer + + AVStreams::MCastConfigIf_var mcast_peer_; + // The multicast VDev peer. }; class TAO_AV_Endpoint_Strategy; @@ -666,26 +863,36 @@ class TAO_ORBSVCS_Export TAO_MMDevice :public virtual POA_AVStreams::MMDevice, public TAO_PropertySet, public virtual PortableServer::RefCountServantBase -// = DESCRIPTION -// Implements a factory to create Endpoints and VDevs { - protected: - - TAO_AV_Endpoint_Strategy *endpoint_strategy_; + // = DESCRIPTION + // Implements a factory to create Endpoints and VDevs - public: +public: + enum MMDevice_Type {MMDEVICE_A = 0,MMDEVICE_B = 1}; TAO_MMDevice (TAO_AV_Endpoint_Strategy *endpoint_strategy_); // Constructor + TAO_MMDevice (TAO_MMDevice const &); + // Copy constructor to fool g++ + + virtual AVStreams::StreamEndPoint_ptr create_A_B (MMDevice_Type type, + AVStreams::StreamCtrl_ptr the_requester, + AVStreams::VDev_out the_vdev, + AVStreams::streamQoS &the_qos, + CORBA::Boolean_out met_qos, + char *&named_vdev, + const AVStreams::flowSpec &the_spec, + CORBA::Environment &env = CORBA::Environment::default_environment ()); + virtual AVStreams::StreamCtrl_ptr bind (AVStreams::MMDevice_ptr peer_device, AVStreams::streamQoS &the_qos, CORBA::Boolean_out is_met, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::noSuchFlow, + AVStreams::streamOpFailed, + AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)); // Can be used to request the MMDevice to create a new StreamCtrl, // and call bind_devs on it @@ -694,10 +901,10 @@ class TAO_ORBSVCS_Export TAO_MMDevice AVStreams::streamQoS &the_qos, CORBA::Boolean_out is_met, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::noSuchFlow, + AVStreams::streamOpFailed, + AVStreams::noSuchFlow, AVStreams::QoSRequestFailed)); // Multicast bind @@ -707,12 +914,12 @@ class TAO_ORBSVCS_Export TAO_MMDevice CORBA::Boolean_out met_qos, char *&named_vdev, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, AVStreams::notSupported, - AVStreams::QoSRequestFailed, + AVStreams::QoSRequestFailed, AVStreams::noSuchFlow)); // Called by StreamCtrl to create a "A" type streamandpoint and vdev @@ -722,59 +929,69 @@ class TAO_ORBSVCS_Export TAO_MMDevice CORBA::Boolean_out met_qos, char *&named_vdev, const AVStreams::flowSpec &the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, AVStreams::notSupported, - AVStreams::QoSRequestFailed, + AVStreams::QoSRequestFailed, AVStreams::noSuchFlow)); // Called by StreamCtrl to create a "B" type streamandpoint and vdev virtual void destroy (AVStreams::StreamEndPoint_ptr the_ep, const char *vdev_name, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)); // Remove the StreamEndPoint and the related vdev virtual char * add_fdev (CORBA::Object_ptr the_fdev, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported, + AVStreams::notSupported, AVStreams::streamOpFailed)); // Not supported in the light profile, raises notsupported virtual CORBA::Object_ptr get_fdev (const char *flow_name, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported, + AVStreams::notSupported, AVStreams::noSuchFlow)); // Not supported in the light profile, raises notsupported virtual void remove_fdev (const char *flow_name, CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported, + AVStreams::notSupported, AVStreams::noSuchFlow)); // Not supported in the light profile, raises notsupported virtual ~TAO_MMDevice (void); // Destructor - protected: +protected: + + TAO_AV_Endpoint_Strategy *endpoint_strategy_; + u_int flow_count_; // Count of the number of flows in this MMDevice , used to // generate unique names for the flows. + u_int flow_num_; // current flow number used for system generation of flow names. - typedef ACE_Hash_Map_Manager <TAO_String_Hash_Key,CORBA::Object_ptr,ACE_Null_Mutex> - FDev_Map; + + typedef ACE_Hash_Map_Manager <TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex> FDev_Map; + typedef ACE_Hash_Map_Iterator <TAO_String_Hash_Key,AVStreams::FDev_ptr,ACE_Null_Mutex> FDev_Map_Iterator; + typedef ACE_Hash_Map_Entry <TAO_String_Hash_Key,AVStreams::FDev_ptr> FDev_Map_Entry; + FDev_Map fdev_map_; // hash table for the flownames and its corresponding flowEndpoint // reference. + AVStreams::flowSpec flows_; // sequence of supported flow names. + + TAO_StreamCtrl *stream_ctrl_; }; class TAO_FlowConsumer; @@ -795,34 +1012,34 @@ public: TAO_FlowConnection (void); // default constructor. - virtual void stop (CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual void stop (CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // stop this flow. - virtual void start (CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual void start (CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // start this flow. - virtual void destroy (CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual void destroy (CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // destroy this flow. virtual CORBA::Boolean modify_QoS (AVStreams::QoS & new_qos, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::QoSRequestFailed)); // modify the QoS for this flow. virtual CORBA::Boolean use_flow_protocol (const char * fp_name, const CORBA::Any & fp_settings, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::FPError, + AVStreams::FPError, AVStreams::notSupported)); // use the specified flow protocol for this flow. virtual void push_event (const AVStreams::streamEvent & the_event, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // pushes an event , to be handled by the application. @@ -830,35 +1047,35 @@ public: virtual CORBA::Boolean connect_devs (AVStreams::FDev_ptr a_party, AVStreams::FDev_ptr b_party, AVStreams::QoS & the_qos, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, AVStreams::QoSRequestFailed)); // connect 2 Flow Devices. - + virtual CORBA::Boolean connect (AVStreams::FlowProducer_ptr flow_producer, AVStreams::FlowConsumer_ptr flow_consumer, AVStreams::QoS & the_qos, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::formatMismatch, - AVStreams::FEPMismatch, + AVStreams::formatMismatch, + AVStreams::FEPMismatch, AVStreams::alreadyConnected)); // Connect a flow producer and consumer under this flow connection. - virtual CORBA::Boolean disconnect (CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual CORBA::Boolean disconnect (CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // disconnect this flow connection. virtual CORBA::Boolean add_producer (AVStreams::FlowProducer_ptr flow_producer, AVStreams::QoS & the_qos, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::alreadyConnected, AVStreams::notSupported)); // adds the producer to this flow connection. - + virtual CORBA::Boolean add_consumer (AVStreams::FlowConsumer_ptr flow_consumer, AVStreams::QoS & the_qos, CORBA::Environment &env = CORBA::Environment::default_environment ()) @@ -867,85 +1084,108 @@ public: // adds a consumer to this flow connection. virtual CORBA::Boolean drop (AVStreams::FlowEndPoint_ptr target, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notConnected)); // drops a flow endpoint from the flow. + int set_mcast_addr (ACE_UINT32 addr,u_short port); + void set_protocol (const char *protocol); protected: - AVStreams::FlowProducer *producer_; - // The producer of this flow. - AVStreams::FlowConsumer *consumer_; - // The consumer of this flow - char * fp_name_; - // name of the flow protocol to be used. + typedef ACE_Unbounded_Set<AVStreams::FlowProducer_ptr> FlowProducer_Set; + typedef ACE_Unbounded_Set_Iterator<AVStreams::FlowProducer_ptr> FlowProducer_SetItor; + typedef ACE_Unbounded_Set<AVStreams::FlowConsumer_ptr> FlowConsumer_Set; + typedef ACE_Unbounded_Set_Iterator<AVStreams::FlowConsumer_ptr> FlowConsumer_SetItor; + + FlowProducer_Set flow_producer_set_; + FlowConsumer_Set flow_consumer_set_; + CORBA::String_var fp_name_; + CORBA::Any fp_settings_; + CORBA::String_var producer_address_; + // The multicast address returned by the producer. + + int ip_multicast_; + // IP Multicasting is used. + TAO_MCastConfigIf *mcastconfigif_i_; + AVStreams::MCastConfigIf_var mcastconfigif_; + u_short mcast_port_; + ACE_UINT32 mcast_addr_; + CORBA::String_var protocol_; }; class TAO_ORBSVCS_Export TAO_FlowEndPoint : public virtual POA_AVStreams::FlowEndPoint, public virtual TAO_PropertySet, - public virtual PortableServer::RefCountServantBase + public virtual PortableServer::RefCountServantBase, + public virtual TAO_Base_StreamEndPoint { // = DESCRIPTION // This class is used per flow e.g video flow and an audio flow - // to encapuslate the transport details. + // to encapuslate the transport details. - public: +public: TAO_FlowEndPoint (void); //default constructor. + TAO_FlowEndPoint (const char *flowname, + AVStreams::protocolSpec &protocols, + const char *format); + + int open (const char *flowname, + AVStreams::protocolSpec &protocols, + const char *format); + + int set_flowname (const char *flowname); + + virtual void set_handler (const char *flowname, + TAO_AV_Flow_Handler *handler); + + virtual int set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object); + virtual CORBA::Boolean lock (CORBA::Environment &env = - CORBA::Environment::default_environment ()) + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // lock the flow endpoint for a particular flow. virtual void unlock (CORBA::Environment &env = - CORBA::Environment::default_environment ()) + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // unlock the flow endpoint for subsequent use. - virtual void stop (CORBA::Environment &env = - CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException)); - // stop this flow, to be overridden by the application. - - virtual void start (CORBA::Environment &env = - CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException)); - // start this flow, to be overridden by the application. virtual void destroy (CORBA::Environment &env = - CORBA::Environment::default_environment ()) + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // destroy this flow. - virtual AVStreams::StreamEndPoint_ptr related_sep(CORBA::Environment &env = - CORBA::Environment::default_environment ()) + virtual AVStreams::StreamEndPoint_ptr related_sep(CORBA::Environment &env = + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // get method for the related streamendpoint under which this // flowendpoint is. virtual void related_sep (AVStreams::StreamEndPoint_ptr related_sep, - CORBA::Environment &env = - CORBA::Environment::default_environment ()) + CORBA::Environment &env = + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // set method for the related streamendpoint under which this // flowendpoint is. - virtual AVStreams::FlowConnection_ptr related_flow_connection(CORBA::Environment &env = - CORBA::Environment::default_environment ()) + virtual AVStreams::FlowConnection_ptr related_flow_connection(CORBA::Environment &env = + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // accessor for the related flow connection attribute. virtual void related_flow_connection (AVStreams::FlowConnection_ptr related_flow_connection, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // set method for the related flow connection attribute. - virtual AVStreams::FlowEndPoint_ptr get_connected_fep (CORBA::Environment &env = - CORBA::Environment::default_environment ()) + virtual AVStreams::FlowEndPoint_ptr get_connected_fep (CORBA::Environment &env = + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notConnected, AVStreams::notSupported)); @@ -953,42 +1193,42 @@ class TAO_ORBSVCS_Export TAO_FlowEndPoint : virtual CORBA::Boolean use_flow_protocol (const char * fp_name, const CORBA::Any & fp_settings, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::FPError, + AVStreams::FPError, AVStreams::notSupported)); /// use the specified flow protocol. virtual void set_format (const char * format, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)); // sets the data format. virtual void set_dev_params (const CosPropertyService::Properties & new_settings, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::PropertyException, + AVStreams::PropertyException, AVStreams::streamOpFailed)); // sets the device parameters. virtual void set_protocol_restriction (const AVStreams::protocolSpec & the_spec, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::notSupported)); // sets the list of protocols to be used. virtual CORBA::Boolean is_fep_compatible (AVStreams::FlowEndPoint_ptr fep, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::formatMismatch, + AVStreams::formatMismatch, AVStreams::deviceQosMismatch)); // checks whether the passed flowendpoint is compatible with this. virtual CORBA::Boolean set_peer (AVStreams::FlowConnection_ptr the_fc, AVStreams::FlowEndPoint_ptr the_peer_fep, AVStreams::QoS & the_qos, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::QoSRequestFailed, AVStreams::streamOpFailed)); @@ -998,7 +1238,7 @@ class TAO_ORBSVCS_Export TAO_FlowEndPoint : AVStreams::MCastConfigIf_ptr a_mcastconfigif, AVStreams::QoS & the_qos, CORBA::Environment &env = - CORBA::Environment::default_environment ()) + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::QoSRequestFailed)); // sets the multicast peer flowendpoint, not implemented. @@ -1008,47 +1248,82 @@ class TAO_ORBSVCS_Export TAO_FlowEndPoint : const char * address, const char * use_flow_protocol, CORBA::Environment &env = - CORBA::Environment::default_environment ()) + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::failedToConnect, - AVStreams::FPError, + AVStreams::FPError, + AVStreams::QoSRequestFailed)) = 0; + // This should be implemented in both the FlowProducer and consumer and hence is + // pure virtual since we need to know the role of the flowendpoint to create appropriate + // protocol objects. eg. in SFP to create Producer Object/ Consumer Object. + + virtual CORBA::Boolean connect_to_peer_i (TAO_FlowSpec_Entry::Role role, + AVStreams::QoS & the_qos, + const char * address, + const char * use_flow_protocol, + CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::failedToConnect, + AVStreams::FPError, AVStreams::QoSRequestFailed)); // connect to the peer endpoint. - virtual CORBA::Boolean handle_connect_to_peer (AVStreams::QoS & the_qos, - const char * address, - const char * use_flow_protocol, - CORBA::Environment &env = - CORBA::Environment::default_environment ()); - // hook method to be overridden by the application to handle the connection request. - virtual char * go_to_listen (AVStreams::QoS & the_qos, CORBA::Boolean is_mcast, - AVStreams::FlowProducer_ptr peer, + AVStreams::FlowEndPoint_ptr peer, char *& flowProtocol, CORBA::Environment &env = - CORBA::Environment::default_environment ()) + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::failedToListen, - AVStreams::FPError, + AVStreams::failedToListen, + AVStreams::FPError, + AVStreams::QoSRequestFailed)) = 0; + // This should be implemented in both the FlowProducer and consumer and hence is + // pure virtual since we need to know the role of the flowendpoint to create appropriate + // protocol objects. eg. in SFP to create Producer Object/ Consumer Object. + + virtual char * go_to_listen_i (TAO_FlowSpec_Entry::Role role, + AVStreams::QoS & the_qos, + CORBA::Boolean is_mcast, + AVStreams::FlowEndPoint_ptr peer, + char *& flowProtocol, + CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::failedToListen, + AVStreams::FPError, AVStreams::QoSRequestFailed)); // listen request from the peer. - virtual char * handle_go_to_listen (AVStreams::QoS & the_qos, - CORBA::Boolean is_mcast, - AVStreams::FlowProducer_ptr peer, - char *& flowProtocol, - CORBA::Environment &env = CORBA::Environment::default_environment ()); - // applications should override this method. - protected: - AVStreams::StreamEndPoint_ptr related_sep_; + AVStreams::StreamEndPoint_var related_sep_; // The related streamendpoint. - AVStreams::FlowConnection_ptr related_flow_connection_; + + AVStreams::FlowConnection_var related_flow_connection_; // The related flow connection reference - AVStreams::FlowEndPoint_ptr peer_fep_; + + AVStreams::FlowEndPoint_var peer_fep_; // The peer flowendpoint reference. + + AVStreams::protocolSpec protocols_; + // Available protocols for this flowendpoint. + + AVStreams::protocolSpec protocol_addresses_; + // Address information for the protocols. + + AVStreams::MCastConfigIf_var mcast_peer_; + // The multicast peer endpoint. + + CORBA::Boolean lock_; + // Lock. + + CORBA::String_var format_; + CORBA::String_var flowname_; + CosPropertyService::Properties dev_params_; + TAO_AV_FlowSpecSet flow_spec_set_; + CORBA::String_var reverse_channel_; }; class TAO_ORBSVCS_Export TAO_FlowProducer: @@ -1056,15 +1331,59 @@ class TAO_ORBSVCS_Export TAO_FlowProducer: public virtual TAO_FlowEndPoint, public virtual PortableServer::RefCountServantBase { - public: +public: TAO_FlowProducer (void); // default constructor + TAO_FlowProducer (const char *flowname, + AVStreams::protocolSpec protocols, + const char *format); + + virtual char * get_rev_channel (const char * pcol_name, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException)); + // get the reverse channel, to be used for feedback for protocols like UDP. + // @@Naga: In the spec this is defined in the TAO_FlowProducer but it seems more reasonable for this + // to be in a FlowEndPoint since any of the flowendpoints can be made to listen. So in the case of + // UDP if the producer is listening and the consumer connects (logically) then the producer needs to + // know the reverse channel on its peer fep to send data to. + + virtual void stop (CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException)); + // stop this flow, to be overridden by the application. + + virtual void start (CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException)); + // start this flow, to be overridden by the application. + + virtual char * go_to_listen (AVStreams::QoS & the_qos, + CORBA::Boolean is_mcast, + AVStreams::FlowEndPoint_ptr peer, + char *& flowProtocol, + CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::failedToListen, + AVStreams::FPError, + AVStreams::QoSRequestFailed)); + + virtual CORBA::Boolean connect_to_peer (AVStreams::QoS & the_qos, + const char * address, + const char * use_flow_protocol, + CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::failedToConnect, + AVStreams::FPError, + AVStreams::QoSRequestFailed)); + virtual char * connect_mcast (AVStreams::QoS & the_qos, CORBA::Boolean_out is_met, const char * address, const char * use_flow_protocol, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::failedToConnect, AVStreams::notSupported, @@ -1073,18 +1392,14 @@ class TAO_ORBSVCS_Export TAO_FlowProducer: // connect to the multicast address, not implemented. - virtual char * get_rev_channel (const char * pcol_name, - CORBA::Environment &env = CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException)); - // get the reverse channel, to be used for feedback for protocols like UDP. virtual void set_key (const AVStreams::key & the_key, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)); // sets the public key to be used for encryption of the data. virtual void set_source_id (CORBA::Long source_id, - CORBA::Environment &env =CORBA::Environment::default_environment()) + CORBA::Environment &env =CORBA::Environment::default_environment()) ACE_THROW_SPEC ((CORBA::SystemException)); // sets the source id of this flow producer so that it can be used // to distinguish this producer from others in the multicast case. @@ -1092,6 +1407,7 @@ class TAO_ORBSVCS_Export TAO_FlowProducer: protected: CORBA::Long source_id_; // source id of this producer. + CORBA::String_var peer_address_; }; class TAO_ORBSVCS_Export TAO_FlowConsumer : @@ -1099,94 +1415,47 @@ class TAO_ORBSVCS_Export TAO_FlowConsumer : public virtual TAO_FlowEndPoint, public virtual PortableServer::RefCountServantBase { - public: +public: TAO_FlowConsumer (void); // default constructor. + TAO_FlowConsumer (const char *flowname, + AVStreams::protocolSpec protocols, + const char *format); -}; - -class TAO_ORBSVCS_Export TAO_FDev : - public virtual POA_AVStreams::FDev, - public virtual TAO_PropertySet, - public virtual PortableServer::RefCountServantBase -{ - public: - TAO_FDev (void); - // default constructor - - AVStreams::FlowProducer_ptr create_producer (AVStreams::FlowConnection_ptr the_requester, - AVStreams::QoS & the_qos, - CORBA::Boolean_out met_qos, - char *& named_fdev, - CORBA::Environment &env = CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, - AVStreams::notSupported, - AVStreams::QoSRequestFailed)); - // create a flow producer object. - - virtual AVStreams::FlowProducer_ptr make_producer (AVStreams::FlowConnection_ptr the_requester, - AVStreams::QoS & the_qos, - CORBA::Boolean_out met_qos, - char *& named_fdev, - CORBA::Environment &env = CORBA::Environment::default_environment ()); - // bridge method for the application to override the producer object - // creation. Default implementation creates a TAO_FlowProducer. - - virtual AVStreams::FlowConsumer_ptr create_consumer (AVStreams::FlowConnection_ptr the_requester, - AVStreams::QoS & the_qos, - CORBA::Boolean_out met_qos, - char *& named_fdev, - CORBA::Environment &env = CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, - AVStreams::streamOpDenied, - AVStreams::notSupported, - AVStreams::QoSRequestFailed)); - // create a flow consumer object. + virtual void stop (CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException)); + // stop this flow, to be overridden by the application. - virtual AVStreams::FlowConsumer_ptr make_consumer (AVStreams::FlowConnection_ptr the_requester, - AVStreams::QoS & the_qos, - CORBA::Boolean_out met_qos, - char *& named_fdev, - CORBA::Environment &env = CORBA::Environment::default_environment ()); - // bridge method for the application to override the consumer object - // creation. Default implementation creates a TAO_FlowConsumer. + virtual void start (CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException)); + // start this flow, to be overridden by the application. - virtual AVStreams::FlowConnection_ptr bind (AVStreams::FDev_ptr peer_device, - AVStreams::QoS & the_qos, - CORBA::Boolean_out is_met, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual char * go_to_listen (AVStreams::QoS & the_qos, + CORBA::Boolean is_mcast, + AVStreams::FlowEndPoint_ptr peer, + char *& flowProtocol, + CORBA::Environment &env = + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, + AVStreams::failedToListen, + AVStreams::FPError, AVStreams::QoSRequestFailed)); - // bind this FDev with another FDev. - virtual AVStreams::FlowConnection_ptr bind_mcast (AVStreams::FDev_ptr first_peer, - AVStreams::QoS & the_qos, - CORBA::Boolean_out is_met, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + virtual CORBA::Boolean connect_to_peer (AVStreams::QoS & the_qos, + const char * address, + const char * use_flow_protocol, + CORBA::Environment &env = + CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::streamOpFailed, + AVStreams::failedToConnect, + AVStreams::FPError, AVStreams::QoSRequestFailed)); - // multicast bind is not implemented yet. - - virtual void destroy (AVStreams::FlowEndPoint_ptr the_ep, - const char * fdev_name, - CORBA::Environment &env = - CORBA::Environment::default_environment ()) - ACE_THROW_SPEC ((CORBA::SystemException, - AVStreams::notSupported)); - // destroys this FDev. - -protected: - AVStreams::FlowProducer_ptr producer_; - AVStreams::FlowConsumer_ptr consumer_; - // references to the created producers and consumers. }; + class TAO_ORBSVCS_Export TAO_MediaControl :public virtual POA_AVStreams::MediaControl, public virtual PortableServer::RefCountServantBase @@ -1197,13 +1466,13 @@ class TAO_ORBSVCS_Export TAO_MediaControl // = DESCRIPTION // The following are to be handled by the specialized media control for the specific // media like camera,speaker. - public: +public: TAO_MediaControl (void); // default constructor virtual AVStreams::Position get_media_position (AVStreams::PositionOrigin an_origin, AVStreams::PositionKey a_key, - CORBA::Environment &env = CORBA::Environment::default_environment ()) + CORBA::Environment &env = CORBA::Environment::default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException, AVStreams::MediaControl::PostionKeyNotSupported)) =0; @@ -1235,127 +1504,38 @@ class TAO_ORBSVCS_Export TAO_MediaControl }; -class TAO_ORBSVCS_Export TAO_Tokenizer +class TAO_ORBSVCS_Export TAO_AV_QoS { public: - TAO_Tokenizer (char *string,char delimiter); + TAO_AV_QoS (void); // constructor. - int parse (char *string,char delimiter); - // parses the string and tokenizes it. + TAO_AV_QoS (AVStreams::streamQoS &stream_qos); + // constructor taking a stream qos parameter. - char *token (void); - // Returns the next token. - - int num_tokens (void); - // Number of tokens. - - char *operator [] (size_t index) const; - -protected: - ACE_Array<char*> token_array_; - size_t count_; - size_t num_tokens_; -}; + int set (AVStreams::streamQoS &stream_qos); + // sets the maps with the QoS paramter. -class TAO_ORBSVCS_Export TAO_FlowSpec_Entry -{ -public: - // = TITLE - // An helper entry class in the flow spec sequence passed to bind_devs. - enum Direction - { - TAO_AV_INVALID = -1, - TAO_AV_DIR_IN = 0, - TAO_AV_DIR_OUT = 1, - TAO_AV_DIR_INOUT = 2}; + int get_flow_qos (const char *flowname,AVStreams::QoS &flow_qos); + // gets the flow_qos. - TAO_FlowSpec_Entry (void); - // constructor. + int convert (AVStreams::streamQoS &network_qos); + // converts the application level QoS to Network-level QoS. - virtual int parse (char* flowSpec_entry) = 0; - // construct the entry from a string specified by the flowSpec grammar. - - virtual ~TAO_FlowSpec_Entry (void); - // virtual destructor. - - virtual int direction (void); - - virtual TAO_SFP* flow_protocol (void); - // Accessor to the flow protocol. - - virtual ACE_Addr *carrier_protocol (void); - // carrier protocol. - - virtual char *format (void); - // format to be used for this flow. protected: - int parse_flow_protocol_string (char *flow_options_string); - // parses the flow protocol string with tokens separated by : - - int set_direction (char *direction_string); - // sets the direction flag. - - int parse_address (char *format_string); - // sets the address for this flow. - - TAO_SFP *sfp_; - // reference to the flowprotocol implementation. - - ACE_Addr *address_; - // Addr information for the carrier protocol. - - char *format_; - // format string. - - Direction direction_; - // Direction of this flow. - - char *flowname_; - // name of this flow. - - char *protocol_; - // name of the protocol used. -}; + AVStreams::streamQoS stream_qos_; + // Stream Qos. -class TAO_ORBSVCS_Export TAO_Forward_FlowSpec_Entry - :public TAO_FlowSpec_Entry -{ -public: - enum Position {TAO_AV_FLOWNAME = 0, - TAO_AV_DIRECTION = 1, - TAO_AV_FORMAT = 2, - TAO_AV_FLOW_PROTOCOL = 3, - TAO_AV_ADDRESS = 4}; - - virtual int parse (char* flowSpec_entry); - // construct the entry from a string specified by the flowSpec grammar. + ACE_Hash_Map_Manager<TAO_String_Hash_Key,AVStreams::QoS,ACE_Null_Mutex> qos_map_; }; -class TAO_ORBSVCS_Export TAO_Reverse_FlowSpec_Entry - :public TAO_FlowSpec_Entry -{ -public: - enum Position {TAO_AV_FLOWNAME = 0, - TAO_AV_ADDRESS = 1, - TAO_AV_FLOW_PROTOCOL = 2, - TAO_AV_DIRECTION = 3, - TAO_AV_FORMAT = 4}; - - virtual int parse (char* flowSpec_entry); - // construct the entry from a string specified by the flowSpec grammar. -}; - -// class TAO_ORBSVCS_Export TAO_AV_QoS -// { -// public: -// TAO_AV_QoS (void) ACE_THROW_SPEC ((CORBA::SystemException)); -// // constructor. - -// int convert (const AVStreams::streamQoS &application_qos, -// AVStreams::streamQoS &network_qos) ACE_THROW_SPEC ((CORBA::SystemException)); -// // converts the application level QoS to Network-level QoS. -// }; +#include "Transport.h" + +#if defined (__ACE_INLINE__) +#include "AVStreams_i.i" +#endif /* __ACE_INLINE__ */ + +#include "Flows_T.h" #endif /* AVSTREAMS_I_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.i b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.i new file mode 100644 index 00000000000..6476b9736ee --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/AVStreams_i.i @@ -0,0 +1,31 @@ +/* -*- C++ -*- */ +// $Id$ + +// AVStreams_i.i + +ACE_INLINE +int +TAO_AV_QoS::set (AVStreams::streamQoS &stream_qos) +{ + this->stream_qos_ = stream_qos; + + for (u_int j=0;j<this->stream_qos_.length ();j++) + { + TAO_String_Hash_Key qos_key (CORBA::string_dup (this->stream_qos_[j].QoSType)); + int result = this->qos_map_.bind (qos_key,this->stream_qos_[j]); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"qos_map::bind failed\n"),-1); + } + return 0; +} + + +ACE_INLINE +int +TAO_AV_QoS::get_flow_qos (const char *flowname,AVStreams::QoS &flow_qos) +{ + int result = this->qos_map_.find (flowname, flow_qos); + if (result < 0) + ACE_ERROR_RETURN ((LM_DEBUG,"qos_map::find failed\n"),-1); + return 0; +} diff --git a/TAO/orbsvcs/orbsvcs/AV/AV_Core.h b/TAO/orbsvcs/orbsvcs/AV/AV_Core.h new file mode 100644 index 00000000000..f98863df02a --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/AV_Core.h @@ -0,0 +1,185 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS (AVStreams) +// +// = FILENAME +// AV_Core.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_CORE_H +#define TAO_AV_CORE_H + +#include "tao/TAO.h" +#include "orbsvcs/AVStreamsC.h" + +class TAO_Base_StreamEndPoint; +class TAO_AV_Connector_Registry; +class TAO_AV_Acceptor_Registry; +class TAO_AV_Acceptor; +class TAO_AV_Connector; +class TAO_FlowSpec_Entry; + +//forward declaration. +class TAO_AV_Transport_Factory; + +class TAO_Export TAO_AV_Transport_Item +{ +public: + TAO_AV_Transport_Item (const ACE_CString &name); + // creator method, the Transport name can only be set when the + // object is created. + + const ACE_CString &name (void); + // return a reference to the character representation of the Transport + // factories name. + + TAO_AV_Transport_Factory *factory (void); + // return a pointer to the Transport factory. + + void factory (TAO_AV_Transport_Factory *factory); + // set the factory pointer's valus. + +private: + ACE_CString name_; + // Transport factory name. + + TAO_AV_Transport_Factory *factory_; + // pointer to factory object. +}; + +class TAO_AV_Flow_Protocol_Factory; + +class TAO_Export TAO_AV_Flow_Protocol_Item +{ +public: + TAO_AV_Flow_Protocol_Item (const ACE_CString &name); + // creator method, the Flow_Protocol name can only be set when the + // object is created. + + const ACE_CString &name (void); + // return a reference to the character representation of the Flow_Protocol + // factories name. + + TAO_AV_Flow_Protocol_Factory *factory (void); + // return a pointer to the Flow_Protocol factory. + + void factory (TAO_AV_Flow_Protocol_Factory *factory); + // set the factory pointer's valus. + +private: + ACE_CString name_; + // Flow_Protocol factory name. + + TAO_AV_Flow_Protocol_Factory *factory_; + // pointer to factory object. +}; + +// typedefs for containers containing the list of loaded Flow_Protocol +// factories. +typedef ACE_Unbounded_Set<TAO_AV_Flow_Protocol_Item*> + TAO_AV_Flow_ProtocolFactorySet; + +typedef ACE_Unbounded_Set_Iterator<TAO_AV_Flow_Protocol_Item*> + TAO_AV_Flow_ProtocolFactorySetItor; + +typedef ACE_Unbounded_Set<TAO_AV_Transport_Item*> + TAO_AV_TransportFactorySet; + +typedef ACE_Unbounded_Set_Iterator<TAO_AV_Transport_Item*> + TAO_AV_TransportFactorySetItor; + +typedef ACE_Unbounded_Set <TAO_FlowSpec_Entry*> TAO_AV_FlowSpecSet; +typedef ACE_Unbounded_Set_Iterator <TAO_FlowSpec_Entry*> TAO_AV_FlowSpecSetItor; + +class TAO_ORBSVCS_Export TAO_AV_Core +{ +public: + enum EndPoint {TAO_AV_ENDPOINT_A,TAO_AV_ENDPOINT_B}; + + enum Protocol + { + TAO_AV_NOPROTOCOL = -1, + TAO_AV_TCP = 0, + TAO_AV_UDP = 1, + TAO_AV_AAL5 = 2, + TAO_AV_AAL3_4 = 3, + TAO_AV_AAL1 = 4, + TAO_AV_RTP_UDP = 5, + TAO_AV_RTP_AAL5 = 6, + TAO_AV_IPX = 7, + TAO_AV_SFP_UDP = 8, + TAO_AV_UDP_MCAST = 9, + TAO_AV_RTP_UDP_MCAST = 10, + TAO_AV_SFP_UDP_MCAST = 11 + }; + + TAO_AV_Core (void); + // Default constructor. + + ~TAO_AV_Core (void); + // Destructor. + + int init (int &argc, + char *argv [], + CORBA::Environment &env); + int run (void); + int stop_run (void); + int init_forward_flows (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_FlowSpecSet &flow_spec_set, + EndPoint direction, + AVStreams::flowSpec &flow_spec); + int init_reverse_flows (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_FlowSpecSet &forward_flow_spec_set, + TAO_AV_FlowSpecSet &reverse_flow_spec_set, + EndPoint direction); + int init_transport_factories (void); + int init_flow_protocol_factories (void); + + TAO_AV_Acceptor *get_acceptor (const char *flowname); + TAO_AV_Connector *get_connector (const char *flowname); + TAO_AV_Connector_Registry *connector_registry (void); + TAO_FlowSpec_Entry *get_flow_spec_entry (TAO_AV_FlowSpecSet &flow_spec_set, + const char *flowname); + // = Get the acceptor registry + TAO_AV_Acceptor_Registry *acceptor_registry (void); + + // = Get the protocol factories + TAO_AV_Flow_ProtocolFactorySet *flow_protocol_factories (void); + TAO_AV_TransportFactorySet *transport_factories (void); + // = Set/get the <ACE_Reactor>. + void reactor (ACE_Reactor *r); + ACE_Reactor *reactor (void); + TAO_ORB_Manager *orb_manager (void); + +protected: + TAO_AV_Connector_Registry *connector_registry_; + // The connector registry which all active connecters must register + // themselves with. + + TAO_AV_Acceptor_Registry *acceptor_registry_; + // The registry which maintains a list of acceptor factories for each + // loaded protocol. + + TAO_AV_TransportFactorySet transport_factories_; + // Pointer to the list of transports loaded into this AV_Core instance. + + TAO_AV_Flow_ProtocolFactorySet flow_protocol_factories_; + // Pointer to the list of flow protocol loaded into this AV_Core instance. + + ACE_Reactor *reactor_; + CORBA::ORB_var orb_; + TAO_ORB_Manager orb_manager_; + CORBA::Boolean stop_run_; +}; + +#endif /* TAO_AV_CORE_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.cpp b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.cpp index aff8c054509..ba0e5fd9521 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.cpp @@ -10,7 +10,7 @@ // // = AUTHOR // Sumedh Mungee <sumedh@cs.wustl.edu> -// +// // // ============================================================================ @@ -91,7 +91,7 @@ TAO_AV_Endpoint_Process_Strategy::~TAO_AV_Endpoint_Process_Strategy (void) // Spawns the process, and waits for it to finish booting. // Then uses bind_to_naming_service, get_stream_endpoint, and get_vdev // to get the object references to the various objects created in the -// child +// child int TAO_AV_Endpoint_Process_Strategy::activate (void) { @@ -109,7 +109,7 @@ TAO_AV_Endpoint_Process_Strategy::activate (void) // Create a unique semaphore name, using my hostname, and pid. char sem_str [BUFSIZ]; - + // create a unique semaphore name ACE_OS::sprintf (sem_str, "%s:%s:%ld", @@ -124,7 +124,7 @@ TAO_AV_Endpoint_Process_Strategy::activate (void) ACE_Process_Semaphore semaphore (0, // 0 means that the // semaphore is locked initially sem_str); - + // wait until the child finishes booting while (1) { @@ -150,7 +150,7 @@ TAO_AV_Endpoint_Process_Strategy::activate (void) "(%P|%t) semaphore remove failed: %p\n", "remove"), -1); - + ACE_DECLARE_NEW_CORBA_ENV; ACE_TRY { @@ -170,7 +170,7 @@ TAO_AV_Endpoint_Process_Strategy::activate (void) { ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_AV_Endpoint_Process_Strategy::activate"); return -1; - } + } ACE_ENDTRY; ACE_CHECK_RETURN (-1); return 0; @@ -220,7 +220,7 @@ TAO_AV_Endpoint_Process_Strategy::get_vdev (CORBA::Environment &ACE_TRY_ENV) this->host_, this->pid_); - ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",vdev_name)); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",vdev_name)); // Create the name CosNaming::Name VDev_Name (1); @@ -278,15 +278,15 @@ TAO_AV_Endpoint_Process_Strategy_A::create_A (AVStreams::StreamEndPoint_A_ptr &s { // use the baseclass activate if (this->activate () == -1) - ACE_ERROR_RETURN ((LM_ERROR, + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) TAO_AV_Endpoint_Process_Strategy: Error in activate ()\n"), -1); - + // return the object references stream_endpoint = this->stream_endpoint_a_; vdev = this->vdev_; return 0; - + } // Gets the stream endpoint object reference from the naming service @@ -302,11 +302,11 @@ TAO_AV_Endpoint_Process_Strategy_A::get_stream_endpoint (CORBA::Environment &ACE this->host_, this->pid_); - ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); // Create the name CosNaming::Name Stream_Endpoint_A_Name (1); - + Stream_Endpoint_A_Name.length (1); Stream_Endpoint_A_Name [0].id = CORBA::string_dup (stream_endpoint_name); @@ -315,13 +315,13 @@ TAO_AV_Endpoint_Process_Strategy_A::get_stream_endpoint (CORBA::Environment &ACE this->naming_context_->resolve (Stream_Endpoint_A_Name, ACE_TRY_ENV); ACE_TRY_CHECK; - + // Narrow the reference this->stream_endpoint_a_ = AVStreams::StreamEndPoint_A::_narrow (stream_endpoint_a.in (), ACE_TRY_ENV); ACE_TRY_CHECK; - + // Check for validity if (CORBA::is_nil (this->stream_endpoint_a_)) ACE_ERROR_RETURN ((LM_ERROR, @@ -362,11 +362,11 @@ TAO_AV_Endpoint_Process_Strategy_B::create_B (AVStreams::StreamEndPoint_B_ptr &s ACE_TRY { if (this->activate () == -1) - ACE_ERROR_RETURN ((LM_ERROR, + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) TAO_AV_Endpoint_Process_Strategy: Error in activate ()\n"), -1); - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Process_Strategy_B::create_B ()\n: stream_endpoint is:%s\n", + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Process_Strategy_B::create_B ()\n: stream_endpoint is:%s\n", TAO_ORB_Core_instance ()->orb ()->object_to_string (this->stream_endpoint_b_, ACE_TRY_ENV))); ACE_TRY_CHECK; @@ -396,14 +396,14 @@ TAO_AV_Endpoint_Process_Strategy_B::get_stream_endpoint (CORBA::Environment &ACE this->host_, this->pid_); - ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); // Create the name CosNaming::Name Stream_Endpoint_B_Name (1); - + Stream_Endpoint_B_Name.length (1); Stream_Endpoint_B_Name [0].id = CORBA::string_dup (stream_endpoint_name); - + // Get the CORBA::Object reference CORBA::Object_var stream_endpoint_b = this->naming_context_->resolve (Stream_Endpoint_B_Name, diff --git a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.h b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.h index 4f014c5c53d..74ed5fbe2fb 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.h +++ b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy.h @@ -5,7 +5,7 @@ // ============================================================================ // // = LIBRARY -// cos +// ORBSVCS AVStreams // // = FILENAME // Endpoint_Strategy.h @@ -29,10 +29,11 @@ #endif /* _MSC_VER */ class TAO_ORBSVCS_Export TAO_AV_Endpoint_Strategy -// = DESCRIPTION -// Base class to define various endpoint strategies -// used by the MMDevice to create the Endpoint and Vdev { + // = DESCRIPTION + // Base class to define various endpoint strategies + // used by the MMDevice to create the Endpoint and Vdev + public: TAO_AV_Endpoint_Strategy (void); // Constructor @@ -50,7 +51,7 @@ public: CORBA::Environment &env); // Called by the MMDevice, when it needs to create an B type endpoint - protected: +protected: AVStreams::StreamEndPoint_A_ptr stream_endpoint_a_; // The "A" stream endpoint @@ -66,11 +67,12 @@ public: class TAO_ORBSVCS_Export TAO_AV_Endpoint_Process_Strategy : public TAO_AV_Endpoint_Strategy -// = DESCRIPTION -// Process-based strategy for creating endpoints -// Abstract base class. { - public: + // = DESCRIPTION + // Process-based strategy for creating endpoints + // Abstract base class. + +public: TAO_AV_Endpoint_Process_Strategy (ACE_Process_Options *process_options); // Constructor. The process_options contain the name and arguments // for the process to be created @@ -82,7 +84,7 @@ class TAO_ORBSVCS_Export TAO_AV_Endpoint_Process_Strategy // creates a new child process, and waits on a semaphore // until the child process has finished creating the endpoints - protected: +protected: virtual int bind_to_naming_service (CORBA::Environment &env); // Bind to the naming service @@ -113,17 +115,18 @@ class TAO_ORBSVCS_Export TAO_AV_Endpoint_Process_Strategy class TAO_ORBSVCS_Export TAO_AV_Endpoint_Process_Strategy_A : public TAO_AV_Endpoint_Process_Strategy -// = DESCRIPTION -// Process-based strategy to create "A" type endpoints { - public: + // = DESCRIPTION + // Process-based strategy to create "A" type endpoints + +public: TAO_AV_Endpoint_Process_Strategy_A (ACE_Process_Options *process_options); // Constructor virtual ~TAO_AV_Endpoint_Process_Strategy_A (void); // Destructor. - protected: +protected: virtual int create_A (AVStreams::StreamEndPoint_A_ptr &stream_endpoint, AVStreams::VDev_ptr &vdev, CORBA::Environment &env); @@ -138,17 +141,17 @@ class TAO_ORBSVCS_Export TAO_AV_Endpoint_Process_Strategy_A class TAO_ORBSVCS_Export TAO_AV_Endpoint_Process_Strategy_B : public TAO_AV_Endpoint_Process_Strategy -// = DESCRIPTION -// Process-based strategy to create "B" type endpoints { - public: + // = DESCRIPTION + // Process-based strategy to create "B" type endpoints +public: TAO_AV_Endpoint_Process_Strategy_B (ACE_Process_Options *process_options); // Constructor virtual ~TAO_AV_Endpoint_Process_Strategy_B (void); // Destructor. - protected: +protected: virtual int create_B (AVStreams::StreamEndPoint_B_ptr &stream_endpoint, AVStreams::VDev_ptr &vdev, CORBA::Environment &env); diff --git a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp index c3bb4ff2714..010ca8ca740 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp @@ -31,15 +31,15 @@ TAO_AV_Endpoint_Reactive_Strategy <T_StreamEndpoint, T_VDev, T_MediaCtrl>::activ { this->activate_stream_endpoint (ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activated stream_endpoint\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activated stream_endpoint\n")); this->activate_vdev (ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activated vdev\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activated vdev\n")); this->activate_mediactrl (ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activated mediactrl\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activated mediactrl\n")); } ACE_CATCHANY { @@ -67,7 +67,7 @@ TAO_AV_Endpoint_Reactive_Strategy <T_StreamEndpoint, T_VDev, T_MediaCtrl>::activ CORBA::String_var vdev_ior = this->orb_manager_->activate (vdev, ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activate_vdev, vdev ior is:%s\n", + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activate_vdev, vdev ior is:%s\n", vdev_ior. in ())); // Save the object reference, so that create_A can return it @@ -102,7 +102,7 @@ TAO_AV_Endpoint_Reactive_Strategy <T_StreamEndpoint, T_VDev, T_MediaCtrl>::activ CORBA::String_var mediactrl_ior = this->orb_manager_->activate (media_ctrl, ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Endpoint_Reactive_Strategy::activate_mediactrl , media_ctrl ior is :%s\n", + 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 ())); @@ -214,7 +214,7 @@ TAO_AV_Endpoint_Reactive_Strategy_A <T_StreamEndpoint, T_VDev, T_MediaCtrl>::act CORBA::String_var stream_endpoint_ior = this->orb_manager_->activate (stream_endpoint_a, ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"TAO_AV_Endpoint_Reactive_Strategy_A::activate_stream_endpoint,Stream Endpoint ior is : %s\n",stream_endpoint_ior.in ())); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Endpoint_Reactive_Strategy_A::activate_stream_endpoint,Stream Endpoint ior is : %s\n",stream_endpoint_ior.in ())); // Save the object references, so that create_a can return them this->stream_endpoint_a_ = stream_endpoint_a->_this (ACE_TRY_ENV); @@ -263,7 +263,7 @@ TAO_AV_Endpoint_Reactive_Strategy_B <T_StreamEndpoint, T_VDev, T_MediaCtrl>::act CORBA::String_var stream_endpoint_ior = this->orb_manager_->activate (stream_endpoint_b, ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"TAO_AV_Endpoint_Reactive_Strategy_B::activate_stream_endpoint,Stream Endpoint ior is : %s\n",stream_endpoint_ior.in ())); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Endpoint_Reactive_Strategy_B::activate_stream_endpoint,Stream Endpoint ior is : %s\n",stream_endpoint_ior.in ())); this->stream_endpoint_b_ = stream_endpoint_b->_this (ACE_TRY_ENV); ACE_TRY_CHECK; @@ -388,20 +388,20 @@ TAO_AV_Child_Process <T_StreamEndpoint, T_VDev, T_MediaCtrl>::activate_objects CORBA::String_var stream_endpoint_ior = this->orb_manager_.activate (this->stream_endpoint_, ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Child_Process::activate_objects,stream_endpoint_ior :%s\n",stream_endpoint_ior.in ())); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Child_Process::activate_objects,stream_endpoint_ior :%s\n",stream_endpoint_ior.in ())); // activate the vdev CORBA::String_var vdev_ior = this->orb_manager_.activate (this->vdev_, ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Child_Process::activate_objects, vdev ior is :%s\n",vdev_ior.in ())); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Child_Process::activate_objects, vdev ior is :%s\n",vdev_ior.in ())); // activate the media controller CORBA::String_var media_ctrl_ior = this->orb_manager_.activate (this->media_ctrl_, ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Child_Process::activate_objects,media_ctrl_ior is: %s\n",media_ctrl_ior.in ())); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Child_Process::activate_objects,media_ctrl_ior is: %s\n",media_ctrl_ior.in ())); } ACE_CATCHANY { @@ -426,7 +426,7 @@ TAO_AV_Child_Process <T_StreamEndpoint, T_VDev, T_MediaCtrl>::bind_to_naming_se ACE_ERROR_RETURN ((LM_ERROR, " (%P|%t) Unable to resolve the Name Service.\n"), -1); - // ACE_DEBUG ((LM_DEBUG, "(%P|%t) %s:%d\n", __FILE__, __LINE__)); + // if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) %s:%d\n", __FILE__, __LINE__)); this->naming_context_ = CosNaming::NamingContext::_narrow (naming_obj.in (), ACE_TRY_ENV); @@ -457,14 +457,14 @@ TAO_AV_Child_Process <T_StreamEndpoint, T_VDev, T_MediaCtrl>::register_vdev (CO this->host_, this->pid_); - ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",vdev_name)); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",vdev_name)); // create the name this->vdev_name_.length (1); this->vdev_name_ [0].id = CORBA::string_dup (vdev_name); // make the media controller a property of the vdev CORBA::Any media_ctrl_property; - CORBA::Object_var media_ctrl_obj = + CORBA::Object_var media_ctrl_obj = this->media_ctrl_->_this (ACE_TRY_ENV); ACE_TRY_CHECK; media_ctrl_property <<= this->orb_manager_.orb ()->object_to_string (media_ctrl_obj.in (), @@ -549,7 +549,7 @@ TAO_AV_Child_Process <T_StreamEndpoint_B, T_VDev, T_MediaCtrl>::release_semapho this->host_, pid); - ACE_DEBUG ((LM_DEBUG, + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) semaphore is %s\n", sem_str)); @@ -580,7 +580,7 @@ TAO_AV_Child_Process <T_StreamEndpoint, T_VDev, T_MediaCtrl>::register_stream_e ACE_TRY_CHECK; this->stream_endpoint_->_remove_ref (ACE_TRY_ENV); ACE_TRY_CHECK; - // ACE_DEBUG ((LM_DEBUG, "(%P|%t) %s:%d\n", __FILE__, __LINE__)); + // if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) %s:%d\n", __FILE__, __LINE__)); // Create a name for the video control object // subclasses can define their own name for the streamendpoint // Register the stream endpoint object with the naming server. @@ -634,7 +634,7 @@ template <class T_StreamEndpoint, class T_VDev , class T_MediaCtrl> int TAO_AV_Child_Process<T_StreamEndpoint, T_VDev, T_MediaCtrl>::make_mediactrl (T_MediaCtrl *&media_ctrl) { - ACE_DEBUG ((LM_DEBUG,"(%P|%t) TAO_AV_Child_Process::make_mediactrl ()\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t) TAO_AV_Child_Process::make_mediactrl ()\n")); ACE_NEW_RETURN (media_ctrl, T_MediaCtrl, -1); @@ -703,7 +703,7 @@ TAO_AV_Child_Process_A<T_StreamEndpoint, T_VDev, T_MediaCtrl>::TAO_AV_Child_Proc this->host_, this->pid_); - ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); this->stream_endpoint_name_.length (1); this->stream_endpoint_name_ [0].id = CORBA::string_dup (stream_endpoint_name); } @@ -729,7 +729,7 @@ TAO_AV_Child_Process_B<T_StreamEndpoint, T_VDev, T_MediaCtrl>::TAO_AV_Child_Proc this->host_, this->pid_); - ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)%s\n",stream_endpoint_name)); this->stream_endpoint_name_.length (1); this->stream_endpoint_name_ [0].id = CORBA::string_dup (stream_endpoint_name); } diff --git a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.h b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.h index d88b3330638..ca805f98bfe 100644 --- a/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.h +++ b/TAO/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.h @@ -1,5 +1,23 @@ +/* -*- C++ -*- */ + // $Id$ +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// Endpoint_Strategy_T.h +// +// = AUTHOR +// Sumedh Mungee <sumedh@cs.wustl.edu> +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + + #ifndef TAO_AV_ENDPOINT_STRATEGY_T_H #define TAO_AV_ENDPOINT_STRATEGY_T_H @@ -7,11 +25,12 @@ template <class T_StreamEndpoint, class T_VDev , class T_MediaCtrl> class TAO_ORBSVCS_Export TAO_AV_Endpoint_Reactive_Strategy - : public TAO_AV_Endpoint_Strategy -// = DESCRIPTION -// Reactive strategy base class +: public TAO_AV_Endpoint_Strategy { - protected: + // = DESCRIPTION + // Reactive strategy base class + +protected: TAO_AV_Endpoint_Reactive_Strategy (TAO_ORB_Manager *orb_manager); // Constructor @@ -51,10 +70,11 @@ class TAO_ORBSVCS_Export TAO_AV_Endpoint_Reactive_Strategy template <class T_StreamEndpoint, class T_VDev , class T_MediaCtrl> class TAO_ORBSVCS_Export TAO_AV_Endpoint_Reactive_Strategy_A : public TAO_AV_Endpoint_Reactive_Strategy<T_StreamEndpoint, T_VDev , T_MediaCtrl> -// = DESCRIPTION -// Reactive strategy { - public: + // = DESCRIPTION + // Reactive strategy + +public: TAO_AV_Endpoint_Reactive_Strategy_A (TAO_ORB_Manager *orb_manager); // Constructor @@ -70,17 +90,16 @@ class TAO_ORBSVCS_Export TAO_AV_Endpoint_Reactive_Strategy_A CORBA::Environment &env); // Called by the MMDevice, when it needs to create an A type endpoint - }; // ---------------------------------------------------------------------- template <class T_StreamEndpoint, class T_Vdev , class T_MediaCtrl> class TAO_ORBSVCS_Export TAO_AV_Endpoint_Reactive_Strategy_B : public TAO_AV_Endpoint_Reactive_Strategy <T_StreamEndpoint, T_Vdev, T_MediaCtrl> -// = DESCRIPTION -// Reactive strategy { - public: + // = DESCRIPTION + // Reactive strategy +public: TAO_AV_Endpoint_Reactive_Strategy_B (TAO_ORB_Manager *); // Constructor. @@ -101,9 +120,10 @@ class TAO_ORBSVCS_Export TAO_AV_Endpoint_Reactive_Strategy_B template <class T_StreamEndpoint, class T_VDev , class T_MediaCtrl> class TAO_ORBSVCS_Export TAO_AV_Child_Process -// = DESCRIPTION -// Helper class for the child process created in TAO_AV_Endpoint_Process_Strategy { + // = DESCRIPTION + // Helper class for the child process created in TAO_AV_Endpoint_Process_Strategy + public: TAO_AV_Child_Process (); // Constructor @@ -118,7 +138,7 @@ public: int run (ACE_Time_Value *tv = 0); // runs the ORB event loop - protected: +protected: int activate_objects (int argc, char **argv, CORBA::Environment &env); @@ -186,9 +206,10 @@ public: template <class T_StreamEndpoint, class T_VDev , class T_MediaCtrl> class TAO_ORBSVCS_Export TAO_AV_Child_Process_A : public TAO_AV_Child_Process <T_StreamEndpoint, T_VDev, T_MediaCtrl> -// = DESCRIPTION -// Helper class for the child process created in TAO_AV_Child_Process { + // = DESCRIPTION + // Helper class for the child process created in TAO_AV_Child_Process + public: TAO_AV_Child_Process_A (void); // Constructor. @@ -202,9 +223,9 @@ public: template <class T_StreamEndpoint, class T_VDev , class T_MediaCtrl> class TAO_ORBSVCS_Export TAO_AV_Child_Process_B : public TAO_AV_Child_Process <T_StreamEndpoint, T_VDev, T_MediaCtrl> -// = DESCRIPTION -// Helper class for the child process created in TAO_AV_Child_Process { + // = DESCRIPTION + // Helper class for the child process created in TAO_AV_Child_Process public: TAO_AV_Child_Process_B (void); // Constructor. diff --git a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp new file mode 100644 index 00000000000..cb2edd12e21 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.cpp @@ -0,0 +1,532 @@ +// $Id$ + +//------------------------------------------------------------ +// TAO_FlowSpec_Entry +//------------------------------------------------------------ +#include "FlowSpec_Entry.h" +#include "tao/TAO.h" + +#if !defined (__ACE_INLINE__) +#include "FlowSpec_Entry.i" +#endif /* __ACE_INLINE__ */ + +// constructor. +TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (void) + :address_ (0), + address_str_ (CORBA::string_dup ("")), + format_ (CORBA::string_dup ("")), + direction_ (TAO_AV_INVALID), + protocol_ (TAO_AV_Core::TAO_AV_NOPROTOCOL), + carrier_protocol_ (CORBA::string_dup ("")), + flow_protocol_ (CORBA::string_dup ("")), + use_flow_protocol_ (0), + entry_ (0), + is_multicast_ (0), + peer_addr_ (0), + local_addr_ (0), + transport_ (0), + handler_ (0), + protocol_object_ (0), + role_ (TAO_AV_INVALID_ROLE) +{ +} + +// constructor. +TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *carrier_protocol, + ACE_Addr *address) + :address_ (address), + address_str_ (0), + format_ (CORBA::string_dup (format_name)), + direction_str_ (CORBA::string_dup (direction)), + flowname_ (CORBA::string_dup (flowname)), + carrier_protocol_ (CORBA::string_dup (carrier_protocol)), + flow_protocol_ (CORBA::string_dup (flow_protocol)), + use_flow_protocol_ (0), + entry_ (0), + peer_addr_ (0), + local_addr_ (0), + transport_ (0), + handler_ (0), + protocol_object_ (0), + is_multicast_ (0), + role_ (TAO_AV_INVALID_ROLE) +{ + this->set_protocol (); + this->set_direction (this->direction_str_); + this->parse_flow_protocol_string (this->flow_protocol_); +} + +TAO_FlowSpec_Entry::TAO_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *address) + :address_ (0), + address_str_ (CORBA::string_dup (address)), + format_ (CORBA::string_dup (format_name)), + direction_str_ (CORBA::string_dup (direction)), + flowname_ (CORBA::string_dup (flowname)), + carrier_protocol_ (0), + flow_protocol_ (CORBA::string_dup (flow_protocol)), + use_flow_protocol_ (0), + entry_ (0), + peer_addr_ (0), + local_addr_ (0), + transport_ (0), + handler_ (0), + protocol_object_ (0), + is_multicast_ (0), + role_ (TAO_AV_INVALID_ROLE) +{ + ACE_CString cstring(this->address_str_,0,0); + int colon_pos = cstring.find (':'); + if (colon_pos != cstring.npos) + cstring[colon_pos] = ';'; + this->address_str_ = cstring.rep (); + this->parse_flow_protocol_string (this->flow_protocol_); + this->parse_address (this->address_str_); + this->set_direction (this->direction_str_); +} + +// Destructor. +TAO_FlowSpec_Entry::~TAO_FlowSpec_Entry (void) +{ + CORBA::string_free (this->format_); + CORBA::string_free (this->direction_str_); + CORBA::string_free (this->flowname_); + CORBA::string_free (this->carrier_protocol_); +} + +int +TAO_FlowSpec_Entry::set_protocol (void) +{ + if (!this->use_flow_protocol_) + { + if (ACE_OS::strcasecmp (this->carrier_protocol_,"TCP") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_TCP; + else if (ACE_OS::strcasecmp (this->carrier_protocol_,"UDP") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_UDP; + else if (ACE_OS::strcasecmp (this->carrier_protocol_,"AAL5") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_AAL5; + else if (ACE_OS::strcasecmp (this->carrier_protocol_,"AAL3_4") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_AAL3_4; + else if (ACE_OS::strcasecmp (this->carrier_protocol_,"AAL1") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_AAL1; + else if (ACE_OS::strcasecmp (this->carrier_protocol_,"RTP/UDP") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_RTP_UDP; + else if (ACE_OS::strcasecmp (this->carrier_protocol_,"RTP/AAL5") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_RTP_AAL5; + else if (ACE_OS::strcasecmp (this->carrier_protocol_,"IPX") == 0) + this->protocol_ = TAO_AV_Core::TAO_AV_IPX; + else + { + this->protocol_ = TAO_AV_Core::TAO_AV_NOPROTOCOL; + return -1; + } + } + else + { + if (ACE_OS::strcasecmp (this->carrier_protocol_,"UDP") == 0) + { + this->protocol_ = TAO_AV_Core::TAO_AV_SFP_UDP; + } + else + { + this->protocol_ = TAO_AV_Core::TAO_AV_NOPROTOCOL; + return -1; + } + } + if (this->address_ != 0) + { + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,this->address_); + char buf[BUFSIZ]; + inet_addr->addr_to_string (buf,BUFSIZ); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_FlowSpec_Entry::set_protocol:%s\n",buf)); + if (IN_CLASSD (inet_addr->get_ip_address ())) + { + 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; + } + } + } + return 0; +} + +int +TAO_FlowSpec_Entry::parse_address (char *address) +{ + 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 (); + if (result < 0) + return result; + + if (protocol_tokenizer [1] != 0) + { + TAO_Tokenizer address_tokenizer (protocol_tokenizer[1],';'); + char addr[BUFSIZ]; + // convert to the ACE_Addr format. + ACE_OS::sprintf (addr,"%s:%s",address_tokenizer[0],address_tokenizer[1]); + 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: + { + this->address_str_ = CORBA::string_dup (addr); + ACE_INET_Addr *inet_addr; + ACE_NEW_RETURN (inet_addr, + ACE_INET_Addr (addr), + -1); + this->address_ = inet_addr; + if (IN_CLASSD (inet_addr->get_ip_address ())) + { + 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")); + } + } + return 0; +} + +char * +TAO_FlowSpec_Entry::get_local_addr_str (void) +{ + if (this->local_addr_ == 0) + return 0; + + switch (this->local_addr_->get_type ()) + { + case AF_INET: + { + char *buf; + ACE_NEW_RETURN (buf, + char [BUFSIZ], + 0); + 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 (); + } + break; + default: + ACE_ERROR_RETURN ((LM_ERROR,"Address family not supported"),0); + } +} + +//------------------------------------------------------------ +// TAO_Forward_FlowSpec_Entry +//------------------------------------------------------------ + +// default constructor. +TAO_Forward_FlowSpec_Entry::TAO_Forward_FlowSpec_Entry (void) +{ +} + +// constructor to construct the entry from the arguments. +TAO_Forward_FlowSpec_Entry::TAO_Forward_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name , + const char *flow_protocol , + const char *carrier_protocol , + ACE_Addr *address ) + :TAO_FlowSpec_Entry (flowname, + direction, + format_name, + flow_protocol, + carrier_protocol, + address) +{ +} + +// constructor to construct the entry from the arguments. +TAO_Forward_FlowSpec_Entry::TAO_Forward_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name , + const char *flow_protocol , + const char *address ) + :TAO_FlowSpec_Entry (flowname, + direction, + format_name, + flow_protocol, + address) +{ +} + +int +TAO_Forward_FlowSpec_Entry::parse (const char *flowSpec_entry) +{ + TAO_Tokenizer tokenizer (flowSpec_entry,'\\'); + + this->flowname_ = tokenizer [TAO_AV_FLOWNAME]; + + 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_ADDRESS] != 0) + if (this->parse_address (tokenizer [TAO_AV_ADDRESS]) < 0) + return -1; + + if (tokenizer [TAO_AV_FLOW_PROTOCOL] != 0) + if (this->parse_flow_protocol_string (tokenizer [TAO_AV_FLOW_PROTOCOL]) < 0) + return -1; + + return 0; +} + +TAO_FlowSpec_Entry::Role +TAO_Forward_FlowSpec_Entry::role (void) +{ + if (this->role_ != TAO_AV_INVALID_ROLE) + return this->role_; + + switch (this->direction_) + { + case TAO_AV_DIR_IN: + // Forward IN means we're the Source. + return TAO_AV_PRODUCER; + case TAO_AV_DIR_OUT: + // Forward out means we're the sink. + return TAO_AV_CONSUMER; + default: + return TAO_AV_INVALID_ROLE; + } + return TAO_AV_INVALID_ROLE; +} + +char * +TAO_Forward_FlowSpec_Entry::entry_to_string (void) +{ + if (this->flowname_ == 0) + return 0; + + ACE_NEW_RETURN (this->entry_, + char [BUFSIZ], + 0); + + char address [BUFSIZ]; + char address_str [BUFSIZ]; + if (this->address_ != 0) + { + 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_UDP_MCAST: + case TAO_AV_Core::TAO_AV_TCP: + { + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,this->address_); + inet_addr->addr_to_string (address,BUFSIZ); + } + break; + default: + break; + } + ACE_CString cstring (address); + int colon_pos = cstring.find (':'); + if (colon_pos != cstring.npos) + cstring[colon_pos] = ';'; + + + ACE_OS::sprintf (address_str,"%s=%s", + this->carrier_protocol_, + cstring.c_str ()); + + } + else + ACE_OS::strcpy (address_str,this->carrier_protocol_); + ACE_OS::sprintf (this->entry_, + "%s\\%s\\%s\\%s\\%s", + this->flowname_, + this->direction_str_, + this->format_, + this->flow_protocol_, + address_str); + + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"entry_to_string: entry = %s\n",this->entry_)); + return this->entry_; +} + +//------------------------------------------------------------ +// TAO_Reverse_FlowSpec_Entry +//------------------------------------------------------------ + +//default constructor. +TAO_Reverse_FlowSpec_Entry::TAO_Reverse_FlowSpec_Entry (void) +{ +} + +// constructor to construct an entry from the arguments. +TAO_Reverse_FlowSpec_Entry::TAO_Reverse_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name , + const char *flow_protocol , + const char *carrier_protocol, + ACE_Addr *address) + :TAO_FlowSpec_Entry (flowname, + direction, + format_name, + flow_protocol, + carrier_protocol, + address) +{ +} + +// constructor to construct an entry from the arguments. +TAO_Reverse_FlowSpec_Entry::TAO_Reverse_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name , + const char *flow_protocol , + const char *address) + :TAO_FlowSpec_Entry (flowname, + direction, + format_name, + flow_protocol, + address) +{ +} + +TAO_FlowSpec_Entry::Role +TAO_Reverse_FlowSpec_Entry::role (void) +{ + if (this->role_ != TAO_AV_INVALID_ROLE) + return this->role_; + switch (this->direction_) + { + case TAO_AV_DIR_IN: + // Forward IN means we're the Source. + return TAO_AV_CONSUMER; + case TAO_AV_DIR_OUT: + // Forward out means we're the sink. + return TAO_AV_PRODUCER; + default: + return TAO_AV_INVALID_ROLE; + } + return TAO_AV_INVALID_ROLE; +} + +int +TAO_Reverse_FlowSpec_Entry::parse (const char *flowSpec_entry) +{ + TAO_Tokenizer tokenizer (flowSpec_entry,'\\'); + this->flowname_ = tokenizer [TAO_AV_FLOWNAME]; + + if (tokenizer [TAO_AV_ADDRESS] != 0) + if (this->parse_address (tokenizer [TAO_AV_ADDRESS]) < 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_FORMAT] != 0) + this->format_ = tokenizer [TAO_AV_FORMAT]; + + return 0; +} + + +char * +TAO_Reverse_FlowSpec_Entry::entry_to_string (void) +{ + if (this->flowname_ == 0) + return 0; + + ACE_NEW_RETURN (this->entry_, + char [BUFSIZ], + 0); + + + char address [BUFSIZ]; + char address_str [BUFSIZ]; + if (this->address_ != 0) + { + + switch (this->protocol_) + { + case TAO_AV_Core::TAO_AV_RTP_UDP: + case TAO_AV_Core::TAO_AV_UDP: + case TAO_AV_Core::TAO_AV_UDP_MCAST: + case TAO_AV_Core::TAO_AV_TCP: + case TAO_AV_Core::TAO_AV_SFP_UDP: + { + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,this->address_); + inet_addr->addr_to_string (address,BUFSIZ); + } + break; + default: + break; + } + ACE_CString cstring (address); + int colon_pos = cstring.find (':'); + if (colon_pos != cstring.npos) + cstring[colon_pos] = ';'; + + ACE_OS::sprintf (address_str,"%s=%s", + this->carrier_protocol_, + cstring.c_str ()); + + } + else + ACE_OS::strcpy (address_str,""); + ACE_OS::sprintf (this->entry_, + "%s\\%s\\%s\\%s\\%s", + this->flowname_, + address_str, + this->flow_protocol_, + this->direction_str_, + this->format_); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"entry_to_string: entry = %s\n",this->entry_)); + return this->entry_; +} diff --git a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h new file mode 100644 index 00000000000..83ab0f9a4c0 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h @@ -0,0 +1,282 @@ +/* -*- C++ -*- */ + +//$Id$ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS (AVStreams) +// +// = FILENAME +// FlowSpec_Entry.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_FLOWSPEC_ENTRY_H +#define TAO_AV_FLOWSPEC_ENTRY_H + +#include "orbsvcs/orbsvcs_export.h" +#include "AV_Core.h" +#include "ace/Addr.h" + +class TAO_ORBSVCS_Export TAO_Tokenizer +{ +public: + TAO_Tokenizer (const char *string,char delimiter); + // constructor. + + ~TAO_Tokenizer (); + // destructor. + + int parse (const char *string,char delimiter); + // parses the string and tokenizes it. + + char *token (void); + // Returns the next token. + + int num_tokens (void); + // Number of tokens. + + char *operator [] (size_t index) const; + +protected: + ACE_Array<char*> token_array_; + size_t count_; + size_t num_tokens_; + char string_ [BUFSIZ]; +}; + +// Forward declaration. +class TAO_AV_Transport; +class TAO_AV_Flow_Handler; +class TAO_AV_Protocol_Object; + +class TAO_ORBSVCS_Export TAO_FlowSpec_Entry +{ +public: + // = TITLE + // An helper entry class in the flow spec sequence passed to bind_devs. + enum Direction + { + TAO_AV_INVALID = -1, + TAO_AV_DIR_IN = 0, + TAO_AV_DIR_OUT = 1 + }; + + enum Role + { + TAO_AV_INVALID_ROLE = -1, + TAO_AV_PRODUCER = 0, + TAO_AV_CONSUMER = 1 + }; + + TAO_FlowSpec_Entry (void); + // default constructor. + + TAO_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *carrier_protocol, + ACE_Addr *address); + // constructor to construct an entry from the arguments. + + TAO_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *address); + + virtual int parse (const char* flowSpec_entry) = 0; + // construct the entry from a string specified by the flowSpec grammar. + + virtual ~TAO_FlowSpec_Entry (void); + // virtual destructor. + + int direction (void); + // accessor to the direction. + + virtual Role role (void) = 0; + void role (Role role); + char * direction_str (void); + // string version of direction . + + char *flow_protocol_str (void); + // accesor to the flow protocol string. + + void flow_protocol_str (const char *flow_protocol_str); + // set the flow protocol string. + + ACE_Addr *address (void); + // Address of the carrier protocol. + + char * address_str (void); + // Address in string format i. hostname:port. + + TAO_AV_Core::Protocol carrier_protocol (void); + // carrier protocol i.e TCP,UDP,RTP/UDP. + + char * carrier_protocol_str (void); + // string version of carrier protocol. + + char *format (void); + // format to be used for this flow. + + const char *flowname (void); + // name of this flow. + + virtual char *entry_to_string (void) = 0; + // converts the entry to a string. + + int set_peer_addr (ACE_Addr *peer_addr); + ACE_Addr *get_peer_addr (void); + int set_local_addr (ACE_Addr *peer_addr); + ACE_Addr *get_local_addr (void); + char *get_local_addr_str (void); + TAO_AV_Transport *transport (void); + void transport (TAO_AV_Transport *transport); + TAO_AV_Flow_Handler* handler (void); + void handler (TAO_AV_Flow_Handler *handler); + TAO_AV_Protocol_Object* protocol_object (void); + void protocol_object (TAO_AV_Protocol_Object *object); + + int parse_address (char *format_string); + // sets the address for this flow. + + int is_multicast (void); + // returns true for a multicast address. + +protected: + + int parse_flow_protocol_string (char *flow_options_string); + // parses the flow protocol string with tokens separated by : + + int set_direction (char *direction_string); + // sets the direction flag. + + + int set_protocol (void); + // sets the protocol_ enum from the carrier_protocol_ string. + + ACE_Addr *address_; + // Addr information for the carrier protocol. + + char *address_str_; + // Addr in string format i.e hostname:port. + + char *format_; + // format string. + + Direction direction_; + // Direction of this flow. + + char *direction_str_; + // string representation of the direction. + + char *flowname_; + // name of this flow. + + TAO_AV_Core::Protocol protocol_; + // name of the protocol used. + + char *carrier_protocol_; + // carrier protocol string. + + char *flow_protocol_; + // flow protocol string. + + int use_flow_protocol_; + char *entry_; + // The flowspec entry; + + int is_multicast_; + ACE_Addr *peer_addr_; + ACE_Addr *local_addr_; + TAO_AV_Transport *transport_; + TAO_AV_Flow_Handler *handler_; + TAO_AV_Protocol_Object *protocol_object_; + Role role_; +}; + +class TAO_ORBSVCS_Export TAO_Forward_FlowSpec_Entry + :public TAO_FlowSpec_Entry +{ +public: + enum Position {TAO_AV_FLOWNAME = 0, + TAO_AV_DIRECTION = 1, + TAO_AV_FORMAT = 2, + TAO_AV_FLOW_PROTOCOL = 3, + TAO_AV_ADDRESS = 4}; + + TAO_Forward_FlowSpec_Entry (void); + // default constructor. + + TAO_Forward_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *carrier_protocol, + ACE_Addr *address); + // constructor to construct an entry from the arguments. + + TAO_Forward_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *address); + + virtual char *entry_to_string (void); + // converts the entry to a string. + + virtual Role role (void); + virtual int parse (const char* flowSpec_entry); + // construct the entry from a string specified by the flowSpec grammar. +}; + +class TAO_ORBSVCS_Export TAO_Reverse_FlowSpec_Entry + :public TAO_FlowSpec_Entry +{ +public: + enum Position {TAO_AV_FLOWNAME = 0, + TAO_AV_ADDRESS = 1, + TAO_AV_FLOW_PROTOCOL = 2, + TAO_AV_DIRECTION = 3, + TAO_AV_FORMAT = 4}; + + TAO_Reverse_FlowSpec_Entry (void); + // default constructor. + + TAO_Reverse_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *carrier_protocol, + ACE_Addr *address); + // constructor to construct an entry from the arguments. + + TAO_Reverse_FlowSpec_Entry (const char *flowname, + const char *direction, + const char *format_name, + const char *flow_protocol, + const char *address); + // Takes the address in protocol=endpoint form. + + virtual char *entry_to_string (void); + // converts the entry to a string. + + virtual Role role (void); + virtual int parse (const char* flowSpec_entry); + // construct the entry from a string specified by the flowSpec grammar. +}; + +#include "Transport.h" + +#if defined (__ACE_INLINE__) +#include "FlowSpec_Entry.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_AV_FLOWSPEC_ENTRY_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i new file mode 100644 index 00000000000..8522b9a55b4 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i @@ -0,0 +1,208 @@ +/* -*- C++ -*- */ +// $Id$ + +// FlowSpec_Entry.i + +ACE_INLINE +int +TAO_FlowSpec_Entry::set_direction (char *direction) +{ + this->direction_str_ = direction; + if (direction == 0) + { + this->direction_ = TAO_AV_INVALID; + return -1; + } + if (ACE_OS::strcasecmp (direction,"in") == 0) + this->direction_ = TAO_AV_DIR_IN; + else if (ACE_OS::strcasecmp (direction,"out") == 0) + this->direction_ = TAO_AV_DIR_OUT; + return 0; +} + +ACE_INLINE +int +TAO_FlowSpec_Entry::parse_flow_protocol_string (char *flow_string) +{ + if (flow_string == 0) + return 0; + if (ACE_OS::strncasecmp (flow_string,"sfp",3) == 0) + { + this->use_flow_protocol_ = 1; + // do some flow protocol processing. + this->flow_protocol_ = flow_string; + } + return 0; +} + +ACE_INLINE +int +TAO_FlowSpec_Entry::direction (void) +{ + return this->direction_; +} + +ACE_INLINE +char * +TAO_FlowSpec_Entry::direction_str (void) +{ + return this->direction_str_; +} + +ACE_INLINE +char * +TAO_FlowSpec_Entry::flow_protocol_str (void) +{ + return this->flow_protocol_; +} + +ACE_INLINE +void +TAO_FlowSpec_Entry::flow_protocol_str (const char *str) +{ + this->flow_protocol_ = CORBA::string_dup (str); +} + +ACE_INLINE +TAO_AV_Core::Protocol +TAO_FlowSpec_Entry::carrier_protocol (void) +{ + return this->protocol_; +} + +ACE_INLINE +char * +TAO_FlowSpec_Entry::carrier_protocol_str (void) +{ + return this->carrier_protocol_; +} + +ACE_INLINE +ACE_Addr * +TAO_FlowSpec_Entry::address (void) +{ + return this->address_; +} + +ACE_INLINE +char * +TAO_FlowSpec_Entry::address_str (void) +{ + return this->address_str_; +} + +ACE_INLINE +char* +TAO_FlowSpec_Entry::format (void) +{ + return this->format_; +} + +ACE_INLINE +const char * +TAO_FlowSpec_Entry::flowname (void) +{ + return this->flowname_; +} + + +ACE_INLINE +int +TAO_FlowSpec_Entry::set_peer_addr (ACE_Addr *peer_addr) +{ + this->peer_addr_ = peer_addr; + if (this->handler_ != 0) + this->handler_->set_remote_address (peer_addr); + return 0; +} + +ACE_INLINE +ACE_Addr * +TAO_FlowSpec_Entry::get_peer_addr (void) +{ + return this->peer_addr_; +} + +ACE_INLINE +int +TAO_FlowSpec_Entry::set_local_addr (ACE_Addr *local_addr) +{ + this->local_addr_ = local_addr; + return 0; +} + +ACE_INLINE +ACE_Addr* +TAO_FlowSpec_Entry::get_local_addr (void) +{ + return this->local_addr_; +} + +ACE_INLINE +TAO_AV_Transport* +TAO_FlowSpec_Entry::transport (void) +{ + return this->transport_; +} + +ACE_INLINE +void +TAO_FlowSpec_Entry::transport (TAO_AV_Transport *transport) +{ + this->transport_ = transport; +} + +ACE_INLINE +TAO_AV_Flow_Handler * +TAO_FlowSpec_Entry::handler (void) +{ + return this->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 ()) +// { +// case TAO_AV_PRODUCER: +// { +// ACE_Event_Handler *event_handler = handler->event_handler (); +// int result = event_handler->reactor ()->remove_handler (event_handler, +// ACE_Event_Handler::READ_MASK); +// if (result < 0) +// ACE_ERROR ((LM_ERROR,"TAO_FlowSpec_Entry::handler\n")); +// break; +// } +// } +} + +ACE_INLINE +TAO_AV_Protocol_Object* +TAO_FlowSpec_Entry::protocol_object (void) +{ + return this->protocol_object_; +} + +ACE_INLINE +void +TAO_FlowSpec_Entry::protocol_object (TAO_AV_Protocol_Object *object) +{ + this->protocol_object_ = object; +} + +ACE_INLINE +int +TAO_FlowSpec_Entry::is_multicast (void) +{ + return this->is_multicast_; +} + +ACE_INLINE +void +TAO_FlowSpec_Entry::role (TAO_FlowSpec_Entry::Role role) +{ + this->role_ = role; +} diff --git a/TAO/orbsvcs/orbsvcs/AV/Flows_T.cpp b/TAO/orbsvcs/orbsvcs/AV/Flows_T.cpp new file mode 100644 index 00000000000..77dc2ecea13 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Flows_T.cpp @@ -0,0 +1,248 @@ +//$Id$ + +#ifndef TAO_AV_FLOWS_T_C +#define TAO_AV_FLOWS_T_C + +#include "Flows_T.h" + + +// ------------------------------------------------------------ +// TAO_FDev +// ------------------------------------------------------------ + +// default constructor +template <class T_Producer, class T_Consumer> +TAO_FDev<T_Producer, T_Consumer>::TAO_FDev (void) +{ +} + +template <class T_Producer, class T_Consumer> +TAO_FDev<T_Producer, T_Consumer>::TAO_FDev (const char *flowname) + :flowname_ (flowname) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::Any flowname_any; + flowname_any <<= flowname; + this->define_property ("Flow", + flowname_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FDev::TAO_FDev"); + } + ACE_ENDTRY; + ACE_CHECK; +} + +template <class T_Producer, class T_Consumer> +TAO_FDev<T_Producer, T_Consumer>::~TAO_FDev (void) +{ + //no-op +} + +template <class T_Producer, class T_Consumer> +const char * +TAO_FDev<T_Producer, T_Consumer>::flowname (void) +{ + return this->flowname_.in (); +} + +template <class T_Producer, class T_Consumer> +void +TAO_FDev<T_Producer, T_Consumer>::flowname (const char *flow_name) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CORBA::Any flowname_any; + flowname_any <<= flow_name; + this->define_property ("Flow", + flowname_any, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FDev::flowname"); + } + ACE_ENDTRY; + ACE_CHECK; + this->flowname_ = flow_name; +} + +template <class T_Producer, class T_Consumer> +AVStreams::FlowProducer_ptr +TAO_FDev<T_Producer, T_Consumer>::create_producer (AVStreams::FlowConnection_ptr the_requester, + AVStreams::QoS & the_qos, + CORBA::Boolean_out met_qos, + char *& named_fdev, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, + AVStreams::notSupported, + AVStreams::QoSRequestFailed)) +{ + // call the bridge method. + return this->make_producer (the_requester, + the_qos, + met_qos, + named_fdev, + ACE_TRY_ENV); +} + +template <class T_Producer, class T_Consumer> +// hook for the applications to override the creation process. +AVStreams::FlowProducer_ptr +TAO_FDev<T_Producer, T_Consumer>::make_producer (AVStreams::FlowConnection_ptr /* the_requester */, + AVStreams::QoS & /* the_qos */, + CORBA::Boolean_out /* met_qos */, + char *& /* named_fdev */, + CORBA::Environment &ACE_TRY_ENV) +{ + AVStreams::FlowProducer_ptr producer = AVStreams::FlowProducer::_nil (); + ACE_TRY + { + // Activate the producer implementation under the Root POA. + T_Producer *producer_i; + ACE_NEW_RETURN (producer_i, + T_Producer, + 0); + this->producer_list_.insert_tail (producer_i); + producer = producer_i->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FDev::make_producer"); + return producer; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (producer); + return producer; +} + +template <class T_Producer, class T_Consumer> +// hook for the applications to override the consumer creation. +AVStreams::FlowConsumer_ptr +TAO_FDev<T_Producer, T_Consumer>::make_consumer (AVStreams::FlowConnection_ptr /* the_requester */, + AVStreams::QoS & /* the_qos */, + CORBA::Boolean_out /* met_qos */, + char *& /* named_fdev */, + CORBA::Environment &ACE_TRY_ENV) +{ + AVStreams::FlowConsumer_ptr consumer = AVStreams::FlowConsumer::_nil (); + ACE_TRY + { + // Activate the consumer implementation under the Root POA. + T_Consumer *consumer_i; + ACE_NEW_RETURN (consumer_i, + T_Consumer, + 0); + this->consumer_list_.insert_tail (consumer_i); + consumer = consumer_i->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_FDev::make_consumer"); + return consumer; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (consumer); + return consumer; +} + +template <class T_Producer, class T_Consumer> +AVStreams::FlowConsumer_ptr +TAO_FDev<T_Producer, T_Consumer>::create_consumer (AVStreams::FlowConnection_ptr the_requester, + AVStreams::QoS & the_qos, + CORBA::Boolean_out met_qos, + char *& named_fdev, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, + AVStreams::notSupported, + AVStreams::QoSRequestFailed)) +{ + return this->make_consumer (the_requester, + the_qos, + met_qos, + named_fdev, + ACE_TRY_ENV); +} + +template <class T_Producer, class T_Consumer> +// not implemented yet. +AVStreams::FlowConnection_ptr +TAO_FDev<T_Producer, T_Consumer>::bind (AVStreams::FDev_ptr peer_device, + AVStreams::QoS & the_qos, + CORBA::Boolean_out is_met, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::QoSRequestFailed)) +{ + ACE_UNUSED_ARG (peer_device); + ACE_UNUSED_ARG (the_qos); + ACE_UNUSED_ARG (is_met); + ACE_UNUSED_ARG (ACE_TRY_ENV); + return 0; +} + +template <class T_Producer, class T_Consumer> +// multicast is not supported yet. +AVStreams::FlowConnection_ptr +TAO_FDev<T_Producer, T_Consumer>::bind_mcast (AVStreams::FDev_ptr first_peer, + AVStreams::QoS & the_qos, + CORBA::Boolean_out is_met, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::QoSRequestFailed)) +{ + ACE_UNUSED_ARG (first_peer); + ACE_UNUSED_ARG (the_qos); + ACE_UNUSED_ARG (is_met); + ACE_UNUSED_ARG (ACE_TRY_ENV); + return 0; +} + +template <class T_Producer, class T_Consumer> +void +TAO_FDev<T_Producer, T_Consumer>::destroy (AVStreams::FlowEndPoint_ptr /* the_ep */, + const char * /* fdev_name */, + CORBA::Environment &/*ACE_TRY_ENV*/) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::notSupported)) +{ + // @@ Shouldn't the parameters be made use of! + // Destroy/delete all the producers and consumers. + PRODUCER_LIST_ITERATOR producer_list_iterator (this->producer_list_); + TAO_FlowProducer *producer_i = 0; + + while ((producer_i = producer_list_iterator.next ()) != 0) + { + deactivate_servant (producer_i); + delete producer_i; + } + + CONSUMER_LIST_ITERATOR consumer_list_iterator (this->consumer_list_); + TAO_FlowConsumer *consumer_i = 0; + + while ((consumer_i = consumer_list_iterator.next ()) != 0) + { + deactivate_servant (producer_i); + delete consumer_i; + } + int result = deactivate_servant (this); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_StreamEndPoint::destroy failed\n")); +} + +#endif /* TAO_AV_FLOWS_T_C */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Flows_T.h b/TAO/orbsvcs/orbsvcs/AV/Flows_T.h new file mode 100644 index 00000000000..268ce852846 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Flows_T.h @@ -0,0 +1,126 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// Flows_T.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_FLOWS_T_H +#define TAO_AV_FLOWS_T_H + +#include "AVStreams_i.h" + +template <class T_Producer, class T_Consumer> +class TAO_ORBSVCS_Export TAO_FDev : + public virtual POA_AVStreams::FDev, + public virtual TAO_PropertySet, + public virtual PortableServer::RefCountServantBase +{ +public: + TAO_FDev (void); + // default constructor + + TAO_FDev (const char *flowname); + // constructor taking a flowname. + + ~TAO_FDev (void); + // Destructor.. + + const char *flowname (void); + void flowname (const char *flowname); + // set/get the flowname. + AVStreams::FlowProducer_ptr create_producer (AVStreams::FlowConnection_ptr the_requester, + AVStreams::QoS & the_qos, + CORBA::Boolean_out met_qos, + char *& named_fdev, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, + AVStreams::notSupported, + AVStreams::QoSRequestFailed)); + // create a flow producer object. + + virtual AVStreams::FlowProducer_ptr make_producer (AVStreams::FlowConnection_ptr the_requester, + AVStreams::QoS & the_qos, + CORBA::Boolean_out met_qos, + char *& named_fdev, + CORBA::Environment &env = CORBA::Environment::default_environment ()); + // bridge method for the application to override the producer object + // creation. Default implementation creates a TAO_FlowProducer. + + virtual AVStreams::FlowConsumer_ptr create_consumer (AVStreams::FlowConnection_ptr the_requester, + AVStreams::QoS & the_qos, + CORBA::Boolean_out met_qos, + char *& named_fdev, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::streamOpDenied, + AVStreams::notSupported, + AVStreams::QoSRequestFailed)); + // create a flow consumer object. + + virtual AVStreams::FlowConsumer_ptr make_consumer (AVStreams::FlowConnection_ptr the_requester, + AVStreams::QoS & the_qos, + CORBA::Boolean_out met_qos, + char *& named_fdev, + CORBA::Environment &env = CORBA::Environment::default_environment ()); + // bridge method for the application to override the consumer object + // creation. Default implementation creates a TAO_FlowConsumer. + + virtual AVStreams::FlowConnection_ptr bind (AVStreams::FDev_ptr peer_device, + AVStreams::QoS & the_qos, + CORBA::Boolean_out is_met, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::QoSRequestFailed)); + // bind this FDev with another FDev. + + virtual AVStreams::FlowConnection_ptr bind_mcast (AVStreams::FDev_ptr first_peer, + AVStreams::QoS & the_qos, + CORBA::Boolean_out is_met, + CORBA::Environment &env = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::streamOpFailed, + AVStreams::QoSRequestFailed)); + // multicast bind is not implemented yet. + + virtual void destroy (AVStreams::FlowEndPoint_ptr the_ep, + const char * fdev_name, + CORBA::Environment &env = + CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + AVStreams::notSupported)); + // destroys this FDev. + +protected: + ACE_DLList <TAO_FlowProducer> producer_list_; + typedef ACE_DLList_Iterator <TAO_FlowProducer> PRODUCER_LIST_ITERATOR; + ACE_DLList <TAO_FlowConsumer> consumer_list_; + typedef ACE_DLList_Iterator <TAO_FlowConsumer> CONSUMER_LIST_ITERATOR; + CORBA::String_var flowname_; +}; + + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "Flows_T.cpp" +#endif /*ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Flows_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* TAO_AV_FLOWS_T_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/MCast.cpp b/TAO/orbsvcs/orbsvcs/AV/MCast.cpp new file mode 100644 index 00000000000..6deb81ea0af --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/MCast.cpp @@ -0,0 +1,207 @@ +// $Id$ + +#include "MCast.h" +#include "Nil.h" +#include "AVStreams_i.h" + +//------------------------------------------------------------ +//TAO_AV_UDP_MCast_Flow_Handler +//------------------------------------------------------------ + +TAO_AV_UDP_MCast_Flow_Handler::TAO_AV_UDP_MCast_Flow_Handler (void) +{ + ACE_NEW (transport_, + TAO_AV_UDP_MCast_Transport (this)); + ACE_NEW (dgram_mcast_, + ACE_SOCK_Dgram_Mcast); +} + +TAO_AV_UDP_MCast_Flow_Handler::~TAO_AV_UDP_MCast_Flow_Handler (void) +{ + delete this->transport_; + delete this->dgram_mcast_; +} + + +int +TAO_AV_UDP_MCast_Flow_Handler::handle_input (ACE_HANDLE /*fd*/) +{ + this->protocol_object_->handle_input (); + return 0; +} + +int +TAO_AV_UDP_MCast_Flow_Handler::handle_timeout (const ACE_Time_Value &tv, + const void *arg) +{ + return TAO_AV_Flow_Handler::handle_timeout (tv,arg); +} + +ACE_HANDLE +TAO_AV_UDP_MCast_Flow_Handler::get_handle (void) const +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_MCast_Flow_Handler::get_handle ")); + return this->get_mcast_socket ()->get_handle () ; +} + + +//------------------------------------------------------------ +// TAO_AV_UDP_MCast_Transport +//------------------------------------------------------------ + +TAO_AV_UDP_MCast_Transport::TAO_AV_UDP_MCast_Transport (void) + :handler_ (0) +{ +} + +TAO_AV_UDP_MCast_Transport::TAO_AV_UDP_MCast_Transport (TAO_AV_UDP_MCast_Flow_Handler *handler) + :handler_ (handler) +{ +} + +TAO_AV_UDP_MCast_Transport::~TAO_AV_UDP_MCast_Transport (void) +{ +} + +int +TAO_AV_UDP_MCast_Transport::open (ACE_Addr */*address*/) +{ + return 0; +} + +int +TAO_AV_UDP_MCast_Transport::close (void) +{ + return 0; +} + + +ACE_Addr* +TAO_AV_UDP_MCast_Transport::get_peer_addr (void) +{ + return &this->peer_addr_; +} + +ACE_Addr* +TAO_AV_UDP_MCast_Transport::get_local_addr (void) +{ + this->handler_->get_mcast_socket ()->get_local_addr (this->local_addr_); + return &this->local_addr_; +} + +ssize_t +TAO_AV_UDP_MCast_Transport::send (const ACE_Message_Block *mblk, ACE_Time_Value *) +{ + // For the most part this was copied from GIOP::send_request and + // friends. + + iovec iov[IOV_MAX]; + int iovcnt = 0; + ssize_t n = 0; + ssize_t nbytes = 0; + + for (const ACE_Message_Block *i = mblk; + i != 0; + i = i->cont ()) + { + // Make sure there is something to send! + if (i->length () > 0) + { + iov[iovcnt].iov_base = i->rd_ptr (); + iov[iovcnt].iov_len = i->length (); + iovcnt++; + + // The buffer is full make a OS call. @@ TODO this should + // be optimized on a per-platform basis, for instance, some + // platforms do not implement writev() there we should copy + // the data into a buffer and call send_n(). In other cases + // there may be some limits on the size of the iovec, there + // we should set IOV_MAX to that limit. + if (iovcnt == IOV_MAX) + { + n = this->handler_->get_mcast_socket ()->send ((const iovec *) iov, + iovcnt); + + if (n < 1) + return n; + + nbytes += n; + iovcnt = 0; + } + } + } + + // Check for remaining buffers to be sent! + if (iovcnt != 0) + { + n = this->handler_->get_mcast_socket ()->send ((const iovec *) iov, + iovcnt); + if (n < 1) + return n; + + nbytes += n; + } + + return nbytes; +} + +ssize_t +TAO_AV_UDP_MCast_Transport::send (const char *buf, + size_t len, + ACE_Time_Value *) +{ +// if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_MCast_Transport::send ")); +// char addr [BUFSIZ]; +// this->peer_addr_.addr_to_string (addr,BUFSIZ); +// if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"to %s\n",addr)); + + return this->handler_->get_mcast_socket ()->send (buf, len); +} + +ssize_t +TAO_AV_UDP_MCast_Transport::send (const iovec *iov, + int iovcnt, + ACE_Time_Value *) +{ + return this->handler_->get_mcast_socket ()->send (iov, + iovcnt, + 0); + +} + +ACE_INLINE int +TAO_AV_UDP_MCast_Transport::mtu (void) +{ + return ACE_MAX_DGRAM_SIZE; +} + + +ACE_INLINE ssize_t +TAO_AV_UDP_MCast_Transport::recv (char *buf, + size_t len, + ACE_Time_Value *) +{ + return this->handler_->get_mcast_socket ()->recv (buf, len,this->peer_addr_); +} + +ACE_INLINE ssize_t +TAO_AV_UDP_MCast_Transport::recv (char *buf, + size_t len, + int flags, + ACE_Time_Value *timeout) +{ + return this->handler_->get_mcast_socket ()->recv (buf, + len, + this->peer_addr_, + flags, + timeout); +} + + +ssize_t +TAO_AV_UDP_MCast_Transport::recv (iovec *iov, + int /*iovcnt*/, + ACE_Time_Value *timeout) +{ + return handler_->get_mcast_socket ()->recv (iov,this->peer_addr_,0,timeout); +} diff --git a/TAO/orbsvcs/orbsvcs/AV/MCast.h b/TAO/orbsvcs/orbsvcs/AV/MCast.h new file mode 100644 index 00000000000..530163eaa49 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/MCast.h @@ -0,0 +1,110 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// MCast.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_MCAST_H +#define TAO_AV_MCAST_H + +#include "FlowSpec_Entry.h" +#include "Protocol_Factory.h" +#include "ace/INET_Addr.h" +#include "ace/SOCK_Dgram_Mcast.h" + +class TAO_AV_UDP_MCast_Flow_Handler; + +class TAO_AV_UDP_MCast_Transport + :public TAO_AV_Transport +{ + // = TITLE + // A transport abstraction for Multicast dgram sockets. + // + // = DESCRIPTION + // Uses the ACE_SOCK_Dgram_Mcast to send the data. +public: + TAO_AV_UDP_MCast_Transport (void); + + TAO_AV_UDP_MCast_Transport (TAO_AV_UDP_MCast_Flow_Handler *handler); + + virtual ~TAO_AV_UDP_MCast_Transport (void); + + virtual int open (ACE_Addr *address); + + virtual int close (void); + + virtual int mtu (void); + + virtual ACE_Addr *get_peer_addr (void); + virtual ACE_Addr *get_local_addr (void); + virtual ssize_t send (const ACE_Message_Block *mblk, + ACE_Time_Value *s = 0); + // Write the complete Message_Block chain to the connection. + + virtual ssize_t send (const char *buf, + size_t len, + ACE_Time_Value *s = 0); + // Write the contents of the buffer of length len to the connection. + + virtual ssize_t send (const iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0); + // Write the contents of iovcnt iovec's to the connection. + + virtual ssize_t recv (char *buf, + size_t len, + ACE_Time_Value *s = 0); + // Read len bytes from into buf. + + virtual ssize_t recv (char *buf, + size_t len, + int flags, + ACE_Time_Value *s = 0); + // Read len bytes from into buf using flags. + + virtual ssize_t recv (iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0); + // Read received data into the iovec buffers. +protected: + TAO_AV_UDP_MCast_Flow_Handler *handler_; + ACE_INET_Addr peer_addr_; + ACE_INET_Addr local_addr_; +}; + +class TAO_AV_UDP_MCast_Flow_Handler + :public virtual TAO_AV_Flow_Handler, + public virtual ACE_Event_Handler +{ +public: + TAO_AV_UDP_MCast_Flow_Handler (void); + // Ctor + ~TAO_AV_UDP_MCast_Flow_Handler (void); + // Dtor + 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; } +protected: + ACE_INET_Addr peer_addr_; + ACE_SOCK_Dgram_Mcast *dgram_mcast_; +}; + +#if defined(__ACE_INLINE__) +#include "MCast.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_AV_MCAST_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/MCast.i b/TAO/orbsvcs/orbsvcs/AV/MCast.i new file mode 100644 index 00000000000..29ea2a73d4f --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/MCast.i @@ -0,0 +1,13 @@ +// $Id$ +//------------------------------------------------------------ +// TAO_AV_UDP_MCast_Flow_Handler +//----------------------------------------------------------- +ACE_INLINE ACE_SOCK_Dgram_Mcast * +TAO_AV_UDP_MCast_Flow_Handler::get_mcast_socket (void) const +{ + return this->dgram_mcast_; +} + + + + diff --git a/TAO/orbsvcs/orbsvcs/AV/Nil.cpp b/TAO/orbsvcs/orbsvcs/AV/Nil.cpp new file mode 100644 index 00000000000..d084789c6b3 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Nil.cpp @@ -0,0 +1,45 @@ +//$Id$ + +#include "Nil.h" +#include "FlowSpec_Entry.h" + +// //------------------------------------------------------------ +// // TAO_AV_UDP_MCast_Object +// //------------------------------------------------------------ + + +// TAO_AV_UDP_MCast_Object::TAO_AV_UDP_MCast_Object (TAO_AV_Callback *callback, +// TAO_AV_Transport *transport) +// :TAO_AV_Protocol_Object (callback,transport) +// { +// } + +// TAO_AV_UDP_MCast_Object::~TAO_AV_UDP_MCast_Object (void) +// { +// //no-op +// } + +// int +// TAO_AV_UDP_MCast_Object::send_frame (ACE_Message_Block *frame, +// TAO_AV_frame_info *frame_info) +// { +// int result = this->transport_->send (frame); +// if (result < 0) +// return result; +// return 0; +// } + +// int +// TAO_AV_UDP_MCast_Object::send_frame (const iovec *iov, +// int iovcnt, +// TAO_AV_frame_info *frame_info) +// { +// return this->transport_->send (iov,iovcnt); +// } + +// int +// TAO_AV_UDP_MCast_Object::end_stream (void) +// { +// this->callback_->handle_end_stream (); +// return 0; +// } diff --git a/TAO/orbsvcs/orbsvcs/AV/Nil.h b/TAO/orbsvcs/orbsvcs/AV/Nil.h new file mode 100644 index 00000000000..350b038ad07 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Nil.h @@ -0,0 +1,45 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// Nil.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_NIL_H +#define TAO_AV_NIL_H + +#include "Policy.h" + +// class TAO_ORBSVCS_Export TAO_AV_UDP_MCast_Object : public TAO_AV_Protocol_Object +// { +// public: +// TAO_AV_UDP_MCast_Object (TAO_AV_Callback *callback, +// TAO_AV_Transport *transport = 0); + +// virtual ~TAO_AV_UDP_MCast_Object (void); +// // Dtor + +// virtual int send_frame (ACE_Message_Block *frame, +// TAO_AV_frame_info *frame_info = 0); +// // send a data frame. + +// virtual int send_frame (const iovec *iov, +// int iovcnt, +// TAO_AV_frame_info *frame_info = 0); + +// virtual int end_stream (void); +// // end the stream. +// }; + +#endif /* TAO_AV_NIL_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Policy.cpp b/TAO/orbsvcs/orbsvcs/AV/Policy.cpp new file mode 100644 index 00000000000..eb86ba138fa --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Policy.cpp @@ -0,0 +1,148 @@ +// $Id$ + +#include "Policy.h" +#include "FlowSpec_Entry.h" + +TAO_AV_Policy::TAO_AV_Policy (CORBA::ULong type) + :type_ (type) +{ +} + + +TAO_AV_SSRC_Policy::TAO_AV_SSRC_Policy (CORBA::ULong ssrc) + :TAO_AV_Policy (TAO_AV_SSRC_POLICY), + ssrc_ (ssrc) +{ +} + + +TAO_AV_Payload_Type_Policy::TAO_AV_Payload_Type_Policy (int payload_type) + :TAO_AV_Policy (TAO_AV_PAYLOAD_TYPE_POLICY), + payload_type_ (payload_type) +{ +} + +// TAO_AV_RTP_Sdes_Policy +TAO_AV_RTCP_Sdes_Policy::TAO_AV_RTCP_Sdes_Policy (void) + :TAO_AV_Policy (TAO_AV_RTCP_SDES_POLICY) +{ +} + +TAO_AV_SFP_Credit_Policy::TAO_AV_SFP_Credit_Policy (void) + :TAO_AV_Policy (TAO_AV_SFP_CREDIT_POLICY) +{ +} + +// TAO_AV_Callback +TAO_AV_Callback::TAO_AV_Callback (void) + :protocol_object_ (0) +{ +} + +int +TAO_AV_Callback::open (TAO_AV_Protocol_Object *object, + TAO_AV_Flow_Handler *handler) +{ + this->protocol_object_ = object; + this->handler_ = handler; + handler->callback (this); + return 0; +} + +int +TAO_AV_Callback::handle_start (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Callback::handle_start\n")); + return -1; +} + +int +TAO_AV_Callback::handle_stop (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Callback::handle_stop\n")); + return -1; +} + +int +TAO_AV_Callback::receive_frame (ACE_Message_Block */*frame*/, + TAO_AV_frame_info *, + const ACE_Addr &) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Callback::receive_frame\n")); + return -1; +} + +int +TAO_AV_Callback::receive_control_frame (ACE_Message_Block *, + const ACE_Addr& ) +{ + return 0; +} + +int +TAO_AV_Callback::handle_destroy (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Callback::handle_end_stream\n")); + return -1; +} + +void +TAO_AV_Callback::get_timeout (ACE_Time_Value *&tv, + void *&arg) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Callback::get_timeout\n")); +} + +int +TAO_AV_Callback::handle_timeout (void *arg) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Callback::handle_timeout\n")); + return 0; +} + +TAO_AV_PolicyList +TAO_AV_Callback::get_policies (void) +{ + TAO_AV_PolicyList list; + return list; +} + +// TAO_AV_Transport* +// TAO_AV_Callback::transport (void) +// { +// return this->transport_; +// } + +// void +// TAO_AV_Callback::transport (TAO_AV_Transport *transport) +// { +// this->transport_ = transport; +// } + +TAO_AV_Protocol_Object* +TAO_AV_Callback::protocol_object (void) +{ + return this->protocol_object_; +} + +// void +// TAO_AV_Callback::protocol_object (TAO_AV_Protocol_Object *object) +// { +// this->protocol_object_ = object; +// } + +int +TAO_AV_Callback::schedule_timer (void) +{ + return this->handler_->schedule_timer (); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +template class TAO_Unbounded_Sequence<TAO_AV_Policy*>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate TAO_Unbounded_Sequence<TAO_AV_Policy*> + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Policy.h b/TAO/orbsvcs/orbsvcs/AV/Policy.h new file mode 100644 index 00000000000..cefec9b2725 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Policy.h @@ -0,0 +1,163 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// Policy.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_POLICY_H +#define TAO_AV_POLICY_H + +#include "ace/Addr.h" +#include "tao/TAO.h" +#include "tao/debug.h" +#include "orbsvcs/orbsvcs_export.h" + +struct TAO_AV_frame_info +{ + CORBA::Boolean boundary_marker; + CORBA::Octet format; + // @@ Shouldn't this be a string. + CORBA::ULong timestamp; + CORBA::ULong ssrc; + CORBA::ULong sequence_num; +}; + +#define TAO_AV_SSRC_POLICY 100 +#define TAO_AV_PAYLOAD_TYPE_POLICY 101 +#define TAO_AV_TIMEOUT_POLICY 102 +#define TAO_AV_RTCP_SDES_POLICY 103 +#define TAO_AV_SFP_CREDIT_POLICY 104 + +struct TAO_AV_RTCP_Sdes +{ + CORBA::String_var name_; + CORBA::String_var value_; +}; + +class TAO_ORBSVCS_Export TAO_AV_Policy +{ +public: + TAO_AV_Policy (CORBA::ULong type); + CORBA::ULong type (void); +protected: + CORBA::ULong type_; +}; + +class TAO_AV_SSRC_Policy + :public TAO_AV_Policy +{ +public: + TAO_AV_SSRC_Policy (CORBA::ULong ssrc = 0); + CORBA::ULong value (void); + void value (CORBA::ULong ssrc); +protected: + CORBA::ULong ssrc_; +}; + +class TAO_AV_Payload_Type_Policy + :public TAO_AV_Policy +{ +public: + TAO_AV_Payload_Type_Policy (int payload_type = -1); + int value (void); + void value (int pt); +protected: + int payload_type_; +}; + + +class TAO_AV_RTCP_Sdes_Policy + :public TAO_AV_Policy +{ +public: + TAO_AV_RTCP_Sdes_Policy (void); + TAO_AV_RTCP_Sdes &value (void); + void value (const TAO_AV_RTCP_Sdes& sdes_val); +protected: + TAO_AV_RTCP_Sdes sdes_; +}; + +class TAO_AV_SFP_Credit_Policy : public TAO_AV_Policy +{ +public: + TAO_AV_SFP_Credit_Policy (void); + int value (void); + void value (int val); +protected: + int value_; +}; + +typedef TAO_Unbounded_Sequence<TAO_AV_Policy*> TAO_AV_PolicyList; + +class TAO_AV_Protocol_Object; +class TAO_AV_Transport; +class TAO_AV_Flow_Handler; + +class TAO_AV_Callback +{ + // = TITLE + // Callback class that the user will be implementing for receiving + // frames from the network and also for timer events. +public: + TAO_AV_Callback (void); + + int open (TAO_AV_Protocol_Object *object, + TAO_AV_Flow_Handler *handler); + // Called for opening the callback. + + virtual int handle_start (void); + // Called during Streamctrl->start. + + virtual int handle_stop (void); + // Called during Streamctrl->stop. + + virtual int handle_timeout (void *arg); + // Called during timeout for Flow Producers. + + virtual int schedule_timer (void); + + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0, + const ACE_Addr &address = ACE_Addr::sap_any); + + // Called when a frame arrives for a FlowConsumer. + + virtual int receive_control_frame (ACE_Message_Block *frame, + const ACE_Addr &address = ACE_Addr::sap_any); + // address from which the frame was received. + + virtual int handle_destroy (void); + // Called during Streamctrl->destroy i.e tear_down of the stream + + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); + // Called to get the timeout. If tv is 0 then the framework stop + // calling this. This will be called during the start of the frame + // and also if schedule_timer is called to get the timeout. + + TAO_AV_Protocol_Object *protocol_object (void); + // Accessor to protocol object. + + virtual TAO_AV_PolicyList get_policies (void); + // get the policies for the protocol object. +protected: + TAO_AV_Protocol_Object *protocol_object_; + TAO_AV_Flow_Handler *handler_; +}; + +#if defined(__ACE_INLINE__) +#include "Policy.i" +#endif /* __ACE_INLINE__ */ +#endif /* TAO_AV_POLICY_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Policy.i b/TAO/orbsvcs/orbsvcs/AV/Policy.i new file mode 100644 index 00000000000..0994186e6ed --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Policy.i @@ -0,0 +1,75 @@ +/* -*- C++ -*- */ +// $Id$ +//-------------------------------------------------- +// TAO_AV_Policy +//-------------------------------------------------- + +ACE_INLINE CORBA::ULong +TAO_AV_Policy::type (void) +{ + return this->type_; +} + +//-------------------------------------------------- +// TAO_AV_SSRC_Policy +//-------------------------------------------------- + +ACE_INLINE CORBA::ULong +TAO_AV_SSRC_Policy::value (void) +{ + return this->ssrc_; +} + + +ACE_INLINE void +TAO_AV_SSRC_Policy::value (CORBA::ULong ssrc) +{ + this->ssrc_ = ssrc; +} + +//-------------------------------------------------- +// TAO_AV_Payload_Type_Policy +//-------------------------------------------------- +ACE_INLINE void +TAO_AV_Payload_Type_Policy::value (int pt) +{ + this->payload_type_ = pt; +} + +ACE_INLINE int +TAO_AV_Payload_Type_Policy::value (void) +{ + return this->payload_type_; +} + + +// TAO_AV_RTCP_Sdes_Policy +ACE_INLINE TAO_AV_RTCP_Sdes & +TAO_AV_RTCP_Sdes_Policy::value (void) +{ + return this->sdes_; +} + +ACE_INLINE void +TAO_AV_RTCP_Sdes_Policy::value (const TAO_AV_RTCP_Sdes &sdes_val) +{ + this->sdes_ = sdes_val; +} + +//---------------------------------------------------------------------- +// TAO_AV_SFP_Credit_Policy +//---------------------------------------------------------------------- + +ACE_INLINE +void +TAO_AV_SFP_Credit_Policy::value (int credit) +{ + this->value_ = credit; +} + +ACE_INLINE +int +TAO_AV_SFP_Credit_Policy::value (void) +{ + return this->value_; +} diff --git a/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp b/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp new file mode 100644 index 00000000000..ea6bf89ddda --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.cpp @@ -0,0 +1,157 @@ +// $Id$ + + +#include "Protocol_Factory.h" +#include "ace/Dynamic_Service.h" + +TAO_AV_Transport_Factory::TAO_AV_Transport_Factory (void) +{ +} + +TAO_AV_Transport_Factory::~TAO_AV_Transport_Factory (void) +{ +} + +int +TAO_AV_Transport_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return -1; +} + +int +TAO_AV_Transport_Factory::match_protocol (const char * /* protocol_string */) +{ + return 0; +} + +TAO_AV_Acceptor * +TAO_AV_Transport_Factory::make_acceptor (void) +{ + return 0; +} + +TAO_AV_Connector * +TAO_AV_Transport_Factory::make_connector (void) +{ + return 0; +} + +// TAO_AV_Flow_Protocol_Factory +TAO_AV_Flow_Protocol_Factory::TAO_AV_Flow_Protocol_Factory (void) +{ +} + +TAO_AV_Flow_Protocol_Factory::~TAO_AV_Flow_Protocol_Factory (void) +{ +} + +TAO_AV_Flow_Protocol_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return -1; +} + +int +TAO_AV_Flow_Protocol_Factory::match_protocol (const char * /* protocol_string */) +{ + return 0; +} + +TAO_AV_Protocol_Object* +TAO_AV_Flow_Protocol_Factory::make_protocol_object (TAO_FlowSpec_Entry * /* entry */, + TAO_Base_StreamEndPoint * /* endpoint */ , + TAO_AV_Flow_Handler * /* handler */, + TAO_AV_Transport * /* transport */) +{ + return 0; +} + +const char * +TAO_AV_Flow_Protocol_Factory::control_flow_factory (void) +{ + return 0; +} + +//---------------------------------------------------------------------- +// TAO_AV_Protocol_Object +//---------------------------------------------------------------------- +TAO_AV_Protocol_Object::TAO_AV_Protocol_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport) + :transport_ (transport), + callback_ (callback) +{ +} + +int +TAO_AV_Protocol_Object::open (TAO_AV_Callback *callback, + TAO_AV_Transport *transport) +{ + this->callback_ = callback; + this->transport_ = transport; + return 0; +} + +TAO_AV_Protocol_Object::~TAO_AV_Protocol_Object (void) +{ + //no-op +} + +int +TAO_AV_Protocol_Object::start (void) +{ + return this->callback_->handle_start (); +} + +int +TAO_AV_Protocol_Object::stop (void) +{ + return this->callback_->handle_stop (); +} + +int +TAO_AV_Protocol_Object::set_policies (const TAO_AV_PolicyList &policy_list) +{ + this->policy_list_ = policy_list; + return 0; +} + +TAO_AV_PolicyList +TAO_AV_Protocol_Object::get_policies (void) +{ + return this->policy_list_; +} + +TAO_AV_Transport* +TAO_AV_Protocol_Object::transport (void) +{ + return this->transport_; +} + +// void +// TAO_AV_Protocol_Object::transport (TAO_AV_Transport *transport) +// { +// this->transport_ = transport; +// } + +void +TAO_AV_Protocol_Object::control_object (TAO_AV_Protocol_Object * /* object */) +{ + return; +} + +int +TAO_AV_Protocol_Object::handle_control_input (ACE_Message_Block *, + const ACE_Addr &) +{ + ACE_DEBUG ((LM_DEBUG,"TAO_AV_Protocol_Object::handle_control_input\n")); + return 0; +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Dynamic_Service<TAO_AV_Transport_Factory>; +template class ACE_Dynamic_Service<TAO_AV_Flow_Protocol_Factory>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Dynamic_Service<TAO_AV_Transport_Factory> +#pragma instantiate ACE_Dynamic_Service<TAO_AV_Flow_Protocol_Factory> +#endif diff --git a/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.h b/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.h new file mode 100644 index 00000000000..53c22530af8 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Protocol_Factory.h @@ -0,0 +1,100 @@ +/* -*- C++ -*- */ + +// $Id$ +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// Protocol_Factory +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_PROTOCOL_FACTORY_T_H +#define TAO_AV_PROTOCOL_FACTORY_T_H + +#include "ace/Service_Object.h" +#include "Policy.h" +#include "FlowSpec_Entry.h" + +class TAO_ORBSVCS_Export TAO_AV_Transport_Factory : public ACE_Service_Object +{ +public: + TAO_AV_Transport_Factory (void); + virtual ~TAO_AV_Transport_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *protocol_string); + virtual TAO_AV_Acceptor *make_acceptor (void); + virtual TAO_AV_Connector *make_connector (void); +}; + +class TAO_AV_Protocol_Object +{ +public: + TAO_AV_Protocol_Object (void); + + TAO_AV_Protocol_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport); + // constructor. + + virtual ~TAO_AV_Protocol_Object (void); + // Destructor + + virtual int open (TAO_AV_Callback *callback, + TAO_AV_Transport *transport); + + virtual int handle_input (void) = 0; + + virtual int handle_control_input (ACE_Message_Block *control_frame, + const ACE_Addr &peer_address); + // Called on a control object. + + virtual int set_policies (const TAO_AV_PolicyList &policy_list); + virtual TAO_AV_PolicyList get_policies (void); + // set/get policies. + + virtual int start (void); + virtual int stop (void); + // start/stop the flow. + + virtual int send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0) = 0; + // send a data frame. + + virtual int send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info = 0) = 0; + // send a frame in iovecs. + + virtual void control_object (TAO_AV_Protocol_Object *object); + virtual int destroy (void) = 0; + // end the stream. + TAO_AV_Transport *transport (void); +protected: + TAO_AV_Transport *transport_; + TAO_AV_PolicyList policy_list_; + TAO_AV_Callback *callback_; +}; + +class TAO_ORBSVCS_Export TAO_AV_Flow_Protocol_Factory : public ACE_Service_Object +{ +public: + TAO_AV_Flow_Protocol_Factory (void); + virtual ~TAO_AV_Flow_Protocol_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *flow_string); + virtual TAO_AV_Protocol_Object* make_protocol_object (TAO_FlowSpec_Entry *entry, + TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Flow_Handler *handler, + TAO_AV_Transport *transport); + virtual const char *control_flow_factory (void); +}; + +#endif /* TAO_AV_PROTOCOL_FACTORY_T_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP.cpp b/TAO/orbsvcs/orbsvcs/AV/RTCP.cpp new file mode 100644 index 00000000000..41145960d59 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP.cpp @@ -0,0 +1,931 @@ +/* + * 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 "ntp-time.h" +#include "RTCP.h" +#include "media-timer.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) +{ + 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 +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) + { + if (*note) + { + nameslot = RTCP_SDES_NOTE; + noteslot = RTCP_SDES_NAME; + } else + { + nameslot = RTCP_SDES_NAME; + noteslot = RTCP_SDES_NOTE; + } + } + 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); +} + +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")); +} + +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 = (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; + + s->lts_ctrl (ACE_OS::gettimeofday ()); + s->sts_ctrl (ntohl (sr->sr_ntp.upper) << 16 | + ntohl (sr->sr_ntp.lower) >> 16); + + int cnt = flags >> 8 & 0x1f; + parse_rr_records (ssrc, (rtcp_rr*) (sr + 1), cnt, ep, addr); +} + +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; + + s->lts_ctrl (ACE_OS::gettimeofday ()); + int cnt = flags >> 8 & 0x1f; + parse_rr_records (ssrc, (rtcp_rr*) (rh + 1), cnt, ep, addr); +} + +int +TAO_AV_RTCP::sdesbody (ACE_UINT32* p, + u_char* ep, + TAO_AV_Source* ps, + ACE_UINT32 addr, + ACE_UINT32 ssrc, + TAO_AV_SourceManager *source_manager) +{ + TAO_AV_Source* s; + ACE_UINT32 srcid = *p; + if (ps->srcid () != 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 ()); + + u_char* cp = (u_char*) (p + 1); + while (cp < ep) + { + char buf[256]; + + 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 (type >= RTCP_SDES_MIN && type <= RTCP_SDES_MAX) + { + memcpy (buf, (char*)&cp[2], len); + buf[len] = 0; + s->sdes (type, buf); + } + else + /*XXX*/; + + 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); +} + +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; + + while (--cnt >= 0) + { + 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; + } +} + +/*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 = (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 = (rtcp_rr*) (sr + 1); + } else { + flags |= RTCP_PT_RR; + rr = (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 ( (rtcphdr*)rr, s); + else + len += build_sdes ( (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 (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) + { + 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; + + /* + * 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; + } + switch (flags & 0xff) { + + case RTCP_PT_SR: + TAO_AV_RTCP::parse_sr (rh, flags, ep, ps, addr, source_manager); + break; + + case RTCP_PT_RR: + TAO_AV_RTCP::parse_rr (rh, flags, ep, ps, addr, source_manager); + break; + + case RTCP_PT_SDES: + TAO_AV_RTCP::parse_sdes (rh, flags, ep, ps, addr, ssrc, source_manager); + break; + + case RTCP_PT_BYE: + TAO_AV_RTCP::parse_bye (rh, flags, ep, ps, source_manager); + break; + + default: + ps->badsessopt (1); + break; + } + rh = (rtcphdr*)ep; + } + return 0; +} + +ACE_UINT32 +TAO_AV_RTCP::alloc_srcid (ACE_UINT32 addr) +{ + timeval tv; + ::gettimeofday(&tv, 0); + ACE_UINT32 srcid = ACE_UINT32 (tv.tv_sec + tv.tv_usec); + srcid += (ACE_UINT32)getuid(); + srcid += (ACE_UINT32)getpid(); + srcid += addr; + return (srcid); +} + + +// TAO_AV_RTCP_Flow_Factory +TAO_AV_RTCP_Flow_Factory::TAO_AV_RTCP_Flow_Factory (void) +{ +} + +TAO_AV_RTCP_Flow_Factory::~TAO_AV_RTCP_Flow_Factory (void) +{ +} + +int +TAO_AV_RTCP_Flow_Factory::match_protocol (const char *flow_string) +{ + if (ACE_OS::strncasecmp (flow_string,"RTCP",4) == 0) + return 1; + return 0; +} + +int +TAO_AV_RTCP_Flow_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return 0; +} + +TAO_AV_Protocol_Object* +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_Protocol_Object *object = 0; + ACE_NEW_RETURN (object, + TAO_AV_RTCP_Object (callback, + transport), + 0); + callback->open (object, + handler); + return object; +} + +// TAO_AV_RTCP_Object +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); + 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); + ACE_Addr *peer_addr = this->transport_->get_peer_addr (); + this->callback_->receive_control_frame (data,*peer_addr); + return 0; +} + +int +TAO_AV_RTCP_Object::send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info) +{ + return this->transport_->send (frame); +} + +int +TAO_AV_RTCP_Object::send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info) +{ + return this->transport_->send (iov, + iovcnt); +} + +TAO_AV_RTCP_Object::TAO_AV_RTCP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport) + :TAO_AV_Protocol_Object (callback,transport) +{ +} + +TAO_AV_RTCP_Object::~TAO_AV_RTCP_Object (void) +{ +} + +int +TAO_AV_RTCP_Object::destroy (void) +{ + this->callback_->handle_destroy (); + return 0; +} + +int +TAO_AV_RTCP_Object::set_policies (const TAO_AV_PolicyList &policy_list) +{ + return -1; +} + +int +TAO_AV_RTCP_Object::start (void) +{ + return this->callback_->handle_start (); +} + +int +TAO_AV_RTCP_Object::stop (void) +{ + return this->callback_->handle_stop (); +} + +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) +{ + ACE_NEW (source_manager_, + TAO_AV_SourceManager (this)); + + ACE_NEW (this->state_, + TAO_AV_RTP_State); +} + +TAO_AV_RTCP_Callback::~TAO_AV_RTCP_Callback (void) +{ +} + +TAO_AV_SourceManager* +TAO_AV_RTCP_Callback::source_manager (void) +{ + return this->source_manager_; +} + +TAO_AV_RTP_State* +TAO_AV_RTCP_Callback::state (void) +{ + return this->state_; +} + +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; +} + +void +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(fmod(double(ACE_OS::rand ()), rint) + rint * .5 + .5); + return 0; +} + +int +TAO_AV_RTCP_Callback::handle_stop (void) +{ + return 0; +} + +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 0; +} + +void +TAO_AV_RTCP_Callback::get_timeout (ACE_Time_Value *&tv, + void *&arg) +{ + // Here we do the RTCP timeout calculation. + ACE_NEW (tv, + ACE_Time_Value (0,this->timeout_*ACE_ONE_SECOND_IN_MSECS)); +} + +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; +} + +int +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; + + frame->rd_ptr (sizeof (TAO_AV_RTP::rtphdr)); + int result = this->demux (rh, + frame, + peer_address); + frame->rd_ptr (buf); + + if (result < 0) + return result; + + return 0; +} + + +int +TAO_AV_RTCP_Callback::receive_control_frame (ACE_Message_Block *frame, + const ACE_Addr &peer_address) +{ + // 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); + return 0; +} + +int +TAO_AV_RTCP_Callback::demux (TAO_AV_RTP::rtphdr* rh, + ACE_Message_Block *data, + const ACE_Addr &address) +{ + 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); + + int 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). + */ +} + +ACE_FACTORY_DEFINE (AV, TAO_AV_RTCP_Flow_Factory) +ACE_STATIC_SVC_DEFINE (TAO_AV_RTCP_Flow_Factory, + ASYS_TEXT ("RTCP_Flow_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_AV_RTCP_Flow_Factory), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) diff --git a/TAO/orbsvcs/orbsvcs/AV/RTCP.h b/TAO/orbsvcs/orbsvcs/AV/RTCP.h new file mode 100644 index 00000000000..1e128cf708b --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTCP.h @@ -0,0 +1,296 @@ +/* -*- 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. + */ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// RTCP.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_RTCP_H +#define TAO_AV_RTCP_H + +#include "ace/OS.h" +#include "source.h" +#include "AVStreams_i.h" +#include "UDP.h" +#include <math.h> +#include <stdlib.h> +#include "RTP.h" + +// TAO_AV_RTP_State +class 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_; +}; + +class TAO_AV_RTCP_Callback; +class TAO_AV_SourceManager; + +class TAO_AV_RTCP +{ +public: + struct rtcphdr + { + ACE_UINT16 rh_flags; /* T:2 P:1 CNT:5 PT:8 */ + ACE_UINT16 rh_len; /* length of message (in bytes) */ + ACE_UINT32 rh_ssrc; /* synchronization src id */ + }; + + struct ntp64 + { + 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 ACE_UINT32 alloc_srcid (ACE_UINT32 addr); +}; + +class TAO_AV_Callback; + +class TAO_ORBSVCS_Export TAO_AV_RTCP_Object : public TAO_AV_Protocol_Object +{ +public: + TAO_AV_RTCP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport = 0); + // constructor. + + virtual ~TAO_AV_RTCP_Object (void); + // Destructor + + virtual int handle_input (void); + virtual int handle_control_input (ACE_Message_Block *frame, + const ACE_Addr &peer_address); + + virtual int set_policies (const TAO_AV_PolicyList &policy_list); + // set/get policies. + + virtual int start (void); + virtual int stop (void); + // start/stop the flow. + + virtual int send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0); + // send a data frame. + + virtual int send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info = 0); + // send a frame in iovecs. + + virtual int destroy (void); + // end the stream. +}; + + +class TAO_ORBSVCS_Export TAO_AV_RTCP_Flow_Factory + :public TAO_AV_Flow_Protocol_Factory +{ +public: + TAO_AV_RTCP_Flow_Factory (void); + virtual ~TAO_AV_RTCP_Flow_Factory (void); + virtual int init (int argc, char *argv[]); + virtual int match_protocol (const char *flow_string); + virtual TAO_AV_Protocol_Object* make_protocol_object (TAO_FlowSpec_Entry *entry, + TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Flow_Handler *handler, + TAO_AV_Transport *transport); +}; + +class TAO_ORBSVCS_Export TAO_AV_RTCP_Callback : public TAO_AV_Callback +{ +public: + TAO_AV_RTCP_Callback (void); + // RTCP callback. + + virtual ~TAO_AV_RTCP_Callback (void); + // virtual destructor. + + virtual int handle_start (void); + // Called during Streamctrl->start. + + virtual int handle_stop (void); + // Called during Streamctrl->stop. + + virtual int handle_timeout (void *arg); + // Called during timeout for Flow Producers. + + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0, + const ACE_Addr &peer_address = ACE_Addr::sap_any); + // Called when a frame arrives for a FlowConsumer. + + virtual int receive_control_frame (ACE_Message_Block *frame, + const ACE_Addr &peer_address = ACE_Addr::sap_any); + + virtual int handle_destroy (void); + // Called during Streamctrl->destroy i.e tear_down of the stream + // @@coryan:Call it handle_destroy or handle_close. + + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); + // Called to get the timeout. If tv is 0 then the framework stop + // calling this. + + 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); + void schedule (int ms); + TAO_AV_SourceManager *source_manager (void); + TAO_AV_RTP_State *state (void); +protected: + TAO_AV_SourceManager *source_manager_; + TAO_AV_RTP_State *state_; + int timeout_; +}; + +ACE_STATIC_SVC_DECLARE (TAO_AV_RTCP_Flow_Factory) +ACE_FACTORY_DECLARE (TAO_ORBSVCS, TAO_AV_RTCP_Flow_Factory) + +#endif /* TAO_AV_RTCP_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/RTP.cpp b/TAO/orbsvcs/orbsvcs/AV/RTP.cpp new file mode 100644 index 00000000000..b3e97a8a67b --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTP.cpp @@ -0,0 +1,344 @@ +/* + * 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 "RTP.h" +#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) + { + // state->bad_version_++; + ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP:bad version\n"),-1); + } + 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; +} + + +ACE_INLINE +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; +} + +// TAO_AV_RTP_Object + +int +TAO_AV_RTP_Object::handle_input (void) +{ + TAO_AV_frame_info *frame_info = 0; + + // 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; + this->control_object_->handle_control_input (data, + *addr); + + this->frame_.rd_ptr (sizeof(TAO_AV_RTP::rtphdr)); + result = this->callback_->receive_frame (&this->frame_, + frame_info, + *addr); + + return 0; +} + +int +TAO_AV_RTP_Object::send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info) +{ + TAO_AV_RTP::rtphdr header; + int result = -1; + 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_; + } + else + { + result = TAO_AV_RTP::write_header (header, + 0, + this->sequence_num_, + 0, + 0, + 0); + } + if (result < 0) + return result; + + ACE_Message_Block mb ((char *)&header, + sizeof (header)); + mb.wr_ptr (sizeof (header)); + mb.cont (frame); + result = this->transport_->send (&mb); + if (result < 0) + ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::send_frame failed\n"),result); + return 0; +} + +int +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; + 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_; + } + else + { + result = TAO_AV_RTP::write_header (header, + 0, + this->sequence_num_, + 0, + 0, + 0); + } + if (result < 0) + return result; + + 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); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_RTP::send_frame failed\n"),result); + return 0; +} + +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->frame_.size (2 * this->transport_->mtu ()); +} + +TAO_AV_RTP_Object::~TAO_AV_RTP_Object (void) +{ +} + +int +TAO_AV_RTP_Object::destroy (void) +{ + this->control_object_->destroy (); + this->callback_->handle_destroy (); + return 0; +} + +int +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]; + switch (policy->type ()) + { + case TAO_AV_PAYLOAD_TYPE_POLICY: + { + TAO_AV_Payload_Type_Policy *payload_policy = + ACE_static_cast (TAO_AV_Payload_Type_Policy *,policy); + if (payload_policy == 0) + ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP_Object::send_frame:Payload policy not defined\n"),-1); + this->format_ = payload_policy->value (); + } + break; + case TAO_AV_SSRC_POLICY: + { + TAO_AV_SSRC_Policy *ssrc_policy = + ACE_static_cast (TAO_AV_SSRC_Policy *,policy); + if (ssrc_policy == 0) + ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP_Object::send_frame:SSRC policy not defined\n"),-1); + this->ssrc_ = ssrc_policy->value ();; + } + break; + default: + break; + } + } +} + +void +TAO_AV_RTP_Object::control_object (TAO_AV_Protocol_Object *object) +{ + this->control_object_ = object; +} + +int +TAO_AV_RTP_Object::start (void) +{ + this->control_object_->start (); + return this->callback_->handle_start (); +} + +int +TAO_AV_RTP_Object::stop (void) +{ + this->control_object_->stop (); + return this->callback_->handle_stop (); +} + +// TAO_AV_RTP_Flow_Factory +TAO_AV_RTP_Flow_Factory::TAO_AV_RTP_Flow_Factory (void) +{ +} + +TAO_AV_RTP_Flow_Factory::~TAO_AV_RTP_Flow_Factory (void) +{ +} + +int +TAO_AV_RTP_Flow_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return 0; +} + +TAO_AV_Protocol_Object* +TAO_AV_RTP_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_callback (entry->flowname (), + callback); + + TAO_AV_Protocol_Object *object = 0; + ACE_NEW_RETURN (object, + TAO_AV_RTP_Object (callback, + transport), + 0); + callback->open (object, + handler); + endpoint->set_protocol_object (entry->flowname (), + object); + return object; +} + +int +TAO_AV_RTP_Flow_Factory::match_protocol (const char *flow_string) +{ + if (ACE_OS::strncasecmp (flow_string,"RTP",3) == 0) + return 1; + return 0; +} + +const char * +TAO_AV_RTP_Flow_Factory::control_flow_factory (void) +{ + return "RTCP"; +} + +ACE_FACTORY_DEFINE (AV, TAO_AV_RTP_Flow_Factory) +ACE_STATIC_SVC_DEFINE (TAO_AV_RTP_Flow_Factory, + ASYS_TEXT ("RTP_Flow_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (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 new file mode 100644 index 00000000000..a6de439f594 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/RTP.h @@ -0,0 +1,299 @@ +/* -*- C++ -*- */ + +/*- + * 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. + */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// RTP.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_RTP_H +#define TAO_AV_RTP_H + +#include "Protocol_Factory.h" + +#define RTP_PT_BVC 22 /* Berkeley video codec */ + +/* RTP standard content encodings for video */ +#define RTP_PT_RGB8 23 /* 8-bit dithered RGB */ +#define RTP_PT_HDCC 24 /* SGI proprietary */ +#define RTP_PT_CELLB 25 /* Sun CellB */ +#define RTP_PT_JPEG 26 /* JPEG */ +#define RTP_PT_CUSEEME 27 /* Cornell CU-SeeMe */ +#define RTP_PT_NV 28 /* Xerox PARC nv */ +#define RTP_PT_PICW 29 /* BB&N PictureWindow */ +#define RTP_PT_CPV 30 /* Concept/Bolter/Viewpoint codec */ +#define RTP_PT_H261 31 /* ITU H.261 */ +#define RTP_PT_MPEG 32 /* MPEG-I & MPEG-II */ +#define RTP_PT_MP2T 33 /* MPEG-II either audio or video */ + +/* backward compat hack for decoding RTPv1 ivs streams */ +#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 + + +/* Offset from UNIX's epoch to the NTP epoch in seconds (NTP's JAN_1970) */ +#define RTP_EPOCH_OFFSET 2208988800UL +#define RTP_VERSION 2 + +#define RTP_M 0x0080 /* Marker: significant event <e.g. frame boundary> */ +#define RTP_P 0x2000 /* Padding is present */ +#define RTP_X 0x1000 /* Extension Header is present */ + + +#define RTCP_PT_SR 200 /* sender report */ +#define RTCP_PT_RR 201 /* receiver report */ +#define RTCP_PT_SDES 202 /* source description */ +#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) */ +#define RTCP_SDES_PHONE 4 /* telephone # (optional) */ +#define RTCP_SDES_LOC 5 /* geographical location */ +#define RTCP_SDES_TOOL 6 /* name/(vers) of app */ +#define RTCP_SDES_NOTE 7 /* transient messages */ +#define RTCP_SDES_PRIV 8 /* private SDES extensions */ +#define RTCP_PT_BYE 203 /* end of participation */ +#define RTCP_PT_APP 204 /* application specific functions */ + +#define RTCP_SDES_MIN 1 + + +/* + * Parameters controling the RTCP report rate timer. + */ +#define RTCP_SESSION_BW_FRACTION (0.05) +#define RTCP_MIN_RPT_TIME (5.) +#define RTCP_SENDER_BW_FRACTION (0.25) +#define RTCP_RECEIVER_BW_FRACTION (1. - RTCP_SENDER_BW_FRACTION) +#define RTCP_SIZE_GAIN (1./8.) + +/* + * Largest (user-level) packet size generated by our rtp applications. + * Individual video formats may use smaller mtu's. + */ +#define RTP_MTU 1024 + +#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 +//------------------------------------------------------------ + + +class TAO_AV_RTP +{ +public: + /* Basic RTP header */ + struct rtphdr + { + ACE_UINT16 rh_flags; /* T:2 P:1 X:1 CC:4 M:1 PT:7 */ + ACE_UINT16 rh_seqno; /* sequence number */ + ACE_UINT32 rh_ts; /* media-specific time stamp */ + ACE_UINT32 rh_ssrc; /* synchronization src id */ + /* data sources follow per cc */ + }; + + /* + * Motion JPEG encapsulation. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MBZ | frag offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Q | Width | Height | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Type = Index into a table of predefined JPEG parameters + * Width = Width of input in 8-pixel blocks + * Height = Height of input in 8-pixel blocks + * Q = Quality factor (0-100 = std, >100 = custom) + * Frag offset = The byte offset into the frame for the data in + * this packet + */ + struct jpeghdr + { + ACE_UINT32 off; /* fragment offset */ + unsigned char type; /* id of jpeg decoder params */ + unsigned char q; /* quantization factor (or table id) */ + unsigned char width; /* 1/8 frame width */ + unsigned char height; /* 1/8 frame height */ + }; + + /* + * NV encapsulation. + */ + struct nvhdr + { + ACE_UINT16 width; + ACE_UINT16 height; + /* nv data */ + }; + + /* + * CellB encapsulation. + */ + struct cellbhdr + { + ACE_UINT16 x; + ACE_UINT16 y; + ACE_UINT16 width; + ACE_UINT16 height; + /* cells */ + }; + + /* + * H.261 encapsulation. + * See Internet draft. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |SBIT |EBIT |I|V| GOBN | MBAP | QUANT | HMVD | VMVD | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#ifdef notdef + struct h261hdr + { + ACE_UINT16 flags; + ACE_UINT16 off; + }; +#endif + + struct bvchdr + { + unsigned char version; + unsigned char pad; + unsigned char width; + unsigned char height; + ACE_UINT32 quant; + unsigned char sbit; + unsigned char ebit; + ACE_UINT16 blkno; + }; + + static int handle_input (ACE_Message_Block *&data, + TAO_AV_frame_info *&frame_info); + + static int write_header (rtphdr &header, + int format, + ACE_UINT16 &sequence_num, + ACE_UINT32 ts, + ACE_UINT32 ssrc, + CORBA::Boolean boundary_marker); + +}; + + +class TAO_AV_RTP_Object : public TAO_AV_Protocol_Object +{ +public: + TAO_AV_RTP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport); + + virtual ~TAO_AV_RTP_Object (void); + + virtual int start (void); + virtual int stop (void); + virtual int handle_input (void); + virtual int send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0); + + virtual int send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info = 0); + + virtual int destroy (void); + virtual int set_policies (const TAO_AV_PolicyList &policy_list); + virtual void control_object (TAO_AV_Protocol_Object *object); + +protected: + ACE_UINT16 sequence_num_; + int format_; + CORBA::ULong ssrc_; + TAO_AV_Protocol_Object *control_object_; + + ACE_Message_Block frame_; + // Pre-allocated memory to receive the data... +}; + +class TAO_ORBSVCS_Export TAO_AV_RTP_Flow_Factory : public TAO_AV_Flow_Protocol_Factory +{ +public: + TAO_AV_RTP_Flow_Factory (void); + virtual ~TAO_AV_RTP_Flow_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *flow_string); + virtual TAO_AV_Protocol_Object* make_protocol_object (TAO_FlowSpec_Entry *entry, + TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Flow_Handler *handler, + TAO_AV_Transport *transport); + virtual const char*control_flow_factory (void); +}; + +ACE_STATIC_SVC_DECLARE (TAO_AV_RTP_Flow_Factory) +ACE_FACTORY_DECLARE (TAO_ORBSVCS, TAO_AV_RTP_Flow_Factory) + +#endif /* TAO_AV_RTP_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/TCP.cpp b/TAO/orbsvcs/orbsvcs/AV/TCP.cpp new file mode 100644 index 00000000000..a8a99fef6dd --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/TCP.cpp @@ -0,0 +1,677 @@ +// $Id$ + +#include "TCP.h" +#include "AVStreams_i.h" + +//------------------------------------------------------------ +// TAO_AV_TCP_Transport +//------------------------------------------------------------ + +TAO_AV_TCP_Transport::TAO_AV_TCP_Transport (void) + :handler_ (0) +{ +} + +TAO_AV_TCP_Transport::TAO_AV_TCP_Transport (TAO_AV_TCP_Flow_Handler *handler) + :handler_ (handler) +{ +} + +TAO_AV_TCP_Transport::~TAO_AV_TCP_Transport (void) +{ +} + +int +TAO_AV_TCP_Transport::open (ACE_Addr */*address*/) +{ + return 0; +} + +int +TAO_AV_TCP_Transport::close (void) +{ + return 0; +} + +int +TAO_AV_TCP_Transport::mtu (void) +{ + return -1; +} + +ACE_Addr* +TAO_AV_TCP_Transport::get_peer_addr (void) +{ + return 0; +} + +ssize_t +TAO_AV_TCP_Transport::send (const ACE_Message_Block *mblk, ACE_Time_Value *) +{ + // For the most part this was copied from GIOP::send_request and + // friends. + + iovec iov[IOV_MAX]; + int iovcnt = 0; + ssize_t n = 0; + ssize_t nbytes = 0; + + for (const ACE_Message_Block *i = mblk; + i != 0; + i = i->cont ()) + { + // Make sure there is something to send! + if (i->length () > 0) + { + iov[iovcnt].iov_base = i->rd_ptr (); + iov[iovcnt].iov_len = i->length (); + iovcnt++; + + // The buffer is full make a OS call. @@ TODO this should + // be optimized on a per-platform basis, for instance, some + // platforms do not implement writev() there we should copy + // the data into a buffer and call send_n(). In other cases + // there may be some limits on the size of the iovec, there + // we should set IOV_MAX to that limit. + if (iovcnt == IOV_MAX) + { + n = this->handler_->peer ().sendv_n ((const iovec *) iov, + iovcnt); + if (n < 1) + return n; + + nbytes += n; + iovcnt = 0; + } + } + } + + // Check for remaining buffers to be sent! + if (iovcnt != 0) + { + n = this->handler_->peer ().sendv_n ((const iovec *) iov, + iovcnt); + if (n < 1) + return n; + + nbytes += n; + } + + return nbytes; +} + +ssize_t +TAO_AV_TCP_Transport::send (const char *buf, + size_t len, + ACE_Time_Value *) +{ + return this->handler_->peer ().send_n (buf, len); +} + +ssize_t +TAO_AV_TCP_Transport::send (const iovec *iov, + int iovcnt, + ACE_Time_Value *) +{ + return this->handler_->peer ().sendv_n ((const iovec *) iov, + iovcnt); +} + +ssize_t +TAO_AV_TCP_Transport::recv (char *buf, + size_t len, + ACE_Time_Value *) +{ + return this->handler_->peer ().recv (buf, len); +} + +ssize_t +TAO_AV_TCP_Transport::recv (char *buf, + size_t len, + int flags, + ACE_Time_Value *) +{ + return this->handler_->peer ().recv (buf, + len, + flags); +} + +ssize_t +TAO_AV_TCP_Transport::recv (iovec *iov, + int iovcnt, + ACE_Time_Value *) +{ + return handler_->peer ().recvv_n (iov, iovcnt); +} + +//------------------------------------------------------------ +// TAO_AV_TCP_Protocol_Factory +//------------------------------------------------------------ + +TAO_AV_TCP_Factory::TAO_AV_TCP_Factory (void) +{ +} + +TAO_AV_TCP_Factory::~TAO_AV_TCP_Factory (void) +{ +} + +int +TAO_AV_TCP_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return 0; +} + +int +TAO_AV_TCP_Factory::match_protocol (const char *protocol_string) +{ + if (ACE_OS::strcasecmp (protocol_string,"TCP") == 0) + return 1; + return 0; +} + +TAO_AV_Acceptor* +TAO_AV_TCP_Factory::make_acceptor (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Factory::make_acceptor ")); + TAO_AV_Acceptor *acceptor = 0; + ACE_NEW_RETURN (acceptor, + TAO_AV_TCP_Acceptor, + 0); + return acceptor; +} + +TAO_AV_Connector* +TAO_AV_TCP_Factory::make_connector (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Factory::make_connector ")); + TAO_AV_Connector *connector = 0; + ACE_NEW_RETURN (connector, + TAO_AV_TCP_Connector, + 0); + return connector; +} + +//------------------------------------------------------------ +// TAO_AV_TCP_Object +//------------------------------------------------------------ + +int +TAO_AV_TCP_Object::handle_input (void) +{ + int n = this->transport_->recv (this->frame_.rd_ptr (), + this->frame_.size ()); + if (n == -1) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_Flow_Handler::handle_input recv failed\n"),-1); + if (n == 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_Flow_Handler::handle_input connection closed\n"),-1); + this->frame_.wr_ptr (this->frame_.rd_ptr () + n); + + return this->callback_->receive_frame (&this->frame_); +} + +int +TAO_AV_TCP_Object::send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info) +{ + int result = this->transport_->send (frame); + if (result < 0) + return result; + return 0; +} + +int +TAO_AV_TCP_Object::send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info) +{ + return this->transport_->send (iov,iovcnt); +} + +TAO_AV_TCP_Object::TAO_AV_TCP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport) + :TAO_AV_Protocol_Object (callback,transport) +{ + // @@ Is this a good size? + this->frame_.size (BUFSIZ); +} + +TAO_AV_TCP_Object::~TAO_AV_TCP_Object (void) +{ + // No-op +} +int +TAO_AV_TCP_Object::destroy (void) +{ + this->callback_->handle_destroy (); + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_TCP_Flow_Factory +//------------------------------------------------------------ +TAO_AV_TCP_Flow_Factory::TAO_AV_TCP_Flow_Factory (void) +{ +} + +TAO_AV_TCP_Flow_Factory::~TAO_AV_TCP_Flow_Factory (void) +{ +} + +int +TAO_AV_TCP_Flow_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return 0; +} + +int +TAO_AV_TCP_Flow_Factory::match_protocol (const char *flow_string) +{ + if (ACE_OS::strcasecmp (flow_string,"TCP") == 0) + return 1; + return 0; +} + +TAO_AV_Protocol_Object* +TAO_AV_TCP_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_callback (entry->flowname (), + callback); + + TAO_AV_TCP_Object *object = 0; + ACE_NEW_RETURN (object, + TAO_AV_TCP_Object (callback, + transport), + 0); + callback->open (object, + handler); + endpoint->set_protocol_object (entry->flowname (), + object); + return object; +} + +//------------------------------------------------------------ +// TAO_AV_TCP_Base_Connector +//------------------------------------------------------------ + +int +TAO_AV_TCP_Base_Connector::connector_open (TAO_AV_TCP_Connector *connector, + ACE_Reactor *reactor) +{ + this->connector_ = connector; + this->reactor_ = reactor; + + int result = ACE_Connector <TAO_AV_TCP_Flow_Handler,ACE_SOCK_CONNECTOR>::open (reactor); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_Base_Connector::open failed\n"),-1); + return 0; +} + +int +TAO_AV_TCP_Base_Connector::make_svc_handler (TAO_AV_TCP_Flow_Handler *&tcp_handler) +{ + int result = + this->connector_->make_svc_handler (tcp_handler); + if (result < 0) + return result; + tcp_handler->reactor (this->reactor_); + return 0; +} + +int +TAO_AV_TCP_Base_Connector::connector_connect (TAO_AV_TCP_Flow_Handler *&handler, + const ACE_INET_Addr &remote_addr) +{ + int result = ACE_Connector <TAO_AV_TCP_Flow_Handler,ACE_SOCK_CONNECTOR>::connect (handler, + remote_addr); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_Base_Connector::connect failed\n"),-1); + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_TCP_Connector +//------------------------------------------------------------ +TAO_AV_TCP_Connector::TAO_AV_TCP_Connector (void) +{ +} + +TAO_AV_TCP_Connector::~TAO_AV_TCP_Connector (void) +{ +} + +int +TAO_AV_TCP_Connector::make_svc_handler (TAO_AV_TCP_Flow_Handler *&tcp_handler) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Connector::make_svc_handler\n")); + TAO_AV_Callback *callback = 0; + if (this->endpoint_ != 0) + { +// this->endpoint_->get_callback (this->flowname_.c_str (), +// callback); + ACE_NEW_RETURN (tcp_handler, + // TAO_AV_TCP_Flow_Handler (callback), + TAO_AV_TCP_Flow_Handler, + -1); + TAO_AV_Protocol_Object *object = + this->flow_protocol_factory_->make_protocol_object (this->entry_, + this->endpoint_, + tcp_handler, + tcp_handler->transport ()); + tcp_handler->protocol_object (object); + // callback->protocol_object (object); +// this->endpoint_->set_protocol_object (this->flowname_.c_str (), +// object); + this->endpoint_->set_handler (this->flowname_.c_str (),tcp_handler); + this->entry_->protocol_object (object); + this->entry_->handler (tcp_handler); + } + return 0; +} + +int +TAO_AV_TCP_Connector::open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_Flow_Protocol_Factory *factory) + +{ + this->endpoint_ = endpoint; + this->flow_protocol_factory_ = factory; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Connector::open ")); + int result = this->connector_.connector_open(this, + av_core->reactor ()); + return result; +} + +int +TAO_AV_TCP_Connector::connect (TAO_FlowSpec_Entry *entry, + TAO_AV_Transport *&transport) +{ + this->entry_ = entry; + this->flowname_ = entry->flowname (); + ACE_Addr *remote_addr = entry->address (); + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr *,remote_addr); + TAO_AV_TCP_Flow_Handler *handler; + 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); + entry->handler (handler); + transport = handler->transport (); + return 0; +} + +int +TAO_AV_TCP_Connector::close (void) +{ + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_TCP_Base_Connector +//------------------------------------------------------------ + +int +TAO_AV_TCP_Base_Acceptor::open (TAO_AV_TCP_Acceptor *acceptor, + ACE_Reactor *reactor, + const ACE_INET_Addr &local_addr, + TAO_FlowSpec_Entry *entry) +{ + this->acceptor_ = acceptor; + this->reactor_ = reactor; + this->entry_ = entry; + + int result = ACE_Acceptor <TAO_AV_TCP_Flow_Handler,ACE_SOCK_ACCEPTOR>::open (local_addr,reactor); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_Base_Connector::open failed\n"),-1); + return 0; +} + +int +TAO_AV_TCP_Base_Acceptor::make_svc_handler (TAO_AV_TCP_Flow_Handler *&handler) +{ + int result = this->acceptor_->make_svc_handler (handler); + if (result < 0) + return result; + handler->reactor (this->reactor_); + this->entry_->handler (handler); + return 0; +} + + +//------------------------------------------------------------ +// TAO_AV_TCP_Acceptor +//------------------------------------------------------------ + +TAO_AV_TCP_Acceptor::TAO_AV_TCP_Acceptor (void) +{ +} + +TAO_AV_TCP_Acceptor::~TAO_AV_TCP_Acceptor (void) +{ +} + +int +TAO_AV_TCP_Acceptor::make_svc_handler (TAO_AV_TCP_Flow_Handler *&tcp_handler) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Acceptor::make_svc_handler\n")); + // TAO_AV_Callback *callback = 0; + if (this->endpoint_ != 0) + { +// this->endpoint_->get_callback (this->flowname_.c_str (), +// callback); + ACE_NEW_RETURN (tcp_handler, + // TAO_AV_TCP_Flow_Handler (callback), + TAO_AV_TCP_Flow_Handler, + -1); + TAO_AV_Protocol_Object *object = +// this->flow_protocol_factory_->make_protocol_object (callback, +// tcp_handler->transport ()); + this->flow_protocol_factory_->make_protocol_object (this->entry_, + this->endpoint_, + tcp_handler, + tcp_handler->transport ()); + tcp_handler->protocol_object (object); + // callback->protocol_object (object); +// this->endpoint_->set_protocol_object (this->flowname_.c_str (), +// object); + this->endpoint_->set_handler (this->flowname_.c_str (),tcp_handler); + this->entry_->protocol_object (object); + this->entry_->handler (tcp_handler); + } + return 0; +} + +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) +{ + this->flow_protocol_factory_ = factory; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Acceptor::open ")); + this->av_core_ = av_core; + this->endpoint_ = endpoint; + this->entry_ = entry; + this->flowname_ = entry->flowname (); + ACE_Addr *address = entry->address (); + ACE_INET_Addr *inet_addr = (ACE_INET_Addr *) address; + inet_addr->set (inet_addr->get_port_number (), + inet_addr->get_host_name ()); + char buf[BUFSIZ]; + inet_addr->addr_to_string (buf, + BUFSIZ); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Acceptor::open: %s", + buf)); + int result = this->acceptor_.open (this, + av_core->reactor (), + *inet_addr, + entry); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_Acceptor::open failed"),-1); + entry->set_local_addr (address); + return 0; +} + +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) +{ + this->flow_protocol_factory_ = factory; + this->av_core_ = av_core; + this->endpoint_ = endpoint; + this->entry_ = entry; + this->flowname_ = entry->flowname (); + ACE_INET_Addr *address; + ACE_NEW_RETURN (address, + ACE_INET_Addr ("0"), + -1); + int result = this->acceptor_.open (this, + av_core->reactor (), + *address, + entry); + + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_TCP_Acceptor::open failed"),-1); + this->acceptor_.acceptor ().get_local_addr (*address); + address->set (address->get_port_number (), + address->get_host_name ()); + char buf[BUFSIZ]; + address->addr_to_string (buf,BUFSIZ); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_TCP_Acceptor::open_default: %s\n",buf)); + entry->set_local_addr (address); + return 0; +} + + +int +TAO_AV_TCP_Acceptor::close (void) +{ + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_TCP_Flow_Handler +//------------------------------------------------------------ + +TAO_AV_TCP_Flow_Handler::TAO_AV_TCP_Flow_Handler (TAO_AV_Callback *callback) + // :TAO_AV_Flow_Handler (callback) +{ + ACE_NEW (this->transport_, + TAO_AV_TCP_Transport (this)); +} + +TAO_AV_Transport * +TAO_AV_TCP_Flow_Handler::transport (void) +{ + return this->transport_; +} + +int +TAO_AV_TCP_Flow_Handler::open (void *arg) +{ + + int nodelay = 1; + +#if defined (TCP_NODELAY) + if (this->peer ().set_option (IPPROTO_TCP, + TCP_NODELAY, + (void *) &nodelay, + sizeof (nodelay)) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "NODELAY failed\n"), + -1); +#endif /* TCP_NODELAY */ + + // Called by the <Strategy_Acceptor> when the handler is completely + // connected. + ACE_INET_Addr addr; + + if (this->peer ().get_remote_addr (addr) == -1) + return -1; + + char server[MAXHOSTNAMELEN + 16]; + + (void) addr.addr_to_string (server, sizeof (server)); + + if (TAO_debug_level > 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, + "(%P|%t) connection to server <%s> on %d\n", + server, this->peer ().get_handle ())); + + this->peer ().enable (ACE_NONBLOCK); + // Register the handler with the reactor. + if (this->reactor () + && this->reactor ()->register_handler + (this, + ACE_Event_Handler::READ_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ASYS_TEXT ("%p\n"), + ASYS_TEXT ("unable to register client handler")), + -1); +} + +int +TAO_AV_TCP_Flow_Handler::handle_input (ACE_HANDLE /*fd*/) +{ + return this->protocol_object_->handle_input (); +} + +int +TAO_AV_TCP_Flow_Handler::handle_timeout (const ACE_Time_Value &tv, + const void *arg) +{ + return TAO_AV_Flow_Handler::handle_timeout (tv,arg); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Acceptor<TAO_AV_TCP_Flow_Handler, ACE_SOCK_ACCEPTOR>; +template class ACE_Connector<TAO_AV_TCP_Flow_Handler, ACE_SOCK_CONNECTOR>; + +template class ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler>; +template class ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *>; +template class ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX>; +template class ACE_Map_Iterator_Base<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX>; +template class ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX>; +template class ACE_Map_Reverse_Iterator<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Acceptor<TAO_AV_TCP_Flow_Handler, ACE_SOCK_Acceptor, ACE_INET_Addr> +#pragma instantiate ACE_Connector<TAO_AV_TCP_Flow_Handler, ACE_SOCK_Connector, ACE_INET_Addr> + +#pragma instantiate ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> +#pragma instantiate ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *> +#pragma instantiate ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX> +#pragma instantiate ACE_Map_Iterator_Base<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX> +#pragma instantiate ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX> +#pragma instantiate ACE_Map_Reverse_Iterator<ACE_HANDLE, ACE_Svc_Tuple<TAO_AV_TCP_Flow_Handler> *, ACE_SYNCH_RW_MUTEX> + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +ACE_STATIC_SVC_DEFINE (TAO_AV_TCP_Flow_Factory, + ASYS_TEXT ("TCP_Flow_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_AV_TCP_Flow_Factory), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) + +ACE_FACTORY_DEFINE (AV, TAO_AV_TCP_Flow_Factory) + +ACE_STATIC_SVC_DEFINE (TAO_AV_TCP_Factory, + ASYS_TEXT ("TCP_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_AV_TCP_Factory), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) + +ACE_FACTORY_DEFINE (AV, TAO_AV_TCP_Factory) diff --git a/TAO/orbsvcs/orbsvcs/AV/TCP.h b/TAO/orbsvcs/orbsvcs/AV/TCP.h new file mode 100644 index 00000000000..da9b2d37c04 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/TCP.h @@ -0,0 +1,236 @@ +/* -*- C++ -*- */ + +// $Id$ +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// TCP.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#if !defined TAO_AV_TCP_H +#define TAO_AV_TCP_H + +#include "ace/OS.h" +#include "Protocol_Factory.h" +#include "FlowSpec_Entry.h" + +class TAO_ORBSVCS_Export TAO_AV_TCP_Factory : public TAO_AV_Transport_Factory +{ +public: + TAO_AV_TCP_Factory (void); + virtual ~TAO_AV_TCP_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *protocol_string); + virtual TAO_AV_Acceptor *make_acceptor (void); + virtual TAO_AV_Connector *make_connector (void); +}; + +class TAO_AV_TCP_Flow_Handler; + +class TAO_AV_TCP_Transport + :public TAO_AV_Transport +{ + // = TITLE + // A transport abstraction for socket streams. + // + // = DESCRIPTION + // Uses the ACE_SOCK_Stream to send the data. +public: + TAO_AV_TCP_Transport (void); + + TAO_AV_TCP_Transport (TAO_AV_TCP_Flow_Handler *handler); + + virtual ~TAO_AV_TCP_Transport (void); + + virtual int open (ACE_Addr *address); + + virtual int close (void); + + virtual int mtu (void); + + virtual ACE_Addr *get_peer_addr (void); + + virtual ssize_t send (const ACE_Message_Block *mblk, + ACE_Time_Value *s = 0); + // Write the complete Message_Block chain to the connection. + + virtual ssize_t send (const char *buf, + size_t len, + ACE_Time_Value *s = 0); + // Write the contents of the buffer of length len to the connection. + + virtual ssize_t send (const iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0); + // Write the contents of iovcnt iovec's to the connection. + + virtual ssize_t recv (char *buf, + size_t len, + ACE_Time_Value *s = 0); + // Read len bytes from into buf. + + virtual ssize_t recv (char *buf, + size_t len, + int flags, + ACE_Time_Value *s = 0); + // Read len bytes from into buf using flags. + + virtual ssize_t recv (iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0); + // Read received data into the iovec buffers. +protected: + TAO_AV_TCP_Flow_Handler *handler_; +}; + +class TAO_AV_TCP_Flow_Handler + :public virtual TAO_AV_Flow_Handler, + public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> +{ +public: + TAO_AV_TCP_Flow_Handler (TAO_AV_Callback *callback = 0); + virtual TAO_AV_Transport *transport (void); + virtual int open (void * = 0); + virtual int handle_input (ACE_HANDLE fd); + virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0); + virtual ACE_Event_Handler* event_handler (void){ return this; } +protected: + TAO_AV_Core *av_core_; +}; + +class TAO_AV_TCP_Acceptor; + +class TAO_AV_TCP_Base_Acceptor :public ACE_Acceptor <TAO_AV_TCP_Flow_Handler,ACE_SOCK_ACCEPTOR> +{ +public: + virtual int open (TAO_AV_TCP_Acceptor *acceptor, + ACE_Reactor *reactor, + const ACE_INET_Addr &local_addr, + TAO_FlowSpec_Entry *entry); + virtual int make_svc_handler (TAO_AV_TCP_Flow_Handler *& handler); +protected: + TAO_AV_TCP_Acceptor *acceptor_; + ACE_Reactor *reactor_; + TAO_FlowSpec_Entry *entry_; +}; + +class TAO_AV_TCP_Acceptor :public TAO_AV_Acceptor +{ +public: + TAO_AV_TCP_Acceptor (void); + virtual ~TAO_AV_TCP_Acceptor (void); + + virtual int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_FlowSpec_Entry *entry, + TAO_AV_Flow_Protocol_Factory *factory); + + virtual int open_default (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_FlowSpec_Entry *entry, + TAO_AV_Flow_Protocol_Factory *factory); + + virtual int close (void); + virtual int make_svc_handler (TAO_AV_TCP_Flow_Handler *&handler); +protected: + TAO_AV_TCP_Base_Acceptor acceptor_; + TAO_FlowSpec_Entry *entry_; + TAO_Base_StreamEndPoint *endpoint_; + TAO_AV_Flow_Protocol_Factory *flow_protocol_factory_; +}; + +class TAO_AV_TCP_Connector; + +class TAO_AV_TCP_Base_Connector : public ACE_Connector <TAO_AV_TCP_Flow_Handler,ACE_SOCK_CONNECTOR> +{ +public: + // To avoid warnings of open and connect hiding the base class functions these have to renamed. + int connector_open (TAO_AV_TCP_Connector *connector, + ACE_Reactor *reactor); + int connector_connect (TAO_AV_TCP_Flow_Handler *&handler, + const ACE_INET_Addr &remote_addr); + virtual int make_svc_handler (TAO_AV_TCP_Flow_Handler *& handler); +protected: + TAO_AV_TCP_Connector *connector_; + ACE_Reactor *reactor_; +}; + +class TAO_AV_TCP_Connector : public TAO_AV_Connector +{ +public: + TAO_AV_TCP_Connector (void); + virtual ~TAO_AV_TCP_Connector (void); + + virtual int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_Flow_Protocol_Factory *factory); + + virtual int connect (TAO_FlowSpec_Entry *entry, + TAO_AV_Transport *&transport); + virtual int close (void); + virtual int make_svc_handler (TAO_AV_TCP_Flow_Handler *&handler); +protected: + TAO_AV_Core *av_core_; + TAO_AV_TCP_Base_Connector connector_; + TAO_Base_StreamEndPoint *endpoint_; + TAO_FlowSpec_Entry *entry_; + TAO_AV_Flow_Protocol_Factory *flow_protocol_factory_; +}; + +class TAO_ORBSVCS_Export TAO_AV_TCP_Object : public TAO_AV_Protocol_Object +{ +public: + TAO_AV_TCP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport = 0); + + virtual ~TAO_AV_TCP_Object (void); + // Dtor + + virtual int handle_input (void); + + virtual int send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0); + // send a data frame. + + virtual int send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info = 0); + + virtual int destroy (void); + // end the stream. + +private: + ACE_Message_Block frame_; + // Pre-allocated memory to receive the data... +}; + +class TAO_AV_TCP_Flow_Factory : public TAO_AV_Flow_Protocol_Factory +{ +public: + TAO_AV_TCP_Flow_Factory (void); + virtual ~TAO_AV_TCP_Flow_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *flow_string); + TAO_AV_Protocol_Object* make_protocol_object (TAO_FlowSpec_Entry *entry, + TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Flow_Handler *handler, + TAO_AV_Transport *transport); +}; + +ACE_STATIC_SVC_DECLARE (TAO_AV_TCP_Flow_Factory) +ACE_FACTORY_DECLARE (TAO_ORBSVCS, TAO_AV_TCP_Flow_Factory) + +ACE_STATIC_SVC_DECLARE (TAO_AV_TCP_Factory) +ACE_FACTORY_DECLARE (TAO_ORBSVCS, TAO_AV_TCP_Factory) + +#endif /* TAO_AV_TCP_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Transport.cpp b/TAO/orbsvcs/orbsvcs/AV/Transport.cpp new file mode 100644 index 00000000000..eea7446020b --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Transport.cpp @@ -0,0 +1,1249 @@ +// $Id$ +#include "tao/TAO.h" +#include "AVStreams_i.h" +#include "sfp.h" +#include "MCast.h" +#include "Nil.h" +#include "RTP.h" +#include "RTCP.h" +#include "UDP.h" +#include "TCP.h" +#include "FlowSpec_Entry.h" + +#if !defined (__ACE_INLINE__) +#include "Transport.i" +#endif /* __ACE_INLINE__ */ + +//------------------------------------------------------------ +// TAO_AV_Core +//------------------------------------------------------------ + +TAO_AV_Core::TAO_AV_Core (void) + :connector_registry_ (0), + acceptor_registry_ (0) +{ +} + +TAO_AV_Core::~TAO_AV_Core (void) +{ + delete this->connector_registry_; + delete this->acceptor_registry_; +} + +int +TAO_AV_Core::init (int &argc, + char *argv [], + CORBA::Environment &env) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Core::init ")); + // Init the orb manager. + int result = this->orb_manager_.init (argc,argv,env); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"orb_manager::init"),result); + ACE_NEW_RETURN (this->connector_registry_, + TAO_AV_Connector_Registry, + -1); + ACE_NEW_RETURN (this->acceptor_registry_, + TAO_AV_Acceptor_Registry, + -1); + this->orb_ = this->orb_manager_.orb (); + this->reactor (this->orb_->orb_core ()->reactor ()); + this->init_transport_factories (); + this->init_flow_protocol_factories (); + return 0; +} + +int +TAO_AV_Core::init_forward_flows (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_FlowSpecSet &flow_spec_set, + TAO_AV_Core::EndPoint direction, + AVStreams::flowSpec &flow_spec) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Core::init_forward_flows\n")); + TAO_AV_FlowSpecSet address_flow_set; + TAO_AV_FlowSpecSet flow_set; + TAO_AV_FlowSpecSetItor end = flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor start = flow_spec_set.begin (); + start != end; ++start) + { + TAO_FlowSpec_Entry *entry = (*start); + switch (direction) + { + case TAO_AV_Core::TAO_AV_ENDPOINT_B: + { + switch (entry->direction ()) + { + case TAO_FlowSpec_Entry::TAO_AV_DIR_IN: + entry->role (TAO_FlowSpec_Entry::TAO_AV_CONSUMER); + break; + case TAO_FlowSpec_Entry::TAO_AV_DIR_OUT: + entry->role (TAO_FlowSpec_Entry::TAO_AV_PRODUCER); + break; + } + } + default: + break; + } + ACE_Addr *address = entry->address (); + if (address != 0) + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"address given for flow %s",entry->flowname ())); + address_flow_set.insert (entry); + } + else + flow_set.insert (entry); + } + int result = -1; + switch (direction) + { + case TAO_AV_Core::TAO_AV_ENDPOINT_A: + if (address_flow_set.size () > 0) + { + result = this->acceptor_registry_->open (endpoint, + this, + address_flow_set); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_Core::init_forward_flows::acceptor_registry::open failed\n"),-1); + TAO_AV_FlowSpecSetItor end = address_flow_set.end (); + for (TAO_AV_FlowSpecSetItor start = address_flow_set.begin (); + start != end; ++start) + { + TAO_FlowSpec_Entry *entry = (*start); + switch (entry->direction ()) + { + case TAO_FlowSpec_Entry::TAO_AV_DIR_IN: + { + if (entry->handler () != 0) + { + // For IN flows on the A side we should remove the handlers from the reactor. + ACE_Event_Handler *event_handler = entry->handler ()->event_handler (); + result = event_handler->reactor ()->remove_handler (event_handler, + ACE_Event_Handler::READ_MASK); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Core::init_forward_flows: remove_handler failed\n")); + } + } + default: + break; + } + // Now if the address_set has been changed due to the addition of a control entry we should + // add that to the flow_spec_set also. + if (flow_spec_set.find (entry) < 0) + { + // entry doesn't exist so add it. + flow_spec_set.insert (entry); +// size_t len = flow_spec.length (); +// flow_spec.length (len+1); +// flow_spec [len] = entry->entry_to_string (); + } + } + } + break; + case TAO_AV_Core::TAO_AV_ENDPOINT_B: + { + if (address_flow_set.size () > 0) + { + result = this->connector_registry_->open (endpoint, + this, + address_flow_set); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_Core::init_Forward_flows: connector_registry open failed\n"),-1); + TAO_AV_FlowSpecSetItor end = address_flow_set.end (); + for (TAO_AV_FlowSpecSetItor start = address_flow_set.begin (); + start != end; ++start) + { + TAO_FlowSpec_Entry *entry = (*start); + switch (entry->direction ()) + { + case TAO_FlowSpec_Entry::TAO_AV_DIR_OUT: + { + if (entry->handler () != 0) + { + // @@Naga: This wont be called in the case of Full Profile. + // For IN flows on the A side we should remove the handlers from the reactor. + ACE_Event_Handler *event_handler = entry->handler ()->event_handler (); + result = event_handler->reactor ()->remove_handler (event_handler, + ACE_Event_Handler::READ_MASK); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Core::init_forward_flows: remove_handler failed\n")); + } + } + default: + break; + } + // Now if the address_set has been changed due to the addition of a control entry we should + // add that to the flow_spec_set also. + if (flow_spec_set.find (entry) < 0) + { + // entry doesn't exist so add it. + flow_spec_set.insert (entry); + } + } + } + if (flow_set.size () > 0) + { + result = this->acceptor_registry_->open (endpoint, + this, + flow_set); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_Core::init_Forward_flows: Acceptor_registry open failed\n"),-1); + TAO_AV_FlowSpecSetItor end = address_flow_set.end (); + for (TAO_AV_FlowSpecSetItor start = address_flow_set.begin (); + start != end; ++start) + { + TAO_FlowSpec_Entry *entry = (*start); + switch (entry->direction ()) + { + case TAO_FlowSpec_Entry::TAO_AV_DIR_OUT: + { + if (entry->handler () != 0) + { + // For IN flows on the A side we should remove the handlers from the reactor. + ACE_Event_Handler *event_handler = entry->handler ()->event_handler (); + result = event_handler->reactor ()->remove_handler (event_handler, + ACE_Event_Handler::READ_MASK); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Core::init_forward_flows: remove_handler failed\n")); + } + } + default: + break; + } + // Now if the address_set has been changed due to the addition of a control entry we should + // add that to the flow_spec_set also. + if (flow_spec_set.find (entry) < 0) + { + // entry doesn't exist so add it. + flow_spec_set.insert (entry); + } + } + } + + AVStreams::flowSpec new_flowspec (flow_spec_set.size ()); + int i=0; + TAO_AV_FlowSpecSetItor connect_end = address_flow_set.end (); + TAO_AV_FlowSpecSetItor connect = address_flow_set.begin (); + for (;connect != connect_end; ++connect) + { + ACE_Addr *local_addr; + local_addr = (*connect)->get_local_addr (); + if (result == 0) + { + TAO_Reverse_FlowSpec_Entry entry ((*connect)->flowname (), + (*connect)->direction_str (), + (*connect)->format (), + (*connect)->flow_protocol_str (), + (*connect)->carrier_protocol_str (), + local_addr); + + int len = new_flowspec.length (); + if (i == len) + new_flowspec.length (len+1); + new_flowspec [i++] = entry.entry_to_string (); + } + } + connect_end = flow_set.end (); + for (connect = flow_set.begin (); + connect != connect_end; ++connect) + { + ACE_Addr *local_addr; + local_addr = (*connect)->get_local_addr (); + if (result == 0) + { + TAO_Reverse_FlowSpec_Entry entry ((*connect)->flowname (), + (*connect)->direction_str (), + (*connect)->format (), + (*connect)->flow_protocol_str (), + (*connect)->carrier_protocol_str (), + local_addr); + + int len = new_flowspec.length (); + if (i == len) + new_flowspec.length (len+1); + new_flowspec [i++] = entry.entry_to_string (); + } + } + // Change the reverse flow spec to be sent. + flow_spec = new_flowspec; + } + break; + default: + break; + } + return 0; +} + +int +TAO_AV_Core::init_reverse_flows (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_FlowSpecSet &forward_flow_spec_set, + TAO_AV_FlowSpecSet &reverse_flow_spec_set, + TAO_AV_Core::EndPoint direction) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)TAO_AV_Core::init_reverse_flows\n")); + TAO_AV_FlowSpecSet acceptor_flow_set; + TAO_AV_FlowSpecSet connector_flow_set; + TAO_AV_FlowSpecSetItor end = reverse_flow_spec_set.end (); + TAO_AV_FlowSpecSetItor start = reverse_flow_spec_set.begin (); + for (;start != end; ++start) + { + TAO_FlowSpec_Entry *entry = (*start); + ACE_Addr *address = entry->address (); + if (address != 0) + { + if (this->get_acceptor (entry->flowname ())!= 0) + { + ACE_Addr *address = entry->address (); + TAO_FlowSpec_Entry *forward_entry = + this->get_flow_spec_entry (forward_flow_spec_set, + entry->flowname ()); + if (forward_entry != 0) + forward_entry->set_peer_addr (address); + // Now we have to match the control and data flow objects. + // Check if there's a control object. + char control_flowname [BUFSIZ]; + ACE_OS::sprintf (control_flowname,"%s_control",entry->flowname ()); + TAO_FlowSpec_Entry *control_entry = this->get_flow_spec_entry (forward_flow_spec_set, + control_flowname); + if (control_entry != 0) + forward_entry->protocol_object ()->control_object (control_entry->protocol_object ()); + } + else + connector_flow_set.insert (entry); + } + } + int result = -1; + switch (direction) + { + case TAO_AV_Core::TAO_AV_ENDPOINT_A: + result = this->connector_registry_->open (endpoint, + this, + connector_flow_set); + break; + default: + break; + } + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"acceptor_registry::open"),-1); + return 0; +} + +TAO_FlowSpec_Entry * +TAO_AV_Core::get_flow_spec_entry (TAO_AV_FlowSpecSet &flow_spec_set, + const char *flowname) +{ + TAO_AV_FlowSpecSetItor end = flow_spec_set.end (); + TAO_AV_FlowSpecSetItor begin = flow_spec_set.begin (); + for (; + begin != end; + ++begin) + { + if (ACE_OS::strcmp ((*begin)->flowname (),flowname) == 0) + return (*begin); + } + return 0; +} + +TAO_AV_Acceptor* +TAO_AV_Core::get_acceptor (const char *flowname) +{ + TAO_AV_AcceptorSetItor acceptor = + this->acceptor_registry_->begin (); + TAO_AV_AcceptorSetItor end = + this->acceptor_registry_->end (); + + for (;acceptor != end; ++acceptor) + { + if (ACE_OS::strcmp ((*acceptor)->flowname (),flowname) == 0) + return *acceptor; + } + return 0; +} + +TAO_AV_Connector* +TAO_AV_Core::get_connector (const char *flowname) +{ + TAO_AV_ConnectorSetItor connector = + this->connector_registry_->begin (); + TAO_AV_ConnectorSetItor end = + this->connector_registry_->end (); + + for (;connector != end; ++connector) + { + if (ACE_OS::strcmp ((*connector)->flowname (),flowname) == 0) + return *connector; + } + return 0; +} + +int +TAO_AV_Core::init_transport_factories (void) +{ + TAO_AV_TransportFactorySetItor end = this->transport_factories_.end (); + TAO_AV_TransportFactorySetItor factory = this->transport_factories_.begin (); + + if (factory == end) + { + TAO_AV_Transport_Factory *udp_factory = 0; + TAO_AV_Transport_Item *udp_item = 0; + + udp_factory = + ACE_Dynamic_Service<TAO_AV_Transport_Factory>::instance ("UDP_Factory"); + if (udp_factory == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_WARNING, + "(%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); + } + + ACE_NEW_RETURN (udp_item, TAO_AV_Transport_Item ("UDP_Factory"), -1); + udp_item->factory (udp_factory); + + this->transport_factories_.insert (udp_item); + + TAO_AV_Transport_Factory *tcp_factory = 0; + TAO_AV_Transport_Item *tcp_item = 0; + + tcp_factory = + ACE_Dynamic_Service<TAO_AV_Transport_Factory>::instance ("TCP_Factory"); + if (tcp_factory == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_WARNING, + "(%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); + } + + ACE_NEW_RETURN (tcp_item, TAO_AV_Transport_Item ("TCP_Factory"), -1); + tcp_item->factory (tcp_factory); + + this->transport_factories_.insert (tcp_item); + + + } + return 0; +} + +int +TAO_AV_Core::init_flow_protocol_factories (void) +{ + TAO_AV_Flow_ProtocolFactorySetItor end = this->flow_protocol_factories_.end (); + TAO_AV_Flow_ProtocolFactorySetItor factory = this->flow_protocol_factories_.begin (); + + if (factory == end) + { + TAO_AV_Flow_Protocol_Factory *udp_flow_factory = 0; + TAO_AV_Flow_Protocol_Item *udp_item = 0; + + udp_flow_factory = + ACE_Dynamic_Service<TAO_AV_Flow_Protocol_Factory>::instance ("UDP_Flow_Factory"); + if (udp_flow_factory == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_WARNING, + "(%P|%t) WARNING - No %s found in Service Repository." + " Using default instance.\n", + "UDP Flow Factory")); + + ACE_NEW_RETURN (udp_flow_factory, + TAO_AV_UDP_Flow_Factory, + -1); + } + + ACE_NEW_RETURN (udp_item, TAO_AV_Flow_Protocol_Item ("UDP_Flow_Factory"), -1); + udp_item->factory (udp_flow_factory); + + this->flow_protocol_factories_.insert (udp_item); + + TAO_AV_Flow_Protocol_Factory *tcp_flow_factory = 0; + TAO_AV_Flow_Protocol_Item *tcp_item = 0; + + tcp_flow_factory = + ACE_Dynamic_Service<TAO_AV_Flow_Protocol_Factory>::instance ("TCP_Flow_Factory"); + if (tcp_flow_factory == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_WARNING, + "(%P|%t) WARNING - No %s found in Service Repository." + " Using default instance.\n", + "TCP Flow Factory")); + + ACE_NEW_RETURN (tcp_flow_factory, + TAO_AV_TCP_Flow_Factory, + -1); + } + + ACE_NEW_RETURN (tcp_item, TAO_AV_Flow_Protocol_Item ("TCP_Flow_Factory"), -1); + tcp_item->factory (tcp_flow_factory); + + this->flow_protocol_factories_.insert (tcp_item); + + TAO_AV_Flow_Protocol_Factory *rtp_flow_factory = 0; + TAO_AV_Flow_Protocol_Item *rtp_item = 0; + + rtp_flow_factory = + ACE_Dynamic_Service<TAO_AV_Flow_Protocol_Factory>::instance ("RTP_Flow_Factory"); + if (rtp_flow_factory == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_WARNING, + "(%P|%t) WARNING - No %s found in Service Repository." + " Using default instance.\n", + "RTP Flow Factory")); + + ACE_NEW_RETURN (rtp_flow_factory, + TAO_AV_RTP_Flow_Factory, + -1); + } + + ACE_NEW_RETURN (rtp_item, TAO_AV_Flow_Protocol_Item ("RTP_Flow_Factory"), -1); + rtp_item->factory (rtp_flow_factory); + + this->flow_protocol_factories_.insert (rtp_item); + + TAO_AV_Flow_Protocol_Factory *rtcp_flow_factory = 0; + TAO_AV_Flow_Protocol_Item *rtcp_item = 0; + + rtcp_flow_factory = + ACE_Dynamic_Service<TAO_AV_Flow_Protocol_Factory>::instance ("RTCP_Flow_Factory"); + if (rtcp_flow_factory == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_WARNING, + "(%P|%t) WARNING - No %s found in Service Repository." + " Using default instance.\n", + "RTCP Flow Factory")); + + ACE_NEW_RETURN (rtcp_flow_factory, + TAO_AV_RTCP_Flow_Factory, + -1); + } + + ACE_NEW_RETURN (rtcp_item, TAO_AV_Flow_Protocol_Item ("RTCP_Flow_Factory"), -1); + rtcp_item->factory (rtcp_flow_factory); + + this->flow_protocol_factories_.insert (rtcp_item); + + TAO_AV_Flow_Protocol_Factory *sfp_flow_factory = 0; + TAO_AV_Flow_Protocol_Item *sfp_item = 0; + + sfp_flow_factory = + ACE_Dynamic_Service<TAO_AV_Flow_Protocol_Factory>::instance ("SFP_Flow_Factory"); + if (sfp_flow_factory == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_WARNING, + "(%P|%t) WARNING - No %s found in Service Repository." + " Using default instance.\n", + "SFP Flow Factory")); + + ACE_NEW_RETURN (sfp_flow_factory, + TAO_AV_SFP_Factory, + -1); + } + + ACE_NEW_RETURN (sfp_item, TAO_AV_Flow_Protocol_Item ("SFP_Flow_Factory"), -1); + sfp_item->factory (sfp_flow_factory); + + this->flow_protocol_factories_.insert (sfp_item); + } + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_Transport_Item +//------------------------------------------------------------ +TAO_AV_Transport_Item::TAO_AV_Transport_Item (const ACE_CString &name) + : name_ (name), + factory_ (0) +{ +} + +//------------------------------------------------------------ +// TAO_AV_Transport_Item +//------------------------------------------------------------ +TAO_AV_Flow_Protocol_Item::TAO_AV_Flow_Protocol_Item (const ACE_CString &name) + : name_ (name), + factory_ (0) +{ +} + +//------------------------------------------------------------ +// TAO_AV_Connector_Registry +//------------------------------------------------------------ + +TAO_AV_Connector_Registry::TAO_AV_Connector_Registry (void) +{ +} + +int +TAO_AV_Connector_Registry::open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_FlowSpecSet &flow_spec_set) +{ + TAO_AV_FlowSpecSetItor last_flowspec = + flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor flow_spec = flow_spec_set.begin (); + flow_spec != last_flowspec; + ++flow_spec) + { + TAO_FlowSpec_Entry *entry = (*flow_spec); + ACE_Addr *address = entry->address (); + 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; + if (address == 0) + { + // Protocol was specified without an endpoint. According to + // the "iioploc" spec, this is valid. As such, we extend + // this feature to all pluggable protocols. All TAO + // pluggable protocols are expected to have the ability to + // create a default 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 (); + + for (TAO_AV_Flow_ProtocolFactorySetItor flow_factory = + av_core->flow_protocol_factories ()->begin (); + flow_factory != flow_factory_end; + ++flow_factory) + { + 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) + { + 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, + (*flow_factory)->factory ()) == -1) + return -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 (); + + if (control_factory_name != 0) + { + TAO_AV_Flow_ProtocolFactorySetItor control_factory_end = + av_core->flow_protocol_factories ()->end (); + + 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 ()); + } + } + } + } + else + continue; + } + } + } + return 0; +} + +int +TAO_AV_Connector_Registry::close_all (void) +{ + TAO_AV_ConnectorSetItor end = + this->connectors_.end (); + + for (TAO_AV_ConnectorSetItor i = this->connectors_.begin (); + i != end; + ++i) + { + if (*i == 0) + continue; + + (*i)->close (); + + delete *i; + } + + this->connectors_.reset (); + return 0; +} + +TAO_AV_Connector_Registry::~TAO_AV_Connector_Registry (void) +{ + this->close_all (); +} + +//------------------------------------------------------------ +// TAO_AV_Acceptor_Registry +//------------------------------------------------------------ + +TAO_AV_Acceptor_Registry::TAO_AV_Acceptor_Registry (void) +{ +} + +TAO_AV_Acceptor_Registry::~TAO_AV_Acceptor_Registry (void) +{ +} + +int +TAO_AV_Acceptor_Registry::open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_FlowSpecSet &flow_spec_set) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Acceptor_Registry::open")); + TAO_AV_FlowSpecSetItor last_flowspec = + flow_spec_set.end (); + for (TAO_AV_FlowSpecSetItor flow_spec = flow_spec_set.begin (); + flow_spec != last_flowspec; + ++flow_spec) + { + TAO_FlowSpec_Entry *entry = (*flow_spec); + ACE_Addr *address = entry->address (); + 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; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Acceptor_Registry::protocol for flow %s is %d", + entry->flowname (),transport_protocol)); + if (address == 0) + { + this->open_default (endpoint,av_core, entry); + 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) + { + if ((*flow_factory)->factory ()->match_protocol (flow_protocol)) + { + 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, + entry, + (*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 check if the flow factory has a control flow factory. + const char *control_factory_name + = (*flow_factory)->factory ()->control_flow_factory (); + + if (control_factory_name != 0) + { + TAO_AV_Flow_ProtocolFactorySetItor control_factory_end = + av_core->flow_protocol_factories ()->end (); + + 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 + continue; + } + } + } + return 0; +} + +int +TAO_AV_Acceptor_Registry::open_default (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_FlowSpec_Entry *entry) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Acceptor_Registry::open_default ")); + // 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_TransportFactorySetItor transport_factory = av_core->transport_factories ()->begin (); + 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_ERROR ((LM_ERROR, + "TAO (%P|%t) Unable to match protocol prefix " + "for <%s>\n", + flow_protocol)); + continue; + } + else + { + TAO_AV_TransportFactorySetItor transport_factory_end = + av_core->transport_factories ()->end (); + 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", + flow_protocol)); + continue; + } + + + + // got it, make an acceptor + TAO_AV_Acceptor *acceptor = + (*transport_factory)->factory ()->make_acceptor (); + + 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; + } + + if (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; + } + + this->acceptors_.insert (acceptor); + } + } + } + if (this->acceptors_.size () == 0) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + "TAO (%P%t) cannot create any default acceptor\n")); + return -1; + } + + return 0; +} + +int +TAO_AV_Acceptor_Registry::close_all (void) +{ + TAO_AV_AcceptorSetItor end = + this->acceptors_.end (); + + for (TAO_AV_AcceptorSetItor i = this->acceptors_.begin (); + i != end; + ++i) + { + if (*i == 0) + continue; + + (*i)->close (); + + delete *i; + } + + this->acceptors_.reset (); + return 0; +} + +//---------------------------------------------------------------------- +// TAO_AV_Transport +//---------------------------------------------------------------------- + +TAO_AV_Transport::TAO_AV_Transport (void) +{ +} + +// Virtual destructor. +TAO_AV_Transport::~TAO_AV_Transport (void) +{ +} + +ACE_Addr* +TAO_AV_Transport::get_local_addr (void) +{ + return 0; +} + +//---------------------------------------------------------------------- +// TAO_AV_Flow_Handler +//---------------------------------------------------------------------- + +//TAO_AV_Flow_Handler::TAO_AV_Flow_Handler (TAO_AV_Callback *callback) +TAO_AV_Flow_Handler::TAO_AV_Flow_Handler (void) + :transport_ (0), + callback_ (0), + protocol_object_ (0) +{ +} + +int +TAO_AV_Flow_Handler::set_remote_address (ACE_Addr */* address */) +{ + return 0; +} + +int +TAO_AV_Flow_Handler::start (TAO_FlowSpec_Entry::Role role) +{ + this->callback_->handle_start (); + switch (role) + { + // only for producer we register for the timeout. + case TAO_FlowSpec_Entry::TAO_AV_PRODUCER: + { + this->schedule_timer (); + } + break; + default: + break; + } + return 0; +} + +int +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_); + if (tv == 0) + return 0; + this->timer_id_ = event_handler->reactor ()->schedule_timer (event_handler, + 0, + *tv); + if (this->timer_id_ < 0) + return -1; +} + +int +TAO_AV_Flow_Handler::stop (TAO_FlowSpec_Entry::Role role) +{ + this->callback_->handle_stop (); + switch (role) + { + case TAO_FlowSpec_Entry::TAO_AV_PRODUCER: + { + int result = this->event_handler ()->reactor ()->cancel_timer (this->timer_id_); + if (result < 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_Flow_Handler::stop:cancel_timer failed\n")); + } + break; + default: + break; + } + return 0; +} + +int +TAO_AV_Flow_Handler::handle_timeout (const ACE_Time_Value &tv, + const void *arg) +{ + 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_); + if (timeout == 0) + return 0; + this->timer_id_ = event_handler->reactor ()->schedule_timer (event_handler, + 0, + *timeout); + return 0; +} + +TAO_AV_Transport* +TAO_AV_Flow_Handler::transport (void) +{ + return this->transport_; +} + +void +TAO_AV_Flow_Handler::protocol_object (TAO_AV_Protocol_Object *protocol_object) +{ + this->protocol_object_ = protocol_object; +} + +TAO_AV_Protocol_Object* +TAO_AV_Flow_Handler::protocol_object (void) +{ + return this->protocol_object_; +} + +void +TAO_AV_Flow_Handler::callback (TAO_AV_Callback *callback) +{ + this->callback_ = callback; +} + +// TAO_AV_Connector +TAO_AV_Connector::TAO_AV_Connector (void) +{ +} + +TAO_AV_Connector::~TAO_AV_Connector (void) +{ +} + +// TAO_AV_Acceptor +TAO_AV_Acceptor::TAO_AV_Acceptor (void) +{ +} + +TAO_AV_Acceptor::~TAO_AV_Acceptor (void) +{ +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Node <TAO_AV_Connector*>; +template class ACE_Node <TAO_AV_Acceptor*>; +template class ACE_Unbounded_Set<TAO_AV_Acceptor*>; +template class ACE_Unbounded_Set<TAO_AV_Connector*>; +template class ACE_Unbounded_Set_Iterator<TAO_AV_Acceptor*>; +template class ACE_Unbounded_Set_Iterator<TAO_AV_Connector*>; +template class ACE_Singleton<TAO_AV_Core,ACE_Null_Mutex>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Node <TAO_AV_Connector*> +#pragma instantiate ACE_Node <TAO_AV_Acceptor*> +#pragma instantiate ACE_Unbounded_Set<TAO_AV_Connector*> +#pragma instantiate ACE_Unbounded_Set<TAO_AV_Acceptor*> +#pragma instantiate ACE_Unbounded_Set_Iterator<TAO_AV_Connector*> +#pragma instantiate ACE_Unbounded_Set_Iterator<TAO_AV_Acceptor*> +#pragma instantiate ACE_Singleton<TAO_AV_Core,ACE_Null_Mutex> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Transport.h b/TAO/orbsvcs/orbsvcs/AV/Transport.h new file mode 100644 index 00000000000..c46fa19e51b --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Transport.h @@ -0,0 +1,226 @@ +/* -*- C++ -*- */ + +// $Id$ +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// Transport.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#if !defined TAO_AV_TRANSPORT_H +#define TAO_AV_TRANSPORT_H + +#include "ace/Acceptor.h" +#include "ace/SOCK_Acceptor.h" +#include "ace/Connector.h" +#include "ace/SOCK_Connector.h" +#include "ace/Addr.h" +#include "ace/SOCK_Dgram.h" +#include "orbsvcs/orbsvcs_export.h" +#include "AV_Core.h" +#include "FlowSpec_Entry.h" + +// Forward declarations. +class TAO_AV_Protocol_Object; +class TAO_AV_Callback; +class TAO_AV_Transport; + +class TAO_AV_Flow_Handler +{ +public: + TAO_AV_Flow_Handler (void); + // Constructor. + + virtual int start (TAO_FlowSpec_Entry::Role role); + virtual int stop (TAO_FlowSpec_Entry::Role role); + // Start/stop the flow handler. + + virtual int schedule_timer (void); + // Schedule timer. Uses the get_timeout method on the callback. + + TAO_AV_Transport *transport (void); + // get the transport. + + TAO_AV_Protocol_Object* protocol_object (void); + void protocol_object (TAO_AV_Protocol_Object *protocol_object); + // set/get protocol_object. + + void callback (TAO_AV_Callback *callback); + // set the callback. + + int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0); + // Handle timeout. called from reactor. + + virtual int set_remote_address (ACE_Addr *address); + // set the remote address. + + virtual ACE_Event_Handler* event_handler (void) = 0; + // get the underlying event handler. To be overridden by the derived clases. + +protected: + TAO_AV_Transport *transport_; + TAO_AV_Callback *callback_; + TAO_AV_Protocol_Object *protocol_object_; + long timer_id_; + ACE_Reactor *reactor_; + void *timeout_arg_; +}; + +// Transports +class TAO_ORBSVCS_Export TAO_AV_Transport +{ + // TITLE + // = A Base class for the different transport protocols. + // + // DESCRIPTION + // = All the different transports should derive and implement + // the open,close,send and recv methods. +public: + TAO_AV_Transport (void); + + virtual ~TAO_AV_Transport (void); + + virtual int open (ACE_Addr *address) = 0; + + virtual int close (void) = 0; + + virtual int mtu (void) = 0; + virtual ACE_Addr *get_peer_addr (void) = 0; + virtual ACE_Addr *get_local_addr (void); + virtual ssize_t send (const ACE_Message_Block *mblk, + ACE_Time_Value *s = 0) = 0; + // Write the complete Message_Block chain to the connection. + + virtual ssize_t send (const char *buf, + size_t len, + ACE_Time_Value *s = 0) = 0; + // Write the contents of the buffer of length len to the connection. + + virtual ssize_t send (const iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0) = 0; + // Write the contents of iovcnt iovec's to the connection. + + virtual ssize_t recv (char *buf, + size_t len, + ACE_Time_Value *s = 0) = 0; + // Read len bytes from into buf. + + virtual ssize_t recv (char *buf, + size_t len, + int flags, + ACE_Time_Value *s = 0) = 0; + // Read len bytes from into buf using flags. + + virtual ssize_t recv (iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0) = 0; + // Read received data into the iovec buffers. + +}; + +class TAO_Base_StreamEndPoint; +class TAO_AV_Core; +class TAO_FlowSpec_Entry; + +class TAO_AV_Acceptor +{ +public: + TAO_AV_Acceptor (void); + virtual ~TAO_AV_Acceptor (void); + virtual int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_FlowSpec_Entry *entry, + TAO_AV_Flow_Protocol_Factory *factory) = 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; + + const char *flowname (); + virtual int close (void) = 0; +protected: + ACE_CString flowname_; + TAO_AV_Core *av_core_; + ACE_Addr *address_; +}; + +class TAO_AV_Connector +{ +public: + TAO_AV_Connector (void); + virtual ~TAO_AV_Connector (void); + const char *flowname (void); + + virtual int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_Flow_Protocol_Factory *factory) = 0; + + virtual int connect (TAO_FlowSpec_Entry *entry, + TAO_AV_Transport *&transport) = 0; + + virtual int close (void) = 0; +protected: + ACE_CString flowname_; +}; + + +typedef ACE_Unbounded_Set<TAO_AV_Connector*> TAO_AV_ConnectorSet; +typedef ACE_Unbounded_Set_Iterator<TAO_AV_Connector*> TAO_AV_ConnectorSetItor; + +class TAO_ORBSVCS_Export TAO_AV_Connector_Registry +{ +public: + TAO_AV_Connector_Registry (void); + ~TAO_AV_Connector_Registry (void); + int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_FlowSpecSet &flow_spec_set); + // int connect (TAO_FlowSpec_Entry *flowspec, + // TAO_AV_Transport *&transport); + int close_all (void); + // TAO_AV_Connector *get_connector (TAO_AV_Core::Protocol protocol); + // Return the connector bridges + TAO_AV_ConnectorSetItor begin (void); + TAO_AV_ConnectorSetItor end (void); +protected: + TAO_AV_ConnectorSet connectors_; +}; + +typedef ACE_Unbounded_Set<TAO_AV_Acceptor*> + TAO_AV_AcceptorSet; +typedef ACE_Unbounded_Set_Iterator<TAO_AV_Acceptor*> + TAO_AV_AcceptorSetItor; + +class TAO_ORBSVCS_Export TAO_AV_Acceptor_Registry +{ +public: + TAO_AV_Acceptor_Registry (void); + ~TAO_AV_Acceptor_Registry (void); + int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_FlowSpecSet &flow_spec_set); + int close_all (void); + TAO_AV_AcceptorSetItor begin (void); + TAO_AV_AcceptorSetItor end (void); +protected: + int open_default (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_FlowSpec_Entry *entry); + TAO_AV_AcceptorSet acceptors_; +}; + +#if defined (__ACE_INLINE__) +#include "Transport.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_AV_TRANSPORT_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/Transport.i b/TAO/orbsvcs/orbsvcs/AV/Transport.i new file mode 100644 index 00000000000..68db1bcf5f0 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/Transport.i @@ -0,0 +1,180 @@ +/* -*- C++ -*- */ +// $Id$ + +// Transport.i + +//------------------------------------------------------------ +// TAO_AV_Core +//------------------------------------------------------------ + +ACE_INLINE +TAO_ORB_Manager* +TAO_AV_Core::orb_manager (void) +{ + return &this->orb_manager_; +} + +ACE_INLINE +int +TAO_AV_Core::stop_run (void) +{ + this->stop_run_ = 1; + return 0; +} + +ACE_INLINE +int +TAO_AV_Core::run (void) +{ + this->stop_run_ = 0; + this->orb_manager_.activate_poa_manager (); + while (!this->stop_run_ && this->orb_->work_pending ()) + this->orb_->perform_work (); + return 0; +} + +ACE_INLINE +void +TAO_AV_Core::reactor (ACE_Reactor *r) +{ + this->reactor_ = r; +} + +ACE_INLINE +ACE_Reactor * +TAO_AV_Core::reactor (void) +{ + return this->reactor_; +} + +ACE_INLINE +TAO_AV_Connector_Registry* +TAO_AV_Core::connector_registry (void) +{ + return this->connector_registry_; +} + +ACE_INLINE +TAO_AV_Acceptor_Registry* +TAO_AV_Core::acceptor_registry (void) +{ + return this->acceptor_registry_; +} + +ACE_INLINE +TAO_AV_TransportFactorySet * +TAO_AV_Core::transport_factories (void) +{ + return &this->transport_factories_; +} + +ACE_INLINE +TAO_AV_Flow_ProtocolFactorySet* +TAO_AV_Core::flow_protocol_factories (void) +{ + return &this->flow_protocol_factories_; +} + +//------------------------------------------------------------ +// TAO_AV_Transport_Item +//------------------------------------------------------------ +ACE_INLINE +const ACE_CString & +TAO_AV_Transport_Item::name (void) +{ + return this->name_; +} + +ACE_INLINE +TAO_AV_Transport_Factory * +TAO_AV_Transport_Item::factory (void) +{ + return this->factory_; +} + +ACE_INLINE +void +TAO_AV_Transport_Item::factory (TAO_AV_Transport_Factory *factory) +{ + this->factory_ = factory; +} + + +//------------------------------------------------------------ +// TAO_AV_Flow_Protocol_Item +//------------------------------------------------------------ +ACE_INLINE +const ACE_CString & +TAO_AV_Flow_Protocol_Item::name (void) +{ + return this->name_; +} + +ACE_INLINE +TAO_AV_Flow_Protocol_Factory * +TAO_AV_Flow_Protocol_Item::factory (void) +{ + return this->factory_; +} + +ACE_INLINE +void +TAO_AV_Flow_Protocol_Item::factory (TAO_AV_Flow_Protocol_Factory *factory) +{ + this->factory_ = factory; +} + +//------------------------------------------------------------ +// TAO_AV_Connector_Registry +//------------------------------------------------------------ + +ACE_INLINE +TAO_AV_ConnectorSetItor +TAO_AV_Connector_Registry::begin (void) +{ + return this->connectors_.begin (); +} + +ACE_INLINE +TAO_AV_ConnectorSetItor +TAO_AV_Connector_Registry::end (void) +{ + return this->connectors_.end (); +} + +//------------------------------------------------------------ +// TAO_AV_Acceptor_Registry +//------------------------------------------------------------ +ACE_INLINE +TAO_AV_AcceptorSetItor +TAO_AV_Acceptor_Registry::begin (void) +{ + return this->acceptors_.begin (); +} + +ACE_INLINE +TAO_AV_AcceptorSetItor +TAO_AV_Acceptor_Registry::end (void) +{ + return this->acceptors_.end (); +} + +//------------------------------------------------------------ +// TAO_AV_Acceptor +//------------------------------------------------------------ +ACE_INLINE +const char * +TAO_AV_Acceptor::flowname (void) +{ + return this->flowname_.c_str (); +} + +//------------------------------------------------------------ +// TAO_AV_Connector +//------------------------------------------------------------ +ACE_INLINE +const char * +TAO_AV_Connector::flowname (void) +{ + return this->flowname_.c_str (); +} diff --git a/TAO/orbsvcs/orbsvcs/AV/UDP.cpp b/TAO/orbsvcs/orbsvcs/AV/UDP.cpp new file mode 100644 index 00000000000..fc7b0b42bb0 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/UDP.cpp @@ -0,0 +1,729 @@ +// $Id$ + +#include "UDP.h" +#include "AVStreams_i.h" +#include "MCast.h" + +#if !defined (__ACE_INLINE__) +#include "UDP.i" +#endif /* __ACE_INLINE__ */ + +//------------------------------------------------------------ +// TAO_AV_UDP_Flow_Handler +//------------------------------------------------------------ + +TAO_AV_UDP_Flow_Handler::TAO_AV_UDP_Flow_Handler (void) +{ + ACE_NEW (this->transport_, + TAO_AV_UDP_Transport (this)); +} + +TAO_AV_UDP_Flow_Handler::~TAO_AV_UDP_Flow_Handler (void) +{ + delete this->transport_; +} + +TAO_AV_Transport * +TAO_AV_UDP_Flow_Handler::transport (void) +{ + return this->transport_; +} + +int +TAO_AV_UDP_Flow_Handler::handle_input (ACE_HANDLE /*fd*/) +{ + this->protocol_object_->handle_input (); + return 0; +} + +int +TAO_AV_UDP_Flow_Handler::handle_timeout (const ACE_Time_Value &tv, + const void *arg) +{ + return TAO_AV_Flow_Handler::handle_timeout (tv,arg); +} + +int +TAO_AV_UDP_Flow_Handler::set_remote_address (ACE_Addr *address) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Flow_Handler::set_remote_address\n")); + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,address); + this->peer_addr_ = *inet_addr; + TAO_AV_UDP_Transport *transport = ACE_dynamic_cast (TAO_AV_UDP_Transport*,this->transport_); + return transport->set_remote_address (*inet_addr); +} + + +ACE_HANDLE +TAO_AV_UDP_Flow_Handler::get_handle (void) const +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Flow_Handler::get_handle:%d\n",this->sock_dgram_.get_handle ())); + return this->sock_dgram_.get_handle () ; +} + +//------------------------------------------------------------ +// TAO_AV_UDP_Transport +//------------------------------------------------------------ + +TAO_AV_UDP_Transport::TAO_AV_UDP_Transport (void) + :handler_ (0) +{ +} + +TAO_AV_UDP_Transport::TAO_AV_UDP_Transport (TAO_AV_UDP_Flow_Handler *handler) + :handler_ (handler), + addr_ (0) +{ +} + +TAO_AV_UDP_Transport::~TAO_AV_UDP_Transport (void) +{ +} + +int +TAO_AV_UDP_Transport::set_remote_address (const ACE_INET_Addr &address) +{ + this->peer_addr_ = address; + return 0; +} + +int +TAO_AV_UDP_Transport::open (ACE_Addr */*address*/) +{ + return 0; +} + +int +TAO_AV_UDP_Transport::close (void) +{ + return 0; +} + +int +TAO_AV_UDP_Transport::mtu (void) +{ + return ACE_MAX_DGRAM_SIZE; +} + +ACE_Addr* +TAO_AV_UDP_Transport::get_peer_addr (void) +{ + return &this->peer_addr_; +} + +ssize_t +TAO_AV_UDP_Transport::send (const ACE_Message_Block *mblk, ACE_Time_Value *) +{ + // For the most part this was copied from GIOP::send_request and + // friends. + + iovec iov[IOV_MAX]; + int iovcnt = 0; + ssize_t n = 0; + ssize_t nbytes = 0; + + for (const ACE_Message_Block *i = mblk; + i != 0; + i = i->cont ()) + { + // Make sure there is something to send! + if (i->length () > 0) + { + iov[iovcnt].iov_base = i->rd_ptr (); + iov[iovcnt].iov_len = i->length (); + iovcnt++; + + // The buffer is full make a OS call. @@ TODO this should + // be optimized on a per-platform basis, for instance, some + // platforms do not implement writev() there we should copy + // the data into a buffer and call send_n(). In other cases + // there may be some limits on the size of the iovec, there + // we should set IOV_MAX to that limit. + if (iovcnt == IOV_MAX) + { + n = this->handler_->get_socket ()->send ((const iovec *) iov, + iovcnt, + this->peer_addr_); + + if (n < 1) + return n; + + nbytes += n; + iovcnt = 0; + } + } + } + + // Check for remaining buffers to be sent! + if (iovcnt != 0) + { + n = this->handler_->get_socket ()->send ((const iovec *) iov, + iovcnt, + this->peer_addr_); + + if (n < 1) + return n; + + nbytes += n; + } + + return nbytes; +} + +ssize_t +TAO_AV_UDP_Transport::send (const char *buf, + size_t len, + ACE_Time_Value *) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Transport::send ")); + char addr [BUFSIZ]; + this->peer_addr_.addr_to_string (addr,BUFSIZ); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"to %s\n",addr)); + + return this->handler_->get_socket ()->send (buf, len,this->peer_addr_); +} + +ssize_t +TAO_AV_UDP_Transport::send (const iovec *iov, + int iovcnt, + ACE_Time_Value *) +{ + return this->handler_->get_socket ()->send ((const iovec *) iov, + iovcnt, + this->peer_addr_); + +} + +ssize_t +TAO_AV_UDP_Transport::recv (char *buf, + size_t len, + ACE_Time_Value *) +{ + return this->handler_->get_socket ()->recv (buf, len,this->peer_addr_); +} + +ssize_t +TAO_AV_UDP_Transport::recv (char *buf, + size_t len, + int flags, + ACE_Time_Value *timeout) +{ + return this->handler_->get_socket ()->recv (buf, + len, + this->peer_addr_, + flags, + timeout); +} + +ssize_t +TAO_AV_UDP_Transport::recv (iovec *iov, + int /*iovcnt*/, + ACE_Time_Value *timeout) +{ + return handler_->get_socket ()->recv (iov,this->peer_addr_,0,timeout); +} + + +//------------------------------------------------------------ +// TAO_AV_UDP_Acceptor +//------------------------------------------------------------ + +TAO_AV_UDP_Acceptor::TAO_AV_UDP_Acceptor (void) +{ +} + +TAO_AV_UDP_Acceptor::~TAO_AV_UDP_Acceptor (void) +{ +} + +int +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; +} + +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) +{ + 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_protocol_factory_ = factory; + this->flowname_ = entry->flowname (); + ACE_INET_Addr *inet_addr = (ACE_INET_Addr *) entry->address (); +// inet_addr->set (inet_addr->get_port_number (), +// inet_addr->get_host_name ()); + char buf[BUFSIZ]; + inet_addr->addr_to_string (buf, + BUFSIZ); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Acceptor::open: %s", + buf)); + int result = this->open_i (inet_addr); + if (result < 0) + return result; + return 0; +} + +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) +{ + this->av_core_ = av_core; + this->endpoint_ = endpoint; + this->entry_ = entry; + 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); + if (result < 0) + return result; + return 0; +} + +int +TAO_AV_UDP_Acceptor::open_i (ACE_INET_Addr *inet_addr) +{ + int result = -1; + // TAO_AV_Callback *callback = 0; +// this->endpoint_->get_callback (this->flowname_.c_str (), +// callback); + ACE_INET_Addr *local_addr; + TAO_AV_Flow_Handler *flow_handler = 0; + if (this->entry_->is_multicast ()) + { + 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); + // Now disable Multicast loopback. + // @@Should we make this a policy? + 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. + 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); + } + 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; + + if (handler->get_socket ()->set_option (SOL_SOCKET, + SO_SNDBUF, + (void *) &sndbufsize, + sizeof (sndbufsize)) == -1 + && errno != ENOTSUP) + return 0; + + else if (handler->get_socket ()->set_option (SOL_SOCKET, + SO_RCVBUF, + (void *) &rcvbufsize, + sizeof (rcvbufsize)) == -1 + && errno != ENOTSUP) + return 0; + + 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 ()); + } + 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_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)); + this->entry_->set_local_addr (local_addr); + this->entry_->handler (flow_handler); + // call activate svc handler. + return this->activate_svc_handler (flow_handler); +} + +int +TAO_AV_UDP_Acceptor::close (void) +{ + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_UDP_Connector +//------------------------------------------------------------ +TAO_AV_UDP_Connector::TAO_AV_UDP_Connector (void) +{ +} + +TAO_AV_UDP_Connector::~TAO_AV_UDP_Connector (void) +{ +} + +int +TAO_AV_UDP_Connector::open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_Flow_Protocol_Factory *factory) + +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Connector::open ")); + this->endpoint_ = endpoint; + this->av_core_ = av_core; + this->flow_protocol_factory_ = factory; + return 0; +} + +int +TAO_AV_UDP_Connector::connect (TAO_FlowSpec_Entry *entry, + TAO_AV_Transport *&transport) +{ + int result = -1; + this->entry_ = entry; + this->flowname_ = entry->flowname (); + ACE_Addr *remote_addr = entry->address (); + ACE_INET_Addr *local_addr; + ACE_NEW_RETURN (local_addr, + ACE_INET_Addr ("0"), + -1); + + // TAO_AV_Callback *callback = 0; +// this->endpoint_->get_callback (this->flowname_.c_str (), +// callback); + ACE_INET_Addr *inet_addr = ACE_dynamic_cast (ACE_INET_Addr*,entry->address ()); + TAO_AV_Flow_Handler *flow_handler = 0; + if (entry->is_multicast ()) + { + TAO_AV_UDP_MCast_Flow_Handler *handler; + ACE_NEW_RETURN (handler, + // TAO_AV_UDP_MCast_Flow_Handler (callback), + 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::open failed\n"),-1); + // Now disable Multicast loopback. + // @@Should we make this a policy? + 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. + 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); + } + else + { + TAO_AV_UDP_Flow_Handler *handler; + ACE_NEW_RETURN (handler, + // TAO_AV_UDP_Flow_Handler (callback), + TAO_AV_UDP_Flow_Handler, + -1); + flow_handler = handler; + result = handler->open (*local_addr); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"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; + + if (handler->get_socket ()->set_option (SOL_SOCKET, + SO_SNDBUF, + (void *) &sndbufsize, + sizeof (sndbufsize)) == -1 + && errno != ENOTSUP) + return 0; + + else if (handler->get_socket ()->set_option (SOL_SOCKET, + SO_RCVBUF, + (void *) &rcvbufsize, + sizeof (rcvbufsize)) == -1 + && errno != ENOTSUP) + return 0; + + handler->set_remote_address (inet_addr); + 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 ()); + } + 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_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; +} + +//------------------------------------------------------------ +// TAO_AV_UDP_Protocol_Factory +//------------------------------------------------------------ + +TAO_AV_UDP_Factory::TAO_AV_UDP_Factory (void) +{ +} + +TAO_AV_UDP_Factory::~TAO_AV_UDP_Factory (void) +{ +} + +int +TAO_AV_UDP_Factory::match_protocol (const char *protocol_string) +{ + if (ACE_OS::strstr (protocol_string,"UDP") != 0) + return 1; + return 0; +} + +TAO_AV_Acceptor* +TAO_AV_UDP_Factory::make_acceptor (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Factory::make_acceptor ")); + TAO_AV_Acceptor *acceptor = 0; + ACE_NEW_RETURN (acceptor, + TAO_AV_UDP_Acceptor, + 0); + return acceptor; +} + +TAO_AV_Connector* +TAO_AV_UDP_Factory::make_connector (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Factory::make_connector ")); + TAO_AV_Connector *connector = 0; + ACE_NEW_RETURN (connector, + TAO_AV_UDP_Connector, + 0); + return connector; +} + +int +TAO_AV_UDP_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return 0; +} + +//------------------------------------------------------------ +// TAO_AV_UDP_Object +//------------------------------------------------------------ + +int +TAO_AV_UDP_Object::handle_input (void) +{ + int n = this->transport_->recv (this->frame_.rd_ptr (), + this->frame_.size ()); + if (n == -1) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_UDP_Flow_Handler::handle_input recv failed\n"),-1); + if (n == -1) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_UDP_Flow_Handler::handle_input connection closed\n"),-1); + this->frame_.wr_ptr (this->frame_.rd_ptr () + n); + + return this->callback_->receive_frame (&this->frame_); +} + +int +TAO_AV_UDP_Object::send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_AV_UDP_Object::send_frame\n")); + int result = this->transport_->send (frame); + if (result < 0) + return result; + return 0; +} + +int +TAO_AV_UDP_Object::send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info) +{ + return this->transport_->send (iov,iovcnt); +} + +TAO_AV_UDP_Object::TAO_AV_UDP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport) + :TAO_AV_Protocol_Object (callback,transport) +{ + this->frame_.size (2 * this->transport_->mtu ()); +} + +TAO_AV_UDP_Object::~TAO_AV_UDP_Object (void) +{ + //no-op +} + +int +TAO_AV_UDP_Object::destroy (void) +{ + this->callback_->handle_destroy (); + return 0; +} + + +//------------------------------------------------------------ +// TAO_AV_UDP_Flow_Factory +//------------------------------------------------------------ +TAO_AV_UDP_Flow_Factory::TAO_AV_UDP_Flow_Factory (void) +{ +} + +TAO_AV_UDP_Flow_Factory::~TAO_AV_UDP_Flow_Factory (void) +{ +} + +int +TAO_AV_UDP_Flow_Factory::init (int /* argc */, + char * /* argv */ []) +{ + return 0; +} + +int +TAO_AV_UDP_Flow_Factory::match_protocol (const char *flow_string) +{ + if (ACE_OS::strcasecmp (flow_string,"UDP") == 0) + return 1; + return 0; +} + +TAO_AV_Protocol_Object* +TAO_AV_UDP_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_callback (entry->flowname (), + callback); + + + TAO_AV_UDP_Object *object = 0; + ACE_NEW_RETURN (object, + TAO_AV_UDP_Object (callback, + transport), + 0); + callback->open (object, + handler); + endpoint->set_protocol_object (entry->flowname (), + object); + return object; +} + +ACE_FACTORY_DEFINE (AV, TAO_AV_UDP_Flow_Factory) +ACE_STATIC_SVC_DEFINE (TAO_AV_UDP_Flow_Factory, + ASYS_TEXT ("UDP_Flow_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_AV_UDP_Flow_Factory), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) + +ACE_FACTORY_DEFINE (AV, TAO_AV_UDP_Factory) + +ACE_STATIC_SVC_DEFINE (TAO_AV_UDP_Factory, + ASYS_TEXT ("UDP_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_AV_UDP_Factory), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) + + diff --git a/TAO/orbsvcs/orbsvcs/AV/UDP.h b/TAO/orbsvcs/orbsvcs/AV/UDP.h new file mode 100644 index 00000000000..f15031ff9e3 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/UDP.h @@ -0,0 +1,219 @@ +/* -*- C++ -*- */ + +// $Id$ +// ============================================================================ +// +// = LIBRARY +// ORBSVCS AVStreams +// +// = FILENAME +// UDP.h +// +// = AUTHOR +// Nagarajan Surendran <naga@cs.wustl.edu> +// +// +// ============================================================================ + +#ifndef TAO_AV_UDP_H +#define TAO_AV_UDP_H + +#include "ace/OS.h" +#include "Protocol_Factory.h" + +class TAO_ORBSVCS_Export TAO_AV_UDP_Factory : public TAO_AV_Transport_Factory +{ +public: + TAO_AV_UDP_Factory (void); + virtual ~TAO_AV_UDP_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *protocol_string); + virtual TAO_AV_Acceptor *make_acceptor (void); + virtual TAO_AV_Connector *make_connector (void); +}; + +class TAO_AV_UDP_Flow_Handler; + +class TAO_AV_UDP_Transport + :public TAO_AV_Transport +{ + // = TITLE + // A transport abstraction for udp sockets. + // + // = DESCRIPTION + // Uses the ACE_SOCK_Dgram to send the data. +public: + TAO_AV_UDP_Transport (void); + + TAO_AV_UDP_Transport (TAO_AV_UDP_Flow_Handler *handler); + + virtual ~TAO_AV_UDP_Transport (void); + virtual int open (ACE_Addr *addr); + + virtual int close (void); + + virtual int mtu (void); + + virtual ACE_Addr *get_peer_addr (void); + + virtual int set_remote_address (const ACE_INET_Addr &address); + + virtual ssize_t send (const ACE_Message_Block *mblk, + ACE_Time_Value *s = 0); + // Write the complete Message_Block chain to the connection. + + virtual ssize_t send (const char *buf, + size_t len, + ACE_Time_Value *s = 0); + // Write the contents of the buffer of length len to the connection. + + virtual ssize_t send (const iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0); + // Write the contents of iovcnt iovec's to the connection. + + virtual ssize_t recv (char *buf, + size_t len, + ACE_Time_Value *s = 0); + // Read len bytes from into buf. + + virtual ssize_t recv (char *buf, + size_t len, + int flags, + ACE_Time_Value *s = 0); + // Read len bytes from into buf using flags. + + virtual ssize_t recv (iovec *iov, + int iovcnt, + ACE_Time_Value *s = 0); + // Read received data into the iovec buffers. +protected: + TAO_AV_UDP_Flow_Handler *handler_; + ACE_Addr *addr_; + ACE_INET_Addr peer_addr_; +}; + +class TAO_AV_UDP_Flow_Handler + :public virtual TAO_AV_Flow_Handler, + public virtual ACE_Event_Handler +{ +public: + TAO_AV_UDP_Flow_Handler (void); + //Ctor + ~TAO_AV_UDP_Flow_Handler (void); + // Dtor + int open (ACE_Addr &address); + virtual TAO_AV_Transport *transport (void); + virtual int set_remote_address (ACE_Addr *address); + 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); + const ACE_SOCK_Dgram *get_socket (void) const; + virtual ACE_Event_Handler* event_handler (void){ return this; } +protected: + TAO_AV_Core *av_core_; + ACE_INET_Addr peer_addr_; + ACE_SOCK_Dgram sock_dgram_; +}; + +class TAO_AV_UDP_Acceptor + :public TAO_AV_Acceptor +{ +public: + TAO_AV_UDP_Acceptor (void); + virtual ~TAO_AV_UDP_Acceptor (void); + virtual int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_FlowSpec_Entry *entry, + TAO_AV_Flow_Protocol_Factory *factory); + + virtual int open_default (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_FlowSpec_Entry *entry, + TAO_AV_Flow_Protocol_Factory *factory); + + virtual int open_i (ACE_INET_Addr *address); + + 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_; +}; + +class TAO_AV_UDP_Connector + :public TAO_AV_Connector +{ +public: + TAO_AV_UDP_Connector (void); + ~TAO_AV_UDP_Connector (void); + virtual int open (TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Core *av_core, + TAO_AV_Flow_Protocol_Factory *factory); + + virtual int connect (TAO_FlowSpec_Entry *entry, + TAO_AV_Transport *&transport); + virtual int activate_svc_handler (TAO_AV_Flow_Handler *handler); + virtual int close (void); +protected: + TAO_Base_StreamEndPoint *endpoint_; + TAO_AV_Core *av_core_; + TAO_FlowSpec_Entry *entry_; + TAO_AV_Flow_Protocol_Factory *flow_protocol_factory_; +}; + +class TAO_ORBSVCS_Export TAO_AV_UDP_Object : public TAO_AV_Protocol_Object +{ +public: + TAO_AV_UDP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport = 0); + + virtual ~TAO_AV_UDP_Object (void); + // Dtor + + virtual int handle_input (void); + + virtual int send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0); + // send a data frame. + + virtual int send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info = 0); + + virtual int destroy (void); + // end the stream. + +private: + ACE_Message_Block frame_; + // Pre-allocated memory to receive the data... +}; + +class TAO_AV_UDP_Flow_Factory : public TAO_AV_Flow_Protocol_Factory +{ +public: + TAO_AV_UDP_Flow_Factory (void); + virtual ~TAO_AV_UDP_Flow_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *flow_string); + TAO_AV_Protocol_Object* make_protocol_object (TAO_FlowSpec_Entry *entry, + TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Flow_Handler *handler, + TAO_AV_Transport *transport); +}; + +ACE_STATIC_SVC_DECLARE (TAO_AV_UDP_Flow_Factory) +ACE_FACTORY_DECLARE (TAO_ORBSVCS, TAO_AV_UDP_Flow_Factory) + +ACE_STATIC_SVC_DECLARE (TAO_AV_UDP_Factory) +ACE_FACTORY_DECLARE (TAO_ORBSVCS, TAO_AV_UDP_Factory) + + +#if defined(__ACE_INLINE__) +#include "UDP.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_AV_UDP_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/UDP.i b/TAO/orbsvcs/orbsvcs/AV/UDP.i new file mode 100644 index 00000000000..2406225e417 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/UDP.i @@ -0,0 +1,20 @@ +/* -*- C++ -*- */ + +// $Id$ + +//---------------------------------------------------------------------- +// TAO_AV_UDP_Flow_Handler +//---------------------------------------------------------------------- +ACE_INLINE +const ACE_SOCK_Dgram * +TAO_AV_UDP_Flow_Handler::get_socket (void) const +{ + return &this->sock_dgram_; +} + +ACE_INLINE +int +TAO_AV_UDP_Flow_Handler::open (ACE_Addr &address) +{ + return this->sock_dgram_.open (address); +} diff --git a/TAO/orbsvcs/orbsvcs/AV/media-timer.cpp b/TAO/orbsvcs/orbsvcs/AV/media-timer.cpp new file mode 100644 index 00000000000..4f24ab9484a --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/media-timer.cpp @@ -0,0 +1,86 @@ +//$Id$ +/* + * Copyright (c) 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 Computer Systems + * Engineering 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. + */ +static const char rcsid[] = + "@(#) $Header$"; + +#include <math.h> +#include "media-timer.h" + +MediaTimer* MediaTimer::instance_; + +MediaTimer::MediaTimer() +{ + instance_ = this; + offset_ = ACE_OS::rand (); +} + +MediaTimer::~MediaTimer() +{ + instance_ = 0; +} + +/* + * Default media timestamp -- convert unix system clock + * into a 90Khz timestamp. Grabbers override this virtual + * method if they can provide their own time base. + * + * XXX + * We save the corresponding unix time stamp to handle the + * unix_ts() call the transmitter will make to get the correspondence + * between the media timestamp & unix time. + */ +ACE_UINT32 MediaTimer::media_ts() +{ + timeval tv; + ::gettimeofday(&tv, 0); + ACE_UINT32 u = tv.tv_usec; + u = (u << 3) + u; /* x 9 */ + /* sec * 90Khz + (usec * 90Khz) / 1e6 */ + u = tv.tv_sec * 90000 + (u / 100); + return (u + offset_); +} + +/* + * compute media time corresponding to the current unix time. + * in this generic routine, this is the same as media_ts() but, + * if a grabber has hardware or kernel timestamping, this routine + * must compute the correspondence between the hardware timestamp + * and the unix clock and appropriately offset the timestamp to + * correspond to the current clock. (This information if vital + * for cross-media synchronization.) + */ +ACE_UINT32 MediaTimer::ref_ts() +{ + return (media_ts()); +} diff --git a/TAO/orbsvcs/orbsvcs/AV/media-timer.h b/TAO/orbsvcs/orbsvcs/AV/media-timer.h new file mode 100644 index 00000000000..9e316044168 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/media-timer.h @@ -0,0 +1,59 @@ +/* -*- C++ -*- */ +// $Id$ +/* + * Copyright (c) 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 Computer Systems + * Engineering 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_MEDIA_TIMER_H +#define TAO_AV_MEDIA_TIMER_H + +#include "ace/OS.h" +long random (void); + +class MediaTimer +{ + public: + MediaTimer(); + virtual ~MediaTimer(); + static inline MediaTimer* instance() { return (instance_); } + virtual ACE_UINT32 media_ts(); + virtual ACE_UINT32 ref_ts(); + inline ACE_UINT32 offset() const { return (offset_); } + private: + static MediaTimer* instance_; + protected: + ACE_UINT32 offset_; /* random offset */ +}; + +#endif /* TAO_AV_MEDIA_TIMER_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/ntp-time.h b/TAO/orbsvcs/orbsvcs/AV/ntp-time.h new file mode 100644 index 00000000000..d6cf15ec3ae --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/ntp-time.h @@ -0,0 +1,96 @@ +/* -*- C++ -*- */ +// $Id$ +/* + * Copyright (c) 1995 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 Network Research + * Group at Lawrence Berkeley National 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_NTP_TIME_H +#define TAO_AV_NTP_TIME_H + +#include "ace/OS.h" +#include "RTCP.h" + +/* + * convert microseconds to fraction of second * 2^32 (i.e., the lsw of + * a 64-bit ntp timestamp). This routine uses the factorization + * 2^32/10^6 = 4096 + 256 - 1825/32 which results in a max conversion + * error of 3 * 10^-7 and an average error of half that. + */ +ACE_INLINE u_int usec2ntp(u_int usec) +{ + u_int t = (usec * 1825) >> 5; + return ((usec << 12) + (usec << 8) - t); +} + +/* + * Number of seconds between 1-Jan-1900 and 1-Jan-1970 + */ +const ACE_UINT32 GETTIMEOFDAY_TO_NTP_OFFSET = 2208988800; + +/* + * Return a 64-bit ntp timestamp (UTC time relative to Jan 1, 1970). + * gettimeofday conveniently gives us the correct reference -- we just + * need to convert sec+usec to a 64-bit fixed point (with binary point + * at bit 32). + */ +ACE_INLINE TAO_AV_RTCP::ntp64 +ntp64time (timeval tv) +{ + TAO_AV_RTCP::ntp64 n; + n.upper = (u_int)tv.tv_sec + GETTIMEOFDAY_TO_NTP_OFFSET; + n.lower = usec2ntp((u_int)tv.tv_usec); + return (n); +} + +ACE_INLINE ACE_UINT32 +ntptime (timeval t) +{ + u_int s = (u_int)t.tv_sec + GETTIMEOFDAY_TO_NTP_OFFSET; + return (s << 16 | usec2ntp((u_int)t.tv_usec) >> 16); +} + +ACE_INLINE ACE_UINT32 +ntptime() +{ + struct timeval tv; + ::gettimeofday(&tv, 0); + return (ntptime(tv)); +} + +ACE_INLINE timeval unixtime() +{ + struct timeval tv; + ::gettimeofday(&tv, 0); + return (tv); +} +#endif /* TAO_AV_NTP_TIME_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/sfp.cpp b/TAO/orbsvcs/orbsvcs/AV/sfp.cpp index bf08d0a3b74..cf7981db389 100644 --- a/TAO/orbsvcs/orbsvcs/AV/sfp.cpp +++ b/TAO/orbsvcs/orbsvcs/AV/sfp.cpp @@ -1,24 +1,32 @@ // $Id$ -#include "orbsvcs/AV/sfp.h" +#include "sfp.h" #include "ace/ARGV.h" // default arguments to pass to use for the ORB -const char *TAO_SFP::TAO_SFP_ORB_ARGUMENTS = "-ORBobjrefstyle URL"; +const char *TAO_SFP_Base::TAO_SFP_ORB_ARGUMENTS = "-ORBobjrefstyle URL"; // SFP magic numbers -const char *TAO_SFP::TAO_SFP_MAGIC_NUMBER = "=SFP"; -const char *TAO_SFP::TAO_SFP_FRAGMENT_MAGIC_NUMBER = "FRAG"; -const char *TAO_SFP::TAO_SFP_START_MAGIC_NUMBER = "=STA"; -const char *TAO_SFP::TAO_SFP_CREDIT_MAGIC_NUMBER = "=CRE"; -const char *TAO_SFP::TAO_SFP_STARTREPLY_MAGIC_NUMBER = "=STR"; +const char *TAO_SFP_Base::TAO_SFP_MAGIC_NUMBER = "=SFP"; +const char *TAO_SFP_Base::TAO_SFP_FRAGMENT_MAGIC_NUMBER = "FRAG"; +const char *TAO_SFP_Base::TAO_SFP_START_MAGIC_NUMBER = "=STA"; +const char *TAO_SFP_Base::TAO_SFP_CREDIT_MAGIC_NUMBER = "=CRE"; +const char *TAO_SFP_Base::TAO_SFP_STARTREPLY_MAGIC_NUMBER = "=STR"; // SFP version 1.0 -const unsigned char TAO_SFP::TAO_SFP_MAJOR_VERSION = 1; -const unsigned char TAO_SFP::TAO_SFP_MINOR_VERSION = 0; +const unsigned char TAO_SFP_Base::TAO_SFP_MAJOR_VERSION = 1; +const unsigned char TAO_SFP_Base::TAO_SFP_MINOR_VERSION = 0; // lengths of various SFP headers -const unsigned char TAO_SFP::TAO_SFP_FRAME_HEADER_LEN = 12; +const unsigned char TAO_SFP_Base::TAO_SFP_FRAME_HEADER_LEN = 12; +const unsigned char TAO_SFP_Base::TAO_SFP_MESSAGE_SIZE_OFFSET = 8; +const unsigned char TAO_SFP_Base::TAO_SFP_FRAGMENT_SIZE_OFFSET = 16; + +u_int TAO_SFP_Base::frame_header_len; +u_int TAO_SFP_Base::start_reply_len; +u_int TAO_SFP_Base::start_len; +u_int TAO_SFP_Base::credit_len; +u_int TAO_SFP_Base::fragment_len; int operator< (const TAO_SFP_Fragment_Node& left, @@ -27,82 +35,88 @@ operator< (const TAO_SFP_Fragment_Node& left, return left.fragment_info_.frag_number < right.fragment_info_.frag_number; } -// constructor. -TAO_SFP::TAO_SFP (CORBA::ORB_ptr orb, - ACE_Reactor* reactor, - ACE_Time_Value timeout1, - ACE_Time_Value timeout2, - SFP_Callback *callback) - :orb_ (orb), - reactor_ (reactor), - start_tries_ (10), - startReply_tries_ (10), - timeout1_ (timeout1), - timeout2_ (timeout2), - callback_ (callback), - sequence_num_ (0), - credit_num_ (10), - magic_number_len_ (sizeof (magic_number_)-1) + +//------------------------------------------------------------ +// TAO_SFP_Base +//------------------------------------------------------------ + +TAO_SFP_Base::TAO_SFP_Base (void) { + TAO_OutputCDR output_cdr; ACE_DECLARE_NEW_CORBA_ENV; + flowProtocol::frameHeader frame_header; + flowProtocol::fragment fragment; + flowProtocol::credit credit; + flowProtocol::Start start; + flowProtocol::StartReply start_reply; ACE_TRY { // fill in the default frameHeader fields. - this->frame_header_.magic_number [0] = '='; - this->frame_header_.magic_number [1] = 'S'; - this->frame_header_.magic_number [2] = 'F'; - this->frame_header_.magic_number [3] = 'P'; - this->frame_header_.flags = TAO_ENCAP_BYTE_ORDER; - this->output_cdr_.reset (); - this->output_cdr_.encode (flowProtocol::_tc_frameHeader, - &this->frame_header_, - 0, - ACE_TRY_ENV); + frame_header.magic_number [0] = '='; + frame_header.magic_number [1] = 'S'; + frame_header.magic_number [2] = 'F'; + frame_header.magic_number [3] = 'P'; + frame_header.flags = TAO_ENCAP_BYTE_ORDER; + output_cdr.reset (); + output_cdr.encode (flowProtocol::_tc_frameHeader, + &frame_header, + 0, + ACE_TRY_ENV); ACE_TRY_CHECK; - this->frame_header_len_ = this->output_cdr_.total_length (); + frame_header_len = output_cdr.total_length (); // fill in the default fragment message fields. - this->fragment_.magic_number [0] = 'F'; - this->fragment_.magic_number [1] = 'R'; - this->fragment_.magic_number [2] = 'A'; - this->fragment_.magic_number [3] = 'G'; - this->output_cdr_.reset (); - this->output_cdr_.encode (flowProtocol::_tc_fragment, - &this->fragment_, + fragment.magic_number [0] = 'F'; + fragment.magic_number [1] = 'R'; + fragment.magic_number [2] = 'A'; + fragment.magic_number [3] = 'G'; + output_cdr.reset (); + output_cdr.encode (flowProtocol::_tc_fragment, + &fragment, 0, ACE_TRY_ENV); ACE_TRY_CHECK; - this->fragment_len_ = this->output_cdr_.total_length (); + fragment_len = output_cdr.total_length (); // fill in the default Start message fields. - this->start_.magic_number [0] = '='; - this->start_.magic_number [1] = 'S'; - this->start_.magic_number [2] = 'T'; - this->start_.magic_number [3] = 'A'; - this->start_.major_version = TAO_SFP_MAJOR_VERSION; - this->start_.minor_version = TAO_SFP_MINOR_VERSION; - this->start_.flags = 0; - this->start_len_ = sizeof (this->start_); + start.magic_number [0] = '='; + start.magic_number [1] = 'S'; + start.magic_number [2] = 'T'; + start.magic_number [3] = 'A'; + start.major_version = TAO_SFP_Base::TAO_SFP_MAJOR_VERSION; + start.minor_version = TAO_SFP_Base::TAO_SFP_MINOR_VERSION; + start.flags = 0; + output_cdr.reset (); + output_cdr.encode (flowProtocol::_tc_Start, + &start, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + start_len = output_cdr.total_length (); // fill in the default StartReply message fields. - this->start_reply_.magic_number [0] = '='; - this->start_reply_.magic_number [1] = 'S'; - this->start_reply_.magic_number [2] = 'T'; - this->start_reply_.magic_number [3] = 'R'; - this->start_reply_.flags = 0; - this->start_reply_len_ = sizeof (this->start_reply_); + start_reply.magic_number [0] = '='; + start_reply.magic_number [1] = 'S'; + start_reply.magic_number [2] = 'T'; + start_reply.magic_number [3] = 'R'; + start_reply.flags = 0; + output_cdr.reset (); + output_cdr.encode (flowProtocol::_tc_StartReply, + &start_reply, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + start_reply_len = output_cdr.total_length (); + // fill in the default Credit message fields. - this->credit_.magic_number [0] = '='; - this->credit_.magic_number [1] = 'C'; - this->credit_.magic_number [2] = 'R'; - this->credit_.magic_number [3] = 'E'; - this->credit_len_ = sizeof (this->credit_); - this->output_cdr_.reset (); - // this->output_cdr_ <<= this->credit_; - this->output_cdr_.reset (); - this->output_cdr_.encode (flowProtocol::_tc_credit, - &this->credit_, - 0, - ACE_TRY_ENV); + credit.magic_number [0] = '='; + credit.magic_number [1] = 'C'; + credit.magic_number [2] = 'R'; + credit.magic_number [3] = 'E'; + output_cdr.reset (); + output_cdr.encode (flowProtocol::_tc_credit, + &credit, + 0, + ACE_TRY_ENV); ACE_TRY_CHECK; - this->credit_len_ = this->output_cdr_.total_length (); + credit_len = output_cdr.total_length (); } ACE_CATCHANY { @@ -111,859 +125,821 @@ TAO_SFP::TAO_SFP (CORBA::ORB_ptr orb, ACE_ENDTRY; } -// Start the active end of the stream. int -TAO_SFP::start_stream (const char *receiver_addr) +TAO_SFP_Base::handle_input (TAO_AV_Transport *transport, + TAO_SFP_Frame_State &state, + TAO_AV_frame_info *&frame_info) { int result; - ACE_INET_Addr sender; - result = this->connect_to_receiver (receiver_addr); + flowProtocol::MsgType msg_type; + result = TAO_SFP_Base::peek_message_type (transport, + msg_type); if (result < 0) return result; - while (this->start_tries_ > 0) + // TAO_InputCDR &input = state.cdr; + switch (msg_type) { - result = this->send_start (); - if (result != 0) - return result; - // Timed recv. - char magic_number [MAGIC_NUMBER_LEN]; - ssize_t n =this->dgram_.recv (magic_number, - this->magic_number_len_, - sender, - MSG_PEEK, - &this->timeout1_); - // ACE_DEBUG ((LM_DEBUG,"n = %d\n",n)); + case flowProtocol::SimpleFrame_Msg: + case flowProtocol::Frame_Msg: + { + result = TAO_SFP_Base::peek_frame_header (transport, + state.frame_header_, + state.cdr); + if (result < 0) + return result; + int result =TAO_SFP_Base::read_frame (transport, + state.frame_header_, + state, + frame_info); + if (result < 0) + return result; + break; + } + case flowProtocol::Fragment_Msg: + { + result = TAO_SFP_Base::peek_fragment_header (transport, + state.fragment_, + state.cdr); + if (result < 0) + return result; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Fragment received\n")); + result = TAO_SFP_Base::read_fragment (transport, + state.fragment_, + state, + frame_info); + if (result < 0) + return result; + break; + } + case flowProtocol::EndofStream_Msg: + { + result = TAO_SFP_Base::read_endofstream_message (transport, + state.frame_header_, + state.cdr); + if (result < 0) + return result; + break; + } + default: + break; + } + return 0; +} + +int +TAO_SFP_Base::read_frame (TAO_AV_Transport *transport, + flowProtocol::frameHeader &frame_header, + TAO_SFP_Frame_State &state, + TAO_AV_frame_info *&frame_info) +{ + ACE_Message_Block *message_block = 0; + int result = -1; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Reading simple frame\n")); + // Check to see what the length of the message is. + int byte_order = frame_header.flags & 0x1; + int message_len = frame_header.message_size; + +// ACE_NEW_RETURN (message_block, +// ACE_Message_Block (message_len), +// 0); + state.static_frame_.rd_ptr (state.static_frame_.base ()); + state.static_frame_.wr_ptr (state.static_frame_.base ()); + int n = transport->recv (state.static_frame_.rd_ptr (),message_len); if (n == -1) + ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input -peek"),0); + else if (n==0) + ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input -peek"),0); + else if (n != message_len) + ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_simple_frame:message truncated\n"),0); + message_block = &state.static_frame_; + // print the buffer. + // this->dump_buf (message,n); + // skip over the frame header. + message_block->rd_ptr (frame_header_len); + message_block->wr_ptr (n); + CORBA::ULong ssrc = 0; + TAO_SFP_Fragment_Table_Entry *fragment_entry = 0; + if (frame_header.flags & 0x2) { - if (errno == ETIME) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"fragmented frame:0th fragment\n")); + state.more_fragments_ = 1; + ACE_Message_Block *data = 0; + switch (frame_header.message_type) + { + case flowProtocol::Frame_Msg: + { + // read the frame info. + ACE_Message_Block frame_info_mb (message_len-frame_header_len+ACE_CDR::MAX_ALIGNMENT); + ACE_CDR::mb_align (&frame_info_mb); + frame_info_mb.copy (message_block->rd_ptr (), + message_block->length ()); + // print the buffer. + // this->dump_buf (message_block->rd_ptr (),16); + TAO_InputCDR frame_info_cdr (&frame_info_mb,byte_order); + frame_info_cdr.decode (flowProtocol::_tc_frame, + &state.frame_, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"frame.timestamp = %d, frame.synchsource = %d, frame.sequence_num = %d\n", + state.frame_.timestamp, + state.frame_.synchSource, + state.frame_.sequence_num)); + ssrc = state.frame_.synchSource; + // The remaining message in the CDR stream is the fragment data for frag.0 + data = frame_info_cdr.start ()->clone (); + break; + } + case flowProtocol::SimpleFrame_Msg: + { + data = message_block->clone (); + break; + } + case flowProtocol::SequencedFrame_Msg: + break; + case flowProtocol::SpecialFrame_Msg: + break; + } + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Length of 0th fragment= %d\n",data->length ())); + TAO_SFP_Fragment_Table *fragment_table = 0; + result = state.fragment_table_map_.find (ssrc,fragment_table); + if (result != 0) { - ACE_DEBUG ((LM_DEBUG,"Timed out in reading StartReply")); - this->start_tries_ --; - continue; + ACE_NEW_RETURN (fragment_table, + TAO_SFP_Fragment_Table, + -1); + result = state.fragment_table_map_.bind (ssrc,fragment_table); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP_Base::read_frame: fragment_table_map:bind failed\n"),-1); } + + TAO_SFP_Fragment_Node *new_node; + ACE_NEW_RETURN (new_node, + TAO_SFP_Fragment_Node, + 0); + new_node->fragment_info_.frag_sz = data->length (); + new_node->fragment_info_.frag_number = 0; + if (state.frame_.source_ids.length () > 0) + new_node->fragment_info_.source_id = state.frame_.source_ids [0]; else - ACE_ERROR_RETURN ((LM_ERROR,"dgram recv error:%d,%p",errno,"recv"),-1); + new_node->fragment_info_.source_id = 0; + new_node->data_ = data; + // TAO_SFP_Base::dump_buf (data->rd_ptr (),data->length ()); + if (fragment_table->find (state.frame_.sequence_num,fragment_entry) == 0) + { + // This case can happen where a nth (n > 0)fragment is received before the 0th fragment. + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"fragment table entry found for 0th fragment:\n")); + result = fragment_entry->fragment_set_.insert (*new_node); + if (result != 0) + ACE_ERROR_RETURN ((LM_ERROR,"insert for 0th fragment failed\n"),0); + // enter the frame info. + + // check if all the fragments have been received. + state.frame_block_ = TAO_SFP_Base::check_all_fragments (fragment_entry); + if (state.frame_block_ != 0) + state.more_fragments_ = 0; + } + else + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"fragment table entry not found for 0th fragment\n")); + TAO_SFP_Fragment_Table_Entry *new_entry; + ACE_NEW_RETURN (new_entry, + TAO_SFP_Fragment_Table_Entry, + 0); + result = new_entry->fragment_set_.insert (*new_node); + if (result != 0) + ACE_ERROR_RETURN ((LM_ERROR,"insert for 0th fragment failed\n"),0); + fragment_entry = new_entry; + // not found. so bind a new entry. + result = fragment_table->bind (state.frame_.sequence_num,new_entry); + if (result != 0) + ACE_ERROR_RETURN ((LM_ERROR,"fragment table bind failed\n"),0); + if (frame_header.message_type & 4 ) + fragment_entry->frame_info.boundary_marker = 1; + switch (frame_header.message_type) + { + case flowProtocol::Frame_Msg: + fragment_entry->frame_info.ssrc = state.frame_.synchSource; + fragment_entry->frame_info.timestamp = state.frame_.timestamp; + fragment_entry->frame_info.sequence_num = state.frame_.sequence_num; + break; + case flowProtocol::SimpleFrame_Msg: + fragment_entry->frame_info.ssrc = + fragment_entry->frame_info.timestamp = + fragment_entry->frame_info.sequence_num = 0; + break; + } + return 0; + } } - else if (n==0) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::start_stream -peek"),-1); - // Null terminate the magic number. - magic_number [this->magic_number_len_] = 0; - // check if its startreply message. - if (ACE_OS::strcmp (magic_number,TAO_SFP_STARTREPLY_MAGIC_NUMBER) == 0) + else { - ACE_DEBUG ((LM_DEBUG,"(%P|%t)StartReply message received\n")); - flowProtocol::StartReply start_reply; - n = this->dgram_.recv ((char *)&start_reply, - sizeof (start_reply), - sender); - if (n != sizeof (start_reply)) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input-StartReply\n"),0); - // check for SFP version difference.?? - this->state_ = REPLY_RECEIVED; + state.more_fragments_ = 0; + state.frame_block_ = message_block; + } + if (state.more_fragments_ == 0) + { + if (fragment_entry != 0) + { + ACE_NEW_RETURN (frame_info, + TAO_AV_frame_info, + -1); + *frame_info = fragment_entry->frame_info; + } } - else - ACE_ERROR_RETURN ((LM_ERROR,"Invalid message while StartReply expected\n"),0); - // register the data handler. - return this->register_dgram_handler (); } + ACE_CATCHANY + { + ACE_TRY_ENV.print_exception ("read_simple_frame"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); return 0; } -// Start the passive end of the stream. int -TAO_SFP::start_stream (const char *local_addr,int /* Credit */) +TAO_SFP_Base::read_fragment (TAO_AV_Transport *transport, + flowProtocol::fragment &fragment, + TAO_SFP_Frame_State &state, + TAO_AV_frame_info *&frame_info) { - int result; - ACE_INET_Addr sender; + TAO_SFP_Fragment_Table_Entry *fragment_entry = 0; + int result = -1; - this->state_ = PASSIVE_START; - ACE_INET_Addr myaddr (local_addr); - result = this->dgram_.open (myaddr); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"frag_number = %d, frag_size = %d,source_id = %d sequnce_num = %d\n", + fragment.frag_number,fragment.frag_sz,fragment.source_id,fragment.sequence_num)); + ACE_Message_Block *data; + ACE_NEW_RETURN (data, + ACE_Message_Block(fragment.frag_sz), + -1); + + // Read the fragment. + int n = transport->recv (data->wr_ptr (),fragment.frag_sz); + if ((n == -1) || (n==0)) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP::read_fragment:%p",""),-1); + // move past the fragment header. + data->rd_ptr (fragment_len); + data->wr_ptr (n); + // TAO_SFP_Base::dump_buf (data->rd_ptr (),data->length ()); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"length of %dth fragment is: %d\n", + fragment.frag_number, + data->length ())); + + TAO_SFP_Fragment_Node *new_node; + ACE_NEW_RETURN (new_node, + TAO_SFP_Fragment_Node, + -1); + new_node->fragment_info_ = fragment; + new_node->data_ = data; + TAO_SFP_Fragment_Table *fragment_table = 0; + result = state.fragment_table_map_.find (fragment.source_id,fragment_table); if (result != 0) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::passive start- open failed\n"),-1); - - char magic_number[MAGIC_NUMBER_LEN]; - // Timed recv. - ssize_t n =this->dgram_.recv (magic_number, - this->magic_number_len_, - sender, - MSG_PEEK, - &this->timeout2_); - if ((n == -1) && (errno == ETIME)) { - ACE_ERROR_RETURN ((LM_ERROR,"Timedout in reading Start"),-1); + ACE_NEW_RETURN (fragment_table, + TAO_SFP_Fragment_Table, + -1); + result = state.fragment_table_map_.bind (fragment.source_id,fragment_table); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP_Base::read_fragment:fragment_table_map:bind failed\n"),-1); } - else if (n==0) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::start_stream -peek"),-1); - // Null terminate the magic_number. - magic_number [this->magic_number_len_] = 0; - if (ACE_OS::strcmp (magic_number,TAO_SFP_START_MAGIC_NUMBER) == 0) + if (fragment_table->find (fragment.sequence_num,fragment_entry) == 0) { - ACE_DEBUG ((LM_DEBUG,"Start received:")); - // Read the start message. - flowProtocol::Start start; - n = this->dgram_.recv ((char *)&start, - sizeof (start), - sender); - if (n != sizeof (start)) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input - Start\n"),0); - else - ACE_DEBUG ((LM_DEBUG,"Start message consumed\n")); - this->state_ = START_RECEIVED; - this->receiver_inet_addr_.set (sender); - // Now send a startReply message back. - result = this->send_startReply (); + // Already an entry exists. Traverse the list and insert it at the right place. + result = fragment_entry->fragment_set_.insert (*new_node); if (result != 0) - return result; - // Now we register a timeout handler until we receive a data - // frame. - result = this->reactor_->schedule_timer (this, - 0, - this->timeout1_); - if (result == -1) - ACE_ERROR_RETURN ((LM_ERROR,"schedule_timer failed\n"),result); - - // register the data handler. - return this->register_dgram_handler (); + ACE_ERROR_RETURN ((LM_ERROR,"insert for %dth node failed\n",fragment.frag_number),-1); + // check if all the fragments have been received. } else - ACE_ERROR_RETURN ((LM_ERROR,"Invalid messaged received while Start expected\n"),-1); + { + ACE_NEW_RETURN (fragment_entry, + TAO_SFP_Fragment_Table_Entry, + -1); + fragment_entry->fragment_set_.insert (*new_node); + // bind a new entry for this sequence number. + result = fragment_table->bind (fragment.sequence_num,fragment_entry); + if (result != 0) + ACE_ERROR_RETURN ((LM_ERROR,"bind for %dth fragment failed\n", + fragment.frag_number),-1); + } + if (!(fragment.flags & 0x2)) + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Last fragment received\n")); + // if bit 1 is not set then there are + // no more fragments. + fragment_entry->last_received_ = 1; + // since fragment number starts from 0 to n-1 we add 1. + fragment_entry->num_fragments_ = fragment.frag_number + 1; + } + + + state.frame_block_ = check_all_fragments (fragment_entry); + if (state.frame_block_ != 0) + { + state.more_fragments_ = 0; + ACE_NEW_RETURN (frame_info, + TAO_AV_frame_info, + -1); + *frame_info = fragment_entry->frame_info; + } + return 0; } -// Sends the ACE_Message_Block data as a frame, fragmenting if necessary. -int -TAO_SFP::send_frame (ACE_Message_Block *frame) +ACE_Message_Block* +TAO_SFP_Base::check_all_fragments (TAO_SFP_Fragment_Table_Entry *fragment_entry) { - ACE_TRY_NEW_ENV + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"table size: %d, num_fragments: %d\n",fragment_entry->fragment_set_.size (),fragment_entry->num_fragments_)); + // check to see if all the frames have been received. + if (fragment_entry->fragment_set_.size () == fragment_entry->num_fragments_) { - if (this->credit_num_ > 0) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"all fragments have been received\n")); + // all the fragments have been received + // we can now chain the ACE_Message_Blocks in the fragment_set_ and then return them + // back. + ACE_Message_Block *frame = 0,*head = 0; + FRAGMENT_SET_ITERATOR frag_iterator (fragment_entry->fragment_set_); + TAO_SFP_Fragment_Node *node; + for (;frag_iterator.next (node) != 0;frag_iterator.advance ()) { - // if we have enough credit then we send. - int total_length = 0; - for (ACE_Message_Block *temp = frame;temp != 0;temp = temp->cont ()) - total_length += temp->length (); - ACE_DEBUG ((LM_DEBUG,"total_length of frame=%d\n",total_length)); - if (total_length < (SFP_MAX_PACKET_SIZE -this->frame_header_len_)) - { - // clear the output cdr. - this->output_cdr_.reset (); - // CDR encode the frame header. - //(<<= isAvailable only in compiled marshalling!) - this->frame_header_.message_type = flowProtocol::SimpleFrame_Msg; - this->frame_header_.message_size = frame->length ()+this->frame_header_len_; - this->output_cdr_.encode (flowProtocol::_tc_frameHeader, - &this->frame_header_, - 0, - ACE_TRY_ENV); - ACE_TRY_CHECK; - // this->output_cdr_ <<= this->frame_header_; - this->send_cdr_buffer (this->output_cdr_,frame); - } - else // larger frame,fragment and send it. + if (!head) + head = frame = node->data_; + else { - // set the fragments bit. - this->frame_header_.flags |= 2; - // This is a good maximum, because Dgrams cannot be longer than - // 64K and the usual size for a CDR fragment is 512 bytes. - // @@ TODO In the future we may need to allocate some memory - // from the heap. - int message_len = this->frame_header_len_; - iovec iov[TAO_WRITEV_MAX]; - int iovcnt = 1;// since first iov is for frameHeader. - flowProtocol::frame frame_info; - frame_info.timestamp = 10; - frame_info.synchSource = 10; - frame_info.source_ids.length (1); - frame_info.source_ids [0] = 1; // XXX random number. - frame_info.sequence_num = this->sequence_num_; - this->output_cdr_.reset (); - this->output_cdr_.encode (flowProtocol::_tc_frame, - &frame_info, - 0, - ACE_TRY_ENV); - ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"frame info length:%d\n",this->output_cdr_.total_length ())); - for (const ACE_Message_Block* b = this->output_cdr_.begin ()->clone (); - b != 0 && iovcnt < TAO_WRITEV_MAX; - b = b->cont ()) - { - // ACE_DEBUG ((LM_DEBUG,"iovcnt:%d\n",iovcnt)); - iov[iovcnt].iov_base = b->rd_ptr (); - iov[iovcnt].iov_len = b->length (); - message_len += b->length (); - ACE_DEBUG ((LM_DEBUG,"send_cdr_buffer:length=%d\n",b->length ())); - // print the buffer. - // this->dump_buf (b->rd_ptr (),b->length ()); - iovcnt++; - } - ACE_Message_Block *mb = frame; - int prev_len; - while (mb != 0) - { - prev_len = message_len; - message_len += mb->length (); - if (message_len > SFP_MAX_PACKET_SIZE) - { - // get only the length that we can accomodate. - size_t current_len = SFP_MAX_PACKET_SIZE - prev_len; - if (current_len < mb->length ()) - { - // The above condition is an assertion. - iov [iovcnt].iov_base = mb->rd_ptr (); - iov [iovcnt].iov_len = current_len; - message_len += (current_len-mb->length ()); - mb->rd_ptr (current_len); - iovcnt++; - } - break; - } - else - { - // we can accomodate this message block - iov [iovcnt].iov_base = mb->rd_ptr (); - iov [iovcnt].iov_len = mb->length (); - message_len += mb->length (); - iovcnt++; - mb = mb->cont (); - } - } - // This can be either a simpleframe or a sequenced frame,other types of frames. - this->frame_header_.message_type = flowProtocol::Frame_Msg; - this->frame_header_.message_size = message_len; - ACE_DEBUG ((LM_DEBUG,"first fragment of size:%d\n",message_len- this->frame_header_len_)); - this->output_cdr_.reset (); - this->output_cdr_.encode (flowProtocol::_tc_frameHeader, - &this->frame_header_, - 0, - ACE_TRY_ENV); - ACE_TRY_CHECK; - // header will be only in the first cdr fragment. - iov[0].iov_base = this->output_cdr_.begin ()->rd_ptr (); - iov[0].iov_len = this->output_cdr_.begin ()->length (); - ACE_DEBUG ((LM_DEBUG,"frame header len:%d\n",iov[0].iov_len)); - // send the first fragment. - for (int i=0;i<iovcnt;i++) - { - // this->dump_buf (iov[i].iov_base,iov[i].iov_len); - } - ssize_t n = this->dgram_.send (iov, - iovcnt, - this->receiver_inet_addr_); - if (n == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "send_frame (%t) fragment 0 send failed %p\n", ""),-1); - else if (n == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "send_Frame (%t) EOF on send \n"),-1); - - int frag_number = 1; - // If there is any more data send those as fragments. - while (mb != 0) - { - message_len = this->fragment_len_; - iovcnt = 1;// 1 is for the frag header. - while (mb != 0) - { - prev_len = message_len; - message_len += mb->length (); - if (message_len > SFP_MAX_PACKET_SIZE) - { - // get only the length that we can accomodate. - size_t current_len = SFP_MAX_PACKET_SIZE - prev_len; - if (current_len < mb->length ()) - { - // The above condition is an assertion. - iov [iovcnt].iov_base = mb->rd_ptr (); - iov [iovcnt].iov_len = current_len; - message_len += (current_len - mb->length ()); - mb->rd_ptr (current_len); - iovcnt++; - } - break; - } - else - { - // we can accomodate this message block - iov [iovcnt].iov_base = mb->rd_ptr (); - iov [iovcnt].iov_len = mb->length (); - iovcnt++; - mb = mb->cont (); - } - } - this->fragment_.flags = TAO_ENCAP_BYTE_ORDER; - if (mb == 0) - { - ACE_DEBUG ((LM_DEBUG,"sending the last fragment\n")); - // This is the last fragment so clear the fragments bit. - } - else - { - // set the more fragments flag - this->fragment_.flags |= 2; - } - // if there are no data blocks. - if (iovcnt == 1) - break; - this->fragment_.frag_number = frag_number++; - this->fragment_.sequence_num = this->sequence_num_; - this->fragment_.frag_sz = message_len; - this->fragment_.source_id = 0; - this->output_cdr_.reset (); - this->output_cdr_.encode (flowProtocol::_tc_fragment, - &this->fragment_, - 0, - ACE_TRY_ENV); - ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"sending a fragment numbered %d of size %d\n", - this->fragment_.frag_number, - this->fragment_.frag_sz)); - // THe header will be only in the first cdr fragment. - iov[0].iov_base = this->output_cdr_.begin ()->rd_ptr (); - iov[0].iov_len = this->output_cdr_.begin ()->length (); - // send the fragment now. - // without the sleep the fragments gets lost! - // probably because the UDP buffer queue on the sender side - // is overflown it drops the packets. - // XXX: This is a hack. - ACE_OS::sleep (1); - ssize_t n = this->dgram_.send (iov, - iovcnt, - this->receiver_inet_addr_); - if ((n == -1) || (n==0)) - ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP::send_framed failed:%p\n",""),-1); - } + frame->cont (node->data_); + frame = node->data_; } } - else - { - // flow controlled so wait. - } + return head; + } + return 0; +} + +CORBA::Boolean +TAO_SFP_Base::start_frame (CORBA::Octet flags, + flowProtocol::MsgType type, + TAO_OutputCDR &msg) +{ + ACE_DECLARE_NEW_CORBA_ENV; + msg.reset (); + flowProtocol::frameHeader frame_header; + ACE_TRY + { + + frame_header.magic_number [0] = '='; + frame_header.magic_number [1] = 'S'; + frame_header.magic_number [2] = 'F'; + frame_header.magic_number [3] = 'P'; + frame_header.flags = flags; + frame_header.message_type = type; + frame_header.message_size = 0; + msg.encode (flowProtocol::_tc_frameHeader, + &frame_header, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP::send_frame"); - return -1; + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::start_frame"); + return 0; } ACE_ENDTRY; - return 0; + ACE_CHECK_RETURN (0); + return 1; } - -// creates a connected dgram. -int -TAO_SFP::connect_to_receiver (const char *receiver_addr) +CORBA::Boolean +TAO_SFP_Base::write_start_message (TAO_OutputCDR &msg) { - this->receiver_addr_ = ACE_OS::strdup (receiver_addr); - // Get the local UDP address - if (this->dgram_.open (ACE_Addr::sap_any) == -1) - ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) datagram open failed %p\n"),1); - - // set the socket buffer sizes to 64k. - int sndbufsize = ACE_DEFAULT_MAX_SOCKET_BUFSIZ; - int rcvbufsize = ACE_DEFAULT_MAX_SOCKET_BUFSIZ; - - if (this->dgram_.set_option (SOL_SOCKET, - SO_SNDBUF, - (void *) &sndbufsize, - sizeof (sndbufsize)) == -1 - && errno != ENOTSUP) - return -1; - else if (this->dgram_.set_option (SOL_SOCKET, - SO_RCVBUF, - (void *) &rcvbufsize, - sizeof (rcvbufsize)) == -1 - && errno != ENOTSUP) - return -1; - - this->receiver_inet_addr_.set (receiver_addr); - return 0; + ACE_DECLARE_NEW_CORBA_ENV; + flowProtocol::Start start; + ACE_TRY + { + start.magic_number [0] = '='; + start.magic_number [1] = 'S'; + start.magic_number [2] = 'T'; + start.magic_number [3] = 'A'; + start.major_version = TAO_SFP_MAJOR_VERSION; + start.minor_version = TAO_SFP_MINOR_VERSION; + start.flags = 0; + msg.encode (flowProtocol::_tc_Start, + &start, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::write_start_message"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; } -// sends all the ACE_Message_Blocks in the current CDR stream. -int -TAO_SFP::send_cdr_buffer (TAO_OutputCDR &cdr,ACE_Message_Block *mb) +CORBA::Boolean +TAO_SFP_Base::write_start_reply_message (TAO_OutputCDR &msg) { - // This is a good maximum, because Dgrams cannot be longer than - // 64K and the usual size for a CDR fragment is 512 bytes. - // @@ TODO In the future we may need to allocate some memory - // from the heap. - iovec iov[TAO_WRITEV_MAX]; - int iovcnt = 0; - const ACE_Message_Block* b = 0; - for (b = cdr.begin (); - b != cdr.end () && iovcnt < TAO_WRITEV_MAX; - b = b->cont ()) + ACE_DECLARE_NEW_CORBA_ENV; + flowProtocol::StartReply start_reply; + ACE_TRY { - iov[iovcnt].iov_base = b->rd_ptr (); - iov[iovcnt].iov_len = b->length (); - // ACE_DEBUG ((LM_DEBUG,"send_cdr_buffer:length=%d\n",b->length ())); - // print the buffer. - // this->dump_buf (b->rd_ptr (),b->length ()); - iovcnt++; + start_reply.magic_number [0] = '='; + start_reply.magic_number [1] = 'S'; + start_reply.magic_number [2] = 'T'; + start_reply.magic_number [3] = 'R'; + start_reply.flags = 0; + msg.encode (flowProtocol::_tc_StartReply, + &start_reply, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; } - for (b = mb; b!=0 && iovcnt < TAO_WRITEV_MAX; b=b->cont ()) + ACE_CATCHANY { - iov [iovcnt].iov_base = b->rd_ptr (); - iov [iovcnt].iov_len = b->length (); - iovcnt++; + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::write_start_reply_message"); + return 0; } - // send the message. - ssize_t n = this->dgram_.send (iov, - iovcnt, - this->receiver_inet_addr_); - if (n == -1) + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; +} + +CORBA::Boolean +TAO_SFP_Base::write_credit_message (CORBA::ULong cred_num, + TAO_OutputCDR &msg) +{ + ACE_DECLARE_NEW_CORBA_ENV; + flowProtocol::credit credit; + ACE_TRY { - ACE_DEBUG ((LM_DEBUG, - "SFP::send_cdr_buffer (%t) send failed %p\n", "")); - return -1; + credit.magic_number [0] = '='; + credit.magic_number [1] = 'C'; + credit.magic_number [2] = 'R'; + credit.magic_number [3] = 'E'; + credit.cred_num = cred_num; + msg.encode (flowProtocol::_tc_credit, + &credit, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; } - else if (n == 0) + ACE_CATCHANY { - ACE_DEBUG ((LM_DEBUG, - "SFP::send_cdr_buffer (%t) EOF on send \n")); - return -1; + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::write_credit_message"); + return 0; } - return 0; + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; } -int -TAO_SFP::send_start (void) +CORBA::Boolean +TAO_SFP_Base::write_fragment_message (CORBA::Octet flags, + CORBA::ULong fragment_number, + CORBA::ULong sequence_number, + CORBA::ULong source_id, + TAO_OutputCDR &msg) { - // copy the magic number into the message - this->state_ = ACTIVE_START; - // Now send the network byte ordered start message. - int n = this->dgram_.send ((char *)&this->start_, - this->start_len_, - this->receiver_inet_addr_); - if (n!= this->start_len_) - ACE_ERROR_RETURN ((LM_ERROR,"start send failed\n"),-1); - - ACE_DEBUG ((LM_DEBUG," Start sent\n")); - return 0; + ACE_DECLARE_NEW_CORBA_ENV; + msg.reset (); + flowProtocol::fragment fragment; + ACE_TRY + { + fragment.magic_number [0] = 'F'; + fragment.magic_number [1] = 'R'; + fragment.magic_number [2] = 'A'; + fragment.magic_number [3] = 'G'; + fragment.flags = flags; + fragment.frag_number = fragment_number; + fragment.sequence_num = sequence_number; + fragment.source_id = source_id; + msg.encode (flowProtocol::_tc_fragment, + &fragment, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::write_fragment_message"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; } -int -TAO_SFP::send_startReply (void) +CORBA::Boolean +TAO_SFP_Base::write_frame_message (CORBA::ULong timestamp, + CORBA::ULong synchSource, + flowProtocol::my_seq_ulong source_ids, + CORBA::ULong sequence_num, + TAO_OutputCDR &msg) { - int n = this->dgram_.send ((char *)&this->start_reply_, - this->start_reply_len_, - this->receiver_inet_addr_); - if (n!= this->start_reply_len_) - ACE_ERROR_RETURN ((LM_ERROR,"startreply send failed\n"),-1); - - ACE_DEBUG ((LM_DEBUG," startReply sent\n")); - return 0; + ACE_DECLARE_NEW_CORBA_ENV; + flowProtocol::frame frame; + ACE_TRY + { + frame.timestamp = timestamp; + frame.synchSource = synchSource; + frame.source_ids = source_ids; + frame.sequence_num = sequence_num; + msg.encode (flowProtocol::_tc_frame, + &frame, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::write_frame_message"); + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + return 1; } int -TAO_SFP::handle_timeout (const ACE_Time_Value &/* tv */, - const void * /* arg */) +TAO_SFP_Base::send_message (TAO_AV_Transport *transport, + TAO_OutputCDR &stream, + ACE_Message_Block *mb) { - int result; - // Handle the timeout for timeout1 and timeout2. - switch (this->state_) + size_t total_len = stream.total_length (); + if (mb != 0) { - case ACTIVE_START: - case PASSIVE_START: - // Timingout for Start Messages. - ACE_DEBUG ((LM_DEBUG,"Invalid state in handle_timeout\n")); - break; - case START_RECEIVED: - // we need to reduce the startreply_tries and also reschedule - // the timer. - if (this->startReply_tries_ --) + for (ACE_Message_Block *temp = mb;temp != 0;temp = temp->cont ()) + total_len += temp->length (); + + char *buf = (char *) stream.buffer (); + size_t offset = TAO_SFP_MESSAGE_SIZE_OFFSET; + // second character distinguished =SFP and FRAG. + if (*(buf) == 'F') { - ACE_DEBUG ((LM_DEBUG,"Timed out on receiving Data Frame\n")); - // send startreply. - result = this->send_startReply (); - if (result != 0) - ACE_ERROR_RETURN ((LM_ERROR,"Error in sending startreply"),0); - this->reactor_->schedule_timer (this, - 0, - this->timeout1_); + // Fragment message. + offset = TAO_SFP_FRAGMENT_SIZE_OFFSET; } +#if !defined (ACE_ENABLE_SWAP_ON_WRITE) + *ACE_reinterpret_cast (CORBA::ULong *, buf + offset) = total_len; +#else + if (!stream->do_byte_swap ()) + *ACE_reinterpret_cast (CORBA::ULong *, + buf + offset) = total_len; else - { - this->end_stream (); - } - break; - default: - ACE_DEBUG ((LM_DEBUG,"Handle_timeout: No Action in this state %d",this->state_)); + ACE_CDR::swap_4 (ACE_reinterpret_cast (char *, + &total_len), + buf + offset); +#endif /* ACE_ENABLE_SWAP_ON_WRITE */ } - return 0; + // we join the data block with the cdr block. + ACE_Message_Block *end = (ACE_Message_Block *)stream.end (); + if (end == 0) + { + // There is only one message block. + end = (ACE_Message_Block *)stream.begin (); + // TAO_SFP_Base::dump_buf (end->rd_ptr (),end->length ()); + } + end->cont (mb); + ssize_t n = transport->send (stream.begin ()); + if (n == -1) + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, + "TAO: (%P|%t) closing conn after fault %p\n", + "GIOP::send_request ()")); + return -1; + } + // EOF. + if (n == 0) + { + if (TAO_orbdebug) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, + "TAO: (%P|%t) GIOP::send_request () " + "EOF, closing conn:\n")); + return -1; + } + return 1; + } -// Handle_input is called when data arrives on the dgram -// socket. Currently both the receiver and sender side input is -// handled in this same handle_input (). int -TAO_SFP::handle_input (ACE_HANDLE /* fd */) +TAO_SFP_Base::peek_message_type (TAO_AV_Transport *transport, + flowProtocol::MsgType &msg_type) { - // ACE_DEBUG ((LM_DEBUG,"TAO_SFP::handle_input\n")); - flowProtocol::MsgType msg_type = flowProtocol::Start_Msg; - ACE_INET_Addr sender; - char peek_buffer [MAGIC_NUMBER_LEN+2];// 2 is for flags + message_type. - int peek_len = MAGIC_NUMBER_LEN +2; - ssize_t n =this->dgram_.recv (peek_buffer, - peek_len, - sender, - MSG_PEEK); - ACE_OS::strncpy (this->magic_number_, + char peek_buffer [TAO_SFP_MAGIC_NUMBER_LEN+2];// 2 is for flags + message_type. + int peek_len = TAO_SFP_MAGIC_NUMBER_LEN +2; + char magic_number [TAO_SFP_MAGIC_NUMBER_LEN+1]; + ssize_t n =transport->recv (peek_buffer, + peek_len, + MSG_PEEK); + ACE_OS::strncpy (magic_number, peek_buffer, - this->magic_number_len_); - this->magic_number_ [this->magic_number_len_] = 0; + TAO_SFP_MAGIC_NUMBER_LEN); + magic_number [TAO_SFP_MAGIC_NUMBER_LEN] = 0; if (n == -1) ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input -peek"),-1); else if (n==0) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input -peek"),0); + ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input -peek"),-1); - if (ACE_OS::strcmp (this->magic_number_,TAO_SFP_START_MAGIC_NUMBER) == 0) + if (ACE_OS::strcmp (magic_number,TAO_SFP_START_MAGIC_NUMBER) == 0) { - ACE_DEBUG ((LM_DEBUG,"(%P|%t)Start message received\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)Start message received\n")); msg_type = flowProtocol::Start_Msg; } - else if (ACE_OS::strcmp (this->magic_number_,TAO_SFP_STARTREPLY_MAGIC_NUMBER) == 0) + else if (ACE_OS::strcmp (magic_number,TAO_SFP_STARTREPLY_MAGIC_NUMBER) == 0) { - ACE_DEBUG ((LM_DEBUG,"(%P|%t)StartReply message received\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t)StartReply message received\n")); msg_type = flowProtocol::StartReply_Msg; } - else if (ACE_OS::strcmp (this->magic_number_,TAO_SFP_MAGIC_NUMBER) == 0) + else if (ACE_OS::strcmp (magic_number,TAO_SFP_MAGIC_NUMBER) == 0) { - // ACE_DEBUG ((LM_DEBUG,"(%P|%t) frameHeader received\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t) frameHeader received\n")); // msg_type = flowProtocol::SimpleFrame; - msg_type = (flowProtocol::MsgType)peek_buffer [MESSAGE_TYPE_OFFSET]; - ACE_DEBUG ((LM_DEBUG,"Message Type = %d\n",msg_type)); + msg_type = (flowProtocol::MsgType)peek_buffer [TAO_SFP_MESSAGE_TYPE_OFFSET]; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"Message Type = %d\n",msg_type)); } - else if (ACE_OS::strcmp (this->magic_number_,TAO_SFP_FRAGMENT_MAGIC_NUMBER) == 0) + else if (ACE_OS::strcmp (magic_number,TAO_SFP_FRAGMENT_MAGIC_NUMBER) == 0) { - ACE_DEBUG ((LM_DEBUG,"(%P|%t) fragment Header received\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t) fragment Header received\n")); msg_type = flowProtocol::Fragment_Msg; } - else if (ACE_OS::strcmp (this->magic_number_,TAO_SFP_CREDIT_MAGIC_NUMBER) == 0) + else if (ACE_OS::strcmp (magic_number,TAO_SFP_CREDIT_MAGIC_NUMBER) == 0) { - ACE_DEBUG ((LM_DEBUG,"(%P|%t) credit message received\n")); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"(%P|%t) credit message received\n")); msg_type = flowProtocol::Credit_Msg; } else - ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP:Invalid magic number\n"),0); - switch (this->state_) - { - case ACTIVE_START: - // Check if we received a StartReply back. - ACE_DEBUG ((LM_DEBUG,"Unexpected message while StartReply expected\n")); - break; - case PASSIVE_START: - // Check if we received a Start from the Sender. - ACE_DEBUG ((LM_DEBUG,"Unexpected message while Start expected\n")); - break; - case START_RECEIVED: - // In this state we check for credit frames. - switch (msg_type) - { - case flowProtocol::Credit_Msg: - { - flowProtocol::credit credit; - n = this->dgram_.recv ((char *)&credit, - sizeof (credit), - sender); - if (n != sizeof (credit)) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input - Credit\n"),0); - break; - } - case flowProtocol::Start_Msg: - // consume the retransmitted start message. - { - flowProtocol::Start start; - n = this->dgram_.recv ((char *)&start, - sizeof (start), - sender); - if (n != sizeof (start)) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input - Start\n"),0); - else - ACE_DEBUG ((LM_DEBUG,"Start message consumed\n")); - break; - } + ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP:Invalid magic number\n"),-1); + return 0; +} - case flowProtocol::Frame_Msg: - case flowProtocol::SimpleFrame_Msg: - { - ACE_Message_Block * mb =this->read_simple_frame (); - if (mb != 0) - this->callback_->receive_frame (mb); - else - { - if (!this->more_fragments_) - { - char buf[BUFSIZ]; - // consume the wrong UDP frame. - this->dgram_.recv (buf, - BUFSIZ, - sender); - } - } - break; - } - case flowProtocol::Fragment_Msg: - { - ACE_DEBUG ((LM_DEBUG,"Fragment received\n")); - ACE_Message_Block *result = this->read_fragment (); - // no more fragments. - if (result != 0) - this->callback_->receive_frame (result); - break; - } - case flowProtocol::EndofStream_Msg: - { - char *buf; - ACE_NEW_RETURN (buf, - char [ this->frame_header_len_], - -1); - n = this->dgram_.recv (buf, - this->frame_header_len_, - sender); - if (n == -1) - ACE_ERROR_RETURN ((LM_ERROR,"Error reading EndofStream;%p",""),-1); - this->callback_->end_stream (); - return -1; - } - default: - break; - } - break; - case REPLY_RECEIVED: - // In this state we check for Data frames. - switch (msg_type) +int +TAO_SFP_Base::read_start_message (TAO_AV_Transport *transport, + flowProtocol::Start &start, + TAO_InputCDR &input) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + input.grow (start_len); + char *buf = input.rd_ptr (); + int n = transport->recv (buf, + start_len); + if (n != ACE_static_cast (int, start_len)) + ACE_ERROR_RETURN ((LM_ERROR,"%p","TAO_SFP_Base::read_start\n"),0); + else { - case flowProtocol::StartReply_Msg: - { - flowProtocol::StartReply start_reply; - n = this->dgram_.recv ((char *)&start_reply, - sizeof (start_reply), - sender); - if (n != sizeof (start_reply)) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input-StartReply\n"),0); - else - ACE_DEBUG ((LM_DEBUG,"start reply consumed\n")); - } - break; - default: - ACE_DEBUG ((LM_DEBUG,"Invalid message in state REPLY_RECEIVED\n")); - break; + input.decode (flowProtocol::_tc_Start, + &start, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; } - break; - default: - break; } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::read_start_message"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); return 0; } + int -TAO_SFP::end_stream (void) +TAO_SFP_Base::read_start_reply_message (TAO_AV_Transport *transport, + flowProtocol::StartReply &start_reply, + TAO_InputCDR &input) { - int result = -1; ACE_DECLARE_NEW_CORBA_ENV; ACE_TRY { - ACE_DEBUG ((LM_DEBUG,"SFP - ending the stream\n")); - // send the EndofStream message. - this->frame_header_.flags = TAO_ENCAP_BYTE_ORDER; - this->frame_header_.message_type = flowProtocol::EndofStream_Msg; - this->output_cdr_.reset (); - this->output_cdr_.encode (flowProtocol::_tc_frameHeader, - &this->frame_header_, - 0, - ACE_TRY_ENV); - ACE_TRY_CHECK; - ssize_t n = this->dgram_.send (this->output_cdr_.begin ()->rd_ptr (), - this->output_cdr_.begin ()->length (), - this->receiver_inet_addr_); - if ((n==-1) || (n==0)) - ACE_ERROR_RETURN ((LM_ERROR,"Error sending endofstream message:%p",""),-1); - result = this->reactor_->remove_handler (this, - ACE_Event_Handler::READ_MASK); - + input.grow (start_len); + char *buf = input.rd_ptr (); + int n = transport->recv (buf, + start_reply_len); + if (n != ACE_static_cast (int, start_len)) + ACE_ERROR_RETURN ((LM_ERROR,"%p","TAO_SFP_Base::read_start_reply_message"),0); + else + { + input.decode (flowProtocol::_tc_StartReply, + &start_reply, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP::end_stream ()\n"); - return result; + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::read_start_reply_message"); + return -1; } ACE_ENDTRY; ACE_CHECK_RETURN (-1); - return result; + return 0; } int -TAO_SFP::register_dgram_handler (void) +TAO_SFP_Base::read_credit_message (TAO_AV_Transport *transport, + flowProtocol::credit &credit, + TAO_InputCDR &input) { - int result = this->reactor_->register_handler (this, - ACE_Event_Handler::READ_MASK); - return result; -} - -ACE_HANDLE -TAO_SFP::get_handle (void) const -{ - return this->dgram_.get_handle (); + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + input.grow (start_len); + char *buf = input.rd_ptr (); + int n = transport->recv (buf, + credit_len); + if (n != ACE_static_cast (int, credit_len)) + ACE_ERROR_RETURN ((LM_ERROR,"%p","TAO_SFP_Base::read_credit_message"),0); + else + { + input.decode (flowProtocol::_tc_credit, + &credit, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::read_credit_message"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; } -ACE_Message_Block * -TAO_SFP::read_simple_frame (void) +int +TAO_SFP_Base::read_endofstream_message (TAO_AV_Transport *transport, + flowProtocol::frameHeader &endofstream, + TAO_InputCDR &input) { - ACE_Message_Block *message_block = 0; ACE_DECLARE_NEW_CORBA_ENV; ACE_TRY { - ACE_DEBUG ((LM_DEBUG,"Reading simple frame\n")); - // Check to see what the length of the message is. - - flowProtocol::frameHeader frame_header; - - int result = - this->read_frame_header (frame_header); - - if (result < 0) - return 0; - int byte_order = frame_header.flags & 0x1; - int message_len = frame_header.message_size; - - ACE_NEW_RETURN (message_block, - ACE_Message_Block (message_len), - 0); - ACE_INET_Addr sender; - int n = this->dgram_.recv (message_block->wr_ptr (),message_len,sender); - if (n == -1) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input -peek"),0); - else if (n==0) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::handle_input -peek"),0); - else if (n != message_len) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_simple_frame:message truncated\n"),0); - // print the buffer. - // this->dump_buf (message,n); - // skip over the frame header. - message_block->rd_ptr (this->frame_header_len_); - message_block->wr_ptr (n); - if (frame_header.flags & 0x2) + input.grow (start_len); + char *buf = input.rd_ptr (); + int n = transport->recv (buf, + frame_header_len); + if (n != ACE_static_cast (int, frame_header_len)) + ACE_ERROR_RETURN ((LM_ERROR,"%p","TAO_SFP_Base::read_endofstream_message"),0); + else { - ACE_DEBUG ((LM_DEBUG,"fragmented frame:0th fragment\n")); - this->more_fragments_ = 1; - // read the frame info. - ACE_Message_Block frame_info_mb (message_len-this->frame_header_len_+ACE_CDR::MAX_ALIGNMENT); - ACE_CDR::mb_align (&frame_info_mb); - frame_info_mb.copy (message_block->rd_ptr (), - message_block->length ()); - // print the buffer. - // this->dump_buf (message_block->rd_ptr (),16); - TAO_InputCDR frame_info_cdr (&frame_info_mb,byte_order); - flowProtocol::frame frame_info; - frame_info_cdr.decode (flowProtocol::_tc_frame, - &frame_info, - 0, - ACE_TRY_ENV); + input.decode (flowProtocol::_tc_frameHeader, + &endofstream, + 0, + ACE_TRY_ENV); ACE_TRY_CHECK; - ACE_DEBUG ((LM_DEBUG,"frame.timestamp = %d, frame.synchsource = %d, frame.sequence_num = %d\n", - frame_info.timestamp, - frame_info.synchSource, - frame_info.sequence_num)); - // The remaining message in the CDR stream is the fragment data for frag.0 - ACE_Message_Block *data = - frame_info_cdr.start ()->clone (); - ACE_DEBUG ((LM_DEBUG,"Length of 0th fragment= %d\n",data->length ())); - TAO_SFP_Fragment_Table_Entry *fragment_entry = 0; - TAO_SFP_Fragment_Node *new_node; - ACE_NEW_RETURN (new_node, - TAO_SFP_Fragment_Node, - 0); - new_node->fragment_info_.frag_sz = data->length (); - new_node->fragment_info_.frag_number = 0; - new_node->fragment_info_.source_id = frame_info.source_ids [0]; - new_node->data_ = data; - if (this->fragment_table_.find (frame_info.sequence_num,fragment_entry) == 0) - { - // This case can happen where a nth (n > 0)fragment is received before the 0th fragment. - ACE_DEBUG ((LM_DEBUG,"fragment table entry found for 0th fragment:\n")); - result = fragment_entry->fragment_set_.insert (*new_node); - if (result != 0) - ACE_ERROR_RETURN ((LM_ERROR,"insert for 0th fragment failed\n"),0); - // check if all the fragments have been received. - return check_all_fragments (fragment_entry); - } - else - { - ACE_DEBUG ((LM_DEBUG,"fragment table entry not found for 0th fragment\n")); - TAO_SFP_Fragment_Table_Entry *new_entry; - ACE_NEW_RETURN (new_entry, - TAO_SFP_Fragment_Table_Entry, - 0); - result = new_entry->fragment_set_.insert (*new_node); - if (result != 0) - ACE_ERROR_RETURN ((LM_ERROR,"insert for 0th fragment failed\n"),0); - // not found. so bind a new entry. - result = this->fragment_table_.bind (frame_info.sequence_num,new_entry); - if (result != 0) - ACE_ERROR_RETURN ((LM_ERROR,"fragment table bind failed\n"),0); - return 0; - } } } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"read_simple_frame"); - return 0; + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::read_credit_message"); + return -1; } ACE_ENDTRY; - ACE_CHECK_RETURN (0); - return message_block; + ACE_CHECK_RETURN (-1); + return 0; } int -TAO_SFP::read_frame_header (flowProtocol::frameHeader &frame_header) +TAO_SFP_Base::peek_frame_header (TAO_AV_Transport *transport, + flowProtocol::frameHeader &header, + TAO_InputCDR &input) { ACE_DECLARE_NEW_CORBA_ENV; ACE_TRY { - ACE_INET_Addr sender; - char *buf; - ACE_NEW_RETURN (buf, - char [this->frame_header_len_+ACE_CDR::MAX_ALIGNMENT], - 0); - ssize_t n =this->dgram_.recv (buf, - this->frame_header_len_, - sender, - MSG_PEEK); - if (n == -1) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_simple_frame -peek:%p",""),0); - else if (n==0) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_simple_frame -peek:%p",""),0); - else if (n != this->frame_header_len_) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_simple_frame - not able to peek\n"),0); - // print the buffer. - // this->dump_buf (buf,n); - ACE_Message_Block mb (n+ACE_CDR::MAX_ALIGNMENT); - ACE_CDR::mb_align (&mb); - int result - = mb.copy (buf,n); - if (result == -1) - ACE_ERROR_RETURN ((LM_ERROR,"Message_Block::copy failed\n"),0); - // buf[4] is the byte order. - int byte_order = buf[4] & 0x1; - // ACE_DEBUG ((LM_DEBUG,"mb len = %d,byte_order=%d\n",mb.length (),byte_order)); - TAO_InputCDR cdr (&mb,byte_order); - // cdr >>= frame_header; - cdr.decode (flowProtocol::_tc_frameHeader, - &frame_header, - 0, - ACE_TRY_ENV); - ACE_TRY_CHECK; - - ACE_DEBUG ((LM_DEBUG,"message_type = %d, message_size = %d,message_flags = %d\n", - frame_header.message_type,frame_header.message_size,frame_header.flags)); - + input.grow (frame_header_len); + char *buf = input.rd_ptr (); + int n = transport->recv (buf, + frame_header_len, + MSG_PEEK); + if (n != ACE_static_cast (int, frame_header_len)) + ACE_ERROR_RETURN ((LM_ERROR,"%p","TAO_SFP_Base::read_endofstream_message"),0); + else + { + input.decode (flowProtocol::_tc_frameHeader, + &header, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + // TAO_SFP_Base::dump_buf (buf,n); } ACE_CATCHANY { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP::read_frame_header"); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::read_credit_message"); return -1; } ACE_ENDTRY; @@ -971,161 +947,530 @@ TAO_SFP::read_frame_header (flowProtocol::frameHeader &frame_header) return 0; } -ACE_Message_Block * -TAO_SFP::read_fragment (void) +int +TAO_SFP_Base::peek_fragment_header (TAO_AV_Transport *transport, + flowProtocol::fragment &fragment, + TAO_InputCDR &input) { - TAO_SFP_Fragment_Table_Entry *fragment_entry = 0; ACE_DECLARE_NEW_CORBA_ENV; ACE_TRY { - flowProtocol::fragment fragment; - ACE_INET_Addr sender; - char *buf = 0; - ACE_NEW_RETURN (buf, - char [this->fragment_len_+ACE_CDR::MAX_ALIGNMENT], - 0); - ssize_t n =this->dgram_.recv (buf, - this->fragment_len_, - sender, - MSG_PEEK); - if (n == -1) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_fragment -peek:%p",""),0); - else if (n==0) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_simple_frame -peek:%p",""),0); - else if (n != this->fragment_len_) - ACE_ERROR_RETURN ((LM_ERROR,"SFP::read_simple_frame - not able to peek\n"),0); - // print the buffer. - this->dump_buf (buf,n); - ACE_Message_Block mb (n+ACE_CDR::MAX_ALIGNMENT); - ACE_CDR::mb_align (&mb); - int result - = mb.copy (buf,n); - if (result == -1) - ACE_ERROR_RETURN ((LM_ERROR,"read_fragment::Message_Block::copy failed\n"),0); - // buf[4] is the byte order. - int byte_order = buf[4] & 0x1; - ACE_DEBUG ((LM_DEBUG,"mb len = %d,byte_order=%d\n",mb.length (),byte_order)); - TAO_InputCDR cdr (&mb,byte_order); - // cdr >>= frame_header; - cdr.decode (flowProtocol::_tc_fragment, - &fragment, - 0, - ACE_TRY_ENV); - ACE_TRY_CHECK; - - ACE_DEBUG ((LM_DEBUG,"frag number = %d, frag size = %d,source id = %d\n", - fragment.frag_number,fragment.frag_sz,fragment.source_id)); - - ACE_Message_Block *data; - ACE_NEW_RETURN (data, - ACE_Message_Block(fragment.frag_sz), - 0); - - // Read the fragment. - n = this->dgram_.recv (data->wr_ptr (),fragment.frag_sz,sender); - if ((n == -1) || (n==0)) - ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP::read_fragment:%p",""),0); - // move past the fragment header. - data->rd_ptr (this->fragment_len_); - data->wr_ptr (n); - ACE_DEBUG ((LM_DEBUG,"length of %dth fragment is: %d\n", - fragment.frag_number, - data->length ())); - - TAO_SFP_Fragment_Node *new_node; - ACE_NEW_RETURN (new_node, - TAO_SFP_Fragment_Node, - 0); - new_node->fragment_info_ = fragment; - new_node->data_ = data; - if (this->fragment_table_.find (fragment.sequence_num,fragment_entry) == 0) + input.grow (fragment_len); + char *buf = input.rd_ptr (); + int n = transport->recv (buf, + fragment_len, + MSG_PEEK); + if (n != ACE_static_cast (int, fragment_len)) + ACE_ERROR_RETURN ((LM_ERROR,"%p","TAO_SFP_Base::read_endofstream_message"),0); + else { - // Already an entry exists. Traverse the list and insert it at the right place. - result = fragment_entry->fragment_set_.insert (*new_node); - if (result != 0) - ACE_ERROR_RETURN ((LM_ERROR,"insert for %dth node failed\n",fragment.frag_number),0); - // check if all the fragments have been received. + input.decode (flowProtocol::_tc_fragment, + &fragment, + 0, + ACE_TRY_ENV); + ACE_TRY_CHECK; } - else + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP_Base::read_credit_message"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +void +TAO_SFP_Base::dump_buf (char *buffer,int size) +{ + char *buf = buffer; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"\n========================================\n")); + for (int i=0;i<size;i++) + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"%d ",buf[i])); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"\n========================================\n")); +} + +//------------------------------------------------------------ +// TAO_SFP_Object +//------------------------------------------------------------ + +TAO_SFP_Object::TAO_SFP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport) + :TAO_AV_Protocol_Object (callback,transport), + source_id_ (10), + max_credit_ (-1), + current_credit_ (-1) +{ + TAO_SFP_BASE::instance (); + this->state_.static_frame_.size (2* this->transport_->mtu ()); +} + +TAO_SFP_Object::~TAO_SFP_Object (void) +{ + //no-op +} + +int +TAO_SFP_Object::destroy (void) +{ + int result = -1; + TAO_OutputCDR out_stream; + result = TAO_SFP_Base::start_frame (TAO_ENCAP_BYTE_ORDER, + flowProtocol::EndofStream_Msg, + out_stream); + if (result < 0) + return result; + result = TAO_SFP_Base::send_message (this->transport_, + out_stream); + if (result < 0) + return result; + this->callback_->handle_destroy (); + return 0; +} + +int +TAO_SFP_Object::send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info) +{ + TAO_OutputCDR out_stream; + CORBA::Boolean result = 0; + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_SFP_Object::send_frame\n")); + CORBA::Octet flags = TAO_ENCAP_BYTE_ORDER; + if (this->transport_ == 0) + ACE_ERROR_RETURN ((LM_ERROR,"TAO_SFP_Object::send_frame: transport is null\n"),-1); + if (this->current_credit_ != 0) + { + // if we have enough credit then we send. + int total_length = 0; + for (ACE_Message_Block *temp = frame;temp != 0;temp = temp->cont ()) + total_length += temp->length (); + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"total_length of frame=%d\n",total_length)); + if (ACE_static_cast (u_int, total_length) < (TAO_SFP_MAX_PACKET_SIZE -TAO_SFP_Base::frame_header_len)) { - ACE_NEW_RETURN (fragment_entry, - TAO_SFP_Fragment_Table_Entry, - 0); - fragment_entry->fragment_set_.insert (*new_node); - // bind a new entry for this sequence number. - result = this->fragment_table_.bind (fragment.sequence_num,fragment_entry); - if (result != 0) - ACE_ERROR_RETURN ((LM_ERROR,"bind for %dth fragment failed\n", - fragment.frag_number),0); + if (frame_info != 0) + { + if (frame_info->boundary_marker) + flags |= 4; + CORBA::Boolean result = TAO_SFP_Base::start_frame (flags, + flowProtocol::Frame_Msg, + out_stream); + if (result == 0) + return 0; + flowProtocol::my_seq_ulong source_ids; + source_ids.length (1); + source_ids [0] = 0; + TAO_SFP_Base::write_frame_message (frame_info->timestamp, + frame_info->ssrc, + source_ids, + this->sequence_num_, + out_stream); + } + else + { + CORBA::Boolean result = TAO_SFP_Base::start_frame (flags, + flowProtocol::SimpleFrame_Msg, + out_stream); + if (result == 0) + return 0; + } + TAO_SFP_Base::send_message (this->transport_, + out_stream, + frame); } - if (!(fragment.flags & 0x2)) + else // larger frame,fragment and send it. { - ACE_DEBUG ((LM_DEBUG,"Last fragment received\n")); - // if bit 1 is not set then there are - // no more fragments. - fragment_entry->last_received_ = 1; - // since fragment number starts from 0 to n-1 we add 1. - fragment_entry->num_fragments_ = fragment.frag_number + 1; + flags = flags | 2; + if (frame_info != 0) + { + if (frame_info->boundary_marker) + flags |= 4; + result = TAO_SFP_Base::start_frame (flags, + flowProtocol::Frame_Msg, + out_stream); + if (result == 0) + return result; + flowProtocol::my_seq_ulong source_ids; + source_ids.length (1); + source_ids [0] = 0; + TAO_SFP_Base::write_frame_message (frame_info->timestamp, + frame_info->ssrc, + source_ids, + this->sequence_num_, + out_stream); + } + else + { + CORBA::Boolean result = TAO_SFP_Base::start_frame (flags, + flowProtocol::SimpleFrame_Msg, + out_stream); + if (result == 0) + return 0; + } + size_t last_len,current_len; + int message_len = out_stream.total_length (); + ACE_Message_Block *mb = frame; + ACE_Message_Block *fragment_mb = + this->get_fragment (mb, + message_len, + last_len, + current_len); + // This can be either a simpleframe or a sequenced frame,other types of frames. + TAO_SFP_Base::send_message (this->transport_, + out_stream, + fragment_mb); + out_stream.reset (); + int frag_number = 1; + mb->length (last_len); + mb->rd_ptr (current_len); + // If there is any more data send those as fragments. + while (mb != 0) + { + message_len = TAO_SFP_Base::fragment_len; + fragment_mb = this->get_fragment (mb, + message_len, + last_len, + current_len); + if (mb == 0) + { + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"sending the last fragment\n")); + // This is the last fragment so clear the fragments bit. + flags = TAO_ENCAP_BYTE_ORDER; + } + if (fragment_mb == 0) + break; + if (frame_info != 0) + { + TAO_SFP_Base::write_fragment_message (flags, + frag_number++, + this->sequence_num_, + frame_info->ssrc, + out_stream); + } + else + { + TAO_SFP_Base::write_fragment_message (flags, + frag_number++, + this->sequence_num_, + 0, + out_stream); + } + // send the fragment now. + // without the sleep the fragments gets lost! + // probably because the UDP buffer queue on the sender side + // is overflown it drops the packets. + // XXX: This is a hack. + ACE_OS::sleep (1); + result = TAO_SFP_Base::send_message (this->transport_, + out_stream, + fragment_mb); + if (mb != 0) + { + mb->length (last_len); + mb->rd_ptr (current_len); + } + } + // Increment the sequence_num after sending the message. + this->sequence_num_++; + // Also reduce the number of credits. + if (this->max_credit_ > 0) + this->current_credit_--; } - } - ACE_CATCHANY + else { - ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"TAO_SFP::read_fragment"); - return 0; + // flow controlled so wait. + // A greater than 0 value indicates that flow control is being exercised. + return 1; } - ACE_ENDTRY; - ACE_CHECK_RETURN (0); - return check_all_fragments (fragment_entry); + return 0; +} + +int +TAO_SFP_Object::send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info) +{ + ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_SFP_Object::send_frame"),-1); } ACE_Message_Block* -TAO_SFP::check_all_fragments (TAO_SFP_Fragment_Table_Entry *fragment_entry) +TAO_SFP_Object::get_fragment (ACE_Message_Block *&mb, + size_t initial_len, + size_t &last_mb_orig_len, + size_t &last_mb_current_len) { - ACE_DEBUG ((LM_DEBUG,"table size: %d, num_fragments: %d\n",fragment_entry->fragment_set_.size (),fragment_entry->num_fragments_)); - // check to see if all the frames have been received. - if (fragment_entry->fragment_set_.size () == fragment_entry->num_fragments_) + ACE_Message_Block *fragment_mb = 0,*temp_mb = 0; + int prev_len,last_len = 0; + size_t current_len = 0; + size_t message_len = initial_len; + while (mb != 0) { - ACE_DEBUG ((LM_DEBUG,"all fragments have been received\n")); - // all the fragments have been received - // we can now chain the ACE_Message_Blocks in the fragment_set_ and then return them - // back. - ACE_Message_Block *frame = 0,*head = 0; - FRAGMENT_SET_ITERATOR frag_iterator (fragment_entry->fragment_set_); - TAO_SFP_Fragment_Node *node; - for (;frag_iterator.next (node) != 0;frag_iterator.advance ()) + prev_len = message_len; + message_len += mb->length (); + if (fragment_mb == 0) + fragment_mb = temp_mb = mb->duplicate (); + if (message_len > TAO_SFP_MAX_PACKET_SIZE) { -// ACE_Message_Block *block = node->data_; -// char *buf =block->rd_ptr (); -// ACE_DEBUG ((LM_DEBUG,"length of buf = %d\n",block->length ())); -// for (int i=0;i<block->length ();i++) -// ACE_DEBUG ((LM_DEBUG,"%c ",buf[i])); -// ACE_DEBUG ((LM_DEBUG,"\n")); - - if (!head) + // get only the length that we can accomodate. + current_len = TAO_SFP_MAX_PACKET_SIZE - prev_len; + if (current_len < mb->length ()) { - frame = node->data_; - head = frame; + // The above condition is an assertion. + message_len += (current_len-mb->length ()); + last_len = mb->length (); + mb->length (current_len); + temp_mb->length (current_len); } - else + break; + } + else + { + // we can accomodate this message block + message_len += mb->length (); + mb = mb->cont (); + temp_mb = temp_mb->cont (); + } + } + last_mb_orig_len = last_len; + last_mb_current_len = current_len; + return fragment_mb; +} + +int +TAO_SFP_Object::set_policies (const TAO_AV_PolicyList& policies) +{ + TAO_AV_Policy *policy = 0; + for (u_int i=0;i<policies.length ();i++) + { + policy = policies[i]; + switch (policies[i]->type ()) + { + + case TAO_AV_SFP_CREDIT_POLICY: + { + TAO_AV_SFP_Credit_Policy *credit_policy = + ACE_reinterpret_cast (TAO_AV_SFP_Credit_Policy*,policy); + this->max_credit_ = credit_policy->value (); + } + default: + break; + } + } + return 0; +} + +// TAO_SFP_Consumer_Object +TAO_SFP_Consumer_Object::TAO_SFP_Consumer_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport, + char *&sfp_options) + :TAO_SFP_Object (callback,transport) +{ + TAO_AV_PolicyList policies = callback->get_policies (); + if (policies.length () == 0) + return; + this->set_policies (policies); + if (this->max_credit_ > 0) + { + ACE_NEW (sfp_options, + char [BUFSIZ]); + + ACE_OS::sprintf (sfp_options, + "sfp:1.0:credit=%d", + max_credit_); + } +} + +int +TAO_SFP_Consumer_Object::handle_input (void) +{ + if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG,"TAO_SFP_Consumer_Object::handle_input\n")); + // This is the entry point for receiving data. + TAO_AV_frame_info *frame_info = 0; + int result = TAO_SFP_Base::handle_input (this->transport_, + this->state_, + frame_info); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"ERROR in TAO_SFP_Consumer_Object::handle_input"),result); + if (this->state_.frame_header_.message_type == flowProtocol::EndofStream_Msg) + this->callback_->handle_destroy (); + if (this->state_.is_complete ()) + { + this->callback_->receive_frame (this->state_.frame_block_, + frame_info); + // Now release the memory for the frame. + if (this->state_.frame_block_ != &this->state_.static_frame_) + { + ACE_Message_Block *temp = 0; + for (temp = this->state_.frame_block_; + temp != 0; + temp = temp->cont ()) { - frame->cont (node->data_); - frame = node->data_; + temp->release (); + delete temp; } } - return head; + this->state_.reset (); } return 0; } -void -TAO_SFP::dump_buf(char *buffer,int size) +TAO_SFP_Producer_Object::TAO_SFP_Producer_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport, + char *&sfp_options) + :TAO_SFP_Object (callback,transport), + credit_sequence_num_ (0) + +{ + TAO_Tokenizer flow_string (sfp_options,':'); + if (flow_string [2] != 0) + { + TAO_Tokenizer options (flow_string[2],'='); + if (options [1] != 0) + this->max_credit_ = ACE_OS::atoi (options[1]); + } +} + +int +TAO_SFP_Producer_Object::handle_input (void) +{ + // A producer can only receive credit messages. + int result; + flowProtocol::MsgType msg_type = flowProtocol::Start_Msg; + result = TAO_SFP_Base::peek_message_type (this->transport_, + msg_type); + if (result < 0) + return result; + switch (msg_type) + { + case flowProtocol::Credit_Msg: + { + flowProtocol::credit credit; + result = TAO_SFP_Base::read_credit_message (this->transport_, + credit, + this->state_.cdr); + if (result < 0) + return result; + if (!this->credit_sequence_num_) + this->credit_sequence_num_ = credit.cred_num; + else + { + // check that the sequence number is above the last sequence number + // else its a duplicate credit message so we can ignore it. + if (credit.cred_num <= this->credit_sequence_num_) + return 0; + else // Update our credit now. + this->current_credit_ = this->max_credit_; + } + } + break; + default: + { + ACE_Message_Block mb (2*this->transport_->mtu ()); + + // Ignore the rest of the message by just reading. + this->transport_->recv (mb.rd_ptr (), + mb.size ()); + break; + } + } + return 0; +} + +// TAO_AV_SFP_Factory +TAO_AV_SFP_Factory::TAO_AV_SFP_Factory (void) +{ +} + +TAO_AV_SFP_Factory::~TAO_AV_SFP_Factory (void) { - char *buf = buffer; - ACE_DEBUG ((LM_DEBUG,"========================================n")); - for (int i=0;i<size;i++) - ACE_DEBUG ((LM_DEBUG,"%d ",buf[i])); - ACE_DEBUG ((LM_DEBUG,"n========================================n")); +} + +// Initialization hook from service configurator. +int +TAO_AV_SFP_Factory::init (int argc, char *argv[]) +{ + return 0; +} + +int +TAO_AV_SFP_Factory::match_protocol (const char *flow_string) +{ + if (ACE_OS::strncasecmp (flow_string,"sfp",3) == 0) + return 1; + return 0; +} + +TAO_AV_Protocol_Object* +TAO_AV_SFP_Factory::make_protocol_object (TAO_FlowSpec_Entry *entry, + TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Flow_Handler *handler, + TAO_AV_Transport *transport) +{ + TAO_AV_Protocol_Object *object = 0; + TAO_AV_Callback *callback = 0; + endpoint->get_callback (entry->flowname (), + callback); + char *flow_string = entry->flow_protocol_str (); + switch (entry->role ()) + { + case TAO_FlowSpec_Entry::TAO_AV_PRODUCER: + { + ACE_NEW_RETURN (object, + TAO_SFP_Producer_Object (callback, + transport, + flow_string), + 0); + } + break; + case TAO_FlowSpec_Entry::TAO_AV_CONSUMER: + { + ACE_NEW_RETURN (object, + TAO_SFP_Consumer_Object (callback, + transport, + flow_string), + 0); + } + break; + case TAO_FlowSpec_Entry::TAO_AV_INVALID_ROLE: + return 0; + } + callback->open (object, + handler); + endpoint->set_protocol_object (entry->flowname (), + object); + return object; +} + +//------------------------------------------------------------ +// TAO_SFP_Frame_State +//------------------------------------------------------------ + +TAO_SFP_Frame_State::TAO_SFP_Frame_State (void) + :cdr (new ACE_Data_Block (ACE_CDR::DEFAULT_BUFSIZE, + ACE_Message_Block::MB_DATA, + 0, + 0, + 0, + 0, + 0), + TAO_ENCAP_BYTE_ORDER), + more_fragments_ (0), + frame_block_ (0) +{ +} + +CORBA::Boolean +TAO_SFP_Frame_State::is_complete (void) +{ + return (!this->more_fragments_) && (this->frame_block_); +} + +int +TAO_SFP_Frame_State::reset (void) +{ + this->frame_block_ = 0; + return 0; } #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) @@ -1134,6 +1479,7 @@ template class ACE_DNode<TAO_SFP_Fragment_Node>; template class ACE_Equal_To<CORBA::ULong>; template class ACE_Ordered_MultiSet<TAO_SFP_Fragment_Node>; template class ACE_Ordered_MultiSet_Iterator<TAO_SFP_Fragment_Node>; + template class ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex>; template class ACE_Hash_Map_Manager_Ex<CORBA::ULong, TAO_SFP_Fragment_Table_Entry *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>; template class ACE_Hash_Map_Entry<CORBA::ULong, TAO_SFP_Fragment_Table_Entry *>; @@ -1142,6 +1488,17 @@ template class ACE_Hash_Map_Reverse_Iterator_Ex<CORBA::ULong,TAO_SFP_Fragment_Ta template class ACE_Hash_Map_Iterator_Ex<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Hash<CORBA::ULong>,ACE_Equal_To<CORBA::ULong>,ACE_Null_Mutex>; template class ACE_Hash_Map_Iterator<CORBA::ULong,TAO_SFP_Fragment_Table_Entry *,ACE_Null_Mutex>; template class ACE_Hash_Map_Reverse_Iterator<CORBA::ULong,TAO_SFP_Fragment_Table_Entry *,ACE_Null_Mutex>; + +template class ACE_Hash_Map_Manager<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex>*,ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<CORBA::ULong, ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Entry<CORBA::ULong, ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *>; +template class ACE_Hash_Map_Iterator_Base_Ex<CORBA::ULong, ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex>*,ACE_Hash<CORBA::ULong>,ACE_Equal_To<CORBA::ULong>,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex>*,ACE_Hash<CORBA::ULong>,ACE_Equal_To<CORBA::ULong>,ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *,ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *,ACE_Null_Mutex>; + +template class ACE_Singleton<TAO_SFP_Base, ACE_SYNCH_MUTEX>; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) #pragma instantiate ACE_DNode<TAO_SFP_Fragment_Node> @@ -1156,4 +1513,24 @@ template class ACE_Hash_Map_Reverse_Iterator<CORBA::ULong,TAO_SFP_Fragment_Table #pragma instantiate ACE_Equal_To<CORBA::ULong> #pragma instantiate ACE_Hash_Map_Iterator<CORBA::ULong,TAO_SFP_Fragment_Table_Entry *,ACE_Null_Mutex> #pragma instantiate ACE_Hash_Map_Reverse_Iterator<CORBA::ULong,TAO_SFP_Fragment_Table_Entry *,ACE_Null_Mutex> + +#pragma instantiate ACE_Hash_Map_Manager<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex>*,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<CORBA::ULong, ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Entry<CORBA::ULong, ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<CORBA::ULong, ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex>*,ACE_Hash<CORBA::ULong>,ACE_Equal_To<CORBA::ULong>,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex>*,ACE_Hash<CORBA::ULong>,ACE_Equal_To<CORBA::ULong>,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *,ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<CORBA::ULong,ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> *,ACE_Null_Mutex> + +#pragma instantiate ACE_Singleton<TAO_SFP_Base, ACE_SYNCH_MUTEX> #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +ACE_FACTORY_DEFINE (AV, TAO_AV_SFP_Factory) +ACE_STATIC_SVC_DEFINE (TAO_AV_SFP_Factory, + ASYS_TEXT ("SFP_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_AV_SFP_Factory), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) diff --git a/TAO/orbsvcs/orbsvcs/AV/sfp.h b/TAO/orbsvcs/orbsvcs/AV/sfp.h index a399ab4ec58..f0151189c0a 100644 --- a/TAO/orbsvcs/orbsvcs/AV/sfp.h +++ b/TAO/orbsvcs/orbsvcs/AV/sfp.h @@ -4,13 +4,13 @@ // ============================================================================ // // = LIBRARY -// AVStreams. +// ORBSVCS AVStreams. // // = FILENAME // sfp.h // // = AUTHOR -// Nagarajan Surendran <naga@cs.wustl.edu> +// Nagarajan Surendran <naga@cs.wustl.edu> // // ============================================================================ @@ -22,41 +22,17 @@ #include "ace/SOCK_Dgram.h" #include "ace/INET_Addr.h" -#define MAGIC_NUMBER_LEN 5 -#define MESSAGE_TYPE_OFFSET 5 -#define TAO_WRITEV_MAX 128 +#include "Policy.h" +#include "MCast.h" +#include "AVStreams_i.h" +#include "UDP.h" +#define TAO_SFP_MAGIC_NUMBER_LEN 4 +#define TAO_SFP_MESSAGE_TYPE_OFFSET 5 +#define TAO_SFP_WRITEV_MAX 128 -#define SFP_MAX_PACKET_SIZE ACE_MAX_DGRAM_SIZE -//#define SFP_MAX_PACKET_SIZE 100 - - -// various message class for SFP. - -class TAO_ORBSVCS_Export SFP_Callback - // =TITLE - // Callback interface for SFP. - // - // =Description - // Application should create a callback object which they - // register with the SFP. The SFP implementation notifies the - // applicationn of any changes in the stream status like stream - // established, stream ended. -{ -public: - virtual int start_failed (void) = 0; - // This is called for both active and passive start. - - virtual int stream_established (void) = 0; - // This is a callback for both active and passive stream - // establshment. - - virtual int receive_frame (ACE_Message_Block *frame) =0; - // upcall to the application to receive a frame. - - virtual void end_stream (void) = 0; - // called when the EndofStream message is received. -}; +#define TAO_SFP_MAX_PACKET_SIZE ACE_MAX_DGRAM_SIZE +//#define TAO_SFP_MAX_PACKET_SIZE 132 class TAO_SFP_Fragment_Node { @@ -79,19 +55,38 @@ public: {} int last_received_; size_t num_fragments_; + TAO_AV_frame_info frame_info; ACE_Ordered_MultiSet<TAO_SFP_Fragment_Node> fragment_set_; }; typedef ACE_Ordered_MultiSet_Iterator<TAO_SFP_Fragment_Node> FRAGMENT_SET_ITERATOR; +typedef ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> TAO_SFP_Fragment_Table; +typedef ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table*,ACE_Null_Mutex> TAO_SFP_Fragment_Table_Map; + +class TAO_ORBSVCS_Export TAO_SFP_Frame_State +{ +public: + TAO_SFP_Frame_State (void); + CORBA::Boolean is_complete (void); + + int reset (void); + + TAO_InputCDR cdr; + // This is the InputCDR that will be used to decode the message. + flowProtocol::frameHeader frame_header_; + flowProtocol::fragment fragment_; + flowProtocol::frame frame_; + CORBA::Boolean more_fragments_; + ACE_Message_Block *frame_block_; + // boolean flags indicating that there are more fragments. + ACE_Message_Block static_frame_; + TAO_SFP_Fragment_Table_Map fragment_table_map_; +}; -class TAO_ORBSVCS_Export TAO_SFP :public virtual ACE_Event_Handler - // = TITLE - // SFP implementation on UDP. - // - // = Description - // This implements the methods to send and receive data octet - // streams using the Simple Flow Protocol. +class TAO_AV_Transport; +class TAO_AV_Core; +class TAO_ORBSVCS_Export TAO_SFP_Base { public: // default arguments to pass to use for the ORB @@ -108,8 +103,16 @@ public: static const unsigned char TAO_SFP_MAJOR_VERSION; static const unsigned char TAO_SFP_MINOR_VERSION; -// lengths of various SFP headers + // lengths of various SFP headers static const unsigned char TAO_SFP_FRAME_HEADER_LEN; + static const unsigned char TAO_SFP_MESSAGE_SIZE_OFFSET; + static const unsigned char TAO_SFP_FRAGMENT_SIZE_OFFSET; + static u_int frame_header_len; + static u_int start_reply_len; + static u_int start_len; + static u_int credit_len; + static u_int fragment_len; + enum State { ACTIVE_START, @@ -120,143 +123,145 @@ public: START_RECEIVED }; - TAO_SFP (CORBA::ORB_ptr orb, - ACE_Reactor* reactor, - ACE_Time_Value timeout1, - ACE_Time_Value timeout2, - SFP_Callback *callback); - // constructor. - - virtual int start_stream (const char *receiver_addr); - // Actively start the stream by trying to connect to the UDP - // receiver_addr in host:port format. - - virtual int start_stream (const char *local_addr,int credit_); - // Passive start. - - virtual int send_frame (ACE_Message_Block *frame); - // sends a single frame over UDP. - - virtual int end_stream (void); - // terminates the stream. - - virtual int handle_input (ACE_HANDLE fd); - // Callback when event happens on the dgram socket. - - virtual int handle_timeout (const ACE_Time_Value&, const void*); - // Used for timeout for the number of tries for starting a stream. - - virtual ACE_HANDLE get_handle (void) const; -private: - - ACE_Message_Block* read_simple_frame (void); - // receives a single frame from the network. - - int read_frame_header (flowProtocol::frameHeader &frame_header); - // reads the frame header from the peek buffer in the datagram. - - ACE_Message_Block* read_fragment (void); - // reads a fragment from the wire. - - void create_local_dgram (void); - // Create the local dgram endpoint. - - int connect_to_receiver (const char *receiver_addr); - // Creates a connected dgram with the receiver addr. - - int send_start (void); - // sends the start message to the receiver. - - int send_startReply (void); - // sends the StartReply message to the receiver. - - int send_cdr_buffer (TAO_OutputCDR &cdr, - ACE_Message_Block *mb); - // sends the cdr buffer using iovecs. - - int register_dgram_handler (void); - // registers the dgram socket with the reactor. - - ACE_Message_Block *check_all_fragments (TAO_SFP_Fragment_Table_Entry *fragment_entry); - // checks if all the fragments for this entry has been received and returns the - // head of the chain of message blocks for that frame. - - void dump_buf (char *buf,int n); + TAO_SFP_Base (void); + static CORBA::Boolean start_frame (CORBA::Octet flags, + flowProtocol::MsgType type, + TAO_OutputCDR &msg); + + static CORBA::Boolean write_start_message (TAO_OutputCDR &msg); + static CORBA::Boolean write_start_reply_message (TAO_OutputCDR &msg); + static CORBA::Boolean write_credit_message (CORBA::ULong cred_num, + TAO_OutputCDR &msg); + static CORBA::Boolean write_fragment_message (CORBA::Octet flags, + CORBA::ULong fragment_number, + CORBA::ULong sequence_number, + CORBA::ULong source_id, + TAO_OutputCDR &msg); + + static CORBA::Boolean write_frame_message (CORBA::ULong timestamp, + CORBA::ULong synchSource, + flowProtocol::my_seq_ulong source_ids, + CORBA::ULong sequence_num, + TAO_OutputCDR &msg); + + static int send_message (TAO_AV_Transport *transport, + TAO_OutputCDR &stream, + ACE_Message_Block *mb = 0); + static int peek_message_type (TAO_AV_Transport *transport, + flowProtocol::MsgType &type); + static int read_start_message (TAO_AV_Transport *transport, + flowProtocol::Start &start, + TAO_InputCDR &cdr); + static int read_start_reply_message (TAO_AV_Transport *transport, + flowProtocol::StartReply &start_reply, + TAO_InputCDR &cdr); + static int read_credit_message (TAO_AV_Transport *transport, + flowProtocol::credit &credit, + TAO_InputCDR &cdr); + static int read_endofstream_message (TAO_AV_Transport *transport, + flowProtocol::frameHeader &endofstream, + TAO_InputCDR &cdr); + + static int read_frame (TAO_AV_Transport *transport, + flowProtocol::frameHeader &frame_header, + TAO_SFP_Frame_State &state, + TAO_AV_frame_info *&frame_info); + + static int read_fragment (TAO_AV_Transport *transport, + flowProtocol::fragment &fragment, + TAO_SFP_Frame_State &state, + TAO_AV_frame_info *&frame_info); + + static int peek_frame_header (TAO_AV_Transport *transport, + flowProtocol::frameHeader &header, + TAO_InputCDR &cdr); + + static int peek_fragment_header (TAO_AV_Transport *transport, + flowProtocol::fragment &fragment, + TAO_InputCDR &cdr); + + static int handle_input (TAO_AV_Transport *transport, + TAO_SFP_Frame_State &state, + TAO_AV_frame_info *&frame_info); + + static ACE_Message_Block* check_all_fragments (TAO_SFP_Fragment_Table_Entry *fragment_entry); + +protected: + static void dump_buf (char *buf,int n); // dumps the buffer to the screen. +}; - CORBA::ORB_ptr orb_; - // ORB reference. - - ACE_Reactor* reactor_; - // Used for registering the dgram handler. - - TAO_OutputCDR output_cdr_; - // Use the TAO CDR decoder to decode everything - - // TAO_InputCDR input_cdr_; - // Use the TAO CDR encoder to encode everything - - ACE_SOCK_Dgram dgram_; - // Connection Oriented Dgram. - - int start_tries_; - // Number of tries to send a Start message. - - int startReply_tries_; - // Number of tries to send a StartReply message. - - ACE_Time_Value timeout1_; - // Timeout used for Start on Sender side and also for Credit on - // receiver side. - - ACE_Time_Value timeout2_; - // Timeout used for StartReply on the receiver side and also for - // CREDIT on the sender side. - - State state_; - // State variable. - - const char *receiver_addr_; - // The address of the receiver to which we're connected to. - - ACE_INET_Addr receiver_inet_addr_; - // INET addr of the receiver. +// Beware the SFP_Base code relies on the Singleton being initialized. +typedef ACE_Singleton <TAO_SFP_Base,ACE_SYNCH_MUTEX> TAO_SFP_BASE; - SFP_Callback *callback_; - // Application Callback Object. +class TAO_ORBSVCS_Export TAO_SFP_Object : public TAO_AV_Protocol_Object +{ +public: + TAO_SFP_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport); + // We should add a sfp options parameter. + + virtual ~TAO_SFP_Object (void); + // Dtor + + virtual int handle_input (void) = 0; + virtual int send_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0); + + virtual int send_frame (const iovec *iov, + int iovcnt, + TAO_AV_frame_info *frame_info = 0); + + virtual int destroy (void); + virtual int set_policies (const TAO_AV_PolicyList &policies); + +protected: + ACE_Message_Block *get_fragment (ACE_Message_Block *&frame, + size_t initial_len, + size_t &last_mb_orig_len, + size_t &last_mb_current_len); + CORBA::ULong sequence_num_; + CORBA::ULong source_id_; + CORBA::Long max_credit_; + CORBA::Long current_credit_; + TAO_SFP_Frame_State state_; +}; - int sequence_num_; - // sequence number of the packet. +class TAO_ORBSVCS_Export TAO_SFP_Producer_Object : public TAO_SFP_Object +{ +public: + TAO_SFP_Producer_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport, + char *&flow_options); + virtual int handle_input (void); +protected: + CORBA::ULong credit_sequence_num_; +}; - flowProtocol::frameHeader frame_header_; - ssize_t frame_header_len_; - // frame header to be sent with all frames. - // length of the frame header. +class TAO_ORBSVCS_Export TAO_SFP_Consumer_Object : public TAO_SFP_Object +{ +public: + TAO_SFP_Consumer_Object (TAO_AV_Callback *callback, + TAO_AV_Transport *transport, + char *&flow_options); + virtual int handle_input (void); +}; - flowProtocol::fragment fragment_; - ssize_t fragment_len_; - // fragment header for each fragment. - - flowProtocol::Start start_; - ssize_t start_len_; - // Start message and its length. - - flowProtocol::StartReply start_reply_; - ssize_t start_reply_len_; - // StartReply message and its length. - - flowProtocol::credit credit_; - ssize_t credit_len_; - CORBA::ULong credit_num_; - // Credit message and its length. - - char magic_number_[MAGIC_NUMBER_LEN]; - // used for peeking the magic_number. - const size_t magic_number_len_; - u_int more_fragments_; - // boolean flags indicating that there are more fragments. - ACE_Hash_Map_Manager<CORBA::ULong,TAO_SFP_Fragment_Table_Entry*,ACE_Null_Mutex> fragment_table_; - // chain of fragments of the current frame. +class TAO_ORBSVCS_Export TAO_AV_SFP_Factory : public TAO_AV_Flow_Protocol_Factory +{ +public: + TAO_AV_SFP_Factory (void); + virtual ~TAO_AV_SFP_Factory (void); + virtual int init (int argc, char *argv[]); + // Initialization hook. + virtual int match_protocol (const char *flow_string); + virtual TAO_AV_Protocol_Object* make_protocol_object (TAO_FlowSpec_Entry *entry, + TAO_Base_StreamEndPoint *endpoint, + TAO_AV_Flow_Handler *handler, + TAO_AV_Transport *transport); }; -#endif /* !defined (TAO_SFP_H) */ +ACE_STATIC_SVC_DECLARE (TAO_AV_SFP_Flow_Factory) +ACE_FACTORY_DECLARE (TAO_ORBSVCS, TAO_AV_SFP_Flow_Factory) + +#endif /* TAO_SFP_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/source.cpp b/TAO/orbsvcs/orbsvcs/AV/source.cpp new file mode 100644 index 00000000000..522f29bd6aa --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/source.cpp @@ -0,0 +1,531 @@ +/* + * 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" + +/* 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))) + +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 (strcasecmp (s, "cname") == 0) + return (RTCP_SDES_CNAME); + if (strcasecmp (s, "name") == 0) + return (RTCP_SDES_NAME); + if (strcasecmp (s, "email") == 0) + return (RTCP_SDES_EMAIL); + if (strcasecmp (s, "phone") == 0) + return (RTCP_SDES_PHONE); + if (strcasecmp (s, "loc") == 0 || strcasecmp (s, "location") == 0) + return (RTCP_SDES_LOC); + if (strcasecmp (s, "tool") == 0) + return (RTCP_SDES_TOOL); + if (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; + } + qsort (srctab, n, sizeof (*srctab), compare); + 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 new file mode 100644 index 00000000000..5adafbfe2b1 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/source.h @@ -0,0 +1,225 @@ +/* -*- 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 + +#define RTCP_SDES_MAX 7 + +#include "ace/OS.h" +#include "tao/TAO.h" +class TAO_AV_SourceManager; + +#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); +protected: + static int compare (const void*, const void*); + 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__ */ + +#endif /* TAO_AV_Source_H */ diff --git a/TAO/orbsvcs/orbsvcs/AV/source.i b/TAO/orbsvcs/orbsvcs/AV/source.i new file mode 100644 index 00000000000..73ed03d86b7 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/AV/source.i @@ -0,0 +1,491 @@ +/* -*- 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; +} + diff --git a/TAO/orbsvcs/orbsvcs/AVStreams.idl b/TAO/orbsvcs/orbsvcs/AVStreams.idl index fac5c06a6f5..61388c797f0 100644 --- a/TAO/orbsvcs/orbsvcs/AVStreams.idl +++ b/TAO/orbsvcs/orbsvcs/AVStreams.idl @@ -1,6 +1,5 @@ /* -*- C++ -*- */ // $Id$ - // ============================================================================ // // = LIBRARY @@ -10,7 +9,7 @@ // AVStreams.idl // // = AUTHOR -// Sumedh Mungee <sumehd@cs.wustl.edu> and Nagarajan Surendran +// Sumedh Mungee <sumedh@cs.wustl.edu> and Nagarajan Surendran // <naga@cs.wustl.edu> // // ============================================================================ @@ -645,7 +644,7 @@ module AVStreams // control, if one is required string go_to_listen(inout AVStreams::QoS the_qos, in boolean is_mcast, - in FlowProducer peer, + in FlowEndPoint peer, inout string flowProtocol)// syntax <flowProtocol> // The out value of flowProtocol contains SFP version // supported and all options including "Credit". diff --git a/TAO/orbsvcs/tests/AVStreams/Full_Profile/Makefile b/TAO/orbsvcs/tests/AVStreams/Full_Profile/Makefile new file mode 100644 index 00000000000..d2f38f81303 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Full_Profile/Makefile @@ -0,0 +1,57 @@ +#---------------------------------------------------------------------------- +# $Id$ +# +# Top-level Makefile for Full Profile testing of AVStreams of TAO. +# +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +LIBS += -lorbsvcs -lTAO + +SERVER_OBJS = server.o +CLIENT_OBJS = ftp.o + +VLDLIBS = $(LDLIBS:%=%$(VAR)) + +ifndef TAO_ROOT +TAO_ROOT = $(ACE_ROOT)/TAO +endif + +FILES = ftp server +DEFS = $(addsuffix .h,$(FILES)) +LSRC = $(addsuffix .cpp,$(FILES)) + +BIN2 = server ftp + +#### If the TAO orbsvcs library wasn't built with sufficient components, +#### don't try to build here. +TAO_ORBSVCS := $(shell $(ACE_ROOT)/bin/ace_components --orbsvcs) +ifeq (AV,$(findstring AV,$(TAO_ORBSVCS))) + BIN = $(BIN2) +endif # AV + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(TAO_ROOT)/rules.tao.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +DCFLAGS = -g +LDFLAGS += -L$(TAO_ROOT)/orbsvcs/orbsvcs -L$(TAO_ROOT)/tao +CPPFLAGS += -I$(TAO_ROOT)/orbsvcs -I$(TAO_ROOT) $(TSS_ORB_FLAG) + +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/TAO/orbsvcs/tests/AVStreams/Full_Profile/ftp.cpp b/TAO/orbsvcs/tests/AVStreams/Full_Profile/ftp.cpp new file mode 100644 index 00000000000..b7fe10b9a8c --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Full_Profile/ftp.cpp @@ -0,0 +1,377 @@ +// $Id$ + +#include "ftp.h" + +FTP_Client_Callback::FTP_Client_Callback (void) + // :handler_ (handler), + :count_ (0) +{ +} + +int +FTP_Client_Callback::handle_end_stream (void) +{ + TAO_AV_CORE::instance ()->stop_run (); + return 0; +} + +void +FTP_Client_Callback::get_timeout (ACE_Time_Value *&tv, + void *&arg) +{ + ACE_Time_Value *timeout; + ACE_NEW (timeout, + ACE_Time_Value(2)); + tv = timeout; +} + +int +FTP_Client_Callback::handle_timeout (void *arg) +{ + ACE_Message_Block mb (BUFSIZ); + ACE_DEBUG ((LM_DEBUG,"FTP_Client_Callback::get_frame")); + char *buf = mb.rd_ptr (); + cerr << "message block size" << mb.size () << endl; + int n = ACE_OS::fread(buf,1,mb.size (),CLIENT::instance ()->file ()); + if (n < 0) + { + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread end of file\n"),-1); + } + if (n == 0) + { + if (::feof (CLIENT::instance ()->file ())) + { + // wait for sometime for the data to be flushed to the other side. + this->count_++; + if (this->count_ == 2) + { + ACE_DEBUG ((LM_DEBUG,"handle_timeout:End of file\n")); + AVStreams::flowSpec stop_spec (1); + ACE_DECLARE_NEW_CORBA_ENV; + CLIENT::instance ()->streamctrl ()->stop (stop_spec,ACE_TRY_ENV); + ACE_CHECK_RETURN (-1); + CLIENT::instance ()->streamctrl ()->destroy (stop_spec,ACE_TRY_ENV); + TAO_AV_CORE::instance ()->stop_run (); + } + else + return 0; + } + else + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread error\n"),-1); + } + cerr << "read bytes = " << n << endl; + mb.wr_ptr (n); + int result = this->protocol_object_->send_frame (&mb); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"send failed:%p","FTP_Client_Flow_Handler::send \n"),-1); + ACE_DEBUG ((LM_DEBUG,"handle_timeout::buffer sent succesfully\n")); + return 0; +} + +FTP_Client_Producer::FTP_Client_Producer (void) + :TAO_FlowProducer ("Data",CLIENT::instance ()->protocols (),CLIENT::instance ()->format ()) +{ +} + +int +FTP_Client_Producer::set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object) +{ + this->callback_->set_protocol_object (object); + return 0; +} + +int +FTP_Client_Producer::get_callback (const char *flowname, + TAO_AV_Callback *&callback) +{ + ACE_NEW_RETURN (this->callback_, + FTP_Client_Callback, + -1); + callback = this->callback_; +} + +Client::parse_args (int argc, + char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:a:p:s"); + + this->use_sfp_ = 0; + char c; + while ((c= opts ()) != -1) + { + switch (c) + { + case 'f': + this->filename_ = ACE_OS::strdup (opts.optarg); + break; + case 'a': + this->address_ = ACE_OS::strdup (opts.optarg); + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + break; + case 's': + this->use_sfp_ = 1; + break; + default: + ACE_DEBUG ((LM_DEBUG,"Unknown option\n")); + return -1; + break; + } + } + return 0; +} + +FILE * +Client::file (void) +{ + return this->fp_; +} + +char* +Client::flowname (void) +{ + return this->flowname_; +} + +AVStreams::protocolSpec +Client::protocols (void) +{ + AVStreams::protocolSpec protocols (1); + protocols.length (1); + char buf [BUFSIZ]; + ACE_OS::sprintf (buf,"%s=%s",this->protocol_,this->address_); + protocols [0] = CORBA::string_dup (buf); + return protocols; +} + +const char * +Client::format (void) +{ + return "UNS:ftp"; +} + +const char * +Client::address (void) + +{ + return this->address_; +} + +TAO_StreamCtrl* +Client::streamctrl (void) +{ + return &this->streamctrl_; +} + +Client::Client (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + endpoint_strategy_ (orb_manager_), + client_mmdevice_ (&endpoint_strategy_), + fdev_ (0), + fp_ (0), + protocol_ (ACE_OS::strdup ("UDP")) +{ +} + + +int +Client::bind_to_server (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + // Initialize the naming services + if (my_naming_client_.init (this->orb_manager_->orb ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice"); + CORBA::Object_var server_mmdevice_obj = + my_naming_client_->resolve (server_mmdevice_name, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + this->server_mmdevice_ = + AVStreams::MMDevice::_narrow (server_mmdevice_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + + if (CORBA::is_nil (this->server_mmdevice_.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " could not resolve Server_Mmdevice in Naming service <%s>\n"), + -1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Command_Handler::resolve_reference"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::init (int argc,char **argv) +{ + this->argc_ = argc; + this->argv_ = argv; + + // Increase the debug_level so that we can see the output + // TAO_debug_level++; + CORBA::String_var ior; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = TAO_AV_CORE::instance ()->orb_manager (); + this->orb_manager_->init_child_poa (this->argc_, + this->argv_, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->parse_args (this->argc_, this->argv_); + // activate the client video mmdevice under the child poa. + ior = this->orb_manager_->activate (&this->client_mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + this->orb_manager_->activate_poa_manager (ACE_TRY_ENV); + ACE_TRY_CHECK; + ACE_NEW_RETURN (this->fdev_, + FTP_Client_FDev, + -1); + ACE_NEW_RETURN (this->flowname_, + char [BUFSIZ], + 0); + ACE_OS::sprintf (this->flowname_, + "Data"); + + this->fdev_->flowname (this->flowname ()); + AVStreams::MMDevice_var mmdevice = this->client_mmdevice_._this (ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FDev_var fdev = this->fdev_->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + mmdevice->add_fdev (fdev.in (), + ACE_TRY_ENV); + + // Initialize the naming services + CORBA::ORB_var orb = orb_manager_->orb (); + if (this->my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + this->fp_ = ACE_OS::fopen (this->filename_,"r"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + if (this->bind_to_server () == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Error binding to the naming service\n"), + -1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + char flow_protocol_str [BUFSIZ]; + if (this->use_sfp_) + ACE_OS::strcpy (flow_protocol_str,"sfp:1.0"); + else + ACE_OS::strcpy (flow_protocol_str,""); + AVStreams::streamQoS_var the_qos (new AVStreams::streamQoS); + AVStreams::flowSpec flow_spec (1); + // Bind the client and server mmdevices. + + ACE_INET_Addr addr (this->address_); + TAO_Forward_FlowSpec_Entry entry (this->flowname_, + "IN", + "USER_DEFINED", + flow_protocol_str, + this->protocol_, + &addr); + flow_spec [0] = CORBA::string_dup (entry.entry_to_string ()); + flow_spec.length (1); + ACE_High_Res_Timer timer; + ACE_Time_Value elapsed; + timer.start (); + CORBA::Boolean result = + this->streamctrl_.bind_devs (this->client_mmdevice_._this (ACE_TRY_ENV), + this->server_mmdevice_.in (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + timer.stop (); + timer.elapsed_time (elapsed); + elapsed.dump (); + ACE_TRY_CHECK; + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"streamctrl::bind_devs failed\n"),-1); + AVStreams::flowSpec start_spec (1); +// start_spec.length (1); +// start_spec [0] = CORBA::string_dup (this->flowname_); + this->streamctrl_.start (start_spec,ACE_TRY_ENV); + ACE_TRY_CHECK; + // Schedule a timer for the for the flow handler. + TAO_AV_CORE::instance ()->run (); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::run"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +main (int argc, + char **argv) +{ + int result = 0; + result = CLIENT::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::init failed\n"),1); + result = CLIENT::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::run failed\n"),1); + +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Client,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_A<TAO_StreamEndPoint_A,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy<TAO_StreamEndPoint_A,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_FDev <FTP_Client_Producer,TAO_FlowConsumer>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Client,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_A<TAO_StreamEndPoint_A,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy<TAO_StreamEndPoint_A,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_FDev <FTP_Client_Producer,TAO_FlowConsumer> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Full_Profile/ftp.h b/TAO/orbsvcs/tests/AVStreams/Full_Profile/ftp.h new file mode 100644 index 00000000000..7b324e481a2 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Full_Profile/ftp.h @@ -0,0 +1,90 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef TAO_AV_FTP_H +#define TAO_AV_FTP_H + +#include "ace/Get_Opt.h" +#include "ace/High_Res_Timer.h" +#include "tao/TAO.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Flows_T.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/Transport.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" + +class FTP_Client_Callback; +class FTP_Client_Producer + :public virtual TAO_FlowProducer +{ +public: + FTP_Client_Producer (void); + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + int set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object); +protected: + FTP_Client_Callback *callback_; +}; + +class FTP_Client_Callback + :public TAO_AV_Callback +{ +public: + FTP_Client_Callback (void); + virtual int handle_timeout (void *arg); + virtual int handle_end_stream (void); + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); + // virtual int get_frame (ACE_Message_Block *&block,TAO_AV_frame_info *&frame_info); + void set_protocol_object (TAO_AV_Protocol_Object *protocol_object) {this->protocol_object_ = protocol_object;} + +protected: + // FTP_Client_Flow_Handler *handler_; + int count_; + TAO_AV_Protocol_Object *protocol_object_; +}; + +typedef TAO_AV_Endpoint_Reactive_Strategy_A<TAO_StreamEndPoint_A,TAO_VDev,AV_Null_MediaCtrl> ENDPOINT_STRATEGY; +typedef TAO_FDev <FTP_Client_Producer,TAO_FlowConsumer> FTP_Client_FDev; + +class Client +{ +public: + Client (void); + int init (int argc, char **argv); + int run (void); + FILE *file (void); + char *flowname (void); + TAO_StreamCtrl* streamctrl (void); + AVStreams::protocolSpec protocols (void); + const char *format (void); + const char *address (void); +private: + int parse_args (int argc, char **argv); + int bind_to_server (void); + TAO_ORB_Manager *orb_manager_; + ENDPOINT_STRATEGY endpoint_strategy_; + AVStreams::MMDevice_var server_mmdevice_; + TAO_MMDevice client_mmdevice_; + FTP_Client_FDev *fdev_; + TAO_StreamCtrl streamctrl_; + // Video stream controller + + int argc_; + char **argv_; + const char *filename_; + const char *address_; + + TAO_Naming_Client my_naming_client_; + FILE *fp_; + char *protocol_; + char *flowname_; + int use_sfp_; +}; + +typedef ACE_Singleton<Client,ACE_Null_Mutex> CLIENT; + +#endif /* TAO_AV_FTP_H */ diff --git a/TAO/orbsvcs/tests/AVStreams/Full_Profile/server.cpp b/TAO/orbsvcs/tests/AVStreams/Full_Profile/server.cpp new file mode 100644 index 00000000000..8c3317f2946 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Full_Profile/server.cpp @@ -0,0 +1,277 @@ +// $Id$ + +#include "server.h" + +FTP_Server_FlowEndPoint::FTP_Server_FlowEndPoint (void) + :TAO_FlowConsumer ("Data",SERVER::instance ()->protocols (),SERVER::instance ()->format ()) +{ + AVStreams::protocolSpec protocols (2); + protocols.length (3); + protocols [0] = CORBA::string_dup ("TCP"); + protocols [1] = CORBA::string_dup ("UDP"); + protocols [2] = CORBA::string_dup ("RTP/UDP"); + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->set_protocol_restriction (protocols, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"FTP_Server_FlowEndPoint::FTP_Server_FlowEndPoint"); + } + ACE_ENDTRY; + ACE_CHECK; +} + +int +FTP_Server_FlowEndPoint::get_callback (const char *flowname, + TAO_AV_Callback *&callback) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_StreamEndPoint::get_sfp_callback\n")); + ACE_NEW_RETURN (callback, + FTP_Server_Callback, + -1); + return 0; +} + +int +FTP_Server_Callback::handle_stop (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::stop")); + ACE_OS::fclose (SERVER::instance ()->file ()); + return 0; +} + +int +FTP_Server_Callback::receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::receive_frame\n")); + while (frame != 0) + { + int result = ACE_OS::fwrite (frame->rd_ptr (), + frame->length (), + 1, + SERVER::instance ()->file ()); + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Server_Flow_Handler::fwrite failed\n"),-1); + frame = frame->cont (); + } + return 0; +} + +int +FTP_Server_Callback::handle_end_stream (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_SFP_Callback::end_stream\n")); + CORBA::ORB_var orb = TAO_AV_CORE::instance ()->orb_manager ()->orb (); + orb->shutdown (); + return 0; +} + +// FTP_Server_FDev::FTP_Server_FDev (void) +// :TAO_FDev ("Data") +// { +// } + +// AVStreams::FlowConsumer_ptr +// FTP_Server_FDev::make_consumer (AVStreams::FlowConnection_ptr the_requester, +// AVStreams::QoS & the_qos, +// CORBA::Boolean_out met_qos, +// char *& named_fdev, +// CORBA::Environment &ACE_TRY_ENV) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Server_FDev::make_consumer")); +// FTP_Server_FlowEndPoint *endpoint; +// ACE_NEW_RETURN (endpoint, +// FTP_Server_FlowEndPoint, +// 0); +// return endpoint->_this (ACE_TRY_ENV); +// ACE_CHECK_RETURN (0); +// } + +Server::Server (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + reactive_strategy_ (orb_manager_) +{ +} + +AVStreams::protocolSpec +Server::protocols (void) +{ + AVStreams::protocolSpec protocols (2); + protocols.length (2); + protocols [0] = CORBA::string_dup ("TCP"); + protocols [1] = CORBA::string_dup ("UDP"); + return protocols; +} + +const char* +Server::format (void) +{ + return "UNS:ftp"; +} + +int +Server::init (int argc, + char **argv) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = + TAO_AV_CORE::instance ()->orb_manager (); + + // Initialize the orb_manager + this->orb_manager_->init_child_poa (argc, + argv, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::ORB_var orb = + this->orb_manager_->orb (); + + PortableServer::POA_var child_poa = + this->orb_manager_->child_poa (); + + int result = this->parse_args (argc,argv); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"parse args failed\n"),-1); + // Initialize the naming services + + if (my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + this->orb_manager_->activate_poa_manager (ACE_TRY_ENV); + ACE_TRY_CHECK; + // Register the video mmdevice object with the ORB + ACE_NEW_RETURN (this->mmdevice_, + TAO_MMDevice (&this->reactive_strategy_), + -1); + + ACE_NEW_RETURN (this->fdev_, + FTP_Server_FDev, + -1); + this->fdev_->flowname ("Data"); + + AVStreams::MMDevice_var mmdevice = this->mmdevice_->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FDev_var fdev = this->fdev_->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + mmdevice->add_fdev (fdev.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + // create the video server mmdevice with the naming service pointer. + this->orb_manager_->activate_under_child_poa ("Server_MMDevice", + this->mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Register the mmdevice with the naming service. + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice"); + + // Register the video control object with the naming server. + this->my_naming_client_->rebind (server_mmdevice_name, + mmdevice.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->orb_manager_->run (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::parse_args (int argc,char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:p:"); + + char c; + while ((c = opts ()) != -1) + { + switch (c) + { + case 'f': + this->fp_ = ACE_OS::fopen (opts.optarg,"w"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + default: + ACE_ERROR_RETURN ((LM_ERROR,"Usage: server -f filename"),-1); + break; + } + } + return 0; +} + +FILE* +Server::file (void) +{ + return this->fp_; +} + +int +main (int argc, + char **argv) +{ + int result = 0; + result = SERVER::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::init failed\n"),1); + result = SERVER::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::run failed\n"),1); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Server,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_B <TAO_StreamEndPoint_B,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy <TAO_StreamEndPoint_B,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_FDev <TAO_FlowProducer, FTP_Server_FlowEndPoint>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Server,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_B <TAO_StreamEndPoint_B,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy <TAO_StreamEndPoint_B,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_FDev <TAO_FlowProducer, FTP_Server_FlowEndPoint> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Full_Profile/server.h b/TAO/orbsvcs/tests/AVStreams/Full_Profile/server.h new file mode 100644 index 00000000000..9f0d18e7767 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Full_Profile/server.h @@ -0,0 +1,72 @@ +/* -*- C++ -*- */ +// $Id$ + +#include "ace/Get_Opt.h" +#include "tao/TAO.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Flows_T.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/Transport.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" +#include "orbsvcs/AV/Policy.h" + +class FTP_Server_Callback + :public TAO_AV_Callback +{ +public: + virtual int handle_stop (void); + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &); + virtual int handle_end_stream (void); +}; + +class FTP_Server_FlowEndPoint + :public TAO_FlowConsumer +{ +public: + FTP_Server_FlowEndPoint (void); + int get_callback (const char *flowname, + TAO_AV_Callback *&callback); +}; + +typedef TAO_FDev <TAO_FlowProducer, FTP_Server_FlowEndPoint> FTP_Server_FDev; +// class FTP_Server_FDev +// :public TAO_FDev +// { +// public: +// FTP_Server_FDev (void); +// virtual AVStreams::FlowConsumer_ptr make_consumer (AVStreams::FlowConnection_ptr the_requester, +// AVStreams::QoS & the_qos, +// CORBA::Boolean_out met_qos, +// char *& named_fdev, +// CORBA::Environment &env = CORBA::Environment::default_environment ()); +// // bridge method for the application to override the consumer object +// // creation. Default implementation creates a TAO_FlowConsumer. + +// }; + +class Server +{ +public: + Server (void); + int init (int argc, + char **argv); + int run (void); + FILE *file (void); + AVStreams::protocolSpec protocols (void); + const char *format (void); +protected: + int parse_args (int argc,char **argv); + TAO_ORB_Manager *orb_manager_; + TAO_Naming_Client my_naming_client_; + TAO_AV_Endpoint_Reactive_Strategy_B <TAO_StreamEndPoint_B,TAO_VDev,AV_Null_MediaCtrl> reactive_strategy_; + TAO_MMDevice *mmdevice_; + FTP_Server_FDev *fdev_; + FILE *fp_; + char *protocol_; +}; + +typedef ACE_Singleton<Server,ACE_Null_Mutex> SERVER; diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/Makefile b/TAO/orbsvcs/tests/AVStreams/Latency/Makefile new file mode 100644 index 00000000000..1056ec71782 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/Makefile @@ -0,0 +1,1123 @@ +#---------------------------------------------------------------------------- +# $Id$ +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +LDLIBS = -lorbsvcs -lTAO + +ifndef TAO_ROOT +TAO_ROOT = $(ACE_ROOT)/TAO +endif + +PSRC = $(PING_OBJS:.o=.cpp) $(PONG_OBJS:.o=.cpp) $(CONTROL_OBJS:.o=.cpp) + +BIN2 = ping pong control + +#### If the TAO orbsvcs library wasn't built with sufficient components, +#### don't try to build here. +TAO_ORBSVCS := $(shell $(ACE_ROOT)/bin/ace_components --orbsvcs) +ifeq (AV,$(findstring AV,$(TAO_ORBSVCS))) + BIN = $(BIN2) +endif # AV + +PING_OBJS = ping.o +PONG_OBJS = pong.o +CONTROL_OBJS = control.o + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(TAO_ROOT)/rules.tao.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU +include $(TAO_ROOT)/taoconfig.mk + +CPPFLAGS += -I$(TAO_ROOT)/orbsvcs + +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +.obj/ping.o .obj/ping.so .shobj/ping.o .shobj/ping.so: ping.cpp ping.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AVStreams_i.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config-sunos5.7.h \ + $(ACE_ROOT)/ace/config-sunos5.6.h \ + $(ACE_ROOT)/ace/config-sunos5.5.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/SOCK_Dgram_Mcast.h \ + $(ACE_ROOT)/ace/SOCK_Dgram.h \ + $(ACE_ROOT)/ace/SOCK.h \ + $(ACE_ROOT)/ace/Addr.h \ + $(ACE_ROOT)/ace/Addr.i \ + $(ACE_ROOT)/ace/IPC_SAP.h \ + $(ACE_ROOT)/ace/IPC_SAP.i \ + $(ACE_ROOT)/ace/SOCK.i \ + $(ACE_ROOT)/ace/SOCK_Dgram.i \ + $(ACE_ROOT)/ace/INET_Addr.h \ + $(ACE_ROOT)/ace/INET_Addr.i \ + $(ACE_ROOT)/ace/SOCK_Dgram_Mcast.i \ + $(ACE_ROOT)/ace/ATM_Addr.h \ + $(ACE_ROOT)/ace/ATM_Addr.i \ + $(ACE_ROOT)/ace/Containers_T.h \ + $(ACE_ROOT)/ace/Containers.h \ + $(ACE_ROOT)/ace/Malloc_Base.h \ + $(ACE_ROOT)/ace/Containers.i \ + $(ACE_ROOT)/ace/Containers_T.i \ + $(ACE_ROOT)/ace/Containers_T.cpp \ + $(ACE_ROOT)/ace/Malloc.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.i \ + $(ACE_ROOT)/ace/Based_Pointer_T.cpp \ + $(ACE_ROOT)/ace/Based_Pointer_Repository.h \ + $(ACE_ROOT)/ace/Singleton.h \ + $(ACE_ROOT)/ace/Synch.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \ + $(ACE_ROOT)/ace/Synch.i \ + $(ACE_ROOT)/ace/Synch_T.h \ + $(ACE_ROOT)/ace/Event_Handler.h \ + $(ACE_ROOT)/ace/Event_Handler.i \ + $(ACE_ROOT)/ace/Synch_T.i \ + $(ACE_ROOT)/ace/Thread.h \ + $(ACE_ROOT)/ace/Thread.i \ + $(ACE_ROOT)/ace/Atomic_Op.i \ + $(ACE_ROOT)/ace/Synch_T.cpp \ + $(ACE_ROOT)/ace/Singleton.i \ + $(ACE_ROOT)/ace/Singleton.cpp \ + $(ACE_ROOT)/ace/Object_Manager.h \ + $(ACE_ROOT)/ace/Object_Manager.i \ + $(ACE_ROOT)/ace/Managed_Object.h \ + $(ACE_ROOT)/ace/Managed_Object.i \ + $(ACE_ROOT)/ace/Managed_Object.cpp \ + $(ACE_ROOT)/ace/Malloc.i \ + $(ACE_ROOT)/ace/Malloc_T.h \ + $(ACE_ROOT)/ace/Free_List.h \ + $(ACE_ROOT)/ace/Free_List.i \ + $(ACE_ROOT)/ace/Free_List.cpp \ + $(ACE_ROOT)/ace/Malloc_T.i \ + $(ACE_ROOT)/ace/Malloc_T.cpp \ + $(ACE_ROOT)/ace/Memory_Pool.h \ + $(ACE_ROOT)/ace/Signal.h \ + $(ACE_ROOT)/ace/Signal.i \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/Mem_Map.i \ + $(ACE_ROOT)/ace/Memory_Pool.i \ + $(ACE_ROOT)/ace/Process.h \ + $(ACE_ROOT)/ace/SString.h \ + $(ACE_ROOT)/ace/SString.i \ + $(ACE_ROOT)/ace/Process.i \ + $(ACE_ROOT)/ace/SOCK_CODgram.h \ + $(ACE_ROOT)/ace/SOCK_IO.h \ + $(ACE_ROOT)/ace/SOCK_IO.i \ + $(ACE_ROOT)/ace/SOCK_CODgram.i \ + $(ACE_ROOT)/ace/Connector.h \ + $(ACE_ROOT)/ace/Service_Config.h \ + $(ACE_ROOT)/ace/Service_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.i \ + $(ACE_ROOT)/ace/Service_Object.i \ + $(ACE_ROOT)/ace/Service_Config.i \ + $(ACE_ROOT)/ace/Reactor.h \ + $(ACE_ROOT)/ace/Handle_Set.h \ + $(ACE_ROOT)/ace/Handle_Set.i \ + $(ACE_ROOT)/ace/Timer_Queue.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.i \ + $(ACE_ROOT)/ace/Timer_Queue_T.cpp \ + $(ACE_ROOT)/ace/Reactor.i \ + $(ACE_ROOT)/ace/Reactor_Impl.h \ + $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \ + $(ACE_ROOT)/ace/Map_Manager.h \ + $(ACE_ROOT)/ace/Map_Manager.i \ + $(ACE_ROOT)/ace/Map_Manager.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.h \ + $(ACE_ROOT)/ace/Synch_Options.h \ + $(ACE_ROOT)/ace/Synch_Options.i \ + $(ACE_ROOT)/ace/Task.h \ + $(ACE_ROOT)/ace/Thread_Manager.h \ + $(ACE_ROOT)/ace/Thread_Manager.i \ + $(ACE_ROOT)/ace/Task.i \ + $(ACE_ROOT)/ace/Task_T.h \ + $(ACE_ROOT)/ace/Message_Queue.h \ + $(ACE_ROOT)/ace/Message_Block.h \ + $(ACE_ROOT)/ace/Message_Block.i \ + $(ACE_ROOT)/ace/Message_Block_T.h \ + $(ACE_ROOT)/ace/Message_Block_T.i \ + $(ACE_ROOT)/ace/Message_Block_T.cpp \ + $(ACE_ROOT)/ace/IO_Cntl_Msg.h \ + $(ACE_ROOT)/ace/Message_Queue_T.h \ + $(ACE_ROOT)/ace/Message_Queue_T.i \ + $(ACE_ROOT)/ace/Message_Queue_T.cpp \ + $(ACE_ROOT)/ace/Strategies.h \ + $(ACE_ROOT)/ace/Strategies_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager.h \ + $(ACE_ROOT)/ace/Functor.h \ + $(ACE_ROOT)/ace/Functor.i \ + $(ACE_ROOT)/ace/Functor_T.h \ + $(ACE_ROOT)/ace/Functor_T.i \ + $(ACE_ROOT)/ace/Functor_T.cpp \ + $(ACE_ROOT)/ace/Hash_Map_Manager.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Strategies_T.i \ + $(ACE_ROOT)/ace/Strategies_T.cpp \ + $(ACE_ROOT)/ace/Service_Repository.h \ + $(ACE_ROOT)/ace/Service_Types.h \ + $(ACE_ROOT)/ace/Service_Types.i \ + $(ACE_ROOT)/ace/Service_Repository.i \ + $(ACE_ROOT)/ace/WFMO_Reactor.h \ + $(ACE_ROOT)/ace/WFMO_Reactor.i \ + $(ACE_ROOT)/ace/Strategies.i \ + $(ACE_ROOT)/ace/Message_Queue.i \ + $(ACE_ROOT)/ace/Task_T.i \ + $(ACE_ROOT)/ace/Task_T.cpp \ + $(ACE_ROOT)/ace/Module.h \ + $(ACE_ROOT)/ace/Module.i \ + $(ACE_ROOT)/ace/Module.cpp \ + $(ACE_ROOT)/ace/Stream_Modules.h \ + $(ACE_ROOT)/ace/Stream_Modules.i \ + $(ACE_ROOT)/ace/Stream_Modules.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.i \ + $(ACE_ROOT)/ace/Svc_Handler.cpp \ + $(ACE_ROOT)/ace/Dynamic.h \ + $(ACE_ROOT)/ace/Dynamic.i \ + $(ACE_ROOT)/ace/Connector.i \ + $(ACE_ROOT)/ace/Connector.cpp \ + $(ACE_ROOT)/ace/SOCK_Connector.h \ + $(ACE_ROOT)/ace/SOCK_Stream.h \ + $(ACE_ROOT)/ace/SOCK_Stream.i \ + $(ACE_ROOT)/ace/Time_Value.h \ + $(ACE_ROOT)/ace/SOCK_Connector.i \ + $(ACE_ROOT)/ace/Acceptor.h \ + $(ACE_ROOT)/ace/Acceptor.i \ + $(ACE_ROOT)/ace/Acceptor.cpp \ + $(ACE_ROOT)/ace/SOCK_Acceptor.h \ + $(ACE_ROOT)/ace/SOCK_Acceptor.i \ + $(TAO_ROOT)/tao/TAO.h \ + $(TAO_ROOT)/tao/corbafwd.h \ + $(ACE_ROOT)/ace/CDR_Stream.h \ + $(ACE_ROOT)/ace/CDR_Stream.i \ + $(TAO_ROOT)/tao/try_macros.h \ + $(TAO_ROOT)/tao/orbconf.h \ + $(ACE_ROOT)/ace/CORBA_macros.h \ + $(TAO_ROOT)/tao/corbafwd.i \ + $(TAO_ROOT)/tao/POAC.h \ + $(TAO_ROOT)/tao/PolicyC.h \ + $(TAO_ROOT)/tao/CurrentC.h \ + $(TAO_ROOT)/tao/Object.h \ + $(TAO_ROOT)/tao/Object.i \ + $(TAO_ROOT)/tao/CurrentC.i \ + $(TAO_ROOT)/tao/CDR.h \ + $(TAO_ROOT)/tao/Typecode.h \ + $(TAO_ROOT)/tao/Exception.h \ + $(TAO_ROOT)/tao/Exception.i \ + $(TAO_ROOT)/tao/Typecode.i \ + $(TAO_ROOT)/tao/CDR.i \ + $(TAO_ROOT)/tao/Sequence.h \ + $(TAO_ROOT)/tao/Managed_Types.h \ + $(TAO_ROOT)/tao/Managed_Types.i \ + $(TAO_ROOT)/tao/Sequence.i \ + $(TAO_ROOT)/tao/Sequence_T.h \ + $(TAO_ROOT)/tao/Sequence_T.i \ + $(TAO_ROOT)/tao/Sequence_T.cpp \ + $(TAO_ROOT)/tao/varout.h \ + $(TAO_ROOT)/tao/varout.i \ + $(TAO_ROOT)/tao/varout.cpp \ + $(TAO_ROOT)/tao/PolicyC.i \ + $(TAO_ROOT)/tao/Environment.h \ + $(TAO_ROOT)/tao/Environment.i \ + $(TAO_ROOT)/tao/POAC.i \ + $(TAO_ROOT)/tao/ORB.h \ + $(TAO_ROOT)/tao/IOR_LookupTable.h \ + $(TAO_ROOT)/tao/Services.h \ + $(TAO_ROOT)/tao/Services.i \ + $(TAO_ROOT)/tao/IORManipulation.h \ + $(TAO_ROOT)/tao/IORS.h \ + $(TAO_ROOT)/tao/IORC.h \ + $(TAO_ROOT)/tao/IORC.i \ + $(TAO_ROOT)/tao/Servant_Base.h \ + $(TAO_ROOT)/tao/Servant_Base.i \ + $(TAO_ROOT)/tao/IORS.i \ + $(TAO_ROOT)/tao/ORB.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/orbsvcs_export.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceC.h \ + $(TAO_ROOT)/tao/corba.h \ + $(TAO_ROOT)/tao/Any.h \ + $(TAO_ROOT)/tao/Any.i \ + $(TAO_ROOT)/tao/NVList.h \ + $(TAO_ROOT)/tao/NVList.i \ + $(TAO_ROOT)/tao/Principal.h \ + $(TAO_ROOT)/tao/Principal.i \ + $(TAO_ROOT)/tao/Request.h \ + $(TAO_ROOT)/tao/Context.h \ + $(TAO_ROOT)/tao/Context.i \ + $(TAO_ROOT)/tao/Request.i \ + $(TAO_ROOT)/tao/Server_Request.h \ + $(TAO_ROOT)/tao/Object_KeyC.h \ + $(TAO_ROOT)/tao/Object_KeyC.i \ + $(TAO_ROOT)/tao/GIOP.h \ + $(TAO_ROOT)/tao/IOPC.h \ + $(TAO_ROOT)/tao/IOPC.i \ + $(TAO_ROOT)/tao/GIOP.i \ + $(TAO_ROOT)/tao/Server_Request.i \ + $(TAO_ROOT)/tao/Marshal.h \ + $(TAO_ROOT)/tao/Marshal.i \ + $(TAO_ROOT)/tao/singletons.h \ + $(TAO_ROOT)/tao/POA.h \ + $(TAO_ROOT)/tao/Object_Adapter.h \ + $(TAO_ROOT)/tao/Key_Adapters.h \ + $(ACE_ROOT)/ace/Map.h \ + $(ACE_ROOT)/ace/Map.i \ + $(ACE_ROOT)/ace/Map_T.h \ + $(ACE_ROOT)/ace/Pair.h \ + $(ACE_ROOT)/ace/Pair.i \ + $(ACE_ROOT)/ace/Pair_T.h \ + $(ACE_ROOT)/ace/Pair_T.i \ + $(ACE_ROOT)/ace/Pair_T.cpp \ + $(ACE_ROOT)/ace/Active_Map_Manager.h \ + $(ACE_ROOT)/ace/Active_Map_Manager.i \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Map_T.i \ + $(ACE_ROOT)/ace/Map_T.cpp \ + $(TAO_ROOT)/tao/Key_Adapters.i \ + $(TAO_ROOT)/tao/Server_Strategy_Factory.h \ + $(TAO_ROOT)/tao/poa_macros.h \ + $(TAO_ROOT)/tao/POAS.h \ + $(TAO_ROOT)/tao/POA_CORBA.h \ + $(TAO_ROOT)/tao/DynAnyC.h \ + $(TAO_ROOT)/tao/DynAnyC.i \ + $(TAO_ROOT)/tao/DomainC.h \ + $(TAO_ROOT)/tao/DomainC.i \ + $(TAO_ROOT)/tao/POAS.i \ + $(TAO_ROOT)/tao/Active_Object_Map.h \ + $(TAO_ROOT)/tao/Active_Object_Map.i \ + $(TAO_ROOT)/tao/Object_Adapter.i \ + $(TAO_ROOT)/tao/POAManager.h \ + $(TAO_ROOT)/tao/POAManager.i \ + $(TAO_ROOT)/tao/POA.i \ + $(TAO_ROOT)/tao/Stub.h \ + $(TAO_ROOT)/tao/Pluggable.h \ + $(TAO_ROOT)/tao/Pluggable.i \ + $(TAO_ROOT)/tao/MProfile.h \ + $(TAO_ROOT)/tao/MProfile.i \ + $(TAO_ROOT)/tao/MessagingS.h \ + $(TAO_ROOT)/tao/TimeBaseS.h \ + $(TAO_ROOT)/tao/TimeBaseC.h \ + $(TAO_ROOT)/tao/TimeBaseC.i \ + $(TAO_ROOT)/tao/TimeBaseS_T.h \ + $(TAO_ROOT)/tao/TimeBaseS_T.i \ + $(TAO_ROOT)/tao/TimeBaseS_T.cpp \ + $(TAO_ROOT)/tao/TimeBaseS.i \ + $(TAO_ROOT)/tao/MessagingC.h \ + $(TAO_ROOT)/tao/PollableC.h \ + $(TAO_ROOT)/tao/MessagingC.i \ + $(TAO_ROOT)/tao/MessagingS.i \ + $(TAO_ROOT)/tao/Stub.i \ + $(TAO_ROOT)/tao/params.h \ + $(TAO_ROOT)/tao/params.i \ + $(TAO_ROOT)/tao/ORB_Core.h \ + $(TAO_ROOT)/tao/Policy_Manager.h \ + $(TAO_ROOT)/tao/Policy_Manager.i \ + $(TAO_ROOT)/tao/Resource_Factory.h \ + $(TAO_ROOT)/tao/Protocol_Factory.h \ + $(TAO_ROOT)/tao/ORB_Core.i \ + $(ACE_ROOT)/ace/Dynamic_Service.h \ + $(ACE_ROOT)/ace/Dynamic_Service.cpp \ + $(TAO_ROOT)/tao/Operation_Table.h \ + $(TAO_ROOT)/tao/Client_Strategy_Factory.h \ + $(TAO_ROOT)/tao/Invocation.h \ + $(TAO_ROOT)/tao/Reply_Dispatcher.h \ + $(TAO_ROOT)/tao/Reply_Dispatcher.i \ + $(TAO_ROOT)/tao/Invocation.i \ + $(TAO_ROOT)/tao/InconsistentTypeCodeC.h \ + $(TAO_ROOT)/tao/DynAny_i.h \ + $(TAO_ROOT)/tao/Union.h \ + $(TAO_ROOT)/tao/ValueBase.h \ + $(TAO_ROOT)/tao/ValueBase.i \ + $(TAO_ROOT)/tao/ValueFactory.h \ + $(TAO_ROOT)/tao/ValueFactory.i \ + $(TAO_ROOT)/tao/ObjectIDList.h \ + $(TAO_ROOT)/tao/ObjectIDList.i \ + $(TAO_ROOT)/tao/WrongTransactionC.h \ + $(TAO_ROOT)/tao/InterfaceC.h \ + $(TAO_ROOT)/tao/InterfaceC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Property/CosPropertyService_i.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosNamingC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosNamingC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AV_Core.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Transport.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Transport.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AVStreams_i.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Policy.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Policy.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Flows_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Protocol_Factory.h \ + $(ACE_ROOT)/ace/Get_Opt.h \ + $(ACE_ROOT)/ace/Get_Opt.i +.obj/pong.o .obj/pong.so .shobj/pong.o .shobj/pong.so: pong.cpp pong.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AVStreams_i.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config-sunos5.7.h \ + $(ACE_ROOT)/ace/config-sunos5.6.h \ + $(ACE_ROOT)/ace/config-sunos5.5.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/SOCK_Dgram_Mcast.h \ + $(ACE_ROOT)/ace/SOCK_Dgram.h \ + $(ACE_ROOT)/ace/SOCK.h \ + $(ACE_ROOT)/ace/Addr.h \ + $(ACE_ROOT)/ace/Addr.i \ + $(ACE_ROOT)/ace/IPC_SAP.h \ + $(ACE_ROOT)/ace/IPC_SAP.i \ + $(ACE_ROOT)/ace/SOCK.i \ + $(ACE_ROOT)/ace/SOCK_Dgram.i \ + $(ACE_ROOT)/ace/INET_Addr.h \ + $(ACE_ROOT)/ace/INET_Addr.i \ + $(ACE_ROOT)/ace/SOCK_Dgram_Mcast.i \ + $(ACE_ROOT)/ace/ATM_Addr.h \ + $(ACE_ROOT)/ace/ATM_Addr.i \ + $(ACE_ROOT)/ace/Containers_T.h \ + $(ACE_ROOT)/ace/Containers.h \ + $(ACE_ROOT)/ace/Malloc_Base.h \ + $(ACE_ROOT)/ace/Containers.i \ + $(ACE_ROOT)/ace/Containers_T.i \ + $(ACE_ROOT)/ace/Containers_T.cpp \ + $(ACE_ROOT)/ace/Malloc.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.i \ + $(ACE_ROOT)/ace/Based_Pointer_T.cpp \ + $(ACE_ROOT)/ace/Based_Pointer_Repository.h \ + $(ACE_ROOT)/ace/Singleton.h \ + $(ACE_ROOT)/ace/Synch.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \ + $(ACE_ROOT)/ace/Synch.i \ + $(ACE_ROOT)/ace/Synch_T.h \ + $(ACE_ROOT)/ace/Event_Handler.h \ + $(ACE_ROOT)/ace/Event_Handler.i \ + $(ACE_ROOT)/ace/Synch_T.i \ + $(ACE_ROOT)/ace/Thread.h \ + $(ACE_ROOT)/ace/Thread.i \ + $(ACE_ROOT)/ace/Atomic_Op.i \ + $(ACE_ROOT)/ace/Synch_T.cpp \ + $(ACE_ROOT)/ace/Singleton.i \ + $(ACE_ROOT)/ace/Singleton.cpp \ + $(ACE_ROOT)/ace/Object_Manager.h \ + $(ACE_ROOT)/ace/Object_Manager.i \ + $(ACE_ROOT)/ace/Managed_Object.h \ + $(ACE_ROOT)/ace/Managed_Object.i \ + $(ACE_ROOT)/ace/Managed_Object.cpp \ + $(ACE_ROOT)/ace/Malloc.i \ + $(ACE_ROOT)/ace/Malloc_T.h \ + $(ACE_ROOT)/ace/Free_List.h \ + $(ACE_ROOT)/ace/Free_List.i \ + $(ACE_ROOT)/ace/Free_List.cpp \ + $(ACE_ROOT)/ace/Malloc_T.i \ + $(ACE_ROOT)/ace/Malloc_T.cpp \ + $(ACE_ROOT)/ace/Memory_Pool.h \ + $(ACE_ROOT)/ace/Signal.h \ + $(ACE_ROOT)/ace/Signal.i \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/Mem_Map.i \ + $(ACE_ROOT)/ace/Memory_Pool.i \ + $(ACE_ROOT)/ace/Process.h \ + $(ACE_ROOT)/ace/SString.h \ + $(ACE_ROOT)/ace/SString.i \ + $(ACE_ROOT)/ace/Process.i \ + $(ACE_ROOT)/ace/SOCK_CODgram.h \ + $(ACE_ROOT)/ace/SOCK_IO.h \ + $(ACE_ROOT)/ace/SOCK_IO.i \ + $(ACE_ROOT)/ace/SOCK_CODgram.i \ + $(ACE_ROOT)/ace/Connector.h \ + $(ACE_ROOT)/ace/Service_Config.h \ + $(ACE_ROOT)/ace/Service_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.i \ + $(ACE_ROOT)/ace/Service_Object.i \ + $(ACE_ROOT)/ace/Service_Config.i \ + $(ACE_ROOT)/ace/Reactor.h \ + $(ACE_ROOT)/ace/Handle_Set.h \ + $(ACE_ROOT)/ace/Handle_Set.i \ + $(ACE_ROOT)/ace/Timer_Queue.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.i \ + $(ACE_ROOT)/ace/Timer_Queue_T.cpp \ + $(ACE_ROOT)/ace/Reactor.i \ + $(ACE_ROOT)/ace/Reactor_Impl.h \ + $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \ + $(ACE_ROOT)/ace/Map_Manager.h \ + $(ACE_ROOT)/ace/Map_Manager.i \ + $(ACE_ROOT)/ace/Map_Manager.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.h \ + $(ACE_ROOT)/ace/Synch_Options.h \ + $(ACE_ROOT)/ace/Synch_Options.i \ + $(ACE_ROOT)/ace/Task.h \ + $(ACE_ROOT)/ace/Thread_Manager.h \ + $(ACE_ROOT)/ace/Thread_Manager.i \ + $(ACE_ROOT)/ace/Task.i \ + $(ACE_ROOT)/ace/Task_T.h \ + $(ACE_ROOT)/ace/Message_Queue.h \ + $(ACE_ROOT)/ace/Message_Block.h \ + $(ACE_ROOT)/ace/Message_Block.i \ + $(ACE_ROOT)/ace/Message_Block_T.h \ + $(ACE_ROOT)/ace/Message_Block_T.i \ + $(ACE_ROOT)/ace/Message_Block_T.cpp \ + $(ACE_ROOT)/ace/IO_Cntl_Msg.h \ + $(ACE_ROOT)/ace/Message_Queue_T.h \ + $(ACE_ROOT)/ace/Message_Queue_T.i \ + $(ACE_ROOT)/ace/Message_Queue_T.cpp \ + $(ACE_ROOT)/ace/Strategies.h \ + $(ACE_ROOT)/ace/Strategies_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager.h \ + $(ACE_ROOT)/ace/Functor.h \ + $(ACE_ROOT)/ace/Functor.i \ + $(ACE_ROOT)/ace/Functor_T.h \ + $(ACE_ROOT)/ace/Functor_T.i \ + $(ACE_ROOT)/ace/Functor_T.cpp \ + $(ACE_ROOT)/ace/Hash_Map_Manager.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Strategies_T.i \ + $(ACE_ROOT)/ace/Strategies_T.cpp \ + $(ACE_ROOT)/ace/Service_Repository.h \ + $(ACE_ROOT)/ace/Service_Types.h \ + $(ACE_ROOT)/ace/Service_Types.i \ + $(ACE_ROOT)/ace/Service_Repository.i \ + $(ACE_ROOT)/ace/WFMO_Reactor.h \ + $(ACE_ROOT)/ace/WFMO_Reactor.i \ + $(ACE_ROOT)/ace/Strategies.i \ + $(ACE_ROOT)/ace/Message_Queue.i \ + $(ACE_ROOT)/ace/Task_T.i \ + $(ACE_ROOT)/ace/Task_T.cpp \ + $(ACE_ROOT)/ace/Module.h \ + $(ACE_ROOT)/ace/Module.i \ + $(ACE_ROOT)/ace/Module.cpp \ + $(ACE_ROOT)/ace/Stream_Modules.h \ + $(ACE_ROOT)/ace/Stream_Modules.i \ + $(ACE_ROOT)/ace/Stream_Modules.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.i \ + $(ACE_ROOT)/ace/Svc_Handler.cpp \ + $(ACE_ROOT)/ace/Dynamic.h \ + $(ACE_ROOT)/ace/Dynamic.i \ + $(ACE_ROOT)/ace/Connector.i \ + $(ACE_ROOT)/ace/Connector.cpp \ + $(ACE_ROOT)/ace/SOCK_Connector.h \ + $(ACE_ROOT)/ace/SOCK_Stream.h \ + $(ACE_ROOT)/ace/SOCK_Stream.i \ + $(ACE_ROOT)/ace/Time_Value.h \ + $(ACE_ROOT)/ace/SOCK_Connector.i \ + $(ACE_ROOT)/ace/Acceptor.h \ + $(ACE_ROOT)/ace/Acceptor.i \ + $(ACE_ROOT)/ace/Acceptor.cpp \ + $(ACE_ROOT)/ace/SOCK_Acceptor.h \ + $(ACE_ROOT)/ace/SOCK_Acceptor.i \ + $(TAO_ROOT)/tao/TAO.h \ + $(TAO_ROOT)/tao/corbafwd.h \ + $(ACE_ROOT)/ace/CDR_Stream.h \ + $(ACE_ROOT)/ace/CDR_Stream.i \ + $(TAO_ROOT)/tao/try_macros.h \ + $(TAO_ROOT)/tao/orbconf.h \ + $(ACE_ROOT)/ace/CORBA_macros.h \ + $(TAO_ROOT)/tao/corbafwd.i \ + $(TAO_ROOT)/tao/POAC.h \ + $(TAO_ROOT)/tao/PolicyC.h \ + $(TAO_ROOT)/tao/CurrentC.h \ + $(TAO_ROOT)/tao/Object.h \ + $(TAO_ROOT)/tao/Object.i \ + $(TAO_ROOT)/tao/CurrentC.i \ + $(TAO_ROOT)/tao/CDR.h \ + $(TAO_ROOT)/tao/Typecode.h \ + $(TAO_ROOT)/tao/Exception.h \ + $(TAO_ROOT)/tao/Exception.i \ + $(TAO_ROOT)/tao/Typecode.i \ + $(TAO_ROOT)/tao/CDR.i \ + $(TAO_ROOT)/tao/Sequence.h \ + $(TAO_ROOT)/tao/Managed_Types.h \ + $(TAO_ROOT)/tao/Managed_Types.i \ + $(TAO_ROOT)/tao/Sequence.i \ + $(TAO_ROOT)/tao/Sequence_T.h \ + $(TAO_ROOT)/tao/Sequence_T.i \ + $(TAO_ROOT)/tao/Sequence_T.cpp \ + $(TAO_ROOT)/tao/varout.h \ + $(TAO_ROOT)/tao/varout.i \ + $(TAO_ROOT)/tao/varout.cpp \ + $(TAO_ROOT)/tao/PolicyC.i \ + $(TAO_ROOT)/tao/Environment.h \ + $(TAO_ROOT)/tao/Environment.i \ + $(TAO_ROOT)/tao/POAC.i \ + $(TAO_ROOT)/tao/ORB.h \ + $(TAO_ROOT)/tao/IOR_LookupTable.h \ + $(TAO_ROOT)/tao/Services.h \ + $(TAO_ROOT)/tao/Services.i \ + $(TAO_ROOT)/tao/IORManipulation.h \ + $(TAO_ROOT)/tao/IORS.h \ + $(TAO_ROOT)/tao/IORC.h \ + $(TAO_ROOT)/tao/IORC.i \ + $(TAO_ROOT)/tao/Servant_Base.h \ + $(TAO_ROOT)/tao/Servant_Base.i \ + $(TAO_ROOT)/tao/IORS.i \ + $(TAO_ROOT)/tao/ORB.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/orbsvcs_export.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceC.h \ + $(TAO_ROOT)/tao/corba.h \ + $(TAO_ROOT)/tao/Any.h \ + $(TAO_ROOT)/tao/Any.i \ + $(TAO_ROOT)/tao/NVList.h \ + $(TAO_ROOT)/tao/NVList.i \ + $(TAO_ROOT)/tao/Principal.h \ + $(TAO_ROOT)/tao/Principal.i \ + $(TAO_ROOT)/tao/Request.h \ + $(TAO_ROOT)/tao/Context.h \ + $(TAO_ROOT)/tao/Context.i \ + $(TAO_ROOT)/tao/Request.i \ + $(TAO_ROOT)/tao/Server_Request.h \ + $(TAO_ROOT)/tao/Object_KeyC.h \ + $(TAO_ROOT)/tao/Object_KeyC.i \ + $(TAO_ROOT)/tao/GIOP.h \ + $(TAO_ROOT)/tao/IOPC.h \ + $(TAO_ROOT)/tao/IOPC.i \ + $(TAO_ROOT)/tao/GIOP.i \ + $(TAO_ROOT)/tao/Server_Request.i \ + $(TAO_ROOT)/tao/Marshal.h \ + $(TAO_ROOT)/tao/Marshal.i \ + $(TAO_ROOT)/tao/singletons.h \ + $(TAO_ROOT)/tao/POA.h \ + $(TAO_ROOT)/tao/Object_Adapter.h \ + $(TAO_ROOT)/tao/Key_Adapters.h \ + $(ACE_ROOT)/ace/Map.h \ + $(ACE_ROOT)/ace/Map.i \ + $(ACE_ROOT)/ace/Map_T.h \ + $(ACE_ROOT)/ace/Pair.h \ + $(ACE_ROOT)/ace/Pair.i \ + $(ACE_ROOT)/ace/Pair_T.h \ + $(ACE_ROOT)/ace/Pair_T.i \ + $(ACE_ROOT)/ace/Pair_T.cpp \ + $(ACE_ROOT)/ace/Active_Map_Manager.h \ + $(ACE_ROOT)/ace/Active_Map_Manager.i \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Map_T.i \ + $(ACE_ROOT)/ace/Map_T.cpp \ + $(TAO_ROOT)/tao/Key_Adapters.i \ + $(TAO_ROOT)/tao/Server_Strategy_Factory.h \ + $(TAO_ROOT)/tao/poa_macros.h \ + $(TAO_ROOT)/tao/POAS.h \ + $(TAO_ROOT)/tao/POA_CORBA.h \ + $(TAO_ROOT)/tao/DynAnyC.h \ + $(TAO_ROOT)/tao/DynAnyC.i \ + $(TAO_ROOT)/tao/DomainC.h \ + $(TAO_ROOT)/tao/DomainC.i \ + $(TAO_ROOT)/tao/POAS.i \ + $(TAO_ROOT)/tao/Active_Object_Map.h \ + $(TAO_ROOT)/tao/Active_Object_Map.i \ + $(TAO_ROOT)/tao/Object_Adapter.i \ + $(TAO_ROOT)/tao/POAManager.h \ + $(TAO_ROOT)/tao/POAManager.i \ + $(TAO_ROOT)/tao/POA.i \ + $(TAO_ROOT)/tao/Stub.h \ + $(TAO_ROOT)/tao/Pluggable.h \ + $(TAO_ROOT)/tao/Pluggable.i \ + $(TAO_ROOT)/tao/MProfile.h \ + $(TAO_ROOT)/tao/MProfile.i \ + $(TAO_ROOT)/tao/MessagingS.h \ + $(TAO_ROOT)/tao/TimeBaseS.h \ + $(TAO_ROOT)/tao/TimeBaseC.h \ + $(TAO_ROOT)/tao/TimeBaseC.i \ + $(TAO_ROOT)/tao/TimeBaseS_T.h \ + $(TAO_ROOT)/tao/TimeBaseS_T.i \ + $(TAO_ROOT)/tao/TimeBaseS_T.cpp \ + $(TAO_ROOT)/tao/TimeBaseS.i \ + $(TAO_ROOT)/tao/MessagingC.h \ + $(TAO_ROOT)/tao/PollableC.h \ + $(TAO_ROOT)/tao/MessagingC.i \ + $(TAO_ROOT)/tao/MessagingS.i \ + $(TAO_ROOT)/tao/Stub.i \ + $(TAO_ROOT)/tao/params.h \ + $(TAO_ROOT)/tao/params.i \ + $(TAO_ROOT)/tao/ORB_Core.h \ + $(TAO_ROOT)/tao/Policy_Manager.h \ + $(TAO_ROOT)/tao/Policy_Manager.i \ + $(TAO_ROOT)/tao/Resource_Factory.h \ + $(TAO_ROOT)/tao/Protocol_Factory.h \ + $(TAO_ROOT)/tao/ORB_Core.i \ + $(ACE_ROOT)/ace/Dynamic_Service.h \ + $(ACE_ROOT)/ace/Dynamic_Service.cpp \ + $(TAO_ROOT)/tao/Operation_Table.h \ + $(TAO_ROOT)/tao/Client_Strategy_Factory.h \ + $(TAO_ROOT)/tao/Invocation.h \ + $(TAO_ROOT)/tao/Reply_Dispatcher.h \ + $(TAO_ROOT)/tao/Reply_Dispatcher.i \ + $(TAO_ROOT)/tao/Invocation.i \ + $(TAO_ROOT)/tao/InconsistentTypeCodeC.h \ + $(TAO_ROOT)/tao/DynAny_i.h \ + $(TAO_ROOT)/tao/Union.h \ + $(TAO_ROOT)/tao/ValueBase.h \ + $(TAO_ROOT)/tao/ValueBase.i \ + $(TAO_ROOT)/tao/ValueFactory.h \ + $(TAO_ROOT)/tao/ValueFactory.i \ + $(TAO_ROOT)/tao/ObjectIDList.h \ + $(TAO_ROOT)/tao/ObjectIDList.i \ + $(TAO_ROOT)/tao/WrongTransactionC.h \ + $(TAO_ROOT)/tao/InterfaceC.h \ + $(TAO_ROOT)/tao/InterfaceC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Property/CosPropertyService_i.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosNamingC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosNamingC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AV_Core.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Transport.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Transport.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AVStreams_i.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Policy.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Policy.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Flows_T.h \ + $(ACE_ROOT)/ace/Stats.h \ + $(ACE_ROOT)/ace/Stats.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Protocol_Factory.h \ + $(ACE_ROOT)/ace/Get_Opt.h \ + $(ACE_ROOT)/ace/Get_Opt.i \ + $(ACE_ROOT)/ace/High_Res_Timer.h \ + $(ACE_ROOT)/ace/High_Res_Timer.i +.obj/control.o .obj/control.so .shobj/control.o .shobj/control.so: control.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AVStreams_i.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config-sunos5.7.h \ + $(ACE_ROOT)/ace/config-sunos5.6.h \ + $(ACE_ROOT)/ace/config-sunos5.5.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/SOCK_Dgram_Mcast.h \ + $(ACE_ROOT)/ace/SOCK_Dgram.h \ + $(ACE_ROOT)/ace/SOCK.h \ + $(ACE_ROOT)/ace/Addr.h \ + $(ACE_ROOT)/ace/Addr.i \ + $(ACE_ROOT)/ace/IPC_SAP.h \ + $(ACE_ROOT)/ace/IPC_SAP.i \ + $(ACE_ROOT)/ace/SOCK.i \ + $(ACE_ROOT)/ace/SOCK_Dgram.i \ + $(ACE_ROOT)/ace/INET_Addr.h \ + $(ACE_ROOT)/ace/INET_Addr.i \ + $(ACE_ROOT)/ace/SOCK_Dgram_Mcast.i \ + $(ACE_ROOT)/ace/ATM_Addr.h \ + $(ACE_ROOT)/ace/ATM_Addr.i \ + $(ACE_ROOT)/ace/Containers_T.h \ + $(ACE_ROOT)/ace/Containers.h \ + $(ACE_ROOT)/ace/Malloc_Base.h \ + $(ACE_ROOT)/ace/Containers.i \ + $(ACE_ROOT)/ace/Containers_T.i \ + $(ACE_ROOT)/ace/Containers_T.cpp \ + $(ACE_ROOT)/ace/Malloc.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.i \ + $(ACE_ROOT)/ace/Based_Pointer_T.cpp \ + $(ACE_ROOT)/ace/Based_Pointer_Repository.h \ + $(ACE_ROOT)/ace/Singleton.h \ + $(ACE_ROOT)/ace/Synch.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \ + $(ACE_ROOT)/ace/Synch.i \ + $(ACE_ROOT)/ace/Synch_T.h \ + $(ACE_ROOT)/ace/Event_Handler.h \ + $(ACE_ROOT)/ace/Event_Handler.i \ + $(ACE_ROOT)/ace/Synch_T.i \ + $(ACE_ROOT)/ace/Thread.h \ + $(ACE_ROOT)/ace/Thread.i \ + $(ACE_ROOT)/ace/Atomic_Op.i \ + $(ACE_ROOT)/ace/Synch_T.cpp \ + $(ACE_ROOT)/ace/Singleton.i \ + $(ACE_ROOT)/ace/Singleton.cpp \ + $(ACE_ROOT)/ace/Object_Manager.h \ + $(ACE_ROOT)/ace/Object_Manager.i \ + $(ACE_ROOT)/ace/Managed_Object.h \ + $(ACE_ROOT)/ace/Managed_Object.i \ + $(ACE_ROOT)/ace/Managed_Object.cpp \ + $(ACE_ROOT)/ace/Malloc.i \ + $(ACE_ROOT)/ace/Malloc_T.h \ + $(ACE_ROOT)/ace/Free_List.h \ + $(ACE_ROOT)/ace/Free_List.i \ + $(ACE_ROOT)/ace/Free_List.cpp \ + $(ACE_ROOT)/ace/Malloc_T.i \ + $(ACE_ROOT)/ace/Malloc_T.cpp \ + $(ACE_ROOT)/ace/Memory_Pool.h \ + $(ACE_ROOT)/ace/Signal.h \ + $(ACE_ROOT)/ace/Signal.i \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/Mem_Map.i \ + $(ACE_ROOT)/ace/Memory_Pool.i \ + $(ACE_ROOT)/ace/Process.h \ + $(ACE_ROOT)/ace/SString.h \ + $(ACE_ROOT)/ace/SString.i \ + $(ACE_ROOT)/ace/Process.i \ + $(ACE_ROOT)/ace/SOCK_CODgram.h \ + $(ACE_ROOT)/ace/SOCK_IO.h \ + $(ACE_ROOT)/ace/SOCK_IO.i \ + $(ACE_ROOT)/ace/SOCK_CODgram.i \ + $(ACE_ROOT)/ace/Connector.h \ + $(ACE_ROOT)/ace/Service_Config.h \ + $(ACE_ROOT)/ace/Service_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.i \ + $(ACE_ROOT)/ace/Service_Object.i \ + $(ACE_ROOT)/ace/Service_Config.i \ + $(ACE_ROOT)/ace/Reactor.h \ + $(ACE_ROOT)/ace/Handle_Set.h \ + $(ACE_ROOT)/ace/Handle_Set.i \ + $(ACE_ROOT)/ace/Timer_Queue.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.i \ + $(ACE_ROOT)/ace/Timer_Queue_T.cpp \ + $(ACE_ROOT)/ace/Reactor.i \ + $(ACE_ROOT)/ace/Reactor_Impl.h \ + $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \ + $(ACE_ROOT)/ace/Map_Manager.h \ + $(ACE_ROOT)/ace/Map_Manager.i \ + $(ACE_ROOT)/ace/Map_Manager.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.h \ + $(ACE_ROOT)/ace/Synch_Options.h \ + $(ACE_ROOT)/ace/Synch_Options.i \ + $(ACE_ROOT)/ace/Task.h \ + $(ACE_ROOT)/ace/Thread_Manager.h \ + $(ACE_ROOT)/ace/Thread_Manager.i \ + $(ACE_ROOT)/ace/Task.i \ + $(ACE_ROOT)/ace/Task_T.h \ + $(ACE_ROOT)/ace/Message_Queue.h \ + $(ACE_ROOT)/ace/Message_Block.h \ + $(ACE_ROOT)/ace/Message_Block.i \ + $(ACE_ROOT)/ace/Message_Block_T.h \ + $(ACE_ROOT)/ace/Message_Block_T.i \ + $(ACE_ROOT)/ace/Message_Block_T.cpp \ + $(ACE_ROOT)/ace/IO_Cntl_Msg.h \ + $(ACE_ROOT)/ace/Message_Queue_T.h \ + $(ACE_ROOT)/ace/Message_Queue_T.i \ + $(ACE_ROOT)/ace/Message_Queue_T.cpp \ + $(ACE_ROOT)/ace/Strategies.h \ + $(ACE_ROOT)/ace/Strategies_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager.h \ + $(ACE_ROOT)/ace/Functor.h \ + $(ACE_ROOT)/ace/Functor.i \ + $(ACE_ROOT)/ace/Functor_T.h \ + $(ACE_ROOT)/ace/Functor_T.i \ + $(ACE_ROOT)/ace/Functor_T.cpp \ + $(ACE_ROOT)/ace/Hash_Map_Manager.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Strategies_T.i \ + $(ACE_ROOT)/ace/Strategies_T.cpp \ + $(ACE_ROOT)/ace/Service_Repository.h \ + $(ACE_ROOT)/ace/Service_Types.h \ + $(ACE_ROOT)/ace/Service_Types.i \ + $(ACE_ROOT)/ace/Service_Repository.i \ + $(ACE_ROOT)/ace/WFMO_Reactor.h \ + $(ACE_ROOT)/ace/WFMO_Reactor.i \ + $(ACE_ROOT)/ace/Strategies.i \ + $(ACE_ROOT)/ace/Message_Queue.i \ + $(ACE_ROOT)/ace/Task_T.i \ + $(ACE_ROOT)/ace/Task_T.cpp \ + $(ACE_ROOT)/ace/Module.h \ + $(ACE_ROOT)/ace/Module.i \ + $(ACE_ROOT)/ace/Module.cpp \ + $(ACE_ROOT)/ace/Stream_Modules.h \ + $(ACE_ROOT)/ace/Stream_Modules.i \ + $(ACE_ROOT)/ace/Stream_Modules.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.i \ + $(ACE_ROOT)/ace/Svc_Handler.cpp \ + $(ACE_ROOT)/ace/Dynamic.h \ + $(ACE_ROOT)/ace/Dynamic.i \ + $(ACE_ROOT)/ace/Connector.i \ + $(ACE_ROOT)/ace/Connector.cpp \ + $(ACE_ROOT)/ace/SOCK_Connector.h \ + $(ACE_ROOT)/ace/SOCK_Stream.h \ + $(ACE_ROOT)/ace/SOCK_Stream.i \ + $(ACE_ROOT)/ace/Time_Value.h \ + $(ACE_ROOT)/ace/SOCK_Connector.i \ + $(ACE_ROOT)/ace/Acceptor.h \ + $(ACE_ROOT)/ace/Acceptor.i \ + $(ACE_ROOT)/ace/Acceptor.cpp \ + $(ACE_ROOT)/ace/SOCK_Acceptor.h \ + $(ACE_ROOT)/ace/SOCK_Acceptor.i \ + $(TAO_ROOT)/tao/TAO.h \ + $(TAO_ROOT)/tao/corbafwd.h \ + $(ACE_ROOT)/ace/CDR_Stream.h \ + $(ACE_ROOT)/ace/CDR_Stream.i \ + $(TAO_ROOT)/tao/try_macros.h \ + $(TAO_ROOT)/tao/orbconf.h \ + $(ACE_ROOT)/ace/CORBA_macros.h \ + $(TAO_ROOT)/tao/corbafwd.i \ + $(TAO_ROOT)/tao/POAC.h \ + $(TAO_ROOT)/tao/PolicyC.h \ + $(TAO_ROOT)/tao/CurrentC.h \ + $(TAO_ROOT)/tao/Object.h \ + $(TAO_ROOT)/tao/Object.i \ + $(TAO_ROOT)/tao/CurrentC.i \ + $(TAO_ROOT)/tao/CDR.h \ + $(TAO_ROOT)/tao/Typecode.h \ + $(TAO_ROOT)/tao/Exception.h \ + $(TAO_ROOT)/tao/Exception.i \ + $(TAO_ROOT)/tao/Typecode.i \ + $(TAO_ROOT)/tao/CDR.i \ + $(TAO_ROOT)/tao/Sequence.h \ + $(TAO_ROOT)/tao/Managed_Types.h \ + $(TAO_ROOT)/tao/Managed_Types.i \ + $(TAO_ROOT)/tao/Sequence.i \ + $(TAO_ROOT)/tao/Sequence_T.h \ + $(TAO_ROOT)/tao/Sequence_T.i \ + $(TAO_ROOT)/tao/Sequence_T.cpp \ + $(TAO_ROOT)/tao/varout.h \ + $(TAO_ROOT)/tao/varout.i \ + $(TAO_ROOT)/tao/varout.cpp \ + $(TAO_ROOT)/tao/PolicyC.i \ + $(TAO_ROOT)/tao/Environment.h \ + $(TAO_ROOT)/tao/Environment.i \ + $(TAO_ROOT)/tao/POAC.i \ + $(TAO_ROOT)/tao/ORB.h \ + $(TAO_ROOT)/tao/IOR_LookupTable.h \ + $(TAO_ROOT)/tao/Services.h \ + $(TAO_ROOT)/tao/Services.i \ + $(TAO_ROOT)/tao/IORManipulation.h \ + $(TAO_ROOT)/tao/IORS.h \ + $(TAO_ROOT)/tao/IORC.h \ + $(TAO_ROOT)/tao/IORC.i \ + $(TAO_ROOT)/tao/Servant_Base.h \ + $(TAO_ROOT)/tao/Servant_Base.i \ + $(TAO_ROOT)/tao/IORS.i \ + $(TAO_ROOT)/tao/ORB.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/orbsvcs_export.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceC.h \ + $(TAO_ROOT)/tao/corba.h \ + $(TAO_ROOT)/tao/Any.h \ + $(TAO_ROOT)/tao/Any.i \ + $(TAO_ROOT)/tao/NVList.h \ + $(TAO_ROOT)/tao/NVList.i \ + $(TAO_ROOT)/tao/Principal.h \ + $(TAO_ROOT)/tao/Principal.i \ + $(TAO_ROOT)/tao/Request.h \ + $(TAO_ROOT)/tao/Context.h \ + $(TAO_ROOT)/tao/Context.i \ + $(TAO_ROOT)/tao/Request.i \ + $(TAO_ROOT)/tao/Server_Request.h \ + $(TAO_ROOT)/tao/Object_KeyC.h \ + $(TAO_ROOT)/tao/Object_KeyC.i \ + $(TAO_ROOT)/tao/GIOP.h \ + $(TAO_ROOT)/tao/IOPC.h \ + $(TAO_ROOT)/tao/IOPC.i \ + $(TAO_ROOT)/tao/GIOP.i \ + $(TAO_ROOT)/tao/Server_Request.i \ + $(TAO_ROOT)/tao/Marshal.h \ + $(TAO_ROOT)/tao/Marshal.i \ + $(TAO_ROOT)/tao/singletons.h \ + $(TAO_ROOT)/tao/POA.h \ + $(TAO_ROOT)/tao/Object_Adapter.h \ + $(TAO_ROOT)/tao/Key_Adapters.h \ + $(ACE_ROOT)/ace/Map.h \ + $(ACE_ROOT)/ace/Map.i \ + $(ACE_ROOT)/ace/Map_T.h \ + $(ACE_ROOT)/ace/Pair.h \ + $(ACE_ROOT)/ace/Pair.i \ + $(ACE_ROOT)/ace/Pair_T.h \ + $(ACE_ROOT)/ace/Pair_T.i \ + $(ACE_ROOT)/ace/Pair_T.cpp \ + $(ACE_ROOT)/ace/Active_Map_Manager.h \ + $(ACE_ROOT)/ace/Active_Map_Manager.i \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Active_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Map_T.i \ + $(ACE_ROOT)/ace/Map_T.cpp \ + $(TAO_ROOT)/tao/Key_Adapters.i \ + $(TAO_ROOT)/tao/Server_Strategy_Factory.h \ + $(TAO_ROOT)/tao/poa_macros.h \ + $(TAO_ROOT)/tao/POAS.h \ + $(TAO_ROOT)/tao/POA_CORBA.h \ + $(TAO_ROOT)/tao/DynAnyC.h \ + $(TAO_ROOT)/tao/DynAnyC.i \ + $(TAO_ROOT)/tao/DomainC.h \ + $(TAO_ROOT)/tao/DomainC.i \ + $(TAO_ROOT)/tao/POAS.i \ + $(TAO_ROOT)/tao/Active_Object_Map.h \ + $(TAO_ROOT)/tao/Active_Object_Map.i \ + $(TAO_ROOT)/tao/Object_Adapter.i \ + $(TAO_ROOT)/tao/POAManager.h \ + $(TAO_ROOT)/tao/POAManager.i \ + $(TAO_ROOT)/tao/POA.i \ + $(TAO_ROOT)/tao/Stub.h \ + $(TAO_ROOT)/tao/Pluggable.h \ + $(TAO_ROOT)/tao/Pluggable.i \ + $(TAO_ROOT)/tao/MProfile.h \ + $(TAO_ROOT)/tao/MProfile.i \ + $(TAO_ROOT)/tao/MessagingS.h \ + $(TAO_ROOT)/tao/TimeBaseS.h \ + $(TAO_ROOT)/tao/TimeBaseC.h \ + $(TAO_ROOT)/tao/TimeBaseC.i \ + $(TAO_ROOT)/tao/TimeBaseS_T.h \ + $(TAO_ROOT)/tao/TimeBaseS_T.i \ + $(TAO_ROOT)/tao/TimeBaseS_T.cpp \ + $(TAO_ROOT)/tao/TimeBaseS.i \ + $(TAO_ROOT)/tao/MessagingC.h \ + $(TAO_ROOT)/tao/PollableC.h \ + $(TAO_ROOT)/tao/MessagingC.i \ + $(TAO_ROOT)/tao/MessagingS.i \ + $(TAO_ROOT)/tao/Stub.i \ + $(TAO_ROOT)/tao/params.h \ + $(TAO_ROOT)/tao/params.i \ + $(TAO_ROOT)/tao/ORB_Core.h \ + $(TAO_ROOT)/tao/Policy_Manager.h \ + $(TAO_ROOT)/tao/Policy_Manager.i \ + $(TAO_ROOT)/tao/Resource_Factory.h \ + $(TAO_ROOT)/tao/Protocol_Factory.h \ + $(TAO_ROOT)/tao/ORB_Core.i \ + $(ACE_ROOT)/ace/Dynamic_Service.h \ + $(ACE_ROOT)/ace/Dynamic_Service.cpp \ + $(TAO_ROOT)/tao/Operation_Table.h \ + $(TAO_ROOT)/tao/Client_Strategy_Factory.h \ + $(TAO_ROOT)/tao/Invocation.h \ + $(TAO_ROOT)/tao/Reply_Dispatcher.h \ + $(TAO_ROOT)/tao/Reply_Dispatcher.i \ + $(TAO_ROOT)/tao/Invocation.i \ + $(TAO_ROOT)/tao/InconsistentTypeCodeC.h \ + $(TAO_ROOT)/tao/DynAny_i.h \ + $(TAO_ROOT)/tao/Union.h \ + $(TAO_ROOT)/tao/ValueBase.h \ + $(TAO_ROOT)/tao/ValueBase.i \ + $(TAO_ROOT)/tao/ValueFactory.h \ + $(TAO_ROOT)/tao/ValueFactory.i \ + $(TAO_ROOT)/tao/ObjectIDList.h \ + $(TAO_ROOT)/tao/ObjectIDList.i \ + $(TAO_ROOT)/tao/WrongTransactionC.h \ + $(TAO_ROOT)/tao/InterfaceC.h \ + $(TAO_ROOT)/tao/InterfaceC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosPropertyServiceS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AVStreamsS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Property/CosPropertyService_i.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosNamingC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/CosNamingC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Endpoint_Strategy_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlC.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlC.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS_T.cpp \ + $(TAO_ROOT)/orbsvcs/orbsvcs/Null_MediaCtrlS.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/FlowSpec_Entry.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AV_Core.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Transport.h \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/Transport.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/FlowSpec_Entry.i \ + $(TAO_ROOT)/orbsvcs/orbsvcs/AV/AVStreams_i.i \ + $(ACE_ROOT)/ace/Get_Opt.h \ + $(ACE_ROOT)/ace/Get_Opt.i + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/README b/TAO/orbsvcs/tests/AVStreams/Latency/README new file mode 100644 index 00000000000..6a96f8cff60 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/README @@ -0,0 +1,9 @@ +# $Id$ + + A simple latency test for the AVStreams pluggable protocol +framework. Run as follows: + +$ ping -o ping.ior +$ pong -o pong.ior +$ control -f file://ping.ior -g file://pong.ior + diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/control.cpp b/TAO/orbsvcs/tests/AVStreams/Latency/control.cpp new file mode 100644 index 00000000000..0cec49350d2 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/control.cpp @@ -0,0 +1,190 @@ +// $Id$ + +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/FlowSpec_Entry.h" +#include "tao/TAO.h" +#include "ace/Get_Opt.h" +#include "ace/INET_Addr.h" + +ACE_RCSID(Latency, ping, "$Id$") + +const char *ping_ior = "file://ping.ior"; +const char *pong_ior = "file://pong.ior"; +const char *ping_address = "224.9.9.2:12345"; +const char *pong_address = "224.9.9.2:23456"; +const char *protocol = "UDP"; + +int milliseconds = 30000; + +int +parse_args (int argc, char *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, "f:g:s:r:t:p:"); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'f': + ping_ior = get_opts.optarg; + break; + + case 'g': + pong_ior = get_opts.optarg; + break; + + case 'r': + ping_address = get_opts.optarg; + break; + + case 's': + pong_address = get_opts.optarg; + break; + + case 't': + milliseconds = ACE_OS::atoi (get_opts.optarg); + break; + + case 'p': + protocol = get_opts.optarg; + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-f <ping_ior> " + "-g <ping_ior> " + "-s <ping_address> " + "-r <pong_address> " + "-t <milliseconds> " + "-p protocols " + "\n", + argv [0]), + -1); + } + + + // Indicates sucessful parsing of the command line + return 0; +} + +int main (int argc, char *argv[]) +{ + ACE_TRY_NEW_ENV + { + TAO_AV_Core *av_core = TAO_AV_CORE::instance (); + av_core->init (argc, argv, ACE_TRY_ENV); + ACE_TRY_CHECK; + + parse_args (argc, argv); + + TAO_ORB_Manager* orb_manager = + av_core->orb_manager (); + + CORBA::ORB_var orb = orb_manager->orb (); + + CORBA::Object_var poa_object = + orb->resolve_initial_references("RootPOA", ACE_TRY_ENV); + ACE_TRY_CHECK; + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (poa_object.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + PortableServer::POAManager_var poa_manager = + root_poa->the_POAManager (ACE_TRY_ENV); + ACE_TRY_CHECK; + + poa_manager->activate (ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Connect the two streams and run them... + AVStreams::flowSpec flow_spec (2); + flow_spec.length (2); + + ACE_INET_Addr ping_addr; + ping_addr.set (ping_address); + TAO_Forward_FlowSpec_Entry ping ("Ping", + "IN", + "UNS:ping", + "", + protocol, + &ping_addr); + flow_spec[0] = CORBA::string_dup (ping.entry_to_string ()); + + ACE_INET_Addr pong_addr; + pong_addr.set (pong_address); + TAO_Forward_FlowSpec_Entry pong ("Pong", + "OUT", + "UNS:pong", + "", + protocol, + &pong_addr); + flow_spec[1] = CORBA::string_dup (pong.entry_to_string ()); + + TAO_StreamCtrl stream_control_impl; + + AVStreams::StreamCtrl_var stream_control = + stream_control_impl._this (ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::Object_var obj = + orb->string_to_object (ping_ior, ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::MMDevice_var ping_sender = + AVStreams::MMDevice::_narrow (obj.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + obj = + orb->string_to_object (pong_ior, ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::MMDevice_var pong_sender = + AVStreams::MMDevice::_narrow (obj.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + AVStreams::streamQoS_var the_qos = + new AVStreams::streamQoS; + + stream_control->bind_devs (pong_sender.in (), + ping_sender.in (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + flow_spec.length (0); + stream_control->start (flow_spec, ACE_TRY_ENV); + ACE_TRY_CHECK; + + ACE_Time_Value tv (0, milliseconds * 1000); + if (orb->run (tv) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "orb->run"), -1); + ACE_DEBUG ((LM_DEBUG, "event loop finished\n")); + + flow_spec.length (0); + stream_control->stop (flow_spec, ACE_TRY_ENV); + ACE_TRY_CHECK; + + // root_poa->destroy (1, 1, ACE_TRY_ENV); + // ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Catched exception:"); + return 1; + } + ACE_ENDTRY; + + return 0; +} + +// **************************************************************** + +// @@ TODO +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/ping.cpp b/TAO/orbsvcs/tests/AVStreams/Latency/ping.cpp new file mode 100644 index 00000000000..80799fd09d2 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/ping.cpp @@ -0,0 +1,351 @@ +// $Id$ + +#include "ping.h" +#include "orbsvcs/AV/Protocol_Factory.h" +#include "tao/corba.h" +#include "tao/TAO.h" +#include "ace/Get_Opt.h" +#include "ace/High_Res_Timer.h" +#include "ace/Stats.h" + +ACE_RCSID(Latency, ping, "$Id$") + +const char *ior_output_file = "ping.ior"; +const char *protocol = "RTP/UDP"; +int milliseconds = 100; +int respond = 1; +AVStreams::protocolSpec ping_protocols; +AVStreams::protocolSpec pong_protocols; + +Pong_Send_Callback pong_callback; + +ACE_hrtime_t recv_base = 0; +ACE_Throughput_Stats recv_latency; + +CORBA::ORB_ptr the_orb = 0; + +int +parse_args (int argc, char *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, "xo:s:r:t:"); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'o': + ior_output_file = get_opts.optarg; + break; + + case 'r': + { + CORBA::ULong l = ping_protocols.length (); + ping_protocols.length (l + 1); + ping_protocols[l] = CORBA::string_dup (get_opts.optarg); + } + break; + + case 's': + { + CORBA::ULong l = pong_protocols.length (); + pong_protocols.length (l + 1); + pong_protocols[l] = CORBA::string_dup (get_opts.optarg); + } + break; + + case 't': + milliseconds = ACE_OS::atoi (get_opts.optarg); + break; + + case 'x': + respond = 0; + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-o <iorfile> " + "-r <protocol=addr> " + "-s <protocol=addr> " + "-t <milliseconds> " + "\n", + argv [0]), + -1); + } + + + // If no protocols are specified use the default... + if (ping_protocols.length () == 0) + { + ping_protocols.length (1); + ping_protocols[0] = CORBA::string_dup ("UDP=224.9.9.2:12345"); + } + + if (pong_protocols.length () == 0) + { + pong_protocols.length (1); + pong_protocols[0] = CORBA::string_dup ("UDP=224.9.9.2:23456"); + } + + // Indicates sucessful parsing of the command line + return 0; +} + +int main (int argc, char *argv[]) +{ + ACE_TRY_NEW_ENV + { + TAO_AV_Core *av_core = TAO_AV_CORE::instance (); + av_core->init (argc, argv, ACE_TRY_ENV); + ACE_TRY_CHECK; + + parse_args (argc, argv); + + TAO_ORB_Manager* orb_manager = + av_core->orb_manager (); + + CORBA::ORB_var orb = orb_manager->orb (); + the_orb = orb.in (); + // No copying, because the global variable is not used after the + // event loop finishes... + + CORBA::Object_var poa_object = + orb->resolve_initial_references("RootPOA", ACE_TRY_ENV); + ACE_TRY_CHECK; + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (poa_object.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + PortableServer::POAManager_var poa_manager = + root_poa->the_POAManager (ACE_TRY_ENV); + ACE_TRY_CHECK; + + poa_manager->activate (ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Register the video mmdevice object with the ORB + + Reactive_Strategy *reactive_strategy; + ACE_NEW_RETURN (reactive_strategy, + Reactive_Strategy (orb_manager), + 1); + TAO_MMDevice *mmdevice_impl; + ACE_NEW_RETURN (mmdevice_impl, + TAO_MMDevice (reactive_strategy), + 1); + + AVStreams::MMDevice_var mmdevice = + mmdevice_impl->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::String_var ior = + orb->object_to_string (mmdevice.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "Activated as <%s>\n", ior.in ())); + + // If the ior_output_file exists, output the ior to it + if (ior_output_file != 0) + { + FILE *output_file= ACE_OS::fopen (ior_output_file, "w"); + if (output_file == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot open output file for writing IOR: %s", + ior_output_file), + 1); + ACE_OS::fprintf (output_file, "%s", ior.in ()); + ACE_OS::fclose (output_file); + } + + Ping_Recv_FDev* ping_fdev_impl; + ACE_NEW_RETURN (ping_fdev_impl, + Ping_Recv_FDev ("Ping"), + 1); + Pong_Send_FDev* pong_fdev_impl; + ACE_NEW_RETURN (pong_fdev_impl, + Pong_Send_FDev ("Pong"), + 1); + + AVStreams::FDev_var ping_fdev = + ping_fdev_impl->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FDev_var pong_fdev = + pong_fdev_impl->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + + mmdevice->add_fdev (ping_fdev.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + if (respond == 1) + { + mmdevice->add_fdev (pong_fdev.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + } + + ACE_Time_Value tv (120, 0); + if (orb->run (tv) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "orb->run"), -1); + ACE_DEBUG ((LM_DEBUG, "event loop finished\n")); + + ACE_DEBUG ((LM_DEBUG, "Calibrating scale factory . . . ")); + ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor (); + ACE_DEBUG ((LM_DEBUG, "done\n")); + + recv_latency.dump_results ("Receive", gsf); + + // root_poa->destroy (1, 1, ACE_TRY_ENV); + // ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Catched exception:"); + return 1; + } + ACE_ENDTRY; + + return 0; +} + +// **************************************************************** + +Ping_Recv::Ping_Recv (void) + : TAO_FlowConsumer ("Ping", + ping_protocols, + "UNS:ping") +{ +} + +int +Ping_Recv::get_callback (const char *, + TAO_AV_Callback *&callback) +{ + // ACE_DEBUG ((LM_DEBUG,"Ping_Recv::get_callback\n")); + callback = &this->callback_; + return 0; +} + +int +Ping_Recv_Callback::handle_stop (void) +{ + ACE_DEBUG ((LM_DEBUG,"Ping_Recv_Callback::stop")); + the_orb->shutdown (); + + return 0; +} + +int +Ping_Recv_Callback::receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &) +{ + // ACE_DEBUG ((LM_DEBUG,"Ping_Recv_Callback::receive_frame\n")); + + for (const ACE_Message_Block *i = frame; + frame != 0; + frame = frame->cont ()) + { + ACE_hrtime_t stamp; + + if (frame->length () < sizeof(stamp)) + return 0; + + ACE_OS::memcpy (&stamp, frame->rd_ptr (), sizeof(stamp)); + + ACE_hrtime_t now = ACE_OS::gethrtime (); + if (recv_base == 0) + { + recv_base = now; + } + else + { + recv_latency.sample (now - recv_base, + now - stamp); + } + + if (respond == 1) + pong_callback.send_response (stamp); + } + return 0; +} + +int +Ping_Recv_Callback::handle_destroy (void) +{ + // ACE_DEBUG ((LM_DEBUG,"Ping_Recv_Callback::destroy\n")); + return 0; +} + +// **************************************************************** + +Pong_Send::Pong_Send (void) + : TAO_FlowProducer ("Pong", + pong_protocols, + "UNS:pong") +{ +} + +int +Pong_Send::get_callback (const char *, + TAO_AV_Callback *&callback) +{ + // ACE_DEBUG ((LM_DEBUG,"Pong_Send::get_callback\n")); + callback = &pong_callback; + return 0; +} + +void +Pong_Send_Callback::get_timeout (ACE_Time_Value *&tv, + void *&) +{ + // @@ ACE_NEW (tv, ACE_Time_Value (0, milliseconds * 1000)); + tv = 0; +} + +int +Pong_Send_Callback::handle_timeout (void *arg) +{ + // ACE_DEBUG ((LM_DEBUG, "pong timeout (ignored)\n")); + return 0; +} + +int +Pong_Send_Callback::handle_end_stream (void) +{ + return 0; +} + +int +Pong_Send_Callback::send_response (ACE_hrtime_t stamp) +{ + // ACE_DEBUG ((LM_DEBUG, "pong send response)\n")); + + ACE_hrtime_t buf[2]; + + ACE_Message_Block mb (ACE_reinterpret_cast (char*,buf), + sizeof(buf)); + + buf[0] = stamp; + buf[1] = ACE_OS::gethrtime (); + mb.wr_ptr (sizeof(buf)); + + int result = this->protocol_object_->send_frame (&mb); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "FTP_Client_Flow_Handler::send - %p\n", + ""), + -1); + + return 0; +} + +// **************************************************************** + +// @@ TODO +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/ping.h b/TAO/orbsvcs/tests/AVStreams/Latency/ping.h new file mode 100644 index 00000000000..c9063f976e3 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/ping.h @@ -0,0 +1,73 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO/orbsvcs/tests/AVStreams/Latency +// +// = FILENAME +// ping.h +// +// = AUTHOR +// Carlos O'Ryan +// +// ============================================================================ + +#ifndef TAO_PING_H +#define TAO_PING_H + +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Policy.h" +#include "orbsvcs/AV/Flows_T.h" + +class Ping_Recv_Callback : public TAO_AV_Callback +{ +public: + virtual int handle_stop (void); + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0, + const ACE_Addr &peer_address = ACE_Addr::sap_any); + virtual int handle_destroy (void); +}; + +class Ping_Recv : public TAO_FlowConsumer +{ +public: + Ping_Recv (void); + + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + +private: + Ping_Recv_Callback callback_; + // The callback object... +}; + +class Pong_Send_Callback : public TAO_AV_Callback +{ +public: + + int send_response (ACE_hrtime_t stamp); + // Ad-hoc method to send a response outside the context of a + // handle_timeout. + + virtual int handle_timeout (void *arg); + virtual int handle_end_stream (void); + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); +}; + +class Pong_Send : public TAO_FlowProducer +{ +public: + Pong_Send (void); + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); +}; + +typedef TAO_AV_Endpoint_Reactive_Strategy_B <TAO_StreamEndPoint_B,TAO_VDev,AV_Null_MediaCtrl> Reactive_Strategy; + +typedef TAO_FDev<TAO_FlowProducer,Ping_Recv> Ping_Recv_FDev; +typedef TAO_FDev<Pong_Send,TAO_FlowConsumer> Pong_Send_FDev; + +#endif /* TAO_PING_H */ diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/pong.cpp b/TAO/orbsvcs/tests/AVStreams/Latency/pong.cpp new file mode 100644 index 00000000000..975963a96b7 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/pong.cpp @@ -0,0 +1,361 @@ +// $Id$ + +#include "pong.h" +#include "orbsvcs/AV/Protocol_Factory.h" +#include "tao/corba.h" +#include "tao/TAO.h" +#include "ace/Get_Opt.h" +#include "ace/High_Res_Timer.h" +#include "ace/Stats.h" + +ACE_RCSID(Latency, ping, "$Id$") + +const char *ior_output_file = "pong.ior"; +const char *protocol = "RTP/UDP"; +int milliseconds = 100; +int message_size = 64; +int respond = 1; +AVStreams::protocolSpec pong_protocols; +AVStreams::protocolSpec ping_protocols; + +ACE_hrtime_t recv_throughput_base = 0; +ACE_Throughput_Stats recv_latency; + +ACE_hrtime_t send_throughput_base = 0; +ACE_Throughput_Stats send_latency; + +CORBA::ORB_ptr the_orb = 0; + +int +parse_args (int argc, char *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, "xo:s:r:t:b:"); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'o': + ior_output_file = get_opts.optarg; + break; + + case 'r': + { + CORBA::ULong l = ping_protocols.length (); + ping_protocols.length (l + 1); + ping_protocols[l] = CORBA::string_dup (get_opts.optarg); + } + break; + + case 's': + { + CORBA::ULong l = pong_protocols.length (); + pong_protocols.length (l + 1); + pong_protocols[l] = CORBA::string_dup (get_opts.optarg); + } + break; + + case 't': + milliseconds = ACE_OS::atoi (get_opts.optarg); + break; + + case 'b': + message_size = ACE_OS::atoi (get_opts.optarg); + if (message_size < sizeof(ACE_hrtime_t)) + { + ACE_DEBUG ((LM_DEBUG, "Invalid message size\n")); + message_size = 64; + } + break; + + case 'x': + respond = 0; + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-o <iorfile> " + "-r <protocol=addr> " + "-s <protocol=addr> " + "-t <milliseconds> " + "\n", + argv [0]), + -1); + } + + + // If no protocols are specified use the default... + if (pong_protocols.length () == 0) + { + pong_protocols.length (1); + pong_protocols[0] = CORBA::string_dup ("UDP=224.9.9.2:23456"); + } + + if (ping_protocols.length () == 0) + { + ping_protocols.length (1); + ping_protocols[0] = CORBA::string_dup ("UDP=224.9.9.2:12345"); + } + + // Indicates sucessful parsing of the command line + return 0; +} + +int main (int argc, char *argv[]) +{ + ACE_TRY_NEW_ENV + { + TAO_AV_Core *av_core = TAO_AV_CORE::instance (); + av_core->init (argc, argv, ACE_TRY_ENV); + ACE_TRY_CHECK; + + parse_args (argc, argv); + + TAO_ORB_Manager* orb_manager = + av_core->orb_manager (); + + CORBA::ORB_var orb = orb_manager->orb (); + the_orb = orb.in (); + // No copying, because the global variable is not used after the + // event loop finishes... + + CORBA::Object_var poa_object = + orb->resolve_initial_references("RootPOA", ACE_TRY_ENV); + ACE_TRY_CHECK; + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (poa_object.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + PortableServer::POAManager_var poa_manager = + root_poa->the_POAManager (ACE_TRY_ENV); + ACE_TRY_CHECK; + + poa_manager->activate (ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Register the video mmdevice object with the ORB + + Reactive_Strategy *reactive_strategy; + ACE_NEW_RETURN (reactive_strategy, + Reactive_Strategy (orb_manager), + 1); + TAO_MMDevice *mmdevice_impl; + ACE_NEW_RETURN (mmdevice_impl, + TAO_MMDevice (reactive_strategy), + 1); + + AVStreams::MMDevice_var mmdevice = + mmdevice_impl->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::String_var ior = + orb->object_to_string (mmdevice.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "Activated as <%s>\n", ior.in ())); + + // If the ior_output_file exists, output the ior to it + if (ior_output_file != 0) + { + FILE *output_file= ACE_OS::fopen (ior_output_file, "w"); + if (output_file == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot open output file for writing IOR: %s", + ior_output_file), + 1); + ACE_OS::fprintf (output_file, "%s", ior.in ()); + ACE_OS::fclose (output_file); + } + + Pong_Recv_FDev* pong_fdev_impl; + ACE_NEW_RETURN (pong_fdev_impl, + Pong_Recv_FDev ("Pong"), + 1); + Ping_Send_FDev* ping_fdev_impl; + ACE_NEW_RETURN (ping_fdev_impl, + Ping_Send_FDev ("Ping"), + 1); + + AVStreams::FDev_var ping_fdev = + ping_fdev_impl->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FDev_var pong_fdev = + pong_fdev_impl->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + + mmdevice->add_fdev (ping_fdev.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + if (respond == 1) + { + mmdevice->add_fdev (pong_fdev.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + } + + ACE_Time_Value tv (120, 0); + if (orb->run (tv) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "orb->run"), -1); + ACE_DEBUG ((LM_DEBUG, "event loop finished\n")); + + ACE_DEBUG ((LM_DEBUG, "Calibrating scale factory . . . ")); + ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor (); + ACE_DEBUG ((LM_DEBUG, "done\n")); + + recv_latency.dump_results ("Receive", gsf); + + send_latency.dump_results ("Send", gsf); + + // root_poa->destroy (1, 1, ACE_TRY_ENV); + // ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Catched exception:"); + return 1; + } + ACE_ENDTRY; + + return 0; +} + +// **************************************************************** + +Pong_Recv::Pong_Recv (void) + : TAO_FlowConsumer ("Pong", + pong_protocols, + "UNS:pong") +{ +} + +int +Pong_Recv::get_callback (const char *, + TAO_AV_Callback *&callback) +{ + // ACE_DEBUG ((LM_DEBUG,"Pong_Recv::get_callback\n")); + callback = &this->callback_; + return 0; +} + +int +Pong_Recv_Callback::handle_stop (void) +{ + // ACE_DEBUG ((LM_DEBUG,"Pong_Recv_Callback::stop")); + the_orb->shutdown (); + return 0; +} + +int +Pong_Recv_Callback::receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &) +{ + // ACE_DEBUG ((LM_DEBUG,"Pong_Recv_Callback::receive_frame\n")); + + ACE_hrtime_t now = ACE_OS::gethrtime (); + for (const ACE_Message_Block *i = frame; + frame != 0; + frame = frame->cont ()) + { + ACE_hrtime_t buf[2]; + + if (frame->length () < sizeof(buf)) + { + ACE_DEBUG ((LM_DEBUG, "Unexpected message size\n")); + return 0; + } + + ACE_OS::memcpy (buf, frame->rd_ptr (), sizeof(buf)); + + if (recv_throughput_base == 0) + { + recv_throughput_base = now; + } + recv_latency.sample (now - recv_throughput_base, + now - buf[0]); + } + return 0; +} + +int +Pong_Recv_Callback::handle_destroy (void) +{ + ACE_DEBUG ((LM_DEBUG,"Pong_Recv_Callback::destroy\n")); + return 0; +} + +// **************************************************************** + +Ping_Send::Ping_Send (void) + : TAO_FlowProducer ("Ping", + ping_protocols, + "UNS:ping") +{ +} + +int +Ping_Send::get_callback (const char *, + TAO_AV_Callback *&callback) +{ + // ACE_DEBUG ((LM_DEBUG,"Ping_Send::get_callback\n")); + callback = &this->callback_; + return 0; +} + +Ping_Send_Callback::Ping_Send_Callback (void) +{ + this->timeout_ = ACE_Time_Value (0, milliseconds * 1000); + + this->frame_.size (message_size); + this->frame_.wr_ptr (message_size); +} + +void +Ping_Send_Callback::get_timeout (ACE_Time_Value *&tv, + void *&) +{ + tv = &this->timeout_; +} + +int +Ping_Send_Callback::handle_timeout (void *arg) +{ + // ACE_DEBUG ((LM_DEBUG, "ping timeout\n")); + + ACE_hrtime_t stamp = ACE_OS::gethrtime (); + ACE_OS::memcpy (this->frame_.rd_ptr (), &stamp, sizeof(stamp)); + + int result = this->protocol_object_->send_frame (&this->frame_); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "FTP_Client_Flow_Handler::send - %p\n", + ""), + -1); + + if (send_throughput_base == 0) + { + send_throughput_base = stamp; + } + ACE_hrtime_t now = ACE_OS::gethrtime (); + send_latency.sample (now - send_throughput_base, + now - stamp); + + return 0; +} + +int +Ping_Send_Callback::handle_end_stream (void) +{ + return 0; +} + +// **************************************************************** + +// @@ TODO +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/pong.h b/TAO/orbsvcs/tests/AVStreams/Latency/pong.h new file mode 100644 index 00000000000..af52b9a70f7 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/pong.h @@ -0,0 +1,81 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO/orbsvcs/tests/AVStreams/Latency +// +// = FILENAME +// ping.h +// +// = AUTHOR +// Carlos O'Ryan +// +// ============================================================================ + +#ifndef TAO_PONG_H +#define TAO_PONG_H + +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Policy.h" +#include "orbsvcs/AV/Flows_T.h" + +class Pong_Recv_Callback : public TAO_AV_Callback +{ +public: + virtual int handle_stop (void); + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0, + const ACE_Addr &peer_address = ACE_Addr::sap_any); + virtual int handle_destroy (void); +}; + +class Pong_Recv : public TAO_FlowConsumer +{ +public: + Pong_Recv (void); + + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + +private: + Pong_Recv_Callback callback_; + // The callback object... +}; + +class Ping_Send_Callback : public TAO_AV_Callback +{ +public: + Ping_Send_Callback (void); + + virtual int handle_timeout (void *arg); + virtual int handle_end_stream (void); + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); + +private: + ACE_Time_Value timeout_; + // the timeout value + + ACE_Message_Block frame_; + // Pre-allocate the message block to send... +}; + +class Ping_Send : public TAO_FlowProducer +{ +public: + Ping_Send (void); + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + +private: + Ping_Send_Callback callback_; + // The callback object... +}; + +typedef TAO_AV_Endpoint_Reactive_Strategy_A <TAO_StreamEndPoint_A,TAO_VDev,AV_Null_MediaCtrl> Reactive_Strategy; + +typedef TAO_FDev<TAO_FlowProducer,Pong_Recv> Pong_Recv_FDev; +typedef TAO_FDev<Ping_Send,TAO_FlowConsumer> Ping_Send_FDev; + +#endif /* TAO_PONG_H */ diff --git a/TAO/orbsvcs/tests/AVStreams/Latency/svc.conf b/TAO/orbsvcs/tests/AVStreams/Latency/svc.conf new file mode 100644 index 00000000000..25ae44055a1 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Latency/svc.conf @@ -0,0 +1,5 @@ +# $Id$ +# +static Resource_Factory "-ORBresources global -ORBReactorType select_st -ORBInputCDRAllocator null" +static Server_Strategy_Factory "-ORBPOALock null -ORBAllowReactivationOfSystemids 0" +static Client_Strategy_Factory "-ORBProfileLock null -ORBClientConnectionHandler ST -ORBConnectorLock null" diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast/Makefile b/TAO/orbsvcs/tests/AVStreams/Multicast/Makefile new file mode 100644 index 00000000000..ad90e057c35 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast/Makefile @@ -0,0 +1,57 @@ +#---------------------------------------------------------------------------- +# $Id$ +# +# Top-level Makefile for Multipoint Binding testing of AVStreams of TAO. +# +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +LIBS += -lorbsvcs -lTAO + +SERVER_OBJS = server.o +CLIENT_OBJS = ftp.o + +VLDLIBS = $(LDLIBS:%=%$(VAR)) + +ifndef TAO_ROOT +TAO_ROOT = $(ACE_ROOT)/TAO +endif + +FILES = ftp server +DEFS = $(addsuffix .h,$(FILES)) +LSRC = $(addsuffix .cpp,$(FILES)) + +BIN2 = server ftp + +#### If the TAO orbsvcs library wasn't built with sufficient components, +#### don't try to build here. +TAO_ORBSVCS := $(shell $(ACE_ROOT)/bin/ace_components --orbsvcs) +ifeq (AV,$(findstring AV,$(TAO_ORBSVCS))) + BIN = $(BIN2) +endif # AV + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(TAO_ROOT)/rules.tao.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +DCFLAGS = -g +LDFLAGS += -L$(TAO_ROOT)/orbsvcs/orbsvcs -L$(TAO_ROOT)/tao +CPPFLAGS += -I$(TAO_ROOT)/orbsvcs -I$(TAO_ROOT) $(TSS_ORB_FLAG) + +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast/ftp.cpp b/TAO/orbsvcs/tests/AVStreams/Multicast/ftp.cpp new file mode 100644 index 00000000000..7c171233d3f --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast/ftp.cpp @@ -0,0 +1,472 @@ +// $Id$ + +#include "ftp.h" + +FTP_Client_Callback::FTP_Client_Callback (void) + // :handler_ (handler), + :count_ (0) +{ +} + +// FTP_Client_Callback::FTP_Client_Callback (FTP_Client_Flow_Handler *handler) +// :handler_ (handler) +// { +// } + +// int +// FTP_Client_Callback::handle_start (void) +// { +// return this->handler_->start (); +// } + +// int +// FTP_Client_Callback::handle_stop (void) +// { +// return this->handler_->stop (); +// } + +int +FTP_Client_Callback::handle_end_stream (void) +{ + TAO_AV_CORE::instance ()->stop_run (); + return 0; +} + +FTP_Client_StreamEndPoint::FTP_Client_StreamEndPoint (TAO_ORB_Manager *orb_manager) + :orb_manager_ (orb_manager) +{ + +} + +void +FTP_Client_Callback::get_timeout (ACE_Time_Value *&tv, + void *&arg) +{ + ACE_Time_Value *timeout; + ACE_NEW (timeout, + ACE_Time_Value(2)); + tv = timeout; +} + +int +FTP_Client_Callback::handle_timeout (void *arg) +{ + ACE_Message_Block mb (BUFSIZ); + ACE_DEBUG ((LM_DEBUG,"FTP_Client_Callback::get_frame")); + char *buf = mb.rd_ptr (); + cerr << "message block size" << mb.size () << endl; + int n = ACE_OS::fread(buf,1,mb.size (),CLIENT::instance ()->file ()); + if (n < 0) + { + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread end of file\n"),-1); + } + if (n == 0) + { + if (::feof (CLIENT::instance ()->file ())) + { + // wait for sometime for the data to be flushed to the other side. + this->count_++; + if (this->count_ == 2) + { + ACE_DEBUG ((LM_DEBUG,"handle_timeout:End of file\n")); + AVStreams::flowSpec stop_spec (1); + ACE_DECLARE_NEW_CORBA_ENV; + CLIENT::instance ()->streamctrl ()->stop (stop_spec,ACE_TRY_ENV); + ACE_CHECK_RETURN (-1); + CLIENT::instance ()->streamctrl ()->destroy (stop_spec,ACE_TRY_ENV); + TAO_AV_CORE::instance ()->stop_run (); + } + else + return 0; + } + else + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread error\n"),-1); + } + cerr << "read bytes = " << n << endl; + mb.wr_ptr (n); + int result = this->protocol_object_->send_frame (&mb); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"send failed:%p","FTP_Client_Flow_Handler::send \n"),-1); + ACE_DEBUG ((LM_DEBUG,"handle_timeout::buffer sent succesfully\n")); + return 0; +} + +int +FTP_Client_StreamEndPoint::get_callback (const char *flowname, + TAO_AV_Callback *&callback) +{ +// ACE_Time_Value timeout (2); +// ACE_NEW_RETURN (this->handler_, +// FTP_Client_Flow_Handler (this->orb_manager_, +// timeout), +// -1); + ACE_NEW_RETURN (this->callback_, + // FTP_Client_Callback (this->handler_), + FTP_Client_Callback, + -1); + callback = this->callback_; + return 0; +} + +int +FTP_Client_StreamEndPoint::set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object) +{ + // int result = this->handler_->set_protocol_object (object); + this->callback_->set_protocol_object (object); + ACE_CString flow_string (flowname); + return 0; +} + +// FTP_Client_Flow_Handler::FTP_Client_Flow_Handler (TAO_ORB_Manager *orb_manager, +// ACE_Time_Value &timeout) +// :orb_manager_ (orb_manager), +// count_ (0), +// protocol_object_ (0), +// timeout_ (timeout) +// { +// } + +// int +// FTP_Client_Flow_Handler::start (void) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_Flow_Handler::start")); +// ACE_Time_Value delta = ACE_Time_Value::zero; +// this->timer_id_ = +// TAO_AV_CORE::instance ()->reactor ()->schedule_timer (this, +// 0, +// delta, +// this->timeout_); +// return 0; +// } + +// int +// FTP_Client_Flow_Handler::stop (void) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_Flow_Handler::stop")); +// int result = TAO_AV_CORE::instance ()->reactor ()->cancel_timer (this->timer_id_); +// if (result < 0) +// ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::stop cancel timer failed\n"),-1); +// return 0; +// } + +// int +// FTP_Client_Flow_Handler::set_protocol_object (TAO_AV_Protocol_Object *object) +// { +// this->protocol_object_ = object; +// return 0; +// } +// int +// FTP_Client_Flow_Handler::handle_timeout (const ACE_Time_Value &tv, +// const void *arg) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_StreamEndPoint::handle_timeout")); +// ACE_Message_Block mb (BUFSIZ); +// char *buf = mb.rd_ptr (); +// cerr << "message block size" << mb.size () << endl; +// int n = ACE_OS::fread(buf,1,mb.size (),CLIENT::instance ()->file ()); +// if (n < 0) +// { +// TAO_AV_CORE::instance ()->reactor ()->cancel_timer (this->timer_id_); +// ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread end of file\n"),-1); +// } +// if (n == 0) +// { +// if (::feof (CLIENT::instance ()->file ())) +// { +// // wait for sometime for the data to be flushed to the other side. +// this->count_++; +// if (this->count_ == 2) +// { +// ACE_DEBUG ((LM_DEBUG,"handle_timeout:End of file\n")); +// AVStreams::flowSpec stop_spec (1); +// stop_spec.length (1); +// ACE_DECLARE_NEW_CORBA_ENV; +// stop_spec [0] = CORBA::string_dup (CLIENT::instance ()->flowname ()); +// CLIENT::instance ()->streamctrl ()->stop (stop_spec,ACE_TRY_ENV); +// ACE_CHECK_RETURN (-1); +// } +// else +// return 0; +// } +// else +// ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread error\n"),-1); +// } +// cerr << "read bytes = " << n << endl; +// mb.wr_ptr (n); +// int result = this->protocol_object_->send_frame (&mb); +// if (result < 0) +// ACE_ERROR_RETURN ((LM_ERROR,"send failed:%p","FTP_Client_Flow_Handler::send \n"),-1); +// ACE_DEBUG ((LM_DEBUG,"handle_timeout::buffer sent succesfully\n")); +// } + + +Endpoint_Reactive_Strategy::Endpoint_Reactive_Strategy (TAO_ORB_Manager *orb_manager, + Client *client) + :ENDPOINT_STRATEGY (orb_manager), + client_ (client), + orb_manager_ (orb_manager) +{ +} + +int +Endpoint_Reactive_Strategy::make_stream_endpoint (FTP_Client_StreamEndPoint *&endpoint) +{ + ACE_DEBUG ((LM_DEBUG,"Endpoint_Reactive_Strategy::make_stream_endpoint")); + ACE_NEW_RETURN (endpoint, + FTP_Client_StreamEndPoint (this->orb_manager_), + -1); + return 0; +} + +Client::parse_args (int argc, + char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:a:p:s"); + + this->use_sfp_ = 0; + char c; + while ((c= opts ()) != -1) + { + switch (c) + { + case 'f': + this->filename_ = ACE_OS::strdup (opts.optarg); + break; + case 'a': + this->address_ = ACE_OS::strdup (opts.optarg); + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + break; + case 's': + this->use_sfp_ = 1; + break; + default: + ACE_DEBUG ((LM_DEBUG,"Unknown option\n")); + return -1; + break; + } + } + return 0; +} + +FILE * +Client::file (void) +{ + return this->fp_; +} + +char* +Client::flowname (void) +{ + return this->flowname_; +} + +TAO_StreamCtrl* +Client::streamctrl (void) +{ + return &this->streamctrl_; +} + +Client::Client (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + endpoint_strategy_ (orb_manager_,this), + client_mmdevice_ (&endpoint_strategy_), + fp_ (0), + protocol_ (ACE_OS::strdup ("UDP")) +{ +} + + +int +Client::bind_to_server (const char *name) +{ + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + // Initialize the naming services + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = name; + CORBA::Object_var server_mmdevice_obj = + my_naming_client_->resolve (server_mmdevice_name, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + this->server_mmdevice_ = + AVStreams::MMDevice::_narrow (server_mmdevice_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + + if (CORBA::is_nil (this->server_mmdevice_.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " could not resolve Server_Mmdevice in Naming service <%s>\n"), + -1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Command_Handler::resolve_reference"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::init (int argc,char **argv) +{ + this->argc_ = argc; + this->argv_ = argv; + + // Increase the debug_level so that we can see the output + // TAO_debug_level++; + CORBA::String_var ior; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = TAO_AV_CORE::instance ()->orb_manager (); + this->orb_manager_->init_child_poa (this->argc_, + this->argv_, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->parse_args (this->argc_, this->argv_); + // activate the client video mmdevice under the child poa. + ior = this->orb_manager_->activate (&this->client_mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Initialize the naming services + CORBA::ORB_var orb = orb_manager_->orb (); + if (this->my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + this->fp_ = ACE_OS::fopen (this->filename_,"r"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + char flow_protocol_str [BUFSIZ]; + if (this->use_sfp_) + ACE_OS::strcpy (flow_protocol_str,"sfp:1.0"); + else + ACE_OS::strcpy (flow_protocol_str,""); + AVStreams::streamQoS_var the_qos (new AVStreams::streamQoS); + AVStreams::flowSpec flow_spec (1); + // Bind the client and server mmdevices. + + this->orb_manager_->activate_poa_manager (ACE_TRY_ENV); + ACE_TRY_CHECK; + ACE_INET_Addr addr (this->address_); + ACE_NEW_RETURN (this->flowname_, + char [BUFSIZ], + 0); + ACE_OS::sprintf (this->flowname_, + "Data_%s", + this->protocol_); + TAO_Forward_FlowSpec_Entry entry (this->flowname_, + "IN", + "USER_DEFINED", + flow_protocol_str, + this->protocol_, + &addr); + flow_spec [0] = entry.entry_to_string (); + flow_spec.length (1); + CORBA::Boolean result = + this->streamctrl_.bind_devs (this->client_mmdevice_._this (ACE_TRY_ENV), + AVStreams::MMDevice::_nil (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (this->bind_to_server ("Server_MMDevice1") == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Error binding to the naming service\n"), + -1); + result = this->streamctrl_.bind_devs (AVStreams::MMDevice::_nil (), + this->server_mmdevice_.in (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (this->bind_to_server ("Server_MMDevice2") == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Error binding to the naming service\n"), + -1); + result = this->streamctrl_.bind_devs (AVStreams::MMDevice::_nil (), + this->server_mmdevice_.in (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"streamctrl::bind_devs failed\n"),-1); + AVStreams::flowSpec start_spec (1); + start_spec.length (1); + start_spec [0] = CORBA::string_dup (this->flowname_); + this->streamctrl_.start (start_spec,ACE_TRY_ENV); + ACE_TRY_CHECK; + // Schedule a timer for the for the flow handler. + TAO_AV_CORE::instance ()->run (); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::run"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +main (int argc, + char **argv) +{ + int result = 0; + result = CLIENT::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::init failed\n"),1); + result = CLIENT::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::run failed\n"),1); + +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Client,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Client,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast/ftp.h b/TAO/orbsvcs/tests/AVStreams/Multicast/ftp.h new file mode 100644 index 00000000000..1d0a3b48aa8 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast/ftp.h @@ -0,0 +1,125 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef TAO_AV_FTP_H +#define TAO_AV_FTP_H + +#include "ace/Get_Opt.h" +#include "tao/TAO.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/Transport.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" + +// class FTP_Client_Flow_Handler +// :public virtual ACE_Event_Handler +// { +// public: +// FTP_Client_Flow_Handler (TAO_ORB_Manager *orb_manager, +// ACE_Time_Value &timeout); +// virtual int handle_timeout (const ACE_Time_Value &tv, +// const void *arg = 0); +// virtual int start (void); +// virtual int stop (void); +// virtual int set_protocol_object (TAO_AV_Protocol_Object *object); +// protected: +// TAO_ORB_Manager *orb_manager_; +// long timer_id_; +// int count_; +// TAO_AV_Protocol_Object *protocol_object_; +// ACE_Time_Value timeout_; +// }; + +class FTP_Client_Callback + :public TAO_AV_Callback +{ +public: + FTP_Client_Callback (void); + // FTP_Client_Callback (FTP_Client_Flow_Handler *handler); +// virtual int handle_start (void); +// virtual int handle_stop (void); + virtual int handle_end_stream (void); + void set_protocol_object (TAO_AV_Protocol_Object *protocol_object) {this->protocol_object_ = protocol_object;} + virtual int handle_timeout (void *arg); + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); + +protected: + int count_; + // FTP_Client_Flow_Handler *handler_; + TAO_AV_Protocol_Object *protocol_object_; +}; + +class FTP_Client_StreamEndPoint + :public TAO_Client_StreamEndPoint +{ +public: + FTP_Client_StreamEndPoint (TAO_ORB_Manager *orb_manager = 0); + + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + + virtual int set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object); +protected: + TAO_ORB_Manager *orb_manager_; + // FTP_Client_Flow_Handler *handler_; + FTP_Client_Callback *callback_; +}; + +typedef TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> ENDPOINT_STRATEGY; + +class Client; +class Endpoint_Reactive_Strategy + : public ENDPOINT_STRATEGY +{ +public: + Endpoint_Reactive_Strategy (TAO_ORB_Manager *orb_manager, + Client *client_ptr); + // constructor . The orb manager is needed for the TAO_AV_Endpoint_Reactive_Strategy_A. + + virtual int make_stream_endpoint (FTP_Client_StreamEndPoint *& endpoint); + // hook to make our streamendpoint taking a Client pointer +private: + Client *client_; + // pointer to command handler object + TAO_ORB_Manager *orb_manager_; +}; + + +class Client +{ +public: + Client (void); + int init (int argc, char **argv); + int run (void); + FILE *file (void); + char *flowname (void); + TAO_StreamCtrl* streamctrl (void); +private: + int parse_args (int argc, char **argv); + int bind_to_server (const char *name); + TAO_ORB_Manager *orb_manager_; + Endpoint_Reactive_Strategy endpoint_strategy_; + AVStreams::MMDevice_var server_mmdevice_; + TAO_MMDevice client_mmdevice_; + TAO_StreamCtrl streamctrl_; + // Video stream controller + + int argc_; + char **argv_; + const char *filename_; + const char *address_; + + TAO_Naming_Client my_naming_client_; + FILE *fp_; + char *protocol_; + char *flowname_; + int use_sfp_; +}; + +typedef ACE_Singleton<Client,ACE_Null_Mutex> CLIENT; + +#endif /* TAO_AV_FTP_H */ diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast/server.cpp b/TAO/orbsvcs/tests/AVStreams/Multicast/server.cpp new file mode 100644 index 00000000000..d565e4d5abb --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast/server.cpp @@ -0,0 +1,219 @@ +// $Id$ + +#include "server.h" + +FTP_Server_StreamEndPoint::FTP_Server_StreamEndPoint (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_StreamEndPoint::FTP_Server_StreamEndPoint")); +} + +int +FTP_Server_StreamEndPoint::get_callback (const char *flowname, + TAO_AV_Callback *&callback) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_StreamEndPoint::get_sfp_callback\n")); + ACE_NEW_RETURN (callback, + FTP_Server_Callback, + -1); + return 0; +} + +int +FTP_Server_Callback::handle_stop (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::stop")); + ACE_OS::fclose (SERVER::instance ()->file ()); + return 0; +} + +int +FTP_Server_Callback::receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::receive_frame\n")); + while (frame != 0) + { + int result = ACE_OS::fwrite (frame->rd_ptr (), + frame->length (), + 1, + SERVER::instance ()->file ()); + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Server_Flow_Handler::fwrite failed\n"),-1); + frame = frame->cont (); + } + return 0; +} + +int +FTP_Server_Callback::handle_end_stream (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_SFP_Callback::end_stream\n")); + CORBA::ORB_var orb = TAO_AV_CORE::instance ()->orb_manager ()->orb (); + orb->shutdown (); + return 0; +} + +Server::Server (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + reactive_strategy_ (orb_manager_) +{ +} + +int +Server::init (int argc, + char **argv) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = + TAO_AV_CORE::instance ()->orb_manager (); + + // Initialize the orb_manager + this->orb_manager_->init_child_poa (argc, + argv, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::ORB_var orb = + this->orb_manager_->orb (); + + PortableServer::POA_var child_poa = + this->orb_manager_->child_poa (); + + + int result = this->parse_args (argc,argv); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"parse args failed\n"),-1); + // Initialize the naming services + + if (my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + // Register the video mmdevice object with the ORB + ACE_NEW_RETURN (this->mmdevice_, + TAO_MMDevice (&this->reactive_strategy_), + -1); + // create the video server mmdevice with the naming service pointer. + this->orb_manager_->activate_under_child_poa ("Server_MMDevice", + this->mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Register the mmdevice with the naming service. + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice1"); + AVStreams::MMDevice_var mmdevice = this->mmdevice_->_this (ACE_TRY_ENV); + ACE_TRY_EX (bind) + { + // Register the video control object with the naming server. + this->my_naming_client_->bind (server_mmdevice_name, + mmdevice.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (bind); + } + ACE_CATCH (CosNaming::NamingContext::AlreadyBound,al_ex) + { + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice2"); + this->my_naming_client_->bind (server_mmdevice_name, + mmdevice.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->orb_manager_->run (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::parse_args (int argc,char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:p:"); + + char c; + while ((c = opts ()) != -1) + { + switch (c) + { + case 'f': + this->fp_ = ACE_OS::fopen (opts.optarg,"w"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + default: + ACE_ERROR_RETURN ((LM_ERROR,"Usage: server -f filename"),-1); + break; + } + } + return 0; +} + +FILE* +Server::file (void) +{ + return this->fp_; +} + +int +main (int argc, + char **argv) +{ + int result = 0; + result = SERVER::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::init failed\n"),1); + result = SERVER::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::run failed\n"),1); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Server,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Server,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast/server.h b/TAO/orbsvcs/tests/AVStreams/Multicast/server.h new file mode 100644 index 00000000000..2df2db4c209 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast/server.h @@ -0,0 +1,53 @@ +/* -*- C++ -*- */ +// $Id$ + +#include "ace/Get_Opt.h" +#include "tao/TAO.h" +#include "orbsvcs/orbsvcs/CosNamingC.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/Transport.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" +#include "orbsvcs/AV/Policy.h" + +class FTP_Server_StreamEndPoint + :public TAO_Server_StreamEndPoint +{ +public: + FTP_Server_StreamEndPoint (void); + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); +}; + +class FTP_Server_Callback + :public TAO_AV_Callback +{ +public: + virtual int handle_stop (void); + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &); + virtual int handle_end_stream (void); +}; + +class Server +{ +public: + Server (void); + int init (int argc, + char **argv); + int run (void); + FILE *file (void); +protected: + int parse_args (int argc,char **argv); + TAO_ORB_Manager *orb_manager_; + TAO_Naming_Client my_naming_client_; + TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> reactive_strategy_; + TAO_MMDevice *mmdevice_; + FILE *fp_; + char *protocol_; +}; + +typedef ACE_Singleton<Server,ACE_Null_Mutex> SERVER; diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/Makefile b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/Makefile new file mode 100644 index 00000000000..d2f38f81303 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/Makefile @@ -0,0 +1,57 @@ +#---------------------------------------------------------------------------- +# $Id$ +# +# Top-level Makefile for Full Profile testing of AVStreams of TAO. +# +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +LIBS += -lorbsvcs -lTAO + +SERVER_OBJS = server.o +CLIENT_OBJS = ftp.o + +VLDLIBS = $(LDLIBS:%=%$(VAR)) + +ifndef TAO_ROOT +TAO_ROOT = $(ACE_ROOT)/TAO +endif + +FILES = ftp server +DEFS = $(addsuffix .h,$(FILES)) +LSRC = $(addsuffix .cpp,$(FILES)) + +BIN2 = server ftp + +#### If the TAO orbsvcs library wasn't built with sufficient components, +#### don't try to build here. +TAO_ORBSVCS := $(shell $(ACE_ROOT)/bin/ace_components --orbsvcs) +ifeq (AV,$(findstring AV,$(TAO_ORBSVCS))) + BIN = $(BIN2) +endif # AV + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(TAO_ROOT)/rules.tao.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +DCFLAGS = -g +LDFLAGS += -L$(TAO_ROOT)/orbsvcs/orbsvcs -L$(TAO_ROOT)/tao +CPPFLAGS += -I$(TAO_ROOT)/orbsvcs -I$(TAO_ROOT) $(TSS_ORB_FLAG) + +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/ftp.cpp b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/ftp.cpp new file mode 100644 index 00000000000..63a5a315342 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/ftp.cpp @@ -0,0 +1,527 @@ +// $Id$ + +#include "ftp.h" + +// FTP_Client_Callback::FTP_Client_Callback (FTP_Client_Flow_Handler *handler) +// :handler_ (handler) +// { +// } + +// int +// FTP_Client_Callback::handle_start (void) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_Callback::handle_start")); +// return this->handler_->start (); +// } + +// int +// FTP_Client_Callback::handle_stop (void) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_Callback::handle_stop")); +// return this->handler_->stop (); +// } + + +// FTP_Client_Flow_Handler::FTP_Client_Flow_Handler (TAO_ORB_Manager *orb_manager, +// ACE_Time_Value &timeout) +// :TAO_FlowProducer ("Data",CLIENT::instance ()->protocols (),CLIENT::instance ()->format ()), +// orb_manager_ (orb_manager), +// count_ (0), +// timeout_ (timeout) +// { +// } + +// int +// FTP_Client_Flow_Handler::get_callback (const char *flowname, +// TAO_AV_Callback *&callback) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_Flow_Handler::get_callback\n")); +// ACE_NEW_RETURN (callback, +// FTP_Client_Callback (this), +// -1); +// return 0; +// } + +// int +// FTP_Client_Flow_Handler::start (void) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_Flow_Handler::start")); +// ACE_Time_Value delta = ACE_Time_Value::zero; +// this->timer_id_ = +// TAO_AV_CORE::instance ()->reactor ()->schedule_timer (this, +// 0, +// delta, +// this->timeout_); +// return 0; +// } + +// int +// FTP_Client_Flow_Handler::stop (void) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_Flow_Handler::stop")); +// int result = TAO_AV_CORE::instance ()->reactor ()->cancel_timer (this->timer_id_); +// if (result < 0) +// ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::stop cancel timer failed\n"),-1); +// return 0; +// } + +// int +// FTP_Client_Flow_Handler::handle_timeout (const ACE_Time_Value &tv, +// const void *arg) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_StreamEndPoint::handle_timeout")); +// ACE_Message_Block mb (BUFSIZ); +// char *buf = mb.rd_ptr (); +// cerr << "message block size" << mb.size () << endl; +// int n = ACE_OS::fread(buf,1,mb.size (),CLIENT::instance ()->file ()); +// if (n < 0) +// { +// TAO_AV_CORE::instance ()->reactor ()->cancel_timer (this->timer_id_); +// ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread end of file\n"),-1); +// } +// if (n == 0) +// { +// if (::feof (CLIENT::instance ()->file ())) +// { +// // wait for sometime for the data to be flushed to the other side. +// this->count_++; +// if (this->count_ == 2) +// { +// ACE_DECLARE_NEW_CORBA_ENV; +// ACE_DEBUG ((LM_DEBUG,"handle_timeout:End of file\n")); +// AVStreams::flowSpec stop_spec (1); +// // stop_spec.length (1); +// // stop_spec [0] = CORBA::string_dup (CLIENT::instance ()->flowname ()); +// CLIENT::instance ()->streamctrl ()->stop (stop_spec,ACE_TRY_ENV); +// ACE_CHECK_RETURN (-1); +// return 0; +// } +// else +// return 0; +// } +// else +// ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread error\n"),-1); +// } +// cerr << "read bytes = " << n << endl; +// mb.wr_ptr (n); +// int result = this->protocol_object_->send_frame (&mb); +// if (result < 0) +// ACE_ERROR_RETURN ((LM_ERROR,"send failed:%p","FTP_Client_Flow_Handler::send \n"),-1); +// ACE_DEBUG ((LM_DEBUG,"handle_timeout::buffer sent succesfully\n")); +// } + +//------------------------------------------------------------ +// FTP_Client_FDev +//------------------------------------------------------------ + +// FTP_Client_FDev::FTP_Client_FDev (TAO_ORB_Manager *orb_manager) +// :TAO_FDev (CORBA::string_dup ("Data")), +// orb_manager_ (orb_manager) +// { +// } + +// AVStreams::FlowProducer_ptr +// FTP_Client_FDev::make_producer (AVStreams::FlowConnection_ptr the_requester, +// AVStreams::QoS & the_qos, +// CORBA::Boolean_out met_qos, +// char *& named_fdev, +// CORBA::Environment &ACE_TRY_ENV) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Client_FDev::make_producer\n")); +// FTP_Client_Flow_Handler *handler; +// ACE_Time_Value timeout (2); +// ACE_NEW_RETURN (handler, +// FTP_Client_Flow_Handler (this->orb_manager_, +// timeout), +// 0); +// AVStreams::FlowProducer_ptr producer = handler->_this (ACE_TRY_ENV); +// ACE_CHECK_RETURN (0); +// return producer; +// } + +FTP_Client_Callback::FTP_Client_Callback (void) + // :handler_ (handler), + :count_ (0) +{ +} + +int +FTP_Client_Callback::handle_end_stream (void) +{ + TAO_AV_CORE::instance ()->stop_run (); + return 0; +} + +void +FTP_Client_Callback::get_timeout (ACE_Time_Value *&tv, + void *&arg) +{ + ACE_Time_Value *timeout; + ACE_NEW (timeout, + ACE_Time_Value(2)); + tv = timeout; +} + +int +FTP_Client_Callback::handle_timeout (void *arg) +{ + ACE_Message_Block mb (BUFSIZ); + ACE_DEBUG ((LM_DEBUG,"FTP_Client_Callback::get_frame")); + char *buf = mb.rd_ptr (); + cerr << "message block size" << mb.size () << endl; + int n = ACE_OS::fread(buf,1,mb.size (),CLIENT::instance ()->file ()); + if (n < 0) + { + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread end of file\n"),-1); + } + if (n == 0) + { + if (feof (CLIENT::instance ()->file ())) + { + // wait for sometime for the data to be flushed to the other side. + this->count_++; + if (this->count_ == 2) + { + ACE_DEBUG ((LM_DEBUG,"handle_timeout:End of file\n")); + AVStreams::flowSpec stop_spec (1); + ACE_DECLARE_NEW_CORBA_ENV; + CLIENT::instance ()->streamctrl ()->stop (stop_spec,ACE_TRY_ENV); + ACE_CHECK_RETURN (-1); + CLIENT::instance ()->streamctrl ()->destroy (stop_spec,ACE_TRY_ENV); + TAO_AV_CORE::instance ()->stop_run (); + } + else + return 0; + } + else + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread error\n"),-1); + } + cerr << "read bytes = " << n << endl; + mb.wr_ptr (n); + int result = this->protocol_object_->send_frame (&mb); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"send failed:%p","FTP_Client_Flow_Handler::send \n"),-1); + ACE_DEBUG ((LM_DEBUG,"handle_timeout::buffer sent succesfully\n")); + return 0; +} + +FTP_Client_Producer::FTP_Client_Producer (void) + :TAO_FlowProducer ("Data",CLIENT::instance ()->protocols (),CLIENT::instance ()->format ()) +{ +} + +int +FTP_Client_Producer::set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object) +{ + this->callback_->set_protocol_object (object); + return 0; +} + +int +FTP_Client_Producer::get_callback (const char *flowname, + TAO_AV_Callback *&callback) +{ + ACE_NEW_RETURN (this->callback_, + FTP_Client_Callback, + -1); + callback = this->callback_; +} + +Client::parse_args (int argc, + char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:a:p:sd"); + + this->use_sfp_ = 0; + char c; + while ((c= opts ()) != -1) + { + switch (c) + { + case 'f': + this->filename_ = ACE_OS::strdup (opts.optarg); + break; + case 'a': + this->address_ = ACE_OS::strdup (opts.optarg); + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + break; + case 's': + this->use_sfp_ = 1; + break; + case 'd': + TAO_debug_level++; + break; + default: + ACE_DEBUG ((LM_DEBUG,"Unknown option\n")); + return -1; + break; + } + } + return 0; +} + +FILE * +Client::file (void) +{ + return this->fp_; +} + +char* +Client::flowname (void) +{ + return this->flowname_; +} + +AVStreams::protocolSpec +Client::protocols (void) +{ + AVStreams::protocolSpec protocols (1); + protocols.length (1); + char buf [BUFSIZ]; + ACE_OS::sprintf (buf,"%s=%s",this->protocol_,this->address_); + protocols [0] = CORBA::string_dup (buf); + return protocols; +} + +const char * +Client::format (void) +{ + return "UNS:ftp"; +} + +const char * +Client::address (void) + +{ + return this->address_; +} + +TAO_StreamCtrl* +Client::streamctrl (void) +{ + return &this->streamctrl_; +} + +Client::Client (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + endpoint_strategy_ (orb_manager_), + client_mmdevice_ (&endpoint_strategy_), + fdev_ (0), + fp_ (0), + protocol_ (ACE_OS::strdup ("UDP")) +{ +} + + +int +Client::bind_to_server (const char *name) +{ + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + // Initialize the naming services + if (my_naming_client_.init (this->orb_manager_->orb ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = name; + CORBA::Object_var server_mmdevice_obj = + my_naming_client_->resolve (server_mmdevice_name, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + this->server_mmdevice_ = + AVStreams::MMDevice::_narrow (server_mmdevice_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + + if (CORBA::is_nil (this->server_mmdevice_.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " could not resolve Server_Mmdevice in Naming service <%s>\n"), + -1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Command_Handler::resolve_reference"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::init (int argc,char **argv) +{ + this->argc_ = argc; + this->argv_ = argv; + + // Increase the debug_level so that we can see the output + // TAO_debug_level++; + CORBA::String_var ior; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = TAO_AV_CORE::instance ()->orb_manager (); + this->orb_manager_->init_child_poa (this->argc_, + this->argv_, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->parse_args (this->argc_, this->argv_); + // activate the client video mmdevice under the child poa. + ior = this->orb_manager_->activate (&this->client_mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + this->orb_manager_->activate_poa_manager (ACE_TRY_ENV); + ACE_TRY_CHECK; + ACE_NEW_RETURN (this->fdev_, + // FTP_Client_FDev (this->orb_manager_), + FTP_Client_FDev, + -1); + + ACE_NEW_RETURN (this->flowname_, + char [BUFSIZ], + 0); + ACE_OS::sprintf (this->flowname_, + "Data"); + this->fdev_->flowname (this->flowname ()); + AVStreams::MMDevice_var mmdevice = this->client_mmdevice_._this (ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FDev_var fdev = this->fdev_->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + mmdevice->add_fdev (fdev.in (), + ACE_TRY_ENV); + + // Initialize the naming services + CORBA::ORB_var orb = orb_manager_->orb (); + if (this->my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + this->fp_ = ACE_OS::fopen (this->filename_,"r"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + char flow_protocol_str [BUFSIZ]; + if (this->use_sfp_) + ACE_OS::strcpy (flow_protocol_str,"sfp:1.0"); + else + ACE_OS::strcpy (flow_protocol_str,""); + AVStreams::streamQoS_var the_qos (new AVStreams::streamQoS); + AVStreams::flowSpec flow_spec (1); + // Bind the client and server mmdevices. + + ACE_INET_Addr addr (this->address_); + TAO_Forward_FlowSpec_Entry entry (this->flowname_, + "IN", + "USER_DEFINED", + flow_protocol_str, + this->protocol_, + &addr); + flow_spec [0] = CORBA::string_dup (entry.entry_to_string ()); + flow_spec.length (1); + CORBA::Boolean result = + this->streamctrl_.bind_devs (this->client_mmdevice_._this (ACE_TRY_ENV), + AVStreams::MMDevice::_nil (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (this->bind_to_server ("Server_MMDevice1") == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Error binding to the naming service\n"), + -1); + result = this->streamctrl_.bind_devs (AVStreams::MMDevice::_nil (), + this->server_mmdevice_.in (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + if (this->bind_to_server ("Server_MMDevice2") == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Error binding to the naming service\n"), + -1); + result = this->streamctrl_.bind_devs (AVStreams::MMDevice::_nil (), + this->server_mmdevice_.in (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"streamctrl::bind_devs failed\n"),-1); + AVStreams::flowSpec start_spec (1); + start_spec.length (1); + start_spec [0] = CORBA::string_dup (this->flowname_); + this->streamctrl_.start (start_spec,ACE_TRY_ENV); + ACE_TRY_CHECK; + // Schedule a timer for the for the flow handler. + TAO_AV_CORE::instance ()->run (); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::run"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +main (int argc, + char *argv[]) +{ + int result = 0; + result = CLIENT::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::init failed\n"),1); + result = CLIENT::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::run failed\n"),1); + +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Client,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Client,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/ftp.h b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/ftp.h new file mode 100644 index 00000000000..2de6020e272 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/ftp.h @@ -0,0 +1,133 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef TAO_AV_FTP_H +#define TAO_AV_FTP_H + +#include "ace/Get_Opt.h" +#include "tao/TAO.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Flows_T.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" + +// class FTP_Client_Flow_Handler +// // :public virtual ACE_Event_Handler, +// public virtual TAO_FlowProducer +// { +// public: +// FTP_Client_Flow_Handler (TAO_ORB_Manager *orb_manager, +// ACE_Time_Value &timeout); +// virtual int handle_timeout (const ACE_Time_Value &tv, +// const void *arg = 0); +// virtual int start (void); +// virtual int stop (void); +// virtual int get_callback (const char *flowname, +// TAO_AV_Callback *&callback); +// protected: +// TAO_ORB_Manager *orb_manager_; +// long timer_id_; +// int count_; +// ACE_Time_Value timeout_; +// }; + +// class FTP_Client_Callback +// :public TAO_AV_Callback +// { +// public: +// FTP_Client_Callback (FTP_Client_Flow_Handler *handler); +// virtual int handle_start (void); +// virtual int handle_stop (void); +// protected: +// FTP_Client_Flow_Handler *handler_; +// }; + +class FTP_Client_Callback; +class FTP_Client_Producer + :public virtual TAO_FlowProducer +{ +public: + FTP_Client_Producer (void); + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + int set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object); +protected: + FTP_Client_Callback *callback_; +}; + +class FTP_Client_Callback + :public TAO_AV_Callback +{ +public: + FTP_Client_Callback (void); + virtual int handle_timeout (void *arg); + virtual int handle_end_stream (void); + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); + // virtual int get_frame (ACE_Message_Block *&block,TAO_AV_frame_info *&frame_info); + void set_protocol_object (TAO_AV_Protocol_Object *protocol_object) {this->protocol_object_ = protocol_object;} + +protected: + // FTP_Client_Flow_Handler *handler_; + int count_; + TAO_AV_Protocol_Object *protocol_object_; +}; + +// class FTP_Client_FDev +// :public TAO_FDev +// { +// public: +// FTP_Client_FDev (TAO_ORB_Manager *orb_manger); +// virtual AVStreams::FlowProducer_ptr make_producer (AVStreams::FlowConnection_ptr the_requester, +// AVStreams::QoS & the_qos, +// CORBA::Boolean_out met_qos, +// char *& named_fdev, +// CORBA::Environment &env = CORBA::Environment::default_environment ()); +// protected: +// TAO_ORB_Manager *orb_manager_; +// }; + +typedef TAO_AV_Endpoint_Reactive_Strategy_A<TAO_StreamEndPoint_A,TAO_VDev,AV_Null_MediaCtrl> ENDPOINT_STRATEGY; + +typedef TAO_FDev <FTP_Client_Producer,TAO_FlowConsumer> FTP_Client_FDev; +class Client +{ +public: + Client (void); + int init (int argc, char **argv); + int run (void); + FILE *file (void); + char *flowname (void); + TAO_StreamCtrl* streamctrl (void); + AVStreams::protocolSpec protocols (void); + const char *format (void); + const char *address (void); +private: + int parse_args (int argc, char **argv); + int bind_to_server (const char *name); + TAO_ORB_Manager *orb_manager_; + ENDPOINT_STRATEGY endpoint_strategy_; + AVStreams::MMDevice_var server_mmdevice_; + TAO_MMDevice client_mmdevice_; + FTP_Client_FDev *fdev_; + TAO_StreamCtrl streamctrl_; + // Video stream controller + + int argc_; + char **argv_; + const char *filename_; + const char *address_; + + TAO_Naming_Client my_naming_client_; + FILE *fp_; + char *protocol_; + char *flowname_; + int use_sfp_; +}; + +typedef ACE_Singleton<Client,ACE_Null_Mutex> CLIENT; + +#endif /* TAO_AV_FTP_H */ diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/server.cpp b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/server.cpp new file mode 100644 index 00000000000..148332ae002 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/server.cpp @@ -0,0 +1,284 @@ +// $Id$ + +#include "server.h" + +FTP_Server_FlowEndPoint::FTP_Server_FlowEndPoint (void) + :TAO_FlowConsumer ("Data",SERVER::instance ()->protocols (),SERVER::instance ()->format ()) +{ + AVStreams::protocolSpec protocols (2); + protocols.length (2); + protocols [0] = CORBA::string_dup ("TCP"); + protocols [1] = CORBA::string_dup ("UDP"); + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->set_protocol_restriction (protocols, + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"FTP_Server_FlowEndPoint::FTP_Server_FlowEndPoint"); + } + ACE_ENDTRY; + ACE_CHECK; +} + +int +FTP_Server_FlowEndPoint::get_callback (const char *flowname, + TAO_AV_Callback *&callback) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_StreamEndPoint::get_sfp_callback\n")); + ACE_NEW_RETURN (callback, + FTP_Server_Callback, + -1); + return 0; +} + +int +FTP_Server_Callback::handle_stop (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::stop")); + ACE_OS::fclose (SERVER::instance ()->file ()); + return 0; +} + +int +FTP_Server_Callback::receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::receive_frame\n")); + while (frame != 0) + { + int result = ACE_OS::fwrite (frame->rd_ptr (), + frame->length (), + 1, + SERVER::instance ()->file ()); + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Server_Flow_Handler::fwrite failed\n"),-1); + frame = frame->cont (); + } + return 0; +} + +int +FTP_Server_Callback::handle_end_stream (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_SFP_Callback::end_stream\n")); + CORBA::ORB_var orb = TAO_AV_CORE::instance ()->orb_manager ()->orb (); + orb->shutdown (); + return 0; +} + +// FTP_Server_FDev::FTP_Server_FDev (void) +// :TAO_FDev ("Data") +// { +// } + +// AVStreams::FlowConsumer_ptr +// FTP_Server_FDev::make_consumer (AVStreams::FlowConnection_ptr the_requester, +// AVStreams::QoS & the_qos, +// CORBA::Boolean_out met_qos, +// char *& named_fdev, +// CORBA::Environment &ACE_TRY_ENV) +// { +// ACE_DEBUG ((LM_DEBUG,"FTP_Server_FDev::make_consumer")); +// FTP_Server_FlowEndPoint *endpoint; +// ACE_NEW_RETURN (endpoint, +// FTP_Server_FlowEndPoint, +// 0); +// return endpoint->_this (ACE_TRY_ENV); +// ACE_CHECK_RETURN (0); +// } + +Server::Server (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + reactive_strategy_ (orb_manager_) +{ +} + +AVStreams::protocolSpec +Server::protocols (void) +{ + AVStreams::protocolSpec protocols (2); + protocols.length (2); + protocols [0] = CORBA::string_dup ("TCP"); + protocols [1] = CORBA::string_dup ("UDP"); + return protocols; +} + +const char* +Server::format (void) +{ + return "UNS:ftp"; +} + +int +Server::init (int argc, + char **argv) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = + TAO_AV_CORE::instance ()->orb_manager (); + + // Initialize the orb_manager + this->orb_manager_->init_child_poa (argc, + argv, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::ORB_var orb = + this->orb_manager_->orb (); + + PortableServer::POA_var child_poa = + this->orb_manager_->child_poa (); + + int result = this->parse_args (argc,argv); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"parse args failed\n"),-1); + // Initialize the naming services + + if (my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + this->orb_manager_->activate_poa_manager (ACE_TRY_ENV); + ACE_TRY_CHECK; + // Register the video mmdevice object with the ORB + ACE_NEW_RETURN (this->mmdevice_, + TAO_MMDevice (&this->reactive_strategy_), + -1); + + ACE_NEW_RETURN (this->fdev_, + FTP_Server_FDev, + -1); + this->fdev_->flowname ("Data"); + AVStreams::MMDevice_var mmdevice = this->mmdevice_->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + AVStreams::FDev_var fdev = this->fdev_->_this (ACE_TRY_ENV); + ACE_TRY_CHECK; + mmdevice->add_fdev (fdev.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + // create the video server mmdevice with the naming service pointer. + this->orb_manager_->activate_under_child_poa ("Server_MMDevice", + this->mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + // Register the mmdevice with the naming service. + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice1"); + ACE_TRY_EX (bind) + { + // Register the video control object with the naming server. + this->my_naming_client_->bind (server_mmdevice_name, + mmdevice.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK_EX (bind); + } + ACE_CATCH (CosNaming::NamingContext::AlreadyBound,al_ex) + { + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice2"); + this->my_naming_client_->bind (server_mmdevice_name, + mmdevice.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->orb_manager_->run (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::parse_args (int argc,char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:p:"); + + char c; + while ((c = opts ()) != -1) + { + switch (c) + { + case 'f': + this->fp_ = ACE_OS::fopen (opts.optarg,"w"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + default: + ACE_ERROR_RETURN ((LM_ERROR,"Usage: server -f filename"),-1); + break; + } + } + return 0; +} + +FILE* +Server::file (void) +{ + return this->fp_; +} + +int +main (int argc, + char **argv) +{ + int result = 0; + result = SERVER::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::init failed\n"),1); + result = SERVER::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::run failed\n"),1); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Server,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Server,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/server.h b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/server.h new file mode 100644 index 00000000000..c62d88142ab --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Multicast_Full_Profile/server.h @@ -0,0 +1,72 @@ +/* -*- C++ -*- */ +// $Id$ + +#include "ace/Get_Opt.h" +#include "tao/TAO.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/Flows_T.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" +#include "orbsvcs/AV/Policy.h" + +class FTP_Server_Callback + :public TAO_AV_Callback +{ +public: + virtual int handle_stop (void); + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info, + const ACE_Addr &); + virtual int handle_end_stream (void); +}; + +class FTP_Server_FlowEndPoint + :public TAO_FlowConsumer +{ +public: + FTP_Server_FlowEndPoint (void); + int get_callback (const char *flowname, + TAO_AV_Callback *&callback); +}; + +// class FTP_Server_FDev +// :public TAO_FDev +// { +// public: +// FTP_Server_FDev (void); +// virtual AVStreams::FlowConsumer_ptr make_consumer (AVStreams::FlowConnection_ptr the_requester, +// AVStreams::QoS & the_qos, +// CORBA::Boolean_out met_qos, +// char *& named_fdev, +// CORBA::Environment &env = CORBA::Environment::default_environment ()); +// // bridge method for the application to override the consumer object +// // creation. Default implementation creates a TAO_FlowConsumer. + +// }; + +typedef TAO_FDev <TAO_FlowProducer, FTP_Server_FlowEndPoint> FTP_Server_FDev; + +class Server +{ +public: + Server (void); + int init (int argc, + char **argv); + int run (void); + FILE *file (void); + AVStreams::protocolSpec protocols (void); + const char *format (void); +protected: + int parse_args (int argc,char **argv); + TAO_ORB_Manager *orb_manager_; + TAO_Naming_Client my_naming_client_; + TAO_AV_Endpoint_Reactive_Strategy_B <TAO_StreamEndPoint_B,TAO_VDev,AV_Null_MediaCtrl> reactive_strategy_; + TAO_MMDevice *mmdevice_; + FTP_Server_FDev *fdev_; + FILE *fp_; + char *protocol_; +}; + +typedef ACE_Singleton<Server,ACE_Null_Mutex> SERVER; diff --git a/TAO/orbsvcs/tests/AVStreams/Pluggable/Makefile b/TAO/orbsvcs/tests/AVStreams/Pluggable/Makefile new file mode 100644 index 00000000000..92776f09769 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Pluggable/Makefile @@ -0,0 +1,65 @@ +#---------------------------------------------------------------------------- +# $Id$ +# +# Top-level Makefile for Pluggable testing of AVStreams of TAO. +# +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +LIBS += -lorbsvcs -lTAO + +SERVER_OBJS = server.o +CLIENT_OBJS = ftp.o + +VLDLIBS = $(LDLIBS:%=%$(VAR)) + +ifndef TAO_ROOT +TAO_ROOT = $(ACE_ROOT)/TAO +endif + +FILES = ftp server +DEFS = $(addsuffix .h,$(FILES)) +LSRC = $(addsuffix .cpp,$(FILES)) + +BIN2 = server ftp + +#### If the TAO orbsvcs library wasn't built with sufficient components, +#### don't try to build here. +TAO_ORBSVCS := $(shell $(ACE_ROOT)/bin/ace_components --orbsvcs) +ifeq (AV,$(findstring AV,$(TAO_ORBSVCS))) + BIN = $(BIN2) +endif # AV + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(TAO_ROOT)/rules.tao.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +#DCFLAGS = -g +LDFLAGS += -L$(TAO_ROOT)/orbsvcs/orbsvcs -L$(TAO_ROOT)/tao +CPPFLAGS += -I$(TAO_ROOT)/orbsvcs -I$(TAO_ROOT) $(TSS_ORB_FLAG) + + + +#server:$(addprefix $(VDIR),$(SERVER_OBJS)) +# $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK) + +#ftp:$(addprefix $(VDIR),$(CLIENT_OBJS)) +# $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK) + +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/TAO/orbsvcs/tests/AVStreams/Pluggable/README b/TAO/orbsvcs/tests/AVStreams/Pluggable/README new file mode 100644 index 00000000000..8c24da61dd7 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Pluggable/README @@ -0,0 +1,22 @@ +// $Id$ + +This directory contains a simple file transfer test program for the +Pluggable Data Protocols in the TAO's Audio/Video Streaming +Service. This program can be run using UDP,TCP and SFP over UDP. + +server: +------- + +-f filename -> The name of the file under which the received stream + data has to be stored. + +ftp: +---- + +-f filename --> The file to be streamed to the server. It is currently + streamed at the rate of 0.5kbytes/s. + +-p protocol --> The protocol string could be UDP or TCP. + +-s --> flag to use SFP. This option cannot be used with -p + TCP since SFP currently runs only over UDP. diff --git a/TAO/orbsvcs/tests/AVStreams/Pluggable/ftp.cpp b/TAO/orbsvcs/tests/AVStreams/Pluggable/ftp.cpp new file mode 100644 index 00000000000..b9c63df838a --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Pluggable/ftp.cpp @@ -0,0 +1,376 @@ +// $Id$ + +#include "ftp.h" + +FTP_Client_Callback::FTP_Client_Callback (void) + :count_ (0) +{ +} + +int +FTP_Client_Callback::handle_destroy (void) +{ + TAO_AV_CORE::instance ()->stop_run (); + return 0; +} + +void +FTP_Client_Callback::get_timeout (ACE_Time_Value *&tv, + void *&arg) +{ + ACE_Time_Value *timeout; + ACE_NEW (timeout, + ACE_Time_Value(2)); + tv = timeout; +} + +//@@coryan: Interpretation for the return value like ACE_Event_Handler's handle_timeout method. +int +FTP_Client_Callback::handle_timeout (void *arg) +{ + //@@coryan: Use a preallocated buffer for benchmarks. + //Memory map the file. + ACE_Message_Block mb (BUFSIZ); + ACE_DEBUG ((LM_DEBUG,"FTP_Client_Callback::get_frame")); + char *buf = mb.rd_ptr (); + cerr << "message block size" << mb.size () << endl; + int n = ACE_OS::fread(buf,1,mb.size (),CLIENT::instance ()->file ()); + if (n < 0) + { + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread end of file\n"),-1); + } + if (n == 0) + { + if (::feof (CLIENT::instance ()->file ())) + { + // wait for sometime for the data to be flushed to the other side. + this->count_++; + if (this->count_ == 2) + { + //@@coryan: Remove these code from this method. + //Should be called when the user wants to stop the stream. + ACE_DEBUG ((LM_DEBUG,"handle_timeout:End of file\n")); + AVStreams::flowSpec stop_spec (1); + ACE_DECLARE_NEW_CORBA_ENV; + CLIENT::instance ()->streamctrl ()->stop (stop_spec,ACE_TRY_ENV); + ACE_CHECK_RETURN (-1); + CLIENT::instance ()->streamctrl ()->destroy (stop_spec,ACE_TRY_ENV); + } + else + return 0; + } + else + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Client_Flow_Handler::fread error\n"),-1); + } + cerr << "read bytes = " << n << endl; + mb.wr_ptr (n); + int result = this->protocol_object_->send_frame (&mb); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"send failed:%p","FTP_Client_Flow_Handler::send \n"),-1); + ACE_DEBUG ((LM_DEBUG,"handle_timeout::buffer sent succesfully\n")); + return 0; +} + +FTP_Client_StreamEndPoint::FTP_Client_StreamEndPoint (TAO_ORB_Manager *orb_manager) + :orb_manager_ (orb_manager) +{ + +} + +int +FTP_Client_StreamEndPoint::get_callback (const char */*flowname*/, + TAO_AV_Callback *&callback) +{ + ACE_NEW_RETURN (this->callback_, + FTP_Client_Callback, + -1); + callback = this->callback_; + return 0; +} + +int +FTP_Client_StreamEndPoint::set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object) +{ + this->callback_->set_protocol_object (object); + return 0; +} + +Endpoint_Reactive_Strategy::Endpoint_Reactive_Strategy (TAO_ORB_Manager *orb_manager, + Client *client) + :ENDPOINT_STRATEGY (orb_manager), + client_ (client), + orb_manager_ (orb_manager) +{ +} + +int +Endpoint_Reactive_Strategy::make_stream_endpoint (FTP_Client_StreamEndPoint *&endpoint) +{ + ACE_DEBUG ((LM_DEBUG,"Endpoint_Reactive_Strategy::make_stream_endpoint")); + ACE_NEW_RETURN (endpoint, + FTP_Client_StreamEndPoint (this->orb_manager_), + -1); + return 0; +} + +int +Client::parse_args (int argc, + char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:a:p:sdt"); + + this->use_sfp_ = 0; + char c; + while ((c= opts ()) != -1) + { + switch (c) + { + case 'f': + this->filename_ = ACE_OS::strdup (opts.optarg); + break; + case 'a': + this->address_ = ACE_OS::strdup (opts.optarg); + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + break; + case 's': + this->use_sfp_ = 1; + break; + case 'd': + TAO_debug_level++; + break; + case 't': + this->test_ = 1; + default: + ACE_DEBUG ((LM_DEBUG,"Unknown option\n")); + return -1; + break; + } + } + return 0; +} + +FILE * +Client::file (void) +{ + return this->fp_; +} + +char* +Client::flowname (void) +{ + return this->flowname_; +} + +TAO_StreamCtrl* +Client::streamctrl (void) +{ + return &this->streamctrl_; +} + +Client::Client (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + endpoint_strategy_ (orb_manager_,this), + client_mmdevice_ (&endpoint_strategy_), + fp_ (0), + protocol_ (ACE_OS::strdup ("UDP")) +{ +} + + +int +Client::bind_to_server (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + // Initialize the naming services + if (my_naming_client_.init (this->orb_manager_->orb ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice"); + CORBA::Object_var server_mmdevice_obj = + my_naming_client_->resolve (server_mmdevice_name, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + this->server_mmdevice_ = + AVStreams::MMDevice::_narrow (server_mmdevice_obj.in (), + ACE_TRY_ENV); + ACE_TRY_CHECK; + + if (CORBA::is_nil (this->server_mmdevice_.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " could not resolve Server_Mmdevice in Naming service <%s>\n"), + -1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Command_Handler::resolve_reference"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::init (int argc,char **argv) +{ + this->argc_ = argc; + this->argv_ = argv; + + // Increase the debug_level so that we can see the output + // TAO_debug_level++; + CORBA::String_var ior; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // @@ Pass the ORB as an argument to the init. + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = TAO_AV_CORE::instance ()->orb_manager (); + this->orb_manager_->init_child_poa (argc, + argv, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->parse_args (argc, argv); + // activate the client video mmdevice under the child poa. + ior = this->orb_manager_->activate (&this->client_mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Initialize the naming services + CORBA::ORB_var orb = orb_manager_->orb (); + if (this->my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + this->fp_ = ACE_OS::fopen (this->filename_,"r"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + if (this->bind_to_server () == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Error binding to the naming service\n"), + -1); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Client::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + char flow_protocol_str [BUFSIZ]; + if (this->use_sfp_) + ACE_OS::strcpy (flow_protocol_str,"sfp:1.0"); + else + ACE_OS::strcpy (flow_protocol_str,""); + AVStreams::streamQoS_var the_qos (new AVStreams::streamQoS); + AVStreams::flowSpec flow_spec (1); + // Bind the client and server mmdevices. + + this->orb_manager_->activate_poa_manager (ACE_TRY_ENV); + ACE_TRY_CHECK; + ACE_INET_Addr addr (this->address_); + ACE_NEW_RETURN (this->flowname_, + char [BUFSIZ], + 0); + ACE_OS::sprintf (this->flowname_, + "Data_%s", + this->protocol_); + TAO_Forward_FlowSpec_Entry entry (this->flowname_, + "IN", + "USER_DEFINED", + flow_protocol_str, + this->protocol_, + &addr); + flow_spec [0] = entry.entry_to_string (); + flow_spec.length (1); + ACE_High_Res_Timer timer; + ACE_Time_Value elapsed; + timer.start (); + CORBA::Boolean result = + this->streamctrl_.bind_devs (this->client_mmdevice_._this (ACE_TRY_ENV), + this->server_mmdevice_.in (), + the_qos.inout (), + flow_spec, + ACE_TRY_ENV); + timer.stop (); + timer.elapsed_time (elapsed); + elapsed.dump (); + // If we're supposed to do only bind_devs time calculation return. + if (this->test_) + { + AVStreams::flowSpec flow_spec; + this->streamctrl_.destroy (flow_spec,ACE_TRY_ENV); + ACE_TRY_CHECK; + return 0; + } + ACE_TRY_CHECK; + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"streamctrl::bind_devs failed\n"),-1); + AVStreams::flowSpec start_spec (1); + start_spec.length (1); + start_spec [0] = CORBA::string_dup (this->flowname_); + this->streamctrl_.start (start_spec,ACE_TRY_ENV); + ACE_TRY_CHECK; + // Schedule a timer for the for the flow handler. + TAO_AV_CORE::instance ()->run (); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Client::run"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +main (int argc, + char **argv) +{ + int result = 0; + result = CLIENT::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::init failed\n"),1); + result = CLIENT::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"client::run failed\n"),1); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Client,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Client,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Pluggable/ftp.h b/TAO/orbsvcs/tests/AVStreams/Pluggable/ftp.h new file mode 100644 index 00000000000..707ed7b8225 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Pluggable/ftp.h @@ -0,0 +1,99 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef TAO_AV_FTP_H +#define TAO_AV_FTP_H + +#include "ace/Get_Opt.h" +#include "tao/TAO.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/FlowSpec_Entry.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" +#include "ace/High_Res_Timer.h" + +class FTP_Client_Callback : public TAO_AV_Callback +{ +public: + FTP_Client_Callback (void); + virtual int handle_timeout (void *arg); + virtual int handle_destroy (void); + virtual void get_timeout (ACE_Time_Value *&tv, + void *&arg); + void set_protocol_object (TAO_AV_Protocol_Object *protocol_object) {this->protocol_object_ = protocol_object;} +protected: + int count_; + TAO_AV_Protocol_Object *protocol_object_; +}; + +class FTP_Client_StreamEndPoint : public TAO_Client_StreamEndPoint +{ +public: + FTP_Client_StreamEndPoint (TAO_ORB_Manager *orb_manager = 0); + + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); + + virtual int set_protocol_object (const char *flowname, + TAO_AV_Protocol_Object *object); +protected: + TAO_ORB_Manager *orb_manager_; + FTP_Client_Callback *callback_; +}; + +typedef TAO_AV_Endpoint_Reactive_Strategy_A<FTP_Client_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> ENDPOINT_STRATEGY; + +class Client; +class Endpoint_Reactive_Strategy : public ENDPOINT_STRATEGY +{ +public: + Endpoint_Reactive_Strategy (TAO_ORB_Manager *orb_manager, + Client *client_ptr); + // constructor . The orb manager is needed for the TAO_AV_Endpoint_Reactive_Strategy_A. + + virtual int make_stream_endpoint (FTP_Client_StreamEndPoint *& endpoint); + // hook to make our streamendpoint taking a Client pointer +private: + Client *client_; + // pointer to command handler object + TAO_ORB_Manager *orb_manager_; +}; + + +class Client +{ +public: + Client (void); + int init (int argc, char **argv); + int run (void); + FILE *file (void); + char *flowname (void); + TAO_StreamCtrl* streamctrl (void); +private: + int parse_args (int argc, char **argv); + int bind_to_server (void); + TAO_ORB_Manager *orb_manager_; + Endpoint_Reactive_Strategy endpoint_strategy_; + AVStreams::MMDevice_var server_mmdevice_; + TAO_MMDevice client_mmdevice_; + TAO_StreamCtrl streamctrl_; + // Video stream controller + + int argc_; + char **argv_; + const char *filename_; + const char *address_; + + TAO_Naming_Client my_naming_client_; + FILE *fp_; + char *protocol_; + char *flowname_; + int use_sfp_; + int test_; +}; + +typedef ACE_Singleton<Client,ACE_Null_Mutex> CLIENT; + +#endif /* TAO_AV_FTP_H */ diff --git a/TAO/orbsvcs/tests/AVStreams/Pluggable/server.cpp b/TAO/orbsvcs/tests/AVStreams/Pluggable/server.cpp new file mode 100644 index 00000000000..1d572be057b --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Pluggable/server.cpp @@ -0,0 +1,205 @@ +// $Id$ + +#include "server.h" + +FTP_Server_StreamEndPoint::FTP_Server_StreamEndPoint (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_StreamEndPoint::FTP_Server_StreamEndPoint")); +} + +int +FTP_Server_StreamEndPoint::get_callback (const char *flowname, + TAO_AV_Callback *&callback) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_StreamEndPoint::get_sfp_callback\n")); + ACE_NEW_RETURN (callback, + FTP_Server_Callback, + -1); + return 0; +} + +int +FTP_Server_Callback::handle_stop (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::stop")); + ACE_OS::fclose (SERVER::instance ()->file ()); + return 0; +} + +int +FTP_Server_Callback::receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *, + const ACE_Addr &) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_Server_Callback::receive_frame\n")); + while (frame != 0) + { + int result = ACE_OS::fwrite (frame->rd_ptr (), + frame->length (), + 1, + SERVER::instance ()->file ()); + if (result == 0) + ACE_ERROR_RETURN ((LM_ERROR,"FTP_Server_Flow_Handler::fwrite failed\n"),-1); + frame = frame->cont (); + } + return 0; +} + +int +FTP_Server_Callback::handle_destroy (void) +{ + ACE_DEBUG ((LM_DEBUG,"FTP_SFP_Callback::end_stream\n")); + TAO_AV_CORE::instance ()->stop_run (); + return 0; +} + +Server::Server (void) + :orb_manager_ (TAO_AV_CORE::instance ()->orb_manager ()), + reactive_strategy_ (orb_manager_) +{ +} + +int +Server::init (int argc, + char **argv) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->init (argc, + argv, + ACE_TRY_ENV); + ACE_TRY_CHECK; + this->orb_manager_ = + TAO_AV_CORE::instance ()->orb_manager (); + + // Initialize the orb_manager + this->orb_manager_->init_child_poa (argc, + argv, + "child_poa", + ACE_TRY_ENV); + ACE_TRY_CHECK; + + CORBA::ORB_var orb = + this->orb_manager_->orb (); + + PortableServer::POA_var child_poa = + this->orb_manager_->child_poa (); + + + int result = this->parse_args (argc,argv); + if (result == -1) + ACE_ERROR_RETURN ((LM_ERROR,"parse args failed\n"),-1); + // Initialize the naming services + + if (my_naming_client_.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + // Register the video mmdevice object with the ORB + ACE_NEW_RETURN (this->mmdevice_, + TAO_MMDevice (&this->reactive_strategy_), + -1); + // create the video server mmdevice with the naming service pointer. + this->orb_manager_->activate_under_child_poa ("Server_MMDevice", + this->mmdevice_, + ACE_TRY_ENV); + ACE_TRY_CHECK; + + // Register the mmdevice with the naming service. + CosNaming::Name server_mmdevice_name (1); + server_mmdevice_name.length (1); + server_mmdevice_name [0].id = CORBA::string_dup ("Server_MMDevice"); + + // Register the video control object with the naming server. + this->my_naming_client_->rebind (server_mmdevice_name, + this->mmdevice_->_this (ACE_TRY_ENV), + ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + TAO_AV_CORE::instance ()->run (); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"server::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +Server::parse_args (int argc,char **argv) +{ + ACE_Get_Opt opts (argc,argv,"f:p:"); + + char c; + while ((c = opts ()) != -1) + { + switch (c) + { + case 'f': + this->fp_ = ACE_OS::fopen (opts.optarg,"w"); + if (this->fp_ != 0) + { + ACE_DEBUG ((LM_DEBUG,"file opened successfully\n")); + } + break; + case 'p': + this->protocol_ = ACE_OS::strdup (opts.optarg); + default: + ACE_ERROR_RETURN ((LM_ERROR,"Usage: server -f filename"),-1); + break; + } + } + return 0; +} + +FILE* +Server::file (void) +{ + return this->fp_; +} + +int +main (int argc, + char **argv) +{ + int result = 0; + result = SERVER::instance ()->init (argc,argv); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::init failed\n"),1); + result = SERVER::instance ()->run (); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR,"SERVER::run failed\n"),1); +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton <Server,ACE_Null_Mutex>; +template class TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +template class TAO_AV_Endpoint_Reactive_Strategy <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton <Server,ACE_Null_Mutex> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#pragma instantiate TAO_AV_Endpoint_Reactive_Strategy <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/AVStreams/Pluggable/server.h b/TAO/orbsvcs/tests/AVStreams/Pluggable/server.h new file mode 100644 index 00000000000..a836cc14e32 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/Pluggable/server.h @@ -0,0 +1,52 @@ +/* -*- C++ -*- */ +// $Id$ + +#include "ace/Get_Opt.h" +#include "tao/TAO.h" +#include "orbsvcs/Naming/Naming_Utils.h" +#include "orbsvcs/AV/AVStreams_i.h" +#include "orbsvcs/AV/Endpoint_Strategy.h" +#include "orbsvcs/AV/FlowSpec_Entry.h" +#include "orbsvcs/AV/sfp.h" +#include "orbsvcs/AV/MCast.h" +#include "orbsvcs/AV/Policy.h" + +class FTP_Server_StreamEndPoint + :public TAO_Server_StreamEndPoint +{ +public: + FTP_Server_StreamEndPoint (void); + virtual int get_callback (const char *flowname, + TAO_AV_Callback *&callback); +}; + +class FTP_Server_Callback + :public TAO_AV_Callback +{ +public: + virtual int handle_stop (void); + virtual int receive_frame (ACE_Message_Block *frame, + TAO_AV_frame_info *frame_info = 0, + const ACE_Addr &peer_address = ACE_Addr::sap_any); + virtual int handle_destroy (void); +}; + +class Server +{ +public: + Server (void); + int init (int argc, + char **argv); + int run (void); + FILE *file (void); +protected: + int parse_args (int argc,char **argv); + TAO_ORB_Manager *orb_manager_; + TAO_Naming_Client my_naming_client_; + TAO_AV_Endpoint_Reactive_Strategy_B <FTP_Server_StreamEndPoint,TAO_VDev,AV_Null_MediaCtrl> reactive_strategy_; + TAO_MMDevice *mmdevice_; + FILE *fp_; + char *protocol_; +}; + +typedef ACE_Singleton<Server,ACE_Null_Mutex> SERVER; |