package com.alecgorge.minecraft.jsonapi;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import com.alecgorge.minecraft.jsonapi.streams.StreamingResponse;
public class JSONSocketServer implements Runnable{
protected int serverPort = 20060;
protected ServerSocket serverSocket = null;
protected JSONServer jsonServer = null;
protected boolean isStopped = true;
protected Thread runningThread = null;
public JSONSocketServer(int port, JSONServer jsonServer){
this.serverPort = port;
this.jsonServer = jsonServer;
start();
}
public void run(){
synchronized(this){
this.runningThread = Thread.currentThread();
isStopped = false;
}
try {
if(JSONAPI.instance.bindAddress != null) {
this.serverSocket = new ServerSocket(this.serverPort, -1, JSONAPI.instance.bindAddress);
}
else {
this.serverSocket = new ServerSocket(this.serverPort);
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
while(!isStopped()){
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
clientSocket.setTcpNoDelay(true);
} catch (IOException e) {
if(isStopped()) {
return;
}
e.printStackTrace();
}
new Thread(
new WorkerRunnable(clientSocket)
).start();
}
}
}
private synchronized boolean isStopped() {
return this.isStopped;
}
public synchronized void stop(){
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void start(){
(new Thread(this)).start();
}
public class WorkerRunnable implements Runnable{
protected Socket clientSocket = null;
protected String serverText = null;
public WorkerRunnable(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
try {
String line2 = "";
final BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
final DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream());
while((line2 = input.readLine()) != null) {
// format method=xyz&args=[]&username=user&password=pass
String[] split = line2.split("\\?", 2);
NanoHTTPD.Response r = null;
if(split.length < 2) {
r = jsonServer.new Response( NanoHTTPD.HTTP_NOTFOUND, NanoHTTPD.MIME_JSON, jsonServer.returnAPIError("", "Incorrect. Socket requests are in the format PAGE?ARGUMENTS. For example, /api/subscribe?source=....").toJSONString());
}
else {
Properties header = new Properties();
NanoHTTPD.decodeParms(split[1], header);
Properties p = new Properties();
p.put("X-REMOTE-ADDR", clientSocket.getInetAddress().getHostAddress());
r = jsonServer.serve(split[0], "GET", p, header);
}
if(r.data instanceof StreamingResponse) {
final StreamingResponse s = (StreamingResponse)r.data;
(new Thread(new Runnable() {
@Override
public void run() {
String line = "";
boolean continueSending = true;
while((line = s.nextLine()) != null && continueSending) {
try {
if(clientSocket.isConnected() && !clientSocket.isClosed()) {
output.write((line.trim()+"\r\n").getBytes("UTF-8"));
}
else {
continueSending = false;
}
} catch (IOException e) {
//e.printStackTrace();
continueSending = false;
try {
clientSocket.close();
output.close();
input.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
})).start();
}
else {
BufferedReader data;
if(r.data != null)
data = new BufferedReader(new InputStreamReader(r.data));
else
data = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(r.bytes)));
try {
String line = "";
while((line = data.readLine()) != null) {
output.write((line+"\r\n").getBytes("UTF-8"));
// fuck java: output.writeUTF(line+"\r\n");
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
output.close();
input.close();
} catch (IOException e) {
try {
clientSocket.close();
} catch (IOException e1) {
}
//e.printStackTrace();
}
}
}
}