Removed client stream useless class. Added more stanza types and namespaces.

git-svn-id: http://yate.null.ro/svn/yate/trunk@1726 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2008-02-14 11:52:26 +00:00
parent 73a496ae0b
commit f87630067c
7 changed files with 213 additions and 236 deletions

View File

@ -408,6 +408,7 @@ void JBEngine::cleanup()
for (ObjList* o = m_streams.skipNull(); o; o = o->skipNext()) {
JBStream* s = static_cast<JBStream*>(o->get());
s->terminate(true,0,XMPPError::Shutdown,0,true);
s->cleanup();
}
}
@ -446,10 +447,7 @@ JBStream* JBEngine::getStream(const JabberID* jid, bool create, const char* pwd)
const JabberID* remote = jid;
// Set remote to be a valid pointer
if (!remote)
if (m_protocol == Component)
remote = &m_componentDomain;
else
return 0;
remote = &m_componentDomain;
// Find the stream
JBStream* stream = 0;
for (ObjList* o = m_streams.skipNull(); o; o = o->skipNext()) {
@ -469,12 +467,9 @@ JBStream* JBEngine::getStream(const JabberID* jid, bool create, const char* pwd)
SocketAddr addr(PF_INET);
addr.host(info->address());
addr.port(info->port());
if (m_protocol == Component)
stream = new JBComponentStream(this,JabberID(0,info->identity(),0),
*remote,info->password(),addr,
true,m_restartCount,m_restartUpdateInterval);
else
stream = new JBClientStream(this,*jid,pwd,addr,m_restartCount,m_restartUpdateInterval);
stream = new JBComponentStream(this,JabberID(0,info->identity(),0),
*remote,info->password(),addr,
info->autoRestart(),m_restartCount,m_restartUpdateInterval);
m_streams.append(stream);
}
return ((stream && stream->ref()) ? stream : 0);

View File

@ -25,7 +25,7 @@
using namespace TelEngine;
static XMPPNamespace s_ns;
static XMPPNamespace s_ns; // Just use the operators
static XMPPError s_err;
static TokenDict s_streamState[] = {
@ -39,10 +39,13 @@ static TokenDict s_streamState[] = {
{0,0},
};
static String s_version = "1.0"; // Protocol version
/**
* JBSocket
*/
// Connect the socket
bool JBSocket::connect(const SocketAddr& addr, bool& terminated)
{
terminate();
@ -82,6 +85,7 @@ bool JBSocket::connect(const SocketAddr& addr, bool& terminated)
return ok;
}
// Close the socket
void JBSocket::terminate()
{
Lock2 lck(m_streamMutex,m_receiveMutex);
@ -94,6 +98,7 @@ void JBSocket::terminate()
}
}
// Read data from socket
bool JBSocket::recv(char* buffer, unsigned int& len)
{
if (!valid())
@ -122,6 +127,7 @@ bool JBSocket::recv(char* buffer, unsigned int& len)
return true;
}
// Write data to socket
bool JBSocket::send(const char* buffer, unsigned int& len)
{
if (!valid())
@ -230,22 +236,21 @@ void JBStream::connect()
"Stream. Attempt to connect local=%s remote=%s addr=%s:%d count=%u [%p]",
m_local.safe(),m_remote.safe(),m_address.host().safe(),m_address.port(),
m_restart,this);
changeState(Connecting);
// Check if we can restart
if (!m_restart) {
terminate(true,0,XMPPError::NoError,"restart counter is 0",false);
// Check if we can restart. Destroy the stream if not auto restarting
if (m_restart)
m_restart--;
else
return;
}
m_restart--;
// Reset data
m_id = "";
m_parser.reset();
lck.drop();
// Re-connect socket
bool terminated = false;
changeState(Connecting);
if (!m_socket.connect(m_address,terminated)) {
if (!terminated)
terminate(false,0,XMPPError::NoError,"connection failed",false);
terminate(false,0,XMPPError::NoError,"connection-failed",false);
return;
}
@ -253,7 +258,8 @@ void JBStream::connect()
m_local.safe(),m_remote.safe(),m_address.host().safe(),m_address.port(),this);
// Send declaration
static String declaration = "<?xml version='1.0' encoding='UTF-8'?>";
String declaration;
declaration << "<?xml version='" << s_version << "' encoding='UTF-8'?>";
if (m_engine->printXml() && m_engine->debugAt(DebugInfo))
Debug(m_engine,DebugInfo,"Stream. Sending XML declaration %s [%p]",
declaration.c_str(),this);
@ -325,26 +331,43 @@ JBEvent* JBStream::getEvent(u_int64_t time)
{
Lock lock(m_socket.m_streamMutex);
// Do nothing if destroying or connecting
if (state() == Destroy || state() == Connecting)
return 0;
// Increase stream restart counter if it's time to
if (m_timeToFillRestart < time) {
if (m_restart < m_restartMax)
if (m_restart < m_restartMax) {
m_restart++;
Debug(m_engine,DebugAll,"Stream. restart count=%u max=%u [%p]",
m_restart,m_restartMax,this);
}
m_timeToFillRestart = time + m_fillRestartInterval;
}
if (state() == Idle) {
if (m_autoRestart && m_restart)
m_engine->connect(this);
return 0;
}
if (m_lastEvent)
return 0;
// Do nothing if destroying or connecting
// Just check Terminated or Running events
// Idle: check if we can restart. Destroy the stream if not auto restarting
if (state() == Idle || state() == Destroy || state() == Connecting) {
if (state() == Idle) {
if (m_restart && m_autoRestart) {
lock.drop();
m_engine->connect(this);
return 0;
}
if (!m_autoRestart)
terminate(true,0,XMPPError::NoError,"connection-failed",false);
}
if (m_terminateEvent) {
m_lastEvent = m_terminateEvent;
m_terminateEvent = 0;
}
else if (m_startEvent) {
m_lastEvent = m_startEvent;
m_startEvent = 0;
}
return m_lastEvent;
}
while (true) {
if (m_terminateEvent)
break;
@ -452,7 +475,7 @@ void JBStream::terminate(bool destroy, XMLElement* recvStanza, XMPPError::Type e
const char* reason, bool send, bool final)
{
Lock2 lock(m_socket.m_streamMutex,m_socket.m_receiveMutex);
if (state() == Destroy || state() == Idle) {
if (state() == Destroy) {
if (recvStanza)
delete recvStanza;
return;
@ -463,11 +486,11 @@ void JBStream::terminate(bool destroy, XMLElement* recvStanza, XMPPError::Type e
}
Debug(m_engine,DebugAll,
"Stream. Terminate state=%s destroy=%u error=%s reason=%s final=%u [%p]",
"Stream. Terminate state=%s destroy=%u error=%s reason='%s' final=%u [%p]",
lookupState(state()),destroy,s_err[error],reason,final,this);
// Send ending stream element
if (send && state() != Connecting) {
if (send && state() != Connecting && state() != Idle) {
XMLElement* e;
if (error == XMPPError::NoError)
e = new XMLElement(XMLElement::StreamEnd);
@ -498,14 +521,18 @@ void JBStream::terminate(bool destroy, XMLElement* recvStanza, XMPPError::Type e
removePending(false,0,true);
// Always set termination event, except when exiting
TelEngine::destruct(m_startEvent);
if (!m_terminateEvent) {
if (!(m_terminateEvent || m_engine->exiting())) {
if (!recvStanza && error != XMPPError::NoError)
recvStanza = XMPPUtils::createStreamError(error,reason);
if (error != XMPPError::Shutdown)
m_terminateEvent = new JBEvent(destroy?JBEvent::Destroy:JBEvent::Terminated,
this,recvStanza);
Debug(m_engine,DebugAll,"Stream. Set terminate error=%s reason=%s [%p]",
s_err[error],reason,this);
m_terminateEvent = new JBEvent(destroy?JBEvent::Destroy:JBEvent::Terminated,
this,recvStanza);
if (!recvStanza)
m_terminateEvent->m_text = reason;
recvStanza = 0;
}
else if (recvStanza)
if (recvStanza)
delete recvStanza;
// Change state
@ -886,46 +913,6 @@ void JBStream::removePending(bool notify, const String* id, bool force)
}
/**
* JBClientStream
*/
JBClientStream::JBClientStream(JBEngine* engine, const JabberID& jid,
const String& password, const SocketAddr& address,
unsigned int maxRestart, u_int64_t incRestartInterval, bool outgoing)
: JBStream(engine,jid,JabberID(0,jid.domain(),0),password,address,
true,maxRestart,incRestartInterval,outgoing,JBEngine::Client)
{
}
// Get the starting stream element to be sent after stream connected
XMLElement* JBClientStream::getStreamStart()
{
Debug(engine(),DebugStub,"Please implement JBComponentStream::getStreamStart()");
return 0;
}
// Process a received element in Securing state
void JBClientStream::processSecuring(XMLElement* xml)
{
Debug(engine(),DebugStub,"Please implement JBComponentStream::processSecuring()");
dropXML(xml);
}
// Process a received element in Auth state
void JBClientStream::processAuth(XMLElement* xml)
{
Debug(engine(),DebugStub,"Please implement JBComponentStream::processAuth()");
dropXML(xml);
}
// Process a received element in Started state
void JBClientStream::processStarted(XMLElement* xml)
{
Debug(engine(),DebugStub,"Please implement JBComponentStream::processStarted()");
dropXML(xml);
}
/**
* JBComponentStream
*/

View File

@ -30,29 +30,42 @@ using namespace TelEngine;
* XMLElement
*/
TokenDict XMLElement::s_names[] = {
{"stream:stream", StreamStart},
{"/stream:stream", StreamEnd},
{"stream:error", StreamError},
{"handshake", Handshake},
{"iq", Iq},
{"message", Message},
{"presence", Presence},
{"error", Error},
{"query", Query},
{"session", Jingle},
{"description", Description},
{"payload-type", PayloadType},
{"transport", Transport},
{"candidate", Candidate},
{"body", Body},
{"feature", Feature},
{"bind", Bind},
{"resource", Resource},
{"dtmf", Dtmf},
{"dtmf-method", DtmfMethod},
{"command", Command},
{0,0}
};
{"stream:stream", StreamStart},
{"/stream:stream", StreamEnd},
{"stream:error", StreamError},
{"stream::features", StreamFeatures},
{"starttls", Starttls},
{"handshake", Handshake},
{"auth", Auth},
{"challenge", Challenge},
{"abort", Abort},
{"aborted", Aborted},
{"response", Response},
{"success", Success},
{"failure", Failure},
{"mechanisms", Mechanisms},
{"mechanism", Mechanism},
{"session", Session},
{"iq", Iq},
{"message", Message},
{"presence", Presence},
{"error", Error},
{"query", Query},
{"session", Jingle},
{"description", Description},
{"payload-type", PayloadType},
{"transport", Transport},
{"candidate", Candidate},
{"body", Body},
{"feature", Feature},
{"bind", Bind},
{"resource", Resource},
{"Required", Required},
{"dtmf", Dtmf},
{"dtmf-method", DtmfMethod},
{"command", Command},
{0,0}
};
XMLElement::XMLElement()
: m_type(StreamEnd), m_owner(true), m_element(0)

View File

@ -70,7 +70,19 @@ public:
StreamStart, // stream:stream
StreamEnd, // /stream:stream
StreamError, // stream::error
StreamFeatures, // stream::features
Starttls, // starttls
Handshake, // handshake
Auth, // auth
Challenge, // challenge
Abort, // abort
Aborted, // aborted
Response, // response
Success, // success
Failure, // failure
Mechanisms, // mechanisms
Mechanism, // mechanism
Session, // session
// *** Stanzas
Iq, // iq
Message, // message
@ -92,6 +104,7 @@ public:
Bind, // bind
Resource, // resource
// Miscellanous
Required, // required
Dtmf, // dtmf
DtmfMethod, // dtmf-method
Command, // command

View File

@ -33,23 +33,28 @@ static XMPPError s_err;
* XMPPNamespace
*/
TokenDict XMPPNamespace::s_value[] = {
{"http://etherx.jabber.org/streams", Stream},
{"jabber:component:accept", ComponentAccept},
{"jabber:component:connect", ComponentConnect},
{"urn:ietf:params:xml:ns:xmpp-streams", StreamError},
{"urn:ietf:params:xml:ns:xmpp-stanzas", StanzaError},
{"urn:ietf:params:xml:ns:xmpp-bind", Bind},
{"http://jabber.org/protocol/disco#info", DiscoInfo},
{"http://jabber.org/protocol/disco#items", DiscoItems},
{"http://www.google.com/session", Jingle},
{"http://www.google.com/session/phone", JingleAudio},
{"http://www.google.com/transport/p2p", JingleTransport},
{"http://jabber.org/protocol/jingle/info/dtmf", Dtmf},
{"http://jabber.org/protocol/jingle/info/dtmf#errors", DtmfError},
{"http://jabber.org/protocol/commands", Command},
{"http://www.google.com/xmpp/protocol/voice/v1", CapVoiceV1},
{0,0}
};
{"http://etherx.jabber.org/streams", Stream},
{"jabber:client", Client},
{"jabber:server", Server},
{"jabber:component:accept", ComponentAccept},
{"jabber:component:connect", ComponentConnect},
{"urn:ietf:params:xml:ns:xmpp-streams", StreamError},
{"urn:ietf:params:xml:ns:xmpp-stanzas", StanzaError},
{"urn:ietf:params:xml:ns:xmpp-tls", Starttls},
{"urn:ietf:params:xml:ns:xmpp-sasl", Sasl},
{"urn:ietf:params:xml:ns:xmpp-session", Session},
{"urn:ietf:params:xml:ns:xmpp-bind", Bind},
{"http://jabber.org/protocol/disco#info", DiscoInfo},
{"http://jabber.org/protocol/disco#items", DiscoItems},
{"http://www.google.com/session", Jingle},
{"http://www.google.com/session/phone", JingleAudio},
{"http://www.google.com/transport/p2p", JingleTransport},
{"http://jabber.org/protocol/jingle/info/dtmf", Dtmf},
{"http://jabber.org/protocol/jingle/info/dtmf#errors", DtmfError},
{"http://jabber.org/protocol/commands", Command},
{"http://www.google.com/xmpp/protocol/voice/v1", CapVoiceV1},
{0,0}
};
bool XMPPNamespace::isText(Type index, const char* txt)
{
@ -63,59 +68,59 @@ bool XMPPNamespace::isText(Type index, const char* txt)
* XMPPError
*/
TokenDict XMPPError::s_value[] = {
{"cancel", TypeCancel},
{"continue", TypeContinue},
{"modify", TypeModify},
{"auth", TypeAuth},
{"wait", TypeWait},
{"bad-format", BadFormat},
{"bad-namespace-prefix", BadNamespace},
{"connection-timeout", ConnTimeout},
{"host-gone", HostGone},
{"host-unknown", HostUnknown},
{"improper-addressing", BadAddressing},
{"internal-server-error", Internal},
{"invalid-from", InvalidFrom},
{"invalid-id", InvalidId},
{"invalid-namespace", InvalidNamespace},
{"invalid-xml", InvalidXml},
{"not-authorized", NotAuth},
{"policy-violation", Policy},
{"remote-connection-failed", RemoteConn},
{"resource-constraint", ResConstraint},
{"restricted-xml", RestrictedXml},
{"see-other-host", SeeOther},
{"system-shutdown", Shutdown},
{"undefined-condition", UndefinedCondition},
{"unsupported-encoding", UnsupportedEnc},
{"unsupported-stanza-type", UnsupportedStanza},
{"unsupported-version", UnsupportedVersion},
{"xml-not-well-formed", Xml},
{"bad-request", SBadRequest},
{"conflict", SConflict},
{"feature-not-implemented", SFeatureNotImpl},
{"forbidden", SForbidden},
{"gone", SGone},
{"internal-server-error", SInternal},
{"item-not-found", SItemNotFound},
{"jid-malformed", SBadJid},
{"not-acceptable", SNotAcceptable},
{"not-allowed", SNotAllowed},
{"not-authorized", SNotAuth},
{"payment-required", SPayment},
{"recipient-unavailable", SUnavailable},
{"redirect", SRedirect},
{"registration-required", SReg},
{"remote-server-not-found", SNoRemote},
{"remote-server-timeout", SRemoteTimeout},
{"resource-constraint", SResource},
{"service-unavailable", SServiceUnavailable},
{"subscription-required", SSubscription},
{"undefined-condition", SUndefinedCondition},
{"unexpected-request", SRequest},
{"unsupported-dtmf-method", DtmfNoMethod},
{0,0}
};
{"cancel", TypeCancel},
{"continue", TypeContinue},
{"modify", TypeModify},
{"auth", TypeAuth},
{"wait", TypeWait},
{"bad-format", BadFormat},
{"bad-namespace-prefix", BadNamespace},
{"connection-timeout", ConnTimeout},
{"host-gone", HostGone},
{"host-unknown", HostUnknown},
{"improper-addressing", BadAddressing},
{"internal-server-error", Internal},
{"invalid-from", InvalidFrom},
{"invalid-id", InvalidId},
{"invalid-namespace", InvalidNamespace},
{"invalid-xml", InvalidXml},
{"not-authorized", NotAuth},
{"policy-violation", Policy},
{"remote-connection-failed", RemoteConn},
{"resource-constraint", ResConstraint},
{"restricted-xml", RestrictedXml},
{"see-other-host", SeeOther},
{"system-shutdown", Shutdown},
{"undefined-condition", UndefinedCondition},
{"unsupported-encoding", UnsupportedEnc},
{"unsupported-stanza-type", UnsupportedStanza},
{"unsupported-version", UnsupportedVersion},
{"xml-not-well-formed", Xml},
{"bad-request", SBadRequest},
{"conflict", SConflict},
{"feature-not-implemented", SFeatureNotImpl},
{"forbidden", SForbidden},
{"gone", SGone},
{"internal-server-error", SInternal},
{"item-not-found", SItemNotFound},
{"jid-malformed", SBadJid},
{"not-acceptable", SNotAcceptable},
{"not-allowed", SNotAllowed},
{"not-authorized", SNotAuth},
{"payment-required", SPayment},
{"recipient-unavailable", SUnavailable},
{"redirect", SRedirect},
{"registration-required", SReg},
{"remote-server-not-found", SNoRemote},
{"remote-server-timeout", SRemoteTimeout},
{"resource-constraint", SResource},
{"service-unavailable", SServiceUnavailable},
{"subscription-required", SSubscription},
{"undefined-condition", SUndefinedCondition},
{"unexpected-request", SRequest},
{"unsupported-dtmf-method", DtmfNoMethod},
{0,0}
};
bool XMPPError::isText(int index, const char* txt)
{

View File

@ -71,16 +71,17 @@ public:
* @param address IP address
* @param port IP port
* @param password Component only: Password used for authentication
* @param identity Component only: the stream identity used when connecting
* @param fullidentity Component only: the user identity
* @param identity Component only: The stream identity used when connecting
* @param fullidentity Component only: The user identity
* @param roster Component only: Keep the user roster
* @param autoRestart Component only: Auto restart stream when connection is down
* @param autoRestart Auto restart stream when connection is down
*/
inline XMPPServerInfo(const char* name, const char* address, int port,
const char* password, const char* identity, const char* fullidentity,
bool roster, bool autoRestart)
: m_name(name), m_address(address), m_port(port), m_password(password),
m_identity(identity), m_fullIdentity(fullidentity), m_roster(roster)
m_identity(identity), m_fullIdentity(fullidentity),
m_roster(roster), m_autoRestart(autoRestart)
{}
/**
@ -141,6 +142,13 @@ public:
inline bool roster() const
{ return m_roster; }
/**
* Check if the stream should restart when down
* @return True if the stream should restart when down
*/
inline bool autoRestart() const
{ return m_autoRestart; }
private:
String m_name; // Domain name
String m_address; // IP address
@ -149,6 +157,7 @@ private:
String m_identity; // Identity. Used for Jabber Component protocol
String m_fullIdentity; // Full identity for this server
bool m_roster; // Keep roster for this server
bool m_autoRestart; // Auto restart stream when down
};
@ -161,10 +170,15 @@ class YJINGLE_API XMPPNamespace
public:
enum Type {
Stream, // http://etherx.jabber.org/streams
Client, // jabber:client
Server, // jabber:server
ComponentAccept, // jabber:component:accept
ComponentConnect, // jabber:component:connect
StreamError, // urn:ietf:params:xml:ns:xmpp-streams
StanzaError, // urn:ietf:params:xml:ns:xmpp-stanzas
Starttls, // urn:ietf:params:xml:ns:xmpp-tls
Sasl, // urn:ietf:params:xml:ns:xmpp-sasl
Session, // urn:ietf:params:xml:ns:xmpp-session
Bind, // urn:ietf:params:xml:ns:xmpp-bind
DiscoInfo, // http://jabber.org/protocol/disco#info
DiscoItems, // http://jabber.org/protocol/disco#items

View File

@ -35,7 +35,6 @@ namespace TelEngine {
class JBEvent; // A Jabber event
class JBStream; // A Jabber stream
class JBComponentStream; // A Jabber Component stream
class JBClientStream; // A Jabber client to server stream
class JBThread; // Base class for private threads
class JBThreadList; // A list of threads
class JBEngine; // A Jabber engine
@ -476,6 +475,17 @@ public:
removePending(notify,&id,false);
}
/**
* Cleanup the stream before destroying
* This method is thread safe
*/
inline void cleanup() {
Lock lock(m_socket.m_streamMutex);
m_events.clear();
TelEngine::destruct(m_terminateEvent);
TelEngine::destruct(m_startEvent);
}
/**
* Get the name of a stream state
* @param state The requested state number
@ -683,66 +693,6 @@ private:
bool m_shaAuth; // Use SHA1/MD5 digest authentication
};
/**
* This class holds a Jabber client stream used to connect an user to its server
* @short A Jabber client to server stream
*/
class YJINGLE_API JBClientStream : public JBStream
{
friend class JBEngine;
public:
/**
* Destructor
*/
virtual ~JBClientStream()
{}
protected:
/**
* Constructor
* @param engine The engine that owns this stream
* @param jid User's JID
* @param password Password used for authentication
* @param address The remote address to connect to
* @param maxRestart The maximum restart attempts allowed
* @param incRestartInterval The interval to increase the restart counter
* @param outgoing Stream direction
*/
JBClientStream(JBEngine* engine, const JabberID& jid,
const String& password, const SocketAddr& address,
unsigned int maxRestart, u_int64_t incRestartInterval,
bool outgoing = true);
/**
* Get the starting stream element to be sent after stream connected
* @return XMLElement pointer
*/
virtual XMLElement* getStreamStart();
/**
* Process a received element in Securing state
* @param xml Valid XMLElement pointer
*/
virtual void processSecuring(XMLElement* xml);
/**
* Process a received element in Auth state
* @param xml Valid XMLElement pointer
*/
virtual void processAuth(XMLElement* xml);
/**
* Process a received element in Started state
* @param xml Valid XMLElement pointer
*/
virtual void processStarted(XMLElement* xml);
private:
// Default constructor is private to avoid unwanted use
JBClientStream() {}
};
/**
* This class holds encapsulates a private library thread
* @short A Jabber thread that can be added to a list of threads