diff --git a/src/server.js b/src/server.js index ea5dc56..f6da4e4 100644 --- a/src/server.js +++ b/src/server.js @@ -18,67 +18,72 @@ server.create = function create() { let server = net.createServer((socket) => { const user = new User(socket) socket.on('data', function (data) { - let splitted = data.toString("ascii").split("\r\n")[0].split(" ") - let tokenized = [] - let lastParam = -1 - for (let i = 0; i < splitted.length; i++) { - if (lastParam > 0) { - tokenized[lastParam] = tokenized[lastParam] + " " + splitted[i] - } else if (splitted[i].charAt(0) == ":" && i > 0) { - lastParam = i - tokenized[lastParam] = splitted[i].slice(1) - } else { - tokenized[i] = splitted[i] - } - } - let command = tokenized[0].toUpperCase() - switch (command) { - case "PING": - if (tokenized[1] && tokenized[1] === "irc.example.com") { - socket.write("PONG irc.example.com\r\n") - } - break; - case "NICK": - if (tokenized[1]) { - let nickname = tokenized[1] - // nick collision test - if (!Object.keys(userlist).includes(nickname)) { - user.setNickname(nickname) - userlist[user.nickname] = user - } else { - socket.write(ERR_NICKNAMEINUSE, " nickname in use") - } + data.toString("ascii").split("\r\n").forEach(function (commandline) { + if (commandline == "") { + return + } + let splitted = commandline.split(" ") + let tokenized = [] + let lastParam = -1 + for (let i = 0; i < splitted.length; i++) { + if (lastParam > 0) { + tokenized[lastParam] = tokenized[lastParam] + " " + splitted[i] + } else if (splitted[i].charAt(0) == ":" && i > 0) { + lastParam = i + tokenized[lastParam] = splitted[i].slice(1) + } else { + tokenized[i] = splitted[i] + } + } + let command = tokenized[0].toUpperCase() + switch (command) { + case "PING": + if (tokenized[1] && tokenized[1] === "irc.example.com") { + socket.write("PONG irc.example.com\r\n") + } + break; + case "NICK": + if (tokenized[1]) { + let nickname = tokenized[1] + // nick collision test + if (!Object.keys(userlist).includes(nickname)) { + user.setNickname(nickname) + userlist[user.nickname] = user + } else { + socket.write(ERR_NICKNAMEINUSE, " nickname in use") + } - } else { - socket.write(ERR_NONICKNAMEGIVEN, "ERROR: NO NICKNAME PROVIDED") - } + } else { + socket.write(ERR_NONICKNAMEGIVEN, "ERROR: NO NICKNAME PROVIDED") + } - break; + break; - case "USER": - // ignoring servername and hostname, not useful these days - user.register(tokenized[1], tokenized[4]) - let address = user.getAddress() - socket.write(`001 ${user.nickname} :Welcome to the example IRC Project ${user.nickname}!~${user.username}@${address}`) - break; - case "PRIVMSG": - let target = userlist[tokenized[1]] - let message = tokenized[2] + case "USER": + // ignoring servername and hostname, not useful these days + user.register(tokenized[1], tokenized[4]) + let address = user.getAddress() + socket.write(`:irc.example.com 001 ${user.nickname} :Welcome to the example IRC Project ${user.nickname}!~${user.username}@${address}\r\n`, "ascii") + break; + case "PRIVMSG": + let target = userlist[tokenized[1]] + let message = tokenized[2] target.sendMsg(user, message) break; - case "QUIT": + case "QUIT": server.closeConnection(user.nickname) break; - case "PASS": + case "PASS": if (tokenized[1]) user.setPassword(tokenized[1]) break; - default: + default: console.error(`Unknown command: ${command}`); } + }); }).on('error', (err) => { console.error(err); }) diff --git a/src/user.js b/src/user.js index e04cc04..f207aef 100644 --- a/src/user.js +++ b/src/user.js @@ -38,7 +38,7 @@ function User(socket) { this.sendMsg = function (from, message) { - this.connection.write(`:${from.nickname} PRIVMSG ${this.nickname} :${message}`) + this.connection.write(`:${from.nickname} PRIVMSG ${this.nickname} :${message}\r\n`, "ascii") } } diff --git a/test/command_privmsg.js b/test/command_privmsg.js index 75b5aa6..d464e0b 100644 --- a/test/command_privmsg.js +++ b/test/command_privmsg.js @@ -12,7 +12,7 @@ describe("PRIVMSG OK", function () { mockedSock.write = function (data) { let answer = data.toString("ascii") if (answer.indexOf("PRIVMSG") >= 0) { - assert.equal(answer, ":some_nick PRIVMSG some_nick :I'm a message") + assert.equal(answer, ":some_nick PRIVMSG some_nick :I'm a message\r\n") done() } } @@ -45,7 +45,7 @@ describe("PRIVMSG OK", function () { mockedSock2.write = function (data) { let answer = data.toString("ascii") if (answer.indexOf("PRIVMSG") >= 0) { - assert.equal(answer, ":some_nick PRIVMSG other_nick :I'm a message") + assert.equal(answer, ":some_nick PRIVMSG other_nick :I'm a message\r\n") done() } } diff --git a/test/command_user.js b/test/command_user.js index 5d459c8..d937f1b 100644 --- a/test/command_user.js +++ b/test/command_user.js @@ -10,7 +10,7 @@ describe("USER OK", function () { return { port: 12346, family: 'IPv4', address: '127.0.0.1' } } mockedSock.write = function (data) { - assert.equal(data.toString("ascii"), "001 some_nick :Welcome to the example IRC Project some_nick!~guest@127.0.0.1") + assert.equal(data.toString("ascii"), ":irc.example.com 001 some_nick :Welcome to the example IRC Project some_nick!~guest@127.0.0.1\r\n") done() } mockedSock.destroy = function () { diff --git a/test/hexchat.js b/test/hexchat.js new file mode 100644 index 0000000..b90f61f --- /dev/null +++ b/test/hexchat.js @@ -0,0 +1,23 @@ +const assert = require('assert'); +const EventEmitter = require('events'); +const IRCServer = require("../src/server.js"); + +describe("hexchat", function () { + it("should handle hexchat inital command list", function (done) { + const server = IRCServer.create() + let mockedSock = new EventEmitter() + mockedSock.address = function() { + return { port: 12346, family: 'IPv4', address: '127.0.0.1' } + } + mockedSock.write = function (data) { + assert.equal(data.toString("ascii"), ":irc.example.com 001 some_nick :Welcome to the example IRC Project some_nick!~guest@127.0.0.1\r\n") + done() + } + mockedSock.destroy = function () { + done("Destroyed socket without answering") + } + + server.emit("connection", mockedSock) + mockedSock.emit('data', Buffer.from("CAP LS 302\r\nNICK some_nick\r\nUSER guest tolmoon tolsun :Ronnie Reagan\r\n", "ascii")) + }) +})