FixAlchemy.Server (FIXAlchemy v0.2.1)

View Source

A FIX acceptor: listens for initiators and runs a session for each.

Where FixAlchemy.Client dials a venue, a server waits to be dialed. It owns a listening socket, and every connection it accepts becomes a FixAlchemy.Server.Session that identifies itself by its Logon before it becomes a session at all.

Both sides run the same FixAlchemy.Engine, so an accepted session behaves the same as an initiated one once logon is complete: subscribers receive {:fix, type, raw, meta}, sequence recovery and validation work the same way, and sessions register in FixAlchemy.Registry under {connection_id, session_name}.

{:ok, _server} =
  FixAlchemy.Server.start_link(
    server_id: "acme",
    port: 5001,
    spec_file: "priv/specs/FIX44.xml",
    validate_inbound: true,
    sessions: [
      [
        connection_id: "acme_client",
        sender_comp_id: "ACME",
        target_comp_id: "CLIENT",
        handlers: [MyApp.OrderHandler]
      ]
    ]
  )

Options

  • :server_id - names the server in the registry (required)
  • :port - the port to listen on; 0 asks the operating system for one, readable afterwards with port/1 (required)
  • :sessions - the sessions this server accepts, each carrying at least :sender_comp_id and :target_comp_id; see FixAlchemy.Server.Logon (required)
  • :spec_file / :app_spec_file - the FIX dictionary, as FixAlchemy.Parser.init/1 takes them
  • :tls - accept TLS rather than plain TCP; pass :certfile and :keyfile (or any other :ssl server option) in :tls_opts
  • :ip - the interface to bind, default all
  • :authenticate - a function replacing per-session credential checking
  • :validate_inbound - check every inbound message and Reject a bad one, default false; an acceptor exposed to a counterparty it does not control should turn this on
  • :sequence_recovery, :validate_checksum, :message_store, :routing_keys - passed to each session's FixAlchemy.Engine

Everything a matched session declares overrides the server-wide value, so one server can accept sessions with different handlers, roles, or storage.

Summary

Functions

Returns a specification to start this module under a supervisor.

The port the server is listening on, resolved when :port was 0.

The sessions this server currently has open, as {connection_id, session_name}.

Start an acceptor.

Stop the server and every session it is running.

Check that opts describe a startable server.

Functions

child_spec(init_arg)

@spec child_spec(keyword()) :: Supervisor.child_spec()

Returns a specification to start this module under a supervisor.

See Supervisor.

port(server_id)

@spec port(binary()) :: :inet.port_number()

The port the server is listening on, resolved when :port was 0.

sessions(server_id)

@spec sessions(binary()) :: [{binary() | nil, atom() | binary()}]

The sessions this server currently has open, as {connection_id, session_name}.

start_link(opts)

@spec start_link(keyword()) ::
  Supervisor.on_start() | {:error, {:invalid_config, term()}}

Start an acceptor.

Returns {:error, {:invalid_config, reason}} when the options cannot describe a working server; no process is started in that case.

stop(server_id)

@spec stop(binary()) :: :ok

Stop the server and every session it is running.

validate(opts)

@spec validate(keyword()) :: :ok | {:error, {:invalid_config, term()}}

Check that opts describe a startable server.

Reports the first problem it finds. start_link/1 calls this itself; call it directly to check a configuration before committing to it.