Пример #1
0
    // Start is called before the first frame update
    void Start()
    {
        uri = new Uri(urlString);
        Debug.Log(QuicheVersion.GetVersion());
        if (isDebugLog)
        {
            QuicheDebug.EnableDebugLogging((line, argp) => {
                Debug.Log(line);
            });
        }
        udpClient    = new UdpClient();
        quicheClient = new QuicheClient(CreateQuicheConfig());
        udpClient.Connect($"{uri.Host}", uri.Port);
        quicheConn = quicheClient.Connect(uri.Authority);
        Debug.Log(
            $"connecting to {uri.Authority} from {udpClient.Client.LocalEndPoint} "
            + $"with scid {quicheClient.HexDump}");
        // initial send
        int write = quicheConn.Send(buf);

        udpClient.Send(buf, write);

        h3Config = new H3Config();
        // Prepare request.
        var reqList = new H3Header[] {
            new H3Header(":method", "GET"),
            new H3Header(":scheme", "https"),
            new H3Header(":authority", uri.Host),
            new H3Header(":path", uri.PathAndQuery),
            new H3Header("user-agent", "unity-quiche"),
        }.ToList();

        // TODO Add custom headers to the request.

        // TODO Add body
        body = null;
        if (body != null)
        {
            reqList.Add(new H3Header(
                            "content-length", $"{body.Length}"));
        }
        req = reqList.ToArray();
    }
Пример #2
0
    // Update is called once per frame
    void Update()
    {
        if (quicheConn == null || quicheConn.IsClosed)
        {
            return;
        }
        quicheConn.OnTimeout();
        if (receiveResult == null)
        {
            receiveResult = udpClient.BeginReceive((res) => {
                var recvBytes = udpClient.EndReceive(res, ref remoteIpEndPoint);
                var read      = quicheConn.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();
                }
            }, null);
        }
        if (receiveResult.IsCompleted)
        {
            receiveResult = null;
        }
        if (quicheConn.IsEstablished && h3Conn == null)
        {
            h3Conn = new H3Connection(quicheConn, h3Config);
        }
        if (h3Conn != null)
        {
            var reqsDone = 0;

            for (var i = reqsSent; i < reqsCount; i++)
            {
                Debug.Log($"sending HTTP request [{string.Join(",", req.Select(x=>H3Header.DebugString(x)))}]");
                var streamId = h3Conn.SendRequest(req, body == null);
                if (streamId == (int)H3Error.QUICHE_H3_TRANSPORT_ERROR)
                {
                    Debug.Log("not enough stream credits, retry later...");
                    break;
                }
                if (streamId < 0)
                {
                    H3Error err = (H3Error)Enum
                                  .ToObject(typeof(H3Error), streamId);
                    Debug.LogError($"recv failed {err}");
                    throw new Exception();
                }
                if (body != null)
                {
                    var e = h3Conn.SendBody((ulong)streamId, body, true);
                    if (e < 0)
                    {
                        H3Error err = (H3Error)Enum
                                      .ToObject(typeof(H3Error), e);
                        Debug.LogError($"recv failed {err}");
                        throw new Exception();
                    }
                }
                reqsDone++;
            }
            reqsSent += reqsDone;
        }
        if (h3Conn != null)
        {
            H3Event ev = null;
            // Process HTTP/3 events.
            while (h3Conn != null)
            {
                var streamId = h3Conn.Poll(ref ev);
                if (streamId == (int)H3Error.QUICHE_H3_DONE)
                {
                    break;
                }
                else if (streamId < 0)
                {
                    H3Error err = (H3Error)Enum
                                  .ToObject(typeof(H3Error), streamId);
                    Debug.LogError($"recv failed {err}");
                    return;
                }
                switch (ev.EventType)
                {
                case (uint)H3EventType.QUICHE_H3_EVENT_HEADERS:
                {
                    var rc = ev.ForEachHeader((name, nameLen, value, valueLen, argp) => {
                            Debug.Log($"got HTTP header: {name}={value}");
                        });
                    if (rc != 0)
                    {
                        Debug.LogError("failed to process headers");
                    }
                    break;
                }

                case (uint)H3EventType.QUICHE_H3_EVENT_DATA:
                {
                    var _out = new byte[65535];
                    var len  = h3Conn.ReceiveBody((ulong)streamId, _out);
                    if (len <= 0)
                    {
                        break;
                    }
                    Debug.Log($"{Encoding.ASCII.GetString(_out.Take((int)len).ToArray())}");
                    break;
                }

                case (uint)H3EventType.QUICHE_H3_EVENT_FINISHED:
                {
                    reqsComplete++;
                    if (reqsComplete == reqsCount)
                    {
                        Debug.Log($"{reqsComplete}/{reqsCount} response(s) received, cloing...");
                        var e = quicheConn.Close(true, 0, Encoding.ASCII.GetBytes("kthxbye"));
                        h3Conn.Dispose();
                        h3Conn = null;
                        if (e == (int)QuicheError.QUICHE_ERR_DONE)
                        {
                            break;
                        }
                        else if (e < 0)
                        {
                            QuicheError err = (QuicheError)Enum
                                              .ToObject(typeof(QuicheError), e);
                            Debug.LogError($"recv failed {err}");
                            throw new Exception();
                        }
                    }
                    break;
                }
                }
                ev.Dispose();
                ev = null;
            }
        }

        var write = quicheConn.Send(buf);

        if (write == (int)QuicheError.QUICHE_ERR_DONE)
        {
            return;
        }
        if (write < 0)
        {
            QuicheError err = (QuicheError)Enum
                              .ToObject(typeof(QuicheError), write);
            Debug.LogError($"send failed {err}");
            throw new Exception();
        }
        udpClient.Send(buf, write);
    }