Skip to content
Don Mendelson edited this page Oct 3, 2015 · 4 revisions

Starting a Silver Flash Engine

Before a FIXP session can be created, supporting services must be started. An Engine object is instantiated using its Builder class, and then it is opened to start the underlying services. Starting an engine is largely the same for client and server side, but the server typically also provides a service to authenticate connecting clients. In this example, a server uses a simple in-memory directory of users for authentication.

    SimpleDirectory directory = new SimpleDirectory();
    String userCredentials = . . .
    directory.add(userCredentials);
    Engine engine =
        Engine.builder().withAuthenticator(new SimpleAuthenticator().withDirectory(directory))
            .build();
    engine.open();

Application layer provides a message Consumer

On both client and server side, the application must provide a Consumer for received messages. You have a choice of providing a separate Consumer for each session or using a single Consumer for all sessions. Thread safety may be a consideration in that decision.

  class MyReceiver implements MessageConsumer<UUID> {

    public void accept(ByteBuffer buf, Session<UUID> session, long seqNo) {
      // FIXP sessions are identified by a UUID
      UUID sessionId = session.getSessionId();
      // Decode and handle the received message
      . . .
    }
  }

Creating a Server

Creating a server Transport

Transports may either be connectionless or connection oriented. In the case of TCP, (connection oriented), a Connector / Acceptor pattern must be used to establish the Transport.

    String hostname = . . .
    int port = . . .
    InetSocketAddress serverAddress = new InetSocketAddress(hostname, port);
    TcpAcceptor tcpAcceptor =
        new TcpAcceptor(engine.getIOReactor().getSelector(), serverAddress, clientAcceptor));
    tcpAcceptor.open().get();

Accepting a new session

Sessions are instantiated by a Function that is invoked by the TcpAcceptor when a new TCP connection is accepted. The function sets all of the characteristics of a new FIXP session. Note that on the server side, it is essential to invoke asServer() to tell the new session to play the server role in FIXP session establishment.

    Function<Transport, FixpSession> clientAcceptor = new Function<Transport, FixpSession>() {

      public FixpSession apply(Transport serverTransport) {
        try {
          FixpSession serverSession =
              FixpSession
                  .builder()
                  .withReactor(engine.getReactor())
                  .withTransport(serverTransport)
                  .withBufferSupplier(
                      new SingleBufferSupplier(ByteBuffer.allocate(16 * 1024).order(
                          ByteOrder.nativeOrder())))
                  .withMessageConsumer(serverReceiver)
                  .withOutboundFlow(FlowType.IDEMPOTENT)
                  .withOutboundKeepaliveInterval(keepAliveInterval)
                  .asServer().build();

          serverSession.open();

          return serverSession;
        } catch (Exception e) {
          // log the exception
        }
        return null;
      }
    };

Creating a client

Creating a client is simpler than the server side. You create a Connector transport and instantiate a session object directly. You just have one additional task on the client side -- to generate a unique session ID.

      Transport clientTransport =
          new TcpConnectorTransport(engine.getIOReactor().getSelector(), serverAddress);
      UUID sessionId = SessionId.generateUUID();

      FixpSession clientSession =
          FixpSession
              .builder()
              .withReactor(engine.getReactor())
              .withTransport(clientTransport)
              .withBufferSupplier(
                  new SingleBufferSupplier(ByteBuffer.allocate(16 * 1024).order(
                      ByteOrder.nativeOrder())))
              .withMessageConsumer(clientReceiver)
              .withOutboundFlow(FlowType.IDEMPOTENT)
              .withSessionId(sessionId)
              .withClientCredentials(userCredentials.getBytes())
              .withOutboundKeepaliveInterval(keepAliveInterval).build();

Opening a client session

Opening a session, like many functions in Silver Flash, is an asynchronous operation. It returns a CompletableFuture that lets you register a function to run when the operation completes.

       CompletableFuture<ByteBuffer> readyFuture =
            new SessionReadyFuture(client.getSessionId(), engine.getReactor());
        readyFuture.thenRun(startTrading);
        client.open();

Similarly, a future can be registered to invoke a cleanup function when a session terminates.

Sending an application message

Once a session has received notification that establishment is complete, your application is free to send application messages.

    ByteBuffer buf = ByteBuffer.allocate(8096).order(ByteOrder.nativeOrder());

    buf.clear();
    // Encode a message
    clientSession.send(buf);