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