/
server.ts
134 lines (116 loc) · 4.19 KB
/
server.ts
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
import { Client } from "./client.ts";
import { EventHandler } from "./eventhandler.ts";
import { Packet } from "./packet.ts";
import type { WebSocket } from "../deps.ts";
import type { HTTPOptions } from "../deps.ts";
import { serve, DenoServer, ServerRequest, serveFile, acceptWebSocket, isWebSocketCloseEvent } from "../deps.ts";
/**
* Class that handles WebSocket messages.
* Uses Client objects and an EventHandler object
* to send messages to Clients.
*/
export class Sono {
public server: DenoServer | null = null;
public hostname = 'localhost';
public clients: {[key: string]: Client} = {};
public channelsList: {[key: string]: Record<string, Client>} = {'home': {}};
public eventHandler: EventHandler;
public lastClientId: number = 1000;
/**
* Constructor creates a new instance of the Event,
* binds handleWs to this and returns a Sono instance.
*/
constructor() {
this.eventHandler = new EventHandler();
this.handleWs = this.handleWs.bind(this);
}
// /**
// * Start server listening on passed-in port number.
// * @param {number} port - Port that Sono.server listens to.
// */
// listen(port: number): DenoServer {
// const options: HTTPOptions = {port};
// this.server = serve(options);
// this.awaitRequests(this.server);
// return this.server;
// }
/**
* Adding a channel to channelsList object
* @param { name } - name of channel
*/
channel(name: string, callback: () => void) :void {
this.channelsList[name] = {};
callback();
return;
}
// /**
// * awaitRequests handles requests to server and returns undefined
// * @param { DenoServer } - Sono.server from which requests are sent from
// */
// async awaitRequests(server: DenoServer):Promise<void> {
// // iterate over async request objects to server
// for await(const req of server) {
// this.handler(req);
// }
// }
connect(req: ServerRequest, callback: () => void){
const { conn, w:bufWriter, r:bufReader, headers } = req;
acceptWebSocket({conn, bufWriter, bufReader, headers})
.then(this.handleWs)
.catch(err => console.log(err, 'err'))
callback();
}
emit(message: string){
Object.values(this.clients).forEach(client => {
client.socket.send(JSON.stringify({message}))
})
}
/**
* handleWS method handles a socket connection
* Instantiants a new client
* Events of socket are looped thru and dealt with accordingly
* @param { WebSocket } - WebSocket connection from a client
*/
async handleWs (socket: WebSocket):Promise<void> {
// create new client, add to clients object, add client to home channel
const client = new Client(socket, this.lastClientId);
this.lastClientId = client.id
this.clients[client.id] = client;
this.channelsList['home'][client.id] = client;
for await(const message of socket){
// if client sends close websocket event, delete client
if (isWebSocketCloseEvent(message) || typeof message !== 'string'){
delete this.channelsList[client.channel][client.id];
delete this.clients[client.id]
break;
}
const data: Packet = JSON.parse(message)
// const event = new Event(data.protocol)
// const grab = data.payload.message;
// depending on data.protocol, invoke an eventHandler method
switch(data.protocol) {
case 'message':
// console.log('case message', this.clients)
this.eventHandler.handleMessage(data, client, this.channelsList);
break;
case 'broadcast':
this.eventHandler.broadcast(data, client, this.channelsList)
break;
case 'changeChannel':
this.channelsList = this.eventHandler.changeChannel(data, client, this.channelsList);
// console.log('case channel', this.channelsList);
break;
case 'directmessage':
this.eventHandler.directMessage(data, client, this.clients);
break;
case 'grab':
this.eventHandler.grab(data, client, this.clients, this.channelsList);
break;
default:
// this.eventHandler
// console.log('default hit', data)
console.log('default case in testServer');
}
}
}
}