Skip to content

Instantly share code, notes, and snippets.

@strax
Forked from anonymous/gist:3854796
Created October 8, 2012 20:36
Show Gist options
  • Save strax/3854815 to your computer and use it in GitHub Desktop.
Save strax/3854815 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace Irc
{
public class MessageReceivedEventArgs: EventArgs
{
public Message Message;
public MessageReceivedEventArgs(Message message)
{
Message = message;
}
}
public class Message
{
}
public class Client: IDisposable
{
const string CRLF = "\r\n";
Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.TCP);
#region Properties
public string Host { get; private set; }
public short Port { get; private set; }
public string Username { get; private set; }
public string Name { get; private set; }
public string Nickname { get; set; }
#endregion
public event EventHandler<MessageReceivedEventArgs> MessageReceived;
public Client(string host, short port = 6667)
{
Host = host;
Port = port;
}
public async Task ConnectAsync()
{
await _socket.BeginConnect(Host, Port);
// Start receiving on a background thread
Task.Run(() => Receive());
// Wait for the server to send AUTH messages and such
await Task.Delay(1000);
await SendCommandAsync("USER {0} 8 * :{1}", Username, Name);
await SendCommandAsync("NICK {0}", Nickname);
}
protected Task Receive()
{
int read = 0, pos;
var buffer = new byte[512];
while((read = await Task<int>.Factory.FromAsync(
_socket.BeginReceive(buffer, read, 512 - read, 0, null, null), _socket.EndReceive)) > 0)
{
string message = Encoding.ASCII.GetString(buffer);
if((pos = message.IndexOf(CRLF)) != -1)
{
// message contains CLRF
try
{
OnMessage(ParseMessage(message.substring(pos)));
// Move the remaining bytes to the start of the buffer so we can read the rest later
Buffer.BlockCopy(buffer, pos + 2, buffer, 0, 512 - (pos + 2));
read -= pos + 2;
}
catch(Exception ex)
{
Console.Error.WriteLine("Cannot read message");
// Gracefully move to next message
read = 0;
}
}
}
// We read 0 bytes (= disconnected)
Disconnect();
}
public async Task SendCommandAsync(string command, params object[] args)
{
if(!socket.Connected) throw new InvalidStateException("Not connected");
string message = String.Format(command, args) + CLRF;
byte[] buffer = Encoding.ASCII.GetBytes(message);
await Task.Factory.FromAsync(
_socket.BeginSend(buffer, 0, buffer.Length, 0, null, null), _socket.EndSend);
}
public void Disconnect()
{
_socket.Shutdown();
_socket.Close();
// TODO shutdown the Receive task (see cancel tokens)
}
// Use events here so we can broadcast messages to many subscribers
protected virtual void OnMessage(EventArgs message)
{
var handler = MessageReceived;
if(handler != null)
{
handler(this, e);
}
}
#region IDisposable
public void Dispose()
{
_socket.Dispose();
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment