Processing - BufferedOutputStream exception - java

I'm a stranger to Java, but I'm developing an app with Processing, and I need enlightenment, please.
I'm running a php server on 127.0.0.1:8080 on the root of the .pde below. all my php scripts are bug free, as well as the rest of the Processing code.
after careful analysis, I've learned that the bug is in the function below.
what is the raised exception down under telling me? and how can I fix the code?
//(cont)
void postPicture(){
//load the saved image into an array of bytes
byte[] thisFile=loadBytes(fileName);
//open a new connection to the server
thisClient = new Client(this, "localhost", 80);
//make an HTTP POST request:
thisClient.write("POST " + pictureScriptUrl + " HTTP/1.1\n");
thisClient.write("Host: localhost\n");
//tell the server you're sending the POST in multiple parts
//and send a unique string that will delineate the parts
thisClient.write("Content-Type: multipart/form-data; boundary=");
thisClient.write(boundary + "\n");
//form the beginning of the request
String requestHead ="--" + boundary + "\n";
requestHead +="Content-Disposition: form-data; name=\"file\"; ";
requestHead += "filename=\"" + fileName + "\"\n";
requestHead +="Content-Type: image/jpeg\n\n";
//form the end of the request
String tail="\n\n--" + boundary + "--\n";
//calculate and send the length of the total request
//including the head of the request, the file, and the tail
int contentLength = requestHead.length() + thisFile.length + tail.length();
thisClient.write("Content-Length: " + contentLength + "\n\n");
//send the header of the request, the file and the tail
thisClient.write(requestHead);
thisClient.write(thisFile);
thisClient.write(tail);
}
java.lang.NullPointerException
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at javax.imageio.stream.FileCacheImageOutputStream.close(FileCacheImageOutputStream.java:238)
at com.sun.imageio.stream.StreamCloser$CloseAction.performAction(StreamCloser.java:130)
at com.sun.imageio.stream.StreamCloser$1.run(StreamCloser.java:74)
at java.lang.Thread.run(Thread.java:745)

Related

java http server response

I'm building a java server which have to handle http requests. I'm trying to handle a GET request and it works partially fine. In the specific case I want to discuss here I want to respond with a Json. This is what i'm doing:
private Socket socket;
OutputStream outputStream = socket.getOutputStream();
String json = gson.toJson(conversazione);
String response =
"HTTP/1.1 200 OK" + CRLF +
"Content-Length: " + (json.getBytes().length)+ CRLF +
"Content-Type: application/json;charset=UTF-8" + CRLF +
"Server: Federico's Java Server" + CRLF +
"Date: " + new Date() + CRLF + CRLF +
json + CRLF + CRLF;
outputStream.write(response.getBytes());
It works, i mean the client receive the status 200 OK but it receive a text instead of the Json. I'm doing a request with Postman and this is what it receive as response:
Are you sure CRLF = "\r\n"? It looks inverted.
"\n\r" might be interpreted as two lines (Unix+MacOS), hence the HTTP header ends after the first line.
Also better call .getBytes(StandardCharsets.UT8).
I think the issue you have is that you are sending the HTTP Headers and the body together, they need to be separate.
A found this article after a quick search which demonstrates this. From the code sample in that article (slightly adjusted to use the values in your sample):
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedOutputStream dataOut = new BufferedOutputStream(connect.getOutputStream());
String content = "application/json;charset=UTF-8";
byte[] fileData = json.getBytes();
int fileLength = (int) file.length();
// send HTTP Headers
out.println("HTTP/1.1 200 OK");
out.println("Server: Federico's Java Server");
out.println("Date: " + new Date());
out.println("Content-type: " + content);
out.println("Content-length: " + fileLength);
out.println(); // blank line between headers and content, very important !
out.flush(); // flush character output stream buffer
dataOut.write(fileData, 0, fileLength);
dataOut.flush();
I encourage to go check that article out. My sample above was written manually and my not work as expected.

How can I support my backend multiple range request while downloading video from aws s3?

I have to perform a request to my backend from a client to download video preview and those are in s3 server. The request fetch the video from s3 and send back to client. For large video file it took much time. So I need to perform range request. Single range request works well and send me exact bytes of data. But when I add multiple range request it does not send that chunked data. Is there a process to do that?
Single range request works well and send me exact bytes of data. But when I add multiple range request it does not send that chunked data. Is there a process to do that?
NB: S3 doesn't support multiple range request. So I am sending request to s3 with only one range and getting that stream of bytes and sending that to client. But it only sending first byte range.
public multiPartRangeRequest() {
val boundaryString = MimeTypeUtils.generateMultipartBoundaryString();
response.setContentType("multipart/byteranges; boundary=" + boundaryString);
val out = response.getOutputStream();
for (val range : ranges) {
val length = objectMeta.getContentLength();
val start = range.getRangeStart(length);
val end = range.getRangeEnd(length);
val rangeLength = end - start + 1;
val inputStreamFromS3 = s3Manager.getObject(fileId, fileType, length, range)
.getObjectContent();
out.println();
out.println("--" + boundaryString);
response.setHeader(CONTENT_LENGTH, String.valueOf(rangeLength));
response.setHeader(CONTENT_RANGE, "bytes " + start + "-" + end + "/" + length);
IOUtils.copy(inputStreamFromS3, response.getOutputStream());
out.println(CONTENT_RANGE + ": bytes " + start + "-" + end + "/" + length);
out.println(CONTENT_LENGTH + ": " + rangeLength);
}
}

Android VpnService forward packets

I want to use android's VpnService to capture packets filter them based off IP address. I can get the packets from the "tun" interface just fine but after that i'm not sure how to forward them to their original destination. Based off of the comments from this answer it seems like i just need to:
Create a new socket to the destination IP address and port
Trim the IP and TCP header to send only the data
Re-attach the IP and TCP header when i get a response
Send the complete packet to the output stream
I have tried to send the data like this:
Socket socket = new Socket();
socket.bind(new InetSocketAddress(0));
if (protect(socket)){
Log.e(TAG, "Socket protected");
}else{
Log.e(TAG, "Socket NOT protected");
}
socket.connect(new InetSocketAddress(ipPacket.getDestinationIp(), ipPacket.getDstPort()));
Log.e(TAG, "Socket connected: " + socket.isConnected());
socket.getOutputStream().write(getTCPHeader(getIpHeader(packet)[1])[1].array());
The methods getTCPHeader(ByteArray packet) and getIpHeader(ByteArray packet) simply splits the packet into two ByteArray's as follows:
private ByteBuffer[] getIpHeader(ByteBuffer packet){
packet.position(0);
ByteBuffer ipHeader = ByteBuffer.allocate(20);
ByteBuffer data = ByteBuffer.allocate(packet.limit() - 20);
packet.get(ipHeader.array(), 0, 20);
packet.get(data.array(), 0, packet.limit() - 20);
return new ByteBuffer[]{ipHeader, data};
}
private ByteBuffer[] getTCPHeader(ByteBuffer packet){
packet.position(20);
ByteBuffer tcpHeader = ByteBuffer.allocate(20);
ByteBuffer data = ByteBuffer.allocate(packet.limit() - 20);
packet.get(tcpHeader.array(), 0, 20);
packet.get(data.array(), 0, packet.limit() - 40);
return new ByteBuffer[]{tcpHeader, data};
}
Now to get a response from the server, i am using the following code:
ByteBuffer responsePacket = ByteBuffer.allocate(65535);
InputStream socketInputStream = socket.getInputStream();
try{
int responseLength = socketInputStream.read(responsePacket.array());
if (responseLength > 20){
Log.e(TAG, "===Server Response===");
Log.e(TAG, "Length: " + responseLength);
ByteBuffer trimmedResponseData = ByteBuffer.allocate(responseLength);
System.arraycopy(responseData.array(), 0, trimmedResponseData.array(), 0, responseLength);
String resp = "";
for (int i = 0; i < responseLength; i++){
resp += String.valueOf(responseData.get(i) + " ");
}
Log.e(TAG, "Response data: " + resp);
ByteBuffer finalPacket = ByteBuffer.allocate(40 + responseLength);
ByteBuffer swappedIpHeader = swapSrcDstAddress(getIpHeader(packet)[0]);
ByteBuffer swappedTcpHeader = swapTCPSrcDst(getTCPHeader(getIpHeader(packet)[1])[0]);
finalPacket.put(swappedIpHeader.array());
finalPacket.put(swappedTcpHeader.array());
finalPacket.put(serverResponseData.array());
Packet finPack = debugPacket(finalPacket);
Log.e("VPN", "Final packet --> Packet size: " + finPack.getTotalLength() + " from " + finPack.getSourceIp() + " src port: " + finPack.getSrcPort() + " going to " + finPack.getDestinationIp() + " dst port: " + finPack.getDstPort());
out.write(finalPacket.array());
}
}catch (Exception e){
//Log.e(TAG, "EXCEPTION: " + e);
e.printStackTrace();
}
This code seems to work either EXTREMELY slowly, or not at all. Sometimes if i go to www.google.com it will load slowly but most of the time it doesn't. Also some times i am getting the following error on the line int responseLength = socketInputStream.read(serverResponse.array());
java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
What is causing this error, and how can i properly forward these packets to the appropriate destination? Any help is greatly appreciated!
What is causing this error?
recvfrom failed exception means that Server has closed the client socket but client was still reading input data (in your case serverResponse.array(). For details, see this.
how can i properly forward these packets to the appropriate
destination?
There is a sample-code from google-sources here that forwards available packets. Please go through the code and the relevant comments. According to google-sources:
This application consists of an Android client and a sample
implementation of a server. It performs IP over UDP and is capable of
doing seamless handover between different networks as long as it
receives the same VPN parameters.It shows how to build a VPN client
using the VpnService class introduced in API level 14.
The sample code of the server-side implementation is Linux-specific
and is available in the server directory. To run the server or port
it to another platform, please see comments in the code for the
details.
one more helpful app link here

Http Client hanging for some reason

Working on a HTTP client program using Netbeans.
So far I have gotten to here in my HttpClient class:
public class MyHttpClient {
MyHttpRequest request;
String host;
public MyHttpResponse execute(MyHttpRequest request) throws IOException {
//Creating the response object
MyHttpResponse response = new MyHttpResponse();
//Get web server host and port from request.
String host = request.getHost();
int port = request.getPort();
//Check 1: HOST AND PORT NAME CORRECT!
System.out.println("host: " + host + " port: " + String.valueOf(port));
//Get resource path on web server from requests.
String path = request.getPath();
//Check 2: ENSURE PATH IS CORRECT!
System.out.println("path: " + path);
//Open connection to the web server
Socket s = new Socket(host, port);
//Get Socket input stream and wrap it in Buffered Reader so it can be read line by line.
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
//Get Socket output stream and wrap it in a DataOutputStream so it can be written to line by line.
DataOutputStream outToServer = new DataOutputStream(s.getOutputStream());
//Get request method
String method = request.getMethod();
//Check 3: ENSURE REQUEST IS CORRECT GET/POST!
System.out.println("Method: " + method);
//GET REQUEST
if(method.equalsIgnoreCase("GET")){
//Send request to server
outToServer.writeChars("GET " + path + " HTTP/1.0");
//HTTP RESPONSE
System.out.println("WAITING FOR RESPONSE!");
String line = inFromServer.readLine();
System.out.println("Line: " + line);
}
//Returning the response
return response;
}
}
I have checked to ensure my request line is constructed correctly, as seen in the print statements throughout. However when I get to this line the program hangs:
System.out.println("WAITING FOR RESPONSE!");
String line = inFromServer.readLine();
I have no idea why... My server is localhost WAMP. It is up and running correctly. I have the file I am requesting stored on the localhost. I can access it through browser.
Any ideas what might be going wrong??
No CR or LF is one of your problems. You should be writing ASCII characters and may be a Host header.
outToServer.write(("GET " + path + " HTTP/1.0\r\n").getBytes("ASCII"));
outToServer.write("Host: myhost.com\r\n\r\n".getBytes("ASCII"));
outToServer.flush();

Java constructing an http request message

I asked a similar question in another thread but I think I'm just having trouble getting the syntax right at this point. I basically want to open a socket in Java, send a HTTP request message to get the header fields of a specific web page. My program looks like this so far:
String server = "www.w3.org";
int port = 80;
String uri = "/Protocols/rfc2616/rfc2616-sec5.html#sec5.1"
Socket socket = new Socket(server, port);
PrintStream output = new PrintStream(socket.getOutputStream());
BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.println("HEAD " + uri + " HTTP/1.1");
//String response = "";
String line = "";
while((line = socketInput.readLine()) != null){
System.out.println(line);
}
socketInput.close();
socket.close();
It doesn't really work. Or it doesn't work for all websites. If someone could just tell me the immediate problems with what I'm doing, that would be great. Thank you!
Change
output.println("HEAD " + uri + " HTTP/1.1");
to
output.println("HEAD " + uri + " HTTP/1.1");
output.println("Host: " + server);
output.println();
You have to send the Host header because usually there are more than one virtual host on one IP address. If you use HTTP/1.0 it works without the Host header.
I would use some higher-level component, like HttpURLConnection (see here) or apache http components.

Categories