Browse Source

Merge commit 'f816cd1adad6c29df25c97b754bed59c30862206' into HEAD

fix/command_quit
Jenkins 5 years ago
parent
commit
5c9fabc9ae
  1. 140
      src/server.js
  2. 57
      test/command_privmsg.js

140
src/server.js

@ -11,89 +11,95 @@ const ERR_NONICKNAMEGIVEN = '431'
const ERR_NICKNAMEINUSE = '433' const ERR_NICKNAMEINUSE = '433'
const ERR_NEEDMOREPARAMS = '461' const ERR_NEEDMOREPARAMS = '461'
let server = {} let server = {}
server.create = function create(config = {}) { server.create = function create(config = {}) {
let password let password
if (config.password) { if (config.password) {
password = config.password
password = config.password
} }
let userlist = {} let userlist = {}
let server = net.createServer((socket) => { let server = net.createServer((socket) => {
const user = new User(socket) const user = new User(socket)
if (!config.password) { if (!config.password) {
user.authenticated = true
user.authenticated = true
} }
socket.on('data', function (data) { socket.on('data', function (data) {
data.toString("ascii").split("\r\n").forEach(function (commandline) { 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 { } 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) => { }).on('error', (err) => {
console.error(err); console.error(err);
}) })

57
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) { it("should handle a PRIVMSG command for multiple users -> PRIVMSG other_nick :I'm a message", function (done) {
const server = IRCServer.create() const server = IRCServer.create()
let mockedSock1 = new EventEmitter() 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) { mockedSock1.write = function (data) {
return return
@ -39,15 +39,15 @@ describe("PRIVMSG OK", function () {
done("Destroyed socket without answering") done("Destroyed socket without answering")
} }
let mockedSock2 = new EventEmitter() 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) { 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 () { mockedSock2.destroy = function () {
done("Destroyed socket without answering") 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("NICK other_nick\r\n", "ascii"))
mockedSock2.emit('data', Buffer.from("USER guest tolmoon tolsun :Ronnie Reagan\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")) mockedSock1.emit('data', Buffer.from("PRIVMSG other_nick :I'm a message\r\n", "ascii"))
}) })
}) })
Loading…
Cancel
Save