예제 #1
0
        async Task SendLoopAsync()
        {
            try
            {
                CancellationToken cancel = this.GrandCancel;

                LocalTimer timer = new LocalTimer();

                long nextPingTick = timer.AddTimeout(0);

                while (true)
                {
                    await LowerStream.WaitReadyToSendAsync(cancel, Timeout.Infinite);

                    await UpperStream.WaitReadyToReceiveAsync(cancel, timer.GetNextInterval(), noTimeoutException : true, cancelEvent : this.SendPongEvent);

                    MemoryBuffer <byte> sendBuffer = new MemoryBuffer <byte>();

                    IReadOnlyList <ReadOnlyMemory <byte> > userDataList = UpperStream.FastReceiveNonBlock(out int totalRecvSize, maxSize: Options.MaxBufferSize);

                    if (totalRecvSize >= 1)
                    {
                        // Send data
                        if (Options.RespectMessageDelimiter == false)
                        {
                            userDataList = Util.DefragmentMemoryArrays(userDataList, Options.SendSingleFragmentSize);
                        }

                        foreach (ReadOnlyMemory <byte> userData in userDataList)
                        {
                            if (userData.Length >= 1)
                            {
                                BuildAndAppendFrame(sendBuffer, true, WebSocketOpcode.Bin, userData);
                            }
                        }
                    }

                    if (timer.Now >= nextPingTick)
                    {
                        // Send ping
                        nextPingTick = timer.AddTimeout(Util.GenRandInterval(Options.SendPingInterval));

                        BuildAndAppendFrame(sendBuffer, true, WebSocketOpcode.Ping, "[WebSocketPing]"._GetBytes_Ascii());
                    }

                    lock (this.PongQueueLock)
                    {
                        // Send pong
                        while (true)
                        {
                            if (this.PongQueue.TryDequeue(out ReadOnlyMemory <byte> data) == false)
                            {
                                break;
                            }

                            BuildAndAppendFrame(sendBuffer, true, WebSocketOpcode.Pong, data);
                        }
                    }

                    if (sendBuffer.Length >= 1)
                    {
                        LowerStream.FastSendNonBlock(sendBuffer.Memory);
                    }
                }
            }
            catch (Exception ex)
            {
                this.UpperStream.Disconnect();
                this.Cancel(ex);
            }
        }
예제 #2
0
    async Task SendLoopAsync(int keepaliveInterval)
    {
        try
        {
            CancellationToken cancel = this.GrandCancel;

            LocalTimer timer = new LocalTimer();

            long nextPingTick = timer.AddTimeout(0);

            bool initialFourZeroSent = false;

            bool localFlag_C2S_SwitchToWebSocket_Requested = false;

            while (true)
            {
                MemoryBuffer <byte> sendBuffer = new MemoryBuffer <byte>();

                if (initialFourZeroSent == false)
                {
                    // 最初の 0x00000000 (4 バイト) を送信
                    initialFourZeroSent = true;
                    sendBuffer.WriteSInt32(4);
                    sendBuffer.WriteSInt32(0x00000000);
                }

                // 上位ストリームからのデータを送信
                IReadOnlyList <ReadOnlyMemory <byte> > userDataList = UpperStream.FastReceiveNonBlock(out int totalSendSize, maxSize: Consts.WideTunnelConsts.MaxBlockSize);

                if (totalSendSize >= 1)
                {
                    // Send data
                    foreach (var mem in userDataList)
                    {
                        //$"Send: {mem.Length}"._Debug();
                        //$"SendData: {mem._GetHexString()}"._Debug();
                        sendBuffer.WriteSInt32(mem.Length);
                        sendBuffer.Write(mem);
                    }
                }

                if (timer.Now >= nextPingTick)
                {
                    // Send ping
                    sendBuffer.WriteSInt32(0);

                    nextPingTick = timer.AddTimeout(Util.GenRandInterval(keepaliveInterval));
                }

                if (localFlag_C2S_SwitchToWebSocket_Requested == false && this.C2S_SwitchToWebSocket_Requested)
                {
                    // Web socket switch request invoked (only once)
                    $"Web socket switch request invoked"._Debug();
                    localFlag_C2S_SwitchToWebSocket_Requested = true;
                    sendBuffer.WriteSInt32(Consts.WideTunnelConsts.SpecialOpCode_C2S_SwitchToWebSocket_Request_Guacd);
                }

                if (sendBuffer.IsThisEmpty() == false)
                {
                    //$"RawSendData: {sendBuffer.Span._GetHexString()}"._Debug();
                    LowerStream.FastSendNonBlock(sendBuffer);
                }

                await LowerStream.WaitReadyToSendAsync(cancel, Timeout.Infinite);

                await UpperStream.WaitReadyToReceiveAsync(cancel, timer.GetNextInterval(), noTimeoutException : true, cancelEvent : C2S_SpecialOp_Event);
            }
        }
        catch (Exception ex)
        {
            //                ex._Debug();
            this.UpperStream.Disconnect();
            await this.CleanupAsync(ex);
        }
    }