diff --git a/bootloader.js b/bootloader.js new file mode 100644 index 0000000..ac09f75 --- /dev/null +++ b/bootloader.js @@ -0,0 +1,19 @@ +// This file is only necessary for compilation to an executable format(if you don't want to install node) +const { + readFileSync +} = require('fs') + +let code +if (process.argv.length < 5) { + code = readFileSync(__dirname + '/server.js') +} else if (process.argv.length > 2) { + code = readFileSync(__dirname + '/client.js') +} +if (process.argv.length < 3) { + process.stdout.write('\nThis program needs either 1 argument, or 3 arguments.\n') + process.stdout.write('For Client: IP, Port, Username\n 127.0.0.1, 30, Steve\n') + process.stdout.write('For Server: Port\n 30\n') + process.exit(0) +} + +eval(code.toString()) diff --git a/client.js b/client.js new file mode 100644 index 0000000..2463752 --- /dev/null +++ b/client.js @@ -0,0 +1,112 @@ +const udp = require('dgram'); +const inp = process.stdin +const out = process.stdout +args = process.argv +fileName = args[1].split('\\'); +msg = `This program needs at least 3 arguments\nIP Port Username\n\nExample:\n${fileName[fileName.length-1]} 127.0.0.1 30 Steve\n\n` +try { + if (args.length < 5) { + process.stderr.write(msg) + process.exit(); + } +} catch { + process.stderr.write(msg) + process.exit() +} // shut up +msg = null; + +ip = process.argv[2] +port = process.argv[3] +username = process.argv[4] +port = parseInt(port) + +inp.setRawMode(true); +inp.resume(); +inp.setEncoding('utf8'); + +const irc = udp.createSocket('udp4') + +irc.bind(port + 1) + +console.log(port, ip) +irc.connect(port, ip, function () { + login = Buffer.allocUnsafe(3) + login[0] = 0x01 + login[1] = 0x02 + login[2] = 0x03 + bufferedUsername = Buffer.from(username) + hello = login + bufferedUsername + irc.send(hello, [port]) +}) + +received = Buffer.allocUnsafe(2) +received[0] = 0x03 +received[1] = 0x01 + +goodbye = Buffer.allocUnsafe(2) +goodbye[0] = 0x01 +goodbye[1] = 0x2F + +userNameDiv = Buffer.allocUnsafe(1) +userNameDiv[0] = 0x02 + +irc.on('message', (msg, rinfo) => { + let userNameParsed = false + let userNameOffSet = 0 + for (let i = 0; i < msg.length; i++) { + if (msg[i] === 2) { + userNameParsed = true + i = 99999 + } else { + userNameOffSet++ + } + } + if (userNameParsed == false) { + out.write('\n\033[1A\033[2K') + out.write('\7' + msg + '\n') + out.write(message.join('')) // rewrite our message so we know what we were trying to say + } else { + out.write('\n\033[1A\033[2K') + out.write(msg.slice(0, userNameOffSet) + ': ' + msg.slice(userNameOffSet + 1) + '\n\7') + out.write(message.join('')) + } + irc.send(received, [port, ip]) +}) + +let message = []; + +inp.on('data', function (key) { + + switch (Buffer.from(key)[0]) { + case 0x0d: { // ENTER + msg = Buffer.from(message.join('')) + out.write('\n\033[1A\033[2K') // delete input line for cleaner interface. + irc.send(msg, [port, ip]) + message = [] + break; + } + case 0x03: { // CTRL+C/Command interrupt + irc.send(goodbye, [port, ip]) + out.write('\n\nDisconnected gracefully.\n') + process.exit(0) + } + case 0x08: { + message.splice(message.length - 1, 1) + out.write('\033[1D\033[0K') + break; + } + case 0x1B: { // Can't have it doing something we REALLY don't want it to. + break; + } + default: { + message.push(key) + out.write(key) + } + } +}) + +process.on('SIGTERM', function() { + irc.send(goodbye, [port, ip],function() { + process.exit(0) + }) +}) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..337db18 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,7 @@ +{ + "name": "node-CLIrc", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { +}} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ed10e36 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "name": "node-CLIrc", + "version": "1.0.0", + "bin" : "./bootloader.js", + "pkg": { + "assets": [ "./*.js" ] + } +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..1f26620 --- /dev/null +++ b/server.js @@ -0,0 +1,74 @@ +const udp = require('dgram'); + +args = process.argv +fileName = args[1].split('\\'); +msg = `This program needs at least 1 argument\nPorts\n\nExample:\n${fileName[fileName.length-1]} 30\n\n` + try { + if (args.length < 3) { + process.stderr.write(msg) + process.exit(); + } + } catch { + process.stderr.write(msg) + process.exit() + } // shut up + msg = null; + +port = process.argv[2] +port = parseInt(port) +const out = process.stdout + +messagingList = []; +names = []; + +const irc = udp.createSocket('udp4') + +irc.bind(port) + +loginMsg = Buffer.allocUnsafe(3) +loginMsg[0] = 0x01 +loginMsg[1] = 0x02 +loginMsg[2] = 0x03 + +goodbye = Buffer.allocUnsafe(2) +goodbye[0] = 0x01 +goodbye[1] = 0x2F + +userNameDiv = Buffer.allocUnsafe(1) +userNameDiv[0] = 0x02 + +received = Buffer.allocUnsafe(2) +received[0] = 0x03 +received[1] = 0x01 + +irc.on('message', (msg, rinfo) => { + let system = false; + if(msg.toString() === received.toString()) { + + } else { + if(msg.slice(0,3).toString() === loginMsg.toString()) { + if(messagingList.indexOf(rinfo.address) === -1) { + messagingList.push(rinfo.address) + names.push(msg.slice(3)) + } + msg = msg.slice(3)+' has connected!' + system = true; +} else if(msg.toString() === goodbye.toString()) { + msg = names[messagingList.indexOf(rinfo.address)]+' has disconnected.' + names.splice(messagingList.indexOf(rinfo.address),1) + messagingList.splice(messagingList.indexOf(rinfo.address),1) + system = true; +} + sender = names[messagingList.indexOf(rinfo.address)] + out.write(sender +' sent: '+msg+'\n') + for(let i = 0; i < messagingList.length;) { + if(system) { + irc.send(msg,port+1,messagingList[i]) + } else { + irc.send(sender+userNameDiv+msg,port+1,messagingList[i]) + } + i++ + + } +} + })