Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
gajim
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Weblate
gajim
Commits
4d904560
Commit
4d904560
authored
15 years ago
by
Alexander Cherniuk
Browse files
Options
Downloads
Patches
Plain Diff
Last portion of doc-string and formatting refactoring
parent
f084a1f7
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/common/xmpp/stringprepare.py
+31
-20
31 additions, 20 deletions
src/common/xmpp/stringprepare.py
src/common/xmpp/tls_nb.py
+31
-19
31 additions, 19 deletions
src/common/xmpp/tls_nb.py
src/common/xmpp/transports_nb.py
+97
-77
97 additions, 77 deletions
src/common/xmpp/transports_nb.py
with
159 additions
and
116 deletions
src/common/xmpp/stringprepare.py
+
31
−
20
View file @
4d904560
...
...
@@ -26,16 +26,26 @@ import unicodedata
from
encodings
import
idna
class
ILookupTable
:
"""
Interface for character lookup classes.
"""
"""
Interface for character lookup classes
"""
def
lookup
(
self
,
c
):
"""
Return whether character is in this table.
"""
"""
Return whether character is in this table
"""
pass
class
IMappingTable
:
"""
Interface for character mapping classes.
"""
"""
Interface for character mapping classes
"""
def
map
(
self
,
c
):
"""
Return mapping for character.
"""
"""
Return mapping for character
"""
pass
class
LookupTableFromFunction
:
...
...
@@ -75,8 +85,8 @@ class EmptyMappingTable:
return
c
class
Profile
:
def
__init__
(
self
,
mappings
=
[],
normalize
=
True
,
prohibiteds
=
[],
check_unassigneds
=
True
,
check_bidi
=
True
):
def
__init__
(
self
,
mappings
=
[],
normalize
=
True
,
prohibiteds
=
[],
check_unassigneds
=
True
,
check_bidi
=
True
):
self
.
mappings
=
mappings
self
.
normalize
=
normalize
self
.
prohibiteds
=
prohibiteds
...
...
@@ -140,24 +150,25 @@ class Profile:
class
NamePrep
:
"""
Implements preparation of internationalized domain names.
"""
Implements preparation of internationalized domain names
This class implements preparing internationalized domain names using the
rules defined in RFC 3491, section 4 (Conversion operations).
This class implements preparing internationalized domain names using the
rules defined in RFC 3491, section 4 (Conversion operations).
We do not perform step 4 since we deal with unicode representations of
domain names and do not convert from or to ASCII representations using
punycode encoding. When such a conversion is needed, the L{idna} standard
library provides the C{ToUnicode()} and C{ToASCII()} functions. Note that
L{idna} itself assumes UseSTD3ASCIIRules to be false.
We do not perform step 4 since we deal with unicode representations of
domain names and do not convert from or to ASCII representations using
punycode encoding. When such a conversion is needed, the L{idna} standard
library provides the C{ToUnicode()} and C{ToASCII()} functions. Note that
L{idna} itself assumes UseSTD3ASCIIRules to be false.
The following steps are performed by C{prepare()}:
The following steps are performed by C{prepare()}:
* Split the domain name in labels at the dots (RFC 3490, 3.1)
* Apply nameprep proper on each label (RFC 3491)
* Enforce the restrictions on ASCII characters in host names by
assuming STD3ASCIIRules to be true. (STD 3)
* Rejoin the labels using the label separator U+002E (full stop).
* Split the domain name in labels at the dots (RFC 3490, 3.1)
* Apply nameprep proper on each label (RFC 3491)
* Enforce the restrictions on ASCII characters in host names by
assuming STD3ASCIIRules to be true. (STD 3)
* Rejoin the labels using the label separator U+002E (full stop).
"""
# Prohibited characters.
...
...
This diff is collapsed.
Click to expand it.
src/common/xmpp/tls_nb.py
+
31
−
19
View file @
4d904560
...
...
@@ -54,13 +54,17 @@ def gattr(obj, attr, default=None):
class
SSLWrapper
:
'''
"""
Abstract SSLWrapper base class
'''
"""
class
Error
(
IOError
):
'''
Generic SSL Error Wrapper
'''
"""
Generic SSL Error Wrapper
"""
def
__init__
(
self
,
sock
=
None
,
exc
=
None
,
errno
=
None
,
strerror
=
None
,
peer
=
None
):
peer
=
None
):
self
.
parent
=
IOError
errno
=
errno
or
gattr
(
exc
,
'
errno
'
)
or
exc
[
0
]
...
...
@@ -122,7 +126,7 @@ class SSLWrapper:
log
.
debug
(
"
%s.__init__ called with %s
"
,
self
.
__class__
,
sslobj
)
def
recv
(
self
,
data
,
flags
=
None
):
'''
"""
Receive wrapper for SSL object
We can return None out of this function to signal that no data is
...
...
@@ -130,16 +134,20 @@ class SSLWrapper:
depending on which SSL lib we
'
re using. Unfortunately returning
''
can indicate that the socket has been closed, so to be sure, we avoid
this by returning None.
'''
"""
raise
NotImplementedError
def
send
(
self
,
data
,
flags
=
None
,
now
=
False
):
'''
Send wrapper for SSL object
'''
"""
Send wrapper for SSL object
"""
raise
NotImplementedError
class
PyOpenSSLWrapper
(
SSLWrapper
):
'''
Wrapper class for PyOpenSSL
'
s recv() and send() methods
'''
"""
Wrapper class for PyOpenSSL
'
s recv() and send() methods
"""
def
__init__
(
self
,
*
args
):
self
.
parent
=
SSLWrapper
...
...
@@ -202,7 +210,9 @@ class PyOpenSSLWrapper(SSLWrapper):
class
StdlibSSLWrapper
(
SSLWrapper
):
'''
Wrapper class for Python socket.ssl read() and write() methods
'''
"""
Wrapper class for Python socket.ssl read() and write() methods
"""
def
__init__
(
self
,
*
args
):
self
.
parent
=
SSLWrapper
...
...
@@ -230,18 +240,18 @@ class StdlibSSLWrapper(SSLWrapper):
class
NonBlockingTLS
(
PlugIn
):
'''
TLS connection used to encrypts already estabilished tcp connection
.
"""
TLS connection used to encrypts already estabilished tcp connection
Can be plugged into NonBlockingTCP and will make use of StdlibSSLWrapper or
PyOpenSSLWrapper.
'''
"""
def
__init__
(
self
,
cacerts
,
mycerts
):
'''
"""
:param cacerts: path to pem file with certificates of known XMPP servers
:param mycerts: path to pem file with certificates of user trusted servers
'''
"""
PlugIn
.
__init__
(
self
)
self
.
cacerts
=
cacerts
self
.
mycerts
=
mycerts
...
...
@@ -254,10 +264,10 @@ class NonBlockingTLS(PlugIn):
"
SSL_CB_HANDSHAKE_START
"
:
0x10
,
"
SSL_CB_HANDSHAKE_DONE
"
:
0x20
}
def
plugin
(
self
,
owner
):
'''
Use to PlugIn TLS into transport and start establishing immediately
Returns True if TLS/SSL was established correctly, otherwise False
.
'''
"""
Use to PlugIn TLS into transport and start establishing immediately
.
Returns True if TLS/SSL was established correctly, otherwise False
"""
log
.
info
(
'
Starting TLS estabilishing
'
)
try
:
res
=
self
.
_startSSL
()
...
...
@@ -289,7 +299,9 @@ class NonBlockingTLS(PlugIn):
"
Unknown
"
),
pkey
.
type
())
def
_startSSL
(
self
):
'''
Immediatedly switch socket to TLS mode. Used internally.
'''
"""
Immediatedly switch socket to TLS mode. Used internally
"""
log
.
debug
(
"
_startSSL called
"
)
if
USE_PYOPENSSL
:
...
...
This diff is collapsed.
Click to expand it.
src/common/xmpp/transports_nb.py
+
97
−
77
View file @
4d904560
...
...
@@ -15,14 +15,14 @@
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## 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 and only responsible for low-level
connection handling.
'''
"""
from
simplexml
import
ustr
from
plugin
import
PlugIn
...
...
@@ -41,12 +41,12 @@ import logging
log
=
logging
.
getLogger
(
'
gajim.c.x.transports_nb
'
)
def
urisplit
(
uri
):
'''
"""
Function for splitting URI string to tuple (protocol, host, port, path).
e.g. urisplit(
'
http://httpcm.jabber.org:123/webclient
'
) returns
(
'
http
'
,
'
httpcm.jabber.org
'
, 123,
'
/webclient
'
)
return 443 as default port if proto
is https else 80
'''
e.g. urisplit(
'
http://httpcm.jabber.org:123/webclient
'
) returns
(
'
http
'
,
'
httpcm.jabber.org
'
, 123,
'
/webclient
'
)
return 443 as default port if proto
is https else 80
"""
splitted
=
urlparse
.
urlsplit
(
uri
)
proto
,
host
,
path
=
splitted
.
scheme
,
splitted
.
hostname
,
splitted
.
path
try
:
...
...
@@ -102,17 +102,18 @@ CONNECTED = 'CONNECTED'
STATES
=
(
DISCONNECTED
,
CONNECTING
,
PROXY_CONNECTING
,
CONNECTED
,
DISCONNECTING
)
class
NonBlockingTransport
(
PlugIn
):
'''
Abstract class representing a transport
.
"""
Abstract class representing a transport
Subclasses CAN have different constructor signature but connect method SHOULD
be the same.
'''
"""
def
__init__
(
self
,
raise_event
,
on_disconnect
,
idlequeue
,
estabilish_tls
,
certs
):
'''
certs
):
"""
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
:param raise_event: callback for monitoring of sent and received data
:param on_disconnect: callback called on disconnection during runtime
...
...
@@ -121,7 +122,7 @@ class NonBlockingTransport(PlugIn):
TCP connection is done
:param certs: tuple of (cacerts, mycerts) see constructor of
tls_nb.NonBlockingTLS for more details
'''
"""
PlugIn
.
__init__
(
self
)
self
.
raise_event
=
raise_event
self
.
on_disconnect
=
on_disconnect
...
...
@@ -157,14 +158,14 @@ class NonBlockingTransport(PlugIn):
self
.
disconnect
(
do_callback
=
False
)
def
connect
(
self
,
conn_5tuple
,
on_connect
,
on_connect_failure
):
'''
"""
Creates and connects transport to server and port defined in conn_5tuple
which 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 on_connect: callback called on successful connect to the server
:param on_connect_failure: callback called on failure when connecting
'''
"""
self
.
on_connect
=
on_connect
self
.
on_connect_failure
=
on_connect_failure
self
.
server
,
self
.
port
=
conn_5tuple
[
4
][:
2
]
...
...
@@ -178,14 +179,18 @@ class NonBlockingTransport(PlugIn):
return
self
.
state
def
_on_connect
(
self
):
'''
preceeds call of on_connect callback
'''
"""
Preceeds call of on_connect callback
"""
# data is reference to socket wrapper instance. We don't need it in client
# because
self
.
set_state
(
CONNECTED
)
self
.
on_connect
()
def
_on_connect_failure
(
self
,
err_message
):
'''
preceeds call of on_connect_failure callback
'''
"""
Preceeds call of on_connect_failure callback
"""
# In case of error while connecting we need to disconnect transport
# but we don't want to call DisconnectHandlers from client,
# thus the do_callback=False
...
...
@@ -204,15 +209,16 @@ class NonBlockingTransport(PlugIn):
self
.
on_disconnect
()
def
onreceive
(
self
,
recv_handler
):
'''
Set
s
the on_receive callback.
"""
Set the on_receive callback.
onreceive(None) sets callback to Dispatcher.ProcessNonBlocking which is
the default one that will decide what to do with received stanza based on
its tag name and namespace.
Do not confuse it with on_receive() method, which is the callback itself.
'''
Do not confuse it with on_receive() method, which is the callback
itself.
"""
if
not
recv_handler
:
if
hasattr
(
self
,
'
_owner
'
)
and
hasattr
(
self
.
_owner
,
'
Dispatcher
'
):
self
.
on_receive
=
self
.
_owner
.
Dispatcher
.
ProcessNonBlocking
...
...
@@ -226,13 +232,17 @@ class NonBlockingTransport(PlugIn):
self
.
set_state
(
CONNECTING
)
def
read_timeout
(
self
):
'''
called when there
'
s no response from server in defined timeout
'''
"""
Called when there
'
s no response from server in defined timeout
"""
if
self
.
on_timeout
:
self
.
on_timeout
()
self
.
renew_send_timeout
()
def
read_timeout2
(
self
):
'''
called when there
'
s no response from server in defined timeout
'''
"""
called when there
'
s no response from server in defined timeout
"""
if
self
.
on_timeout2
:
self
.
on_timeout2
()
self
.
renew_send_timeout2
()
...
...
@@ -277,17 +287,17 @@ class NonBlockingTransport(PlugIn):
class
NonBlockingTCP
(
NonBlockingTransport
,
IdleObject
):
'''
Non-blocking TCP socket wrapper
.
"""
Non-blocking TCP socket wrapper
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
,
certs
,
proxy_dict
=
None
):
'''
certs
,
proxy_dict
=
None
):
"""
:param proxy_dict: dictionary with proxy data as loaded from config file
'''
"""
NonBlockingTransport
.
__init__
(
self
,
raise_event
,
on_disconnect
,
idlequeue
,
estabilish_tls
,
certs
)
IdleObject
.
__init__
(
self
)
...
...
@@ -371,10 +381,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
proxy_creds
=
self
.
proxy_dict
[
'
credentials
'
])
def
_on_connect
(
self
):
'''
Preceed
s
invoking of on_connect callback. TCP connection is already
estabilished by this time
.
'''
"""
Preceed invoking of on_connect callback. TCP connection is already
estabilished by this time
"""
if
self
.
estabilish_tls
:
self
.
tls_init
(
on_succ
=
lambda
:
NonBlockingTransport
.
_on_connect
(
self
),
...
...
@@ -384,10 +394,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
NonBlockingTransport
.
_on_connect
(
self
)
def
tls_init
(
self
,
on_succ
,
on_fail
):
'''
"""
Estabilishes TLS/SSL using this TCP connection by plugging a
NonBlockingTLS module
'''
"""
cacerts
,
mycerts
=
self
.
certs
result
=
tls_nb
.
NonBlockingTLS
.
get_instance
(
cacerts
,
mycerts
).
PlugIn
(
self
)
if
result
:
...
...
@@ -396,12 +406,16 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
on_fail
()
def
pollin
(
self
):
'''
called by idlequeu 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
())
self
.
_do_receive
()
def
pollout
(
self
):
'''
called by idlequeu 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
())
if
self
.
get_state
()
==
CONNECTING
:
...
...
@@ -417,7 +431,9 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self
.
_do_send
()
def
pollend
(
self
):
'''
called by idlequeue on TCP connection errors
'''
"""
Called by idlequeue on TCP connection errors
"""
log
.
info
(
'
pollend called, state == %s
'
%
self
.
get_state
())
if
self
.
get_state
()
==
CONNECTING
:
...
...
@@ -465,10 +481,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
log
.
warn
(
'
remove_timeout: no self.fd state is %s
'
%
self
.
get_state
())
def
send
(
self
,
raw_data
,
now
=
False
):
'''
Append raw_data to the queue of messages to be send.
If supplied data is
unicode string, encode it to utf-8.
'''
"""
Append raw_data to the queue of messages to be send.
If supplied data is
unicode string, encode it to utf-8.
"""
NonBlockingTransport
.
send
(
self
,
raw_data
,
now
)
r
=
self
.
encode_stanza
(
raw_data
)
...
...
@@ -482,7 +498,9 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self
.
_plug_idle
(
writable
=
True
,
readable
=
True
)
def
encode_stanza
(
self
,
stanza
):
'''
Encode str or unicode to utf-8
'''
"""
Encode str or unicode to utf-8
"""
if
isinstance
(
stanza
,
unicode
):
stanza
=
stanza
.
encode
(
'
utf-8
'
)
elif
not
isinstance
(
stanza
,
str
):
...
...
@@ -490,8 +508,8 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
return
stanza
def
_plug_idle
(
self
,
writable
,
readable
):
'''
Plug
s
file descriptor of socket to Idlequeue
.
"""
Plug file descriptor of socket to Idlequeue
Plugged socket will be watched for
"
send possible
"
or/and
"
recv possible
"
events. pollin() callback is invoked on
"
recv possible
"
, pollout() on
...
...
@@ -499,15 +517,15 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
Plugged socket will always be watched for
"
error
"
event - in that case,
pollend() is called.
'''
"""
log
.
info
(
'
Plugging fd %d, W:%s, R:%s
'
%
(
self
.
fd
,
writable
,
readable
))
self
.
idlequeue
.
plug_idle
(
self
,
writable
,
readable
)
def
_do_send
(
self
):
'''
"""
Called when send() to connected socket is possible. First message from
sendqueue will be sent
.
'''
sendqueue will be sent
"""
if
not
self
.
sendbuff
:
if
not
self
.
sendqueue
:
log
.
warn
(
'
calling send on empty buffer and queue
'
)
...
...
@@ -530,10 +548,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self
.
disconnect
()
def
_do_receive
(
self
):
'''
"""
Reads all pending incoming data. Will call owner
'
s disconnected() method
if appropriate
.
'''
if appropriate
"""
received
=
None
errnum
=
0
errstr
=
'
No Error Set
'
...
...
@@ -588,27 +606,29 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
self
.
disconnect
()
def
_on_receive
(
self
,
data
):
'''
preceeds on_receive callback. It peels off and checks HTTP headers in
HTTP classes, in here it just calls the callback.
'''
"""
Preceeds on_receive callback. It peels off and checks HTTP headers in
HTTP classes, in here it just calls the callback
"""
self
.
on_receive
(
data
)
class
NonBlockingHTTP
(
NonBlockingTCP
):
'''
Socket wrapper that creates HTTP message out of sent data and peels-off
HTTP
headers from incoming messages
.
'''
"""
Socket wrapper that creates HTTP message out of sent data and peels-off
HTTP
headers from incoming messages
"""
def
__init__
(
self
,
raise_event
,
on_disconnect
,
idlequeue
,
estabilish_tls
,
certs
,
on_http_request_possible
,
on_persistent_fallback
,
http_dict
,
proxy_dict
=
None
):
'''
certs
,
on_http_request_possible
,
on_persistent_fallback
,
http_dict
,
proxy_dict
=
None
):
"""
:param on_http_request_possible: method to call when HTTP request to
socket owned by transport is possible.
:param on_persistent_fallback: callback called when server ends TCP
connection. It doesn
'
t have to be fatal for HTTP session.
:param http_dict: dictionary with data for HTTP request and headers
'''
"""
NonBlockingTCP
.
__init__
(
self
,
raise_event
,
on_disconnect
,
idlequeue
,
estabilish_tls
,
certs
,
proxy_dict
)
...
...
@@ -639,10 +659,10 @@ class NonBlockingHTTP(NonBlockingTCP):
self
.
send
(
self
.
build_http_message
(
raw_data
),
now
)
def
_on_receive
(
self
,
data
):
'''
"""
Preceeds passing received data to owner class. Gets rid of HTTP headers
and checks them.
'''
"""
if
self
.
get_state
()
==
PROXY_CONNECTING
:
NonBlockingTCP
.
_on_receive
(
self
,
data
)
return
...
...
@@ -686,10 +706,10 @@ class NonBlockingHTTP(NonBlockingTCP):
self
.
on_http_request_possible
()
def
build_http_message
(
self
,
httpbody
,
method
=
'
POST
'
):
'''
Builds http message with given body.
Values for headers and status line
fields are taken from class variables
.
'''
"""
Builds http message with given body.
Values for headers and status line
fields are taken from class variables
"""
absolute_uri
=
'
%s://%s:%s%s
'
%
(
self
.
http_protocol
,
self
.
http_host
,
self
.
http_port
,
self
.
http_path
)
headers
=
[
'
%s %s %s
'
%
(
method
,
absolute_uri
,
self
.
http_version
),
...
...
@@ -711,14 +731,14 @@ class NonBlockingHTTP(NonBlockingTCP):
return
(
'
%s%s
'
%
(
headers
,
httpbody
))
def
parse_http_message
(
self
,
message
):
'''
s
plit
s
http message
to
tuple:
"""
S
plit http message
into a
tuple:
(statusline - list of e.g. [
'
HTTP/1.1
'
,
'
200
'
,
'
OK
'
],
headers - dictionary of headers e.g. {
'
Content-Length
'
:
'
604
'
,
'
Content-Type
'
:
'
text/xml; charset=utf-8
'
},
httpbody - string with http body)
http_rest - what is left in the message after a full HTTP header + body
'''
"""
message
=
message
.
replace
(
'
\r
'
,
''
)
message
=
message
.
lstrip
(
'
\n
'
)
splitted
=
message
.
split
(
'
\n\n
'
)
...
...
@@ -745,10 +765,10 @@ class NonBlockingHTTP(NonBlockingTCP):
class
NonBlockingHTTPBOSH
(
NonBlockingHTTP
):
'''
Class for BOSH HTTP connections. Slightly redefines HTTP transport by
calling
bosh bodytag generating callback before putting data on wire
.
'''
"""
Class for BOSH HTTP connections. Slightly redefines HTTP transport by
calling
bosh bodytag generating callback before putting data on wire
"""
def
set_stanza_build_cb
(
self
,
build_cb
):
self
.
build_cb
=
build_cb
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment