Skip to content

Commit 5f27776

Browse files
committed
Created TelnetServerLibrary project and moved files into it.
Created interfaces.
1 parent 7267b04 commit 5f27776

File tree

8 files changed

+221
-120
lines changed

8 files changed

+221
-120
lines changed

TelnetServer.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1212
TelnetServer\README.md = TelnetServer\README.md
1313
EndProjectSection
1414
EndProject
15+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelnetServerLibrary", "TelnetServerLibrary\TelnetServerLibrary.csproj", "{AA4894D1-2A50-4327-85E9-4737E3B782F6}"
16+
EndProject
1517
Global
1618
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1719
Debug|Any CPU = Debug|Any CPU
@@ -22,6 +24,10 @@ Global
2224
{05317095-0AD5-4EB4-8967-42FA558E74D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
2325
{05317095-0AD5-4EB4-8967-42FA558E74D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
2426
{05317095-0AD5-4EB4-8967-42FA558E74D1}.Release|Any CPU.Build.0 = Release|Any CPU
27+
{AA4894D1-2A50-4327-85E9-4737E3B782F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
28+
{AA4894D1-2A50-4327-85E9-4737E3B782F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
29+
{AA4894D1-2A50-4327-85E9-4737E3B782F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
30+
{AA4894D1-2A50-4327-85E9-4737E3B782F6}.Release|Any CPU.Build.0 = Release|Any CPU
2531
EndGlobalSection
2632
GlobalSection(SolutionProperties) = preSolution
2733
HideSolutionNode = FALSE

TelnetServer/Program.cs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
using System;
22
using System.Net;
3-
3+
using TelnetServerLibrary;
4+
using TelnetServerLibrary.Models;
45

56
namespace TelnetServer
67
{
78
public class Program
89
{
9-
private static readonly Server s_server = new Server(IPAddress.Any);
10+
private static readonly ITelnetServer s_server = new Server(IPAddress.Any);
1011

1112
static void Main(string[] args)
1213
{
@@ -17,62 +18,72 @@ static void Main(string[] args)
1718

1819
s_server.Start();
1920

20-
Console.WriteLine($"SERVER STARTED ON: {DateTime.Now} (IP {IPAddress.Any})");
21+
Console.WriteLine($"SERVER STARTED AT: {DateTime.Now} (IP {IPAddress.Any})");
22+
Console.WriteLine("Type 'Q' to quit or 'B' to broadcast a message.");
2123

22-
char read = Console.ReadKey(true).KeyChar;
24+
ConsoleKey read = ConsoleKey.NoName;
2325

2426
do
2527
{
26-
if (read.Equals('b'))
28+
if (read == ConsoleKey.B)
29+
{
30+
Console.WriteLine("Enter broadcast message:");
2731
s_server.SendMessageToAll(Console.ReadLine());
28-
} while ((read = Console.ReadKey(true).KeyChar) != 'q');
32+
}
33+
} while ((read = Console.ReadKey(true).Key) != ConsoleKey.Q);
2934

35+
Console.WriteLine($"SERVER STOPPED AT {DateTime.Now}");
3036
s_server.Stop();
3137
s_server.Dispose();
3238
}
3339

34-
private static void ClientConnected(Client client)
40+
private static void ClientConnected(object sender, IClientModel client)
3541
{
3642
Console.WriteLine("CONNECTED: " + client);
37-
s_server.SendMessageToClient(client, $"Telnet Server{Environment.NewLine}Login: ");
43+
s_server.SendMessageToClient(client, $"Telnet Server{Server.CRLF}Login: ");
3844
}
3945

40-
private static void ClientDisconnected(Client client) => Console.WriteLine("DISCONNECTED: " + client);
46+
private static void ClientDisconnected(object sender, IClientModel client) => Console.WriteLine("DISCONNECTED: " + client);
4147

42-
private static void ConnectionBlocked(IPEndPoint? endPoint) =>
48+
private static void ConnectionBlocked(object sender, IPEndPoint? endPoint) =>
4349
Console.WriteLine(string.Format($"BLOCKED: {endPoint?.Address}:{endPoint?.Port} at {DateTime.Now}"));
4450

45-
private static void MessageReceived(Client client, string message)
51+
private static void MessageReceived(object sender, MessageReceivedEventArgs args)
4652
{
47-
if (client.CurrentStatus != CLIENT_STATUS.LOGGED_IN)
53+
if (args.ClientInstance.CurrentStatus != CLIENT_STATUS.LOGGED_IN)
4854
{
49-
HandleLogin(client, message);
55+
HandleLogin(args.ClientInstance, args.ReceivedData);
5056
return;
5157
}
5258

53-
Console.WriteLine("MESSAGE: " + message);
59+
Console.WriteLine("MESSAGE: " + args.ReceivedData);
5460

55-
if (message.Equals("kickmyass") || message.Equals("logout") || message.Equals("exit"))
56-
{
57-
s_server.SendMessageToClient(client, Environment.NewLine + Server.CURSOR);
58-
s_server.KickClient(client);
59-
}
60-
else if (message.Equals("clear"))
61+
switch (args.ReceivedData)
6162
{
62-
s_server.ClearClientScreen(client);
63-
s_server.SendMessageToClient(client, Server.CURSOR);
63+
case "q":
64+
case "quit":
65+
case "lo":
66+
case "logout":
67+
case "exit":
68+
s_server.KickClient(args.ClientInstance);
69+
break;
70+
case "clear":
71+
s_server.ClearClientScreen(args.ClientInstance);
72+
s_server.SendMessageToClient(args.ClientInstance, Server.CURSOR);
73+
break;
74+
default:
75+
s_server.SendMessageToClient(args.ClientInstance, Server.CRLF + Server.CURSOR);
76+
break;
6477
}
65-
else
66-
s_server.SendMessageToClient(client, Environment.NewLine + Server.CURSOR);
6778
}
6879

69-
private static void HandleLogin(Client client, string message)
80+
private static void HandleLogin(IClientModel client, string message)
7081
{
7182
if (client.CurrentStatus == CLIENT_STATUS.GUEST)
7283
{
7384
if (message.Equals("root"))
7485
{
75-
s_server.SendMessageToClient(client, Environment.NewLine + "Password: ");
86+
s_server.SendMessageToClient(client, Server.CRLF + "Password: ");
7687
client.CurrentStatus = CLIENT_STATUS.AUTHENTICATING;
7788
}
7889
else
@@ -83,7 +94,8 @@ private static void HandleLogin(Client client, string message)
8394
if (message.Equals("r00t"))
8495
{
8596
s_server.ClearClientScreen(client);
86-
s_server.SendMessageToClient(client, $"Successfully authenticated.{Environment.NewLine}{Server.CURSOR}");
97+
s_server.SendMessageToClient(client, $"Successfully authenticated. There are {s_server.ConnectionCount - 1} other users online.");
98+
s_server.SendMessageToClient(client, Server.CRLF + Server.CURSOR);
8799
client.CurrentStatus = CLIENT_STATUS.LOGGED_IN;
88100
}
89101
else

TelnetServer/TelnetServer.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@
66
<Nullable>enable</Nullable>
77
</PropertyGroup>
88

9+
<ItemGroup>
10+
<ProjectReference Include="..\TelnetServerLibrary\TelnetServerLibrary.csproj" />
11+
</ItemGroup>
12+
913
</Project>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#nullable enable
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Net;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using TelnetServerLibrary.Models;
9+
10+
namespace TelnetServerLibrary
11+
{
12+
public sealed class MessageReceivedEventArgs : EventArgs
13+
{
14+
public IClientModel ClientInstance { get; set; }
15+
public string ReceivedData { get; set; }
16+
}
17+
18+
public interface ITelnetServer : IDisposable
19+
{
20+
event EventHandler<IClientModel> ClientConnected;
21+
event EventHandler<IClientModel> ClientDisconnected;
22+
event EventHandler<IPEndPoint> ConnectionBlocked;
23+
event EventHandler<MessageReceivedEventArgs> MessageReceived;
24+
25+
bool AcceptConnections { get; }
26+
int ConnectionCount { get; }
27+
void ClearClientScreen(IClientModel client);
28+
void KickClient(IClientModel client);
29+
void SendMessageToAll(string? message);
30+
void SendMessageToClient(IClientModel client, string? message);
31+
void Start();
32+
void Stop();
33+
}
34+
}
Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,40 @@
1+
#nullable enable
12
using System;
23
using System.Net;
4+
using TelnetServerLibrary.Models;
35

46

5-
namespace TelnetServer
7+
namespace TelnetServerLibrary
68
{
7-
public enum CLIENT_STATUS
8-
{
9-
/// <summary>
10-
/// Unauthenticated client.
11-
/// </summary>
12-
GUEST = 0,
13-
/// <summary>
14-
/// Client is authenticating.
15-
/// </summary>
16-
AUTHENTICATING = 1,
17-
/// <summary>
18-
/// Client is logged in.
19-
/// </summary>
20-
LOGGED_IN = 2
21-
}
22-
23-
public class Client
9+
internal sealed class ClientModel : IClientModel
2410
{
2511
#region Class fields
2612
/// <summary>
2713
/// Client's identifier.
2814
/// </summary>
29-
internal uint ClientID { get; set; }
15+
public uint ClientID { get; private set; }
3016

3117
/// <summary>
3218
/// Connection datetime.
3319
/// </summary>
34-
private readonly DateTime m_connectedAt;
20+
internal DateTime ConnectTime { get; private set; }
21+
22+
/// <summary>
23+
/// Last time client had activity.
24+
/// </summary>
25+
internal DateTime LastActivity { get; private set; }
3526
#endregion
3627

3728
/// <summary>
38-
/// Initialize a new instance of the <see cref="Client"/> class.
29+
/// Initialize a new instance of the <see cref="ClientModel"/> class.
3930
/// </summary>
4031
/// <param name="clientId">The client's identifier.</param>
4132
/// <param name="remoteAddress">The remote address.</param>
42-
public Client(uint clientId, IPEndPoint remoteAddress)
33+
internal ClientModel(uint clientId, IPEndPoint remoteAddress)
4334
{
4435
ClientID = clientId;
4536
RemoteAddress = remoteAddress;
46-
m_connectedAt = DateTime.Now;
37+
ConnectTime = DateTime.Now;
4738
CurrentStatus = CLIENT_STATUS.GUEST;
4839
ReceivedData = string.Empty;
4940
}
@@ -58,28 +49,36 @@ public Client(uint clientId, IPEndPoint remoteAddress)
5849
/// Get or set the client's current status.
5950
/// </summary>
6051
/// <returns>The client's status.</returns>
61-
public CLIENT_STATUS CurrentStatus { get; internal set; }
52+
public CLIENT_STATUS CurrentStatus { get; set; }
6253

6354
/// <summary>
6455
/// Get or set the client's last received data.
6556
/// </summary>
66-
public string ReceivedData { get; internal set; } = string.Empty;
57+
internal string ReceivedData { get; set; } = string.Empty;
6758

6859
/// <summary>
6960
/// Append a string to the client's last received data.
7061
/// </summary>
7162
/// <param name="dataToAppend">The data to append.</param>
72-
public void AppendReceivedData(string dataToAppend) => ReceivedData += dataToAppend;
63+
internal void AppendReceivedData(string dataToAppend)
64+
{
65+
ReceivedData += dataToAppend;
66+
LastActivity = DateTime.Now;
67+
}
7368

7469
/// <summary>
7570
/// Remove the last character from the client's last received data.
7671
/// </summary>
77-
public void RemoveLastCharacterReceived() => ReceivedData = ReceivedData[0..^1];
72+
internal void RemoveLastCharacterReceived()
73+
{
74+
ReceivedData = ReceivedData[0..^1];
75+
LastActivity = DateTime.Now;
76+
}
7877

7978
public override string ToString()
8079
{
8180
string ip = string.Format($"{RemoteAddress.Address}:{RemoteAddress.Port}");
82-
string res = string.Format($"Client #{ClientID} (From: {ip}, Status: {CurrentStatus}, Connected at: {m_connectedAt})");
81+
string res = string.Format($"Client #{ClientID} (From: {ip}, Status: {CurrentStatus}, Connected at: {ConnectTime})");
8382
return res;
8483
}
8584
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Net;
4+
using System.Text;
5+
6+
namespace TelnetServerLibrary.Models
7+
{
8+
public enum CLIENT_STATUS
9+
{
10+
/// <summary>
11+
/// Unauthenticated client.
12+
/// </summary>
13+
GUEST = 0,
14+
/// <summary>
15+
/// Client is authenticating.
16+
/// </summary>
17+
AUTHENTICATING = 1,
18+
/// <summary>
19+
/// Client is logged in.
20+
/// </summary>
21+
LOGGED_IN = 2
22+
}
23+
24+
public interface IClientModel
25+
{
26+
uint ClientID { get; }
27+
IPEndPoint RemoteAddress { get; }
28+
CLIENT_STATUS CurrentStatus { get; set; }
29+
string ToString();
30+
}
31+
}

0 commit comments

Comments
 (0)