Skip to content

Commit 8aa35c1

Browse files
committed
Fix decoded chars array being too small issue and switch to using StringBuilder
1 parent 6597261 commit 8aa35c1

File tree

1 file changed

+45
-46
lines changed

1 file changed

+45
-46
lines changed

Unity-Twitch-Chat/Assets/Package/Runtime/TwitchConnection.ReadThread.cs

Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,73 +3,71 @@
33
using System.Text;
44
using System.Threading;
55
using System.Net.Sockets;
6-
7-
using Random = System.Random;
6+
using System.IO;
87

98
namespace Lexone.UnityTwitchChat
109
{
1110
internal partial class TwitchConnection
1211
{
13-
private string currentRawLine;
14-
private byte[] inputBuffer;
15-
private char[] chars;
16-
private Decoder decoder = Encoding.UTF8.GetDecoder();
17-
1812
// Used to generate session based random colors for undefined users
19-
private int sessionRandom = DateTime.Now.Second;
13+
private int sessionRandom = DateTime.Now.Second;
2014

2115
private void ReadThreadLoop()
2216
{
2317
if (showThreadDebug)
2418
Debug.Log($"{Tags.thread} Read thread started");
2519

26-
Socket socket = tcpClient.Client;
27-
currentRawLine = string.Empty;
28-
inputBuffer = new byte[readBufferSize];
29-
chars = new char[readBufferSize];
30-
31-
while (ThreadsRunning)
20+
using (NetworkStream stream = tcpClient.GetStream())
3221
{
33-
if (!CheckConnection(socket))
34-
{
35-
// Sometimes, right after a new TcpClient is created, the socket says
36-
// it has been shutdown. This catches that case and attempts reconnecting.
37-
alertQueue.Enqueue(IRCReply.CONNECTION_INTERRUPTED);
38-
break;
39-
}
22+
byte[] readBuffer = new byte[readBufferSize];
23+
StringBuilder currentLine = new StringBuilder();
24+
Decoder decoder = Encoding.UTF8.GetDecoder();
4025

41-
while (socket.Available > 0)
42-
{
43-
// Receive data from the socket
44-
int bytesReceived = socket.Receive(inputBuffer);
26+
// Temporary solution(?):
27+
// Certain multi-byte UTF-8 characters can result in overflowing (special characters)
28+
// So we add a little extra space to the chars array just to be safe
29+
char[] chars = new char[readBufferSize + Mathf.Clamp(readBufferSize / 4, 1, 32)];
4530

46-
// Decode data into text
47-
int charCount = decoder.GetChars(inputBuffer, 0, bytesReceived, chars, 0);
31+
while (ThreadsRunning)
32+
{
33+
// Check if the connection is still alive
34+
if (!CheckConnection(tcpClient.Client))
35+
{
36+
alertQueue.Enqueue(IRCReply.CONNECTION_INTERRUPTED);
37+
return;
38+
}
4839

49-
for (int i = 0; i < charCount; ++i)
40+
while (stream.DataAvailable)
5041
{
51-
// If the character is a linebreak, we have a complete line
52-
if (chars[i] == '\n' || chars[i] == '\r')
42+
// Read the bytes from the stream
43+
int bytesReceived = stream.Read(readBuffer, 0, readBufferSize);
44+
45+
// Decode the bytes to chars
46+
int charsDecoded = decoder.GetChars(readBuffer, 0, bytesReceived, chars, 0);
47+
48+
for (int i = 0; i < charsDecoded; ++i)
5349
{
54-
// Process the line if it's not empty
55-
if (currentRawLine.Length > 0)
50+
// Character is a linebreak -> We have a complete line
51+
if (chars[i] == '\n' || chars[i] == '\r')
5652
{
57-
HandleRawLine(currentRawLine);
58-
currentRawLine = string.Empty;
53+
// If the line is not empty, handle it
54+
if (currentLine.Length > 0)
55+
{
56+
HandleRawLine(currentLine.ToString());
57+
currentLine.Clear();
58+
}
59+
}
60+
else
61+
{
62+
// Append the character to the current line
63+
currentLine.Append(chars[i]);
5964
}
60-
continue;
61-
}
62-
63-
// Otherwise, append the character to the current line
64-
else
65-
{
66-
currentRawLine += chars[i];
6765
}
6866
}
69-
}
7067

71-
// Sleep to prevent high CPU usage
72-
Thread.Sleep(readInterval);
68+
// Sleep to prevent high CPU usage
69+
Thread.Sleep(readInterval);
70+
}
7371
}
7472

7573
if (showThreadDebug)
@@ -87,6 +85,7 @@ private bool CheckConnection(Socket socket)
8785
return true;
8886
}
8987

88+
9089
private void HandleRawLine(string raw)
9190
{
9291
if (showIRCDebug)
@@ -147,10 +146,10 @@ private void HandlePRIVMSG(string ircString, string tagString)
147146
var channel = ParseHelper.ParseChannel(ircString);
148147
var message = ParseHelper.ParseMessage(ircString);
149148
var tags = ParseHelper.ParseTags(tagString);
150-
149+
151150
// Not all users have set their Twitch name color, so we need to check for that
152151
if (tags.colorHex.Length <= 0)
153-
tags.colorHex = useRandomColorForUndefined
152+
tags.colorHex = useRandomColorForUndefined
154153
? ChatColors.GetRandomNameColor(sessionRandom, login)
155154
: "#FFFFFF";
156155

0 commit comments

Comments
 (0)