Problem
I'm developing a remote app to control software on remote machine through sockets.
Between my app and the softwares there is a sort of router/reverse proxy (software) to pass my commands to the desired software.
Unfortunately, for now, this router doesn't support chunked requests, ie all the command must be received in the same TCP packet else it interprets it as two separates ones.
On some devices all goes well. But some others the command is separated in two separates packets and doesn't be interpreted correctly by the router.
I want to prevent request chunking. Is this possible (Android side)?
Technical details
Java code
In my app I'm using a Socket and a DataOutputStream to send commands, like this:
socket = new Socket(ip, port);
out = new DataOutputStream(socket.getOutputStream());
The protocole to communicate with the router is a little bit weird but I need to send an HTTP header first (for a sort of authentication) waiting for an OK from server and then send my commands (without header this time)
I'm doing this like this:
# Sending header
out.writeBytes("SOURCE content HTTP/1.0\n" +
"Content-type: type\n" +
"Authorization: Basic\n" +
"Nom: rouge\n\n");
# Getting server answer
String answer;
int charsRead;
char[] buffer = new char[256];
charsRead = in.read(buffer);
answer = new String(buffer).substring(0, charsRead);
# ... A little bit of computation of the answer to know if it's OK
# Sending my command to server
out.writeBytes("0 rouge violet getNext 1");
# Same as above to get and compute response
Devices used to test
"Chunking" device : LG Nexus 5X - Android 7.1.2 - API 25
"Non chunking" device : Kesa TM708 ($60 cheap tablet) - Android 5.1.1 - API 22
It's exactly the same code on this two devices
Wireshark captures
Here the two requests sent:
Here the chunked capture file (pcap)
Here the not chunked capture file (pcap)
Thank you :)
Related
The code below works to two other sites I've tried, but will not work with my domain hosted by 1and1. The return code is always 500 - Permanent Negative Completion reply.
I know I'm connecting because FTPReply.isPositiveCompletion(reply) returns true. I tried it with both reading file off phone storage and sending it from a byte array populated early in the code. This is the byte array. Both return 500. Both work on the other sites.
If I don't use enterLocalPassiveMode() the code stops executing on the storeFile call. No exception, no socket time-out. It just ends there and the async task will not call again in that session. The code does not do that on the other sites.
I've tried both ASCII and BINARY file types. Both return 500. 1and1 site says to use my domain and port 21. I can connect with CoreFTP and read and write using both of the accounts I've set up.
I also tired ftp4j and had the same response with all scenarios so went back to Apache because the code was already written with robust error trapping.
I've tried both mydomain.com and ftp.mydomian.com. 500 on both. I also tried the dot quad I can see in the CoreFTP window, but i get "cannot resolve host name" with the Apache Java code. Maybe not a static IP?
This is what CoreFTP does. It connects on port 21 and then goes in to passive mode and an ASCII data connection.
It's a long shot, but has anyone else ever FTPed to their 1and1 domain using Java in Android Studio?
Greg
Resolving mydomain.com...
Connect socket #5684 to xx.xx.xx.xxx, port 21...
220 Microsoft FTP Service
USER ftp79815757-0
331 Password required for ftp79815757-0.
PASS **********
230 User logged in.
SYST
215 Windows_NT
Keep alive off...
PWD
257 "/ftp79815757-0" is current directory.
PASV
227 Entering Passive Mode (xx,xxx,xx,xxx,xxx,xxx).
LIST
Connect socket #5700 to xx.xx.xx.xx, port 62894...
150 Opening ASCII mode data connection.
226 Transfer complete.
Transferred 51 bytes in 0.094 seconds
FTPClient mFtpClient = new FTPClient();
String ip = "my domain dot com";
String userName = "ftp79815757-0";
String pass = "password";
mFtpClient.connect(InetAddress.getByName(ip));
mFtpClient.login(userName, pass);
int reply = mFtpClient.getReplyCode();
if (FTPReply.isPositiveCompletion(reply)) {
mFtpClient.setFileType(FTP.BINARY_FILE_TYPE);
//one thread said this would do the trick
mFtpClient.enterLocalPassiveMode();
mFtpClient.enterRemotePassiveMode();
InputStream stream = new ByteArrayInputStream(imageData);
//I have two accounts. One points to images_in
/*if (!mFtpClient.changeWorkingDirectory("images_in")) {
Log.e("ChangeDir", String.valueOf(mFtpClient.getReplyCode()));
}*/
if (!mFtpClient.storeFile("remoteName.jpg", stream)) {
Log.e("FTPUpload", String.valueOf(mFtpClient.getReplyCode()));
}
stream.close();
mFtpClient.disconnect();
}
Finally got it. The main problem was that I was using an old version of the Apache library. The Jar I was using was commons-net-1.4.jar. Someone in another thread pointed me to commons-net-3.3.jar.
I commented out both mFtpClient.enterLocalPassiveMode() and mFtpClient.enterRemotePassiveMode(), and with some trail and error it worked with FTP.BINARY_FILE_TYPE and not ASCII_FILE_TYPE. ASCII got the file there, but it was garbage.
Some background:
I'm part of a team that's developing an Android game for a college course.
I am the person in charge of networking, and my aim is to have a game running in "client mode" submit input to a game running in "host mode". The host will then do all physics/collisions etc, and send back the updated state of the game.
I'm confident that I can compress the state of the game enough that sending the whole state of it will work fine (graphics will be done client-side).
I'm aiming have this game work on a wireless LAN, using IPv4 addresses that I get from
NetworkInterface.getNetworkInterfaces().
All activity code and user input is handled outside of my code, so I'm basically working with Java sockets.
Question:
My code below should send a single packet of a single data byte to the host, telling it that there's client who wants to connect. However, I've used Wireshark to trace all packet activity for about 80 seconds after I run this code, and all I can see is
11 2.825742000 MurataMa_41:d5:ed Broadcast ARP 42 Who has 192.168.0.25? Tell 192.168.0.24
That is, an unanswered ARP request. I've tried multiple ports, in case that was the problem, but I'm currently using 5000.
int hostPort = 5000;
hostSocket = new DatagramSocket(hostPort);
byte [] buffer = new byte[1];
buffer[0] = 'h';
DatagramPacket hello = new DatagramPacket(buffer, buffer.length, hostAddress, hostPort);
hostSocket.send(hello);
So, how can I get the host Android device to respond to ARP requests? I have an Android 2.2 phone sending the requests, and a Nexus 7 running Android 4.2.2, which should be receiving them.
EDIT
I've checked LogCat output for any/all exceptions when sending. There are none.
I'm trying to make a port of a chat program a friend of mine made with lacewing and multimedia fusion 2 for android device.
I've managed to create a socket connecting to the listening socket of the server successfully, but I cannot seem to be able to send data to login and enter the chat. The login for now just requires a name, but even if I send a String of data, the server doesn't seem to reply or accept that data to get me over the channel.
I know I could easily port this with other way like using the NDK of the multimedia fusion 2 exporter, but I just want to figure out how this works
PS: I'm using Java and libgdx for the development
You need to read the liblacewing relay protocol:
https://github.com/udp/lacewing/blob/0.2.x/relay/current_spec.txt
On initial connection, you have to send byte 0 to identify that you are not an HTTP client. After this, you can exchange normal protocol messages.
The first message you need to send is the connection request (which may be denied by the server with a deny message). This would be:
byte 0 (2.1.0 request)
(1.2 size)
byte 0 (2.1.0.0 connection request)
string "revision 3" (2.1.0.0 connection request -> version)
When the server responds with response 0 (2.2.0.0 Connect), you then have to set a name before you may join any channels. This is done with message 2.1.0.1 SetName, which is the same structure as above but instead of 2.1.0.0's byte 0, it is 2.1.0.1's byte 1, followed by the name as a string instead of the protocol version.
The server should then respond with 2.2.0.1 SetName, assuming it accepted your name change request. You should process this message in case the server gave you a different name than you requested. Finally, once you have a name, you can join a channel with 2.1.0.2 JoinChannel. The flags you specify here will be used if the channel doesn't exist yet (e.g. nobody is in the chat yet) - these should match the ones in the MMF2 project file. The name should also match.
After all that, you're still not done! You have to process more messages, etc. it's almost like writing the RelayClient class yourself. It's a tough task, but with the protocol specification in hand you should be able to work it all out.
I'm trying to write a WebSocket Server in both, java and C++ but I'm stuck right now.
Using java and java.net.ServerSocket/java.net.Socket I managed to get a connection and succesfully do the handshake but the data sent by the WebSocket to the Java Server is not quite what I expected.
When sending messages from javascript like this:
var count = 0;
function loop(){
websocket.send("loop: " + count + "\n");
count++;
setTimeout(loop, 100);
}
The Java server receives this, with line feeds every now and then but not for every websocket.send() that has been invoked.
?‡½÷"˜Ñ˜Mè‡×?‡AÎ3-¡C{îN?‡ŒÍ[Uà¢4%¶íi?‡$ÍåøH¢ŠˆíÖ?‡·†ÞžÛé±î?¦ê?‡'½Ø…KÒ·õ?í?‡dÒÛ‘½´á^òí?‡+ù?YG–â)Ùº?‡›?
Ë÷àb»¡¯5?‡mÉŒQ¦ã!Wéµ?ˆ:J FV%f6
The Java server retrieves values from the socket using BufferedReader.readLine()
BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line =socketReader.readLine();
This works fine for the handshake and all handshake data is readable but it does not work after the handshake is done.
Is the data after the handshake somehow encrypted? How can I read it?
EDIT :
The program files:
SocketConnectTest.html
ServerTest.java
ClientSessionTest.java
ResponseGenerator.java
output
Just run ServerTest.java and then open SocketConnectTest.html.
ClientSessionTest.initClientListener() handles the messages from the client.
SOLUTION :
For the solution see pimvdbs post below and his answer at How to (de)construct data frames in WebSockets hybi 08+?
The data coming across web sockets is raw, not string encoded data.
I'd suggest not wrapping a BufferedReader around the incoming data as packets are framed with 0x00 bytes. The crazy characters you are seeing are a result of Java not understanding the encoding that the data is in.
You will need to be responsible for splitting up the data into character and control parts. Once you've split the data up into the appropriate areas, then you can decode the data as a string.
I'm currently developing an IDS/IPS that uses NetFlow data to draw assumptions whether there is an ongoing attack. I didn't afford an expensive CISCO router so I bought a LINKSYS router on which I installed DD-WRT. DD-WRT sends netflow v5 packets to your preferred machine so it's like having a CISCO router but older. Basically you get a $200-$500 router for $80 and a little tweaking.
I've set up the router, I'm getting the packets, I even used the DD-WRT provided tool for capturing rFlow (they named it like that but it's netflow v5) and everything works.
My application will have to do everything internally so that means i need to capture rflow packets, read them and draw the assumptions based on my readings.
I started developing in JAVA and set up a UDP daemon to listen on 2055 (port for receiving rflow packets). All good, i'm getting the packets but when i try to view the content i get some weird characters, like I'm dumping stuff from memory.
Here's my code for setting up the deamon and reading data.
try {
serverSocket = new DatagramSocket(2055);
while (true) {
DatagramPacket receivedPacket = new DatagramPacket(received, received.length);
serverSocket.receive(receivedPacket);
ByteArrayInputStream byteIn = new ByteArrayInputStream(receivedPacket.getData(),0,receivedPacket.getLength());
DataInputStream in = new DataInputStream(byteIn);
String input = "";
while( (input = in.readLine()) != null) {
System.out.println(input + "\n");
}
Inet4Address from = (Inet4Address) receivedPacket.getAddress();
System.out.println("FROM: " + from + "\nDATA: " + data[4]);
}
} catch (SocketException ex) {
System.out.println(ex.getMessage());
}
I have found a library called jflow..but there is no source code so i'm pretty skeptical on using it. I was wondering if somebody can tell me how can i actually read the content of the packets being sent to me. Since i'm at an early stage of development I am not bound to use JAVA, i could go for C++. My biggest problem, no matter the programming language is how to read the content of those packets so that I can draw the correct conclusions that i need for my other modules.
The rFlow / NetFlow v5 packets are a binary packet layout, so viewed as text they will appear, well, unreadable.
The packet format for the v5 packets is known, and can be found with a google search. This seems a good reference.
Note that the rFlow daemon on the dd-wrt has a long standing bug where it does not fill in the input or output interface fields correctly.