From 8d5a6524329a8a3a06a9460275336423ab38e4e2 Mon Sep 17 00:00:00 2001
From: jeffcheasey88 <66554203+jeffcheasey88@users.noreply.github.com>
Date: Sat, 25 Mar 2023 19:47:30 +0100
Subject: [PATCH] first commit
---
.classpath | 11 +
.gitignore | 2 +
.project | 17 +
json-simple-1.1.1.jar | Bin 0 -> 23931 bytes
src/be/jeffcheasey88/Main.java | 70 ++++
src/be/jeffcheasey88/Party.java | 39 ++
src/be/jeffcheasey88/Player.java | 26 ++
src/be/jeffcheasey88/webserver/Client.java | 29 ++
.../jeffcheasey88/webserver/HttpReader.java | 40 +++
src/be/jeffcheasey88/webserver/HttpUtil.java | 334 ++++++++++++++++++
.../jeffcheasey88/webserver/HttpWriter.java | 36 ++
src/be/jeffcheasey88/webserver/Response.java | 9 +
src/be/jeffcheasey88/webserver/Route.java | 15 +
src/be/jeffcheasey88/webserver/Router.java | 49 +++
14 files changed, 677 insertions(+)
create mode 100644 .classpath
create mode 100644 .gitignore
create mode 100644 .project
create mode 100644 json-simple-1.1.1.jar
create mode 100644 src/be/jeffcheasey88/Main.java
create mode 100644 src/be/jeffcheasey88/Party.java
create mode 100644 src/be/jeffcheasey88/Player.java
create mode 100644 src/be/jeffcheasey88/webserver/Client.java
create mode 100644 src/be/jeffcheasey88/webserver/HttpReader.java
create mode 100644 src/be/jeffcheasey88/webserver/HttpUtil.java
create mode 100644 src/be/jeffcheasey88/webserver/HttpWriter.java
create mode 100644 src/be/jeffcheasey88/webserver/Response.java
create mode 100644 src/be/jeffcheasey88/webserver/Route.java
create mode 100644 src/be/jeffcheasey88/webserver/Router.java
diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..da9ddb9
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..30263e5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+bin/
+.settings/
\ No newline at end of file
diff --git a/.project b/.project
new file mode 100644
index 0000000..710842b
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ Endg-2048-Backend
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/json-simple-1.1.1.jar b/json-simple-1.1.1.jar
new file mode 100644
index 0000000000000000000000000000000000000000..dfd5856d0cad81dfe7845ea6ff4d170d8064d7b0
GIT binary patch
literal 23931
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 parties = new HashSet<>();
+
+ public static Party pick(){
+ for(Party party : parties){
+ if(!party.ready()) return party;
+ }
+ Party party = new Party();
+ parties.add(party);
+ return party;
+ }
+
+ private Player one;
+ private Player second;
+
+ private Party() {}
+
+ public void join(Player player){
+ if(this.one == null){
+ this.one = player;
+ }else{
+ this.second = player;
+ }
+ }
+
+ public boolean ready(){
+ return one != null && second != null;
+ }
+
+ public Player getOpposite(Player current){
+ return current.equals(one) ? second : one;
+ }
+}
diff --git a/src/be/jeffcheasey88/Player.java b/src/be/jeffcheasey88/Player.java
new file mode 100644
index 0000000..e7a5adc
--- /dev/null
+++ b/src/be/jeffcheasey88/Player.java
@@ -0,0 +1,26 @@
+package be.jeffcheasey88;
+
+import be.jeffcheasey88.webserver.HttpWriter;
+
+public class Player {
+
+ private String state;
+ private final HttpWriter writer;
+
+ public Player(HttpWriter writer){
+ this.writer = writer;
+ }
+
+ public void setState(String state){
+ this.state = state;
+ }
+
+ public String getState(){
+ return this.state;
+ }
+
+ public HttpWriter getWriter(){
+ return this.writer;
+ }
+
+}
diff --git a/src/be/jeffcheasey88/webserver/Client.java b/src/be/jeffcheasey88/webserver/Client.java
new file mode 100644
index 0000000..fd4f825
--- /dev/null
+++ b/src/be/jeffcheasey88/webserver/Client.java
@@ -0,0 +1,29 @@
+package be.jeffcheasey88.webserver;
+
+import java.net.Socket;
+import java.util.Arrays;
+
+public class Client extends Thread{
+
+ private HttpReader reader;
+ private HttpWriter writer;
+ private Router router;
+
+ public Client(Socket socket, Router router) throws Exception{
+ 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);
+ writer.flush();
+ writer.close();
+ } catch (Exception e){}
+ }
+}
\ No newline at end of file
diff --git a/src/be/jeffcheasey88/webserver/HttpReader.java b/src/be/jeffcheasey88/webserver/HttpReader.java
new file mode 100644
index 0000000..7438e83
--- /dev/null
+++ b/src/be/jeffcheasey88/webserver/HttpReader.java
@@ -0,0 +1,40 @@
+package be.jeffcheasey88.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();
+ }
+}
\ No newline at end of file
diff --git a/src/be/jeffcheasey88/webserver/HttpUtil.java b/src/be/jeffcheasey88/webserver/HttpUtil.java
new file mode 100644
index 0000000..c7175a4
--- /dev/null
+++ b/src/be/jeffcheasey88/webserver/HttpUtil.java
@@ -0,0 +1,334 @@
+package be.jeffcheasey88.webserver;
+
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+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 List readMultiPartData(HttpReader reader) throws Exception{
+ List list = new ArrayList<>();
+
+ reader.readLine();
+
+ while(reader.ready()){
+ String line;
+ while(((line = reader.readLine()) != null) && (line.length() > 0)){
+
+ }
+ String buffer = "";
+ while(((line = reader.readLine()) != null) && (!line.startsWith("------WebKitFormBoundary"))){
+ buffer+=line;
+ }
+ list.add(buffer);
+ }
+
+ return list;
+ }
+
+ 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: "+
+ 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("Authorization: Bearer (.*)");
+
+ public static String readAuthorization(HttpReader reader) throws Exception {
+ String line;
+ String key = null;
+ while(((line = reader.readLine()) != null) && (line.length() > 0)){
+ Matcher matcher = AUTORIZATION.matcher(line);
+ if(matcher.matches()){
+ key = matcher.group(1);
+ break;
+ }
+ }
+ 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= 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= 3; j += 3) {
+ paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j] >> 2);
+ paramArrayOfchar[paramInt3++] = encode((paramArrayOfbyte[j] & 0x3) << 4 | paramArrayOfbyte[j + 1] >> 4 & 0xF);
+ paramArrayOfchar[paramInt3++] = encode((paramArrayOfbyte[j + 1] & 0xF) << 2 | paramArrayOfbyte[j + 2] >> 6 & 0x3);
+ paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j + 2] & 0x3F);
+ i -= 3;
+ }
+ if (i == 1) {
+ paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j] >> 2);
+ paramArrayOfchar[paramInt3++] = encode((paramArrayOfbyte[j] & 0x3) << 4);
+ paramArrayOfchar[paramInt3++] = '=';
+ paramArrayOfchar[paramInt3++] = '=';
+ }
+ if (i == 2) {
+ paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j] >> 2);
+ paramArrayOfchar[paramInt3++] = encode((paramArrayOfbyte[j] & 0x3) << 4 | paramArrayOfbyte[j + 1] >> 4 & 0xF);
+ paramArrayOfchar[paramInt3++] = encode((paramArrayOfbyte[j + 1] & 0xF) << 2);
+ paramArrayOfchar[paramInt3++] = '=';
+ }
+ return paramInt3;
+ }
+
+ private static char encode(int paramInt) {
+ return encodeMap[paramInt & 0x3F];
+ }
+ private static final char[] encodeMap = initEncodeMap();
+
+ private static char[] initEncodeMap() {
+ char[] arrayOfChar = new char[64];
+ byte b;
+ for (b = 0; b < 26; b++)
+ arrayOfChar[b] = (char)(65 + b);
+ for (b = 26; b < 52; b++)
+ arrayOfChar[b] = (char)(97 + b - 26);
+ for (b = 52; b < 62; b++)
+ arrayOfChar[b] = (char)(48 + b - 52);
+ arrayOfChar[62] = '+';
+ arrayOfChar[63] = '/';
+ return arrayOfChar;
+ }
+}
\ No newline at end of file
diff --git a/src/be/jeffcheasey88/webserver/HttpWriter.java b/src/be/jeffcheasey88/webserver/HttpWriter.java
new file mode 100644
index 0000000..7fc8389
--- /dev/null
+++ b/src/be/jeffcheasey88/webserver/HttpWriter.java
@@ -0,0 +1,36 @@
+package be.jeffcheasey88.webserver;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+
+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, StandardCharsets.UTF_8));
+ }
+
+ 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();
+ }
+}
\ No newline at end of file
diff --git a/src/be/jeffcheasey88/webserver/Response.java b/src/be/jeffcheasey88/webserver/Response.java
new file mode 100644
index 0000000..9c543ae
--- /dev/null
+++ b/src/be/jeffcheasey88/webserver/Response.java
@@ -0,0 +1,9 @@
+package be.jeffcheasey88.webserver;
+
+import java.util.regex.Matcher;
+
+public interface Response{
+
+ void exec(Matcher matcher, HttpReader reader, HttpWriter writer) throws Exception ;
+
+}
\ No newline at end of file
diff --git a/src/be/jeffcheasey88/webserver/Route.java b/src/be/jeffcheasey88/webserver/Route.java
new file mode 100644
index 0000000..26f5ebe
--- /dev/null
+++ b/src/be/jeffcheasey88/webserver/Route.java
@@ -0,0 +1,15 @@
+package be.jeffcheasey88.webserver;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Route {
+
+ String path() default "^.*$";
+ String type() default "GET";
+
+}
\ No newline at end of file
diff --git a/src/be/jeffcheasey88/webserver/Router.java b/src/be/jeffcheasey88/webserver/Router.java
new file mode 100644
index 0000000..f62c8bf
--- /dev/null
+++ b/src/be/jeffcheasey88/webserver/Router.java
@@ -0,0 +1,49 @@
+package be.jeffcheasey88.webserver;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Router{
+
+ private Map responses;
+ private Map patterns;
+ private Response noFileFound;
+
+ public Router() throws Exception{
+ this.responses = new HashMap<>();
+ this.patterns = new HashMap<>();
+ }
+
+ public void register(Response response){
+ try {
+ Method method = response.getClass().getDeclaredMethod("exec", Response.class.getDeclaredMethods()[0].getParameterTypes());
+ Route route = method.getAnnotation(Route.class);
+
+ this.responses.put(response, route);
+ this.patterns.put(response, Pattern.compile(route.path()));
+ } catch (Exception e){
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public void setDefault(Response response){
+ this.noFileFound = response;
+ }
+
+ public void exec(String type, String path,HttpReader reader, HttpWriter writer) throws Exception {
+ for(Entry routes : this.responses.entrySet()){
+ if(routes.getValue().type().equals(type)){
+ Matcher matcher = this.patterns.get(routes.getKey()).matcher(path);
+ if(matcher.matches()){
+ routes.getKey().exec(matcher, reader, writer);
+ return;
+ }
+ }
+ }
+ if(noFileFound != null) noFileFound.exec(null, reader, writer);
+ }
+}
\ No newline at end of file