""" @author Georg Hopp """ import socket import errno import sys import Transport from contextlib import contextmanager CONTINUE = (errno.EAGAIN, errno.EWOULDBLOCK) if 'win32' == sys.platform: CONTINUE = CONTINUE + (errno.WSAEWOULDBLOCK) class Socket(object): def __init__(self, host, port, socket_type, con_ttl=30): self.socket = None self._host = host self._port = port self._con_ttl = con_ttl self._socket_type = socket_type self._listen = False self._fin_state = 0 def isListen(self): return self._listen def isFin(self): # TODO important, create something sane here. return 0 != self._fin_state def readReady(self): return 0 == self._fin_state & 1 def writeReady(self): return 0 == self._fin_state & 2 def getHandle(self): return self.socket def getHost(self): return self._host def getPort(self): return self._port def getAddr(self): return (self._host, self._port) @contextmanager def _addrinfo(self, flags=0): for res in socket.getaddrinfo( self._host, self._port, socket.AF_UNSPEC, self._socket_type, 0, flags): af, socktype, proto, canonname, self._sa = res try: if not self.socket: self.socket = socket.socket(af, socktype, proto) except socket.error as error: current_exception = error self.socket = None continue try: yield socktype except socket.error as error: current_exception = error self.socket.close() self.socket = None continue break if not self.socket: raise Transport.Error(Transport.Error.ERR_FAILED) def bind(self): with self._addrinfo(socket.AI_PASSIVE): self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self._sa) self.socket.setblocking(0) def open(self): with self._addrinfo(socket.AI_PASSIVE): self.socket.setblocking(0) def shutdownRead(self): try: if 0 == self._fin_state & 1: self.socket.shutdown(socket.SHUT_RD) self._fin_state |= 1 except socket.error as error: self._fin_state |= 3 return self._fin_state def shutdownWrite(self): try: if 0 == self._fin_state & 2: self.socket.shutdown(socket.SHUT_WR) self._fin_state |= 2 except socket.error as error: self._fin_state |= 3 return self._fin_state def shutdown(self): try: if 0 == self._fin_state: self.socket.shutdown(socket.SHUT_RDWR) else: self.shutdownRead() self.shutdownWrite() except socket.error as error: pass self._fin_state |= 3 return self._fin_state def close(self): try: self.shutdown() self.socket.close() except socket.error as error: pass self.socket = None # vim: set ft=python et ts=4 sw=4 sts=4: