web stats
Sending bytes with TCP Sender - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #1  
Old 11-09-2018, 06:49 PM
kerig kerig is offline
Mirth Newb
 
Join Date: Nov 2018
Posts: 6
kerig is on a distinguished road
Lightbulb Sending bytes with TCP Sender

Hi !

First, this is my first post here and I would like to thank you for this amazing project !
I am facing a Java related problem but I hope Mirth users have a workaround.

I am trying to implement a TCP protocole and I need to send bytes through TCP:
I have to send an Integer with 8 bytes in little endian. This my code:

Code:
var bytes = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 8);
bytes[0] = (data_length & 0xFF);
bytes[1] = (data_length >> 8) & 0xFF;
bytes[2] = (data_length >> 16) & 0xFF;
bytes[3] = (data_length >> 24) & 0xFF;

for(var i = 0; i < bytes.length; i++){
	logger.info(java.lang.Integer.toHexString(bytes[i]) );
	logger.info(String.fromCharCode(bytes[i]) );
	length_hex[i] = java.lang.Integer.toHexString(bytes[i]);
	length_bytes[i] = String.fromCharCode(bytes[i]);
}
globalChannelMap.put('value', length_bytes.join(''));
This is working as expected except for some integer values.
For example 1664 (0x80 0x06 0x00 0x00 0x00 0x00 0x00 0x00 in 8 bytes little endian).
I have the error: "can't convert 128 to java.lang.Byte" because of Java primitive Byte which is signed so I can only store values in [-127, 127]. 0x80 = 128 > 127.

I tried with ByteBuffer: no error but a memory bug:

Code:
bb = Packages.java.nio.ByteBuffer.allocate(8);
bb.order(java.nio.ByteOrder.LITTLE_ENDIAN);
bb.putInt(1664);

for(var i = 0; i < bb.array().length; i++){
	length_hex[i] = java.lang.String.format("%1$02X", Packages.java.lang.Integer(bb.array()[i]) );
	length_bytes[i] = String.fromCharCode(bb.array()[i]);
}
First byte is 0xffffff80 instead of 0x80, it makes no sense for the server.
Is there any way to bypass this problem with Mirth ?

Thanks !
Reply With Quote
  #2  
Old 11-12-2018, 08:50 AM
kerig kerig is offline
Mirth Newb
 
Join Date: Nov 2018
Posts: 6
kerig is on a distinguished road
Default

Hi,

I found a way to store int values > 128:
Considering I will never have negative values, I store (value - 127) in a Java Byte and add 127 when I read this value.

Another problem appeared when sending data through TCP:

I can't send 0x80, Mirth seems to add a byte before.
I will post TCP dump at the end of the day.
Reply With Quote
  #3  
Old 11-12-2018, 12:19 PM
agermano agermano is offline
Mirth Guru
 
Join Date: Apr 2017
Location: Indiana, USA
Posts: 967
agermano is on a distinguished road
Default

The ByteBuffer works. It was your byte to integer conversion that was off.

Code:
bb = Packages.java.nio.ByteBuffer.allocate(8);
bb.order(java.nio.ByteOrder.LITTLE_ENDIAN);
bb.putInt(1664);

for(var i = 0; i < bb.array().length; i++){
	length_hex[i] = java.lang.String.format("%1$02X", Packages.java.lang.Integer(bb.array()[i] & 0xFF));
	length_bytes[i] = String.fromCharCode(bb.array()[i] & 0xFF);
}
You might also just want to try
Code:
msg = FileUtil.encode(bb.array());
When you have your TCP sender in binary mode, it expects a base64 encoded message.
Reply With Quote
  #4  
Old 11-12-2018, 05:50 PM
kerig kerig is offline
Mirth Newb
 
Join Date: Nov 2018
Posts: 6
kerig is on a distinguished road
Default

Thanks Agermano !
ByteBuffer is working with your solution !

When I send length_bytes = 1664 (0x80 0x06 0x00 0x00 0x00 0x00 0x00 0x00) through TCP Sender in Text mode I can see (in Hex) c2 8006 0000 0000 0000 on the network. Mirth seems to add 0xC2 before 0x80.
Same problem with Binary mode and Base 64 encoding.

If I send length_bytes = 1657 (0x79 0x06 0x00 0x00 0x00 0x00 0x00 0x00), there is no byte added, everything is ok.

I would like to try with bb.array() but do you have an idea how to concat bb.array() safely with strings ? Because I have to send text data with those 8 bytes.

Thanks again for your help !
Reply With Quote
  #5  
Old 11-12-2018, 08:48 PM
agermano agermano is offline
Mirth Guru
 
Join Date: Apr 2017
Location: Indiana, USA
Posts: 967
agermano is on a distinguished road
Default

I've never actually worked with ByteBuffers before, but I think this should work:

Code:
var data = 'this is a test string.';
var dataBytes = new java.lang.String(data).getBytes('UTF-8');

var bb = java.nio.ByteBuffer.allocate(8 + dataBytes.length);
bb.order(java.nio.ByteOrder.LITTLE_ENDIAN);

bb.putInt(1664);
bb.putInt(0x00000679);
bb.put(dataBytes);

msg = FileUtil.encode(bb.array());
I don't think you should have the C2 issue when in binary mode. I'm pretty sure that is coming from the UTF-8 character encoding in text mode. Any char code over 0x79 (where the high order bit is 1) will translate to multiple bytes in UTF-8 encoding.

Code:
js> new java.lang.String(String.fromCharCode(0x80)).getBytes('UTF-8').map(function(x) { return (x & 0xFF).toString(16)})
c2,80
Reply With Quote
  #6  
Old 11-12-2018, 09:23 PM
agermano agermano is offline
Mirth Guru
 
Join Date: Apr 2017
Location: Indiana, USA
Posts: 967
agermano is on a distinguished road
Default

Assigning the base64 string to msg assumes for this transformer that you have your outbound data type set to Raw, and you have no outbound template specified. Then in your tcp sender template, you use ${message.encodedData}. Notice when you change from text to binary mode that the encoding drop-down becomes disabled.
Reply With Quote
  #7  
Old 11-13-2018, 02:53 PM
kerig kerig is offline
Mirth Newb
 
Join Date: Nov 2018
Posts: 6
kerig is on a distinguished road
Thumbs up

Hi !
It's working now, thanks a lot Agermano !
I think Text mode cause the additional byte problem, working with binary mode avoid the problem.

For people interested in the code (TCP Sender in binary mode needed):

Code:
var data = "thanks Agermano !";

var header = "Mirth Forum";
var length_hex = []; //for debug purpose only

header_bytes = new java.lang.String(header).getBytes('UTF-8');
data_bytes = new java.lang.String(data).getBytes('UTF-8');

bb = Packages.java.nio.ByteBuffer.allocate(8);
bb.order(java.nio.ByteOrder.LITTLE_ENDIAN);
bb.putInt(data_bytes.length);

//for debug purpose only:
for(var i = 0; i < bb.array().length; i++){
	length_hex[i] = java.lang.String.format("%1$02X", Packages.java.lang.Integer(bb.array()[i] & 0xFF) ); 
}
logger.info("LENGTH HEX little endian: " + length_hex); //for debug purpose only

full_message = Packages.java.nio.ByteBuffer.allocate(header_bytes.length + 8 + data_bytes.length);
full_message.put(header_bytes);
full_message.put(bb.array());
full_message.put(data_bytes);

msg = FileUtil.encode(full_message.array());
Everything is working fine, server is happy !
Reply With Quote
Reply

Tags
bytes, tcp sender

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 02:45 PM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Mirth Corporation