First Commit

This commit is contained in:
jeffcheasey88 2023-02-05 21:39:56 +01:00
commit 98533f91ea
11 changed files with 507 additions and 0 deletions

7
.classpath Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="json-simple-1.1.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.settings/
bin/
.project

BIN
json-simple-1.1.1.jar Normal file

Binary file not shown.

View file

@ -0,0 +1,50 @@
package be.jeffcheasey88.peeratcode;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import be.jeffcheasey88.peeratcode.routes.PuzzleList;
import be.jeffcheasey88.peeratcode.webserver.Client;
import be.jeffcheasey88.peeratcode.webserver.HttpReader;
import be.jeffcheasey88.peeratcode.webserver.HttpUtil;
import be.jeffcheasey88.peeratcode.webserver.HttpWriter;
import be.jeffcheasey88.peeratcode.webserver.Response;
import be.jeffcheasey88.peeratcode.webserver.Router;
public class Main {
public static void main(String[] args) throws Exception {
Router router = new Router();
router.setDefault(new Response(){
@Override
public Pattern getPattern(){return null;}
@Override
public void exec(Matcher matcher, HttpReader reader, HttpWriter writer) throws Exception {
HttpUtil.responseHeaders(writer, 404, "Access-Control-Allow-Origin: *");
writer.write("404 not Found.\n");
writer.flush();
writer.close();
}
});
initRoutes(router);
ServerSocket server = new ServerSocket(80);
while(!server.isClosed()){
Socket socket = server.accept();
Client client = new Client(socket, router);
client.start();
}
}
private static void initRoutes(Router router){
router.register(new PuzzleList());
}
}

View file

@ -0,0 +1,31 @@
package be.jeffcheasey88.peeratcode.routes;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.webserver.HttpReader;
import be.jeffcheasey88.peeratcode.webserver.HttpUtil;
import be.jeffcheasey88.peeratcode.webserver.HttpWriter;
import be.jeffcheasey88.peeratcode.webserver.Response;
public class PuzzleList implements Response{
@Override
public void exec(Matcher matcher, HttpReader reader, HttpWriter writer) throws Exception {
HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *");
JSONObject json = new JSONObject();
json.put("Theo", "GL HF");
writer.write(json.toJSONString());
writer.flush();
writer.close();
}
@Override
public Pattern getPattern(){
return Pattern.compile("^\\/puzzle\\/?$");
}
}

View file

@ -0,0 +1,30 @@
package be.jeffcheasey88.peeratcode.webserver;
import java.net.Socket;
import java.util.Arrays;
public class Client extends Thread{
private Socket socket;
private HttpReader reader;
private HttpWriter writer;
private Router router;
public Client(Socket socket, Router router) throws Exception{
this.socket = socket;
this.reader = new HttpReader(socket);
this.writer = new HttpWriter(socket);
this.router = router;
}
@Override
public void run(){
try {
String[] headers = reader.readLine().split("\s");
System.out.println(Arrays.toString(headers));
router.exec(headers[0], headers[1], reader, writer);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,41 @@
package be.jeffcheasey88.peeratcode.webserver;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class HttpReader {
private Socket socket;
private InputStream in;
private BufferedReader reader;
public HttpReader(Socket socket) throws Exception{
this.socket = socket;
this.in = socket.getInputStream();
this.reader = new BufferedReader(new InputStreamReader(in));
}
public boolean isClosed(){
return this.socket.isClosed();
}
public int read(byte[] buffer) throws IOException{
return this.in.read(buffer);
}
public int read(char[] buffer) throws IOException {
return this.reader.read(buffer);
}
public String readLine() throws IOException{
return this.reader.readLine();
}
public boolean ready() throws IOException{
return this.reader.ready();
}
}

View file

@ -0,0 +1,260 @@
package be.jeffcheasey88.peeratcode.webserver;
import java.security.MessageDigest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
import org.json.simple.parser.JSONParser;
public class HttpUtil {
private HttpUtil(){}
public static void responseHeaders(HttpWriter writer, int code, String... headers) throws Exception{
writer.write("HTTP/1.1 "+code+" "+codeMessage(code)+"\n");
for(String header : headers) writer.write(header+"\n");
writer.write("\n");
writer.flush();
}
public static void skipHeaders(HttpReader reader) throws Exception{
String line;
while(((line = reader.readLine()) != null) && (line.length() > 0));
}
public static void switchToWebSocket(HttpReader reader, HttpWriter writer) throws Exception{
String key = readWebSocketKey(reader);
if(key == null) throw new IllegalArgumentException();
writer.write("HTTP/1.1 101 Switching Protocols\n");
writer.write("Connection: Upgrade\n");
writer.write("Upgrade: websocket\n");
writer.write("Sec-WebSocket-Accept: "+
DatatypeConverter.printBase64Binary(
MessageDigest.getInstance("SHA-1").
digest((key+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8")))+"\n");
writer.write("\n");
writer.flush();
}
private static Pattern WEBSOCKET_KEY = Pattern.compile("Sec-WebSocket-Key: (.*)");
public static String readWebSocketKey(HttpReader reader) throws Exception {
String line;
String key = null;
while(((line = reader.readLine()) != null) && (line.length() > 0)){
if(key != null){
continue;
}
Matcher matcher = WEBSOCKET_KEY.matcher(line);
if(matcher.matches()) key = matcher.group(1);
}
return key;
}
private static Pattern AUTORIZATION = Pattern.compile("Autorization: Bearer (.*)");
public static String readAutorization(HttpReader reader) throws Exception {
String line;
String key = null;
while(((line = reader.readLine()) != null) && (line.length() > 0)){
if(key != null) continue;
Matcher matcher = AUTORIZATION.matcher(line);
if(matcher.matches()) key = matcher.group(1);
}
return key;
}
public static Object readJson(HttpReader reader) throws Exception{
String line = "";
while(reader.ready()){
char[] c = new char[1];
reader.read(c);
line+=c[0];
if(c[0] == '}'){
Object parse;
try {
parse = new JSONParser().parse(line);
if(parse != null) return parse;
}catch(Exception e){}
}
}
return null;
}
//I found this code on StackOverFlow !!!!! (and the write too)
public static String readWebSocket(HttpReader reader) throws Exception{
int buffLenth = 1024;
int len = 0;
byte[] b = new byte[buffLenth];
//rawIn is a Socket.getInputStream();
while(true){
len = reader.read(b);
if(len!=-1){
byte rLength = 0;
int rMaskIndex = 2;
int rDataStart = 0;
//b[0] is always text in my case so no need to check;
byte data = b[1];
byte op = (byte) 127;
rLength = (byte) (data & op);
if(rLength==(byte)126) rMaskIndex=4;
if(rLength==(byte)127) rMaskIndex=10;
byte[] masks = new byte[4];
int j=0;
int i=0;
for(i=rMaskIndex;i<(rMaskIndex+4);i++){
masks[j] = b[i];
j++;
}
rDataStart = rMaskIndex + 4;
int messLen = len - rDataStart;
byte[] message = new byte[messLen];
for(i=rDataStart, j=0; i<len; i++, j++){
message[j] = (byte) (b[i] ^ masks[j % 4]);
}
return new String(message);
}else break;
}
return null;
}
public static void sendWebSocket(HttpWriter writer, String message) throws Exception{
byte[] rawData = message.getBytes();
int frameCount = 0;
byte[] frame = new byte[10];
frame[0] = (byte) 129;
if(rawData.length <= 125){
frame[1] = (byte) rawData.length;
frameCount = 2;
}else if(rawData.length >= 126 && rawData.length <= 65535){
frame[1] = (byte) 126;
int len = rawData.length;
frame[2] = (byte)((len >> 8 ) & (byte)255);
frame[3] = (byte)(len & (byte)255);
frameCount = 4;
}else{
frame[1] = (byte) 127;
int len = rawData.length;
frame[2] = (byte)((len >> 56 ) & (byte)255);
frame[3] = (byte)((len >> 48 ) & (byte)255);
frame[4] = (byte)((len >> 40 ) & (byte)255);
frame[5] = (byte)((len >> 32 ) & (byte)255);
frame[6] = (byte)((len >> 24 ) & (byte)255);
frame[7] = (byte)((len >> 16 ) & (byte)255);
frame[8] = (byte)((len >> 8 ) & (byte)255);
frame[9] = (byte)(len & (byte)255);
frameCount = 10;
}
int bLength = frameCount + rawData.length;
byte[] reply = new byte[bLength];
int bLim = 0;
for(int i=0; i<frameCount;i++){
reply[bLim] = frame[i];
bLim++;
}
for(int i=0; i<rawData.length;i++){
reply[bLim] = rawData[i];
bLim++;
}
writer.write(reply);
writer.flush();
}
private static String codeMessage(int paramInt) {
switch (paramInt) {
case 200:
return " OK";
case 100:
return " Continue";
case 201:
return " Created";
case 202:
return " Accepted";
case 203:
return " Non-Authoritative Information";
case 204:
return " No Content";
case 205:
return " Reset Content";
case 206:
return " Partial Content";
case 300:
return " Multiple Choices";
case 301:
return " Moved Permanently";
case 302:
return " Temporary Redirect";
case 303:
return " See Other";
case 304:
return " Not Modified";
case 305:
return " Use Proxy";
case 400:
return " Bad Request";
case 401:
return " Unauthorized";
case 402:
return " Payment Required";
case 403:
return " Forbidden";
case 404:
return " Not Found";
case 405:
return " Method Not Allowed";
case 406:
return " Not Acceptable";
case 407:
return " Proxy Authentication Required";
case 408:
return " Request Time-Out";
case 409:
return " Conflict";
case 410:
return " Gone";
case 411:
return " Length Required";
case 412:
return " Precondition Failed";
case 413:
return " Request Entity Too Large";
case 414:
return " Request-URI Too Large";
case 415:
return " Unsupported Media Type";
case 500:
return " Internal Server Error";
case 501:
return " Not Implemented";
case 502:
return " Bad Gateway";
case 503:
return " Service Unavailable";
case 504:
return " Gateway Timeout";
case 505:
return " HTTP Version Not Supported";
}
return " ";
}
}

View file

@ -0,0 +1,35 @@
package be.jeffcheasey88.peeratcode.webserver;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class HttpWriter{
private OutputStream out;
private BufferedWriter writer;
public HttpWriter(Socket socket) throws Exception{
this.out = socket.getOutputStream();
this.writer = new BufferedWriter(new OutputStreamWriter(out));
}
public void write(byte[] buffer) throws IOException{
this.out.write(buffer);
this.out.flush();
}
public void write(String message) throws IOException{
this.writer.write(message);
}
public void flush() throws IOException{
this.writer.flush();
}
public void close() throws IOException{
this.writer.close();
}
}

View file

@ -0,0 +1,13 @@
package be.jeffcheasey88.peeratcode.webserver;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public interface Response{
void exec(Matcher matcher, HttpReader reader, HttpWriter writer) throws Exception ;
Pattern getPattern();
default String getType(){ return "GET"; }
}

View file

@ -0,0 +1,37 @@
package be.jeffcheasey88.peeratcode.webserver;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
public class Router{
private List<Response> responses;
private Response noFileFound;
public Router(){
this.responses = new ArrayList<>();
}
public void register(Response response){
this.responses.add(response);
}
public void setDefault(Response response){
this.noFileFound = response;
}
public void exec(String type, String path, HttpReader reader, HttpWriter writer) throws Exception {
for(Response response : this.responses){
if(type.equals(response.getType())){
Matcher matcher = response.getPattern().matcher(path);
if(matcher.matches()){
response.exec(matcher, reader, writer);
return;
}
}
}
if(noFileFound != null) noFileFound.exec(null, reader, writer);
}
}