Example #1
0
 void OnDestroy()
 {
     if (h3Conn != null)
     {
         h3Conn.Dispose();
         h3Conn = null;
     }
     if (h3Config != null)
     {
         h3Config.Dispose();
         h3Config = null;
     }
     if (quicheClient != null)
     {
         quicheClient.Dispose();
         quicheClient = null;
     }
     if (udpClient != null)
     {
         udpClient.Dispose();
         udpClient = null;
     }
 }
Example #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);
    }