Separated data and connect related features in a CallEndpoint class.

git-svn-id: http://voip.null.ro/svn/yate@312 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2005-04-25 22:19:54 +00:00
parent c58d8e8b7a
commit a1160d84f6
3 changed files with 290 additions and 239 deletions

View File

@ -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<DataEndpoint*>(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<CallEndpoint*>(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<DataEndpoint*>(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<DataEndpoint*>(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<DataEndpoint*>(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<DataEndpoint*>(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<Channel*>(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<DataEndpoint*>(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<DataEndpoint*>(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<DataEndpoint*>(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 },

View File

@ -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();

View File

@ -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
};