-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathnull.js
139 lines (110 loc) · 3.58 KB
/
null.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import express from 'express'
import http from 'http'
import bodyParser from 'body-parser'
import SocketIO from 'socket.io'
import crypto from 'crypto'
import nunjucks from 'nunjucks'
import { getNick } from './lib/nicknames'
/* initialization */
let app = express()
nunjucks.configure('views', {
autoescape: true,
express: app
})
let server = http.Server(app)
let io = SocketIO(server)
// TODO use redis to store keys & sockets
let users = {}
let rooms = {}
/* middleware */
app.use('/static', express.static('public'))
app.use('/directives', express.static('directives'))
/* routes */
app.get('/', (req, res) => {
res.render('index.html')
})
app.get('/new_chat/', (req, res) => {
var chatKey = crypto.randomBytes(16).toString('hex')
res.redirect('/chat/' + chatKey)
})
app.get('/chat/:roomId', (req, res) => {
var roomId = req.params.roomId
var rsaKeySize = process.env.RSA_KEY_SIZE || 2048
if (!(roomId in rooms)) {
rooms[roomId] = []
}
res.render('null.html', { roomId: roomId, rsaKeySize: rsaKeySize })
})
/* socket */
io.on('connection', (sk) => {
let generatedNick = getNick()
let currentUser = {
id: sk.id,
nick: generatedNick,
pubkey: null,
room: null
}
// emit nick to client
sk.emit('welcome', currentUser.nick)
sk.on('pubkey', (data) => {
// save user's public key
currentUser.pubkey = data
})
sk.on('joinRoom', (roomId) => {
if (!(roomId in rooms) || (rooms[roomId] === undefined)) {
sk.emit('warn', 'Room does not exist.')
sk.disconnect()
return false
}
if (rooms[roomId].length >= 2) {
// room is full; two users maximum
sk.emit('full', 'Room is full.')
sk.disconnect()
return false
}
// join room
sk.join(roomId)
currentUser.room = roomId
if (rooms[roomId].length == 1) {
// there is already a user in the room
// perform public key exchange
var existingUser = rooms[roomId][0]
var existingUserPubkey = existingUser.pubkey
// send existing user's pubkey to the new user
sk.emit('recv_pubkey', existingUserPubkey)
// send new user's pubkey to the existing user
sk.broadcast.to(existingUser.id).emit('recv_pubkey', currentUser.pubkey)
}
// save user to current users
users[sk.id] = currentUser
// add user to roomId
rooms[roomId].push(currentUser)
sk.on('relayMsg', (msg) => {
// relay encrypted message to room
var nick = users[sk.id].nick
sk.to(roomId).emit('newMessage', nick, msg)
})
sk.on('sendExchangeKey', (key, nonce) => {
sk.to(roomId).emit('validateExchange', currentUser.nick, key, nonce)
})
})
sk.on('disconnect', () => {
// if the user disconnects, destroy their room
// and warn any other users of the room that a user has disconnected
if (!(sk.id in users) || users[sk.id] === undefined) {
return
}
let roomId = users[sk.id].room
let nick = users[sk.id].nick
sk.to(roomId).emit('warn', nick + ' has disconnected. This room has been closed.')
sk.to(roomId).emit('roomClosed')
delete rooms[roomId]
delete users[sk.id]
})
sk.on('get_users', (roomId) => {
for (let user in rooms[roomId]) {
sk.emit('warn', rooms[roomId][user].nick + ' joined the room.')
}
})
})
export { server }