Skip to content

Commit

Permalink
Implement USER/PASS/NICK command.
Browse files Browse the repository at this point in the history
Fix SharedPtr destructor bug.
  • Loading branch information
Ria9993 committed Apr 8, 2024
1 parent fed409a commit b491d7a
Show file tree
Hide file tree
Showing 12 changed files with 422 additions and 107 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
"numeric": "cpp",
"random": "cpp",
"numbers": "cpp",
"cinttypes": "cpp"
"cinttypes": "cpp",
"queue": "cpp"
},
"C_Cpp.vcFormat.indent.preserveComments": true
}
13 changes: 8 additions & 5 deletions Source/Core/FixedMemoryPool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@ class FixedMemoryPool

~FixedMemoryPool()
{
// Release data that is not deallocated
for (size_t i = 0; i < mCapacity; ++i)
if (mCursor != 0)
{
T* ptr = (T*)(mMemoryRaw + i * sizeof(T));
ptr->~T(); //< Call the destructor
CoreLog("[FixedMemoryPool] Memory Leak Detected. Cursor: " + ValToString(mCursor));
}

delete[] mMemoryRaw;
Expand All @@ -53,7 +51,7 @@ class FixedMemoryPool
const size_t idx = mIndices[mCursor++];
const char* ptrRaw = mMemoryRaw + (idx * sizeof(T));

CoreLog("[FixedMemoryPool] Allocate: " + ValToStringByHex(ptrRaw) + " idx: " + ValToString(idx));
CoreLog("[FixedMemoryPool] Allocate: " + ValToStringByHex(reinterpret_cast<const void*>(ptrRaw)) + " idx: " + ValToString(idx));

return (T*)ptrRaw;
}
Expand Down Expand Up @@ -82,6 +80,11 @@ class FixedMemoryPool
return mCursor == mCapacity;
}

FORCEINLINE bool IsInPool(const void* ptr) const
{
return ptr >= mMemoryRaw && ptr < mMemoryRaw + mCapacity * sizeof(T);
}

private:
enum { CAPACITY = MemoryPageCapacity * PAGE_SIZE / sizeof(T) }; //< Floor to the sizeof(T)

Expand Down
64 changes: 38 additions & 26 deletions Source/Core/SharedPtr.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

// DEBUG
#include <typeinfo>

#include "Core/MacroDefines.hpp"
#include "Core/AttributeDefines.hpp"
#include "Core/VariableMemoryPool.hpp"
Expand All @@ -24,7 +27,7 @@ namespace detail
template <typename T>
struct ControlBlock
{
ALIGNAS(ALIGNOF(T)) T data;
ALIGNAS(ALIGNOF(T)) char data[sizeof(T)];

size_t StrongRefCount;
size_t WeakRefCount;
Expand All @@ -37,7 +40,7 @@ struct ControlBlock
{
}

virtual ~ControlBlock()
FORCEINLINE ~ControlBlock()
{
}

Expand All @@ -47,28 +50,40 @@ struct ControlBlock
* Overload new and delete operator with memory pool for memory management.
*/
///@{
NODISCARD FORCEINLINE void* operator new (size_t size)
{
Assert(size == sizeof(ControlBlock));
return reinterpret_cast<void*>(sMemoryPool.Allocate());
}

NODISCARD FORCEINLINE void* operator new (size_t size, void* ptr)
{
Assert(size == sizeof(ControlBlock));
return ptr;
}
// NODISCARD FORCEINLINE void* operator new (size_t size)
// {
// Assert(size == sizeof(ControlBlock));
// return reinterpret_cast<void*>(sMemoryPool.Allocate());
// }

// NODISCARD FORCEINLINE void* operator new (size_t size, void* ptr)
// {
// Assert(size == sizeof(ControlBlock));
// return ptr;
// }

FORCEINLINE void operator delete (void* ptr)
{
sMemoryPool.Deallocate(reinterpret_cast<ControlBlock*>(ptr));
}
// FORCEINLINE void operator delete (void* ptr)
// {
// sMemoryPool.Deallocate(reinterpret_cast<ControlBlock*>(ptr));
// }

// FORCEINLINE void operator delete (void* ptr, void* place)
// {
// Assert(false);
// (void)place;
// (void)ptr;
// }
///@}

FORCEINLINE void operator delete (void* ptr, void* place)
{
(void)place;
(void)ptr;
}
private:
/** @name new[]/delete[] operators
*
* Use new/delete operator instead.
*/
///@{
UNUSED NORETURN FORCEINLINE void* operator new[] (size_t size);

UNUSED NORETURN FORCEINLINE void operator delete[] (void* ptr);
///@}

private:
Expand Down Expand Up @@ -234,7 +249,6 @@ class SharedPtr
: mControlBlock(controlBlock)
{
Assert(mControlBlock != NULL);
Assert(mControlBlock->bExpired == false);

if (mControlBlock != NULL)
{
Expand Down Expand Up @@ -312,20 +326,18 @@ class SharedPtr
{
if (mControlBlock != NULL)
{
CoreLog("SharedPtr Reset(): StrongRefCount: " + ValToString(mControlBlock->StrongRefCount) + " WeakRefCount: " + ValToString(mControlBlock->WeakRefCount));
Assert(mControlBlock->StrongRefCount > 0);
mControlBlock->StrongRefCount -= 1;
if (mControlBlock->StrongRefCount == 0)
{
CoreLog("SharedPtr Reset(): Call Destructor");
T* ptrData = reinterpret_cast<T*>(&mControlBlock->data);
ptrData->~T();

mControlBlock->bExpired = true;

if (mControlBlock->WeakRefCount == 0)
{
CoreLog("SharedPtr Reset(): Delete ControlBlock");
CoreLog("SharedPtr Reset(): Delete ControlBlock" + std::string(typeid(T).name()));
delete mControlBlock;
}
}
Expand Down
1 change: 1 addition & 0 deletions Source/Core/WeakPtr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class WeakPtr
{
if (mControlBlock->StrongRefCount == 0)
{
CoreLog("WeakPtr Reset(): Delete ControlBlock" + std::string(typeid(T).name()));
delete mControlBlock;
}
}
Expand Down
5 changes: 5 additions & 0 deletions Source/Server/ClientCommand/ClientCommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ namespace IRC

} // namespace irc

/**
* @def IRC_CLIENT_COMMAND_X
* @brief Macro for defining a client command.
*/
#define IRC_CLIENT_COMMAND_LIST \
IRC_CLIENT_COMMAND_X(PASS) \
IRC_CLIENT_COMMAND_X(NICK) \
IRC_CLIENT_COMMAND_X(USER)

48 changes: 42 additions & 6 deletions Source/Server/ClientCommand/NICK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ EIrcErrorCode Server::executeClientCommand_NICK(SharedPtr<ClientControlBlock> cl
// No nickname given
if (arguments.size() == 0)
{
MakeIrcReplyMsg_ERR_NEEDMOREPARAMS(replyCode, replyMsg, mServerName, commandName);
MakeIrcReplyMsg_ERR_NONICKNAMEGIVEN(replyCode, replyMsg, mServerName);
goto SEND_REPLY;
}

Expand All @@ -31,6 +31,9 @@ EIrcErrorCode Server::executeClientCommand_NICK(SharedPtr<ClientControlBlock> cl
goto SEND_REPLY;
}
}

// Empty nickname
Assert(arguments[0][0] != '\0');

// Nickname is already in use
if (mNickToClientMap.find(arguments[0]) != mNickToClientMap.end())
Expand All @@ -39,12 +42,45 @@ EIrcErrorCode Server::executeClientCommand_NICK(SharedPtr<ClientControlBlock> cl
goto SEND_REPLY;
}

// Update nickname
mNickToClientMap.erase(client->Nickname);
mNickToClientMap.insert(std::make_pair(arguments[0], client));
client->Nickname = arguments[0];
// Try to register the client
if (!client->bRegistered)
{
client->Nickname = arguments[0];
registerClient(client);

return IRC_SUCCESS;
}
// Update the nickname in Server, Channels
else
{
const std::string oldNickname = client->Nickname;
const std::string newNickname = arguments[0];
client->Nickname = newNickname;
mNickToClientMap.erase(oldNickname);
mNickToClientMap.insert(std::make_pair(newNickname, client));

for (std::map< std::string, WeakPtr< ChannelControlBlock > >::iterator it = client->Channels.begin(); it != client->Channels.end(); ++it)
{
SharedPtr<ChannelControlBlock> channel = it->second.Lock();
if (channel != NULL)
{
channel->Clients.erase(client->Nickname);
channel->Clients.insert(std::make_pair(client->Nickname, client));
}
}

// Send NICK message to all channels the client is in
const std::string nickMsgStr = ":" + oldNickname + " NICK " + newNickname;
SharedPtr<MsgBlock> nickMsg = MakeShared<MsgBlock>(nickMsgStr);
sendMsgToConnectedChannels(client, nickMsg);

// Send NICK message to the origin client itself
sendMsgToClient(client, nickMsg);

return IRC_SUCCESS;
}


// Send NICK message to all channels the client is in

SEND_REPLY:
sendMsgToClient(client, MakeShared<MsgBlock>(replyMsg));
Expand Down
26 changes: 23 additions & 3 deletions Source/Server/ClientCommand/PASS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,36 @@ namespace IRC

EIrcErrorCode Server::executeClientCommand_PASS(SharedPtr<ClientControlBlock> client, const std::vector<const char*>& arguments)
{
const std::string commandName("PASS");
EIrcReplyCode replyCode;
std::string replyMsg;

if (client->bExpired)
{

return IRC_SUCCESS;
}

// TODO: Implement
// Already registered
if (client->bRegistered)
{
MakeIrcReplyMsg_ERR_ALREADYREGISTRED(replyCode, replyMsg, mServerName);
sendMsgToClient(client, MakeShared<MsgBlock>(replyMsg));
}
// Need more parameters
else if (arguments.size() == 0)
{
MakeIrcReplyMsg_ERR_NEEDMOREPARAMS(replyCode, replyMsg, mServerName, commandName);
sendMsgToClient(client, MakeShared<MsgBlock>(replyMsg));
}
else
{
client->ServerPass = arguments[0];

return IRC_SUCCESS;
// Try to register the client
registerClient(client);
}

return IRC_SUCCESS;
}

}
67 changes: 67 additions & 0 deletions Source/Server/ClientCommand/USER.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <cctype>
#include "Server/Server.hpp"

namespace IRC
{

EIrcErrorCode Server::executeClientCommand_USER(SharedPtr<ClientControlBlock> client, const std::vector<const char*>& arguments)
{
const std::string commandName("USER");
EIrcReplyCode replyCode;
std::string replyMsg;

if (client->bExpired)
{
return IRC_SUCCESS;
}

// Already registered
if (client->bRegistered)
{
MakeIrcReplyMsg_ERR_ALREADYREGISTRED(replyCode, replyMsg, mServerName);
goto SEND_REPLY;
}

// Need more parameters
if (arguments.size() < 4)
{
MakeIrcReplyMsg_ERR_NEEDMOREPARAMS(replyCode, replyMsg, mServerName, commandName);
goto SEND_REPLY;
}

// Validate names
for (size_t i = 0; i < 4; i++)
{
for (const char* p = arguments[i]; *p != '\0'; p++)
{
if (isalnum(*p) == 0 && *p != '_')
{
replyMsg = "ERROR :Invalid USER arguments";
sendMsgToClient(client, MakeShared<MsgBlock>(replyMsg));
disconnectClient(client);

return IRC_SUCCESS;
}
}

// Empty name
Assert(arguments[i][0] != '\0');
}

// Set user information
// (Hostname and Servername are ignored)
client->Username = arguments[0];
client->Realname = arguments[3];

// Register the client
registerClient(client);
return IRC_SUCCESS;


SEND_REPLY:
sendMsgToClient(client, MakeShared<MsgBlock>(replyMsg));

return IRC_SUCCESS;
}

}
Loading

0 comments on commit b491d7a

Please sign in to comment.