7c3940b1ff2e3ba20f2ade815bc3e922ea4acd03
[KiwiIRC.git] / server / irc / connection.js
1 var net = require('net'),
2 tls = require('tls'),
3 events = require('events'),
4 util = require('util');
5
6 var IrcConnection = function (hostname, port, ssl, nick, user, pass, webirc) {
7 var that = this;
8 events.EventEmitter.call(this);
9
10 if (ssl) {
11 this.socket = tls.connect(port, hostname, {}, connect_handler);
12 } else {
13 this.socket = net.createConnection(port, hostname);
14 this.socket.on('connect', function () {
15 connect_handler.apply(that, arguments);
16 });
17 }
18
19 this.socket.on('error', function (event) {
20 that.emit('error', event);
21 });
22
23 this.socket.setEncoding('utf-8');
24
25 this.socket.on('data', function () {
26 parse.apply(that, arguments);
27 });
28
29 this.socket.on('close', function () {
30 that.emit('close');
31 });
32
33 this.connected = false;
34 this.registered = false;
35 this.nick = nick;
36 this.user = user;
37 this.ssl = !(!ssl);
38 this.options = Object.create(null);
39
40 this.webirc = webirc;
41 this.password = pass;
42 this.hold_last = false;
43 this.held_data = '';
44 };
45 util.inherits(IrcConnection, events.EventEmitter);
46
47 module.exports.IrcConnection = IrcConnection;
48
49
50 IrcConnection.prototype.write = function (data, callback) {
51 write.call(this, data + '\r\n', 'utf-8', callback);
52 };
53
54 IrcConnection.prototype.end = function (data, callback) {
55 console.log('Closing IRC socket');
56 end.call(this, data + '\r\n', 'utf-8', callback);
57 };
58
59 var write = function (data, encoding, callback) {
60 this.socket.write(data, encoding, callback);
61 };
62
63 var end = function (data, encoding, callback) {
64 this.socket.end(data, encoding, callback);
65 };
66
67
68 var connect_handler = function () {
69 if (this.webirc) {
70 this.write('WEBIRC ' + this.webirc.pass + ' KiwiIRC ' + this.user.hostname + ' ' + this.user.address);
71 }
72 if (this.password) {
73 this.write('PASS ' + this.password);
74 }
75 //this.write('CAP LS');
76 this.write('NICK ' + this.nick);
77 this.write('USER kiwi_' + this.nick.replace(/[^0-9a-zA-Z\-_.]/, '') + ' 0 0 :' + this.nick);
78
79 this.connected = true;
80 console.log("IrcConnection.emit('connected')");
81 this.emit('connected');
82 };
83
84 parse_regex = /^(?::(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@?([a-z0-9\.\-:\/]+)?) )?(\S+)(?: (?!:)(.+?))?(?: :(.+))?$/i;
85
86 var parse = function (data) {
87 var i,
88 msg,
89 msg2,
90 trm;
91
92 if ((this.hold_last) && (this.held_data !== '')) {
93 data = this.held_data + data;
94 this.hold_last = false;
95 this.held_data = '';
96 }
97 if (data.substr(-1) !== '\n') {
98 this.hold_last = true;
99 }
100 data = data.split("\n");
101 for (i = 0; i < data.length; i++) {
102 if (data[i]) {
103 if ((this.hold_last) && (i === data.length - 1)) {
104 this.held_data = data[i];
105 break;
106 }
107
108 // We have a complete line of data, parse it!
109 msg = parse_regex.exec(data[i].replace(/^\r+|\r+$/, ''));
110 if (msg) {
111 msg = {
112 prefix: msg[1],
113 nick: msg[2],
114 ident: msg[3],
115 hostname: msg[4] || '',
116 command: msg[5],
117 params: msg[6] || '',
118 trailing: (msg[7]) ? msg[7].trim() : ''
119 };
120 msg.params = msg.params.split(' ');
121
122 this.emit('irc_' + msg.command.toUpperCase(), msg);
123 } else {
124 console.log("Malformed IRC line: " + data[i].replace(/^\r+|\r+$/, ''));
125 }
126 }
127 }
128 };