diff --git a/engine/Channel.cpp b/engine/Channel.cpp index 02d84568..018980b9 100644 --- a/engine/Channel.cpp +++ b/engine/Channel.cpp @@ -27,14 +27,148 @@ using namespace TelEngine; +CallEndpoint::CallEndpoint(const char* id) + : m_peer(0), m_id(id) +{ +} + +CallEndpoint::~CallEndpoint() +{ +#ifdef DEBUG + ObjList* l = m_data.skipNull(); + for (; l; l=l->skipNext()) { + DataEndpoint* e = static_cast(l->get()); + Debug(DebugAll,"Endpoint at %p type '%s' refcount=%d",e,e->name().c_str(),e->refcount()); + } +#endif + disconnect(true,0); + m_data.clear(); +} + +void* CallEndpoint::getObject(const String& name) const +{ + if (name == "CallEndpoint") + return const_cast(this); + return RefObject::getObject(name); +} + +bool CallEndpoint::connect(CallEndpoint* peer) +{ + if (!peer) { + disconnect(); + return false; + } + if (peer == m_peer) + return true; + DDebug(DebugInfo,"CallEndpoint '%s' connecting peer %p to [%p]",m_id.c_str(),peer,this); + + ref(); + disconnect(); + peer->ref(); + peer->disconnect(); + + ObjList* l = m_data.skipNull(); + for (; l; l=l->skipNext()) { + DataEndpoint* e = static_cast(l->get()); + e->connect(peer->getEndpoint(e->name())); + } + + m_peer = peer; + peer->setPeer(this); + connected(); + + return true; +} + +void CallEndpoint::disconnect(bool final, const char* reason) +{ + if (!m_peer) + return; + DDebug(DebugInfo,"CallEndpoint '%s' disconnecting peer %p from [%p]",m_id.c_str(),m_peer,this); + + CallEndpoint *temp = m_peer; + m_peer = 0; + + ObjList* l = m_data.skipNull(); + for (; l; l=l->skipNext()) { + DataEndpoint* e = static_cast(l->get()); + DDebug(DebugAll,"Endpoint at %p type '%s' peer %p",e,e->name().c_str(),e->getPeer()); + e->disconnect(); + } + + temp->setPeer(0,reason); + temp->deref(); + + disconnected(final,reason); + deref(); +} + +void CallEndpoint::setPeer(CallEndpoint* peer, const char* reason) +{ + m_peer = peer; + if (m_peer) + connected(); + else + disconnected(false,reason); +} + +DataEndpoint* CallEndpoint::getEndpoint(const char* type) const +{ + if (null(type)) + return 0; + const ObjList* pos = m_data.find(type); + return pos ? static_cast(pos->get()) : 0; +} + +DataEndpoint* CallEndpoint::setEndpoint(const char* type) +{ + if (null(type)) + return 0; + DataEndpoint* dat = getEndpoint(type); + if (!dat) { + dat = new DataEndpoint(this,type); + if (m_peer) + dat->connect(m_peer->getEndpoint(type)); + } + return dat; +} + +void CallEndpoint::setSource(DataSource* source, const char* type) +{ + DataEndpoint* dat = source ? setEndpoint(type) : getEndpoint(type); + if (dat) + dat->setSource(source); +} + +DataSource* CallEndpoint::getSource(const char* type) const +{ + DataEndpoint* dat = getEndpoint(type); + return dat ? dat->getSource() : 0; +} + +void CallEndpoint::setConsumer(DataConsumer* consumer, const char* type) +{ + DataEndpoint* dat = consumer ? setEndpoint(type) : getEndpoint(type); + if (dat) + dat->setConsumer(consumer); +} + +DataConsumer* CallEndpoint::getConsumer(const char* type) const +{ + DataEndpoint* dat = getEndpoint(type); + return dat ? dat->getConsumer() : 0; +} + Channel::Channel(Driver* driver, const char* id, bool outgoing) - : m_peer(0), m_driver(driver), m_outgoing(outgoing), m_id(id) + : CallEndpoint(id), + m_driver(driver), m_outgoing(outgoing) { init(); } Channel::Channel(Driver& driver, const char* id, bool outgoing) - : m_peer(0), m_driver(&driver), m_outgoing(outgoing), m_id(id) + : CallEndpoint(id), + m_driver(&driver), m_outgoing(outgoing) { init(); } @@ -52,22 +186,13 @@ Channel::~Channel() m_driver->unlock(); m_driver = 0; } -#ifdef DEBUG - ObjList* l = m_data.skipNull(); - for (; l; l=l->skipNext()) { - DataEndpoint* e = static_cast(l->get()); - Debug(DebugAll,"Endpoint at %p type '%s' refcount=%d",e,e->name().c_str(),e->refcount()); - } -#endif - disconnect(true,0); - m_data.clear(); } void* Channel::getObject(const String& name) const { if (name == "Channel") return const_cast(this); - return RefObject::getObject(name); + return CallEndpoint::getObject(name); } void Channel::init() @@ -90,66 +215,6 @@ const char* Channel::direction() const return m_outgoing ? "outgoing" : "incoming"; } -bool Channel::connect(Channel* peer) -{ - if (!peer) { - disconnect(); - return false; - } - if (peer == m_peer) - return true; - DDebug(DebugInfo,"Channel '%s' connecting peer %p to [%p]",m_id.c_str(),peer,this); - - ref(); - disconnect(); - peer->ref(); - peer->disconnect(); - - ObjList* l = m_data.skipNull(); - for (; l; l=l->skipNext()) { - DataEndpoint* e = static_cast(l->get()); - e->connect(peer->getEndpoint(e->name())); - } - - m_peer = peer; - peer->setPeer(this); - connected(); - - return true; -} - -void Channel::disconnect(bool final, const char* reason) -{ - if (!m_peer) - return; - DDebug(DebugInfo,"Channel '%s' disconnecting peer %p from [%p]",m_id.c_str(),m_peer,this); - - Channel *temp = m_peer; - m_peer = 0; - - ObjList* l = m_data.skipNull(); - for (; l; l=l->skipNext()) { - DataEndpoint* e = static_cast(l->get()); - DDebug(DebugAll,"Endpoint at %p type '%s' peer %p",e,e->name().c_str(),e->getPeer()); - e->disconnect(); - } - - temp->setPeer(0,reason); - temp->deref(); - - disconnected(final,reason); - deref(); -} - -void Channel::setPeer(Channel* peer, const char* reason) -{ - m_peer = peer; - if (m_peer) - connected(); - else - disconnected(false,reason); -} - void Channel::complete(Message& msg, bool minimal) const { msg.setParam("id",m_id); @@ -167,8 +232,8 @@ void Channel::complete(Message& msg, bool minimal) const msg.setParam("targetid",m_targetid); if (m_billid) msg.setParam("billid",m_billid); - if (m_peer) - msg.setParam("peerid",m_peer->id()); + if (getPeer()) + msg.setParam("peerid",getPeer()->id()); } Message* Channel::message(const char* name, bool minimal) const @@ -265,53 +330,6 @@ bool Channel::setDebug(Message& msg) return true; } -DataEndpoint* Channel::getEndpoint(const char* type) const -{ - if (null(type)) - return 0; - const ObjList* pos = m_data.find(type); - return pos ? static_cast(pos->get()) : 0; -} - -DataEndpoint* Channel::setEndpoint(const char* type) -{ - if (null(type)) - return 0; - DataEndpoint* dat = getEndpoint(type); - if (!dat) { - dat = new DataEndpoint(this,type); - if (m_peer) - dat->connect(m_peer->getEndpoint(type)); - } - return dat; -} - -void Channel::setSource(DataSource* source, const char* type) -{ - DataEndpoint* dat = source ? setEndpoint(type) : getEndpoint(type); - if (dat) - dat->setSource(source); -} - -DataSource* Channel::getSource(const char* type) const -{ - DataEndpoint* dat = getEndpoint(type); - return dat ? dat->getSource() : 0; -} - -void Channel::setConsumer(DataConsumer* consumer, const char* type) -{ - DataEndpoint* dat = consumer ? setEndpoint(type) : getEndpoint(type); - if (dat) - dat->setConsumer(consumer); -} - -DataConsumer* Channel::getConsumer(const char* type) const -{ - DataEndpoint* dat = getEndpoint(type); - return dat ? dat->getConsumer() : 0; -} - TokenDict Module::s_messages[] = { { "engine.status", Module::Status }, diff --git a/engine/DataFormat.cpp b/engine/DataFormat.cpp index acca9863..c9770048 100644 --- a/engine/DataFormat.cpp +++ b/engine/DataFormat.cpp @@ -232,20 +232,20 @@ void* DataSource::getObject(const String& name) const return DataNode::getObject(name); } -DataEndpoint::DataEndpoint(Channel* chan, const char* name) - : m_name(name), m_source(0), m_consumer(0), m_peer(0), m_channel(chan) +DataEndpoint::DataEndpoint(CallEndpoint* call, const char* name) + : m_name(name), m_source(0), m_consumer(0), m_peer(0), m_call(call) { - Debug(DebugInfo,"DataEndpoint::DataEndpoint(%p,'%s') [%p]",chan,name,this); - if (m_channel) - m_channel->m_data.append(this); + Debug(DebugInfo,"DataEndpoint::DataEndpoint(%p,'%s') [%p]",call,name,this); + if (m_call) + m_call->m_data.append(this); } DataEndpoint::~DataEndpoint() { - Debug(DebugInfo,"DataEndpoint::~DataEndpoint() '%s' chan=%p [%p]", - m_name.c_str(),m_channel,this); - if (m_channel) - m_channel->m_data.remove(this,false); + Debug(DebugInfo,"DataEndpoint::~DataEndpoint() '%s' call=%p [%p]", + m_name.c_str(),m_call,this); + if (m_call) + m_call->m_data.remove(this,false); disconnect(); setSource(); setConsumer(); diff --git a/yatephone.h b/yatephone.h index 033962f0..8a78c864 100644 --- a/yatephone.h +++ b/yatephone.h @@ -116,7 +116,7 @@ struct FormatInfo { { } }; -class Channel; +class CallEndpoint; class Driver; /** @@ -602,7 +602,7 @@ public: /** * Creates an empty data endpoint */ - DataEndpoint(Channel* chan = 0, const char* name = "audio"); + DataEndpoint(CallEndpoint* call = 0, const char* name = "audio"); /** * Destroys the endpoint, source and consumer @@ -668,11 +668,11 @@ public: { return m_peer; } /* - * Get a pointer to the owner channel - * @return A pointer to the owner channel or NULL + * Get a pointer to the owner call + * @return A pointer to the owner call or NULL */ - inline Channel* getChannel() const - { return m_channel; } + inline CallEndpoint* getCall() const + { return m_call; } /** * Get the name set in constructor @@ -695,7 +695,141 @@ private: DataSource* m_source; DataConsumer* m_consumer; DataEndpoint* m_peer; - Channel* m_channel; + CallEndpoint* m_call; +}; + +/** + * A class that holds common call control and data related features + * @short An abstract call endpoint + */ +class YATE_API CallEndpoint : public RefObject +{ + friend class DataEndpoint; + +private: + CallEndpoint* m_peer; + +protected: + ObjList m_data; + String m_id; + +public: + /** + * Destructor + */ + virtual ~CallEndpoint(); + + /** + * Get a pointer to a derived class given that class name + * @param name Name of the class we are asking for + * @return Pointer to the requested class or NULL if this object doesn't implement it + */ + virtual void* getObject(const String& name) const; + + /** + * Get a string representation of this channel + * @return A reference to the name of this object + */ + virtual const String& toString() const + { return m_id; } + + /** + * Get the unique channel identifier + * @return A String holding the unique channel id + */ + inline const String& id() const + { return m_id; } + + /** + * Get the connected peer call + * @return Pointer to connected peer call or NULL + */ + inline CallEndpoint* getPeer() const + { return m_peer; } + + /** + * Connect the call endpoint to a peer. + * @param peer Pointer to the peer call endpoint. + * @return True if connected, false if an error occured. + */ + bool connect(CallEndpoint* peer); + + /** + * Disconnect from the connected peer call endpoint. + * @param reason Text that describes disconnect reason. + */ + inline void disconnect(const char* reason = 0) + { disconnect(false,reason); } + + /** + * Get a data endpoint of this object + * @param type Type of data endpoint: "audio", "video", "text" + * @return A pointer to the DataEndpoint object or NULL if not found + */ + DataEndpoint* getEndpoint(const char* type = "audio") const; + + /** + * Get a data endpoint of this object, create if required + * @param type Type of data endpoint: "audio", "video", "text" + * @return A pointer to the DataEndpoint object or NULL if an error occured + */ + DataEndpoint* setEndpoint(const char* type = "audio"); + + /** + * Set a data source of this object + * @param source A pointer to the new source or NULL + * @param type Type of data node: "audio", "video", "text" + */ + void setSource(DataSource* source = 0, const char* type = "audio"); + + /** + * Get a data source of this object + * @param type Type of data node: "audio", "video", "text" + * @return A pointer to the DataSource object or NULL + */ + DataSource* getSource(const char* type = "audio") const; + + /** + * Set the data consumer of this object + * @param consumer A pointer to the new consumer or NULL + * @param type Type of data node: "audio", "video", "text" + */ + void setConsumer(DataConsumer* consumer = 0, const char* type = "audio"); + + /** + * Get the data consumer of this object + * @param type Type of data node: "audio", "video", "text" + * @return A pointer to the DataConsumer object or NULL + */ + DataConsumer* getConsumer(const char* type = "audio") const; + +protected: + /** + * Constructor + */ + CallEndpoint(const char* id = 0); + + /** + * Connect notification method. + */ + virtual void connected() { } + + /** + * Disconnect notification method. + * @param final True if this disconnect was called from the destructor. + * @param reason Text that describes disconnect reason. + */ + virtual void disconnected(bool final, const char* reason) { } + + /* + * Set the peer call endpoint pointer. + * @param peer A pointer to the new peer or NULL. + * @param reason Text describing the reason in case of disconnect. + */ + void setPeer(CallEndpoint* peer, const char* reason = 0); + +private: + void disconnect(bool final, const char* reason); }; /** @@ -878,24 +1012,20 @@ private: * A class that holds common channel related features (a.k.a. call leg) * @short An abstract communication channel */ -class YATE_API Channel : public RefObject, public DebugEnabler +class YATE_API Channel : public CallEndpoint, public DebugEnabler { friend class Driver; friend class Router; - friend class DataEndpoint; private: - Channel* m_peer; Driver* m_driver; bool m_outgoing; - String m_id; protected: String m_status; String m_address; String m_targetid; String m_billid; - ObjList m_data; public: /** @@ -910,13 +1040,6 @@ public: */ virtual void* getObject(const String& name) const; - /** - * Get a string representation of this channel - * @return A reference to the name of this object - */ - virtual const String& toString() const - { return m_id; } - /** * Put channel variables into a message * @param msg Message to fill in @@ -1037,13 +1160,6 @@ public: inline Driver* driver() const { return m_driver; } - /** - * Get the unique channel identifier - * @return A String holding the unique channel id - */ - inline const String& id() const - { return m_id; } - /** * Get the connected channel identifier. * @return A String holding the unique channel id of the target or an empty @@ -1060,27 +1176,6 @@ public: inline const String& billid() const { return m_billid; } - /** - * Get the connected peer channel - * @return Pointer to connected peer channel or NULL - */ - inline Channel* getPeer() const - { return m_peer; } - - /** - * Connect the channel to a peer. - * @param peer Pointer to the peer channel. - * @return True if connected, false if an error occured. - */ - bool connect(Channel* peer); - - /** - * Disconnect from the connected peer channel. - * @param reason Text that describes disconnect reason. - */ - inline void disconnect(const char* reason = 0) - { disconnect(false,reason); } - /** * Start a routing thread for this channel, dereference dynamic channels * @param msg Pointer to message to route, typically a "call.route", will be @@ -1089,48 +1184,6 @@ public: */ bool startRouter(Message* msg); - /** - * Get a data endpoint of this object - * @param type Type of data endpoint: "audio", "video", "text" - * @return A pointer to the DataEndpoint object or NULL if not found - */ - DataEndpoint* getEndpoint(const char* type = "audio") const; - - /** - * Get a data endpoint of this object, create if required - * @param type Type of data endpoint: "audio", "video", "text" - * @return A pointer to the DataEndpoint object or NULL if an error occured - */ - DataEndpoint* setEndpoint(const char* type = "audio"); - - /** - * Set a data source of this object - * @param source A pointer to the new source or NULL - * @param type Type of data node: "audio", "video", "text" - */ - void setSource(DataSource* source = 0, const char* type = "audio"); - - /** - * Get a data source of this object - * @param type Type of data node: "audio", "video", "text" - * @return A pointer to the DataSource object or NULL - */ - DataSource* getSource(const char* type = "audio") const; - - /** - * Set the data consumer of this object - * @param consumer A pointer to the new consumer or NULL - * @param type Type of data node: "audio", "video", "text" - */ - void setConsumer(DataConsumer* consumer = 0, const char* type = "audio"); - - /** - * Get the data consumer of this object - * @param type Type of data node: "audio", "video", "text" - * @return A pointer to the DataConsumer object or NULL - */ - DataConsumer* getConsumer(const char* type = "audio") const; - protected: /** * Constructor @@ -1156,28 +1209,8 @@ protected: inline void setOutgoing(bool outgoing = true) { m_outgoing = outgoing; } - /** - * Connect notification method. - */ - virtual void connected() { } - - /** - * Disconnect notification method. - * @param final True if this disconnect was called from the destructor. - * @param reason Text that describes disconnect reason. - */ - virtual void disconnected(bool final, const char* reason) { } - - /* - * Set the peer channel pointer. - * @param peer A pointer to the new peer or NULL. - * @param reason Text describing the reason in case of disconnect. - */ - void setPeer(Channel* peer, const char* reason = 0); - private: void init(); - void disconnect(bool final, const char* reason); Channel(); // no default constructor please };