IRC parsing, tokenization, and state handling in C#
at 8acaa752c3a03feecd4a9131d09ec4be7756289d 73 lines 2.3 kB view raw
1using System; 2using System.Net.Sockets; 3using System.Threading; 4using IRCTokens; 5 6namespace Tokens 7{ 8 public class Client 9 { 10 private readonly byte[] _bytes; 11 private readonly StatefulDecoder _decoder; 12 private readonly StatefulEncoder _encoder; 13 private readonly Socket _socket; 14 15 public Client() 16 { 17 _decoder = new StatefulDecoder(); 18 _encoder = new StatefulEncoder(); 19 _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 20 _bytes = new byte[1024]; 21 } 22 23 public void Start() 24 { 25 _socket.Connect("127.0.0.1", 6667); 26 while (!_socket.Connected) Thread.Sleep(1000); 27 28 Send(new Line("NICK", "tokensbot")); 29 Send(new Line("USER", "tokensbot", "0", "*", "real name")); 30 31 while (true) 32 { 33 var bytesReceived = _socket.Receive(_bytes); 34 35 if (bytesReceived == 0) 36 { 37 Console.WriteLine("! disconnected"); 38 _socket.Shutdown(SocketShutdown.Both); 39 _socket.Close(); 40 break; 41 } 42 43 var lines = _decoder.Push(_bytes, bytesReceived); 44 45 foreach (var line in lines) 46 { 47 Console.WriteLine($"< {line.Format()}"); 48 49 switch (line.Command) 50 { 51 case "PING": 52 Send(new Line("PONG", line.Params[0])); 53 break; 54 case "001": 55 Send(new Line("JOIN", "#irctokens")); 56 break; 57 case "PRIVMSG": 58 Send(new Line("PRIVMSG", line.Params[0], "hello there")); 59 break; 60 } 61 } 62 } 63 } 64 65 private void Send(Line line) 66 { 67 Console.WriteLine($"> {line.Format()}"); 68 _encoder.Push(line); 69 while (_encoder.PendingBytes.Length > 0) 70 _encoder.Pop(_socket.Send(_encoder.PendingBytes, SocketFlags.None)); 71 } 72 } 73}