public async Task ConnectionDoesNotResumeAfterSocketCloseIfBackpressureIsApplied()
        {
            var mockConnectionHandler = new MockConnectionHandler();
            var mockLibuv             = new MockLibuv();
            var transportContext      = new TestLibuvTransportContext()
            {
                ConnectionHandler = mockConnectionHandler
            };
            var transport = new LibuvTransport(mockLibuv, transportContext, null);
            var thread    = new LibuvThread(transport);

            mockConnectionHandler.InputOptions = pool =>
                                                 new PipeOptions(
                bufferPool: pool,
                maximumSizeHigh: 3);

            // We don't set the output writer scheduler here since we want to run the callback inline

            mockConnectionHandler.OutputOptions = pool => new PipeOptions(bufferPool: pool, readerScheduler: thread);


            Task connectionTask = null;

            try
            {
                await thread.StartAsync();

                // Write enough to make sure back pressure will be applied
                await thread.PostAsync <object>(_ =>
                {
                    var listenerContext = new ListenerContext(transportContext)
                    {
                        Thread = thread
                    };
                    var socket     = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log);
                    var connection = new LibuvConnection(listenerContext, socket);
                    connectionTask = connection.Start();

                    mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out var ignored);
                    mockLibuv.ReadCallback(socket.InternalGetHandle(), 5, ref ignored);
                }, null);

                // Now assert that we removed the callback from libuv to stop reading
                Assert.Null(mockLibuv.AllocCallback);
                Assert.Null(mockLibuv.ReadCallback);

                // Now complete the output writer so that the connection closes
                mockConnectionHandler.Output.Writer.Complete();

                await connectionTask.TimeoutAfter(TimeSpan.FromSeconds(10));

                // Assert that we don't try to start reading
                Assert.Null(mockLibuv.AllocCallback);
                Assert.Null(mockLibuv.ReadCallback);
            }
            finally
            {
                await thread.StopAsync(TimeSpan.FromSeconds(1));
            }
        }
Esempio n. 2
0
        /// <inheritdoc/>
        protected override void BeginAccept(ListenerContext listener)
        {
            SocketAsyncEventArgs acceptEventArg = (SocketAsyncEventArgs)listener.Tag;

            if (acceptEventArg == null)
            {
                acceptEventArg            = new SocketAsyncEventArgs();
                acceptEventArg.UserToken  = listener;
                acceptEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(AcceptEventArg_Completed);
            }
            else
            {
                // socket must be cleared since the context object is being reused
                acceptEventArg.AcceptSocket = null;
            }

            Boolean willRaiseEvent;

            try
            {
                willRaiseEvent = listener.Socket.AcceptAsync(acceptEventArg);
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            if (!willRaiseEvent)
            {
                ProcessAccept(acceptEventArg);
            }
        }
        public async Task DoesNotEndConnectionOnZeroRead()
        {
            var mockLibuv        = new MockLibuv();
            var transportContext = new TestLibuvTransportContext();
            var thread           = new LibuvThread(mockLibuv, transportContext);
            var listenerContext  = new ListenerContext(transportContext)
            {
                Thread = thread
            };

            try
            {
                await thread.StartAsync();

                await thread.PostAsync(_ =>
                {
                    var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log);
                    listenerContext.HandleConnection(socket);

                    mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out var ignored);
                    mockLibuv.ReadCallback(socket.InternalGetHandle(), 0, ref ignored);
                }, (object)null);

                await using var connection = await listenerContext.AcceptAsync();

                var readAwaitable = connection.Transport.Input.ReadAsync();
                Assert.False(readAwaitable.IsCompleted);
            }
            finally
            {
                await thread.StopAsync(TimeSpan.FromSeconds(5));
            }
        }
Esempio n. 4
0
        private IEnumerator <object> KeepAliveTask(ListenerContext context, Socket socket)
        {
            EndPoint localEp = socket.LocalEndPoint, remoteEp = socket.RemoteEndPoint;
            var      evtArgs = new ConnectionEventArgs(localEp, remoteEp);

            if (SocketOpened != null)
            {
                SocketOpened(this, evtArgs);
            }

            try {
                using (var adapter = new SocketDataAdapter(socket, true)) {
                    while (!adapter.IsDisposed && adapter.Socket.Connected)
                    {
                        var fTask = Scheduler.Start(RequestTask(context, adapter));
                        yield return(fTask);

                        if (fTask.Failed)
                        {
                            adapter.Dispose();
                            yield break;
                        }
                    }
                }
            } finally {
                if (SocketClosed != null)
                {
                    SocketClosed(this, evtArgs);
                }
            }
        }
Esempio n. 5
0
        public void DoesNotEndConnectionOnZeroRead()
        {
            var mockLibuv = new MockLibuv();

            using (var memory = new MemoryPool())
                using (var engine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                {
                    engine.Start(count: 1);

                    var trace   = new TestKestrelTrace();
                    var context = new ListenerContext(new TestServiceContext())
                    {
                        FrameFactory = connectionContext => new Frame <HttpContext>(
                            new DummyApplication(httpContext => TaskUtilities.CompletedTask), connectionContext),
                        Memory        = memory,
                        ServerAddress = ServerAddress.FromUrl($"http://localhost:{TestServer.GetNextPort()}"),
                        Thread        = engine.Threads[0]
                    };
                    var socket     = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, trace);
                    var connection = new Connection(context, socket);
                    connection.Start();

                    Libuv.uv_buf_t ignored;
                    mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out ignored);
                    mockLibuv.ReadCallback(socket.InternalGetHandle(), 0, ref ignored);
                    Assert.False(connection.SocketInput.RemoteIntakeFin);

                    connection.ConnectionControl.End(ProduceEndType.SocketDisconnect);
                }
        }
        public async Task DoesNotThrowIfOnReadCallbackCalledWithEOFButAllocCallbackNotCalled()
        {
            var mockLibuv        = new MockLibuv();
            var transportContext = new TestLibuvTransportContext();
            var thread           = new LibuvThread(mockLibuv, transportContext);
            var listenerContext  = new ListenerContext(transportContext)
            {
                Thread = thread
            };

            try
            {
                await thread.StartAsync();

                await thread.PostAsync(_ =>
                {
                    var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log);
                    listenerContext.HandleConnection(socket);

                    var ignored = new LibuvFunctions.uv_buf_t();
                    mockLibuv.ReadCallback(socket.InternalGetHandle(), TestConstants.EOF, ref ignored);
                }, (object)null);

                await using var connection = await listenerContext.AcceptAsync();

                var readAwaitable = await connection.Transport.Input.ReadAsync();

                Assert.True(readAwaitable.IsCompleted);
            }
            finally
            {
                await thread.StopAsync(TimeSpan.FromSeconds(5));
            }
        }
Esempio n. 7
0
 /// <summary>
 /// On request
 /// </summary>
 /// <param name="context">Command context</param>
 public void OnRequest(ListenerContext context)
 {
     context.StatusCode       = 200;
     context.ResponseEncoding = Encoding.UTF8;
     context.ContentType      = "text/html";
     context.Response         = "It works!";
 }
Esempio n. 8
0
        Ex2Listener()
        {
            // Subject를 등록합니다.
            ListenerContext.AddSubject(new Ex2Subject());

            // Listener를 등록합니다.
            ListenerContext.BindListener <Ex2Subject>(this);
        }
Esempio n. 9
0
        public void Dispose()
        {
            // 등록된 Listener 해제 합니다.
            ListenerContext.UnbindListener(this);

            // 등록된 Subject를 제거합니다.
            ListenerContext.RemoveSubject <Ex1Subject>();
        }
Esempio n. 10
0
        Ex1Listener()
        {
            // Subject를 등록합니다.
            ListenerContext.AddSubject(new Ex1Subject());

            // Listener를 등록합니다.
            ListenerContext.BindListener(this);
        }
        public async Task ConnectionDoesNotResumeAfterSocketCloseIfBackpressureIsApplied()
        {
            var mockLibuv        = new MockLibuv();
            var transportContext = new TestLibuvTransportContext();
            var thread           = new LibuvThread(mockLibuv, transportContext);
            var listenerContext  = new ListenerContext(transportContext)
            {
                Thread       = thread,
                InputOptions = new PipeOptions(
                    pool: thread.MemoryPool,
                    pauseWriterThreshold: 3,
                    readerScheduler: PipeScheduler.Inline,
                    writerScheduler: PipeScheduler.Inline,
                    useSynchronizationContext: false),

                // We don't set the output writer scheduler here since we want to run the callback inline
                OutputOptions = new PipeOptions(
                    pool: thread.MemoryPool,
                    readerScheduler: thread,
                    writerScheduler: PipeScheduler.Inline,
                    useSynchronizationContext: false)
            };

            try
            {
                await thread.StartAsync();

                // Write enough to make sure back pressure will be applied
                await thread.PostAsync <object>(_ =>
                {
                    var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log);
                    listenerContext.HandleConnection(socket);

                    mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out var ignored);
                    mockLibuv.ReadCallback(socket.InternalGetHandle(), 5, ref ignored);
                }, null);

                var connection = await listenerContext.AcceptAsync();

                // Now assert that we removed the callback from libuv to stop reading
                Assert.Null(mockLibuv.AllocCallback);
                Assert.Null(mockLibuv.ReadCallback);

                // Now complete the output writer so that the connection closes
                await connection.DisposeAsync();

                // Assert that we don't try to start reading
                Assert.Null(mockLibuv.AllocCallback);
                Assert.Null(mockLibuv.ReadCallback);
            }
            finally
            {
                await thread.StopAsync(TimeSpan.FromSeconds(5));
            }
        }
Esempio n. 12
0
        private IEnumerator <object> KeepAliveTask(ListenerContext context, IncomingConnection incomingConnection)
        {
            var      socket = incomingConnection.Socket;
            EndPoint localEp = socket.LocalEndPoint, remoteEp = socket.RemoteEndPoint;
            var      evtArgs = new ConnectionEventArgs(localEp, remoteEp);

            var keepAliveStarted = DateTime.UtcNow;

            if (SocketOpened != null)
            {
                SocketOpened(this, evtArgs);
            }

            int requestCount = 0;

            try {
                using (var adapter = new SocketDataAdapter(socket, true)) {
                    while (!adapter.IsDisposed && adapter.Socket.Connected)
                    {
                        var fTask = Scheduler.Start(RequestTask(context, adapter));
                        yield return(fTask);

                        requestCount += 1;

                        if (fTask.Failed)
                        {
                            adapter.Dispose();
                            yield break;
                        }
                    }
                }
            } finally {
                var keepAliveEnded = DateTime.UtcNow;

                if (SocketClosed != null)
                {
                    SocketClosed(this, evtArgs);
                }

                if (Trace != null)
                {
                    Trace(
                        String.Format(
                            "KA_START {0:0000.0}ms  KA_LENGTH {1:00000.0}ms  {2} REQ(S)",
                            (keepAliveStarted - incomingConnection.AcceptedWhenUTC).TotalMilliseconds,
                            (keepAliveEnded - keepAliveStarted).TotalMilliseconds,
                            requestCount
                            )
                        );
                }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Creates a new connection from the listener context.
        /// </summary>
        /// <param name="context">The listener context to use.</param>
        /// <param name="socket">The socket handle.</param>
        internal Connection(ListenerContext context, UvStreamHandle socket) : base(context)
        {
            _socket           = socket;
            socket.Connection = this;

            ConnectionId = ConnectionId.NewConnectionId();

            _rawSocketInput  = new SocketInput(Memory, ThreadPool);
            _rawSocketOutput = new SocketOutput(Thread, _socket, Memory, this, ConnectionId, ThreadPool, WriteReqPool);

            this.Expires = Timer.Now + TimeSpan.FromMinutes(1);
            this.ConnectionManager.Register(this);
        }
 protected override void BeginAccept(ListenerContext listener)
 {
     try
     {
         listener.Socket.BeginAccept(AcceptCallback, listener);
     }
     catch (ObjectDisposedException)
     {
         // do nothing
     }
     catch (System.Net.Sockets.SocketException ex)
     {
         ExceptionMonitor.Instance.ExceptionCaught(ex);
     }
 }
Esempio n. 15
0
        private void StartAccept(ListenerContext listener)
        {
            if (_connectionPool == null)
            {
                BeginAccept(listener);
            }
            else
            {
#if NET20
                System.Threading.ThreadPool.QueueUserWorkItem(_startAccept, listener);
#else
                System.Threading.Tasks.Task.Factory.StartNew(_startAccept, listener);
#endif
            }
        }
 protected override void BeginAccept(ListenerContext listener)
 {
     try
     {
         listener.Socket.BeginAccept(AcceptCallback, listener);
     }
     catch (ObjectDisposedException)
     {
         // do nothing
     }
     catch (System.Net.Sockets.SocketException ex)
     {
         ExceptionMonitor.Instance.ExceptionCaught(ex);
     }
 }
Esempio n. 17
0
        public async Task DoesNotThrowIfOnReadCallbackCalledWithEOFButAllocCallbackNotCalled()
        {
            var mockConnectionDispatcher = new MockConnectionDispatcher();
            var mockLibuv        = new MockLibuv();
            var transportContext = new TestLibuvTransportContext()
            {
                ConnectionDispatcher = mockConnectionDispatcher
            };
            var transport = new LibuvTransport(mockLibuv, transportContext, null);
            var thread    = new LibuvThread(transport);

            Task connectionTask = null;

            try
            {
                await thread.StartAsync();

                await thread.PostAsync(_ =>
                {
                    var listenerContext = new ListenerContext(transportContext)
                    {
                        Thread = thread
                    };
                    var socket     = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log);
                    var connection = new LibuvConnection(socket, listenerContext.TransportContext.Log, thread, null, null);
                    listenerContext.TransportContext.ConnectionDispatcher.OnConnection(connection);
                    connectionTask = connection.Start();

                    var ignored = new LibuvFunctions.uv_buf_t();
                    mockLibuv.ReadCallback(socket.InternalGetHandle(), TestConstants.EOF, ref ignored);
                }, (object)null);

                var readAwaitable = await mockConnectionDispatcher.Input.Reader.ReadAsync();

                Assert.True(readAwaitable.IsCompleted);
            }
            finally
            {
                mockConnectionDispatcher.Input.Reader.Complete();
                mockConnectionDispatcher.Output.Writer.Complete();
                await connectionTask;

                await thread.StopAsync(TimeSpan.FromSeconds(5));
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Ends an accept operation.
        /// </summary>
        /// <param name="socket">the accepted client socket</param>
        /// <param name="listener">the <see cref="ListenerContext"/></param>
        protected void EndAccept(System.Net.Sockets.Socket socket, ListenerContext listener)
        {
            if (socket != null)
            {
                IoSession session = NewSession(_processor, socket);
                try
                {
                    InitSession <IoFuture>(session, null, null);
                    session.Processor.Add(session);
                }
                catch (Exception ex)
                {
                    ExceptionMonitor.Instance.ExceptionCaught(ex);
                }
            }

            // Accept the next connection request
            StartAccept(listener);
        }
Esempio n. 19
0
        public SignalFuture StartListening()
        {
            if (IsListening)
            {
                throw new InvalidOperationException("Already listening");
            }

            var context = new ListenerContext(this);

            ActiveListener = Scheduler.Start(ListenerTask(context));
            ActiveListener.RegisterOnComplete((_) => {
                if (_.Failed)
                {
                    OnListenerError(_.Error);
                }
            });

            return(context.Started);
        }
Esempio n. 20
0
        private IEnumerator <object> ListenerTask(ListenerContext context)
        {
            using (context) {
                yield return(Future.RunInThread(context.Start));

                var       wfns = new WaitForNextStep();
                var       acceptedConnections                  = new List <IncomingConnection>();
                const int connectionsToAcceptPerStep           = 4;
                Future <IncomingConnection> acceptedConnection = null;

                while (true)
                {
                    if (acceptedConnection != null)
                    {
                        if (acceptedConnection.Failed)
                        {
                            OnListenerError(acceptedConnection.Error);
                        }
                        else
                        {
                            acceptedConnections.Add(acceptedConnection.Result);
                        }
                    }

                    context.IncomingConnections.DequeueMultiple(
                        acceptedConnections, connectionsToAcceptPerStep
                        );

                    foreach (var ac in acceptedConnections)
                    {
                        var fKeepAlive = Scheduler.Start(KeepAliveTask(context, ac));
                        fKeepAlive.RegisterOnComplete(RequestOnComplete);
                    }

                    acceptedConnections.Clear();
                    acceptedConnection = context.IncomingConnections.Dequeue();

                    yield return(acceptedConnection);
                }
            }
        }
        private void AcceptCallback(IAsyncResult ar)
        {
            ListenerContext listener = (ListenerContext)ar.AsyncState;

            System.Net.Sockets.Socket socket;

            try
            {
                socket = listener.Socket.EndAccept(ar);
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (Exception ex)
            {
                ExceptionMonitor.Instance.ExceptionCaught(ex);
                socket = null;
            }

            EndAccept(socket, listener);
        }
Esempio n. 22
0
        /// <summary>
        /// Creates a connection for a remote endpoint.
        /// </summary>
        /// <param name="context">The listener context to use.</param>
        /// <param name="remote">The endpoint to connect to.</param>
        public static Task <Connection> ConnectAsync(ListenerContext context, IPEndPoint remote)
        {
            var tcs = new TaskCompletionSource <Connection>();

            context.Thread.PostAsync((state) =>
            {
                var socket = new UvTcpHandle();
                try
                {
                    socket.Init(context.Thread.Loop, context.Thread.QueueCloseHandle);
                    socket.NoDelay(true);
                    socket.Connect(context.Thread.Loop, ServiceAddress.FromIPEndPoint(remote), (request, status, ex, sender) =>
                    {
                        request.Dispose();

                        if (ex != null)
                        {
                            // Error has occured, set the exception
                            socket.Dispose();
                            tcs.SetException(ex);
                            return;
                        }

                        // Create the connection and notify
                        var connection = new Connection(context, socket);
                        tcs.SetResult(connection.Start() ? connection : null);
                    }, tcs);
                }
                catch (UvException ex)
                {
                    //Service.Logger.Log(ex);
                    socket.Dispose();
                    tcs.SetException(ex);
                }
            }, tcs);
            return(tcs.Task);
        }
Esempio n. 23
0
 /// <summary>
 /// Context recieved callback
 /// </summary>
 /// <param name="asyncResult">Asynchronous result</param>
 private void ContextReceivedCallback(IAsyncResult asyncResult)
 {
     try
     {
         if (IsListening)
         {
             HttpListenerContext context = httpListener.EndGetContext(asyncResult);
             httpListener.BeginGetContext(new AsyncCallback(ContextReceivedCallback), null);
             using (Stream stream = context.Response.OutputStream)
             {
                 foreach (IPlugin plugin in plugins)
                 {
                     ListenerContext listener_context = new ListenerContext(context, StandardOutput, ErrorOutput);
                     plugin.OnRequest(listener_context);
                     stream.Write(listener_context.ResponseBytes, 0, listener_context.ResponseBytes.Length);
                 }
             }
         }
     }
     catch (Exception e)
     {
         ErrorOutput.WriteLine(e);
     }
 }
        public ContinuationAction MessageReceived(ListenerContext e)
        {
            // You can inherit from MessageExtendedInformation if you wish,
            // the likely scenario for this is if you support plugins yourself.
            var extended = e.ReceivedInformation.Message.GetExtendedInformation<MessageExtendedInformation>();
            var replyExtended = extended.Invert(null);

            string workflowName;
            if (extended.Message.Title.StartsWith("START: ", StringComparison.OrdinalIgnoreCase))
            {
                workflowName = extended.Message.Title.Substring(7).Trim();
            }
            else
            {
                return ContinuationAction.Continue; // Allow other plugins to execute.
            }

            // Get the message body.
            string body;
            try
            {
                using (var bodyStream = e.ReceivedInformation.Message.OpenView(new ContentType("text/plain")))
                {
                    if (bodyStream != null)
                    {
                        // Another plugin may have moved the position within the stream.
                        bodyStream.Seek(0, System.IO.SeekOrigin.Begin);
                        using (var sr = new StreamReader(bodyStream))
                        {
                            body = sr.ReadToEnd().Trim();
                        }
                    }
                    else
                    {
                        body = string.Empty;
                    }
                }
            }
            catch
            {
                // TODO: Logging etc.
                return ContinuationAction.Continue; // Allow other plugins to execute.
            }

            // TODO: Get data from the body somehow.
            // You can also look into attachments for e.g. InfoPath forms:
            // e.ReceivedInformation.Message.Attachments

            try
            {
                var con = new Connection();
                var cs = new ConnectionSetup();
                cs.ParseConnectionString(_k2ServerConnectionString);

                try
                {
                    Exception lastException = null;
                    con.Open(cs);

                    // AlternateIdentities are identities with the same email
                    // address, most likely due badly configured claims.
                    for (var i = 0; i < e.AlternateIdentities.Length; i++)
                    {
                        var alt = e.AlternateIdentities[i];
                        string fqn;

                        // Search for a FQN in the identity.
                        if (alt.TryGetValue("Fqn", out fqn))
                        {
                            try
                            {
                                con.RevertUser();
                                con.ImpersonateUser(fqn);

                                var pi = con.CreateProcessInstance(workflowName);
                                // TODO: Set data in the workflow.
                                con.StartProcessInstance(pi);

                                // Tell the user the workflow was started.
                                _destination.ReplyTo(e.ReceivedInformation.Message, new MessageBodyReader("text/plain", "Workflow started"), replyExtended);

                                e.ReceivedInformation.Commit(); // Indicate we were able to handle the message.
                                return ContinuationAction.Halt; // Stop other plugins from executing.
                            }
                            catch (Exception ex)
                            {
                                // TODO: Logging etc.
                                // This isn't nessecarily a complete failure,
                                // one of the other alternate identities may be
                                // able to action this.
                                lastException = ex;
                            }
                        }
                    }

                    string message;
                    if (lastException != null)
                    {
                        // Identities exist, but the user likely doesn't have rights.
                        message = lastException.ToString();
                    }
                    else
                    {
                        // No identities exist.
                        message = "Could not find a K2 user for your email address.";
                    }

                    message = "The workflow could not be started: " + message;

                    // Respond with the error.
                    _destination.ReplyTo(e.ReceivedInformation.Message, new MessageBodyReader("text/plain", message), replyExtended);

                    e.ReceivedInformation.Commit(); // Indicate we were able to handle the message.
                    return ContinuationAction.Halt; // Stop other plugins from executing.
                }
                finally
                {
                    if (con != null)
                    {
                        con.Close();
                        con.Dispose();
                    }
                }
            }
            catch
            {
                // TODO: Logging etc.
                return ContinuationAction.Continue; // Allow other plugins to execute.
            }
        }
Esempio n. 25
0
        private static async Task <Task <LibuvConnection> > WaitForSecondaryListener(Uri address, ListenerContext listenerPrimary, ListenerContext listenerSecondary)
        {
            int maxRetries = 100;
            int retryDelay = 100;

            Task <LibuvConnection> primary   = null;
            Task <LibuvConnection> secondary = null;

            for (var i = 0; i < maxRetries; i++)
            {
                primary ??= listenerPrimary.AcceptAsync().AsTask();
                secondary ??= listenerSecondary.AcceptAsync().AsTask();

                using var _ = await HttpClientSlim.GetSocket(address);

                var task = await Task.WhenAny(primary, secondary);

                if (task == secondary)
                {
                    // Dispose this connection now that we know the seconary listener is working
                    await(await secondary).DisposeAsync();

                    // Return the primary task (it should be incomplete), we do this so that we can
                    return(primary);
                }
                else
                {
                    // Dispose the connection
                    await(await primary).DisposeAsync();

                    primary = null;
                }

                await Task.Delay(retryDelay);
            }

            Assert.True(false, $"'{address}' failed to get queued connection in secondary listener in {maxRetries} retries.");
            return(null);
        }
Esempio n. 26
0
        private static async Task AssertRoundRobin(Uri address, ListenerPrimary listenerPrimary, ListenerSecondary listenerSecondary, ListenerContext currentListener, Task <LibuvConnection> expected = null, int connections = 4)
        {
            for (int i = 0; i < connections; i++)
            {
                if (currentListener == listenerPrimary)
                {
                    expected ??= listenerSecondary.AcceptAsync().AsTask();
                    currentListener = listenerSecondary;
                }
                else
                {
                    expected ??= listenerPrimary.AcceptAsync().AsTask();
                    currentListener = listenerPrimary;
                }

                using var socket = await HttpClientSlim.GetSocket(address);

                await using var connection = await expected.DefaultTimeout();

                expected = null;
            }
        }
Esempio n. 27
0
 /// <summary>
 /// Begins an accept operation.
 /// </summary>
 /// <param name="listener"></param>
 protected abstract void BeginAccept(ListenerContext listener);
        ContinuationAction IMessageListener.MessageReceived(ListenerContext e)
        {
            string body;
            using (Stream bodyStream = e.ReceivedInformation.Message.OpenView(new ContentType("text/plain")))
            {
                if (bodyStream != null)
                {
                    // Another plugin may have moved the position within the stream.
                    bodyStream.Seek(0, System.IO.SeekOrigin.Begin);
                    using (StreamReader sr = new StreamReader(bodyStream))
                    {
                        body = sr.ReadToEnd().Trim();
                    }
                }
                else
                {
                    body = string.Empty;
                }
            }

            foreach (ConnectionInformation con in _connections)
            {
                string path = con.ConnectionString;
                string filename = string.Format(@"{0}\received\MessageReceived_{1}.txt", path, e.ReceivedInformation.Message.Title.Replace(':', '_'));
                using (StreamWriter writer = new StreamWriter(filename))
                {
                    writer.Write(body);
                    writer.Close();
                }
            }

            // This method should fire when a message is received by the MessageBus.
            // Processing can be done by yourself.
            e.ReceivedInformation.Commit();
            return ContinuationAction.Halt;
        }
Esempio n. 29
0
        private IEnumerator<object> RequestTask(ListenerContext context, SocketDataAdapter adapter)
        {
            var startedWhen = DateTime.UtcNow;
            bool successful = false;

            try {
                const int headerBufferSize = 1024 * 32;
                const int bodyBufferSize = 1024 * 128;
                const double requestLineTimeout = 5;

                // RFC2616:
                // Words of *TEXT MAY contain characters from character sets other than ISO-8859-1 [22]
                //  only when encoded according to the rules of RFC 2047 [14].
                Encoding headerEncoding;
                try {
                    headerEncoding = Encoding.GetEncoding("ISO-8859-1");
                } catch {
                    headerEncoding = Encoding.ASCII;
                }

                Request request;
                RequestBody body;
                HeaderCollection headers;
                long bodyBytesRead = 0;
                long? expectedBodyLength = null;

                var reader = new AsyncTextReader(adapter, headerEncoding, headerBufferSize, false);
                string requestLineText;

                while (true) {
                    var fRequestLine = reader.ReadLine();
                    var fRequestOrTimeout = Scheduler.Start(new WaitWithTimeout(fRequestLine, requestLineTimeout));

                    yield return fRequestOrTimeout;

                    if (fRequestOrTimeout.Failed) {
                        if (!(fRequestOrTimeout.Error is TimeoutException))
                            OnRequestError(fRequestOrTimeout.Error);

                        yield break;
                    }

                    if (fRequestLine.Failed) {
                        if (!(fRequestLine.Error is SocketDisconnectedException))
                            OnRequestError(fRequestLine.Error);

                        yield break;
                    }

                    requestLineText = fRequestLine.Result;

                    // RFC2616:
                    // In the interest of robustness, servers SHOULD ignore any empty line(s) received where a
                    //  Request-Line is expected. In other words, if the server is reading the protocol stream
                    //   at the beginning of a message and receives a CRLF first, it should ignore the CRLF.
                    if ((requestLineText != null) && (requestLineText.Trim().Length == 0))
                        continue;

                    break;
                }

                var requestLineParsed = DateTime.UtcNow;

                headers = new HeaderCollection();
                while (true) {
                    var fHeaderLine = reader.ReadLine();
                    yield return fHeaderLine;

                    if (String.IsNullOrWhiteSpace(fHeaderLine.Result))
                        break;

                    headers.Add(new Header(fHeaderLine.Result));
                }

                var headersParsed = DateTime.UtcNow;

                var expectHeader = (headers.GetValue("Expect") ?? "").ToLowerInvariant();
                var expectsContinue = expectHeader.Contains("100-continue");

                string hostName;
                if (headers.Contains("Host")) {
                    hostName = String.Format("http://{0}", headers["Host"].Value);
                } else {
                    var lep = (IPEndPoint)adapter.Socket.LocalEndPoint;
                    hostName = String.Format("http://{0}:{1}", lep.Address, lep.Port);
                }

                var requestLine = new RequestLine(hostName, requestLineText);

                var remainingBytes = reader.DisposeAndGetRemainingBytes();
                bodyBytesRead += remainingBytes.Count;

                var connectionHeader = (headers.GetValue("Connection") ?? "").ToLowerInvariant();
                var shouldKeepAlive =
                    ((requestLine.Version == "1.1") || connectionHeader.Contains("keep-alive")) &&
                    !connectionHeader.Contains("close");

                if (headers.Contains("Content-Length"))
                    expectedBodyLength = long.Parse(headers["Content-Length"].Value);

                body = new RequestBody(remainingBytes, expectedBodyLength);

                if (expectsContinue)
                    yield return adapter.Write(Continue100, 0, Continue100.Length);

                request = new Request(
                    this, adapter, shouldKeepAlive,
                    requestLine, headers, body
                );

                IncomingRequests.Enqueue(request);

                var requestEnqueued = DateTime.UtcNow;
                DateTime? requestBodyRead = null;

                // FIXME: I think it's technically accepted to send a body without a content-length, but
                //  it seems to be impossible to make that work right.
                if (expectedBodyLength.HasValue) {
                    using (var bodyBuffer = BufferPool<byte>.Allocate(bodyBufferSize))
                    while (bodyBytesRead < expectedBodyLength.Value) {
                        long bytesToRead = Math.Min(expectedBodyLength.Value - bodyBytesRead, bodyBufferSize);

                        if (bytesToRead <= 0)
                            break;

                        var fBytesRead = adapter.Read(bodyBuffer.Data, 0, (int)bytesToRead);
                        yield return fBytesRead;

                        if (fBytesRead.Failed) {
                            if (fBytesRead.Error is SocketDisconnectedException)
                                break;

                            body.Failed(fBytesRead.Error);
                            OnRequestError(fBytesRead.Error);
                            yield break;
                        }

                        var bytesRead = fBytesRead.Result;

                        bodyBytesRead += bytesRead;
                        body.Append(bodyBuffer.Data, 0, bytesRead);
                    }

                    requestBodyRead = DateTime.UtcNow;
                }

                body.Finish();
                successful = true;

                request.Timing = new Request.TimingData {
                    Line = (requestLineParsed - startedWhen),
                    Headers = (headersParsed - requestLineParsed),
                    Queue = (requestEnqueued - headersParsed),
                    Body = (requestBodyRead - requestEnqueued)
                };
            } finally {
                if (!successful)
                    adapter.Dispose();
            }
        }
Esempio n. 30
0
        public async Task ConnectionDoesNotResumeAfterReadCallbackScheduledAndSocketCloseIfBackpressureIsApplied()
        {
            var mockConnectionDispatcher = new MockConnectionDispatcher();
            var mockLibuv        = new MockLibuv();
            var transportContext = new TestLibuvTransportContext()
            {
                ConnectionDispatcher = mockConnectionDispatcher
            };
            var    transport     = new LibuvTransport(mockLibuv, transportContext, null);
            var    thread        = new LibuvThread(transport);
            var    mockScheduler = new Mock <PipeScheduler>();
            Action backPressure  = null;

            mockScheduler.Setup(m => m.Schedule(It.IsAny <Action <object> >(), It.IsAny <object>())).Callback <Action <object>, object>((a, o) =>
            {
                backPressure = () => a(o);
            });
            mockConnectionDispatcher.InputOptions = pool =>
                                                    new PipeOptions(
                pool: pool,
                pauseWriterThreshold: 3,
                resumeWriterThreshold: 3,
                writerScheduler: mockScheduler.Object,
                readerScheduler: PipeScheduler.Inline,
                useSynchronizationContext: false);

            mockConnectionDispatcher.OutputOptions = pool => new PipeOptions(pool: pool, readerScheduler: thread, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);

            Task connectionTask = null;

            try
            {
                await thread.StartAsync();

                // Write enough to make sure back pressure will be applied
                await thread.PostAsync <object>(_ =>
                {
                    var listenerContext = new ListenerContext(transportContext)
                    {
                        Thread = thread
                    };
                    var socket     = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log);
                    var connection = new LibuvConnection(socket, listenerContext.TransportContext.Log, thread, null, null);
                    listenerContext.TransportContext.ConnectionDispatcher.OnConnection(connection);
                    connectionTask = connection.Start();

                    mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out var ignored);
                    mockLibuv.ReadCallback(socket.InternalGetHandle(), 5, ref ignored);
                }, null);

                // Now assert that we removed the callback from libuv to stop reading
                Assert.Null(mockLibuv.AllocCallback);
                Assert.Null(mockLibuv.ReadCallback);

                // Now release backpressure by reading the input
                var result = await mockConnectionDispatcher.Input.Reader.ReadAsync();

                // Calling advance will call into our custom scheduler that captures the back pressure
                // callback
                mockConnectionDispatcher.Input.Reader.AdvanceTo(result.Buffer.End);

                // Cancel the current pending flush
                mockConnectionDispatcher.Input.Writer.CancelPendingFlush();

                // Now release the back pressure
                await thread.PostAsync(a => a(), backPressure);

                // Assert that we don't try to start reading since the write was cancelled
                Assert.Null(mockLibuv.AllocCallback);
                Assert.Null(mockLibuv.ReadCallback);

                // Now complete the output writer and wait for the connection to close
                mockConnectionDispatcher.Output.Writer.Complete();

                await connectionTask.DefaultTimeout();

                // Assert that we don't try to start reading
                Assert.Null(mockLibuv.AllocCallback);
                Assert.Null(mockLibuv.ReadCallback);
            }
            finally
            {
                await thread.StopAsync(TimeSpan.FromSeconds(5));
            }
        }
        public ContinuationAction MessageReceived(ListenerContext e)
        {
            // You can inherit from MessageExtendedInformation if you wish,
            // the likely scenario for this is if you support plugins yourself.
            var extended      = e.ReceivedInformation.Message.GetExtendedInformation <MessageExtendedInformation>();
            var replyExtended = extended.Invert(null);

            string workflowName;

            if (extended.Message.Title.StartsWith("START: ", StringComparison.OrdinalIgnoreCase))
            {
                workflowName = extended.Message.Title.Substring(7).Trim();
            }
            else
            {
                return(ContinuationAction.Continue); // Allow other plugins to execute.
            }

            // Get the message body.
            string body;

            try
            {
                using (var bodyStream = e.ReceivedInformation.Message.OpenView(new ContentType("text/plain")))
                {
                    if (bodyStream != null)
                    {
                        // Another plugin may have moved the position within the stream.
                        bodyStream.Seek(0, System.IO.SeekOrigin.Begin);
                        using (var sr = new StreamReader(bodyStream))
                        {
                            body = sr.ReadToEnd().Trim();
                        }
                    }
                    else
                    {
                        body = string.Empty;
                    }
                }
            }
            catch
            {
                // TODO: Logging etc.
                return(ContinuationAction.Continue); // Allow other plugins to execute.
            }

            // TODO: Get data from the body somehow.
            // You can also look into attachments for e.g. InfoPath forms:
            // e.ReceivedInformation.Message.Attachments

            try
            {
                var con = new Connection();
                var cs  = new ConnectionSetup();
                cs.ParseConnectionString(_k2ServerConnectionString);

                try
                {
                    Exception lastException = null;
                    con.Open(cs);

                    // AlternateIdentities are identities with the same email
                    // address, most likely due badly configured claims.
                    for (var i = 0; i < e.AlternateIdentities.Length; i++)
                    {
                        var    alt = e.AlternateIdentities[i];
                        string fqn;

                        // Search for a FQN in the identity.
                        if (alt.TryGetValue("Fqn", out fqn))
                        {
                            try
                            {
                                con.RevertUser();
                                con.ImpersonateUser(fqn);

                                var pi = con.CreateProcessInstance(workflowName);
                                // TODO: Set data in the workflow.
                                con.StartProcessInstance(pi);

                                // Tell the user the workflow was started.
                                _destination.ReplyTo(e.ReceivedInformation.Message, new MessageBodyReader("text/plain", "Workflow started"), replyExtended);

                                e.ReceivedInformation.Commit();  // Indicate we were able to handle the message.
                                return(ContinuationAction.Halt); // Stop other plugins from executing.
                            }
                            catch (Exception ex)
                            {
                                // TODO: Logging etc.
                                // This isn't nessecarily a complete failure,
                                // one of the other alternate identities may be
                                // able to action this.
                                lastException = ex;
                            }
                        }
                    }

                    string message;
                    if (lastException != null)
                    {
                        // Identities exist, but the user likely doesn't have rights.
                        message = lastException.ToString();
                    }
                    else
                    {
                        // No identities exist.
                        message = "Could not find a K2 user for your email address.";
                    }

                    message = "The workflow could not be started: " + message;

                    // Respond with the error.
                    _destination.ReplyTo(e.ReceivedInformation.Message, new MessageBodyReader("text/plain", message), replyExtended);

                    e.ReceivedInformation.Commit();  // Indicate we were able to handle the message.
                    return(ContinuationAction.Halt); // Stop other plugins from executing.
                }
                finally
                {
                    if (con != null)
                    {
                        con.Close();
                        con.Dispose();
                    }
                }
            }
            catch
            {
                // TODO: Logging etc.
                return(ContinuationAction.Continue); // Allow other plugins to execute.
            }
        }
Esempio n. 32
0
        private IEnumerator<object> ListenerTask(ListenerContext context)
        {
            using (context) {
                yield return Future.RunInThread(context.Start);

                var wfns = new WaitForNextStep();
                var acceptedConnections = new List<IncomingConnection>();
                const int connectionsToAcceptPerStep = 4;
                Future<IncomingConnection> acceptedConnection = null;

                while (true) {
                    if (acceptedConnection != null) {
                        if (acceptedConnection.Failed)
                            OnListenerError(acceptedConnection.Error);
                        else
                            acceptedConnections.Add(acceptedConnection.Result);
                    }

                    context.IncomingConnections.DequeueMultiple(
                        acceptedConnections, connectionsToAcceptPerStep
                    );

                    foreach (var ac in acceptedConnections) {
                        var fKeepAlive = Scheduler.Start(KeepAliveTask(context, ac));
                        fKeepAlive.RegisterOnComplete(RequestOnComplete);
                    }

                    acceptedConnections.Clear();
                    acceptedConnection = context.IncomingConnections.Dequeue();

                    yield return acceptedConnection;
                }
            }
        }
 public ConnectionContext(ListenerContext context) : base(context)
 {
 }
Esempio n. 34
0
        public async Task ConnectionsGetRoundRobinedToSecondaryListeners()
        {
            var libuv = new LibuvFunctions();

            var endpoint = new IPEndPoint(IPAddress.Loopback, 0);

            var transportContextPrimary   = new TestLibuvTransportContext();
            var transportContextSecondary = new TestLibuvTransportContext();

            var pipeName    = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
            var pipeMessage = Guid.NewGuid().ToByteArray();

            // Start primary listener
            var libuvThreadPrimary = new LibuvThread(libuv, transportContextPrimary);
            await libuvThreadPrimary.StartAsync();

            var listenerPrimary = new ListenerPrimary(transportContextPrimary);
            await listenerPrimary.StartAsync(pipeName, pipeMessage, endpoint, libuvThreadPrimary);

            var address = GetUri(listenerPrimary.EndPoint);

            var acceptTask = listenerPrimary.AcceptAsync().AsTask();

            using (var socket = await HttpClientSlim.GetSocket(address))
            {
                await(await acceptTask.DefaultTimeout()).DisposeAsync();
            }

            acceptTask = listenerPrimary.AcceptAsync().AsTask();
            using (var socket = await HttpClientSlim.GetSocket(address))
            {
                await(await acceptTask.DefaultTimeout()).DisposeAsync();
            }

            var listenerCount = listenerPrimary.UvPipeCount;
            // Add secondary listener
            var libuvThreadSecondary = new LibuvThread(libuv, transportContextSecondary);
            await libuvThreadSecondary.StartAsync();

            var listenerSecondary = new ListenerSecondary(transportContextSecondary);
            await listenerSecondary.StartAsync(pipeName, pipeMessage, endpoint, libuvThreadSecondary);

            var maxWait = Task.Delay(TestConstants.DefaultTimeout);

            // wait for ListenerPrimary.ReadCallback to add the secondary pipe
            while (listenerPrimary.UvPipeCount == listenerCount)
            {
                var completed = await Task.WhenAny(maxWait, Task.Delay(100));

                if (ReferenceEquals(completed, maxWait))
                {
                    throw new TimeoutException("Timed out waiting for secondary listener to become available");
                }
            }

            // Once a secondary listener is added, TCP connections start getting dispatched to it
            // This returns the incomplete primary task after the secondary listener got the last
            // connection
            var primary = await WaitForSecondaryListener(address, listenerPrimary, listenerSecondary);

            // TCP connections will still get round-robined to the primary listener
            ListenerContext        currentListener = listenerSecondary;
            Task <LibuvConnection> expected        = primary;

            await AssertRoundRobin(address, listenerPrimary, listenerSecondary, currentListener, expected);

            await listenerSecondary.DisposeAsync();

            await libuvThreadSecondary.StopAsync(TimeSpan.FromSeconds(5));

            await listenerPrimary.DisposeAsync();

            await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(5));
        }
        protected void EndAccept(System.Net.Sockets.Socket socket, ListenerContext listener)
        {
            if (socket != null)
            {
                IoSession session = NewSession(_processor, socket);
                try
                {
                    InitSession<IoFuture>(session, null, null);
                    session.Processor.Add(session);
                }
                catch (Exception ex)
                {
                    ExceptionMonitor.Instance.ExceptionCaught(ex);
                }
            }

            // Accept the next connection request
            StartAccept(listener);
        }
Esempio n. 36
0
        private IEnumerator <object> RequestTask(ListenerContext context, SocketDataAdapter adapter)
        {
            var  startedWhen = DateTime.UtcNow;
            bool successful  = false;

            try {
                const int    headerBufferSize   = 1024 * 32;
                const int    bodyBufferSize     = 1024 * 128;
                const double requestLineTimeout = 5;

                // RFC2616:
                // Words of *TEXT MAY contain characters from character sets other than ISO-8859-1 [22]
                //  only when encoded according to the rules of RFC 2047 [14].
                Encoding headerEncoding;
                try {
                    headerEncoding = Encoding.GetEncoding("ISO-8859-1");
                } catch {
                    headerEncoding = Encoding.ASCII;
                }

                Request          request;
                RequestBody      body;
                HeaderCollection headers;
                long             bodyBytesRead      = 0;
                long?            expectedBodyLength = null;

                var    reader = new AsyncTextReader(adapter, headerEncoding, headerBufferSize, false);
                string requestLineText;

                while (true)
                {
                    var fRequestLine      = reader.ReadLine();
                    var fRequestOrTimeout = Scheduler.Start(new WaitWithTimeout(fRequestLine, requestLineTimeout));

                    yield return(fRequestOrTimeout);

                    if (fRequestOrTimeout.Failed)
                    {
                        if (!(fRequestOrTimeout.Error is TimeoutException))
                        {
                            OnRequestError(fRequestOrTimeout.Error);
                        }

                        yield break;
                    }

                    if (fRequestLine.Failed)
                    {
                        if (!(fRequestLine.Error is SocketDisconnectedException))
                        {
                            OnRequestError(fRequestLine.Error);
                        }

                        yield break;
                    }

                    requestLineText = fRequestLine.Result;

                    // RFC2616:
                    // In the interest of robustness, servers SHOULD ignore any empty line(s) received where a
                    //  Request-Line is expected. In other words, if the server is reading the protocol stream
                    //   at the beginning of a message and receives a CRLF first, it should ignore the CRLF.
                    if ((requestLineText != null) && (requestLineText.Trim().Length == 0))
                    {
                        continue;
                    }

                    break;
                }

                var requestLineParsed = DateTime.UtcNow;

                headers = new HeaderCollection();
                while (true)
                {
                    var fHeaderLine = reader.ReadLine();
                    yield return(fHeaderLine);

                    if (String.IsNullOrWhiteSpace(fHeaderLine.Result))
                    {
                        break;
                    }

                    headers.Add(new Header(fHeaderLine.Result));
                }

                var headersParsed = DateTime.UtcNow;

                var expectHeader    = (headers.GetValue("Expect") ?? "").ToLowerInvariant();
                var expectsContinue = expectHeader.Contains("100-continue");

                string hostName;
                if (headers.Contains("Host"))
                {
                    hostName = String.Format("http://{0}", headers["Host"].Value);
                }
                else
                {
                    var lep = (IPEndPoint)adapter.Socket.LocalEndPoint;
                    hostName = String.Format("http://{0}:{1}", lep.Address, lep.Port);
                }

                var requestLine = new RequestLine(hostName, requestLineText);

                var remainingBytes = reader.DisposeAndGetRemainingBytes();
                bodyBytesRead += remainingBytes.Count;

                var connectionHeader = (headers.GetValue("Connection") ?? "").ToLowerInvariant();
                var shouldKeepAlive  =
                    ((requestLine.Version == "1.1") || connectionHeader.Contains("keep-alive")) &&
                    !connectionHeader.Contains("close");

                if (headers.Contains("Content-Length"))
                {
                    expectedBodyLength = long.Parse(headers["Content-Length"].Value);
                }

                body = new RequestBody(remainingBytes, expectedBodyLength);

                if (expectsContinue)
                {
                    yield return(adapter.Write(Continue100, 0, Continue100.Length));
                }

                request = new Request(
                    this, adapter, shouldKeepAlive,
                    requestLine, headers, body
                    );

                IncomingRequests.Enqueue(request);

                var      requestEnqueued = DateTime.UtcNow;
                DateTime?requestBodyRead = null;

                // FIXME: I think it's technically accepted to send a body without a content-length, but
                //  it seems to be impossible to make that work right.
                if (expectedBodyLength.HasValue)
                {
                    using (var bodyBuffer = BufferPool <byte> .Allocate(bodyBufferSize))
                        while (bodyBytesRead < expectedBodyLength.Value)
                        {
                            long bytesToRead = Math.Min(expectedBodyLength.Value - bodyBytesRead, bodyBufferSize);

                            if (bytesToRead <= 0)
                            {
                                break;
                            }

                            var fBytesRead = adapter.Read(bodyBuffer.Data, 0, (int)bytesToRead);
                            yield return(fBytesRead);

                            if (fBytesRead.Failed)
                            {
                                if (fBytesRead.Error is SocketDisconnectedException)
                                {
                                    break;
                                }

                                body.Failed(fBytesRead.Error);
                                OnRequestError(fBytesRead.Error);
                                yield break;
                            }

                            var bytesRead = fBytesRead.Result;

                            bodyBytesRead += bytesRead;
                            body.Append(bodyBuffer.Data, 0, bytesRead);
                        }

                    requestBodyRead = DateTime.UtcNow;
                }

                body.Finish();
                successful = true;

                request.Timing = new Request.TimingData {
                    Line    = (requestLineParsed - startedWhen),
                    Headers = (headersParsed - requestLineParsed),
                    Queue   = (requestEnqueued - headersParsed),
                    Body    = (requestBodyRead - requestEnqueued)
                };
            } finally {
                if (!successful)
                {
                    adapter.Dispose();
                }
            }
        }
Esempio n. 37
0
        public SignalFuture StartListening()
        {
            if (IsListening)
                throw new InvalidOperationException("Already listening");

            var context = new ListenerContext(this);
            ActiveListener = Scheduler.Start(ListenerTask(context));
            ActiveListener.RegisterOnComplete((_) => {
                if (_.Failed)
                    OnListenerError(_.Error);
            });

            return context.Started;
        }
Esempio n. 38
0
        private IEnumerator<object> KeepAliveTask(ListenerContext context, IncomingConnection incomingConnection)
        {
            var socket = incomingConnection.Socket;
            EndPoint localEp = socket.LocalEndPoint, remoteEp = socket.RemoteEndPoint;
            var evtArgs = new ConnectionEventArgs(localEp, remoteEp);

            var keepAliveStarted = DateTime.UtcNow;

            if (SocketOpened != null)
                SocketOpened(this, evtArgs);

            int requestCount = 0;

            try {
                using (var adapter = new SocketDataAdapter(socket, true)) {
                    while (!adapter.IsDisposed && adapter.Socket.Connected) {
                        var fTask = Scheduler.Start(RequestTask(context, adapter));
                        yield return fTask;

                        requestCount += 1;

                        if (fTask.Failed) {
                            adapter.Dispose();
                            yield break;
                        }
                    }
                }
            } finally {
                var keepAliveEnded = DateTime.UtcNow;

                if (SocketClosed != null)
                    SocketClosed(this, evtArgs);

                if (Trace != null)
                    Trace(
                        String.Format(
                            "KA_START {0:0000.0}ms  KA_LENGTH {1:00000.0}ms  {2} REQ(S)",
                            (keepAliveStarted - incomingConnection.AcceptedWhenUTC).TotalMilliseconds,
                            (keepAliveEnded - keepAliveStarted).TotalMilliseconds,
                            requestCount
                        )
                    );
            }
        }
 private void StartAccept(ListenerContext listener)
 {
     if (_connectionPool == null)
     {
         BeginAccept(listener);
     }
     else
     {
         System.Threading.Tasks.Task.Factory.StartNew(_startAccept, listener);
     }
 }
 public ConnectionContext(ListenerContext context)
     : base(context)
 {
 }
Esempio n. 41
0
        /// <inheritdoc/>
        protected override void BeginAccept(ListenerContext listener)
        {
            SocketAsyncEventArgs acceptEventArg = (SocketAsyncEventArgs)listener.Tag;
            if (acceptEventArg == null)
            {
                acceptEventArg = new SocketAsyncEventArgs();
                acceptEventArg.UserToken = listener;
                acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
            }
            else
            {
                // socket must be cleared since the context object is being reused
                acceptEventArg.AcceptSocket = null;
            }

            Boolean willRaiseEvent;
            try
            {
                willRaiseEvent = listener.Socket.AcceptAsync(acceptEventArg);
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            if (!willRaiseEvent)
            {
                ProcessAccept(acceptEventArg);
            }
        }
 protected abstract void BeginAccept(ListenerContext listener);