IRC Client

From Noisebridge
Jump to navigation Jump to search

AS3 IRC Desktop Client

A goal of this is to create a base resource of knowledge around IRC and specifically the capturing the knowledge for both building and using IRC Clients.

Basics of IRC Client communication.

IRC is protocol that operates over a TCP/IP socket connection with ASCII encoding typically on port 6667.

In order to connect an IRC Server a socket must first be opened on the appropriate portThis is done in AS3 by using the flash.net.Socket class, and passing the hostname as a string (DNS host name or IP) and a port number as an integer.

var socket:flash.net.Socket = new flash.net.Socket("irc.freenode.net", 6667);

The Socket class generates an Event.CONNECT when the connection is established, several other error events can be generated if the connection fails. Once the socket is open the Client needs to register the connection by sending a NICK and USER command, all messages are sent to the server with the Socket method writeUTFBytes, all messages must be terminated with the ASCII character pair of CRLF (\r\n), and the flush method is called to send the queued data.

socket.writeUTFBytes("NICK the-x\r\n");
socket.writeUTFBytes("USER thex experimental irc.freenode.net :John Doe\r\n");

Upon successful registration the server will respond with a numeric messages 001..004.


This is the complete code for a basic "bot" that tests some code and tells teh time

package
{
	import flash.display.Sprite;
	import flash.net.Socket;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.KeyboardEvent;
	import flash.text.TextField;
	
	public class IRCc extends Sprite
	{
		public var keyHit:Sprite;
		public var text_txt:TextField;
		
		private var socket:Socket;
		
		private var hostPath:String = "irc.freenode.net";
		private var hostPort:int = 6667;
		
		private var nickname:String = "debugUser";
		private var username:String = "Test User";
		private var hostname:String = "TEST-HOST";
		private var realname:String = "NO NAME";
		
		private var connectionState:String = "INIT";

		public function IRCc()
		{
			text_txt.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler);
			
			initSocket();
		}
		
		private function initSocket():void
		{
			socket = new Socket(hostPath, hostPort);
			socket.addEventListener(Event.CONNECT, connectHandler);
			socket.addEventListener(Event.CLOSE, closeHandler);
			socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
			
			connectionState = "CONNECTING";
		}
		
		private function sendNick():void
		{
			/*
				Command: NICK
   				Parameters: <nickname> [ <hopcount> ]
				
				Command: USER
				Parameters: <username> <hostname> <servername> <realname>
			*/
			
			// connectionState = "HANDSHAKE";

			socket.writeUTFBytes("NICK " + nickname + "\r\n");
			socket.writeUTFBytes("USER " + username + " " + hostname + " " + hostPath + ": " + realname + "\r\n");
			socket.flush();
		}
		
		private function quit():void
		{
			trace("quit");
			
			connectionState = "QUIT";
			socket.writeUTFBytes("QUIT :i quit there 4...\r\n");
			socket.flush();
		}
		
		private function joinChannel(channel:String):void
		{
			trace("JOIN: " + channel);
			socket.writeUTFBytes("JOIN " + channel + "\r\n");
			socket.flush();
		}
		
		private function sendMessage(msg:String):void
		{
			trace("MSG: " + msg);
			socket.writeUTFBytes("PRIVMSG #fort :test\r\n");
			socket.flush();
		}
		
		private function sendTime():void
		{
			var now:Date = new Date();
			
			trace("TIME: " + now.toString());
			socket.writeUTFBytes("PRIVMSG #fort :teh time is now " + now.toString() + "\r\n");
			socket.flush();
		}
		
		private function pongServer(daemon:String):void
		{
			trace("PONG: *" + daemon + "*");
			socket.writeUTFBytes("PONG " + daemon + "\r\n");
			socket.flush();
		}
		
		private function readData():void
		{
			var socketData:String = socket.readUTFBytes(socket.bytesAvailable);
			trace(socketData);
			
			if (socketData.split(' ', 1)[0] == "PING")
			{
				// PING Command, send PONG
				pongServer(socketData.split(':')[1]);
			}
			else
			{
				var msg:String = socketData.substr(socketData.lastIndexOf(":"));
				trace("MSG: " + msg);
				if (msg.toLowerCase().indexOf("time") >= 0)
				{
					sendTime();
				}
				else if (msg.toLowerCase().indexOf("test") >= 0)
				{
					sendMessage("test");
				}
			}
		}
		
		private function socketDataHandler(e:ProgressEvent):void
		{
			trace("Data");
			readData();
		}
		
		private function connectHandler(e:Event):void
		{
			trace("Connect");
			connectionState = "CONNECTED";
			sendNick();
		}
		
		private function closeHandler(e:Event):void
		{
			trace("Close");
			connectionState = "CLOSED";
		}
		
		private function keyHandler(e:KeyboardEvent):void
		{
			trace("key: " + e.keyCode);
			if (e.keyCode == 74)
			{
				joinChannel("#fort");
			}
			else if (e.keyCode == 77)
			{
				sendMessage("test");
			}
			else if (e.keyCode == 84)
			{
				sendTime();
			}
			else if (e.keyCode == 81)
			{
				quit();
			}
		}

	}
	
}


Sample connection to irc.freenode.net, captured socket data to/from babel client.

ASCII

NICK [jc]

USER thex windows irc.freenode.net :J.C.

:lindbohm.freenode.net NOTICE * :*** Looking up your hostname...

:lindbohm.freenode.net NOTICE * :*** Checking Ident

:lindbohm.freenode.net NOTICE * :*** Found your hostname

:lindbohm.freenode.net NOTICE * :*** No Ident response

:lindbohm.freenode.net 001 [jc] :Welcome to the freenode Internet Relay Chat Network [jc]

:lindbohm.freenode.net 002 [jc] :Your host is lindbohm.freenode.net[130.237.188.200/6667], running version ircd-seven-1.1.3

:lindbohm.freenode.net 003 [jc] :This server was created Tue Dec 27 2011 at 20:37:56 CET

:lindbohm.freenode.net 004 [jc] lindbohm.freenode.net ircd-seven-1.1.3 DOQRSZaghilopswz CFILMPQbcefgijklmnopqrstvz bkloveqjfI

:lindbohm.freenode.net 005 [jc] CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQcgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=freenode KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server

:lindbohm.freenode.net 005 [jc] CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server

:lindbohm.freenode.net 005 [jc] EXTBAN=$,arx WHOX CLIENTVER=3.0 SAFELIST ELIST=CTU :are supported by this server

:lindbohm.freenode.net 251 [jc] :There are 209 users and 85659 invisible on 31 servers

:lindbohm.freenode.net 252 [jc] 29 :IRC Operators online

:lindbohm.freenode.net 253 [jc] 8 :unknown connection(s)

:lindbohm.freenode.net 254 [jc] 43384 :channels formed

:lindbohm.freenode.net 255 [jc] :I have 4326 clients and 1 servers

:lindbohm.freenode.net 265 [jc] 4326 9029 :Current local users 4326, max 9029

:lindbohm.freenode.net 266 [jc] 85868 87783 :Current global users 85868, max 87783

:lindbohm.freenode.net 250 [jc] :Highest connection count: 9030 (9029 clients) (3464522 connections received)

:lindbohm.freenode.net 375 [jc] :- lindbohm.freenode.net Message of the Day - 

:lindbohm.freenode.net 372 [jc] :- Welcome to lindbohm.freenode.net in Stockholm, Sweden, EU! Thanks to

:lindbohm.freenode.net 372 [jc] :- Stockholm University (http://www.su.se) for sponsoring

:lindbohm.freenode.net 372 [jc] :- this server!

:lindbohm.freenode.net 372 [jc] :-  

:lindbohm.freenode.net 372 [jc] :- D.nis Lindbohm (1927-2005) was a Swedish author and one of the 

:lindbohm.freenode.net 372 [jc] :- founders of Swedish science fiction.

:lindbohm.freenode.net 372 [jc] :- You're using freenode, a service of Peer-Directed Projects

:lindbohm.freenode.net 372 [jc] :- Center Ltd (http://freenode.net/pdpc.shtml).

:lindbohm.freenode.net 372 [jc] :-  

:lindbohm.freenode.net 372 [jc] :- By connecting to freenode you indicate that you have read

:lindbohm.freenode.net 372 [jc] :- and agree to adhere to our policies and procedures as per

:lindbohm.freenode.net 372 [jc] :- the website (http://freenode.net)We would like to remind

:lindbohm.freenode.net 372 [jc] :- you that unauthorized public logging of channels on the

:lindbohm.freenode.net 372 [jc] :- network is prohibitedPublic channel logging should only

:lindbohm.freenode.net 372 [jc] :- take place where the channel ownJOIN #fort

er(s) has requested this

:lindbohm.freenode.net 372 [jc] :- and users of the channel are all made aware (if you are

:lindbohm.freenode.net 372 [jc] :- publically logging your channel, you may wish to keep a

:lindbohm.freenode.net 372 [jc] :- notice in topic and perhaps as a on-join message).

:lindbohm.freenode.net 372 [jc] :-  

:lindbohm.freenode.net 372 [jc] :- freenode runs an open proxy scanner. [http://vcsc.cs.uh.edu/second- url:computing/show_user.php?userid=2557 docx] For details on

:lindbohm.freenode.net 372 [jc] :- freenode network policy, please take a look at our policy

:lindbohm.freenode.net 372 [jc] :- page (http://freenode.net/policy.shtml)Thank you for using

:lindbohm.freenode.net 372 [jc] :- the network!

:lindbohm.freenode.net 372 [jc] :-  

:lindbohm.freenode.net 372 [jc] :- Don't forget to check out these other Peer-Directed Projects:

:lindbohm.freenode.net 372 [jc] :- FOSSCON [http://www.fosscon.org] and fossevents 

:lindbohm.freenode.net 372 [jc] :- [http://www.fossevents.org], and soon we'll repeat last years 

:lindbohm.freenode.net 372 [jc] :- success with Picnics for Geeks across the globe, more info at 

:lindbohm.freenode.net 372 [jc] :- [http://geeknic.org]

:lindbohm.freenode.net 372 [jc] :-  

:lindbohm.freenode.net 372 [jc] :- freenode is a service of Peer-Directed Projects Center Ltd,

:lindbohm.freenode.net 372 [jc] :- a not for profit organisation registered in England and Wales.

:lindbohm.freenode.net 372 [jc] :-  

:lindbohm.freenode.net 372 [jc] :- Thank you for using freenode!

:lindbohm.freenode.net 372 [jc] :-  

:lindbohm.freenode.net 372 [jc] :- ***************************************************************

:lindbohm.freenode.net 372 [jc] :- Please read http://blog.freenode.net/2010/11/be-safe-out-there/

:lindbohm.freenode.net 372 [jc] :- ***************************************************************

:lindbohm.freenode.net 376 [jc] :End of /MOTD command.

:[jc] MODE [jc] :+i

PRIVMSG [jc] :.CON-PING.

:[jc]!~thex@108-83-132-49.lightspeed.sntcca.sbcglobal.net JOIN #fort

MODE #fort

MODE #fort +b

:lindbohm.freenode.net 353 [jc] = #fort :[jc] tunabananas thex praveen__ wlfyit_

:lindbohm.freenode.net 366 [jc] #fort :End of /NAMES list.

:[jc]!~thex@108-83-132-49.lightspeed.sntcca.sbcglobal.net PRIVMSG [jc] :.CON-PING.

:lindbohm.freenode.net 324 [jc] #fort +cnt

:lindbohm.freenode.net 329 [jc] #fort 1358076009

:lindbohm.freenode.net 368 [jc] #fort :End of Channel Ban List

PRIVMSG #fort :hello


HEX

00000000  4e 49 43 4b 20 5b 6a 63  5d 0d 0a 55 53 45 52 20 NICK [jc ]..USER 
00000010  74 68 65 78 20 77 69 6e  64 6f 77 73 20 69 72 63 thex win dows irc
00000020  2e 66 72 65 65 6e 6f 64  65 2e 6e 65 74 20 3a 4a .freenod e.net :J
00000030  2e 43 2e 0d 0a                                   .C...
    00000000  3a 73 65 6e 64 61 6b 2e  66 72 65 65 6e 6f 64 65 :sendakfreenode
    00000010  2e 6e 65 74 20 4e 4f 54  49 43 45 20 2a 20 3a 2a .net NOT ICE * :*
    00000020  2a 2a 20 4c 6f 6f 6b 69  6e 67 20 75 70 20 79 6f ** Looki ng up yo
    00000030  75 72 20 68 6f 73 74 6e  61 6d 65 2e 2e 2e 0d 0a ur hostn ame.....
    00000040  3a 73 65 6e 64 61 6b 2e  66 72 65 65 6e 6f 64 65 :sendakfreenode
    00000050  2e 6e 65 74 20 4e 4f 54  49 43 45 20 2a 20 3a 2a .net NOT ICE * :*
    00000060  2a 2a 20 43 68 65 63 6b  69 6e 67 20 49 64 65 6e ** Check ing Iden
    00000070  74 0d 0a                                         t..
    00000073  3a 73 65 6e 64 61 6b 2e  66 72 65 65 6e 6f 64 65 :sendakfreenode
    00000083  2e 6e 65 74 20 4e 4f 54  49 43 45 20 2a 20 3a 2a .net NOT ICE * :*
    00000093  2a 2a 20 46 6f 75 6e 64  20 79 6f 75 72 20 68 6f ** Found  your ho
    000000A3  73 74 6e 61 6d 65 0d 0a                          stname.

Specs:

IRC http://tools.ietf.org/html/rfc1459.html


Socket based connection http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/Socket.html