IRC parsing, tokenization, and state handling in C#
at 338763fde71ba2dc0de8ea5e2437d24ee365874b 68 lines 2.1 kB view raw
1using System; 2using System.Collections.Generic; 3using System.Net.Sockets; 4using System.Text; 5using IrcTokens; 6 7namespace Sample 8{ 9 public class Client 10 { 11 private readonly Socket _socket; 12 private readonly StatefulDecoder _decoder; 13 private readonly StatefulEncoder _encoder; 14 private readonly byte[] _bytes; 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 28 Send(new Line {Command = "USER", Params = new List<string> {"username", "0", "*", "real name"}}); 29 Send(new Line {Command = "NICK", Params = new List<string> {"statefulbot"}}); 30 31 while (true) 32 { 33 var bytesReceived = _socket.Receive(_bytes); 34 var lines = _decoder.Push(_bytes); 35 36 if (lines.Count == 0) 37 { 38 Console.WriteLine("! disconnected"); 39 _socket.Shutdown(SocketShutdown.Both); 40 break; 41 } 42 43 foreach (var line in lines) 44 { 45 Console.WriteLine($"< {line.Format()}"); 46 47 switch (line.Command) 48 { 49 case "PING": 50 Send(new Line {Command = "PONG", Params = line.Params}); 51 break; 52 case "001": 53 Send(new Line {Command = "JOIN", Params = new List<string> {"#channel"}}); 54 break; 55 } 56 } 57 } 58 } 59 60 private void Send(Line line) 61 { 62 Console.WriteLine($"> {line.Format()}"); 63 _encoder.Push(line); 64 while (_encoder.PendingBytes.Length > 0) 65 _encoder.Pop(_socket.Send(_encoder.PendingBytes)); 66 } 67 } 68}