def flush(self): """ May raise TcpDisconnect """ if hasattr(self.o, "flush"): try: self.o.flush() except (socket.error, IOError) as v: raise 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 TcpDisconnect() else: raise TcpReadIncomplete("Expected %s bytes, got %s" % (length, len(result))) return result
def write(self, v): """ May raise 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 TcpDisconnect(str(e))
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. if (time.time() - start) < self.o.gettimeout(): time.sleep(0.1) continue else: raise TcpTimeout() except socket.timeout: raise TcpTimeout() except socket.error as e: raise TcpDisconnect(str(e)) except SSL.SysCallError as e: if e.args == (-1, 'Unexpected EOF'): break raise TlsException(str(e)) except SSL.Error as e: raise 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