diff options
Diffstat (limited to 'third_party/websockify/include/wsirc.js')
-rw-r--r-- | third_party/websockify/include/wsirc.js | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/third_party/websockify/include/wsirc.js b/third_party/websockify/include/wsirc.js new file mode 100644 index 00000000..bef8f8de --- /dev/null +++ b/third_party/websockify/include/wsirc.js @@ -0,0 +1,235 @@ +/* + * WebSockets IRC client + * Copyright (C) 2011 Joel Martin + * Licensed under LGPL-3 (see LICENSE.txt) + * + * Includes VT100.js from: + * http://code.google.com/p/sshconsole + * Which was modified from: + * http://fzort.org/bi/o.php#vt100_js + + * IRC Client protocol: + * http://www.faqs.org/rfcs/rfc2812.html + */ + + +function IRC(target, connect_callback, disconnect_callback) { + +var that = {}, // Public API interface + vt100, ws, sQ = [], + state = "unconnected", + irc_nick, irc_channel, + termType = "VT100"; + + +Array.prototype.pushStr = function (str) { + var n = str.length; + for (var i=0; i < n; i++) { + this.push(str.charCodeAt(i)); + } +} + +function do_send() { + if (sQ.length > 0) { + Util.Debug("Sending " + sQ); + ws.send(sQ); + sQ = []; + } +} + +function do_recv() { + console.log(">> do_recv"); + var rQ, rQi, i; + + while (ws.rQlen() > 1) { + rQ = ws.get_rQ(); + rQi = ws.get_rQi(); + for (i = rQi; i < rQ.length; i++) { + if (rQ[i] === 10) { + break; + } + } + if (i >= rQ.length) { + // No line break found + break; + } + recvMsg(ws.rQshiftStr((i-rQi) + 1)); + } + //console.log("<< do_recv"); +} + +// Handle an IRC message +function recvMsg(msg) { + Util.Debug(">> recvMsg('" + msg + "')"); + + var tokens = msg.split(' '), in_params = true, + prefix, command, params = [], trailing = []; + + Util.Info(" tokens: " + tokens); + + if (tokens[0].charAt(0) === ":") { + prefix = tokens.shift(); + } + + command = tokens.shift(); + + while (tokens.length > 0) { + if (tokens[0].charAt(0) === ":") { + in_params = false; + } + if (in_params) { + params.push(tokens.shift()); + } else { + trailing.push(tokens.shift()); + } + } + + Util.Info(" prefix: " + prefix); + Util.Info(" command: " + command); + Util.Info(" params: " + params); + Util.Info(" trailing: " + trailing); + + // Show raw received + vt100.write(msg); + + switch (command) { + case "004": + state = "registered"; + vt100.write("Joining channel #" + irc_channel); + sendCmd("JOIN #" + irc_channel); + break; + case "JOIN": + state = "joined"; + vt100.write("Joined channel #" + irc_channel); + break; + + } + + Util.Debug("<< recvMsg('" + msg + "')"); +} + +function sendCmd(msg) { + Util.Info("Sending: " + msg); + sQ.pushStr(msg + "\r\n"); + do_send(); +} + +that.sendMsg = function(msg) { + // TODO parse into message + sendCmd("PRIVMSG #" + irc_channel + " :" + msg); +} + + +that.connect = function(host, port, encrypt, nick, channel) { + var host = host, + port = port, + scheme = "ws://", uri; + + irc_nick = nick; + irc_channel = channel; + + Util.Debug(">> connect"); + if ((!host) || (!port)) { + alert("must set host and port"); + return false; + } + + if (ws) { + ws.close(); + } + + if (encrypt) { + scheme = "wss://"; + } + uri = scheme + host + ":" + port; + Util.Info("connecting to " + uri); + + ws.open(uri); + + Util.Debug("<< connect"); + + return true; +} + +that.disconnect = function() { + Util.Debug(">> disconnect"); + if (ws) { + ws.close(); + } + + disconnect_callback(); + Util.Debug("<< disconnect"); +} + + +function constructor() { + /* Initialize Websock object */ + ws = new Websock(); + + ws.on('message', do_recv); + ws.on('open', function(e) { + Util.Info(">> WebSockets.onopen"); + // Send registration commands + state = "connected"; + sendCmd("NICK " + irc_nick); + // TODO: how to determine this? + sendCmd("USER joelm 0 * :Joel Martin"); + connect_callback(); + Util.Info("<< WebSockets.onopen"); + }); + ws.on('close', function(e) { + Util.Info(">> WebSockets.onclose"); + that.disconnect(); + Util.Info("<< WebSockets.onclose"); + }); + ws.on('error', function(e) { + Util.Info(">> WebSockets.onerror"); + that.disconnect(); + Util.Info("<< WebSockets.onerror"); + }); + + /* Initialize the terminal emulator/renderer */ + + vt100 = new VT100(80, 24, target); + + // Show cursor + vt100.curs_set(true, false); + + /* + * Override VT100 I/O routines + */ + + // Set handler for sending characters + vt100.getch( + function send_chr(chr, vt) { + var i; + Util.Debug(">> send_chr: " + chr); + for (i = 0; i < chr.length; i++) { + sQ.push(chr.charCodeAt(i)); + } + do_send(); + vt100.getch(send_chr); + } + ); + + vt100.debug = function(message) { + Util.Debug(message + "\n"); + } + + vt100.warn = function(message) { + Util.Warn(message + "\n"); + } + + vt100.curs_set = function(vis, grab, eventist) + { + this.debug("curs_set:: vis: " + vis + ", grab: " + grab); + if (vis !== undefined) + this.cursor_vis_ = (vis > 0); + } + + return that; +} + +return constructor(); // Return the public API interface + +} // End of Telnet() |