/* * Copyright 2015 LMAX Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lmax.nanofix; import java.net.InetSocketAddress; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.lmax.nanofix.concurrent.NamedThreadFactory; import com.lmax.nanofix.concurrent.ThreadBlocker; import com.lmax.nanofix.incoming.ByteChannelReader; import com.lmax.nanofix.incoming.FixMessagePublisher; import com.lmax.nanofix.incoming.FixMessageStreamFactory; import com.lmax.nanofix.incoming.FixStreamMessageParser; import com.lmax.nanofix.incoming.FixTagParser; import com.lmax.nanofix.incoming.RawFixMessageHandler; import com.lmax.nanofix.outgoing.OutboundMessageHandler; import com.lmax.nanofix.transport.AsyncTcpSocketFactory; import com.lmax.nanofix.transport.PublishingConnectionObserver; import com.lmax.nanofix.transport.SocketFactory; import com.lmax.nanofix.transport.TcpTransport; import com.lmax.nanofix.transport.Transport; import com.lmax.nanofix.transport.TransportConfigImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class FixClientFactory { private static final Logger LOGGER = LoggerFactory.getLogger(FixClientFactory.class); static final Thread.UncaughtExceptionHandler UNCAUGHT_EXCEPTION_HANDLER = new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread thread, Throwable throwable) { LOGGER.error("Uncaught Exception thrown in thread: " + thread.getName(), throwable); } }; private FixClientFactory() { } /** * Max Fix Message size */ private static final int MAX_MESSAGE_SIZE = 2000; /** * Create an initiating fix client that will connect to the host on connect() * * @param host hostname of server to connect to. * @param port tcp port number int between 0 and 65535 */ public static FixClient createFixClient(final String host, final int port) { return createFixClient(new InetSocketAddress(host, port), new SystemConfig(false)); } /** * Create an listening fix client that will listen for inbound tcp connections on port * * @param port tcp port number int between 0 and 65535 */ public static FixClient createFixClient(final int port) { return createFixClient(new InetSocketAddress(port), new SystemConfig(false)); } /** * Create a fix client * * @param host to bind to if listening for a connection or host to connect to when attempting to connect. * @param port tcp port number int between 0 and 65535 * @param systemConfig additional NanoFix configuration */ public static FixClient createFixClient(final String host, final int port, final SystemConfig systemConfig) { return createFixClient(new InetSocketAddress(host, port), systemConfig); } public static FixClient createFixClient(final SocketFactory socketFactory) { final PublishingConnectionObserver publishingTransportObserver = new PublishingConnectionObserver(); final TcpTransport transport = new TcpTransport(publishingTransportObserver, null, socketFactory, new TransportConfigImpl(false)); publishingTransportObserver.addObserver(transport); return buildFixClient(transport, publishingTransportObserver, MAX_MESSAGE_SIZE); } /** * Build an initiating or listening {@link FixClient} based on the values contained in {@link FixClientConfiguration} * * @param fixClientConfiguration Contains configuration that determines the type of {@link FixClient} */ public static FixClient createFixClient(final FixClientConfiguration fixClientConfiguration) { final InetSocketAddress socketAddress = fixClientConfiguration.getSocketAddress(); final SocketFactory socketFactory = fixClientConfiguration.getSocketFactory(); final SystemConfig systemConfig = fixClientConfiguration.getSystemConfig(); final int maxMessageSize = fixClientConfiguration.getMaxMessageSize(); final PublishingConnectionObserver publishingTransportObserver = new PublishingConnectionObserver(); final TcpTransport transport = new TcpTransport(publishingTransportObserver, socketAddress, socketFactory, systemConfig); publishingTransportObserver.addObserver(transport); return buildFixClient(transport, publishingTransportObserver, maxMessageSize); } private static FixClient createFixClient(final InetSocketAddress socketAddress, final SystemConfig systemConfig) { final PublishingConnectionObserver publishingTransportObserver = new PublishingConnectionObserver(); final ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("InboundConnection", true, UNCAUGHT_EXCEPTION_HANDLER)); final AsyncTcpSocketFactory asyncTcpSocketFactory = new AsyncTcpSocketFactory(executorService); final TcpTransport transport = new TcpTransport(publishingTransportObserver, socketAddress, asyncTcpSocketFactory, systemConfig); publishingTransportObserver.addObserver(transport); return buildFixClient(transport, publishingTransportObserver, MAX_MESSAGE_SIZE); } private static FixClient buildFixClient(final Transport transport, final PublishingConnectionObserver publishingTransportObserver, final int maxMessageSize) { final FixStreamMessageParser fixStreamMessageParser = new FixStreamMessageParser(maxMessageSize); final ThreadBlocker messageConsumingThreadBlocker = new ThreadBlocker(); final FixMessagePublisher fixMessagePublisher = new FixMessagePublisher(); fixStreamMessageParser.initialise(new RawFixMessageHandler(new FixTagParser(new FixMessageStreamFactory(fixMessagePublisher)))); final OutboundMessageHandler outboundMessageSender = new OutboundMessageHandler(publishingTransportObserver); final ByteChannelReader inputStreamReader = new ByteChannelReader(fixStreamMessageParser, messageConsumingThreadBlocker, publishingTransportObserver); final ExecutorService channelReaderExecutorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("channelReader", true, UNCAUGHT_EXCEPTION_HANDLER)); final ChannelInitializer channelInitializer = new ChannelInitializer(transport, inputStreamReader, outboundMessageSender, channelReaderExecutorService); publishingTransportObserver.addObserver(channelInitializer); return new FixClient(fixMessagePublisher, channelInitializer, transport, new FixSession(outboundMessageSender), messageConsumingThreadBlocker); } }