private byte[] MintToken(QuicheHeaderInfo header, IPEndPoint src)
    {
        var token = Encoding.ASCII.GetBytes("quiche");
        var addr  = src.Address.GetAddressBytes();

        return(token.Concat(addr).Concat(header.Dcid).ToArray());
    }
    private void Poll(ClientState state)
    {
        var recvBytes        = state.ReceiveBytes;
        var remoteIpEndPoint = state.remoteIpEndPoint;
        QuicheHeaderInfo header;

        try{
            header = QuicheHeaderInfo.Construct(recvBytes);
        } catch (Exception e)
        {
            Debug.LogError($"{e}");
            return;
        }

        if (header.Type == 6 /* Type::VersionNegotiation */)
        {
            Debug.LogError("Version negotiation invalid on the server");
            return;
        }

        var key = HexDump(header.Dcid);

        Client client;

        if (!clients.TryGetValue(key, out client))
        {
            if (header.Type != 1 /* Type::Initial */)
            {
                Debug.LogError("Packet is not Initial");
                return;
            }

            if (!VersionIsSupported(header.Version))
            {
                Debug.LogWarning("Doing version negotiation");

                var length = (int)NegotiateVersion(
                    header.Scid, header.Dcid, negotiateBuf);
                var sendBuf = negotiateBuf.Take(length).ToArray();
                udpClient.Send(sendBuf, length, remoteIpEndPoint);
                return;
            }
            var scid = new byte[QuicheClient.LOCAL_CONN_ID_LEN];
            new System.Random().NextBytes(scid);
            byte[] odcid = new byte[65535];
            if (!noRetry)
            {
                if (header.Token.Length == 0)
                {
                    Debug.LogWarning("Doing stateless retry");

                    Debug.Log($"Retry: scid={HexDump(header.Scid)} new_scid={HexDump(scid)}");

                    var new_token = MintToken(header, remoteIpEndPoint);
                    var _out      = new byte[65535];
                    var written   = (int)Retry(header.Scid, header.Dcid, scid, new_token, _out);
                    udpClient.Send(
                        _out.Take(written).ToArray(), written, remoteIpEndPoint);
                    return;
                }
                odcid = ValidateToken(header.Token, remoteIpEndPoint);
                if (odcid == null)
                {
                    Debug.LogError("Invalid address validation token");
                    return;
                }
            }
            if (scid.Length != header.Dcid.Length)
            {
                Debug.LogError("Invalid destination connection ID");
                return;
            }
            scid = header.Dcid;
            var conn    = quiche.Accept(scid, odcid);
            var _client = new Client(conn, remoteIpEndPoint);
            clients.Add(HexDump(scid), _client);
            client = _client;
        }
        var read = client.Connection.Receive(recvBytes);

        if (read == (int)QuicheError.QUICHE_ERR_DONE)
        {
            Debug.Log("done reading");
            return;
        }
        if (read < 0)
        {
            QuicheError err = (QuicheError)Enum
                              .ToObject(typeof(QuicheError), read);
            Debug.LogError($"recv failed {err}");
            throw new Exception();
        }
        Debug.Log($"recv {read} bytes");
        if (client.Connection.IsInEarlyData || client.Connection.IsEstablished)
        {
            foreach (ulong streamId in client.Connection.Writable())
            {
                if (!client.PartialResponses.ContainsKey(streamId))
                {
                    continue;
                }
                var partialResponse = client.PartialResponses[streamId];
                var written         = client.Connection.StreamSend(streamId, partialResponse.Body, true);
                if (written < 0)
                {
                    continue;
                }
                partialResponse.Written += written;
                if (partialResponse.Written == partialResponse.Body.Length)
                {
                    client.PartialResponses.Remove(streamId);
                }
            }
            foreach (ulong streamId in client.Connection.Readable())
            {
                Debug.Log($"stream {streamId} is readable");
                bool fin        = false;
                var  readStream = client.Connection.StreamReceive(
                    streamId, streamRecv, ref fin);
                if (readStream < 0)
                {
                    continue;
                }
                if (fin)
                {
                    var body    = Encoding.ASCII.GetBytes("Hello World!\n");
                    var written = client.Connection.StreamSend(
                        streamId, body, true);
                    if (written < 0)
                    {
                        continue;
                    }
                    if (written < body.Length)
                    {
                        var partialResponse = new PartialResponse(body, written);
                        client.PartialResponses.Add(streamId, partialResponse);
                    }
                }
            }
        }
    }