diff --git a/src/server.js b/src/server.js index 7c7138b..988abd9 100644 --- a/src/server.js +++ b/src/server.js @@ -11,89 +11,95 @@ const ERR_NONICKNAMEGIVEN = '431' const ERR_NICKNAMEINUSE = '433' const ERR_NEEDMOREPARAMS = '461' + let server = {} server.create = function create(config = {}) { let password if (config.password) { - password = config.password + password = config.password } let userlist = {} let server = net.createServer((socket) => { const user = new User(socket) if (!config.password) { - user.authenticated = true + user.authenticated = true } socket.on('data', function (data) { 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") - } - - break; - - 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": - server.closeConnection(user.nickname) - break; - case "PASS": - if (tokenized[1] === config.password) { - user.authenticated = true + 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 { - user.closeConnection() + tokenized[i] = splitted[i] } - break; + } + 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") + } + + break; + + 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] + if (target.registered === false) { + socket.write(`:irc.example.com ${ERR_NOSUCHNICK} ${target} no such nick/channel`) + + } else { + target.sendMsg(user, message) + + } + break; + case "QUIT": + server.closeConnection(user.nickname) + break; + case "PASS": + if (tokenized[1] === config.password) { + user.authenticated = true + } else { + user.closeConnection() + } + break; - default: - console.error(`Unknown command: ${command}`); - } - }); + default: + console.error(`Unknown command: ${command}`); + } + }); }).on('error', (err) => { console.error(err); }) diff --git a/test/command_privmsg.js b/test/command_privmsg.js index d464e0b..10df41e 100644 --- a/test/command_privmsg.js +++ b/test/command_privmsg.js @@ -29,8 +29,8 @@ describe("PRIVMSG OK", function () { it("should handle a PRIVMSG command for multiple users -> PRIVMSG other_nick :I'm a message", function (done) { const server = IRCServer.create() let mockedSock1 = new EventEmitter() - mockedSock1.address = function() { - return { port: 12346, family: 'IPv4', address: '127.0.0.1' } + mockedSock1.address = function () { + return {port: 12346, family: 'IPv4', address: '127.0.0.1'} } mockedSock1.write = function (data) { return @@ -39,15 +39,15 @@ describe("PRIVMSG OK", function () { done("Destroyed socket without answering") } let mockedSock2 = new EventEmitter() - mockedSock2.address = function() { - return { port: 12346, family: 'IPv4', address: '127.0.0.1' } + mockedSock2.address = function () { + return {port: 12346, family: 'IPv4', address: '127.0.0.1'} } 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\r\n") - done() - } + let answer = data.toString("ascii") + if (answer.indexOf("PRIVMSG") >= 0) { + assert.equal(answer, ":some_nick PRIVMSG other_nick :I'm a message\r\n") + done() + } } mockedSock2.destroy = function () { done("Destroyed socket without answering") @@ -60,6 +60,45 @@ describe("PRIVMSG OK", function () { mockedSock2.emit('data', Buffer.from("NICK other_nick\r\n", "ascii")) mockedSock2.emit('data', Buffer.from("USER guest tolmoon tolsun :Ronnie Reagan\r\n", "ascii")) + mockedSock1.emit('data', Buffer.from("PRIVMSG other_nick :I'm a message\r\n", "ascii")) + }) + it("dont send message to unregistered user", function (done) { + const server = IRCServer.create() + let mockedSock1 = new EventEmitter() + mockedSock1.address = function () { + return {port: 12346, family: 'IPv4', address: '127.0.0.1'} + } + mockedSock1.write = function (data) { + answer = data.toString('ascii') + if (answer.indexOf("401")>=0) { + assert.equal(answer, ":irc.example.com 401 some_nick no such nick/channel") + } + done() + } + mockedSock1.destroy = function () { + done("Destroyed socket without answering") + } + let mockedSock2 = new EventEmitter() + mockedSock2.address = function () { + return {port: 12346, family: 'IPv4', address: '127.0.0.1'} + } + 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\r\n") + done("I got a message that I shouldn't have seen") + } + } + mockedSock2.destroy = function () { + done("Destroyed socket without answering") + } + + server.emit("connection", mockedSock1) + server.emit("connection", mockedSock2) + mockedSock1.emit('data', Buffer.from("NICK some_nick\r\n", "ascii")) + mockedSock1.emit('data', Buffer.from("USER guest tolmoon tolsun :Ronnie Reagan\r\n", "ascii")) + mockedSock2.emit('data', Buffer.from("NICK other_nick\r\n", "ascii")) + mockedSock1.emit('data', Buffer.from("PRIVMSG other_nick :I'm a message\r\n", "ascii")) }) })