晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。   林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。   见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝)   既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。   南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。 sh-3ll

HOME


sh-3ll 1.0
DIR:/proc/thread-self/root/proc/self/root/usr/lib/python3.9/site-packages/dns/quic/
Upload File :
Current File : //proc/thread-self/root/proc/self/root/usr/lib/python3.9/site-packages/dns/quic/_common.py
# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license

import copy
import functools
import socket
import struct
import time
from typing import Any, Optional

import aioquic.quic.configuration  # type: ignore
import aioquic.quic.connection  # type: ignore

import dns.inet

QUIC_MAX_DATAGRAM = 2048
MAX_SESSION_TICKETS = 8
# If we hit the max sessions limit we will delete this many of the oldest connections.
# The value must be a integer > 0 and <= MAX_SESSION_TICKETS.
SESSIONS_TO_DELETE = MAX_SESSION_TICKETS // 4


class UnexpectedEOF(Exception):
    pass


class Buffer:
    def __init__(self):
        self._buffer = b""
        self._seen_end = False

    def put(self, data, is_end):
        if self._seen_end:
            return
        self._buffer += data
        if is_end:
            self._seen_end = True

    def have(self, amount):
        if len(self._buffer) >= amount:
            return True
        if self._seen_end:
            raise UnexpectedEOF
        return False

    def seen_end(self):
        return self._seen_end

    def get(self, amount):
        assert self.have(amount)
        data = self._buffer[:amount]
        self._buffer = self._buffer[amount:]
        return data


class BaseQuicStream:
    def __init__(self, connection, stream_id):
        self._connection = connection
        self._stream_id = stream_id
        self._buffer = Buffer()
        self._expecting = 0

    def id(self):
        return self._stream_id

    def _expiration_from_timeout(self, timeout):
        if timeout is not None:
            expiration = time.time() + timeout
        else:
            expiration = None
        return expiration

    def _timeout_from_expiration(self, expiration):
        if expiration is not None:
            timeout = max(expiration - time.time(), 0.0)
        else:
            timeout = None
        return timeout

    # Subclass must implement receive() as sync / async and which returns a message
    # or raises UnexpectedEOF.

    def _encapsulate(self, datagram):
        l = len(datagram)
        return struct.pack("!H", l) + datagram

    def _common_add_input(self, data, is_end):
        self._buffer.put(data, is_end)
        try:
            return self._expecting > 0 and self._buffer.have(self._expecting)
        except UnexpectedEOF:
            return True

    def _close(self):
        self._connection.close_stream(self._stream_id)
        self._buffer.put(b"", True)  # send EOF in case we haven't seen it.


class BaseQuicConnection:
    def __init__(
        self, connection, address, port, source=None, source_port=0, manager=None
    ):
        self._done = False
        self._connection = connection
        self._address = address
        self._port = port
        self._closed = False
        self._manager = manager
        self._streams = {}
        self._af = dns.inet.af_for_address(address)
        self._peer = dns.inet.low_level_address_tuple((address, port))
        if source is None and source_port != 0:
            if self._af == socket.AF_INET:
                source = "0.0.0.0"
            elif self._af == socket.AF_INET6:
                source = "::"
            else:
                raise NotImplementedError
        if source:
            self._source = (source, source_port)
        else:
            self._source = None

    def close_stream(self, stream_id):
        del self._streams[stream_id]

    def _get_timer_values(self, closed_is_special=True):
        now = time.time()
        expiration = self._connection.get_timer()
        if expiration is None:
            expiration = now + 3600  # arbitrary "big" value
        interval = max(expiration - now, 0)
        if self._closed and closed_is_special:
            # lower sleep interval to avoid a race in the closing process
            # which can lead to higher latency closing due to sleeping when
            # we have events.
            interval = min(interval, 0.05)
        return (expiration, interval)

    def _handle_timer(self, expiration):
        now = time.time()
        if expiration <= now:
            self._connection.handle_timer(now)


class AsyncQuicConnection(BaseQuicConnection):
    async def make_stream(self, timeout: Optional[float] = None) -> Any:
        pass


class BaseQuicManager:
    def __init__(self, conf, verify_mode, connection_factory, server_name=None):
        self._connections = {}
        self._connection_factory = connection_factory
        self._session_tickets = {}
        if conf is None:
            verify_path = None
            if isinstance(verify_mode, str):
                verify_path = verify_mode
                verify_mode = True
            conf = aioquic.quic.configuration.QuicConfiguration(
                alpn_protocols=["doq", "doq-i03"],
                verify_mode=verify_mode,
                server_name=server_name,
            )
            if verify_path is not None:
                conf.load_verify_locations(verify_path)
        self._conf = conf

    def _connect(
        self, address, port=853, source=None, source_port=0, want_session_ticket=True
    ):
        connection = self._connections.get((address, port))
        if connection is not None:
            return (connection, False)
        conf = self._conf
        if want_session_ticket:
            try:
                session_ticket = self._session_tickets.pop((address, port))
                # We found a session ticket, so make a configuration that uses it.
                conf = copy.copy(conf)
                conf.session_ticket = session_ticket
            except KeyError:
                # No session ticket.
                pass
            # Whether or not we found a session ticket, we want a handler to save
            # one.
            session_ticket_handler = functools.partial(
                self.save_session_ticket, address, port
            )
        else:
            session_ticket_handler = None
        qconn = aioquic.quic.connection.QuicConnection(
            configuration=conf,
            session_ticket_handler=session_ticket_handler,
        )
        lladdress = dns.inet.low_level_address_tuple((address, port))
        qconn.connect(lladdress, time.time())
        connection = self._connection_factory(
            qconn, address, port, source, source_port, self
        )
        self._connections[(address, port)] = connection
        return (connection, True)

    def closed(self, address, port):
        try:
            del self._connections[(address, port)]
        except KeyError:
            pass

    def save_session_ticket(self, address, port, ticket):
        # We rely on dictionaries keys() being in insertion order here.  We
        # can't just popitem() as that would be LIFO which is the opposite of
        # what we want.
        l = len(self._session_tickets)
        if l >= MAX_SESSION_TICKETS:
            keys_to_delete = list(self._session_tickets.keys())[0:SESSIONS_TO_DELETE]
            for key in keys_to_delete:
                del self._session_tickets[key]
        self._session_tickets[(address, port)] = ticket


class AsyncQuicManager(BaseQuicManager):
    def connect(self, address, port=853, source=None, source_port=0):
        raise NotImplementedError