How to properly parse a tcp packet in java? - java

I currently have a simple TCP server, which calls a function and passes it the binary TCP payload in the form of a byte array on every new incoming packet, what is the proper way to parse it?
I tried doing it by just slicing it into different byte arrays and processing them separately, but my packets include a variable-length datatype, which I am unable to split from the other data. It really seems like it's not what I should do and I think there is a better way to do it
readVarInt() is a function that parses the variable-length datatype and returns the result and the length of the unparsed datatype in an int[] array
PacketHeader is a class that that has size, id and body fields, id and size are already parsed and the body field contains everything else after the size and id bytes
int[] parsedProtocolVersion = Main.readVarInt(packetHeader.body);
System.out.println(parsedProtocolVersion[0] + ' ' + parsedProtocolVersion[1]);
int[] parsedServerAddressSize = Main.readVarInt( packetHeader.body.subList(parsedProtocolVersion[1], packetHeader.body.size()));
System.out.println("parsed 1 " + parsedServerAddressSize[1] + " " + parsedServerAddressSize[0]);
String parsedServerAddress = String.valueOf(packetHeader.body.subList(parsedServerAddressSize[1], parsedServerAddressSize[0]));
System.out.println("parsed 2");
int parsedServerPort = Integer.parseUnsignedInt((packetHeader.body.subList(parsedServerAddressSize[1]+parsedProtocolVersion[1], parsedServerAddressSize[1]+parsedProtocolVersion[1]+2).toString()));
System.out.println("parsed 3");
int[] parsedNextState = Main.readVarInt(packetHeader.body.subList(parsedServerAddressSize[1]+parsedProtocolVersion[1]+2, packetHeader.body.size()));
System.out.println("parsed 4");
return String.format("%d %s %d %d",parsedProtocolVersion[0], parsedServerAddress, parsedServerPort, parsedNextState[0]);

Related

Send / Receive MPI-Fortran-Java

I have a send / receive implementation in Open-MPI and Java. The goal is to send a Fortran character set to Java. When Java receives this String it prints the following result.
Result send/receive
My Fortran code is:
program simple4
implicit none
include 'mpif.h'
integer ierr,my_rank,size
integer src, dest, tag, position, charSize
integer status(MPI_STATUS_SIZE)
CHARACTER*80 TEXT
call mpi_init(ierr)
call mpi_comm_rank(MPI_COMM_WORLD,my_rank,ierr)
call mpi_comm_size(MPI_COMM_WORLD,size,ierr)
src = 0
dest = 1
tag = 999
if(my_rank.eq.0) then
position = 0
TEXT = "PRO"
call MPI_SEND(TEXT, 3, MPI_CHARACTER, dest, tag, MPI_COMM_WORLD, ierr)
else
print *, "Fortran process ", my_rank
end if
call mpi_finalize(ierr)
end
My Java code is:
....
char[] textChar = new char[3];
MPI.COMM_WORLD.recv(textChar, 3, MPI.CHAR, sourceRank, messageTag);
String text = String.copyValueOf(textChar);
System.out.println("Java - Text receive: " + text);
What would be the problem in my code?
Fortran and Java will not be able to communicate this way? What would be another solution?
The root cause is a Fortran CHARACTER is in ASCII whereas a Java String is in Unicode, so some extra steps are involved.
Here is a snippet of what you could do in Java
byte[] textByte = new byte[3];
MPI.COMM_WORLD.recv(textByte, 3, MPI.BYTE, sourceRank, messageTag);
String text = new String(textByte, java.nio.charset.Charset.forName("UTF-8"));
System.out.println("Java - Text receive: " + text);

extract values of ping message

I am working on an application on android that performs ping requests (via android shell) and I read from the console the message displayed. A typical message is the following
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=46 time=186 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=46 time=209 ms
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 186.127/197.891/209.656/11.772 ms
I store the above message in a String. I want to extract the values of the time, for example 186 and 209 and also the percentage for loss, 0 (in this case).
I was thinking to go through the string and look the values after "time=". However I don't know how to do it.
How can I manipulate the string I have in order to extract the values?
Start by getting each line of the string:
String[] lines = pingResult.split("\n");
Then, loop and use substring.
for (String line : lines) {
if (!line.contains("time=")) continue;
// Find the index of "time="
int index = line.indexOf("time=");
String time = line.substring(index + "time=".length());
// do what you will
}
If you want to parse to an int, you could additionally do:
int millis = Integer.parseInt(time.replaceAll("[^0-9]", ""));
This will remove all non-digit characters
You can do something similar for the percentage:
for (String line : lines) {
if (!line.contains("%")) continue;
// Find the index of "received, "
int index1 = line.indexOf("received, ");
// Find the index of "%"
int index2 = line.indexOf("%");
String percent = line.substring(index1 + "received, ".length(), index2);
// do what you will
}

How will I be able to printout the captured packets using pcap.loop() with a parameter of Pcap.LOOP_INFINITE into the JTextArea?

I'm quite new to JNetPcap and I'm still finding my way around with it, I'm trying to build a Packet sniffer for my project, Lately I'm trying printout packet information into a JTextArea by appending the information from a pcap.loop() that I am using, but when I set the first parameter using a specific integer value let say 5 the pcap.loop() outputs 5 packets that had been captured, Now what I want is to continuously capture and output the packet until I press the button stop. The syntax below shows the Packet handler.
PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {
public void nextPacket(PcapPacket packet, String user) {
// System.out.printf is included to check if my code works in a non GUI fashion
System.out.printf("Received packet at %s caplen=%-4d len=%-4d %s\n",
new Date(packet.getCaptureHeader().timestampInMillis()),
packet.getCaptureHeader().caplen(), // Length actually captured
packet.getCaptureHeader().wirelen(), // Original length
user // User supplied object
);
Date a = new Date(packet.getCaptureHeader().timestampInMillis());
int b = packet.getCaptureHeader().caplen();
int c = packet.getCaptureHeader().wirelen();
String d = user;
pcktTextArea.append("Received packet at " + a + " caplen=" + Integer.toString(b) + " len=" + Integer.toString(b) + user + "\n" );
pcktTextArea.setForeground(Color.red);
pcktTextArea.setFont(font);
}
};
Now this bit here is my pcktTextArea which I use append to print out the information in the textarea:
pcktTextArea.append("Received packet at " + a + " caplen=" + Integer.toString(b) + " len=" + Integer.toString(b) + user + "\n" );
pcktTextArea.setForeground(Color.red);
pcktTextArea.setFont(font);
And Finally the Pcap.loop which I am having trouble with, if I replace that i with let say 5 it does get printed in the JTextArea but when I put the Pcap.LOOP_INFINTE it only prints the information through console but not in GUI JTextArea:
int i = Pcap.LOOP_INFINITE;
pcap.loop(i , jpacketHandler, " ");
/***************************************************************************
* Last thing to do is close the pcap handle
**************************************************************************/
pcap.close();
Is it because it has to finish the loop before printing the information out in the Textarea?
I assume you run the code in a thread. Use
SwingUtilities.invokeAndWait to call the pcktTextArea.append() code

Receive string from processing to arduino

I want to receive a string from processing to arduino. I am writing a string(Basically an array of single digits in the form of string eg: <0213> is an array: 0 2 1 3). I am able to write it to port but how do I receive it on arduino? Following code is to send to arduino.
int[] send={0,2,3,1};
myPort =new Serial(this,"/dev/ttyACM0", 9600);
String theStg = "<" + nf(send[0], 3) +
" " + nf(send[1], 3) +
" " + nf(send[2], 3) +
" " + nf(send[3], 3) +
">";
myPort.write(theStg);
if you were using a string of char*, rather than the String Class, then you could use avrlibc's strtok() command.
This has been addressed previously(click here)
And here is a nice function you can simply add to your code to do the equivalent of the strtok(), but on a String object.

java reading numbers, interpreting as octal, want interpreted as string

i am having an issue, where java is reading an array list from a YAML file of numbers, or strings, and it is interpreting the numbers as octal if it has a leading 0, and no 8-9 digit.
is there a way to force java to read the yaml field as a string?
code:
ArrayList recordrarray = (ArrayList) sect.get("recordnum");
if (recordrarray != null) {
recno = join (recordrarray, " ");
}
HAVE ALSO TRIED:
Iterator<String> iter = recordrarray.iterator();
if (iter.hasNext()) recno = " " +String.valueOf(iter.next());
System.out.println(" this recnum:" + recno);
while (iter.hasNext()){
recno += ""+String.valueOf(iter.next()));
System.out.println(" done recnum:" + String.valueOf(iter.next()));
}
the input is such:
061456 changes to 25390
061506 changes to 25414
061559 -> FINE
it took a while to figure out what it was doing, and apparently this is a common issue for java,
ideas?
thanks
edit: using jvyaml
yaml:
22:
country_code: ' '
description: ''
insection: 1
recordnum:
- 061264
type: misc
yaml loading:
import org.jvyaml.YAML;
Map structure = new HashMap();
structure = (Map) YAML.load(new FileReader(structurefn)); // load the structure file
Where are you reading the file? The problem lies in where the file contents are being read. Most likeley the recordarray list contains integers, ie. they have alreadey been parsed. Find the place where the records are being read. Maybe you are doing something like this:
int val = Integer.parseInt(record);
Use this instead:
int val = Integer.parseInt(record, 10);

Categories

Resources