Adding a custom MINA IO Filter allows you to inspect and manipulate:
MINA's javadoc for IoFilter
gives some examples of how this could be useful:
- Event logging
- Performance measurement
- Authorization
- Overload control
- Message transformation (e.g. encryption and decryption, ...)
To add a filter, you need to insert it into the filter chain by supplying an IoFilterChainBuilder to the connector or acceptor with setIoFilterChainBuilder().
final BlacklistFilter blacklistFilter = new BlacklistFilter(); ... /* * setIoFilterChainBuilder is defined on the SessionConnector abstract class */ ((SessionConnector) acceptor).setIoFilterChainBuilder(new IoFilterChainBuilder() { public void buildFilterChain(IoFilterChain chain) { chain.addBefore(FIXProtocolCodecFactory.FILTER_NAME, "BlacklistFilter", blacklistFilter); }});
Note the reference to FIXProtocolCodecFactory.FILTER_NAME. QuickFIX/J uses a ProtocolCodecFilter to transform between streamed byte data on the wire and quickfix.Message objects, as shown below.
You should add your filter before this one to have it act on the byte stream, or after it to act on quickfix.Message data.
Following are some examples showing how to add filters to the example order executor application
MINA comes with a Blacklist filter which closes incoming connections from blacklisted addresses. Lets add this filter to the order executor and make it block connections from localhost. We will add it before the protocol codec filter.
To do this, change:
acceptor = new SocketAcceptor (application, messageStoreFactory, settings, logFactory, messageFactory); acceptor.start();
to this (plus the appropriate imports):
acceptor = new SocketAcceptor (application, messageStoreFactory, settings, logFactory, messageFactory); /* create the filter and add an address to the blacklist */ final BlacklistFilter blacklistFilter = new BlacklistFilter(); blacklistFilter.block(InetAddress.getByName("localhost")); /* add it to the acceptor */ ((SessionConnector) acceptor).setIoFilterChainBuilder(new IoFilterChainBuilder() { public void buildFilterChain(IoFilterChain chain) { chain.addBefore(FIXProtocolCodecFactory.FILTER_NAME, "BlacklistFilter", blacklistFilter); }}); acceptor.start();
Now when you start the executor and banzai apps you'll see this:
Executor Log<20060913-10:54:22, FIX.4.2:EXEC->BANZAI, event> (Session FIX.4.2:EXEC->BANZAI schedule is daily, 00:00:00 UTC - 00:00:00 UTC) <20060913-10:54:22, FIX.4.2:EXEC->BANZAI, event> (Valid order types: [F, 2]) <20060913-10:54:22, FIX.4.2:EXEC->BANZAI, event> (Created session: FIX.4.2:EXEC->BANZAI) 13/09/2006 20:54:22 quickfix.mina.acceptor.AbstractSocketAcceptor startAcceptingConnections INFO: Listening for connections at 0.0.0.0/0.0.0.0:9876 press <enter> to quit 13/09/2006 20:54:26 quickfix.mina.acceptor.AcceptorIoHandler sessionCreated INFO: MINA session created: /127.0.0.1:4538 13/09/2006 20:54:26 org.apache.mina.util.SessionLog info INFO: [/127.0.0.1:4538] Remote address in the blacklist; closing. 13/09/2006 20:54:26 org.apache.mina.util.SessionLog info INFO: [/127.0.0.1:4538] Remote address in the blacklist; closing.Banzai Log
<20060913-10:54:26, FIX.4.2:BANZAI->EXEC, event> (Session FIX.4.2:BANZAI->EXEC schedule is daily, 00:00:00 UTC - 00:00:00 UTC) <20060913-10:54:26, FIX.4.2:BANZAI->EXEC, event> (Created session: FIX.4.2:BANZAI->EXEC) <20060913-10:54:26, FIX.4.2:BANZAI->EXEC, outgoing> (8=FIX.4.29=6535=A34=449=BANZAI52=20060913-10:54:26.75056=EXEC98=0108=3010=223) <20060913-10:54:26, FIX.4.2:BANZAI->EXEC, event> (Initiated logon request) <20060913-10:54:26, FIX.4.2:BANZAI->EXEC, event> (Disconnecting) 13/09/2006 20:54:26 quickfix.mina.initiator.InitiatorIoHandler sessionCreated INFO: MINA session created: /127.0.0.1:4538
A whitelist filter is available at http://www.quickfixj.org/confluence/download/attachments/530/WhitelistFilter.java. The code changes required to use it are similar to the Blacklist filter, except that:
acceptor = new SocketAcceptor (application, messageStoreFactory, settings, logFactory, messageFactory); final WhitelistFilter whitelistFilter = new WhitelistFilter(settings); ((SessionConnector) acceptor).setIoFilterChainBuilder(new IoFilterChainBuilder() { public void buildFilterChain(IoFilterChain chain) { chain.addAfter(FIXProtocolCodecFactory.FILTER_NAME, "WhitelistFilter", whitelistFilter); }}); acceptor.start();
Specify valid IP addresses with the WhitelistHost setting, at either the default or session levels as required.
[default] ... WhitelistHost=www.quickfixj.org [session] SenderCompID=EXEC TargetCompID=BANZAI [session] SenderCompID=EXEC TargetCompID=SONOFBANZAI WhitelistHost1=127.0.0.1 WhitelistHost2=192.168.0.1, 192.168.0.2 [session] SenderCompID=EXEC TargetCompID=FREEFORALL WhitelistHost=
On startup the valid hosts will be logged:
INFO: Authorised IPs for FIX.4.2:EXEC->FREEFORALL: [Any] INFO: Authorised IPs for FIX.4.2:EXEC->BANZAI: [www.quickfixj.org/213.246.61.101] INFO: Authorised IPs for FIX.4.2:EXEC->SONOFBANZAI: [/192.168.0.1, /127.0.0.1, www.quickfixj.org/213.246.61.101, /192.168.0.2]
New connections will be validated against the authorised IPs once the first message is received and closed if they are not valid:
WARNING: [/127.0.0.1:2633] Closing FIX.4.2:EXEC->BANZAI connection from unauthorised address.