Files
tcp-chat/src/network/tcp-chat-protocol/v1.c
2025-12-15 23:26:32 +05:00

238 lines
7.1 KiB
C

#include "v1.h"
str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_username_str){
// must end with 0
if(username[USERNAME_SIZE_MAX] != '\0'){
return str_copy(STR("Username string doesn't end correctly"));
}
str u = str_from_cstr(username);
str error_str = validateUsername_str(u);
if(error_str.data)
return error_str;
*out_username_str = u;
return str_null;
}
str validateUsername_str(str username){
if(username.len < USERNAME_SIZE_MIN || username.len > USERNAME_SIZE_MAX){
return str_from_cstr(
sprintf_malloc(
"username length (in bytes) must be >= %i and <= %i\n",
USERNAME_SIZE_MIN, USERNAME_SIZE_MAX
)
);
}
for(u32 i = 0; i < username.len; i++){
char c = username.data[i];
if (char_isLatinLower(c) ||
char_isLatinUpper(c) ||
char_isDigit(c) ||
c == '.' || c == '_' || c == '-')
continue;
return str_copy(STR("Username contains restricted characters. "
"Allowed characters: latin, digits, ._-"));
}
return str_null;
}
#define _PacketHeader_construct(T) \
PacketHeader_construct(header, PROTOCOL_VERSION, PacketType_##T, sizeof(T))
void ErrorMessage_construct(ErrorMessage* ptr, PacketHeader* header, u32 msg_size){
_PacketHeader_construct(ErrorMessage);
zeroStruct(ptr);
ptr->msg_size = msg_size;
}
Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* header,
Array(u8) session_key)
{
Deferral(1);
_PacketHeader_construct(ClientHandshake);
zeroStruct(ptr);
try_assert(session_key.len == sizeof(ptr->session_key));
memcpy(ptr->session_key, session_key.data, session_key.len);
Return RESULT_VOID;
}
void ServerHandshake_construct(ServerHandshake* ptr, PacketHeader* header,
i64 session_id)
{
_PacketHeader_construct(ServerHandshake);
zeroStruct(ptr);
ptr->session_id = session_id;
}
void ServerPublicInfoRequest_construct(ServerPublicInfoRequest *ptr, PacketHeader* header,
ServerPublicInfo property)
{
_PacketHeader_construct(ServerPublicInfoRequest);
zeroStruct(ptr);
ptr->property = property;
}
void ServerPublicInfoResponse_construct(ServerPublicInfoResponse* ptr, PacketHeader* header,
u32 data_size)
{
_PacketHeader_construct(ServerPublicInfoResponse);
zeroStruct(ptr);
ptr->data_size = data_size;
}
Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header,
str username, Array(u8) token)
{
Deferral(1);
_PacketHeader_construct(LoginRequest);
zeroStruct(ptr);
str name_error_str = validateUsername_str(username);
if(name_error_str.data){
Return RESULT_ERROR(name_error_str, true);
}
memcpy(ptr->username, username.data, username.len);
try_assert(token.len == sizeof(ptr->token));
memcpy(ptr->token, token.data, token.len);
Return RESULT_VOID;
}
void LoginResponse_construct(LoginResponse* ptr, PacketHeader* header,
i64 user_id, i64 landing_channel_id)
{
_PacketHeader_construct(LoginResponse);
zeroStruct(ptr);
ptr->user_id = user_id;
ptr->landing_channel_id = landing_channel_id;
}
Result(void) RegisterRequest_tryConstruct(RegisterRequest *ptr, PacketHeader* header,
str username, Array(u8) token)
{
Deferral(1);
_PacketHeader_construct(RegisterRequest);
zeroStruct(ptr);
str name_error_str = validateUsername_str(username);
if(name_error_str.data){
Return RESULT_ERROR(name_error_str, true);
}
memcpy(ptr->username, username.data, username.len);
try_assert(token.len == sizeof(ptr->token));
memcpy(ptr->token, token.data, token.len);
Return RESULT_VOID;
}
void RegisterResponse_construct(RegisterResponse *ptr, PacketHeader* header,
i64 user_id)
{
_PacketHeader_construct(RegisterResponse);
zeroStruct(ptr);
ptr->user_id = user_id;
}
Result(u32) MessageBlock_writeMessage(
MessageMeta* msg, Array(u8) msg_content,
MessageBlockMeta* block_meta, Array(u8)* block_free_part)
{
Deferral(1);
try_assert(msg->data_size >= MESSAGE_SIZE_MIN && msg->data_size <= MESSAGE_SIZE_MAX);
try_assert(msg->data_size <= msg_content.len);
u32 offset_increment = sizeof(MessageMeta) + msg->data_size;
if(block_free_part->len < offset_increment){
Return RESULT_VALUE(u, 0);
}
memcpy(block_free_part->data, msg, sizeof(MessageMeta));
block_free_part->data += sizeof(MessageMeta);
block_free_part->len -= sizeof(MessageMeta);
memcpy(block_free_part->data, msg_content.data, msg->data_size);
block_free_part->data += msg->data_size;
block_free_part->len -= msg->data_size;
if(block_meta->message_count == 0)
block_meta->first_message_id = msg->id;
block_meta->message_count++;
block_meta->data_size += offset_increment;
Return RESULT_VALUE(u, offset_increment);
}
Result(u32) MessageBlock_readMessage(
Array(u8)* block_unread_part,
MessageMeta* msg, Array(u8) msg_content)
{
Deferral(1);
try_assert(block_unread_part->len >= sizeof(MessageMeta) + MESSAGE_SIZE_MIN);
try_assert(msg_content.len >= MESSAGE_SIZE_MIN && msg_content.len <= MESSAGE_SIZE_MAX);
memcpy(msg, block_unread_part->data, sizeof(MessageMeta));
block_unread_part->data += sizeof(MessageMeta);
block_unread_part->len -= sizeof(MessageMeta);
if(msg->magic.n != MESSAGE_MAGIC.n){
Return RESULT_VALUE(u, 0);
}
try_assert(block_unread_part->len >= msg->data_size);
try_assert(msg->data_size >= MESSAGE_SIZE_MIN && msg->data_size <= MESSAGE_SIZE_MAX);
try_assert(msg->id > 0);
try_assert(msg->sender_id > 0);
try_assert(msg->timestamp.d.year > 2024);
memcpy(msg_content.data, block_unread_part->data, msg->data_size);
block_unread_part->data += msg->data_size;
block_unread_part->len -= msg->data_size;
u32 offset_increment = sizeof(MessageMeta) + msg->data_size;
Return RESULT_VALUE(u, offset_increment);
}
void SendMessageRequest_construct(SendMessageRequest *ptr, PacketHeader *header,
i64 channel_id, u16 data_size)
{
_PacketHeader_construct(SendMessageRequest);
zeroStruct(ptr);
ptr->channel_id = channel_id;
ptr->data_size = data_size;
}
void SendMessageResponse_construct(SendMessageResponse *ptr, PacketHeader *header,
i64 message_id, DateTime timestamp)
{
_PacketHeader_construct(SendMessageResponse);
zeroStruct(ptr);
ptr->message_id = message_id;
ptr->timestamp = timestamp;
}
void GetMessageBlockRequest_construct(GetMessageBlockRequest *ptr, PacketHeader *header,
i64 channel_id, i64 first_message_id, u32 message_count)
{
_PacketHeader_construct(GetMessageBlockRequest);
zeroStruct(ptr);
ptr->channel_id = channel_id;
ptr->first_message_id = first_message_id;
ptr->message_count = message_count;
}
void GetMessageBlockResponse_construct(GetMessageBlockResponse *ptr, PacketHeader *header,
MessageBlockMeta* block_meta)
{
_PacketHeader_construct(GetMessageBlockResponse);
zeroStruct(ptr);
memcpy(&ptr->block_meta, block_meta, sizeof(MessageBlockMeta));
}