Coding standards and documentation improvements in transports_nb.py
This commit is contained in:
parent
7163be96e0
commit
5c02a907b4
|
@ -15,6 +15,14 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
|
'''
|
||||||
|
Transports are objects responsible for connecting to XMPP server and putting
|
||||||
|
data to wrapped sockets in in desired form (SSL, TLS, TCP, for HTTP proxy,
|
||||||
|
for SOCKS5 proxy...)
|
||||||
|
|
||||||
|
Transports are not aware of XMPP stanzas.
|
||||||
|
'''
|
||||||
|
|
||||||
from simplexml import ustr
|
from simplexml import ustr
|
||||||
from client import PlugIn
|
from client import PlugIn
|
||||||
from idlequeue import IdleObject
|
from idlequeue import IdleObject
|
||||||
|
@ -23,8 +31,6 @@ import proxy_connectors
|
||||||
import tls_nb
|
import tls_nb
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import errno
|
import errno
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -47,8 +53,8 @@ def urisplit(uri):
|
||||||
|
|
||||||
def get_proxy_data_from_dict(proxy):
|
def get_proxy_data_from_dict(proxy):
|
||||||
tcp_host, tcp_port, proxy_user, proxy_pass = None, None, None, None
|
tcp_host, tcp_port, proxy_user, proxy_pass = None, None, None, None
|
||||||
type = proxy['type']
|
proxy_type = proxy['type']
|
||||||
if type == 'bosh' and not proxy['bosh_useproxy']:
|
if proxy_type == 'bosh' and not proxy['bosh_useproxy']:
|
||||||
# with BOSH not over proxy we have to parse the hostname from BOSH URI
|
# with BOSH not over proxy we have to parse the hostname from BOSH URI
|
||||||
tcp_host, tcp_port = urisplit(proxy['bosh_uri'])[1], proxy['bosh_port']
|
tcp_host, tcp_port = urisplit(proxy['bosh_uri'])[1], proxy['bosh_port']
|
||||||
else:
|
else:
|
||||||
|
@ -83,10 +89,10 @@ STATES = [DISCONNECTED, CONNECTING, PROXY_CONNECTING, CONNECTED, DISCONNECTING]
|
||||||
|
|
||||||
class NonBlockingTransport(PlugIn):
|
class NonBlockingTransport(PlugIn):
|
||||||
'''
|
'''
|
||||||
Abstract class representing a trasport - object responsible for connecting to
|
Abstract class representing a transport.
|
||||||
XMPP server and putting stanzas on wire in desired form.
|
|
||||||
'''
|
'''
|
||||||
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls, certs):
|
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
|
||||||
|
certs):
|
||||||
'''
|
'''
|
||||||
Each trasport class can have different constructor but it has to have at
|
Each trasport class can have different constructor but it has to have at
|
||||||
least all the arguments of NonBlockingTransport constructor.
|
least all the arguments of NonBlockingTransport constructor.
|
||||||
|
@ -94,10 +100,10 @@ class NonBlockingTransport(PlugIn):
|
||||||
:param raise_event: callback for monitoring of sent and received data
|
:param raise_event: callback for monitoring of sent and received data
|
||||||
:param on_disconnect: callback called on disconnection during runtime
|
:param on_disconnect: callback called on disconnection during runtime
|
||||||
:param idlequeue: processing idlequeue
|
:param idlequeue: processing idlequeue
|
||||||
:param estabilish_tls: boolean whether to estabilish TLS connection after TCP
|
:param estabilish_tls: boolean whether to estabilish TLS connection after
|
||||||
connection is done
|
TCP connection is done
|
||||||
:param certs: tuple of (cacerts, mycerts) see tls_nb.NonBlockingTLS
|
:param certs: tuple of (cacerts, mycerts) see constructor of
|
||||||
constructor for more details
|
tls_nb.NonBlockingTLS for more details
|
||||||
'''
|
'''
|
||||||
PlugIn.__init__(self)
|
PlugIn.__init__(self)
|
||||||
self.raise_event = raise_event
|
self.raise_event = raise_event
|
||||||
|
@ -108,6 +114,7 @@ class NonBlockingTransport(PlugIn):
|
||||||
self.on_receive = None
|
self.on_receive = None
|
||||||
self.server = None
|
self.server = None
|
||||||
self.port = None
|
self.port = None
|
||||||
|
self.conn_5tuple = None
|
||||||
self.set_state(DISCONNECTED)
|
self.set_state(DISCONNECTED)
|
||||||
self.estabilish_tls = estabilish_tls
|
self.estabilish_tls = estabilish_tls
|
||||||
self.certs = certs
|
self.certs = certs
|
||||||
|
@ -132,8 +139,9 @@ class NonBlockingTransport(PlugIn):
|
||||||
|
|
||||||
def connect(self, conn_5tuple, on_connect, on_connect_failure):
|
def connect(self, conn_5tuple, on_connect, on_connect_failure):
|
||||||
'''
|
'''
|
||||||
Creates and connects transport to server and port defined in conn_5tupe which
|
Creates and connects transport to server and port defined in conn_5tuple
|
||||||
should be item from list returned from getaddrinfo.
|
which should be item from list returned from getaddrinfo.
|
||||||
|
|
||||||
:param conn_5tuple: 5-tuple returned from getaddrinfo
|
:param conn_5tuple: 5-tuple returned from getaddrinfo
|
||||||
:param on_connect: callback called on successful connect to the server
|
:param on_connect: callback called on successful connect to the server
|
||||||
:param on_connect_failure: callback called on failure when connecting
|
:param on_connect_failure: callback called on failure when connecting
|
||||||
|
@ -178,11 +186,13 @@ class NonBlockingTransport(PlugIn):
|
||||||
|
|
||||||
def onreceive(self, recv_handler):
|
def onreceive(self, recv_handler):
|
||||||
'''
|
'''
|
||||||
Sets the on_receive callback. Do not confuse it with on_receive() method,
|
Sets the on_receive callback.
|
||||||
which is the callback itself.
|
|
||||||
onreceive(None) sets callback to Dispatcher.ProcessNonBlocking which is the
|
onreceive(None) sets callback to Dispatcher.ProcessNonBlocking which is
|
||||||
default one that will decide what to do with received stanza based on its
|
the default one that will decide what to do with received stanza based on
|
||||||
tag name and namespace.
|
its tag name and namespace.
|
||||||
|
|
||||||
|
Do not confuse it with on_receive() method, which is the callback itself.
|
||||||
'''
|
'''
|
||||||
if not recv_handler:
|
if not recv_handler:
|
||||||
if hasattr(self._owner, 'Dispatcher'):
|
if hasattr(self._owner, 'Dispatcher'):
|
||||||
|
@ -229,8 +239,10 @@ class NonBlockingTransport(PlugIn):
|
||||||
|
|
||||||
class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
'''
|
'''
|
||||||
Non-blocking TCP socket wrapper. It is used for simple XMPP connection. Can be
|
Non-blocking TCP socket wrapper.
|
||||||
connected via proxy and can estabilish TLS connection.
|
|
||||||
|
It is used for simple XMPP connection. Can be connected via proxy and can
|
||||||
|
estabilish TLS connection.
|
||||||
'''
|
'''
|
||||||
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
|
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
|
||||||
certs, proxy_dict=None):
|
certs, proxy_dict=None):
|
||||||
|
@ -239,6 +251,7 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
'''
|
'''
|
||||||
NonBlockingTransport.__init__(self, raise_event, on_disconnect, idlequeue,
|
NonBlockingTransport.__init__(self, raise_event, on_disconnect, idlequeue,
|
||||||
estabilish_tls, certs)
|
estabilish_tls, certs)
|
||||||
|
IdleObject.__init__(self)
|
||||||
|
|
||||||
# queue with messages to be send
|
# queue with messages to be send
|
||||||
self.sendqueue = []
|
self.sendqueue = []
|
||||||
|
@ -255,14 +268,16 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
def connect(self, conn_5tuple, on_connect, on_connect_failure):
|
def connect(self, conn_5tuple, on_connect, on_connect_failure):
|
||||||
NonBlockingTransport.connect(self, conn_5tuple, on_connect, on_connect_failure)
|
NonBlockingTransport.connect(self, conn_5tuple, on_connect,
|
||||||
log.info('NonBlockingTCP Connect :: About to connect to %s:%s' % (self.server, self.port))
|
on_connect_failure)
|
||||||
|
log.info('NonBlockingTCP Connect :: About to connect to %s:%s' %
|
||||||
|
(self.server, self.port))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._sock = socket.socket(*conn_5tuple[:3])
|
self._sock = socket.socket(*conn_5tuple[:3])
|
||||||
except socket.error, (errnum, errstr):
|
except socket.error, (errnum, errstr):
|
||||||
self._on_connect_failure('NonBlockingTCP Connect: Error while creating socket:\
|
self._on_connect_failure('NonBlockingTCP Connect: Error while creating\
|
||||||
%s %s' % (errnum, errstr))
|
socket: %s %s' % (errnum, errstr))
|
||||||
return
|
return
|
||||||
|
|
||||||
self._send = self._sock.send
|
self._send = self._sock.send
|
||||||
|
@ -274,7 +289,8 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
self._plug_idle(writable=True, readable=False)
|
self._plug_idle(writable=True, readable=False)
|
||||||
self.peerhost = None
|
self.peerhost = None
|
||||||
|
|
||||||
# variable for errno symbol that will be found from exception raised from connect()
|
# variable for errno symbol that will be found from exception raised
|
||||||
|
# from connect()
|
||||||
errnum = 0
|
errnum = 0
|
||||||
|
|
||||||
# set timeout for TCP connecting - if nonblocking connect() fails, pollend
|
# set timeout for TCP connecting - if nonblocking connect() fails, pollend
|
||||||
|
@ -289,12 +305,13 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
|
|
||||||
if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
|
if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
|
||||||
# connecting in progress
|
# connecting in progress
|
||||||
log.info('After NB connect() of %s. "%s" raised => CONNECTING' % (id(self),errstr))
|
log.info('After NB connect() of %s. "%s" raised => CONNECTING' %
|
||||||
|
(id(self), errstr))
|
||||||
self.tcp_connecting_started()
|
self.tcp_connecting_started()
|
||||||
return
|
return
|
||||||
|
|
||||||
# if there was some other exception, call failure callback and unplug transport
|
# if there was some other exception, call failure callback and unplug
|
||||||
# which will also remove read_timeouts for descriptor
|
# transport which will also remove read_timeouts for descriptor
|
||||||
self._on_connect_failure('Exception while connecting to %s:%s - %s %s' %
|
self._on_connect_failure('Exception while connecting to %s:%s - %s %s' %
|
||||||
(self.server, self.port, errnum, errstr))
|
(self.server, self.port, errnum, errstr))
|
||||||
|
|
||||||
|
@ -322,14 +339,16 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
if self.estabilish_tls:
|
if self.estabilish_tls:
|
||||||
self.tls_init(
|
self.tls_init(
|
||||||
on_succ = lambda: NonBlockingTransport._on_connect(self),
|
on_succ = lambda: NonBlockingTransport._on_connect(self),
|
||||||
on_fail = lambda: self._on_connect_failure('error while estabilishing TLS'))
|
on_fail = lambda: self._on_connect_failure(
|
||||||
|
'error while estabilishing TLS'))
|
||||||
else:
|
else:
|
||||||
NonBlockingTransport._on_connect(self)
|
NonBlockingTransport._on_connect(self)
|
||||||
|
|
||||||
|
|
||||||
def tls_init(self, on_succ, on_fail):
|
def tls_init(self, on_succ, on_fail):
|
||||||
'''
|
'''
|
||||||
Estabilishes a TLS/SSL on TCP connection by plugging a NonBlockingTLS module
|
Estabilishes TLS/SSL using this TCP connection by plugging a
|
||||||
|
NonBlockingTLS module
|
||||||
'''
|
'''
|
||||||
cacerts, mycerts = self.certs
|
cacerts, mycerts = self.certs
|
||||||
result = tls_nb.NonBlockingTLS(cacerts, mycerts).PlugIn(self)
|
result = tls_nb.NonBlockingTLS(cacerts, mycerts).PlugIn(self)
|
||||||
|
@ -339,12 +358,12 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
on_fail()
|
on_fail()
|
||||||
|
|
||||||
def pollin(self):
|
def pollin(self):
|
||||||
'''called when receive on plugged socket is possible '''
|
'''called by idlequeu when receive on plugged socket is possible '''
|
||||||
log.info('pollin called, state == %s' % self.get_state())
|
log.info('pollin called, state == %s' % self.get_state())
|
||||||
self._do_receive()
|
self._do_receive()
|
||||||
|
|
||||||
def pollout(self):
|
def pollout(self):
|
||||||
'''called when send to plugged socket is possible'''
|
'''called by idlequeu when send to plugged socket is possible'''
|
||||||
log.info('pollout called, state == %s' % self.get_state())
|
log.info('pollout called, state == %s' % self.get_state())
|
||||||
|
|
||||||
if self.get_state() == CONNECTING:
|
if self.get_state() == CONNECTING:
|
||||||
|
@ -352,13 +371,15 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
self.idlequeue.remove_timeout(self.fd)
|
self.idlequeue.remove_timeout(self.fd)
|
||||||
self._plug_idle(writable=False, readable=False)
|
self._plug_idle(writable=False, readable=False)
|
||||||
self.peerhost = self._sock.getsockname()
|
self.peerhost = self._sock.getsockname()
|
||||||
if self.proxy_dict: self._connect_to_proxy()
|
if self.proxy_dict:
|
||||||
else: self._on_connect()
|
self._connect_to_proxy()
|
||||||
return
|
else:
|
||||||
|
self._on_connect()
|
||||||
|
else:
|
||||||
self._do_send()
|
self._do_send()
|
||||||
|
|
||||||
def pollend(self):
|
def pollend(self):
|
||||||
'''called on error on TCP connection'''
|
'''called by idlequeue on TCP connection errors'''
|
||||||
log.info('pollend called, state == %s' % self.get_state())
|
log.info('pollend called, state == %s' % self.get_state())
|
||||||
|
|
||||||
if self.get_state() == CONNECTING:
|
if self.get_state() == CONNECTING:
|
||||||
|
@ -382,7 +403,6 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
NonBlockingTransport.disconnect(self, do_callback)
|
NonBlockingTransport.disconnect(self, do_callback)
|
||||||
|
|
||||||
def read_timeout(self):
|
def read_timeout(self):
|
||||||
''' method called when timeout passed '''
|
|
||||||
log.info('read_timeout called, state == %s' % self.get_state())
|
log.info('read_timeout called, state == %s' % self.get_state())
|
||||||
if self.get_state()==CONNECTING:
|
if self.get_state()==CONNECTING:
|
||||||
# if read_timeout is called during connecting, connect() didn't end yet
|
# if read_timeout is called during connecting, connect() didn't end yet
|
||||||
|
@ -396,7 +416,8 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
if self.get_state() != DISCONNECTED and self.fd != -1:
|
if self.get_state() != DISCONNECTED and self.fd != -1:
|
||||||
NonBlockingTransport.set_timeout(self, timeout)
|
NonBlockingTransport.set_timeout(self, timeout)
|
||||||
else:
|
else:
|
||||||
log.warn('set_timeout: TIMEOUT NOT SET: state is %s, fd is %s' % (self.get_state(), self.fd))
|
log.warn('set_timeout: TIMEOUT NOT SET: state is %s, fd is %s' %
|
||||||
|
(self.get_state(), self.fd))
|
||||||
|
|
||||||
def remove_timeout(self):
|
def remove_timeout(self):
|
||||||
if self.fd:
|
if self.fd:
|
||||||
|
@ -405,7 +426,8 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
log.warn('remove_timeout: no self.fd state is %s' % self.get_state())
|
log.warn('remove_timeout: no self.fd state is %s' % self.get_state())
|
||||||
|
|
||||||
def send(self, raw_data, now=False):
|
def send(self, raw_data, now=False):
|
||||||
'''Append raw_data to the queue of messages to be send.
|
'''
|
||||||
|
Append raw_data to the queue of messages to be send.
|
||||||
If supplied data is unicode string, encode it to utf-8.
|
If supplied data is unicode string, encode it to utf-8.
|
||||||
'''
|
'''
|
||||||
NonBlockingTransport.send(self, raw_data, now)
|
NonBlockingTransport.send(self, raw_data, now)
|
||||||
|
@ -421,6 +443,7 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
self._plug_idle(writable=True, readable=True)
|
self._plug_idle(writable=True, readable=True)
|
||||||
|
|
||||||
def encode_stanza(self, stanza):
|
def encode_stanza(self, stanza):
|
||||||
|
''' Encode str or unicode to utf-8 '''
|
||||||
if isinstance(stanza, unicode):
|
if isinstance(stanza, unicode):
|
||||||
stanza = stanza.encode('utf-8')
|
stanza = stanza.encode('utf-8')
|
||||||
elif not isinstance(stanza, str):
|
elif not isinstance(stanza, str):
|
||||||
|
@ -429,16 +452,18 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
|
|
||||||
def _plug_idle(self, writable, readable):
|
def _plug_idle(self, writable, readable):
|
||||||
'''
|
'''
|
||||||
Plugs file descriptor of socket to Idlequeue. Plugged socket
|
Plugs file descriptor of socket to Idlequeue.
|
||||||
will be watched for "send possible" or/and "recv possible" events. pollin()
|
|
||||||
callback is invoked on "recv possible", pollout() on "send_possible".
|
Plugged socket will be watched for "send possible" or/and "recv possible"
|
||||||
|
events. pollin() callback is invoked on "recv possible", pollout() on
|
||||||
|
"send_possible".
|
||||||
|
|
||||||
Plugged socket will always be watched for "error" event - in that case,
|
Plugged socket will always be watched for "error" event - in that case,
|
||||||
pollend() is called.
|
pollend() is called.
|
||||||
'''
|
'''
|
||||||
log.info('Plugging fd %d, W:%s, R:%s' % (self.fd, writable, readable))
|
log.info('Plugging fd %d, W:%s, R:%s' % (self.fd, writable, readable))
|
||||||
self.idlequeue.plug_idle(self, writable, readable)
|
self.idlequeue.plug_idle(self, writable, readable)
|
||||||
|
|
||||||
|
|
||||||
def _do_send(self):
|
def _do_send(self):
|
||||||
'''
|
'''
|
||||||
Called when send() to connected socket is possible. First message from
|
Called when send() to connected socket is possible. First message from
|
||||||
|
@ -466,7 +491,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
def _do_receive(self):
|
def _do_receive(self):
|
||||||
''' Reads all pending incoming data. Calls owner's disconnected() method if appropriate.'''
|
'''
|
||||||
|
Reads all pending incoming data. Will call owner's disconnected() method
|
||||||
|
if appropriate.
|
||||||
|
'''
|
||||||
received = None
|
received = None
|
||||||
errnum = 0
|
errnum = 0
|
||||||
errstr = 'No Error Set'
|
errstr = 'No Error Set'
|
||||||
|
@ -477,7 +505,8 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
except socket.error, (errnum, errstr):
|
except socket.error, (errnum, errstr):
|
||||||
log.info("_do_receive: got %s:" % received , exc_info=True)
|
log.info("_do_receive: got %s:" % received , exc_info=True)
|
||||||
except tls_nb.SSLWrapper.Error, e:
|
except tls_nb.SSLWrapper.Error, e:
|
||||||
log.info("_do_receive, caught SSL error, got %s:" % received , exc_info=True)
|
log.info("_do_receive, caught SSL error, got %s:" % received,
|
||||||
|
exc_info=True)
|
||||||
errnum, errstr = e.exc
|
errnum, errstr = e.exc
|
||||||
|
|
||||||
if received == '': errstr = 'zero bytes on recv'
|
if received == '': errstr = 'zero bytes on recv'
|
||||||
|
@ -491,15 +520,14 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
self.on_remote_disconnect()
|
self.on_remote_disconnect()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
if errnum:
|
if errnum:
|
||||||
log.error("Connection to %s:%s lost: %s %s" % ( self.server, self.port, errnum, errstr), exc_info=True)
|
log.error("Connection to %s:%s lost: %s %s" % (self.server, self.port,
|
||||||
|
errnum, errstr), exc_info=True)
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
|
|
||||||
# this branch is for case of non-fatal SSL errors - None is returned from
|
# this branch is for case of non-fatal SSL errors - None is returned from
|
||||||
# recv() but no errnum is set
|
# recv() but no errnum is set
|
||||||
|
|
||||||
if received is None:
|
if received is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -510,48 +538,50 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
self.raise_event(DATA_RECEIVED, received)
|
self.raise_event(DATA_RECEIVED, received)
|
||||||
self._on_receive(received)
|
self._on_receive(received)
|
||||||
else:
|
else:
|
||||||
# This should never happen, so we need the debug. (If there is no handler
|
# This should never happen, so we need the debug.
|
||||||
# on receive specified, data are passed to Dispatcher.ProcessNonBlocking)
|
# (If there is no handler on receive specified, data is passed to
|
||||||
log.error('SOCKET %s Unhandled data received: %s' % (id(self), received))
|
# Dispatcher.ProcessNonBlocking)
|
||||||
|
log.error('SOCKET %s Unhandled data received: %s' % (id(self),
|
||||||
|
received))
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
def _on_receive(self, data):
|
def _on_receive(self, data):
|
||||||
''' preceeds on_receive callback. It peels off and checks HTTP headers in
|
''' preceeds on_receive callback. It peels off and checks HTTP headers in
|
||||||
class, in here it just calls the callback.'''
|
HTTP classes, in here it just calls the callback.'''
|
||||||
self.on_receive(data)
|
self.on_receive(data)
|
||||||
|
|
||||||
|
|
||||||
class NonBlockingHTTP(NonBlockingTCP):
|
class NonBlockingHTTP(NonBlockingTCP):
|
||||||
'''
|
'''
|
||||||
Socket wrapper that creates HTTP message out of sent data and peels-off
|
Socket wrapper that creates HTTP message out of sent data and peels-off
|
||||||
HTTP headers from incoming messages
|
HTTP headers from incoming messages.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
|
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
|
||||||
certs, on_http_request_possible, on_persistent_fallback, http_dict,
|
certs, on_http_request_possible, on_persistent_fallback, http_dict,
|
||||||
proxy_dict = None):
|
proxy_dict = None):
|
||||||
'''
|
'''
|
||||||
:param on_http_request_possible: method to call when HTTP request to socket
|
:param on_http_request_possible: method to call when HTTP request to
|
||||||
owned by transport is possible.
|
socket owned by transport is possible.
|
||||||
:param on_persistent_fallback: callback called when server ends TCP
|
:param on_persistent_fallback: callback called when server ends TCP
|
||||||
connection. It doesn't have to be fatal for HTTP session.
|
connection. It doesn't have to be fatal for HTTP session.
|
||||||
:param http_dict: dictionary with data for HTTP request and headers
|
:param http_dict: dictionary with data for HTTP request and headers
|
||||||
'''
|
'''
|
||||||
|
|
||||||
NonBlockingTCP.__init__(self, raise_event, on_disconnect, idlequeue,
|
NonBlockingTCP.__init__(self, raise_event, on_disconnect, idlequeue,
|
||||||
estabilish_tls, certs, proxy_dict)
|
estabilish_tls, certs, proxy_dict)
|
||||||
|
|
||||||
self.http_protocol, self.http_host, self.http_path = urisplit(http_dict['http_uri'])
|
self.http_protocol, self.http_host, self.http_path = urisplit(
|
||||||
if self.http_protocol is None:
|
http_dict['http_uri'])
|
||||||
self.http_protocol = 'http'
|
self.http_protocol = self.http_protocol or 'http'
|
||||||
if self.http_path == '':
|
self.http_path = self.http_path or '/'
|
||||||
self.http_path = '/'
|
|
||||||
self.http_port = http_dict['http_port']
|
self.http_port = http_dict['http_port']
|
||||||
self.http_version = http_dict['http_version']
|
self.http_version = http_dict['http_version']
|
||||||
self.http_persistent = http_dict['http_persistent']
|
self.http_persistent = http_dict['http_persistent']
|
||||||
self.add_proxy_headers = http_dict['add_proxy_headers']
|
self.add_proxy_headers = http_dict['add_proxy_headers']
|
||||||
if http_dict.has_key('proxy_user') and http_dict.has_key('proxy_pass'):
|
|
||||||
self.proxy_user, self.proxy_pass = http_dict['proxy_user'], http_dict['proxy_pass']
|
if 'proxy_user' in http_dict and 'proxy_pass' in http_dict:
|
||||||
|
self.proxy_user, self.proxy_pass = http_dict['proxy_user'], http_dict[
|
||||||
|
'proxy_pass']
|
||||||
else:
|
else:
|
||||||
self.proxy_user, self.proxy_pass = None, None
|
self.proxy_user, self.proxy_pass = None, None
|
||||||
|
|
||||||
|
@ -587,7 +617,7 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
self.expected_length = int(headers['Content-Length'])
|
self.expected_length = int(headers['Content-Length'])
|
||||||
if headers.has_key('Connection') and headers['Connection'].strip()=='close':
|
if 'Connection' in headers and headers['Connection'].strip()=='close':
|
||||||
self.close_current_connection = True
|
self.close_current_connection = True
|
||||||
else:
|
else:
|
||||||
#sth in recvbuff - append currently received data to HTTP msg in buffer
|
#sth in recvbuff - append currently received data to HTTP msg in buffer
|
||||||
|
@ -614,7 +644,6 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
self.on_receive(data=httpbody, socket=self)
|
self.on_receive(data=httpbody, socket=self)
|
||||||
self.on_http_request_possible()
|
self.on_http_request_possible()
|
||||||
|
|
||||||
|
|
||||||
def build_http_message(self, httpbody, method='POST'):
|
def build_http_message(self, httpbody, method='POST'):
|
||||||
'''
|
'''
|
||||||
Builds http message with given body.
|
Builds http message with given body.
|
||||||
|
@ -642,12 +671,11 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
|
|
||||||
def parse_http_message(self, message):
|
def parse_http_message(self, message):
|
||||||
'''
|
'''
|
||||||
splits http message to tuple (
|
splits http message to tuple:
|
||||||
statusline - list of e.g. ['HTTP/1.1', '200', 'OK'],
|
(statusline - list of e.g. ['HTTP/1.1', '200', 'OK'],
|
||||||
headers - dictionary of headers e.g. {'Content-Length': '604',
|
headers - dictionary of headers e.g. {'Content-Length': '604',
|
||||||
'Content-Type': 'text/xml; charset=utf-8'},
|
'Content-Type': 'text/xml; charset=utf-8'},
|
||||||
httpbody - string with http body
|
httpbody - string with http body)
|
||||||
)
|
|
||||||
'''
|
'''
|
||||||
message = message.replace('\r','')
|
message = message.replace('\r','')
|
||||||
(header, httpbody) = message.split('\n\n', 1)
|
(header, httpbody) = message.split('\n\n', 1)
|
||||||
|
|
Loading…
Reference in New Issue