Hi,
I am working on a MINA-based application that communicates with a
wide variety of manufacturers' devices, some are serial, others use
socket connections. All have been designed to be
transport-transparent, allowing us to simulate devices and specific
situations via socket-based simulator.
I added a CaptureLogFilter object to log data flow to a separate
file. I hook that object into the filter chain as each connection is
created.
Inside CaptureLogFilter, in both messageSent() and messageReceived()
hooks, I check the message parameter, and if it is an IoBuffer, I spit
out a capture line SENT (or RECEIVED) + # of bytes + a hex dump of those
bytes.
For simulated data sets (socket-based connections) this works great, my
capture log shows
SENT x bytes blah blah blah
SENT 0 bytes
RECEIVED y bytes blah blah blah
The extra "SENT 0 bytes" seemed odd but harmless.... until I noticed
what happens on serial connections. For those I invariably see:
SENT 0 bytes
RECEIVED y bytes blah blah blah
Each and every SENT line from a serial-based connection reads 0 bytes,
and I never see the actual command packet that I sent out. It seems
apparent that said data was received by the far end device, as the
RECEIVED lines show all the right responses, but my log only contains
half the conversation since all the SENT lines erroneously report "0 bytes."
My filter looks like:
public class CaptureLogFilter extends IoFilterAdapter {
...
@Override
public void messageReceived(NextFilter nextFilter, IoSession
session, Object message) throws Exception {
log("RECEIVED: ", message);
if (nextFilter != null ) nextFilter.messageReceived(session,
message);
}
@Override
public void messageSent(NextFilter nextFilter, IoSession session,
WriteRequest writeRequest) throws Exception {
log("SENT: ", writeRequest.getMessage());
if (nextFilter != null ) nextFilter.messageSent(session,
writeRequest);
}
...
private void log(String event, Object arg) {
if (arg != null && arg instanceof IoBuffer) {
byte b[] = IoBufferUtils.asBytes((IoBuffer) arg);
log(event + b.length + " bytes: " + ByteUtils.toHex(b));
// IoBuffer i = (IoBuffer)arg;
// log("DBG: " + event + "pos: " + i.position() + ", lim:
"+i.limit());
// Previous debug was added to confirm IoBufferUtils operation, the
IoBuffer 'arg' is confirmed empty (both position & limit are 0)
}
else log(event);
}
...
}
And is hooked in the IoConnector set up:
private final IoConnector buildIoConnector() {
...
if ( codecFilter == null )
codecFilter = new ProtocolCodecFilter(createCodecFactory());
...
DefaultIoFilterChainBuilder fc = connector.getFilterChain();
if ( fc.contains("logging") ) fc.remove("logging");
if ( fc.contains("codec") ) fc.remove("codec");
fc.addLast("logging", new
CaptureLogFilter(getClass().getSimpleName()));
fc.addLast("codec", codecFilter);
...
}
Anything obvious jump out at you experts? :-) I'm baffled as to why
one type of connection would perform any differently than the other.
I tried reversing the order of the codec & logging filter addLast()
calls, but that captured internal protocol objects that had not yet been
encoded into the data stream.
I can switch the same protocol handler between simulated (socket) and
real (serial) connections and watch the SENT lines appear or disappear
based on the connection type.
Any clues at all would be greatly appreciated!!
Thanks in advance!!
boB
--
boB Gage
Software Engineer
Merge Healthcare