예제 #1
0
        async Task <Result> ClientSingleConnectionAsync(Direction dir, AsyncManualResetEvent fireMeWhenReady, CancellationToken cancel)
        {
            Result ret = new Result();

            using (NetPalTcpProtocolStub tcp = new NetPalTcpProtocolStub(cancel: cancel))
            {
                await tcp.ConnectAsync(ServerIP, ServerPort, cancel, ConnectTimeout);

                using (ConnSock sock = new ConnSock(tcp))
                {
                    NetAppStub app = sock.GetNetAppProtocolStub();

                    AttachHandle attachHandle = app.AttachHandle;

                    PipeStream st = app.GetStream();

                    if (dir == Direction.Recv)
                    {
                        app.AttachHandle.SetStreamReceiveTimeout(RecvTimeout);
                    }

                    try
                    {
                        var hello = await st.ReceiveAllAsync(16);

                        if (hello.Span.ToArray()._GetString_Ascii().StartsWith("TrafficServer\r\n") == false)
                        {
                            throw new ApplicationException("Target server is not a Traffic Server.");
                        }

                        //throw new ApplicationException("aaaa" + dir.ToString());

                        fireMeWhenReady.Set();

                        cancel.ThrowIfCancellationRequested();

                        await TaskUtil.WaitObjectsAsync(
                            manualEvents : ClientStartEvent._SingleArray(),
                            cancels : cancel._SingleArray()
                            );

                        long tickStart = FastTick64.Now;
                        long tickEnd   = tickStart + this.TimeSpan;

                        var sendData = new MemoryBuffer <byte>();
                        sendData.WriteBool8(dir == Direction.Recv);
                        sendData.WriteUInt64(SessionId);
                        sendData.WriteSInt64(TimeSpan);

                        await st.SendAsync(sendData);

                        if (dir == Direction.Recv)
                        {
                            RefInt totalRecvSize = new RefInt();
                            while (true)
                            {
                                long now = FastTick64.Now;

                                if (now >= tickEnd)
                                {
                                    break;
                                }

                                await TaskUtil.WaitObjectsAsync(
                                    tasks : st.FastReceiveAsync(totalRecvSize : totalRecvSize)._SingleArray(),
                                    timeout : (int)(tickEnd - now),
                                    exceptions : ExceptionWhen.TaskException | ExceptionWhen.CancelException);

                                ret.NumBytesDownload += totalRecvSize;
                            }
                        }
                        else
                        {
                            attachHandle.SetStreamReceiveTimeout(Timeout.Infinite);

                            while (true)
                            {
                                long now = FastTick64.Now;

                                if (now >= tickEnd)
                                {
                                    break;
                                }

                                /*await WebSocketHelper.WaitObjectsAsync(
                                 *  tasks: st.FastSendAsync(SendData, flush: true).ToSingleArray(),
                                 *  timeout: (int)(tick_end - now),
                                 *  exceptions: ExceptionWhen.TaskException | ExceptionWhen.CancelException);*/

                                await st.FastSendAsync(SendData, flush : true);
                            }

                            Task recvResult = Task.Run(async() =>
                            {
                                var recvMemory = await st.ReceiveAllAsync(8);

                                MemoryBuffer <byte> recvMemoryBuf = recvMemory;
                                ret.NumBytesUpload = recvMemoryBuf.ReadSInt64();

                                st.Disconnect();
                            });

                            Task sendSurprise = Task.Run(async() =>
                            {
                                byte[] surprise = new byte[260];
                                surprise.AsSpan().Fill((byte)'!');
                                while (true)
                                {
                                    await st.SendAsync(surprise);

                                    await TaskUtil.WaitObjectsAsync(
                                        manualEvents: sock.Pipe.OnDisconnectedEvent._SingleArray(),
                                        timeout: 200);
                                }
                            });

                            await WhenAll.Await(false, recvResult, sendSurprise);

                            await recvResult;
                        }

                        st.Disconnect();
                        return(ret);
                    }
                    catch (Exception ex)
                    {
                        ExceptionQueue !.Add(ex);
                        throw;
                    }
                }
            }
        }