2010-10-07 14:58:13 +00:00
|
|
|
"""
|
|
|
|
SleekXMPP: The Sleek XMPP Library
|
|
|
|
Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
|
|
|
|
This file is part of SleekXMPP.
|
|
|
|
|
|
|
|
See the file LICENSE for copying permission.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import socket
|
|
|
|
try:
|
|
|
|
import queue
|
|
|
|
except ImportError:
|
|
|
|
import Queue as queue
|
|
|
|
|
|
|
|
|
|
|
|
class TestSocket(object):
|
|
|
|
|
|
|
|
"""
|
|
|
|
A dummy socket that reads and writes to queues instead
|
|
|
|
of an actual networking socket.
|
|
|
|
|
|
|
|
Methods:
|
|
|
|
next_sent -- Return the next sent stanza.
|
|
|
|
recv_data -- Make a stanza available to read next.
|
|
|
|
recv -- Read the next stanza from the socket.
|
|
|
|
send -- Write a stanza to the socket.
|
|
|
|
makefile -- Dummy call, returns self.
|
|
|
|
read -- Read the next stanza from the socket.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""
|
|
|
|
Create a new test socket.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
Same as arguments for socket.socket
|
|
|
|
"""
|
|
|
|
self.socket = socket.socket(*args, **kwargs)
|
|
|
|
self.recv_queue = queue.Queue()
|
|
|
|
self.send_queue = queue.Queue()
|
2010-10-07 23:43:51 +00:00
|
|
|
self.is_live = False
|
2011-05-27 18:01:30 +00:00
|
|
|
self.disconnected = False
|
2010-10-07 14:58:13 +00:00
|
|
|
|
|
|
|
def __getattr__(self, name):
|
|
|
|
"""
|
|
|
|
Return attribute values of internal, dummy socket.
|
|
|
|
|
|
|
|
Some attributes and methods are disabled to prevent the
|
|
|
|
socket from connecting to the network.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
name -- Name of the attribute requested.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def dummy(*args):
|
|
|
|
"""Method to do nothing and prevent actual socket connections."""
|
|
|
|
return None
|
|
|
|
|
|
|
|
overrides = {'connect': dummy,
|
|
|
|
'close': dummy,
|
|
|
|
'shutdown': dummy}
|
|
|
|
|
|
|
|
return overrides.get(name, getattr(self.socket, name))
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
# Testing Interface
|
|
|
|
|
|
|
|
def next_sent(self, timeout=None):
|
|
|
|
"""
|
|
|
|
Get the next stanza that has been 'sent'.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
timeout -- Optional timeout for waiting for a new value.
|
|
|
|
"""
|
|
|
|
args = {'block': False}
|
|
|
|
if timeout is not None:
|
|
|
|
args = {'block': True, 'timeout': timeout}
|
|
|
|
try:
|
|
|
|
return self.send_queue.get(**args)
|
|
|
|
except:
|
|
|
|
return None
|
|
|
|
|
|
|
|
def recv_data(self, data):
|
|
|
|
"""
|
|
|
|
Add data to the receiving queue.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
data -- String data to 'write' to the socket to be received
|
|
|
|
by the XMPP client.
|
|
|
|
"""
|
|
|
|
self.recv_queue.put(data)
|
|
|
|
|
2011-05-27 18:01:30 +00:00
|
|
|
def disconnect_error(self):
|
|
|
|
"""
|
|
|
|
Simulate a disconnect error by raising a socket.error exception
|
|
|
|
for any current or further socket operations.
|
|
|
|
"""
|
|
|
|
self.disconnected = True
|
|
|
|
|
2010-10-07 14:58:13 +00:00
|
|
|
# ------------------------------------------------------------------
|
|
|
|
# Socket Interface
|
|
|
|
|
|
|
|
def recv(self, *args, **kwargs):
|
|
|
|
"""
|
|
|
|
Read a value from the received queue.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
Placeholders. Same as for socket.Socket.recv.
|
|
|
|
"""
|
2011-05-27 18:01:30 +00:00
|
|
|
if self.disconnected:
|
|
|
|
raise socket.error
|
2010-10-07 14:58:13 +00:00
|
|
|
return self.read(block=True)
|
|
|
|
|
|
|
|
def send(self, data):
|
|
|
|
"""
|
|
|
|
Send data by placing it in the send queue.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
data -- String value to write.
|
|
|
|
"""
|
2011-05-27 18:01:30 +00:00
|
|
|
if self.disconnected:
|
|
|
|
raise socket.error
|
2010-10-07 14:58:13 +00:00
|
|
|
self.send_queue.put(data)
|
2011-08-25 22:08:45 +00:00
|
|
|
return len(data)
|
2010-10-07 14:58:13 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
# File Socket
|
|
|
|
|
|
|
|
def makefile(self, *args, **kwargs):
|
|
|
|
"""
|
|
|
|
File socket version to use with ElementTree.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
Placeholders, same as socket.Socket.makefile()
|
|
|
|
"""
|
|
|
|
return self
|
|
|
|
|
|
|
|
def read(self, block=True, timeout=None, **kwargs):
|
|
|
|
"""
|
|
|
|
Implement the file socket interface.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
block -- Indicate if the read should block until a
|
|
|
|
value is ready.
|
|
|
|
timeout -- Time in seconds a block should last before
|
|
|
|
returning None.
|
|
|
|
"""
|
2011-05-27 18:01:30 +00:00
|
|
|
if self.disconnected:
|
|
|
|
raise socket.error
|
2010-10-07 14:58:13 +00:00
|
|
|
if timeout is not None:
|
|
|
|
block = True
|
|
|
|
try:
|
|
|
|
return self.recv_queue.get(block, timeout)
|
|
|
|
except:
|
|
|
|
return None
|