Class ServerSocketAccept

  • All Implemented Interfaces:
    de.esoco.lib.property.Fluent<CoroutineStep<java.lang.Void,​java.lang.Void>>, org.obrel.core.FluentRelatable<CoroutineStep<java.lang.Void,​java.lang.Void>>, org.obrel.core.Relatable

    public class ServerSocketAccept
    extends AsynchronousChannelStep<java.lang.Void,​java.lang.Void>
    A coroutine step for servers that listens to network request through an instance of AsynchronousServerSocketChannel. The step will suspend execution until a request is accepted and then spawn another coroutine for the handling of the request. The handling coroutine will receive the AsynchronousSocketChannel for the communication with the client. It could then store the channel as AsynchronousSocketStep.SOCKET_CHANNEL and process the request with SocketReceive and SocketSend steps.

    After the request handling coroutine has been spawned this step will resume execution of it's own coroutine. A typical server accept loop therefore needs to be implemented in that coroutine, e.g. inside a conditional Loop step. Handling coroutines will run in parallel in separate continuations but in the same scope. Interdependencies between the main coroutine and the request handling should be avoided to prevent the risk of deadlocks.

    • Field Summary

      Fields 
      Modifier and Type Field Description
      static org.obrel.core.RelationType<java.nio.channels.AsynchronousServerSocketChannel> SERVER_SOCKET_CHANNEL
      State: an AsynchronousServerSocketChannel that has been openened and connected by an asynchronous execution.
    • Constructor Summary

      Constructors 
      Constructor Description
      ServerSocketAccept​(java.util.function.Function<Continuation<?>,​java.net.SocketAddress> getSocketAddress, Coroutine<java.nio.channels.AsynchronousSocketChannel,​?> requestHandler)
      Creates a new instance that accepts a single server request and processes it asynchronously in a coroutine.
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      static ServerSocketAccept acceptRequestOn​(java.util.function.Function<Continuation<?>,​java.net.SocketAddress> getSocketAddress, Coroutine<java.nio.channels.AsynchronousSocketChannel,​?> requestHandler)
      Accepts an incoming request on the given socket address and then handles it by executing the given coroutine with the client socket channel as it's input.
      protected java.lang.Void execute​(java.lang.Void input, Continuation<?> continuation)
      This method must be implemented by subclasses to provide the actual functionality of this step.
      protected java.nio.channels.AsynchronousServerSocketChannel getServerSocketChannel​(Continuation<?> continuation)
      Returns the channel to be used by this step.
      protected java.net.SocketAddress getSocketAddress​(Continuation<?> continuation)
      Returns the address of the socket to connect to.
      protected java.util.function.Function<Continuation<?>,​java.net.SocketAddress> getSocketAddressFactory()
      Returns the socket address factory of this step.
      void runAsync​(java.util.concurrent.CompletableFuture<java.lang.Void> previousExecution, CoroutineStep<java.lang.Void,​?> nextStep, Continuation<?> continuation)
      Runs this execution step asynchronously as a continuation of a previous code execution in a CompletableFuture and proceeds to the next step afterwards.
      • Methods inherited from class org.obrel.core.RelatedObject

        deleteRelation, get, getRelation, getRelations, notifyRelationListeners, readRelations, relationsEqual, relationsHashCode, relationsString, set, set, transform, writeRelations
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • Methods inherited from interface de.esoco.lib.property.Fluent

        _with
      • Methods inherited from interface org.obrel.core.FluentRelatable

        with, with, with
      • Methods inherited from interface org.obrel.core.Relatable

        deleteRelation, deleteRelation, deleteRelations, get, getAll, getOption, getRelation, getRelationCount, getRelations, getRelations, hasFlag, hasRelation, hasRelations, init, set, set, set, set, set, setOption, streamRelations, transform
    • Field Detail

      • SERVER_SOCKET_CHANNEL

        public static final org.obrel.core.RelationType<java.nio.channels.AsynchronousServerSocketChannel> SERVER_SOCKET_CHANNEL
        State: an AsynchronousServerSocketChannel that has been openened and connected by an asynchronous execution.
    • Constructor Detail

      • ServerSocketAccept

        public ServerSocketAccept​(java.util.function.Function<Continuation<?>,​java.net.SocketAddress> getSocketAddress,
                                  Coroutine<java.nio.channels.AsynchronousSocketChannel,​?> requestHandler)
        Creates a new instance that accepts a single server request and processes it asynchronously in a coroutine. The server socket is bound to the local socket with the address provided by the given factory. The factory may return NULL if the step should connect to a channel that is stored in a state relation with the type SERVER_SOCKET_CHANNEL.
        Parameters:
        getSocketAddress - A function that provides the socket address to connect to from the current continuation
        requestHandler - A coroutine that processes a single server request
    • Method Detail

      • acceptRequestOn

        public static ServerSocketAccept acceptRequestOn​(java.util.function.Function<Continuation<?>,​java.net.SocketAddress> getSocketAddress,
                                                         Coroutine<java.nio.channels.AsynchronousSocketChannel,​?> requestHandler)
        Accepts an incoming request on the given socket address and then handles it by executing the given coroutine with the client socket channel as it's input.
        Parameters:
        getSocketAddress - A function that produces the address of the local address to accept the request from
        requestHandler - The coroutine to process the next request with
        Returns:
        The new step
      • runAsync

        public void runAsync​(java.util.concurrent.CompletableFuture<java.lang.Void> previousExecution,
                             CoroutineStep<java.lang.Void,​?> nextStep,
                             Continuation<?> continuation)
        Runs this execution step asynchronously as a continuation of a previous code execution in a CompletableFuture and proceeds to the next step afterwards.

        Subclasses that need to suspend the invocation of the next step until some condition is met (e.g. sending or receiving data has finished) need to override this method and create a Suspension by invoking Continuation.suspend(CoroutineStep, CoroutineStep) on the next step. If the condition that caused the suspension resolves the coroutine execution can be resumed by calling Suspension.resume(Object).

        Subclasses that override this method also need to handle errors by terminating any further execution (i.e. not resuming a suspension if such exists) and forwarding the causing exception to Continuation.fail(Throwable).

        Overrides:
        runAsync in class CoroutineStep<java.lang.Void,​java.lang.Void>
        Parameters:
        previousExecution - The future of the previous code execution
        nextStep - The next step to execute or NULL for none
        continuation - The continuation of the execution
      • execute

        protected java.lang.Void execute​(java.lang.Void input,
                                         Continuation<?> continuation)
        This method must be implemented by subclasses to provide the actual functionality of this step.
        Specified by:
        execute in class CoroutineStep<java.lang.Void,​java.lang.Void>
        Parameters:
        input - The input value
        continuation - The continuation of the execution
        Returns:
        The result of the execution
      • getServerSocketChannel

        protected java.nio.channels.AsynchronousServerSocketChannel getServerSocketChannel​(Continuation<?> continuation)
                                                                                    throws java.io.IOException
        Returns the channel to be used by this step. This first checks the currently exexcuting coroutine in the continuation parameter for an existing SERVER_SOCKET_CHANNEL relation. If that doesn't exists or if it contains a closed channel a new AsynchronousServerSocketChannel will be opened and stored in the state object.
        Parameters:
        continuation - The continuation to query for an existing channel
        Returns:
        The channel
        Throws:
        java.io.IOException - If opening the channel fails
      • getSocketAddress

        protected java.net.SocketAddress getSocketAddress​(Continuation<?> continuation)
        Returns the address of the socket to connect to.
        Parameters:
        continuation - The current continuation
        Returns:
        The socket address
      • getSocketAddressFactory

        protected java.util.function.Function<Continuation<?>,​java.net.SocketAddress> getSocketAddressFactory()
        Returns the socket address factory of this step.
        Returns:
        The socket address factory function