Connection

- Cleaned up imports
- Switched to using a switch statement for handling the different `CommandType`s
This commit is contained in:
Tristan B. Velloza Kildaire 2023-11-22 10:30:04 +02:00
parent b120ba19e4
commit c36223ac08
1 changed files with 195 additions and 146 deletions

View File

@ -8,6 +8,18 @@ import tristanable;
import renaissance.logging;
import renaissance.server.messagemanager : MessageManager, Message;
import davinci.base.components : Validatable;
import davinci.c2s.auth : AuthMessage, AuthResponse;
import davinci.c2s.generic : UnknownCommandReply;
import davinci.c2s.channels : ChannelEnumerateRequest, ChannelEnumerateReply, ChannelMembership, ChannelMessage;
import davinci.c2s.test : NopMessage;
import renaissance.server.channelmanager : ChannelManager, Channel;
import std.conv : to;
public class Connection : Thread
{
/**
@ -134,6 +146,7 @@ public class Connection : Thread
logger.dbg("Incoming message: "~baseMessage.getCommand().toString());
logger.dbg("BaseMessage type: ", baseMessage.getMessageType());
Command incomingCommand = baseMessage.getCommand();
CommandType incomingCommandType = baseMessage.getCommandType();
logger.dbg("Incoming CommandType: ", incomingCommandType);
@ -143,180 +156,216 @@ public class Connection : Thread
CommandType responseType;
Status responseStatus;
if(incomingCommandType == CommandType.NOP_COMMAND)
/**
* Perform validation before continueing
*/
if(cast(Validatable)incomingCommand)
{
import davinci.c2s.test;
logger.dbg("We got a NOP");
NopMessage nopMessage = cast(NopMessage)baseMessage.getCommand();
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.NOP_COMMAND;
responseCommand = nopMessage;
}
// Handle authentication request
else if(incomingCommandType == CommandType.AUTH_COMMAND)
{
import davinci.c2s.auth : AuthMessage, AuthResponse;
AuthMessage authMessage = cast(AuthMessage)baseMessage.getCommand();
bool status = this.associatedServer.attemptAuth(authMessage.getUsername(), authMessage.getPassword());
// TODO: This is just for testing now - i intend to have a nice auth manager
AuthResponse authResp = new AuthResponse();
if(status)
Validatable validtabaleCommand = cast(Validatable)incomingCommand;
string reason;
if(!validtabaleCommand.validate(reason))
{
authResp.good();
logger.error("Validation failed with reason: '", reason, "'");
// Save username
this.myUsername = authMessage.getUsername();
UnknownCommandReply unknownCmdReply = new UnknownCommandReply(reason);
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.UNKNOWN_COMMAND;
responseCommand = unknownCmdReply;
// TODO: Can we do this without gotos?
goto encode_n_send;
}
else
}
switch(incomingCommandType)
{
/**
* Handle NOP commands
*/
case CommandType.NOP_COMMAND:
{
authResp.bad();
}
logger.dbg("We got a NOP");
NopMessage nopMessage = cast(NopMessage)baseMessage.getCommand();
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.AUTH_RESPONSE;
responseCommand = authResp;
}
// Handle channel list requests
else if(incomingCommandType == CommandType.CHANNELS_ENUMERATE_REQ)
{
// FIXME: Figure out how we want to do auth checks
if(!isAuthd())
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.NOP_COMMAND;
responseCommand = nopMessage;
break;
}
/**
* Handle authentication request
*/
case CommandType.AUTH_COMMAND:
{
AuthMessage authMessage = cast(AuthMessage)baseMessage.getCommand();
bool status = this.associatedServer.attemptAuth(authMessage.getUsername(), authMessage.getPassword());
// TODO: This is just for testing now - i intend to have a nice auth manager
AuthResponse authResp = new AuthResponse();
if(status)
{
authResp.good();
// Save username
this.myUsername = authMessage.getUsername();
}
else
{
authResp.bad();
}
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.AUTH_RESPONSE;
responseCommand = authResp;
break;
}
import davinci.c2s.channels : ChannelEnumerateRequest, ChannelEnumerateReply;
/**
* Handle channel list requests
*/
case CommandType.CHANNELS_ENUMERATE_REQ:
{
// FIXME: Figure out how we want to do auth checks
if(!isAuthd())
{
ChannelEnumerateRequest chanEnumReq = cast(ChannelEnumerateRequest)baseMessage.getCommand();
ubyte limit = chanEnumReq.getLimit();
ulong offset = chanEnumReq.getOffset();
}
ChannelEnumerateRequest chanEnumReq = cast(ChannelEnumerateRequest)baseMessage.getCommand();
ubyte limit = chanEnumReq.getLimit();
ulong offset = chanEnumReq.getOffset();
string[] channelNames = this.associatedServer.getChannelNames(offset, limit);
ChannelEnumerateReply chanEnumRep = new ChannelEnumerateReply(channelNames);
string[] channelNames = this.associatedServer.getChannelNames(offset, limit);
ChannelEnumerateReply chanEnumRep = new ChannelEnumerateReply(channelNames);
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.CHANNELS_ENUMERATE_REP;
responseCommand = chanEnumRep;
}
// Handle channel joins
else if(incomingCommandType == CommandType.MEMBERSHIP_JOIN)
{
import davinci.c2s.channels : ChannelMembership;
import renaissance.server.channelmanager : ChannelManager, Channel;
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.CHANNELS_ENUMERATE_REP;
responseCommand = chanEnumRep;
ChannelMembership chanMemReq = cast(ChannelMembership)baseMessage.getCommand();
string channel = chanMemReq.getChannel();
break;
}
/**
* Handle channel joins
*/
case CommandType.MEMBERSHIP_JOIN:
{
ChannelMembership chanMemReq = cast(ChannelMembership)baseMessage.getCommand();
string channel = chanMemReq.getChannel();
// Join the channel
ChannelManager chanMan = this.associatedServer.getChannelManager();
bool status = chanMan.membershipJoin(channel, this.myUsername); // TODO: Handle return value
chanMemReq.replyGood();
// Join the channel
ChannelManager chanMan = this.associatedServer.getChannelManager();
bool status = chanMan.membershipJoin(channel, this.myUsername); // TODO: Handle return value
chanMemReq.replyGood();
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.MEMBERSHIP_JOIN_REP;
responseCommand = chanMemReq;
}
// Handle channel membership requests
else if(incomingCommandType == CommandType.MEMBERSHIP_LIST)
{
import davinci.c2s.channels : ChannelMembership;
import renaissance.server.channelmanager : ChannelManager, Channel;
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.MEMBERSHIP_JOIN_REP;
responseCommand = chanMemReq;
logger.error("HALO");
break;
}
/**
* Handle channel membership requests
*/
case CommandType.MEMBERSHIP_LIST:
{
ChannelMembership chanMemReq = cast(ChannelMembership)baseMessage.getCommand();
string channel = chanMemReq.getChannel();
ChannelMembership chanMemReq = cast(ChannelMembership)baseMessage.getCommand();
string channel = chanMemReq.getChannel();
// Obtain the current members
ChannelManager chanMan = this.associatedServer.getChannelManager();
string[] currentMembers;
// TODO: Handle return value
bool status = chanMan.membershipList(channel, currentMembers);
logger.dbg("Current members of '"~channel~"': ", currentMembers);
chanMemReq.listReplyGood(currentMembers);
// Obtain the current members
ChannelManager chanMan = this.associatedServer.getChannelManager();
string[] currentMembers;
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.MEMBERSHIP_LIST_REP;
responseCommand = chanMemReq;
break;
}
/**
* Handle channel leaves
*/
case CommandType.MEMBERSHIP_LEAVE:
{
ChannelMembership chanMemReq = cast(ChannelMembership)baseMessage.getCommand();
string channel = chanMemReq.getChannel();
// Join the channel
ChannelManager chanMan = this.associatedServer.getChannelManager();
bool status = chanMan.membershipLeave(channel, this.myUsername); // TODO: Handle return value
chanMemReq.replyGood();
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.MEMBERSHIP_LEAVE_REP;
responseCommand = chanMemReq;
break;
}
/**
* Handle message sending
*/
case CommandType.CHANNEL_SEND_MESSAGE:
{
ChannelMessage chanMesg = cast(ChannelMessage)baseMessage.getCommand();
// TODO: Handle return value
bool status = chanMan.membershipList(channel, currentMembers);
logger.dbg("Current members of '"~channel~"': ", currentMembers);
chanMemReq.listReplyGood(currentMembers);
// TODO: Get channel, lookup and do permission checks
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.MEMBERSHIP_LIST_REP;
responseCommand = chanMemReq;
}
// Handle channel leaves
else if(incomingCommandType == CommandType.MEMBERSHIP_LEAVE)
{
import davinci.c2s.channels : ChannelMembership;
import renaissance.server.channelmanager : ChannelManager, Channel;
ChannelMembership chanMemReq = cast(ChannelMembership)baseMessage.getCommand();
string channel = chanMemReq.getChannel();
// Join the channel
ChannelManager chanMan = this.associatedServer.getChannelManager();
bool status = chanMan.membershipLeave(channel, this.myUsername); // TODO: Handle return value
chanMemReq.replyGood();
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.MEMBERSHIP_LEAVE_REP;
responseCommand = chanMemReq;
}
// Handle message sending
else if(incomingCommandType == CommandType.CHANNEL_SEND_MESSAGE)
{
import davinci.c2s.channels : ChannelMessage;
import renaissance.server.channelmanager : ChannelManager, Channel;
ChannelMessage chanMesg = cast(ChannelMessage)baseMessage.getCommand();
// TODO: Get channel, lookup and do permission checks
// TODO: Use a messagemanager thing here
MessageManager mesgMan = this.associatedServer.getMessageManager();
// TODO: Use a messagemanager thing here
MessageManager mesgMan = this.associatedServer.getMessageManager();
// TODO: Check multiple recipients
string[] recipients = chanMesg.getRecipients();
foreach(string to; recipients)
{
Message message;
message.setBody(chanMesg.getMessage());
message.setFrom(this.myUsername);
message.setDestination(to);
// TODO: Check multiple recipients
string[] recipients = chanMesg.getRecipients();
foreach(string to; recipients)
{
Message message;
message.setBody(chanMesg.getMessage());
message.setFrom(this.myUsername);
message.setDestination(to);
logger.dbg("Sending message: ", message);
mesgMan.sendq(message);
logger.dbg("Sending message: ", message);
mesgMan.sendq(message);
}
// TODO: Set this ONLY if we succeeeded in delivery
chanMesg.messageDelivered();
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.SEND_CHANNEL_MESG_REP;
responseCommand = chanMesg;
break;
}
/**
* Anything else is an unknown
* command, therefore generate
* an error reply
*/
default:
{
logger.warn("Received unsupported message type", baseMessage);
UnknownCommandReply unknownCmdReply = new UnknownCommandReply("Command with type number: "~to!(string)(cast(ulong)incomingCommandType));
// TODO: Set this ONLY if we succeeeded in delivery
chanMesg.messageDelivered();
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.UNKNOWN_COMMAND;
responseCommand = unknownCmdReply;
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.SEND_CHANNEL_MESG_REP;
responseCommand = chanMesg;
}
// Unsupported type for server
else
{
import davinci.c2s.generic : UnknownCommandReply;
import std.conv : to;
logger.warn("Received unsupported message type", baseMessage);
// TODO: Generate error here
UnknownCommandReply unknownCmdReply = new UnknownCommandReply("Command with type number: "~to!(string)(cast(ulong)incomingCommandType));
mType = MessageType.CLIENT_TO_SERVER;
responseType = CommandType.UNKNOWN_COMMAND;
responseCommand = unknownCmdReply;
logger.warn("We have generated err: ", responseCommand);
logger.warn("We have generated err: ", responseCommand);
break;
}
}
// Ensure a response was created
// assert(responseCommand !is null);
encode_n_send:
// Generate response
response = new BaseMessage(mType, responseType, responseCommand);