Jabberpy V0.5
This commit is contained in:
parent
cf2c7b5037
commit
fa49d30545
133
common/jabber.py
133
common/jabber.py
|
@ -1,4 +1,4 @@
|
||||||
## jabber.py
|
## jabber.py
|
||||||
##
|
##
|
||||||
## Copyright (C) 2001 Matthew Allum
|
## Copyright (C) 2001 Matthew Allum
|
||||||
##
|
##
|
||||||
|
@ -86,7 +86,7 @@ DBG_NODE_UNKNOWN = 'jb-node-unknown' ; debug.debug_flags.append( DBG_NODE_UNK
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# JANA core namespaces
|
# JANA core namespaces
|
||||||
# from http://www.jabber.org/jana/namespaces.php as of 2003-01-12
|
# from http://www.jabber.org/jana/namespaces.php as of 2003-01-12
|
||||||
# "myname" means that namespace didnt have a name in the jabberd headers
|
# "myname" means that namespace didnt have a name in the jabberd headers
|
||||||
#
|
#
|
||||||
|
@ -107,7 +107,7 @@ NS_COMP_ACCEPT = "jabber:component:accept" # myname
|
||||||
NS_COMP_CONNECT = "jabber:component:connect" # myname
|
NS_COMP_CONNECT = "jabber:component:connect" # myname
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# JANA JEP namespaces, ordered by JEP
|
# JANA JEP namespaces, ordered by JEP
|
||||||
# from http://www.jabber.org/jana/namespaces.php as of 2003-01-12
|
# from http://www.jabber.org/jana/namespaces.php as of 2003-01-12
|
||||||
|
@ -140,10 +140,10 @@ NS_P_COMMANDS = _NS_PROTOCOL + "/commands" # JEP-0050
|
||||||
|
|
||||||
"""
|
"""
|
||||||
2002-01-11 jaclu
|
2002-01-11 jaclu
|
||||||
|
|
||||||
Defined in jabberd/lib/lib.h, but not JANA aproved and not used in jabber.py
|
Defined in jabberd/lib/lib.h, but not JANA aproved and not used in jabber.py
|
||||||
so commented out, should/could propably be removed...
|
so commented out, should/could propably be removed...
|
||||||
|
|
||||||
NS_ADMIN = "jabber:iq:admin"
|
NS_ADMIN = "jabber:iq:admin"
|
||||||
NS_AUTH_OK = "jabber:iq:auth:0k"
|
NS_AUTH_OK = "jabber:iq:auth:0k"
|
||||||
NS_CONFERENCE = "jabber:iq:conference"
|
NS_CONFERENCE = "jabber:iq:conference"
|
||||||
|
@ -189,13 +189,13 @@ def ustr(what):
|
||||||
return r
|
return r
|
||||||
xmlstream.ustr = ustr
|
xmlstream.ustr = ustr
|
||||||
|
|
||||||
class NodeProcessed(Exception): pass # currently only for Connection._expectedIqHandler
|
class NodeProcessed(Exception): pass # currently only for Connection._expectedIqHandler
|
||||||
|
|
||||||
class Connection(xmlstream.Client):
|
class Connection(xmlstream.Client):
|
||||||
"""Forms the base for both Client and Component Classes"""
|
"""Forms the base for both Client and Component Classes"""
|
||||||
def __init__(self, host, port, namespace,
|
def __init__(self, host, port, namespace,
|
||||||
debug=False, log=False, connection=xmlstream.TCP, hostIP=None, proxy=None):
|
debug=[], log=False, connection=xmlstream.TCP, hostIP=None, proxy=None):
|
||||||
|
|
||||||
xmlstream.Client.__init__(self, host, port, namespace,
|
xmlstream.Client.__init__(self, host, port, namespace,
|
||||||
debug=debug, log=log,
|
debug=debug, log=log,
|
||||||
connection=connection,
|
connection=connection,
|
||||||
|
@ -207,11 +207,11 @@ class Connection(xmlstream.Client):
|
||||||
self.registerProtocol('presence', Presence)
|
self.registerProtocol('presence', Presence)
|
||||||
|
|
||||||
self.registerHandler('iq',self._expectedIqHandler,system=True)
|
self.registerHandler('iq',self._expectedIqHandler,system=True)
|
||||||
|
|
||||||
self._expected = {}
|
self._expected = {}
|
||||||
|
|
||||||
self._id = 0;
|
self._id = 0;
|
||||||
|
|
||||||
self.lastErr = ''
|
self.lastErr = ''
|
||||||
self.lastErrCode = 0
|
self.lastErrCode = 0
|
||||||
|
|
||||||
|
@ -230,13 +230,13 @@ class Connection(xmlstream.Client):
|
||||||
print "WARNING! setIqHandler(...) method is obsolette, use registerHandler('iq',...) instead."
|
print "WARNING! setIqHandler(...) method is obsolette, use registerHandler('iq',...) instead."
|
||||||
return self.registerHandler('iq', func, type, ns)
|
return self.registerHandler('iq', func, type, ns)
|
||||||
|
|
||||||
def header(self):
|
def header(self):
|
||||||
self.DEBUG("stream: sending initial header",DBG_INIT)
|
self.DEBUG("stream: sending initial header",DBG_INIT)
|
||||||
str = u"<?xml version='1.0' encoding='UTF-8' ?> \
|
str = u"<?xml version='1.0' encoding='UTF-8' ?> \
|
||||||
<stream:stream to='%s' xmlns='%s'" % ( self._host,
|
<stream:stream to='%s' xmlns='%s'" % ( self._host,
|
||||||
self._namespace )
|
self._namespace )
|
||||||
|
|
||||||
if self._outgoingID: str = str + " id='%s' " % self._outgoingID
|
if self._outgoingID: str = str + " id='%s' " % self._outgoingID
|
||||||
str = str + " xmlns:stream='http://etherx.jabber.org/streams'>"
|
str = str + " xmlns:stream='http://etherx.jabber.org/streams'>"
|
||||||
self.send(str)
|
self.send(str)
|
||||||
self.process(timeout)
|
self.process(timeout)
|
||||||
|
@ -276,7 +276,7 @@ class Connection(xmlstream.Client):
|
||||||
if not self.handlers[name].has_key(ns): ns=''
|
if not self.handlers[name].has_key(ns): ns=''
|
||||||
if not self.handlers[name].has_key(typ): typ=''
|
if not self.handlers[name].has_key(typ): typ=''
|
||||||
if not self.handlers[name].has_key(typns): typns=''
|
if not self.handlers[name].has_key(typns): typns=''
|
||||||
if typ==typns: typns=''
|
if typ==typns: typns=''
|
||||||
|
|
||||||
chain=[]
|
chain=[]
|
||||||
for key in ['default',typ,ns,typns]: # we will use all handlers: from very common to very particular
|
for key in ['default',typ,ns,typns]: # we will use all handlers: from very common to very particular
|
||||||
|
@ -307,10 +307,10 @@ class Connection(xmlstream.Client):
|
||||||
def registerHandler(self,name,handler,type='',ns='',chained=False, makefirst=False, system=False):
|
def registerHandler(self,name,handler,type='',ns='',chained=False, makefirst=False, system=False):
|
||||||
"""Sets the callback func for processing incoming stanzas.
|
"""Sets the callback func for processing incoming stanzas.
|
||||||
Multiple callback functions can be set which are called in
|
Multiple callback functions can be set which are called in
|
||||||
succession. Callback can optionally raise an NodeProcessed error to
|
succession. Callback can optionally raise an NodeProcessed error to
|
||||||
stop stanza from further processing. A type and namespace attributes can
|
stop stanza from further processing. A type and namespace attributes can
|
||||||
also be optionally passed so the callback is only called when a stanza of
|
also be optionally passed so the callback is only called when a stanza of
|
||||||
this type is received. Namespace attribute MUST be omitted if you
|
this type is received. Namespace attribute MUST be omitted if you
|
||||||
registering an Iq processing handler.
|
registering an Iq processing handler.
|
||||||
|
|
||||||
If 'chainOutput' is set to False (the default), the given function
|
If 'chainOutput' is set to False (the default), the given function
|
||||||
|
@ -359,7 +359,7 @@ class Connection(xmlstream.Client):
|
||||||
self.lastErr and self.lastErrCode is set to the received error. If
|
self.lastErr and self.lastErrCode is set to the received error. If
|
||||||
the operation times out (which only happens if a timeout value is
|
the operation times out (which only happens if a timeout value is
|
||||||
given), waitForResponse will return None and self.lastErr will be
|
given), waitForResponse will return None and self.lastErr will be
|
||||||
set to "Timeout".
|
set to "Timeout".
|
||||||
Changed default from timeout=0 to timeout=300 to avoid hangs in
|
Changed default from timeout=0 to timeout=300 to avoid hangs in
|
||||||
scripts and such.
|
scripts and such.
|
||||||
If you _really_ want no timeout, just set it to 0"""
|
If you _really_ want no timeout, just set it to 0"""
|
||||||
|
@ -372,7 +372,7 @@ class Connection(xmlstream.Client):
|
||||||
self.DEBUG("waiting with timeout:%s for %s" % (timeout,ustr(ID)),DBG_NODE_IQ)
|
self.DEBUG("waiting with timeout:%s for %s" % (timeout,ustr(ID)),DBG_NODE_IQ)
|
||||||
else:
|
else:
|
||||||
self.DEBUG("waiting for %s" % ustr(ID),DBG_NODE_IQ)
|
self.DEBUG("waiting for %s" % ustr(ID),DBG_NODE_IQ)
|
||||||
|
|
||||||
while (not self._expected[ID]) and not has_timed_out:
|
while (not self._expected[ID]) and not has_timed_out:
|
||||||
if not self.process(0.2): return None
|
if not self.process(0.2): return None
|
||||||
if timeout and (time.time() > abort_time):
|
if timeout and (time.time() > abort_time):
|
||||||
|
@ -405,17 +405,17 @@ class Connection(xmlstream.Client):
|
||||||
"""Returns a unique ID"""
|
"""Returns a unique ID"""
|
||||||
self._id = self._id + 1
|
self._id = self._id + 1
|
||||||
return ustr(self._id)
|
return ustr(self._id)
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
class Client(Connection):
|
class Client(Connection):
|
||||||
"""Class for managing a client connection to a jabber server."""
|
"""Class for managing a client connection to a jabber server."""
|
||||||
def __init__(self, host, port=5222, debug=False, log=False,
|
def __init__(self, host, port=5222, debug=[], log=False,
|
||||||
connection=xmlstream.TCP, hostIP=None, proxy=None):
|
connection=xmlstream.TCP, hostIP=None, proxy=None):
|
||||||
|
|
||||||
Connection.__init__(self, host, port, NS_CLIENT, debug, log,
|
Connection.__init__(self, host, port, NS_CLIENT, debug, log,
|
||||||
connection=connection, hostIP=hostIP, proxy=proxy)
|
connection=connection, hostIP=hostIP, proxy=proxy)
|
||||||
|
|
||||||
self.registerHandler('iq',self._IqRosterManage,'result',NS_ROSTER,system=True)
|
self.registerHandler('iq',self._IqRosterManage,'result',NS_ROSTER,system=True)
|
||||||
self.registerHandler('iq',self._IqRosterManage,'set',NS_ROSTER,system=True)
|
self.registerHandler('iq',self._IqRosterManage,'set',NS_ROSTER,system=True)
|
||||||
self.registerHandler('iq',self._IqRegisterResult,'result',NS_REGISTER,system=True)
|
self.registerHandler('iq',self._IqRegisterResult,'result',NS_REGISTER,system=True)
|
||||||
|
@ -478,7 +478,7 @@ class Client(Connection):
|
||||||
"NS_REGISTER and type==result"
|
"NS_REGISTER and type==result"
|
||||||
self._reg_info = {}
|
self._reg_info = {}
|
||||||
for item in iq_obj.getQueryNode().getChildren():
|
for item in iq_obj.getQueryNode().getChildren():
|
||||||
self._reg_info[item.getName()] = item.getData()
|
self._reg_info[item.getName()] = item.getData()
|
||||||
|
|
||||||
def _IqAgentsResult(self, conn, iq_obj):
|
def _IqAgentsResult(self, conn, iq_obj):
|
||||||
"NS_AGENTS and type==result"
|
"NS_AGENTS and type==result"
|
||||||
|
@ -515,13 +515,13 @@ class Client(Connection):
|
||||||
|
|
||||||
auth_set_iq = Iq(type='set')
|
auth_set_iq = Iq(type='set')
|
||||||
auth_set_iq.setID('auth-set')
|
auth_set_iq.setID('auth-set')
|
||||||
|
|
||||||
q = auth_set_iq.setQuery(NS_AUTH)
|
q = auth_set_iq.setQuery(NS_AUTH)
|
||||||
q.insertTag('username').insertData(username)
|
q.insertTag('username').insertData(username)
|
||||||
q.insertTag('resource').insertData(resource)
|
q.insertTag('resource').insertData(resource)
|
||||||
|
|
||||||
if auth_ret_query.getTag('token'):
|
if auth_ret_query.getTag('token'):
|
||||||
|
|
||||||
token = auth_ret_query.getTag('token').getData()
|
token = auth_ret_query.getTag('token').getData()
|
||||||
seq = auth_ret_query.getTag('sequence').getData()
|
seq = auth_ret_query.getTag('sequence').getData()
|
||||||
self.DEBUG("zero-k authentication supported",(DBG_INIT,DBG_NODE_IQ))
|
self.DEBUG("zero-k authentication supported",(DBG_INIT,DBG_NODE_IQ))
|
||||||
|
@ -538,7 +538,7 @@ class Client(Connection):
|
||||||
else:
|
else:
|
||||||
self.DEBUG("plain text authentication supported",(DBG_INIT,DBG_NODE_IQ))
|
self.DEBUG("plain text authentication supported",(DBG_INIT,DBG_NODE_IQ))
|
||||||
q.insertTag('password').insertData(passwd)
|
q.insertTag('password').insertData(passwd)
|
||||||
|
|
||||||
iq_result = self.SendAndWaitForResponse(auth_set_iq)
|
iq_result = self.SendAndWaitForResponse(auth_set_iq)
|
||||||
|
|
||||||
if iq_result==None:
|
if iq_result==None:
|
||||||
|
@ -592,7 +592,6 @@ class Client(Connection):
|
||||||
if groups != None:
|
if groups != None:
|
||||||
for group in groups:
|
for group in groups:
|
||||||
item.insertTag('group').insertData(group)
|
item.insertTag('group').insertData(group)
|
||||||
# self.send(iq)
|
|
||||||
dummy = self.SendAndWaitForResponse(iq) # Do we need to wait??
|
dummy = self.SendAndWaitForResponse(iq) # Do we need to wait??
|
||||||
|
|
||||||
|
|
||||||
|
@ -620,7 +619,7 @@ class Client(Connection):
|
||||||
# self.DEBUG("Requesting reg info from %s%s:" % (agent, self._host), DBG_NODE_IQ)
|
# self.DEBUG("Requesting reg info from %s%s:" % (agent, self._host), DBG_NODE_IQ)
|
||||||
self.DEBUG("Requesting reg info from %s:" % agent, DBG_NODE_IQ)
|
self.DEBUG("Requesting reg info from %s:" % agent, DBG_NODE_IQ)
|
||||||
self.DEBUG(ustr(reg_iq),DBG_NODE_IQ)
|
self.DEBUG(ustr(reg_iq),DBG_NODE_IQ)
|
||||||
return self.SendAndWaitForResponse(reg_iq)
|
return self.SendAndWaitForResponse(reg_iq)
|
||||||
|
|
||||||
|
|
||||||
def getRegInfo(self):
|
def getRegInfo(self):
|
||||||
|
@ -656,14 +655,16 @@ class Client(Connection):
|
||||||
Note that you must be authorised before attempting to deregister.
|
Note that you must be authorised before attempting to deregister.
|
||||||
"""
|
"""
|
||||||
if agent:
|
if agent:
|
||||||
agent = agent + '.'
|
# agent = agent + '.'
|
||||||
self.send(Presence(to=agent+self._host,type='unsubscribed')) # This is enough f.e. for icqv7t or jit
|
# self.send(Presence(to=agent+self._host,type='unsubscribed')) # This is enough f.e. for icqv7t or jit
|
||||||
|
self.send(Presence(to=agent,type='unsubscribed')) # This is enough f.e. for icqv7t or jit
|
||||||
if agent is None: agent = ''
|
if agent is None: agent = ''
|
||||||
q = self.requestRegInfo()
|
q = self.requestRegInfo()
|
||||||
kids = q.getQueryPayload()
|
kids = q.getQueryPayload()
|
||||||
keyTag = kids.getTag("key")
|
keyTag = kids.getTag("key")
|
||||||
|
|
||||||
iq = Iq(to=agent+self._host, type="set")
|
# iq = Iq(to=agent+self._host, type="set")
|
||||||
|
iq = Iq(to=agent, type="set")
|
||||||
iq.setQuery(NS_REGISTER)
|
iq.setQuery(NS_REGISTER)
|
||||||
iq.setQueryNode("")
|
iq.setQueryNode("")
|
||||||
q = iq.getQueryNode()
|
q = iq.getQueryNode()
|
||||||
|
@ -766,7 +767,7 @@ class Protocol(xmlstream.Node):
|
||||||
try: return JID(self.getAttr('to'))
|
try: return JID(self.getAttr('to'))
|
||||||
except: return None
|
except: return None
|
||||||
|
|
||||||
|
|
||||||
def getFrom(self):
|
def getFrom(self):
|
||||||
"""Returns the 'from' attribute as a JID object."""
|
"""Returns the 'from' attribute as a JID object."""
|
||||||
try: return JID(self.getAttr('from'))
|
try: return JID(self.getAttr('from'))
|
||||||
|
@ -808,7 +809,7 @@ class Protocol(xmlstream.Node):
|
||||||
def getX(self,index=0):
|
def getX(self,index=0):
|
||||||
"""Returns the x namespace, optionally passed an index if there are
|
"""Returns the x namespace, optionally passed an index if there are
|
||||||
multiple tags."""
|
multiple tags."""
|
||||||
try: return self.getXNodes('x')[index].namespace
|
try: return self.getXNodes()[index].namespace
|
||||||
except: return None
|
except: return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -829,10 +830,10 @@ class Protocol(xmlstream.Node):
|
||||||
if type(payload) == type('') or type(payload) == type(u''):
|
if type(payload) == type('') or type(payload) == type(u''):
|
||||||
payload = xmlstream.NodeBuilder(payload).getDom()
|
payload = xmlstream.NodeBuilder(payload).getDom()
|
||||||
|
|
||||||
x.kids = [] # should be a method for this realy
|
x.kids = [] # should be a method for this realy
|
||||||
x.insertNode(payload)
|
x.insertNode(payload)
|
||||||
|
|
||||||
|
|
||||||
def getXPayload(self, val=None):
|
def getXPayload(self, val=None):
|
||||||
"""Returns the x tags' payload as a list of Node instances."""
|
"""Returns the x tags' payload as a list of Node instances."""
|
||||||
nodes = []
|
nodes = []
|
||||||
|
@ -849,7 +850,7 @@ class Protocol(xmlstream.Node):
|
||||||
nodes.append(xnode.kids[0])
|
nodes.append(xnode.kids[0])
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
|
|
||||||
def getXNode(self, val=None):
|
def getXNode(self, val=None):
|
||||||
"""Returns the x Node instance. If there are multiple tags
|
"""Returns the x Node instance. If there are multiple tags
|
||||||
the first Node is returned. For multiple X nodes use getXNodes
|
the first Node is returned. For multiple X nodes use getXNodes
|
||||||
|
@ -904,7 +905,7 @@ class Message(Protocol):
|
||||||
except: return None
|
except: return None
|
||||||
|
|
||||||
|
|
||||||
def getSubject(self):
|
def getSubject(self):
|
||||||
"""Returns the message's subject."""
|
"""Returns the message's subject."""
|
||||||
try: return self.getTag('subject').getData()
|
try: return self.getTag('subject').getData()
|
||||||
except: return None
|
except: return None
|
||||||
|
@ -928,7 +929,7 @@ class Message(Protocol):
|
||||||
else:
|
else:
|
||||||
body = self.insertTag('body').putData(val)
|
body = self.insertTag('body').putData(val)
|
||||||
|
|
||||||
|
|
||||||
def setSubject(self,val):
|
def setSubject(self,val):
|
||||||
"""Sets the message subject text."""
|
"""Sets the message subject text."""
|
||||||
subj = self.getTag('subject')
|
subj = self.getTag('subject')
|
||||||
|
@ -959,7 +960,7 @@ class Message(Protocol):
|
||||||
automatically set."""
|
automatically set."""
|
||||||
m = Message(to=self.getFrom(), body=reply_txt)
|
m = Message(to=self.getFrom(), body=reply_txt)
|
||||||
if not self.getType() == None:
|
if not self.getType() == None:
|
||||||
m.setType(self.getType())
|
m.setType(self.getType())
|
||||||
t = self.getThread()
|
t = self.getThread()
|
||||||
if t: m.setThread(t)
|
if t: m.setThread(t)
|
||||||
return m
|
return m
|
||||||
|
@ -993,7 +994,7 @@ class Presence(Protocol):
|
||||||
"""Returns the presence priority"""
|
"""Returns the presence priority"""
|
||||||
try: return self.getTag('priority').getData()
|
try: return self.getTag('priority').getData()
|
||||||
except: return None
|
except: return None
|
||||||
|
|
||||||
def setShow(self,val):
|
def setShow(self,val):
|
||||||
"""Sets the presence show"""
|
"""Sets the presence show"""
|
||||||
show = self.getTag('show')
|
show = self.getTag('show')
|
||||||
|
@ -1014,7 +1015,7 @@ class Presence(Protocol):
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
class Iq(Protocol):
|
class Iq(Protocol):
|
||||||
"""Class for creating and managing jabber <iq> protocol
|
"""Class for creating and managing jabber <iq> protocol
|
||||||
elements"""
|
elements"""
|
||||||
def __init__(self, to=None, type=None, query=None, attrs=None, frm=None, payload=[], node=None):
|
def __init__(self, to=None, type=None, query=None, attrs=None, frm=None, payload=[], node=None):
|
||||||
|
@ -1069,12 +1070,12 @@ class Iq(Protocol):
|
||||||
if not add: q.kids = []
|
if not add: q.kids = []
|
||||||
q.insertNode(payload)
|
q.insertNode(payload)
|
||||||
|
|
||||||
|
|
||||||
def getQueryPayload(self):
|
def getQueryPayload(self):
|
||||||
"""Returns the query's payload as a Node list"""
|
"""Returns the query's payload as a Node list"""
|
||||||
q = self.getQueryNode()
|
q = self.getQueryNode()
|
||||||
if q: return q.kids
|
if q: return q.kids
|
||||||
|
|
||||||
def getQueryNode(self):
|
def getQueryNode(self):
|
||||||
"""Returns any textual data contained by the query tag"""
|
"""Returns any textual data contained by the query tag"""
|
||||||
try: return self.getTag('query')
|
try: return self.getTag('query')
|
||||||
|
@ -1141,7 +1142,7 @@ class Roster:
|
||||||
|
|
||||||
def getStatus(self, jid): ## extended
|
def getStatus(self, jid): ## extended
|
||||||
"""Returns the 'status' value for a Roster item with the given jid."""
|
"""Returns the 'status' value for a Roster item with the given jid."""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
return self._data[jid]['status']
|
return self._data[jid]['status']
|
||||||
return None
|
return None
|
||||||
|
@ -1149,7 +1150,7 @@ class Roster:
|
||||||
|
|
||||||
def getShow(self, jid): ## extended
|
def getShow(self, jid): ## extended
|
||||||
"""Returns the 'show' value for a Roster item with the given jid."""
|
"""Returns the 'show' value for a Roster item with the given jid."""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
return self._data[jid]['show']
|
return self._data[jid]['show']
|
||||||
return None
|
return None
|
||||||
|
@ -1158,16 +1159,16 @@ class Roster:
|
||||||
def getOnline(self,jid): ## extended
|
def getOnline(self,jid): ## extended
|
||||||
"""Returns the 'online' status for a Roster item with the given jid.
|
"""Returns the 'online' status for a Roster item with the given jid.
|
||||||
"""
|
"""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
return self._data[jid]['online']
|
return self._data[jid]['online']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def getSub(self,jid):
|
def getSub(self,jid):
|
||||||
"""Returns the 'subscription' status for a Roster item with the given
|
"""Returns the 'subscription' status for a Roster item with the given
|
||||||
jid."""
|
jid."""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
return self._data[jid]['sub']
|
return self._data[jid]['sub']
|
||||||
return None
|
return None
|
||||||
|
@ -1175,7 +1176,7 @@ class Roster:
|
||||||
|
|
||||||
def getName(self,jid):
|
def getName(self,jid):
|
||||||
"""Returns the 'name' for a Roster item with the given jid."""
|
"""Returns the 'name' for a Roster item with the given jid."""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
return self._data[jid]['name']
|
return self._data[jid]['name']
|
||||||
return None
|
return None
|
||||||
|
@ -1192,7 +1193,7 @@ class Roster:
|
||||||
|
|
||||||
def getAsk(self,jid):
|
def getAsk(self,jid):
|
||||||
"""Returns the 'ask' status for a Roster item with the given jid."""
|
"""Returns the 'ask' status for a Roster item with the given jid."""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
return self._data[jid]['ask']
|
return self._data[jid]['ask']
|
||||||
return None
|
return None
|
||||||
|
@ -1258,12 +1259,12 @@ class Roster:
|
||||||
|
|
||||||
def _setOnline(self,jid,val):
|
def _setOnline(self,jid,val):
|
||||||
"""Used internally - private"""
|
"""Used internally - private"""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
self._data[jid]['online'] = val
|
self._data[jid]['online'] = val
|
||||||
if self._listener != None:
|
if self._listener != None:
|
||||||
self._listener("update", jid, {'online' : val})
|
self._listener("update", jid, {'online' : val})
|
||||||
else: ## fall back
|
else: ## fall back
|
||||||
jid_basic = JID(jid).getStripped()
|
jid_basic = JID(jid).getStripped()
|
||||||
if self._data.has_key(jid_basic):
|
if self._data.has_key(jid_basic):
|
||||||
self._data[jid_basic]['online'] = val
|
self._data[jid_basic]['online'] = val
|
||||||
|
@ -1273,12 +1274,12 @@ class Roster:
|
||||||
|
|
||||||
def _setShow(self,jid,val):
|
def _setShow(self,jid,val):
|
||||||
"""Used internally - private"""
|
"""Used internally - private"""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
self._data[jid]['show'] = val
|
self._data[jid]['show'] = val
|
||||||
if self._listener != None:
|
if self._listener != None:
|
||||||
self._listener("update", jid, {'show' : val})
|
self._listener("update", jid, {'show' : val})
|
||||||
else: ## fall back
|
else: ## fall back
|
||||||
jid_basic = JID(jid).getStripped()
|
jid_basic = JID(jid).getStripped()
|
||||||
if self._data.has_key(jid_basic):
|
if self._data.has_key(jid_basic):
|
||||||
self._data[jid_basic]['show'] = val
|
self._data[jid_basic]['show'] = val
|
||||||
|
@ -1288,12 +1289,12 @@ class Roster:
|
||||||
|
|
||||||
def _setStatus(self,jid,val):
|
def _setStatus(self,jid,val):
|
||||||
"""Used internally - private"""
|
"""Used internally - private"""
|
||||||
jid = ustr(jid)
|
jid = ustr(jid)
|
||||||
if self._data.has_key(jid):
|
if self._data.has_key(jid):
|
||||||
self._data[jid]['status'] = val
|
self._data[jid]['status'] = val
|
||||||
if self._listener != None:
|
if self._listener != None:
|
||||||
self._listener("update", jid, {'status' : val})
|
self._listener("update", jid, {'status' : val})
|
||||||
else: ## fall back
|
else: ## fall back
|
||||||
jid_basic = JID(jid).getStripped()
|
jid_basic = JID(jid).getStripped()
|
||||||
if self._data.has_key(jid_basic):
|
if self._data.has_key(jid_basic):
|
||||||
self._data[jid_basic]['status'] = val
|
self._data[jid_basic]['status'] = val
|
||||||
|
@ -1320,12 +1321,12 @@ class JID:
|
||||||
bits = jid.split('@', 1)
|
bits = jid.split('@', 1)
|
||||||
self.node = bits[0]
|
self.node = bits[0]
|
||||||
jid = bits[1]
|
jid = bits[1]
|
||||||
|
|
||||||
if jid.find('/') == -1:
|
if jid.find('/') == -1:
|
||||||
self.domain = jid
|
self.domain = jid
|
||||||
self.resource = ''
|
self.resource = ''
|
||||||
else:
|
else:
|
||||||
self.domain, self.resource = jid.split('/', 1)
|
self.domain, self.resource = jid.split('/', 1)
|
||||||
else:
|
else:
|
||||||
self.node = node
|
self.node = node
|
||||||
self.domain = domain
|
self.domain = domain
|
||||||
|
@ -1342,7 +1343,7 @@ class JID:
|
||||||
|
|
||||||
def getBasic(self):
|
def getBasic(self):
|
||||||
"""Returns a jid string with no resource"""
|
"""Returns a jid string with no resource"""
|
||||||
return self.node + '@' + self.domain
|
return self.node + '@' + self.domain
|
||||||
|
|
||||||
def getNode(self):
|
def getNode(self):
|
||||||
"""Returns JID Node as string"""
|
"""Returns JID Node as string"""
|
||||||
|
@ -1375,7 +1376,7 @@ class JID:
|
||||||
|
|
||||||
|
|
||||||
def getStripped(self):
|
def getStripped(self):
|
||||||
"""Returns a JID string with no resource"""
|
"""Returns a JID string with no resource"""
|
||||||
if self.node: return self.node + '@' + self.domain
|
if self.node: return self.node + '@' + self.domain
|
||||||
else: return self.domain
|
else: return self.domain
|
||||||
|
|
||||||
|
@ -1395,7 +1396,7 @@ class JID:
|
||||||
class Component(Connection):
|
class Component(Connection):
|
||||||
"""docs to come soon... """
|
"""docs to come soon... """
|
||||||
def __init__(self, host, port, connection=xmlstream.TCP,
|
def __init__(self, host, port, connection=xmlstream.TCP,
|
||||||
debug=False, log=False, ns=NS_COMP_ACCEPT, hostIP=None, proxy=None):
|
debug=[], log=False, ns=NS_COMP_ACCEPT, hostIP=None, proxy=None):
|
||||||
Connection.__init__(self, host, port, namespace=ns, debug=debug,
|
Connection.__init__(self, host, port, namespace=ns, debug=debug,
|
||||||
log=log, connection=connection, hostIP=hostIP, proxy=proxy)
|
log=log, connection=connection, hostIP=hostIP, proxy=proxy)
|
||||||
self._auth_OK = False
|
self._auth_OK = False
|
||||||
|
@ -1404,7 +1405,7 @@ class Component(Connection):
|
||||||
|
|
||||||
def auth(self,secret):
|
def auth(self,secret):
|
||||||
"""will disconnect on failure"""
|
"""will disconnect on failure"""
|
||||||
self.send( u"<handshake id='1'>%s</handshake>"
|
self.send( u"<handshake id='1'>%s</handshake>"
|
||||||
% sha.new( self.getIncomingID() + secret ).hexdigest()
|
% sha.new( self.getIncomingID() + secret ).hexdigest()
|
||||||
)
|
)
|
||||||
while not self._auth_OK:
|
while not self._auth_OK:
|
||||||
|
@ -1434,7 +1435,7 @@ class Log(Protocol):
|
||||||
## eg: <log type='warn' from='component'>Hello Log File</log>
|
## eg: <log type='warn' from='component'>Hello Log File</log>
|
||||||
def __init__(self, attrs=None, type=None, frm=None, to=None, payload=[], node=None):
|
def __init__(self, attrs=None, type=None, frm=None, to=None, payload=[], node=None):
|
||||||
Protocol.__init__(self, 'log', attrs=attrs, type=type, frm=frm, to=to, payload=payload, node=node)
|
Protocol.__init__(self, 'log', attrs=attrs, type=type, frm=frm, to=to, payload=payload, node=node)
|
||||||
|
|
||||||
def setBody(self,val):
|
def setBody(self,val):
|
||||||
"Sets the log message text."
|
"Sets the log message text."
|
||||||
self.getTag('log').putData(val)
|
self.getTag('log').putData(val)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## xmlstream.py
|
## xmlstream.py
|
||||||
##
|
##
|
||||||
## Copyright (C) 2001 Matthew Allum
|
## Copyright (C) 2001 Matthew Allum
|
||||||
##
|
##
|
||||||
|
@ -28,7 +28,7 @@ case.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# $Id: xmlstream.py,v 1.42 2004/01/08 15:47:40 snakeru Exp $
|
# $Id$
|
||||||
|
|
||||||
import time, sys, re, socket
|
import time, sys, re, socket
|
||||||
from select import select
|
from select import select
|
||||||
|
@ -37,7 +37,7 @@ import xml.parsers.expat
|
||||||
import debug
|
import debug
|
||||||
_debug=debug
|
_debug=debug
|
||||||
|
|
||||||
VERSION = "0.5-rc1"
|
VERSION = "0.5"
|
||||||
|
|
||||||
False = 0
|
False = 0
|
||||||
True = 1
|
True = 1
|
||||||
|
@ -78,7 +78,7 @@ class error:
|
||||||
self.value = str(value)
|
self.value = str(value)
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
"""A simple XML DOM like class"""
|
"""A simple XML DOM like class"""
|
||||||
def __init__(self, tag=None, parent=None, attrs={}, payload=[], node=None):
|
def __init__(self, tag=None, parent=None, attrs={}, payload=[], node=None):
|
||||||
|
@ -93,7 +93,7 @@ class Node:
|
||||||
|
|
||||||
if parent: self.parent = parent
|
if parent: self.parent = parent
|
||||||
|
|
||||||
# if self.parent and not self.namespace: self.namespace=self.parent.namespace # Doesn't checked if this neccessary
|
# if self.parent and not self.namespace: self.namespace=self.parent.namespace # Doesn't checked if this neccessary
|
||||||
|
|
||||||
for attr in attrs.keys():
|
for attr in attrs.keys():
|
||||||
self.attrs[attr]=attrs[attr]
|
self.attrs[attr]=attrs[attr]
|
||||||
|
@ -101,7 +101,7 @@ class Node:
|
||||||
for i in payload:
|
for i in payload:
|
||||||
if type(i)==type(self): self.insertNode(i)
|
if type(i)==type(self): self.insertNode(i)
|
||||||
else: self.insertXML(i)
|
else: self.insertXML(i)
|
||||||
# self.insertNode(Node(node=i)) # Alternative way. Needs perfomance testing.
|
# self.insertNode(Node(node=i)) # Alternative way. Needs perfomance testing.
|
||||||
|
|
||||||
def setParent(self, node):
|
def setParent(self, node):
|
||||||
"Set the nodes parent node."
|
"Set the nodes parent node."
|
||||||
|
@ -127,29 +127,29 @@ class Node:
|
||||||
"Get a value for the nodes named attribute."
|
"Get a value for the nodes named attribute."
|
||||||
try: return self.attrs[key]
|
try: return self.attrs[key]
|
||||||
except: return None
|
except: return None
|
||||||
|
|
||||||
def putData(self, data):
|
def putData(self, data):
|
||||||
"Set the nodes textual data"
|
"Set the nodes textual data"
|
||||||
self.data.append(data)
|
self.data.append(data)
|
||||||
|
|
||||||
def insertData(self, data):
|
def insertData(self, data):
|
||||||
"Set the nodes textual data"
|
"Set the nodes textual data"
|
||||||
self.data.append(data)
|
self.data.append(data)
|
||||||
|
|
||||||
def getData(self):
|
def getData(self):
|
||||||
"Return the nodes textual data"
|
"Return the nodes textual data"
|
||||||
return ''.join(self.data)
|
return ''.join(self.data)
|
||||||
|
|
||||||
def getDataAsParts(self):
|
def getDataAsParts(self):
|
||||||
"Return the node data as an array"
|
"Return the node data as an array"
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
def getNamespace(self):
|
def getNamespace(self):
|
||||||
"Returns the nodes namespace."
|
"Returns the nodes namespace."
|
||||||
return self.namespace
|
return self.namespace
|
||||||
|
|
||||||
def setNamespace(self, namespace):
|
def setNamespace(self, namespace):
|
||||||
"Set the nodes namespace."
|
"Set the nodes namespace."
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
|
|
||||||
def insertTag(self, name=None, attrs={}, payload=[], node=None):
|
def insertTag(self, name=None, attrs={}, payload=[], node=None):
|
||||||
|
@ -178,7 +178,7 @@ class Node:
|
||||||
def _xmlnode2str(self, parent=None):
|
def _xmlnode2str(self, parent=None):
|
||||||
"""Returns an xml ( string ) representation of the node
|
"""Returns an xml ( string ) representation of the node
|
||||||
and it children"""
|
and it children"""
|
||||||
s = "<" + self.name
|
s = "<" + self.name
|
||||||
if self.namespace:
|
if self.namespace:
|
||||||
if parent and parent.namespace != self.namespace:
|
if parent and parent.namespace != self.namespace:
|
||||||
s = s + " xmlns = '%s' " % self.namespace
|
s = s + " xmlns = '%s' " % self.namespace
|
||||||
|
@ -186,7 +186,7 @@ class Node:
|
||||||
val = ustr(self.attrs[key])
|
val = ustr(self.attrs[key])
|
||||||
s = s + " %s='%s'" % ( key, XMLescape(val) )
|
s = s + " %s='%s'" % ( key, XMLescape(val) )
|
||||||
s = s + ">"
|
s = s + ">"
|
||||||
cnt = 0
|
cnt = 0
|
||||||
if self.kids != None:
|
if self.kids != None:
|
||||||
for a in self.kids:
|
for a in self.kids:
|
||||||
if (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt])
|
if (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt])
|
||||||
|
@ -199,12 +199,13 @@ class Node:
|
||||||
s = s + "</" + self.name + ">"
|
s = s + "</" + self.name + ">"
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def getTag(self, name):
|
def getTag(self, name, index=None):
|
||||||
"""Returns a child node with tag name. Returns None
|
"""Returns a child node with tag name. Returns None
|
||||||
if not found."""
|
if not found."""
|
||||||
for node in self.kids:
|
for node in self.kids:
|
||||||
if node.getName() == name:
|
if node.getName() == name:
|
||||||
return node
|
if not index: return node
|
||||||
|
if index is not None: index-=1
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getTags(self, name):
|
def getTags(self, name):
|
||||||
|
@ -214,7 +215,7 @@ class Node:
|
||||||
if node.getName() == name:
|
if node.getName() == name:
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def getChildren(self):
|
def getChildren(self):
|
||||||
"""Returns a nodes children"""
|
"""Returns a nodes children"""
|
||||||
return self.kids
|
return self.kids
|
||||||
|
@ -242,7 +243,7 @@ class NodeBuilder:
|
||||||
|
|
||||||
self.__depth = 0
|
self.__depth = 0
|
||||||
self._dispatch_depth = 1
|
self._dispatch_depth = 1
|
||||||
|
|
||||||
if data: self._parser.Parse(data,1)
|
if data: self._parser.Parse(data,1)
|
||||||
|
|
||||||
def unknown_starttag(self, tag, attrs):
|
def unknown_starttag(self, tag, attrs):
|
||||||
|
@ -293,8 +294,8 @@ class NodeBuilder:
|
||||||
|
|
||||||
|
|
||||||
class Stream(NodeBuilder):
|
class Stream(NodeBuilder):
|
||||||
"""Extention of NodeBuilder class. Handles stream of XML stanzas.
|
"""Extention of NodeBuilder class. Handles stream of XML stanzas.
|
||||||
Calls dispatch method for every child of root node
|
Calls dispatch method for every child of root node
|
||||||
(stream:stream for jabber stream).
|
(stream:stream for jabber stream).
|
||||||
attributes _read, _write and _reader must be set by external entity
|
attributes _read, _write and _reader must be set by external entity
|
||||||
"""
|
"""
|
||||||
|
@ -371,7 +372,7 @@ class Stream(NodeBuilder):
|
||||||
except:
|
except:
|
||||||
self.DEBUG("xmlstream write threw error",DBG_CONN_ERROR)
|
self.DEBUG("xmlstream write threw error",DBG_CONN_ERROR)
|
||||||
self.disconnected(self)
|
self.disconnected(self)
|
||||||
|
|
||||||
def process(self, timeout=0):
|
def process(self, timeout=0):
|
||||||
"""Receives incoming data (if any) and processes it.
|
"""Receives incoming data (if any) and processes it.
|
||||||
Waits for data no more than timeout seconds."""
|
Waits for data no more than timeout seconds."""
|
||||||
|
@ -379,7 +380,7 @@ class Stream(NodeBuilder):
|
||||||
data = self.read()
|
data = self.read()
|
||||||
self._parser.Parse(data)
|
self._parser.Parse(data)
|
||||||
return len(data)
|
return len(data)
|
||||||
return '0' # Zero means that nothing received but link is alive.
|
return '0' # Zero means that nothing received but link is alive.
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
"""Close the stream and socket"""
|
"""Close the stream and socket"""
|
||||||
|
@ -387,7 +388,7 @@ class Stream(NodeBuilder):
|
||||||
while self.process(): pass
|
while self.process(): pass
|
||||||
self._sock.close()
|
self._sock.close()
|
||||||
self._sock = None
|
self._sock = None
|
||||||
|
|
||||||
def disconnected(self,conn):
|
def disconnected(self,conn):
|
||||||
"""Called when a Network Error or disconnection occurs."""
|
"""Called when a Network Error or disconnection occurs."""
|
||||||
try: self.disconnectHandler(conn)
|
try: self.disconnectHandler(conn)
|
||||||
|
@ -399,7 +400,7 @@ class Stream(NodeBuilder):
|
||||||
raise error("Standart disconnectionHandler called. Replace it with appropriate for your client.")
|
raise error("Standart disconnectionHandler called. Replace it with appropriate for your client.")
|
||||||
|
|
||||||
def log(self, data, inout=''):
|
def log(self, data, inout=''):
|
||||||
"""Logs data to the specified filehandle. Data is time stamped
|
"""Logs data to the specified filehandle. Data is time stamped
|
||||||
and prefixed with inout"""
|
and prefixed with inout"""
|
||||||
if self._logFH is not None:
|
if self._logFH is not None:
|
||||||
if self._timestampLog:
|
if self._timestampLog:
|
||||||
|
@ -431,7 +432,7 @@ class Client(Stream):
|
||||||
Stream.__init__(self, namespace, debug, log, id)
|
Stream.__init__(self, namespace, debug, log, id)
|
||||||
|
|
||||||
self._host = host
|
self._host = host
|
||||||
self._port = port
|
self._port = port
|
||||||
self._sock = sock
|
self._sock = sock
|
||||||
self._connection = connection
|
self._connection = connection
|
||||||
if hostIP: self._hostIP = hostIP
|
if hostIP: self._hostIP = hostIP
|
||||||
|
@ -528,33 +529,33 @@ class Client(Stream):
|
||||||
self.DEBUG('unknown connection type',DBG_CONN_ERROR)
|
self.DEBUG('unknown connection type',DBG_CONN_ERROR)
|
||||||
raise IOError('unknown connection type')
|
raise IOError('unknown connection type')
|
||||||
|
|
||||||
class Server:
|
class Server:
|
||||||
|
|
||||||
def now(self): return time.ctime(time.time())
|
def now(self): return time.ctime(time.time())
|
||||||
|
|
||||||
def __init__(self, maxclients=10):
|
def __init__(self, maxclients=10):
|
||||||
|
|
||||||
self.host = ''
|
self.host = ''
|
||||||
self.port = 5222
|
self.port = 5222
|
||||||
self.streams = []
|
self.streams = []
|
||||||
|
|
||||||
# make main sockets for accepting new client requests
|
# make main sockets for accepting new client requests
|
||||||
self.mainsocks, self.readsocks, self.writesocks = [], [], []
|
self.mainsocks, self.readsocks, self.writesocks = [], [], []
|
||||||
|
|
||||||
self.portsock = socket(AF_INET, SOCK_STREAM)
|
self.portsock = socket(AF_INET, SOCK_STREAM)
|
||||||
self.portsock.bind((self.host, self.port))
|
self.portsock.bind((self.host, self.port))
|
||||||
self.portsock.listen(maxclients)
|
self.portsock.listen(maxclients)
|
||||||
|
|
||||||
self.mainsocks.append(self.portsock) # add to main list to identify
|
self.mainsocks.append(self.portsock) # add to main list to identify
|
||||||
self.readsocks.append(self.portsock) # add to select inputs list
|
self.readsocks.append(self.portsock) # add to select inputs list
|
||||||
|
|
||||||
# event loop: listen and multiplex until server process killed
|
# event loop: listen and multiplex until server process killed
|
||||||
|
|
||||||
|
|
||||||
def serve(self):
|
def serve(self):
|
||||||
|
|
||||||
print 'select-server loop starting'
|
print 'select-server loop starting'
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
print "LOOPING"
|
print "LOOPING"
|
||||||
readables, writeables, exceptions = select(self.readsocks,
|
readables, writeables, exceptions = select(self.readsocks,
|
||||||
|
@ -562,7 +563,7 @@ class Server:
|
||||||
for sockobj in readables:
|
for sockobj in readables:
|
||||||
if sockobj in self. mainsocks: # for ready input sockets
|
if sockobj in self. mainsocks: # for ready input sockets
|
||||||
newsock, address = sockobj.accept() # accept not block
|
newsock, address = sockobj.accept() # accept not block
|
||||||
print 'Connect:', address, id(newsock)
|
print 'Connect:', address, id(newsock)
|
||||||
self.readsocks.append(newsock)
|
self.readsocks.append(newsock)
|
||||||
self._makeNewStream(newsock)
|
self._makeNewStream(newsock)
|
||||||
# add to select list, wait
|
# add to select list, wait
|
||||||
|
@ -571,9 +572,9 @@ class Server:
|
||||||
data = sockobj.recv(1024)
|
data = sockobj.recv(1024)
|
||||||
# recv should not block
|
# recv should not block
|
||||||
print '\tgot', data, 'on', id(sockobj)
|
print '\tgot', data, 'on', id(sockobj)
|
||||||
if not data: # if closed by the clients
|
if not data: # if closed by the clients
|
||||||
sockobj.close() # close here and remv from
|
sockobj.close() # close here and remv from
|
||||||
self.readsocks.remove(sockobj)
|
self.readsocks.remove(sockobj)
|
||||||
else:
|
else:
|
||||||
# this may block: should really select for writes too
|
# this may block: should really select for writes too
|
||||||
sockobj.send('Echo=>%s' % data)
|
sockobj.send('Echo=>%s' % data)
|
||||||
|
@ -592,7 +593,7 @@ class Server:
|
||||||
for s in self.streams:
|
for s in self.streams:
|
||||||
socks.append(s.getSocket())
|
socks.append(s.getSocket())
|
||||||
return socks
|
return socks
|
||||||
|
|
||||||
def _getStreamFromSocket(self, sock):
|
def _getStreamFromSocket(self, sock):
|
||||||
for s in self.streams:
|
for s in self.streams:
|
||||||
if s.getSocket() == sock:
|
if s.getSocket() == sock:
|
||||||
|
|
Loading…
Reference in New Issue