Пример #1
0
 def send(self, data, flags=0, timeout=timeout_default):
     if timeout is timeout_default:
         timeout = self.timeout
     if self._sslobj:
         if flags != 0:
             raise ValueError(
                 "non-zero flags not allowed in calls to send() on %s" %
                 self.__class__)
         while True:
             try:
                 v = self._sslobj.write(data)
             except SSLError, x:
                 if x.args[0] == SSL_ERROR_WANT_READ:
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     sys.exc_clear()
                     wait_read(self.fileno(), timeout=timeout)
                 elif x.args[0] == SSL_ERROR_WANT_WRITE:
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     sys.exc_clear()
                     wait_write(self.fileno(), timeout=timeout)
                 else:
                     raise
             else:
                 return v
Пример #2
0
 def send(self, data, flags=0, timeout=timeout_default):
     if timeout is timeout_default:
         timeout = self.timeout
     if self._sslobj:
         if flags != 0:
             raise ValueError(
                 "non-zero flags not allowed in calls to send() on %s" %
                 self.__class__)
         while True:
             try:
                 v = self._sslobj.write(data)
             except SSLError, x:
                 if x.args[0] == SSL_ERROR_WANT_READ:
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     sys.exc_clear()
                     wait_read(self.fileno(), timeout=timeout)
                 elif x.args[0] == SSL_ERROR_WANT_WRITE:
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     sys.exc_clear()
                     wait_write(self.fileno(), timeout=timeout)
                 else:
                     raise
             else:
                 return v
Пример #3
0
 def recv_into(self, buffer, nbytes=None, flags=0):
     if buffer and (nbytes is None):
         nbytes = len(buffer)
     elif nbytes is None:
         nbytes = 1024
     if self._sslobj:
         if flags != 0:
             raise ValueError(
                 "non-zero flags not allowed in calls to recv_into() on %s"
                 % self.__class__)
         while True:
             try:
                 tmp_buffer = self.read(nbytes)
                 v = len(tmp_buffer)
                 buffer[:v] = tmp_buffer
                 return v
             except SSLError, x:
                 if x.args[0] == SSL_ERROR_WANT_READ:
                     sys.exc_clear()
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     wait_read(self.fileno(), timeout=self.timeout)
                     continue
                 else:
                     raise
Пример #4
0
 def recv_into(self, buffer, nbytes=None, flags=0):
     if buffer and (nbytes is None):
         nbytes = len(buffer)
     elif nbytes is None:
         nbytes = 1024
     if self._sslobj:
         if flags != 0:
             raise ValueError(
               "non-zero flags not allowed in calls to recv_into() on %s" %
               self.__class__)
         while True:
             try:
                 tmp_buffer = self.read(nbytes)
                 v = len(tmp_buffer)
                 buffer[:v] = tmp_buffer
                 return v
             except SSLError, x:
                 if x.args[0] == SSL_ERROR_WANT_READ:
                     sys.exc_clear()
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     wait_read(self.fileno(), timeout=self.timeout)
                     continue
                 else:
                     raise
Пример #5
0
 def send(self, data, flags=0, timeout=timeout_default):
     if timeout is timeout_default:
         timeout = self.timeout
     while True:
         try:
             return self._sock.send(data, flags)
         except SSL.WantWriteError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_write(self.fileno(), timeout=timeout)
         except SSL.WantReadError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_read(self.fileno(), timeout=timeout)
Пример #6
0
 def send(self, data, flags=0, timeout=timeout_default):
     if timeout is timeout_default:
         timeout = self.timeout
     while True:
         try:
             return self._sock.send(data, flags)
         except SSL.WantWriteError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_write(self.fileno(), timeout=timeout)
         except SSL.WantReadError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_read(self.fileno(), timeout=timeout)
Пример #7
0
 def recv(self, buflen):
     pending = self._sock.pending()
     if pending:
         return self._sock.recv(min(pending, buflen))
     while True:
         try:
             return self._sock.recv(buflen)
         except SSL.WantReadError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_read(self.fileno(), timeout=self.timeout)
         except SSL.WantWriteError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_read(self.fileno(), timeout=self.timeout)
Пример #8
0
 def recv(self, buflen):
     pending = self._sock.pending()
     if pending:
         return self._sock.recv(min(pending, buflen))
     while True:
         try:
             return self._sock.recv(buflen)
         except SSL.WantReadError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_read(self.fileno(), timeout=self.timeout)
         except SSL.WantWriteError, ex:
             if self.timeout == 0.0:
                 raise timeout(str(ex))
             else:
                 sys.exc_clear()
                 wait_read(self.fileno(), timeout=self.timeout)
Пример #9
0
 def wait_for_first_udp(self):
     # wait util first VALID packet come. 
     start = time.time()
     timeout = self.timeout
     while True:
         readable, _, _ = select.select([self.socksconn, self.client2local_udpsock], [], [], timeout)
         if not readable:
             raise socket.timeout("timeout")  # @UndefinedVariable
         if self.socksconn in readable:
             raise RelaySessionError("unexcepted read-event from tcp socket in UDP session")    
     
         timeout -= (time.time() - start)
         if timeout <= 0:
             raise socket.timeout("timeout")  # @UndefinedVariable
         data, addr = self.client2local_udpsock.recvfrom(65536)
         try:
             udpreq = UDPRequest(data)
             if udpreq.frag == '\x00':
                 return data, addr
         except:
             pass
Пример #10
0
 def wait_for_first_udp(self):
     # wait util first VALID packet come. 
     start = time.time()
     timeout = self.timeout
     while True:
         readable = select.select([self.socksconn, self.client2local_udpsock], [], [], timeout)
         if not readable:
             raise socket.timeout("timeout")
         if self.socksconn in readable:
             raise RelaySessionError("unexcepted read-event from tcp socket in UDP session")    
     
         timeout -= (time.time() - start)
         if timeout <= 0:
             raise socket.timeout("timeout")
         data, addr = self.client2local_udpsock.recvfrom(65536)
         try:
             udpreq = UDPRequest(data)
             if udpreq.frag == '\x00':
                 return data, addr
         except:
             pass
Пример #11
0
 def recv(self, buflen=1024, flags=0):
     if self._sslobj:
         if flags != 0:
             raise ValueError(
                 "non-zero flags not allowed in calls to recv() on %s" %
                 self.__class__)
         while True:
             try:
                 return self.read(buflen)
             except SSLError, x:
                 if x.args[0] == SSL_ERROR_WANT_READ:
                     sys.exc_clear()
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     wait_read(self.fileno(), timeout=self.timeout)
                     continue
                 else:
                     raise
Пример #12
0
 def recv(self, buflen=1024, flags=0):
     if self._sslobj:
         if flags != 0:
             raise ValueError(
                 "non-zero flags not allowed in calls to recv() on %s" %
                 self.__class__)
         while True:
             try:
                 return self.read(buflen)
             except SSLError, x:
                 if x.args[0] == SSL_ERROR_WANT_READ:
                     sys.exc_clear()
                     if self.timeout == 0.0:
                         raise timeout(str(x))
                     wait_read(self.fileno(), timeout=self.timeout)
                     continue
                 else:
                     raise
Пример #13
0
def create_connection(
    address,
    timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
    dns_timeout=None,
    source_address=None,
    use_happyeyeballs=True,
    prepare=None,
):
    _log.debug("create_connection %r", address)
    (host, port, *_) = address
    try:
        ipaddress.ip_address(host)
        use_happyeyeballs = False
    except ValueError:
        pass
    if not use_happyeyeballs:
        # TODO: a bit problematic we use socket's hidden timeout sentinel
        # as our default, but it hasn't changed for 12 years so we're probably
        # gonna be fine; maybe!
        return _create_connection(address,
                                  timeout=timeout,
                                  source_address=source_address,
                                  prepare=prepare)

    group = pool.Group()
    # TODO: OK, I'm gonna be honest: this system of greenlet orchestration
    # is really, uhh, let's just say not good; the proper way of implementing
    # this would be something like curio's TaskGroup: a Group that tracks the
    # completion states of its members
    # (0, (family, addr)) = success (gai)
    # (1, sock) = success (result)
    # (-1, (family, None, exc)) = fail (gai)
    # (-2, (family, addr, exc)) = fail (connect)
    bus = queue.Queue()

    def _do_gai(family, proto=0, flags=0):
        _log.debug("_do_gai: started family=%s, proto=%d, flags=%s", family,
                   proto, flags)
        try:
            addrs = gevent.with_timeout(
                dns_timeout,
                socket.getaddrinfo,
                host,
                port,
                family,
                socket.SOCK_STREAM,
                proto,
                flags,
            )
            _log.debug("_do_gai: finished family=%s, addrs=%r", family, addrs)
            while addrs:
                (*_, addr) = addrs.pop()
                bus.put((0, (family, addr)))
        except _Cancel:
            _log.debug("_do_gai: cancelled family=%s", family)
        except gevent.Timeout:
            bus.put((-1, (family, None,
                          socket.gaierror(-errno.ETIMEDOUT, "Timed out"))))
        except Exception as e:
            bus.put((-1, (family, None, e)))

    dns_attempts = 2
    group.apply_async(_do_gai, args=(socket.AF_INET6, 0, socket.AI_V4MAPPED))
    group.apply_async(_do_gai, args=(socket.AF_INET, ))

    def _do_connect(family, addr):
        _log.debug("_do_connect: started family=%s, addr=%s", family, addr)
        # TODO: god I hate the flow of logic in this proc
        sock = socket.socket(family, socket.SOCK_STREAM)
        if source_address:
            sock.bind(source_address)
        if prepare:
            prepare(sock)
        try:
            sock.connect(addr)
            _log.debug(
                "_do_connect: finished family=%s, addr=%s, socket=%r",
                family,
                addr,
                sock,
            )
        except _Cancel:
            _log.debug("_do_connect: cancelled family=%s, addr=%s", family,
                       addr)
        except Exception as e:
            bus.put((-2, (family, addr, e)))
        except:
            sock.close()
            raise
        else:
            return bus.put((1, sock))
        sock.close()

    do_later = queue.Queue()
    started_ipv6 = event.Event()

    def _laterlet():
        try:
            stagger = started_ipv6.wait(timeout=RESOLVE_DELAY)
            if stagger:
                gevent.sleep(CONNECT_DELAY)
            for cb, args, kwds in do_later:
                group.apply_async(cb, args, kwds)
        except _Cancel:
            pass

    group.apply_async(_laterlet)

    if timeout is socket._GLOBAL_DEFAULT_TIMEOUT:
        timeout = None

    started = time.monotonic()
    conn_attempts = 0
    errors = []
    t = timeout
    try:
        while True:
            # TODO: technically this is not right:
            # we take dns query times into account as timeout
            # no good; though there's no better way of solving it
            # without restructuring the entire algo
            if t is not None:
                t = max(MIN_TIMEOUT, timeout - (time.monotonic() - started))
            op, rest = bus.get(timeout=t)
            _log.debug("bus get op %d with payload %s", op, rest)
            _log.debug("error states = %r", errors)
            if op == 1:
                return rest
            elif op == -1:
                errors.append(rest)
                dns_attempts -= 1
                if dns_attempts <= 0:
                    raise socket.error(errors)
                continue
            elif op == -2:
                errors.append(rest)
                conn_attempts -= 1
                if conn_attempts <= 0:
                    raise socket.error(errors)
                continue
            family, addr = rest
            conn_attempts += 1
            if family == socket.AF_INET:
                do_later.put((_do_connect, (socket.AF_INET, addr), {}))
            else:
                started_ipv6.set()
                group.apply_async(_do_connect, (socket.AF_INET6, addr))
    except queue.Empty:
        raise socket.timeout("timed out")
    finally:
        group.kill(_Cancel)