
lowentry.ue4.classes.http.HttpClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java Show documentation
Show all versions of java Show documentation
A Java library for the Low Entry UE4 plugins.
package lowentry.ue4.classes.http;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import lowentry.ue4.classes.internal.CachedTime;
import lowentry.ue4.library.LowEntry;
public class HttpClient
{
public static final long TIMEOUT_SECONDS = 30;
public static final long TIMEOUT_NANOS = TIMEOUT_SECONDS * 1000000000;
public static final long MAX_CONTENT_LENGTH = 20 * 1024;
public static final int DEFAULT_SO_TIMEOUT = 100;
protected final HttpServer server;
protected final Socket client;
protected final BufferedInputStream input;
protected final BufferedOutputStream output;
protected final long creationTime = CachedTime.nanoTime();
protected ByteArrayOutputStream headerBytes = new ByteArrayOutputStream();
protected byte headerBytesStage = 0;
protected ByteArrayOutputStream contentBytes = null;
protected int contentBytesRemaining = 0;
protected HttpRequest request;
protected int currentSoTimeout;
public HttpClient(HttpServer server, Socket client) throws Throwable
{
this.server = server;
this.client = client;
this.request = new HttpRequest(server.secure);
this.input = new BufferedInputStream(client.getInputStream());
this.output = new BufferedOutputStream(client.getOutputStream());
currentSoTimeout = client.getSoTimeout();
setSoTimeout(DEFAULT_SO_TIMEOUT);
}
/**
* Executes pending tasks.
*
* WARNING: Only call this on the same thread this object was created in!
*/
protected void listen(long time) throws Throwable
{
if((time - creationTime) >= TIMEOUT_NANOS)
{
disconnect();
return;
}
if(request == null)
{
if(input.read() < 0)
{
disconnect();
}
return;
}
{// receive bytes >>
if(server.secure)
{
setSoTimeout(1);
try
{
read(1);
}
catch(Throwable e)
{
// no data available
return;
}
}
int available = input.available();
if(available <= 0)
{
return;
}
if(server.secure)
{
setSoTimeout(DEFAULT_SO_TIMEOUT);
}
read(available);
}// receive bytes <<
}
/**
* Sets the SO_TIMEOUT.
*/
protected void setSoTimeout(int timeout) throws Throwable
{
if(currentSoTimeout == timeout)
{
return;
}
client.setSoTimeout(timeout);
currentSoTimeout = timeout;
}
/**
* Tries to read from the socket.
*/
protected void read(int max) throws Throwable
{
ByteBuffer buffer = server.networkBuffer;
buffer.clear();
int size = input.read(buffer.array(), 0, Math.min(max, buffer.remaining()));
if(size <= 0)
{
if(size < 0)
{
disconnect();
}
return;
}
buffer.limit(size);
receivedData(buffer);
}
/**
* Process the received data.
*/
protected void receivedData(final ByteBuffer data) throws Throwable
{
if(request == null)
{
return;
}
if(headerBytes != null)
{
while(data.hasRemaining())
{
{// wait for header end >>
byte b = data.get();
headerBytes.write(b);
if(headerBytes.size() > 8192) // 8 KB
{
// handshake packet too big
disconnect();
return;
}
if(headerBytesStage == 0)
{
if(b == 13) // \r
{
headerBytesStage++;
continue;
}
else
{
continue;
}
}
if(headerBytesStage == 1)
{
if(b == 10) // \n
{
headerBytesStage++;
continue;
}
else
{
headerBytesStage = 0;
continue;
}
}
if(headerBytesStage == 2)
{
if(b == 13) // \r
{
headerBytesStage++;
continue;
}
else
{
headerBytesStage = 0;
continue;
}
}
if(headerBytesStage == 3)
{
if(b == 10) // \n
{
// done
headerBytesStage = 0;
}
else
{
headerBytesStage = 0;
continue;
}
}
}// wait for header end <<
String header = LowEntry.bytesToStringLatin1(headerBytes.toByteArray()).trim();
contentBytes = headerBytes;
contentBytes.reset();
headerBytes = null;
{// parse header >>
boolean first = true;
for(String line : header.split("\r\n"))
{
if(first)
{
String[] meta = line.split(" ", 3);
if(meta.length != 3)
{
disconnect();
return;
}
request.internal_setMethod(meta[0]);
request.internal_setPath(meta[1]);
first = false;
continue;
}
String[] headerparts = line.split(":", 2);
request.internal_setHeader(headerparts[0], ((headerparts.length == 2) ? headerparts[1] : ""));
}
}// parse header <<
contentBytesRemaining = request.getContentLength();
if(contentBytesRemaining > MAX_CONTENT_LENGTH)
{
disconnect();
return;
}
break;
}
if(headerBytes != null)
{
return;
}
}
if(contentBytesRemaining > 0)
{
while(data.hasRemaining())
{
byte b = data.get();
contentBytes.write(b);
contentBytesRemaining--;
if(contentBytesRemaining <= 0)
{
byte[] content = contentBytes.toByteArray();
contentBytes = null;
request.internal_setContent(content);
break;
}
}
if(contentBytesRemaining > 0)
{
return;
}
}
request.internal_setRequest();
server.internal_listenerReceivedRequest(this, request, new HttpResponse(this, request));
request = null;
}
/**
* Sends the given bytes.
*/
public void send(byte[] bytes)
{
if((bytes == null) || (bytes.length <= 0))
{
return;
}
try
{
output.write(bytes, 0, bytes.length);
}
catch(Exception e)
{
}
try
{
output.flush();
}
catch(Exception e)
{
}
}
/**
* Returns the local socket address (host and port), can return null.
*/
public InetSocketAddress getLocalAddress()
{
return (InetSocketAddress) client.getLocalSocketAddress();
}
/**
* Returns the remote socket address (host and port), can return null.
*/
public InetSocketAddress getRemoteAddress()
{
return (InetSocketAddress) client.getRemoteSocketAddress();
}
/**
* Returns the IP, can return null.
*/
public InetAddress getIp()
{
return client.getInetAddress();
}
/**
* Returns the IP as a String, can return null.
*/
public String getIpString()
{
InetAddress ip = getIp();
if(ip == null)
{
return null;
}
return ip.getHostAddress();
}
/**
* Disconnects the client.
*/
public void disconnect()
{
internal_disconnect();
server.internal_removeClient(this);
}
/**
* Returns true if the client is still connected.
*/
public boolean isConnected()
{
return (client.isConnected() && !client.isClosed());
}
/**
* Disconnects the client (without removing the client from the server client list).
*/
protected void internal_disconnect()
{
try
{
output.flush();
}
catch(Exception e)
{
}
try
{
client.close();
}
catch(Exception e)
{
}
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + getAddressText() + "]";
}
private final String getAddressText()
{
if(!isConnected())
{
return "closed";
}
InetSocketAddress sockaddr = this.getRemoteAddress();
if(sockaddr == null)
{
return "connecting";
}
InetAddress inetaddr = sockaddr.getAddress();
return inetaddr.getHostAddress() + "@" + sockaddr.getPort();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy