119 lines
3.3 KiB
C#
119 lines
3.3 KiB
C#
|
using SharpChat.Protocol.IRC.Replies;
|
|||
|
using SharpChat.Protocol.IRC.ServerCommands;
|
|||
|
using SharpChat.Protocol.IRC.Users;
|
|||
|
using SharpChat.Sessions;
|
|||
|
using SharpChat.Users;
|
|||
|
using System;
|
|||
|
using System.Net;
|
|||
|
using System.Net.Sockets;
|
|||
|
using System.Text;
|
|||
|
|
|||
|
namespace SharpChat.Protocol.IRC {
|
|||
|
public class IRCConnection : IConnection {
|
|||
|
public const int ID_LENGTH = 16;
|
|||
|
|
|||
|
public string ConnectionId { get; }
|
|||
|
public IPAddress RemoteAddress { get; }
|
|||
|
public bool IsSecure { get; }
|
|||
|
|
|||
|
public bool IsAvailable => Socket.Connected;
|
|||
|
|
|||
|
public Socket Socket { get; }
|
|||
|
private readonly object Sync = new();
|
|||
|
|
|||
|
public bool IsAuthenticating { get; set; }
|
|||
|
public bool HasAuthenticated { get; set; }
|
|||
|
public string Password { get; set; }
|
|||
|
|
|||
|
public DateTimeOffset LastPing { get; set; }
|
|||
|
|
|||
|
private IRCServer Server { get; }
|
|||
|
|
|||
|
public ISession Session { get; set; }
|
|||
|
|
|||
|
public IRCConnection(IRCServer server, Socket sock) {
|
|||
|
Socket = sock ?? throw new ArgumentNullException(nameof(sock));
|
|||
|
Server = server ?? throw new ArgumentNullException(nameof(server));
|
|||
|
ConnectionId = @"IRC!" + RNG.NextString(ID_LENGTH);
|
|||
|
RemoteAddress = sock.RemoteEndPoint is IPEndPoint ipep ? ipep.Address : IPAddress.None;
|
|||
|
}
|
|||
|
|
|||
|
public void SendCommand(IServerCommand command) {
|
|||
|
StringBuilder sb = new();
|
|||
|
|
|||
|
// Sender
|
|||
|
sb.Append(IRCServer.PREFIX);
|
|||
|
IUser sender = command.Sender;
|
|||
|
if(sender != null) {
|
|||
|
sb.Append(sender.GetIRCName());
|
|||
|
sb.Append('!');
|
|||
|
sb.Append(sender.UserName);
|
|||
|
sb.Append('@');
|
|||
|
}
|
|||
|
sb.Append(Server.ServerHost);
|
|||
|
sb.Append(' ');
|
|||
|
|
|||
|
// Command
|
|||
|
sb.Append(command.CommandName);
|
|||
|
sb.Append(' ');
|
|||
|
|
|||
|
// Contents
|
|||
|
sb.Append(command.GetLine());
|
|||
|
sb.Append(IServerCommand.CRLF);
|
|||
|
|
|||
|
Send(sb);
|
|||
|
}
|
|||
|
|
|||
|
public void SendReply(IReply reply) {
|
|||
|
StringBuilder sb = new();
|
|||
|
|
|||
|
// Server
|
|||
|
sb.Append(IRCServer.PREFIX);
|
|||
|
sb.Append(Server.ServerHost);
|
|||
|
sb.Append(' ');
|
|||
|
|
|||
|
// Reply code
|
|||
|
sb.AppendFormat(@"{0:000}", reply.ReplyCode);
|
|||
|
sb.Append(' ');
|
|||
|
|
|||
|
// Receiver
|
|||
|
if(Session == null)
|
|||
|
sb.Append('-');
|
|||
|
else
|
|||
|
sb.Append(Session.User.GetIRCName());
|
|||
|
sb.Append(' ');
|
|||
|
|
|||
|
// Contents
|
|||
|
sb.Append(reply.GetLine());
|
|||
|
sb.Append(IReply.CRLF);
|
|||
|
|
|||
|
Send(sb);
|
|||
|
}
|
|||
|
|
|||
|
public int Receive(byte[] buffer) {
|
|||
|
lock(Sync)
|
|||
|
return Socket.Receive(buffer);
|
|||
|
}
|
|||
|
|
|||
|
private int Send(object obj) {
|
|||
|
lock(Sync)
|
|||
|
return Socket.Send(Encoding.UTF8.GetBytes(obj.ToString()));
|
|||
|
}
|
|||
|
|
|||
|
public void Close() {
|
|||
|
lock(Sync) {
|
|||
|
Password = null;
|
|||
|
|
|||
|
try {
|
|||
|
Socket.Shutdown(SocketShutdown.Both);
|
|||
|
} finally {
|
|||
|
Socket.Dispose();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString()
|
|||
|
=> $@"C#{ConnectionId}";
|
|||
|
}
|
|||
|
}
|