From 22990fa35e3b8c37e77e005b9de8e8f6811a3682 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 11:37:04 +0100 Subject: [PATCH 01/12] Add: Document outlining the core components and roles in the server-side networking --- .../docs/networking/server-architecture.md | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 documents/docs/networking/server-architecture.md diff --git a/documents/docs/networking/server-architecture.md b/documents/docs/networking/server-architecture.md new file mode 100644 index 0000000..93ad908 --- /dev/null +++ b/documents/docs/networking/server-architecture.md @@ -0,0 +1,81 @@ +# Server-Side Networking — How It All Fits Together + +This doc is meant to give a solid mixed-level understanding of how our server-side networking works. No deep dives — just a clear picture of what's happening under the hood when a client connects and sends a command. + +> **Note:** This is v1. Annotations and Reflection-based dispatching are on the roadmap but not covered here yet. + +> **Disclamer:** This document has been written by Claude. I modified certain parts and verified its contents for correctness. + +## Our Protocol at a Glance + +Our protocol is inspired by **POP3** - a classic, text-based protocol that communicates over a raw TCP connection. The idea is simple: the client sends a command as a plain-text string, and the server responds with either a success or an error. + +A typical exchange looks something like this: + +``` +Client → GET_DELTA SINCE=42 +Server → +OK + PLAYER_FOLDED playerId=3 + POT 240 + NEXT_TURN playerId=1 + . +``` + +Responses start with `+OK` on success or `-ERR` when something goes wrong. Commands are short, uppercase strings - sometimes followed by arguments. + +We don't use HTTP, there's no JSON body, no headers. Just a raw socket, a text stream, and a clearly defined set of commands. + +## Core Components & Their Roles + +Here's a quick rundown of the main building blocks: + +### `NetworkManager` +This is the entry point. It binds to a specific port and listens for incoming TCP connections. +Once a client connects, it creates a `Session` adds it to the `SessionManager` and goes back to waiting. Its not the responsibility of the `NetworkManager` to recieve and send data from and to each connected client. + +### `Session` +Every client that connects has its own `Session` instance running on its own thread. This component owns the lifecycle of that connection: it reads incoming data, passes it along for processing, and writes responses back. + +### `SessionManager` +The `SessionManager` stores all currently active sessions. It allows for the retrieval of a specific session by its id. + +### `ProtocolParser` +Raw text (encapsulated in a `RawRequest`) coming off the socket isn't immediately useful — the `ProtocolParser` turns it with the help of the `Tokenizer` into a `PrimitiveRequest`. + +### `RawRequest` +The `RawRequest` object is created after a message has been recieved. +It holds both a reference to the `Session` that recieved the message and the message itself. + +### `PrimitiveRequest` +The `PrimitiveRequest` object is created by the `ProtocolParser` after the content of the `RawRequest` has been tokenized by the `Tokenizer`. +The command is stored in its own attribute and the arguments are accessible as a dictionary. + +### `Tokenizer` +The job of the `tokenizer` is it, to take the raw string and turn it into tokens. +For example, the command `CHAT_LOBBY GAME=12 MESSAGE='All-in?'` will be decoded as `"CHAT_LOBBY", "GAME", "=", "12", "MESSAGE", "=", "All-in?"`. +It is unaware about the meaning. + +### `CommandParser` (per command) +Takes in the `PrimitiveRequest` and checks if all required fields are provided with the correct value. +Creates a command specific `Request` object containing command arguments in a structured manner. + +### `Request` (per command) +Has fields common along each implementation such as a reference to the `Session` that recieved the request. +Furthermore each implementation has fields unique to each command. For example, the `ChatLobbyRequest` has fields for the game and the message. + +### `CommandRouter` +By identifying the type of class of the `Request`, the `CommandRouter` routes the request to the matching `CommandHandler`. + +### `CommandHandler` (per command) +Each supported command has its own handler — a small, focused class that contains the logic for that specific command. They have access to the domain, containing inner parts of the game itself. + +### `Response` (per response) +The interface has two sub-interfaces for either failed `ErrorResponse` or successfull `SuccessResponse` execution of commands. + +Each step has exactly one responsibility. Increasing the ability to test and extend different components later on. + +## Concurrency - Handling Multiple Clients + +Every incoming connection spawns a new **Thread**. This means multiple clients can be served simultaneously without blocking each other. + +As each `Session` runs entirely on its own thread, there's no shared mutable state between sessions, with exception of the `SessionManager` and other key components explained later. From 32e4b04c87a31b288de398422ee7bed6baa9b9f8 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 11:43:27 +0100 Subject: [PATCH 02/12] Add: SessionId to identify each session --- documents/docs/networking/server-architecture.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documents/docs/networking/server-architecture.md b/documents/docs/networking/server-architecture.md index 93ad908..1be14eb 100644 --- a/documents/docs/networking/server-architecture.md +++ b/documents/docs/networking/server-architecture.md @@ -36,6 +36,9 @@ Once a client connects, it creates a `Session` adds it to the `SessionManager` a ### `Session` Every client that connects has its own `Session` instance running on its own thread. This component owns the lifecycle of that connection: it reads incoming data, passes it along for processing, and writes responses back. +### `SessionId` +The `SessionId` is used to uniquely identify each session. Essentially its a wrapper arround the UUID type. + ### `SessionManager` The `SessionManager` stores all currently active sessions. It allows for the retrieval of a specific session by its id. From fb6f14371ff191031ad56f33ae6ded8ccbbd33b9 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 11:49:46 +0100 Subject: [PATCH 03/12] Add: PlantUML diagramm outlining each component --- .../networking_components.puml | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 documents/images/docs/networking/server-architecure/networking_components.puml diff --git a/documents/images/docs/networking/server-architecure/networking_components.puml b/documents/images/docs/networking/server-architecure/networking_components.puml new file mode 100644 index 0000000..647654a --- /dev/null +++ b/documents/images/docs/networking/server-architecure/networking_components.puml @@ -0,0 +1,96 @@ +@startuml +skinparam classAttributeIconSize 0 +skinparam packageStyle rectangle +skinparam linetype ortho +skinparam backgroundColor transparent + +' Network Layer +class NetworkManager { + + start(port: int) +} + +class Session { + - id: SessionId + + Session(id: SessionId) + + getId(): SessionId + + run() + + send(response: String) +} + +class SessionId { + - value: UUID + + SessionId() + + SessionId(value: UUID) +} + +class SessionManager { + - sessions: Map + + add(session: Session) + + getById(id: UUID): Session + + remove(id: UUID) +} + +NetworkManager --> Session : creates +NetworkManager --> SessionManager : adds session to +Session --> SessionId : identified by +Session --> RawRequest : creates +Session ..> Response : sends +SessionManager o-- Session : manages + +' Protocol Layer +class RawRequest { + - session: Session + - rawMessage: String +} + +class Tokenizer { + + tokenize(input: String): List +} + +class ProtocolParser { + + parse(raw: RawRequest): PrimitiveRequest +} + +class PrimitiveRequest { + - command: String + - arguments: Map +} + +RawRequest --> ProtocolParser : passed to +ProtocolParser --> Tokenizer : uses +ProtocolParser --> PrimitiveRequest : produces + +' Command Layer +interface CommandParser <> { + + parse(primitive: PrimitiveRequest): Request +} + +interface Request <> { + - session: Session +} + +class CommandRouter { + + route(request: Request) +} + +interface CommandHandler <> { + + handle(request: Request) +} + +PrimitiveRequest --> CommandParser : passed to +CommandParser --> Request : produces +CommandRouter --> CommandHandler : dispatches to +CommandRouter ..> Request : receives + +' Response Layer +interface Response { + + encode(): String +} + +interface SuccessResponse + +interface ErrorResponse + +Response <|-- SuccessResponse +Response <|-- ErrorResponse +@enduml From a5272b99ab44785de568ebf13f9376fc3f9a7c89 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 11:50:59 +0100 Subject: [PATCH 04/12] Add: Include diagramm in document --- documents/docs/networking/server-architecture.md | 2 ++ .../networking/server-architecure/networking_components.svg | 1 + 2 files changed, 3 insertions(+) create mode 100644 documents/images/docs/networking/server-architecure/networking_components.svg diff --git a/documents/docs/networking/server-architecture.md b/documents/docs/networking/server-architecture.md index 1be14eb..8537382 100644 --- a/documents/docs/networking/server-architecture.md +++ b/documents/docs/networking/server-architecture.md @@ -27,6 +27,8 @@ We don't use HTTP, there's no JSON body, no headers. Just a raw socket, a text s ## Core Components & Their Roles +![PlantUML diagramm of all components outlined in this document](/documents/images/docs/networking/server-architecure/networking_components.svg) + Here's a quick rundown of the main building blocks: ### `NetworkManager` diff --git a/documents/images/docs/networking/server-architecure/networking_components.svg b/documents/images/docs/networking/server-architecure/networking_components.svg new file mode 100644 index 0000000..9db9f6d --- /dev/null +++ b/documents/images/docs/networking/server-architecure/networking_components.svg @@ -0,0 +1 @@ +NetworkManager+start(port: int)Session-id: SessionId+Session(id: SessionId)+getId(): SessionId+run()+send(response: String)SessionId-value: UUID+SessionId()+SessionId(value: UUID)SessionManager-sessions: Map<UUID, Session>+add(session: Session)+getById(id: UUID): Session+remove(id: UUID)RawRequest-session: Session-rawMessage: StringResponse+encode(): StringTokenizer+tokenize(input: String): List<String>ProtocolParser+parse(raw: RawRequest): PrimitiveRequestPrimitiveRequest-command: String-arguments: Map<String, String>«per command»CommandParser+parse(primitive: PrimitiveRequest): Request«per command»Request-session: SessionCommandRouter+route(request: Request)«per command»CommandHandler+handle(request: Request)SuccessResponseErrorResponsecreatesadds session toidentified bycreatessendsmanagespassed tousesproducespassed toproducesdispatches toreceives \ No newline at end of file From 3c9f19c5dad5b42c9a2a864d9d5c4483a4d141ca Mon Sep 17 00:00:00 2001 From: Jona Walpert Date: Wed, 11 Mar 2026 13:13:42 +0100 Subject: [PATCH 05/12] Add: Game logo, placeholder abckground image --- src/main/resources/images/backround.png | Bin 0 -> 4917 bytes src/main/resources/images/logo.png | Bin 0 -> 3121 bytes src/main/resources/images/logoinverted.png | Bin 0 -> 198316 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/images/backround.png create mode 100644 src/main/resources/images/logo.png create mode 100644 src/main/resources/images/logoinverted.png diff --git a/src/main/resources/images/backround.png b/src/main/resources/images/backround.png new file mode 100644 index 0000000000000000000000000000000000000000..e5e1841521b60a35d641455cf7ad2731329e2198 GIT binary patch literal 4917 zcmeAS@N?(olHy`uVBq!ia0y~yU}<1rVCvvt1B!5HH}V20#^NA%Cx&(BWL^R}Ea{HE zjtmSN`?>!lvI6;>1s;*b3=DjSL74G){)!Z!hW5;mh>{3jAFJg2T)o7U{G?R9irfOA zY6b=y`-+0Zwic-?7f?V97Du6s&rHqo2 z0xNy}^73-Ma$~*xqI7*jOG`_A10#JSBVC{h-Qvo;lEez#ykcdj0WPV<$wiq3C7Jno z3Lpa$lk!VTY?Vq&GgGY664OkRQc_HHlM;G+w>Jz04=6AkI1nV;^P{|t?Z(6j zzvYz`lh2phfnsOVKXVXuA&G$zNF9-M0Pzah1c0Q&97Yx(C6GQUH5wYDX=5}yj1~@~ z<>6@UFj^swHV;NyM58UD(H7BYi)ge(G}Z4nKt7LmByA9kD2J#|vRcxCW(^>bP0 Hl+XkK_IHxK literal 0 HcmV?d00001 diff --git a/src/main/resources/images/logo.png b/src/main/resources/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e906bd477ab5f700d7b1d62575ac4cfb9e9bf110 GIT binary patch literal 3121 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 a$AP*V*dH?OiofV(K0rF;O(_3~a`nI3SIF4_ literal 0 HcmV?d00001 diff --git a/src/main/resources/images/logoinverted.png b/src/main/resources/images/logoinverted.png new file mode 100644 index 0000000000000000000000000000000000000000..73053b6241f54d33d8d5422e05dd44236443b79d GIT binary patch literal 198316 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 Date: Wed, 11 Mar 2026 13:22:33 +0100 Subject: [PATCH 06/12] Chore: Added javafx modules to build.gradle file --- .vscode/settings.json | 3 +++ bin/main/images/backround.png | Bin 0 -> 4917 bytes bin/main/images/logo.png | Bin 0 -> 3121 bytes bin/main/images/logoinverted.png | Bin 0 -> 198316 bytes build.gradle | 2 +- 5 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json create mode 100644 bin/main/images/backround.png create mode 100644 bin/main/images/logo.png create mode 100644 bin/main/images/logoinverted.png diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e0f15db --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/bin/main/images/backround.png b/bin/main/images/backround.png new file mode 100644 index 0000000000000000000000000000000000000000..e5e1841521b60a35d641455cf7ad2731329e2198 GIT binary patch literal 4917 zcmeAS@N?(olHy`uVBq!ia0y~yU}<1rVCvvt1B!5HH}V20#^NA%Cx&(BWL^R}Ea{HE zjtmSN`?>!lvI6;>1s;*b3=DjSL74G){)!Z!hW5;mh>{3jAFJg2T)o7U{G?R9irfOA zY6b=y`-+0Zwic-?7f?V97Du6s&rHqo2 z0xNy}^73-Ma$~*xqI7*jOG`_A10#JSBVC{h-Qvo;lEez#ykcdj0WPV<$wiq3C7Jno z3Lpa$lk!VTY?Vq&GgGY664OkRQc_HHlM;G+w>Jz04=6AkI1nV;^P{|t?Z(6j zzvYz`lh2phfnsOVKXVXuA&G$zNF9-M0Pzah1c0Q&97Yx(C6GQUH5wYDX=5}yj1~@~ z<>6@UFj^swHV;NyM58UD(H7BYi)ge(G}Z4nKt7LmByA9kD2J#|vRcxCW(^>bP0 Hl+XkK_IHxK literal 0 HcmV?d00001 diff --git a/bin/main/images/logo.png b/bin/main/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e906bd477ab5f700d7b1d62575ac4cfb9e9bf110 GIT binary patch literal 3121 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 a$AP*V*dH?OiofV(K0rF;O(_3~a`nI3SIF4_ literal 0 HcmV?d00001 diff --git a/bin/main/images/logoinverted.png b/bin/main/images/logoinverted.png new file mode 100644 index 0000000000000000000000000000000000000000..73053b6241f54d33d8d5422e05dd44236443b79d GIT binary patch literal 198316 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 Date: Wed, 11 Mar 2026 14:20:18 +0100 Subject: [PATCH 07/12] Add: Added "bin" to gitignroe --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index aa33988..c29286e 100644 --- a/.gitignore +++ b/.gitignore @@ -118,4 +118,7 @@ $RECYCLE.BIN/ *.drawio.pdf ## IntelliJ -.idea \ No newline at end of file +.idea + +## bin +bin/ \ No newline at end of file From 2b012aa256cf9e0ca3077726a7713b2c31eb4988 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 17:40:46 +0100 Subject: [PATCH 08/12] Add: log4j as gradle dependency --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 99a402a..0a481cf 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,10 @@ javafx { } dependencies { + // Source: https://mvnrepository.com/artifact/org.apache.logging.log4j + implementation("org.apache.logging.log4j:log4j-api:2.25.3") + runtimeOnly("org.apache.logging.log4j:log4j-core:2.25.3") + testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0") } From 85c872df239b39329c8ff76f43b6e29bec237df9 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 17:41:14 +0100 Subject: [PATCH 09/12] Add: Konfigure log4j with the bare minimum --- src/main/resources/log4j2.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/resources/log4j2.xml diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..1c7e406 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file From a2256b2c1e3bd6747b75cfb85c5b84410d1e35d3 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 17:44:19 +0100 Subject: [PATCH 10/12] Add: Jansi as gradle dependency to allow colored console output --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 0a481cf..8196bdb 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,9 @@ dependencies { implementation("org.apache.logging.log4j:log4j-api:2.25.3") runtimeOnly("org.apache.logging.log4j:log4j-core:2.25.3") + // Source: https://mvnrepository.com/artifact/org.fusesource.jansi/jansi + runtimeOnly("org.fusesource.jansi:jansi:2.4.2") + testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0") } From 18331a7cc3e5153ad459ce16c08f4c20f445487a Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Wed, 11 Mar 2026 17:47:36 +0100 Subject: [PATCH 11/12] Add: Colored log output, based on log level --- src/main/resources/log4j2.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 1c7e406..01d74ca 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -3,12 +3,21 @@ - + - + From 0b51f4f45ae97cf6816c8e4e2ab96416cacab0ac Mon Sep 17 00:00:00 2001 From: Jona Walpert <98217482+Jona-Walpert@users.noreply.github.com> Date: Fri, 13 Mar 2026 11:29:21 +0100 Subject: [PATCH 12/12] Chore: Add client run task to gradle --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index 99a402a..469141c 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,12 @@ tasks.named('jar', Jar) { } } +tasks.register('cruntest', JavaExec) { + classpath = sourceSets.main.runtimeClasspath + mainClass = 'ch.unibas.dmi.dbis.cs108.casono.Main' + jvmArgs '--enable-native-access=ALL-UNNAMED' + args 'client', '0.0.0.0:1234' +} tasks.register('fatJar', Jar) { group = 'build'