camel netty4 message 1024 truncated..how can i solve it? - apache-camel

i made a camel netty4 server program.and client sent 1119 byte message but my decoder truncated by 1024/95
here is my code.
#ChannelHandler.Sharable
public static class BytesDecoder extends MessageToMessageDecoder<ByteBuf> {
#Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
System.out.println("BytesDecoder readableBytes:"+msg.readableBytes());
if (msg.isReadable()) {
byte[] bytes = new byte[msg.readableBytes()];
int readerIndex = msg.readerIndex();
msg.getBytes(readerIndex, bytes);
out.add(bytes);
}
}
}
result ===>
BytesDecoder readableBytes:1024
BytesDecoder readableBytes:95
I want to get a full message byte 1119 byte.

Actually I already replied to this question on the netty mailinglist.
There is not guarantee that you will received all the data in one read call. Thus you will need to account for this by extending ByteToMessageDecoder and only read the bytes once there are at least 1024 readable.
For more example and details please see the javadocs of ByteToMessageDecoder.

Related

GLIB D-BUS Bluetooth - How to get the file descriptor?

I am using BLUEZ and GLIB/D-BUS to connect 2 Raspberry Pi (also a laptop and a Raspberry Pi).
So far I could make fair progress.
EDIT: on good advises from #ukBaz I am using a python client from my laptop, and my C code server on the Raspberry Pi.
On the "server", I can register the device with a custom service UUID and a Serial RFCOMM profile UUID, and wait for connection. Connecting with the python client works and I can see that there is a handler available (see after code below for debug output)
I'm using this code (within a dbus loop, code simplified for readability):
static void new_connection(GDBusMethodInvocation *inv)
{
g_log(LOG_SERVER, G_LOG_LEVEL_MESSAGE, "New connection.");
GDBusMessage *msg = g_dbus_method_invocation_get_message(inv);
// This prints the output below this code snippet
gchar *content = g_dbus_message_print(msg, 2);
g_log(LOG_SERVER, G_LOG_LEVEL_INFO, "Message is:\n%s", content);
g_free(content);
GVariant *params = g_dbus_method_invocation_get_parameters(inv);
const char *object;
GVariant *properties;
gint32 *handle;
g_variant_get(params, "(oha{sv})", &object, &handle, &properties);
// Problem here, 'handle' is NULL
g_log(LOG_SERVER, G_LOG_LEVEL_INFO, "Object is [%s]\nHandle is [%ls]", object, handle);
GVariantIter iter;
g_variant_iter_init(&iter, properties);
display_properties(&iter);
}
Here is the output:
New connection.
Message is:
Type: method-call
Flags: none
Version: 0
Serial: 32
Headers:
path -> objectpath '/org/bluez/jscturret'
interface -> 'org.bluez.Profile1'
member -> 'NewConnection'
destination -> ':1.18'
sender -> ':1.11'
signature -> signature 'oha{sv}'
num-unix-fds -> uint32 1
Body: (objectpath '/org/bluez/hci0/dev_00_AA_AA_AA_AA_AA', handle 0, #a{sv} {})
UNIX File Descriptors:
fd 7: dev=0:8,mode=0140777,ino=41101,uid=0,gid=0,rdev=0:0,size=0,atime=0,mtime=0,ctime=0
Object is [/org/bluez/hci0/dev_00_AA_AA_AA_AA_AA]
Handle is [(null)]
It shows that there is a file descriptor fd 7 but when I read the GVariant parameter I get NULL.
How can I access the file descriptor? My understanding is I need that to be able to read/write from/to the client.
I used https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt and https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/adapter-api.txt for reference and a few other posts here on SO.
Also got a lot of info in https://www.linumiz.com/.
Current full code is available here: btservice
Oh! I am pretty sure you are supposed to send a pointer to an integer (not a pointer to a pointer to it).
You can do
gint32 handle; // instead of gint32 *handle;
and it should work.
This API has a very poor design (relying on variadic, with format specifiers... the reason why people dislike C).

Extracting data from an unknown encoding file

We use testing equipment (1995 year manufacturing) powered by MS DOS. Analog-digital converter records information in the file.
In [picture1] is shown the structure of that file.
In [picture2] is shown the oscillogram that constructed according to the data from the file (program for opening the file on MS DOS).
Below I placed link to this file (google drive).
This file contains the data that need for me - the massive of point of oscillogram. I want have opportunities to keep, analyze and print this chart on Windows or Linux (not MS DOS). So I need to extract data from the file.
But I can't make it. And no program (known to me) can't open this file. I analyzed a few first byte and they point to program 'TRAS v4.99'. This program is on MS DOS.
But I really hope, that it is really to get data without this program.
P.S. If anyone will say it is impossible - it is will well too because I haven't found point of view yet:)
Thank you for your time! Best regards!
LINK TO FILE ON GOOGLE DISK - 00014380.K00
STRUCTURE OF FILE
OPENING FILE VIA PROGRAM IN MS DOS
Here is an idea on how you can tackle this problem. Since the format is relatively well specified in the handbook you can use the Java programming language for example with something like java.io.RandomAccessFile to read arrays of bytes. These arrays of bytes can then be converted to Java primitive types OR to string according to the data type. After this conversion you can the print out the data in a human readable format.
Below you can find some sample code to give you an idea of what you could do with this approach (I have not tested the code, it is not complete, it is just to give you an idea of what you can do):
public static void readBinaryfile() throws IOException {
java.io.RandomAccessFile randomAccessFile = new RandomAccessFile("test.bin", "r");
byte[] addKenStrBytes = new byte[12];
randomAccessFile.read(addKenStrBytes);
String addKenStr = new String(addKenStrBytes, "UTF-8");
// TODO: Do something with addKenStr.
System.out.println(addKenStr);
byte[] kopfSizeBytes = new byte[2];
randomAccessFile.read(kopfSizeBytes);
// TODO: Do something with kopfSizeBytes
System.out.println(convertToInt(kopfSizeBytes));
byte[] addRufNrCounterBytes = new byte[6];
randomAccessFile.read(addRufNrCounterBytes);
long addRufNrCounter = convertToLong(addRufNrCounterBytes);
// TODO: Do something with addRufNrCounter
System.out.println(addRufNrCounter);
byte[] endAdrBytes = new byte[4];
randomAccessFile.read(endAdrBytes);
// TODO: Do something with endAdrBytes
System.out.println(convertToLong(endAdrBytes));
// Continue here and after you reached the end of the record repeat until you reached the end off the file
}
private static int convertToInt(byte[] bytes) {
if(bytes.length > 4) {
throw new IllegalArgumentException();
}
int buffer = 0;
for(byte b : bytes) {
buffer |= b;
buffer = buffer << 8;
}
return buffer;
}
private static long convertToLong(byte[] bytes) {
if(bytes.length > 8) {
throw new IllegalArgumentException();
}
long buffer = 0L;
for(byte b : bytes) {
buffer |= b;
buffer = buffer << 8;
}
return buffer;
}
Note that fields with more than 8 bytes need to be most probably converted to strings. This is not complete code, just an example to give you an idea on how you can tackle this problem.

ns2 rebroadcasting packet when timer is expired

i need to rebroadcast packet when a waiting timer is expired, i follow steps defined at How to add timer in aodv using ns2 , i define agent and timer classes; the cross reference; initialization of timer object in agent constructor; and finally expire(Event*) for class B_suppression. when the execution reach
agent->rebroadcast((Packet*)p, 0); it abort with following message 'invalid SDVCAST packet type'. is casting from Event to Packet causes the problem?
class SDVCAST;
class B_suppression_Timer : public TimerHandler {
friend class SDVCAST;
public:
B_suppression_Timer (SDVCAST *s){agent = s;};
virtual void expire (Event *p);
private:
SDVCAST *agent;
};
class SDVCAST: public Agent
{ //define object from timer
B_suppression_Timer bstimer;
}
//initialized timer in Constructor of the SDVCAST
SDVCAST::SDVCAST(nsaddr_t id) : Agent(PT_SDVCAST),
bstimer(this){
}
// start timer
void
SDVCAST::weightepersistence(Packet *p, double delay){
bstimer.resched(delay);
}
// define expire of bstimer
void
B_suppression_Timer::expire(Event *p){
agent->rebroadcast((Packet*)p, 0);
}
Add the new packet type PT_SDVCAST to common/packet.h
static const packet_t PT_ SDVCAST = 73;
// insert new packet types here
static packet_t PT_NTYPE = 74; // This MUST be the LAST one
.
.
type == PT_SDVCAST)
.
.
name_[PT_SDVCAST]= "SDVCAST"
And maybe add SDVCAST to tcl/lib/ns-packet.tcl, ns-default.tcl , ns-agent.tcl etc.
EDIT : Answer to "Segmentation fault"
"The implementation of the Packet data structure of NS2 does not math
the realities. The packet in ns2 simulation keeps all packet headers
for any protocols implemented in NS2. For example, a DSR routing
packet may keep DSDV, AODV, or even a PING application header. For
this reason, till today, a packet used in ns2 simulation, would have a
header size around 40~64KB. And NO packet would be deleted to release
the memory it holds until the end of the simulation. So for a typical
simulation with 100 nodes in ns2 around 1M packets exchanged (of
course, you may reuse the packets already being freed through
Packet::free(Packet*). To learn the implementation of it, please check
file common/packet{.h,.cc} ), you may hold 10% of it, 100K packets,
and you may use a memory at least 100K*64KB -> 6.4GB, which definitely
would crash your computer (even it is a super server)."
Etc. etc. See http://www.linuxquestions.org/questions/linux-networking-3/ns2-and-aqua-sim-4175507630/#3
http://www.linuxquestions.org/questions/tags/segmentation%20fault%20ns2/

Send complete string array at once

I'm trying to send some Hayes commands (AT commands) to my modem through a serial line.
The function I call is post_request::open(). Within this method there is a static commands string array holding the commands to configure the connection profile.
My first question is: Should I use a more "flexible" approach on creating the commands list?
I always need to send these eight commands to my modem. Of course the url, content_type and content_length vary.
Maybe somebody can show me a better way to do it.
int post_request::open(const char *url, unsigned content_length, const char *content_type)
{
static const char *commands[] =
{
// Connection profile
"AT^SISS=0,conId,0;",
// HTTP
"AT^SISS=0,srvType,Http;",
// User Agent
"AT^SISS=0,hcUsrAgent," USER_AGENT_STRING ";",
// HTTP method
"AT^SISS=0,hcMethod,1;",
// Placeholder for modem type bdx80
"AT;",
// Placeholder for address
"AT;",
// Placeholder for number of bytes sent
"AT;",
// Placeholder for content type
"AT;",
// Open internet session with configured profile
"AT^SISO=0\r",
NULL
};
// Some code...
if (modem->modem_type == bdx80)
commands[4] = "AT^SISS=0,secOpt,-1;";
// Some more code...
commands[6] = "AT^SISS=0,hcContLen,",content_length,";";
// Code for content_type settings...
int error = send_commands(modem, timeout, commands);
if (error)
return error;
}
After I finished the connection profile setup, I call send_commands().
I have a third party library which does the uart transmit & receive stuff.
The function I call within send_commands() is uart_tx().
Question: What do I need to do, to call uart_tx() correctly? I want the complete commands list to be sent at once.
Thx
static int
send_commands(modem_t *modem, unsigned timeout, const char *commands[])
{
// determine size of commands pointer array
unsigned len = ???;
// Send commands through serial line
if (uart_tx(modem->port, ???, &len, timeout))
return TIMEOUT;
}
/**
* Sends count bytes.
* #param port The serial port.
* #param buf[in] Pointer to the buffer containing the bytes to be sent.
* #param count[in,out] Pointer to the value containing the number of bytes to send
* (in) and the number of bytes actually sent (out).
* #param time_to_wait The maximum amount of time the task should block waiting
* for count bytes to be sent should the transmit queue be full at some time.
* #return 0 on successful transmission, 1 on timeout
*/
unsigned uart_tx(SerialPort port, const void *buf, unsigned *count, unsigned time_to_wait)
It seems like you want to just concatenate (memcpy or strcat or whatever) all the commands into a single buffer before sending them out.

How do I send async data via libwebsocket?

I am using warmcat's libwebsocket C library for a small websocket server. I have the examples up and working and can send data in response to receiving data from the websocket (such as echoing back the reversed bytes sent). However, I haven't been able to figure out how to send data asynchronously from the server without already being in the libwebsocket callback function. I need the wsi pointer to pass to libwebsocket_write() but don't see how to get the pointer except while in the callback.
I've read that libwebsocket is not thread safe, as my own experience seems to confirm.
In libwebsockets.c:line2483, I read that "The protocol callback functions are [...] called periodically to allow async transmission." This is exactly what I want but I haven't observed this happening in my own code and haven't found any way to "turn it on".
Suggestions on how to write asynchronously to the websocket I am serving?
Code for libwebsocket: http://git.warmcat.com/cgi-bin/cgit/libwebsockets/
Example of use: http://martinsikora.com/libwebsockets-simple-websocket-server
I haven't found a super clean way of doing that. What I would suggest is to register a callback on the event that server can write to the client and then check if there's asynchronous work to send there. the LWS_CALLBACK_SERVER_WRITEABLE event is just that, and if you call libwebsocket_callback_on_writable(context, wsi); from within your callback it'll be periodically called.
So, something like this:
static int callback_myprotocol(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
SendState *ss = (SendState*)user;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
printf("connection established\n");
// get the ball rolling
libwebsocket_callback_on_writable(context, wsi);
break;
case LWS_CALLBACK_SERVER_WRITEABLE: {
if (!work_to_be_done) {
// schedule ourselves to run next tick anyway
libwebsocket_callback_on_writable(context, wsi);
return 0;
}
// send our asynchronous message
libwebsocket_write(wsi, buf, size, flag);
// and schedule ourselves again
libwebsocket_callback_on_writable(context, wsi);
break;
}
default:
break;
}
return 0;
}
I adapted this from the test-fraggle.c example; the above is roughly what that example does to send messages in smaller chunks.

Resources