def flush(self): """ May raise exceptions.TcpDisconnect """ if hasattr(self.o, "flush"): try: self.o.flush() except (socket.error, IOError) as v: raise exceptions.TcpDisconnect(str(v))
def safe_read(self, length): """ Like .read, but is guaranteed to either return length bytes, or raise an exception. """ result = self.read(length) if length != -1 and len(result) != length: if not result: raise exceptions.TcpDisconnect() else: raise exceptions.TcpReadIncomplete( "Expected %s bytes, got %s" % (length, len(result))) return result
def read(self, length): """ If length is -1, we read until connection closes. """ result = b'' start = time.time() while length == -1 or length > 0: if length == -1 or length > self.BLOCKSIZE: rlen = self.BLOCKSIZE else: rlen = length try: data = self.o.read(rlen) except SSL.ZeroReturnError: # TLS connection was shut down cleanly break except (SSL.WantWriteError, SSL.WantReadError): # From the OpenSSL docs: # If the underlying BIO is non-blocking, SSL_read() will also return when the # underlying BIO could not satisfy the needs of SSL_read() to continue the # operation. In this case a call to SSL_get_error with the return value of # SSL_read() will yield SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. # 300 is OpenSSL default timeout timeout = self.o.gettimeout() or 300 if (time.time() - start) < timeout: time.sleep(0.1) continue else: raise exceptions.TcpTimeout() except socket.timeout: raise exceptions.TcpTimeout() except OSError as e: raise exceptions.TcpDisconnect(str(e)) except SSL.SysCallError as e: if e.args == (-1, 'Unexpected EOF'): break raise exceptions.TlsException(str(e)) except SSL.Error as e: raise exceptions.TlsException(str(e)) self.first_byte_timestamp = self.first_byte_timestamp or time.time( ) if not data: break result += data if length != -1: length -= len(data) self.add_log(result) return result
def write(self, v): """ May raise exceptions.TcpDisconnect """ if v: self.first_byte_timestamp = self.first_byte_timestamp or time.time() try: if hasattr(self.o, "sendall"): self.add_log(v) return self.o.sendall(v) else: r = self.o.write(v) self.add_log(v[:r]) return r except (SSL.Error, socket.error) as e: raise exceptions.TcpDisconnect(str(e))