238 lines
7.1 KiB
C
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));
|
|
}
|