def __init__(self, _socket): """@type socket: native network socket or L{Socket} Whether socket is connected will be detected automatically by means of a zero-length write""" FileDescriptorChannel.__init__(self) if isinstance(_socket, Socket): self.socket = _socket.socket else: self.socket = _socket self.active = True self.blocking = True self.timeout = None self.socket.settimeout(None) # Detect whether socket is connected try: self.socket.send('') except socket.error as e: if e.errno in (10057, 11, 32): # Resource temporarily unavailable or Broken pipe self.connected = False else: self.connected = True else: self.connected = True
def read(self, count, less=False, peek=False): if not self.active: # If we cannot satisfy the request, we need to raise an exception # because we will never be able to do so if len(self.rx_buffer) == 0: # this would always fail raise ChannelClosed, 'channel closed' if len(self.rx_buffer) >= count: # if we can safely satisfy the request right away, do it return FileDescriptorChannel.read(self, count, less, peek) else: # we cannot satisfy all of the request, only less might save us now # from raising an exception if less: return FileDescriptorChannel.read(self, count, less, peek) else: raise ChannelClosed, 'channel closed`' if self.blocking: while len(self.rx_buffer) < count: # We might spend some time here try: s = self.socket.recv(count-len(self.rx_buffer)) except socket.error: self.close() raise UnderlyingFailure, 'socket recv failed' except socket.timeout: raise DataNotAvailable, 'timeout on recv' self.rx_buffer.extend(s) if len(s) == 0: self.close() # The channel has been closed right now. Invoke a recursive # call to this function, it will do the necessary checking, # because now it will be true that self.active == False return Socket.read(self, count, less, peek) if less: # a single recv passed, we can return with less data return FileDescriptorChannel.read(self, count, less, peek) return FileDescriptorChannel.read(self, count, less, peek)
def read(self, count, less=False, peek=False): """ Performs a SSL read. You ask why there is a method ripped out from L{satella.channels.sockets.sockets.Socket} only so that you can change a few lines? Here's the answer. SSL returns SSLError on timeouts. SSLError is a subclass of socket.error, not socket.timeout. This behaviour is a bug but it will not be backported into earlier Python versions (see http://bugs.python.org/issue10272 ). We need to intercept SSLError, check if it's a timeout and then raise suitable exception. """ if not self.active: # If we cannot satisfy the request, we need to raise an exception # because we will never be able to do so if len(self.rx_buffer) == 0: # this would always fail raise ChannelClosed, 'channel closed' if len(self.rx_buffer) >= count: # if we can safely satisfy the request right away, do it return FileDescriptorChannel.read(self, count, less, peek) else: # we cannot satisfy all of the request, only less might save us now # from raising an exception if less: return FileDescriptorChannel.read(self, count, less, peek) else: raise ChannelClosed, 'channel closed`' if self.blocking: while len(self.rx_buffer) < count: # We might spend some time here try: s = self.socket.recv(count-len(self.rx_buffer)) except SSLError as e: # strerror is available under PyPy, and message under CPython serr = e.strerror or e.message if 'timed out' in serr: # timeout raise DataNotAvailable, 'ssl timeout' else: # something else raise UnderlyingFailure, 'socket recv failed' except socket.error: self.close() raise UnderlyingFailure, 'socket recv failed' except socket.timeout: raise DataNotAvailable, 'timeout on recv' self.rx_buffer.extend(s) if len(s) == 0: self.close() # The channel has been closed right now. Invoke a recursive # call to this function, it will do the necessary checking, # because now it will be true that self.active == False return SSLSocket.read(self, count, less, peek) if less: # a single recv passed, we can return with less data return FileDescriptorChannel.read(self, count, less, peek) return FileDescriptorChannel.read(self, count, less, peek)
def settimeout(self, timeout): self.socket.settimeout(timeout) FileDescriptorChannel.settimeout(self, timeout)
def __init__(self, socket): FileDescriptorChannel.__init__(self) self.socket = socket self.blocking = True self.active = True self.socket.settimeout(None)