1
0
mirror of https://github.com/deavminet/dnetd synced 2024-09-21 09:43:37 +02:00
dnetd_old/source/dnetd/dchannel.d

306 lines
5.8 KiB
D
Raw Normal View History

2020-09-23 18:52:11 +02:00
/**
* DChannel
*
* Represents a channel and its
* associated information such
* as its name, topic, members
*/
module dnetd.dchannel;
import dnetd.dconnection : DConnection;
import core.sync.mutex : Mutex;
2020-09-23 19:39:16 +02:00
import std.conv : to;
import std.stdio : writeln;
2020-09-23 18:52:11 +02:00
public class DChannel
{
/**
* Channel information
*/
private string name;
//private string topic;
/**
* Users in this channel
*/
private DConnection[] members;
private Mutex memberLock;
2020-09-23 18:52:11 +02:00
this(string name)
{
/* Initialize the lock */
memberLock = new Mutex();
this.name = name;
2020-09-23 18:52:11 +02:00
}
public string getName()
{
return name;
}
/**
* Joins the given client to this channel
*/
2020-09-25 19:30:45 +02:00
public bool join(DConnection client)
{
/* Send a message stating the user has joined (TODO: This should be done later, possibly, how defensive should we program) */
broadcastJoin(client);
/* Lock the members list */
memberLock.lock();
2020-09-25 19:30:45 +02:00
/**
* Don't allow the user to join a channel he
* is already in
*/
bool isPresent = false;
foreach(DConnection member; members)
{
if(client is member)
{
isPresent = true;
break;
}
}
/**
* TODO: Error handling if the calling DConnection fails midway
* and doesn't unlock it
*/
2020-09-25 19:30:45 +02:00
/* Only join channel if not already joined */
if(!isPresent)
{
/* Add the client */
members ~= client;
}
/* Unlock the members list */
memberLock.unlock();
2020-09-25 19:30:45 +02:00
return isPresent;
}
2020-09-26 15:05:52 +02:00
/**
* Returns the number of members in this channel
*/
public ulong getMemberCount()
{
/* The count of members */
ulong memberCount;
/* Lock the members list */
memberLock.lock();
/* Get the member count */
memberCount = members.length;
/* Unlock the members list */
memberLock.unlock();
return memberCount;
}
public bool isMember(DConnection client)
{
/* Whether or not you are a member */
bool isMem;
/* Lock the members list */
memberLock.lock();
/* CHeck if you are in this channel */
foreach(DConnection member; members)
{
if(member is client)
{
isMem = true;
break;
}
}
/* Unlock the members list */
memberLock.unlock();
return isMem;
}
/**
* Removes the given client from this channel
*/
public void leave(DConnection client)
2020-09-23 18:52:11 +02:00
{
/* Lock the members list */
memberLock.lock();
/* TODO: Get a better implementation */
/* Create a new list without the `client` */
DConnection[] newMembers;
foreach(DConnection currentMember; members)
{
if(!(currentMember is client))
{
newMembers ~= currentMember;
}
}
/* Set it as the new list */
members = newMembers;
/* Unlock the members list */
memberLock.unlock();
/* Send broadcast leave message */
broadcastLeave(client);
}
/**
* Sends a message to all users of this
* channel that the given user has left
*/
private void broadcastLeave(DConnection left)
{
/* Lock the members list */
memberLock.lock();
/* Send left message here */
foreach(DConnection currentMember; members)
{
sendLeaveMessage(currentMember, left);
}
/* Unlock the members list */
memberLock.unlock();
2020-09-23 18:52:11 +02:00
}
/**
* Sends a message to the user stating the given
* (other) user has left the channel
*/
private void sendLeaveMessage(DConnection member, DConnection left)
{
/* The protocol data to send */
byte[] protocolData;
/* Set the notificaiton type to `channel status` */
protocolData ~= [1];
/* Set the sub-type to leave */
protocolData ~= [0];
/* Set the channel notificaiton type to `member leave` */
protocolData ~= cast(byte[])left.getUsername();
/* Write the notification */
member.writeSocket(0, protocolData);
}
/**
* Sends a message to all users of this
* channel that the given user has joined
*/
private void broadcastJoin(DConnection joined)
{
/* Lock the members list */
memberLock.lock();
/* Send join message here */
foreach(DConnection currentMember; members)
{
sendJoinMessage(currentMember, joined);
}
/* Unlock the members list */
memberLock.unlock();
}
/**
* Sends a message to the user stating the given
* (other) user has joined the channel
*/
private void sendJoinMessage(DConnection member, DConnection joined)
{
/* The protocol data to send */
byte[] protocolData;
/* Set the notificaiton type to `channel status` */
protocolData ~= [1];
/* Set the sub-type to join */
protocolData ~= [1];
/* Set the channel notificaiton type to `member join` */
protocolData ~= cast(byte[])joined.getUsername();
/* Write the notification */
member.writeSocket(0, protocolData);
}
public bool sendMessage(DConnection sender, string message)
{
bool status;
/* The protocol data to send */
byte[] msg;
/* Set the notificaiton type to `message notification` */
msg ~= [0];
2020-09-25 19:30:45 +02:00
/**
* Format
* 0 - dm
* 1 - channel (this case)
* byte length of name of channel/person (dm case)
* message-bytes
*/
msg ~= [cast(byte)1,(cast(byte)sender.getUsername().length)]~cast(byte[])sender.getUsername()~cast(byte[])message;
/* Send the message to everyone else in the channel */
foreach(DConnection member; members)
{
/* Skip sending to self */
if(!(member is sender))
{
/* Send the message */
writeln("Delivering message '"~message~"' for channel '"~name~"' to user '"~member.getUsername()~"'...");
status = member.writeSocket(0, msg);
if(status)
{
writeln("Delivered message '"~message~"' for channel '"~name~"' to user '"~member.getUsername()~"'!");
}
else
{
writeln("Failed to deliver message '"~message~"' for channel '"~name~"' to user '"~member.getUsername()~"'!");
}
}
}
/* TODO: Don't, retur true */
return true;
}
public override string toString()
{
2020-09-23 21:40:22 +02:00
string toStr;
/* Lock the members list */
memberLock.lock();
toStr = "DChannel [Name: "~name~", Members: "~to!(string)(members)~"]";
/* Unlock the members list */
memberLock.unlock();
return toStr;
}
2020-09-23 18:52:11 +02:00
}