asfur/PROTOCOL
Lorenzo Torres 238eff5bb3 Add unit test suite and complete protocol documentation
- Add test framework (test.h) with assertion macros and test runner
- Add comprehensive unit tests (test_network.c) covering:
  - Packet parsing and error handling
  - User registration and authentication
  - Room operations (create, join, leave, delete, list)
  - Direct messaging functionality
  - Message broadcasting
  - Password hashing
- Update Makefile with 'make test' target
- Rewrite PROTOCOL file with complete specification:
  - All 14 packet types with data layouts
  - All error codes with descriptions
  - Typical usage flows
2026-01-08 15:51:01 +01:00

177 lines
5 KiB
Text

ASFUR PROTOCOL SPECIFICATION
All packets follow this structure:
[u16 size][u8 type][data...]
size: total length of the packet (including header)
type: packet type identifier
data: payload bytes (format depends on type)
================================================================================
PACKET TYPES
================================================================================
Client -> Server:
PACKET_REGISTER = 1
PACKET_AUTHENTICATE = 2
PACKET_JOIN = 3
PACKET_TEXT = 4
PACKET_LEAVE = 5
PACKET_DM_OPEN = 7
PACKET_CREATE_ROOM = 9
PACKET_DELETE_ROOM = 10
PACKET_LIST_ROOMS = 12
Server -> Client:
PACKET_ERROR = 0
PACKET_OK = 6
PACKET_DM_ROOM = 8
PACKET_ROOM_CREATED = 11
PACKET_ROOM_LIST = 13
Bidirectional:
PACKET_TEXT = 4 (client sends, server broadcasts)
================================================================================
PACKET DATA LAYOUTS
================================================================================
PACKET_ERROR (0)
Server response indicating an error occurred.
[u8 code]
Error codes:
0 = ERR_OK (no error)
1 = ERR_UNKNOWN (unknown error)
2 = ERR_INVALID_PACKET (malformed packet)
3 = ERR_NOT_AUTHENTICATED (action requires authentication)
4 = ERR_ALREADY_REGISTERED (username already taken)
5 = ERR_INVALID_CREDENTIALS (wrong username/password)
6 = ERR_REGISTRATION_DISABLED (server disabled registration)
7 = ERR_DATABASE (internal database error)
8 = ERR_USER_NOT_FOUND (target user does not exist)
9 = ERR_ACCESS_DENIED (not allowed to access resource)
10 = ERR_ROOM_NOT_FOUND (room does not exist)
11 = ERR_ROOM_NAME_TAKEN (room name already in use)
12 = ERR_NOT_ROOM_OWNER (action requires room ownership)
PACKET_REGISTER (1)
Register a new user account.
[char username[20]][char password[100]]
Response: PACKET_OK or PACKET_ERROR
PACKET_AUTHENTICATE (2)
Authenticate with existing credentials.
[char username[20]][char password[100]]
Response: PACKET_OK or PACKET_ERROR
PACKET_JOIN (3)
Join a room (public or DM).
[u64 room_id]
Response: PACKET_OK or PACKET_ERROR
Requires: authentication
PACKET_TEXT (4)
Send a message to a room (client -> server).
[u64 room_id][char message[...]]
message is variable length (packet size - header - 8 bytes)
Client must have joined the room first.
Requires: authentication, joined room
Broadcast format (server -> client):
[u64 room_id][char username[32]][char message[...]]
Server broadcasts to all authenticated clients in the room.
PACKET_LEAVE (5)
Leave a room.
[u64 room_id]
Response: PACKET_OK or PACKET_ERROR
Requires: authentication
PACKET_OK (6)
Server response indicating success.
(no data)
PACKET_DM_OPEN (7)
Open or get existing DM room with another user.
[char username[20]]
Response: PACKET_DM_ROOM or PACKET_ERROR
Requires: authentication
PACKET_DM_ROOM (8)
Server response with DM room ID.
[u64 room_id]
The room_id can be used with PACKET_JOIN.
PACKET_CREATE_ROOM (9)
Create a new public room.
[char name[32]]
Response: PACKET_ROOM_CREATED or PACKET_ERROR
Requires: authentication
PACKET_DELETE_ROOM (10)
Delete a public room.
[u64 room_id]
Response: PACKET_OK or PACKET_ERROR
Requires: authentication, room ownership
PACKET_ROOM_CREATED (11)
Server response after successful room creation.
[u64 room_id][char name[32]]
PACKET_LIST_ROOMS (12)
Request list of all public rooms.
(no data)
Response: PACKET_ROOM_LIST or PACKET_ERROR
Requires: authentication
PACKET_ROOM_LIST (13)
Server response with list of public rooms.
[u32 count][room_entry[count]]
room_entry format:
[u64 room_id][char name[32]][char owner[20]]
================================================================================
TYPICAL FLOWS
================================================================================
Registration:
Client: PACKET_REGISTER(username, password)
Server: PACKET_OK or PACKET_ERROR(ERR_ALREADY_REGISTERED)
Authentication:
Client: PACKET_AUTHENTICATE(username, password)
Server: PACKET_OK or PACKET_ERROR(ERR_INVALID_CREDENTIALS)
Join public room:
Client: PACKET_LIST_ROOMS
Server: PACKET_ROOM_LIST(rooms)
Client: PACKET_JOIN(room_id)
Server: PACKET_OK
Send message:
Client: PACKET_TEXT(room_id, "hello")
Server: PACKET_TEXT(room_id, sender_username, "hello") -> all clients in room
Direct message:
Client: PACKET_DM_OPEN(target_username)
Server: PACKET_DM_ROOM(room_id)
Client: PACKET_JOIN(room_id)
Server: PACKET_OK
Client: PACKET_TEXT(room_id, "private message")
Create room:
Client: PACKET_CREATE_ROOM("my-room")
Server: PACKET_ROOM_CREATED(room_id, "my-room")