Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vincent Pelletier
neoppod
Commits
29e8323c
Commit
29e8323c
authored
Apr 28, 2017
by
Julien Muchembled
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Better logging of connector errors
parent
d33cedc0
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
67 additions
and
13 deletions
+67
-13
neo/lib/connection.py
neo/lib/connection.py
+3
-1
neo/lib/connector.py
neo/lib/connector.py
+50
-11
neo/tests/threaded/testSSL.py
neo/tests/threaded/testSSL.py
+14
-1
No files found.
neo/lib/connection.py
View file @
29e8323c
...
@@ -317,9 +317,11 @@ class ListeningConnection(BaseConnection):
...
@@ -317,9 +317,11 @@ class ListeningConnection(BaseConnection):
if
self
.
_ssl
:
if
self
.
_ssl
:
conn
.
connecting
=
True
conn
.
connecting
=
True
connector
.
ssl
(
self
.
_ssl
,
conn
.
_connected
)
connector
.
ssl
(
self
.
_ssl
,
conn
.
_connected
)
# Nothing to send as long as we haven't received a ClientHello
# message.
else
:
else
:
conn
.
_connected
()
conn
.
_connected
()
self
.
em
.
addWriter
(
conn
)
# for SSL
or ENCODED_VERSION
self
.
em
.
addWriter
(
conn
)
# f
or ENCODED_VERSION
def
getAddress
(
self
):
def
getAddress
(
self
):
return
self
.
connector
.
getAddress
()
return
self
.
connector
.
getAddress
()
...
...
neo/lib/connector.py
View file @
29e8323c
...
@@ -67,7 +67,10 @@ class SocketConnector(object):
...
@@ -67,7 +67,10 @@ class SocketConnector(object):
self
.
queued
+=
data
self
.
queued
+=
data
return
was_empty
return
was_empty
def
_error
(
self
,
op
,
exc
):
def
_error
(
self
,
op
,
exc
=
None
):
if
exc
is
None
:
logging
.
debug
(
'%r closed in %s'
,
self
,
op
)
else
:
logging
.
debug
(
"%s failed for %s: %s (%s)"
,
logging
.
debug
(
"%s failed for %s: %s (%s)"
,
op
,
self
,
errno
.
errorcode
[
exc
.
errno
],
exc
.
strerror
)
op
,
self
,
errno
.
errorcode
[
exc
.
errno
],
exc
.
strerror
)
raise
ConnectorException
raise
ConnectorException
...
@@ -152,8 +155,7 @@ class SocketConnector(object):
...
@@ -152,8 +155,7 @@ class SocketConnector(object):
if
data
:
if
data
:
read_buf
.
append
(
data
)
read_buf
.
append
(
data
)
return
return
logging
.
debug
(
'%r closed in recv'
,
self
)
self
.
_error
(
'recv'
)
raise
ConnectorException
def
send
(
self
):
def
send
(
self
):
# XXX: unefficient for big packets
# XXX: unefficient for big packets
...
@@ -241,10 +243,12 @@ def overlay_connector_class(cls):
...
@@ -241,10 +243,12 @@ def overlay_connector_class(cls):
@
overlay_connector_class
@
overlay_connector_class
class
_SSL
:
class
_SSL
:
def
_error
(
self
,
op
,
exc
):
def
_error
(
self
,
op
,
exc
=
None
):
if
isinstance
(
exc
,
ssl
.
SSLError
):
if
isinstance
(
exc
,
ssl
.
SSLError
):
if
not
isinstance
(
exc
,
ssl
.
SSLEOFError
):
logging
.
debug
(
"%s failed for %s: %s"
,
op
,
self
,
exc
)
logging
.
debug
(
"%s failed for %s: %s"
,
op
,
self
,
exc
)
raise
ConnectorException
raise
ConnectorException
exc
=
None
SocketConnector
.
_error
(
self
,
op
,
exc
)
SocketConnector
.
_error
(
self
,
op
,
exc
)
def
receive
(
self
,
read_buf
):
def
receive
(
self
,
read_buf
):
...
@@ -259,7 +263,27 @@ class _SSL:
...
@@ -259,7 +263,27 @@ class _SSL:
@
overlay_connector_class
@
overlay_connector_class
class
_SSLHandshake
(
_SSL
):
class
_SSLHandshake
(
_SSL
):
def
receive
(
self
,
read_buf
=
None
):
# WKRD: Unfortunately, SSL_do_handshake(3SSL) does not try to reject
# non-SSL connections as soon as possible, by checking the first
# byte. It even does nothing before receiving a full TLSPlaintext
# frame (5 bytes).
# The NEO protocol is such that a client connection is always the
# first to send a packet, as soon as the connection is established,
# and without waiting that the protocol versions are checked.
# So in practice, non-SSL connection to SSL would never hang, but
# there's another issue: such case results in WRONG_VERSION_NUMBER
# instead of something like UNEXPECTED_RECORD, because the SSL
# version is checked first.
# For better logging, we try to detect non-SSL connections with
# MSG_PEEK. This only works reliably on server side.
# For SSL client connections, 2 things may prevent the workaround to
# log that the remote node has not enabled SSL:
# - non-SSL data received (or connection closed) before the first
# call to 'recv' in 'do_handshake'
# - the server connection detects a wrong protocol version before it
# sent its one
def
_handshake
(
self
,
read_buf
=
None
):
# ???Writer | send | receive
# ???Writer | send | receive
# -----------+--------+--------
# -----------+--------+--------
# want read | remove | -
# want read | remove | -
...
@@ -271,9 +295,10 @@ class _SSLHandshake(_SSL):
...
@@ -271,9 +295,10 @@ class _SSLHandshake(_SSL):
except
ssl
.
SSLWantWriteError
:
except
ssl
.
SSLWantWriteError
:
return
read_buf
is
not
None
return
read_buf
is
not
None
except
socket
.
error
,
e
:
except
socket
.
error
,
e
:
self
.
_error
(
'
SSL handshake
'
,
e
)
self
.
_error
(
'
send'
if
read_buf
is
None
else
'recv
'
,
e
)
if
not
self
.
queued
[
0
]:
if
not
self
.
queued
[
0
]:
del
self
.
queued
[
0
]
del
self
.
queued
[
0
]
del
self
.
receive
,
self
.
send
self
.
__class__
=
self
.
SSLConnectorClass
self
.
__class__
=
self
.
SSLConnectorClass
cipher
,
proto
,
bits
=
self
.
socket
.
cipher
()
cipher
,
proto
,
bits
=
self
.
socket
.
cipher
()
logging
.
debug
(
"SSL handshake done for %s: %s %s"
,
self
,
cipher
,
bits
)
logging
.
debug
(
"SSL handshake done for %s: %s %s"
,
self
,
cipher
,
bits
)
...
@@ -285,7 +310,21 @@ class _SSLHandshake(_SSL):
...
@@ -285,7 +310,21 @@ class _SSLHandshake(_SSL):
self
.
receive
(
read_buf
)
self
.
receive
(
read_buf
)
return
self
.
queued
return
self
.
queued
send
=
receive
def
send
(
self
,
read_buf
=
None
):
handshake
=
self
.
receive
=
self
.
send
=
self
.
_handshake
return
handshake
(
read_buf
)
def
receive
(
self
,
read_buf
):
try
:
content_type
=
self
.
socket
.
_sock
.
recv
(
1
,
socket
.
MSG_PEEK
)
except
socket
.
error
,
e
:
self
.
_error
(
'recv'
,
e
)
if
content_type
==
'
\
26
'
:
# handshake
return
self
.
send
(
read_buf
)
if
content_type
:
logging
.
debug
(
'Rejecting non-SSL %r'
,
self
)
raise
ConnectorException
self
.
_error
(
'recv'
)
class
ConnectorException
(
Exception
):
class
ConnectorException
(
Exception
):
...
...
neo/tests/threaded/testSSL.py
View file @
29e8323c
...
@@ -15,8 +15,9 @@
...
@@ -15,8 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import
unittest
import
unittest
from
neo.lib.connection
import
ClientConnection
,
ListeningConnection
from
neo.lib.protocol
import
Packets
from
neo.lib.protocol
import
Packets
from
..
import
SSL
from
..
import
Patch
,
SSL
from
.
import
NEOCluster
,
test
,
testReplication
from
.
import
NEOCluster
,
test
,
testReplication
...
@@ -57,6 +58,18 @@ class SSLTests(SSLMixin, test.Test):
...
@@ -57,6 +58,18 @@ class SSLTests(SSLMixin, test.Test):
def
testAbortConnectionBeforeHandshake
(
self
):
def
testAbortConnectionBeforeHandshake
(
self
):
self
.
testAbortConnection
(
0
)
self
.
testAbortConnection
(
0
)
def
testSSLVsNoSSL
(
self
):
def
__init__
(
orig
,
self
,
app
,
*
args
,
**
kw
):
with
Patch
(
app
,
ssl
=
None
):
orig
(
self
,
app
,
*
args
,
**
kw
)
for
cls
in
(
ListeningConnection
,
# SSL connecting to non-SSL
ClientConnection
,
# non-SSL connecting to SSL
):
with
Patch
(
cls
,
__init__
=
__init__
),
\
self
.
getLoopbackConnection
()
as
conn
:
while
not
conn
.
isClosed
():
conn
.
em
.
poll
(
1
)
class
SSLReplicationTests
(
SSLMixin
,
testReplication
.
ReplicationTests
):
class
SSLReplicationTests
(
SSLMixin
,
testReplication
.
ReplicationTests
):
# do not repeat slowest tests with SSL
# do not repeat slowest tests with SSL
testBackupNodeLost
=
testBackupNormalCase
=
None
testBackupNodeLost
=
testBackupNormalCase
=
None
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment