From 8ee231d8e7a5e512a7f886df2a3f537f452e487a Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 20 Mar 2024 00:26:45 -0500 Subject: [PATCH] Add SSL support --- TwitchIrcClient/IRC/IrcConnection.cs | 32 +++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/TwitchIrcClient/IRC/IrcConnection.cs b/TwitchIrcClient/IRC/IrcConnection.cs index 2ea6cc6..e0d15cc 100644 --- a/TwitchIrcClient/IRC/IrcConnection.cs +++ b/TwitchIrcClient/IRC/IrcConnection.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; +using System.Net.Security; using System.Net.Sockets; using System.Reflection.Metadata; using System.Security.Cryptography; @@ -17,10 +18,7 @@ namespace TwitchLogger.IRC { /// /// Connects to a single Twitch chat channel via limited IRC implementation. - /// /// - /// - /// public class IrcConnection : IDisposable { public static readonly string ENDL = "\r\n"; @@ -28,6 +26,7 @@ namespace TwitchLogger.IRC public string Url { get; } public bool Connected { get; } = false; public bool TrackUsers { get; } + public bool UsesSsl { get; } //this seems to be the only concurrentcollection that allows //removing specific items protected ConcurrentDictionary UserCollection = new(); @@ -42,7 +41,8 @@ namespace TwitchLogger.IRC public event EventHandler? onUserChange; private TcpClient Client = new(); - private NetworkStream Stream => Client.GetStream(); + //private NetworkStream Stream => Client.GetStream(); + private Stream _Stream; private CancellationTokenSource TokenSource = new(); //it looks like you can't get the Token after the Source is disposed protected CancellationToken Token; @@ -51,12 +51,13 @@ namespace TwitchLogger.IRC private Task? UserUpdateTask; public IrcConnection(string url, int port, - RateLimiter? limiter = null, bool trackUsers = false) + RateLimiter? limiter = null, bool trackUsers = false, bool useSsl = false) { Url = url; Port = port; Limiter = limiter; TrackUsers = trackUsers; + UsesSsl = useSsl; Token = TokenSource.Token; if (TrackUsers) { @@ -99,6 +100,16 @@ namespace TwitchLogger.IRC await Client.ConnectAsync(Url, Port); if (!Client.Connected) return false; + if (UsesSsl) + { + var stream = new SslStream(Client.GetStream()); + await stream.AuthenticateAsClientAsync(Url); + _Stream = stream; + } + else + { + _Stream = Client.GetStream(); + } ListenerTask = Task.Run(ListenForInput, Token); UserUpdateTask = Task.Run(UpdateUsers, Token); return true; @@ -112,7 +123,8 @@ namespace TwitchLogger.IRC Limiter?.WaitForAvailable(Token); if (Token.IsCancellationRequested) return; - Stream.Write(new Span(Encoding.UTF8.GetBytes(line + ENDL))); + var bytes = Encoding.UTF8.GetBytes(line + ENDL); + _Stream.Write(bytes, 0, bytes.Length); } public void Authenticate(string? user, string? pass) { @@ -134,17 +146,17 @@ namespace TwitchLogger.IRC byte[] buffer = new byte[5 * 1024]; while (!Token.IsCancellationRequested) { - var bytesRead = await Stream.ReadAsync(buffer, 0, buffer.Length, Token); + var bytesRead = await _Stream.ReadAsync(buffer, Token); if (bytesRead > 0) onDataReceived(buffer, bytesRead); - if (!Stream.CanRead) + if (!_Stream.CanRead) return; } Token.ThrowIfCancellationRequested(); } - ConcurrentBag _JoinedUsers = []; - ConcurrentBag _LeftUsers = []; + private readonly ConcurrentBag _JoinedUsers = []; + private readonly ConcurrentBag _LeftUsers = []; private void UserJoin(Join message) { _JoinedUsers.Add(message.Username);