diff --git a/bin/irslackd.js b/bin/irslackd.js index ea9e97d..c120c01 100755 --- a/bin/irslackd.js +++ b/bin/irslackd.js @@ -10,6 +10,7 @@ const DEFAULT_PORT = 6697; const DEFAULT_TLS_PKEY = os.homedir() + '/.irslackd/pkey.pem'; const DEFAULT_TLS_CERT = os.homedir() + '/.irslackd/cert.pem'; const DEFAULT_RTM_CLIENT_LOG_LEVEL = 'info'; +const DEFAULT_LINE_LEN = 4096; const opt = require('node-getopt').create([ [ 'h', 'help', 'Show this help' ], @@ -19,6 +20,7 @@ const opt = require('node-getopt').create([ [ 'c', 'cert=PATH', 'Set TLS cert path (default: ' + DEFAULT_TLS_CERT + ')' ], [ 'L', 'rtmLogLvl=LEVEL', 'Set RTM Client log level (default: ' + DEFAULT_RTM_CLIENT_LOG_LEVEL + ')' ], [ 'i', 'insecure', 'Do not use TLS encryption (not recommended)' ], + [ 'l', 'lineLen', 'Set RPL_ISUPPORT LINELEN (default: ' + DEFAULT_LINE_LEN + ')' ], ]).bindHelp().parseSystem(); new irslackd.Irslackd({ @@ -29,4 +31,5 @@ new irslackd.Irslackd({ cert: fs.readFileSync(opt.options.cert || DEFAULT_TLS_CERT), }, rtmClientLogLevel: opt.options.rtmLogLvl || DEFAULT_RTM_CLIENT_LOG_LEVEL, + lineLen: opt.options.lineLen || DEFAULT_LINE_LEN, }).listen(); diff --git a/lib/ircd.js b/lib/ircd.js index ddef2cd..a73ad55 100644 --- a/lib/ircd.js +++ b/lib/ircd.js @@ -6,9 +6,10 @@ const util = require('util'); const EventEmitter = require('events'); class Ircd extends EventEmitter { - constructor(tlsOpts) { + constructor(config) { super(); - this.tlsOpts = tlsOpts; + this.tlsOpts = config.tlsOpts; + this.lineLen = config.lineLen; } listen(port, host) { const socketFunc = this.onConnect.bind(this); @@ -62,6 +63,8 @@ class Ircd extends EventEmitter { console.log('irc_out', line); line += '\r\n'; if (line.length > 512) { + this.emit('ircError', socket, 'Long line (' + line.length + ' bytes) (clients without LINELEN support may reject): ' + line); + } else if (line.length > this.lineLen) { this.emit('ircError', socket, 'Long line (' + line.length + ' bytes) (clients may reject): ' + line); } return socket.write(line); diff --git a/lib/irslackd.js b/lib/irslackd.js index 5cc1927..f8e7db7 100644 --- a/lib/irslackd.js +++ b/lib/irslackd.js @@ -20,7 +20,7 @@ class Irslackd { } listen() { const self = this; - self.ircd = self.getNewIrcd(self.config.tlsOpts); + self.ircd = self.getNewIrcd(self.config); const requireInit = true; const noRequireInit = false; new Map([ @@ -509,8 +509,13 @@ class Irslackd { } } async onSlackReady(ircUser, event) { - // Send MOTD + // RPL_WELCOME this.ircd.write(ircUser.socket, 'irslackd', '001', [ ircUser.ircNick, 'irslackd' ]); + + // RPL_ISUPPORT + this.ircd.write(ircUser.socket, 'irslackd', '005', [ ircUser.ircNick, 'LINELEN=' + this.config.lineLen, 'are supported by this server' ]); + + // RPL_ENDOFMOTD this.ircd.write(ircUser.socket, 'irslackd', '376', [ ircUser.ircNick, 'End of MOTD' ]); // set user presence to auto instead of away @@ -1331,8 +1336,8 @@ class Irslackd { await ircUser.slackWeb.apiCallOrThrow('users.setPresence', { presence: status }); } // Dependency injectors - getNewIrcd(tlsOpts) { - return new ircd.Ircd(tlsOpts); + getNewIrcd(config) { + return new ircd.Ircd(config); } getNewSlackWebClient(token, cookie = null) { const params = cookie ? { headers: { Cookie: cookie }} : {}; diff --git a/tests/mocks.js b/tests/mocks.js index c27dad8..546df50 100644 --- a/tests/mocks.js +++ b/tests/mocks.js @@ -132,6 +132,7 @@ async function connectOneIrcClient(t, prefs = []) { ircSocket.expect(':irslackd 353 test_slack_user = #test_chan_1 :test_slack_user test_slack_user test_slack_fooo test_slack_barr'); ircSocket.expect(':irslackd 366 test_slack_user #test_chan_1 :End of /NAMES list'); ircSocket.expect(':irslackd 001 test_slack_user irslackd'); + ircSocket.expect(':irslackd 005 test_slack_user LINELEN=4096 :are supported by this server'); ircSocket.expect(':irslackd 376 test_slack_user :End of MOTD'); }; @@ -143,8 +144,9 @@ async function connectOneIrcClient(t, prefs = []) { key: 'key', cert: 'cert', }, + lineLen: 4096, }); - daemon.getNewIrcd = (tlsOpts) => { return new MockIrcd(tlsOpts); }; + daemon.getNewIrcd = (config) => { return new MockIrcd(config); }; daemon.getNewSlackRtmClient = (token) => { return new MockSlackRtmClient(t); }; daemon.getNewSlackWebClient = (token) => { const slackWeb = new MockSlackWebClient(t); @@ -190,7 +192,7 @@ async function connectOneIrcClient(t, prefs = []) { end: () => ircSocket.end(), }; } -connectOneIrcClient.planCount = 21; +connectOneIrcClient.planCount = 22; exports.MockSlackWebClient = MockSlackWebClient; exports.MockSlackRtmClient = MockSlackRtmClient;