Files
EchoHub/src/EchoHub.Server.Irc/IrcClientConnection.cs
T
HueByte cb6b9d1e55 feat: Implement IRC Gateway Service and related functionality
- Add IrcGatewayService to handle IRC connections and commands.
- Create IrcMessage class for parsing IRC protocol lines.
- Implement IrcMessageFormatter for formatting messages as IRC lines.
- Define IrcNumericReply constants for IRC numeric replies.
- Add IrcOptions class for configuration settings related to IRC.
- Create IrcServiceExtensions for adding IRC services to the application.
- Refactor ChannelsController to use IChatService for broadcasting messages and channel updates.
- Update ChatHub to utilize IChatService for user connection and message handling.
- Introduce ChatService to manage chat-related operations and interactions.
- Implement SignalRBroadcaster for broadcasting messages to SignalR clients.
- Update PresenceTracker to retrieve usernames for connections.
- Modify appsettings.example.json to include IRC configuration options.
- Update solution file to include the new IRC project.
2026-02-19 11:31:20 +01:00

88 lines
2.4 KiB
C#

using System.Net.Sockets;
using System.Text;
namespace EchoHub.Server.Irc;
/// <summary>
/// Manages a single IRC client TCP connection.
/// </summary>
public sealed class IrcClientConnection : IAsyncDisposable
{
private readonly TcpClient _tcpClient;
private readonly StreamReader _reader;
private readonly StreamWriter _writer;
private readonly SemaphoreSlim _writeLock = new(1, 1);
// Connection identity
public string ConnectionId { get; } = $"irc-{Guid.NewGuid()}";
// Registration state
public string? Nickname { get; set; }
public string? Username { get; set; }
public string? RealName { get; set; }
public string? Password { get; set; }
public Guid? UserId { get; set; }
public bool IsRegistered { get; set; }
public bool IsAuthenticated { get; set; }
public bool IsSasl { get; set; }
public bool CapNegotiating { get; set; }
// Channel state
public HashSet<string> JoinedChannels { get; } = new(StringComparer.OrdinalIgnoreCase);
// Away state
public string? AwayMessage { get; set; }
public string Hostmask => $"{Nickname}!{Username ?? Nickname}@echohub";
public IrcClientConnection(TcpClient tcpClient, Stream stream)
{
_tcpClient = tcpClient;
_reader = new StreamReader(stream, Encoding.UTF8);
_writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true, NewLine = "\r\n" };
}
public async Task<string?> ReadLineAsync(CancellationToken ct)
{
try
{
return await _reader.ReadLineAsync(ct);
}
catch
{
return null;
}
}
public async Task SendAsync(string line)
{
await _writeLock.WaitAsync();
try
{
await _writer.WriteLineAsync(line);
}
catch
{
// Connection lost — swallow
}
finally
{
_writeLock.Release();
}
}
public Task SendNumericAsync(string serverName, string numeric, string target, string text)
=> SendAsync($":{serverName} {numeric} {target} {text}");
public Task SendNumericAsync(string serverName, string numeric, string text)
=> SendNumericAsync(serverName, numeric, Nickname ?? "*", text);
public async ValueTask DisposeAsync()
{
try { _tcpClient.Close(); } catch { }
_reader.Dispose();
_writer.Dispose();
_writeLock.Dispose();
}
}