IRC parsing, tokenization, and state handling in C#
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}