SSL socket blocking error handling

This commit is contained in:
Peter Šurda 2017-02-07 13:00:24 +01:00
parent ddc0ca5ede
commit 15c620dcc2
Signed by: PeterSurda
GPG Key ID: 0C5F50C0B5F37D87
2 changed files with 34 additions and 10 deletions

View File

@ -86,11 +86,11 @@ class receiveDataThread(threading.Thread):
while state.shutdown == 0: while state.shutdown == 0:
dataLen = len(self.data) dataLen = len(self.data)
try: try:
ssl = False isSSL = False
if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
self.connectionIsOrWasFullyEstablished and self.connectionIsOrWasFullyEstablished and
protocol.haveSSL(not self.initiatedConnection)): protocol.haveSSL(not self.initiatedConnection)):
ssl = True isSSL = True
dataRecv = self.sslSock.recv(throttle.ReceiveThrottle().chunkSize) dataRecv = self.sslSock.recv(throttle.ReceiveThrottle().chunkSize)
else: else:
dataRecv = self.sock.recv(throttle.ReceiveThrottle().chunkSize) dataRecv = self.sock.recv(throttle.ReceiveThrottle().chunkSize)
@ -99,13 +99,21 @@ class receiveDataThread(threading.Thread):
except socket.timeout: except socket.timeout:
logger.error ('Timeout occurred waiting for data from ' + str(self.peer) + '. Closing receiveData thread. (ID: ' + str(id(self)) + ')') logger.error ('Timeout occurred waiting for data from ' + str(self.peer) + '. Closing receiveData thread. (ID: ' + str(id(self)) + ')')
break break
except ssl.SSLError as err:
if err.errno == ssl.SSL_ERROR_WANT_READ:
select.select([self.sslSock], [], [], 10)
logger.debug('sock.recv retriable SSL error')
continue
logger.error ('SSL error: %i/%s', err.errno, str(err))
break
except socket.error as err: except socket.error as err:
if err.errno == errno.EWOULDBLOCK: if err.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
if ssl: select.select([self.sslSock if isSSL else self.sock], [], [], 10)
select.select([self.sslSock], [], [], 10) logger.debug('sock.recv retriable error')
else: continue
select.select([self.sock], [], [], 10) if sys.platform.startswith('win') and err.errno in (errno.WSAEAGAIN, errno.WSAEWOULDBLOCK):
logger.error('sock.recv retriable error') select.select([self.sslSock if isSSL else self.sock], [], [], 10)
logger.debug('sock.recv retriable error')
continue continue
logger.error('sock.recv error. Closing receiveData thread (' + str(self.peer) + ', Thread ID: ' + str(id(self)) + ').' + str(err.errno) + "/" + str(err)) logger.error('sock.recv error. Closing receiveData thread (' + str(self.peer) + ', Thread ID: ' + str(id(self)) + ').' + str(err.errno) + "/" + str(err))
if self.initiatedConnection and not self.connectionIsOrWasFullyEstablished: if self.initiatedConnection and not self.connectionIsOrWasFullyEstablished:

View File

@ -5,8 +5,10 @@ import Queue
from struct import unpack, pack from struct import unpack, pack
import hashlib import hashlib
import random import random
import sys import select
import socket import socket
from ssl import SSLError, SSL_ERROR_WANT_WRITE
import sys
from helper_generic import addDataPadding from helper_generic import addDataPadding
from class_objectHashHolder import * from class_objectHashHolder import *
@ -78,17 +80,31 @@ class sendDataThread(threading.Thread):
return return
while self.buffer and state.shutdown == 0: while self.buffer and state.shutdown == 0:
isSSL = False
try: try:
if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
self.connectionIsOrWasFullyEstablished and self.connectionIsOrWasFullyEstablished and
protocol.haveSSL(not self.initiatedConnection)): protocol.haveSSL(not self.initiatedConnection)):
isSSL = True
amountSent = self.sslSock.send(self.buffer[:throttle.SendThrottle().chunkSize]) amountSent = self.sslSock.send(self.buffer[:throttle.SendThrottle().chunkSize])
else: else:
amountSent = self.sock.send(self.buffer[:throttle.SendThrottle().chunkSize]) amountSent = self.sock.send(self.buffer[:throttle.SendThrottle().chunkSize])
except socket.timeout: except socket.timeout:
continue continue
except SSLError as e:
if e.errno == SSL_ERROR_WANT_WRITE:
select.select([], [self.sslSock], [], 10)
logger.debug('sock.recv retriable SSL error')
continue
raise
except socket.error as e: except socket.error as e:
if e.errno == errno.EAGAIN: if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
select.select([], [self.sslSock if isSSL else self.sock], [], 10)
logger.debug('sock.recv retriable error')
continue
if sys.platform.startswith('win') and e.errno in (errno.WSAEAGAIN, errno.WSAEWOULDBLOCK):
select.select([], [self.sslSock if isSSL else self.sock], [], 10)
logger.debug('sock.recv retriable error')
continue continue
raise raise
throttle.SendThrottle().wait(amountSent) throttle.SendThrottle().wait(amountSent)