Anne Lefebvre commited on
Commit
2ca92eb
·
2 Parent(s): a3bbdc4 d4fcf4a

Merge pull request #13 from AnujPanthri/server_new_id

Browse files
server/package-lock.json CHANGED
@@ -10,6 +10,7 @@
10
  "license": "ISC",
11
  "dependencies": {
12
  "@types/ws": "^8.5.9",
 
13
  "express": "^4.18.2",
14
  "pino": "^8.16.2",
15
  "ws": "^8.14.2",
@@ -341,6 +342,11 @@
341
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
342
  "dev": true
343
  },
 
 
 
 
 
344
  "node_modules/base64-js": {
345
  "version": "1.5.1",
346
  "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
 
10
  "license": "ISC",
11
  "dependencies": {
12
  "@types/ws": "^8.5.9",
13
+ "base-x": "^4.0.0",
14
  "express": "^4.18.2",
15
  "pino": "^8.16.2",
16
  "ws": "^8.14.2",
 
342
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
343
  "dev": true
344
  },
345
+ "node_modules/base-x": {
346
+ "version": "4.0.0",
347
+ "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz",
348
+ "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw=="
349
+ },
350
  "node_modules/base64-js": {
351
  "version": "1.5.1",
352
  "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
server/package.json CHANGED
@@ -26,6 +26,7 @@
26
  },
27
  "dependencies": {
28
  "@types/ws": "^8.5.9",
 
29
  "express": "^4.18.2",
30
  "pino": "^8.16.2",
31
  "ws": "^8.14.2",
 
26
  },
27
  "dependencies": {
28
  "@types/ws": "^8.5.9",
29
+ "base-x": "^4.0.0",
30
  "express": "^4.18.2",
31
  "pino": "^8.16.2",
32
  "ws": "^8.14.2",
server/src/helpers.ts CHANGED
@@ -1,7 +1,15 @@
1
  import * as crypto from "crypto";
 
2
 
3
  export function generateSessionToken(length: number): string {
4
- if (length < 1) throw new Error("invalid length. length must be greater than 0")
5
- return crypto.randomBytes(length).toString("hex");
6
- }
 
 
7
 
 
 
 
 
 
 
1
  import * as crypto from "crypto";
2
+ import basex from "base-x";
3
 
4
  export function generateSessionToken(length: number): string {
5
+ if (length < 1) throw new Error("invalid length. length must be greater than 0");
6
+ const base31Tokens = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
7
+ const base31 = basex(base31Tokens);
8
+
9
+ const byteLength = Math.ceil((length * Math.log(256)) / Math.log(base31Tokens.length)) + 2;
10
 
11
+ const buffer = crypto.randomBytes(Math.ceil(byteLength));
12
+ const token = base31.encode(buffer);
13
+
14
+ return token.substring(0, length);
15
+ }
server/src/socket/hapticLinkServer.ts CHANGED
@@ -12,13 +12,14 @@ export interface Route<T> {
12
  }
13
 
14
  export class User {
 
15
  id: string;
16
  username?: string;
17
  socket: WebSocketInterface;
18
  currentRoom?: Room;
19
 
20
  constructor(socket: WebSocketInterface) {
21
- this.id = generateSessionToken(16);
22
  this.socket = socket;
23
  }
24
  }
 
12
  }
13
 
14
  export class User {
15
+ static userIdLength: number = 32
16
  id: string;
17
  username?: string;
18
  socket: WebSocketInterface;
19
  currentRoom?: Room;
20
 
21
  constructor(socket: WebSocketInterface) {
22
+ this.id = generateSessionToken(32);
23
  this.socket = socket;
24
  }
25
  }
server/src/socket/room.ts CHANGED
@@ -9,10 +9,11 @@ export interface UserData {
9
  }
10
 
11
  export class Room {
 
12
  id: string;
13
  users: User[];
14
  constructor(roomId?: string) {
15
- this.id = roomId || generateSessionToken(16);
16
  this.users = [];
17
  }
18
 
 
9
  }
10
 
11
  export class Room {
12
+ static roomIdLength: number = 6;
13
  id: string;
14
  users: User[];
15
  constructor(roomId?: string) {
16
+ this.id = roomId || generateSessionToken(Room.roomIdLength);
17
  this.users = [];
18
  }
19
 
server/src/socket/routes/join_room.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { z } from "zod";
2
- import { Context, Route } from "../hapticLinkServer";
3
- import { generateSessionToken } from "../../helpers";
4
  import { Room } from "../room";
5
 
6
  export interface JoinRoomPayload {
@@ -18,17 +17,26 @@ export function JoinRoomHandler(ctx: Context<JoinRoomPayload>) {
18
  ctx.user.username = ctx.payload.username;
19
  }
20
 
 
 
21
  let room: Room;
22
 
23
  if (ctx.payload.roomId && !ctx.server.rooms[ctx.payload.roomId]) {
24
  // User sent roomId, but room doesn't exist
25
- room = new Room(ctx.payload.roomId);
26
- ctx.server.rooms[room.id] = room;
 
 
 
 
 
 
27
 
28
  } else if (!ctx.payload.roomId) {
29
  // Didn't include RoomID, creating new one
30
- ctx.payload.roomId = generateSessionToken(12);
31
  room = new Room(ctx.payload.roomId);
 
 
32
  ctx.server.rooms[room.id] = room;
33
 
34
  } else {
 
1
  import { z } from "zod";
2
+ import { Context } from "../hapticLinkServer";
 
3
  import { Room } from "../room";
4
 
5
  export interface JoinRoomPayload {
 
17
  ctx.user.username = ctx.payload.username;
18
  }
19
 
20
+ if (ctx.payload.roomId) ctx.payload.roomId = ctx.payload.roomId.toUpperCase();
21
+
22
  let room: Room;
23
 
24
  if (ctx.payload.roomId && !ctx.server.rooms[ctx.payload.roomId]) {
25
  // User sent roomId, but room doesn't exist
26
+ return ctx.ws.send(JSON.stringify({
27
+ "message": "join_room_response",
28
+ "status": "room doesn't exist",
29
+ }))
30
+ // Custom ID Code:
31
+ // room = new Room(ctx.payload.roomId);
32
+ // room.id = room.id.toUpperCase();
33
+ // ctx.server.rooms[room.id] = room;
34
 
35
  } else if (!ctx.payload.roomId) {
36
  // Didn't include RoomID, creating new one
 
37
  room = new Room(ctx.payload.roomId);
38
+ room.id = room.id.toUpperCase();
39
+ ctx.payload.roomId = room.id;
40
  ctx.server.rooms[room.id] = room;
41
 
42
  } else {
server/test/helpers.spec.ts CHANGED
@@ -8,12 +8,12 @@ describe('Helpers', () => {
8
 
9
  // Since the token is hexadecimal, its string length should be twice the byte length
10
  expect(token).to.be.a('string');
11
- expect(token.length).to.equal(length * 2);
12
  });
13
 
14
  it('should generate a unique token each time', () => {
15
  const tokens = new Set<string>();
16
- const tokenCount = 100; // Generate a number of tokens to test uniqueness
17
  const length = 16;
18
 
19
  for (let i = 0; i < tokenCount; i++) {
 
8
 
9
  // Since the token is hexadecimal, its string length should be twice the byte length
10
  expect(token).to.be.a('string');
11
+ expect(token.length).to.equal(length);
12
  });
13
 
14
  it('should generate a unique token each time', () => {
15
  const tokens = new Set<string>();
16
+ const tokenCount = 1000; // Generate a number of tokens to test uniqueness
17
  const length = 16;
18
 
19
  for (let i = 0; i < tokenCount; i++) {
server/test/socket/routes/join_room.spec.ts CHANGED
@@ -43,6 +43,16 @@ describe("Join Room", () => {
43
  expect(ctx.payload.roomId!).to.satisfy((id: string) => id.length > 3, "room id not generated");
44
  expect(user.username).to.equal("test", "didn't set username");
45
  });
 
 
 
 
 
 
 
 
 
 
46
 
47
  it("should join existing room", () => {
48
  testJoinRoom(1); // Initial user joins and creates room
@@ -58,4 +68,16 @@ describe("Join Room", () => {
58
  JoinRoomHandler(ctx);
59
  expect(server.rooms[ctx.payload.roomId!].users.length).to.equal(2, "user joined twice");
60
  });
 
 
 
 
 
 
 
 
 
 
 
 
61
  });
 
43
  expect(ctx.payload.roomId!).to.satisfy((id: string) => id.length > 3, "room id not generated");
44
  expect(user.username).to.equal("test", "didn't set username");
45
  });
46
+
47
+ it("should fail to join not existant room", () => {
48
+ ctx.payload.roomId = "testid"
49
+ JoinRoomHandler(ctx);
50
+ const resData = (ws.sendData as string);
51
+ const res = JSON.parse(resData);
52
+ expect(res.message).to.eq("join_room_response", "didn't get server response");
53
+ const roomNowExists = server.rooms["testid"]
54
+ expect(roomNowExists).to.equal(undefined, "server allowed to join non-existant room");
55
+ });
56
 
57
  it("should join existing room", () => {
58
  testJoinRoom(1); // Initial user joins and creates room
 
68
  JoinRoomHandler(ctx);
69
  expect(server.rooms[ctx.payload.roomId!].users.length).to.equal(2, "user joined twice");
70
  });
71
+
72
+ it("should have case insensitive IDs", () => {
73
+ testJoinRoom(1); // Initial user joins and creates room
74
+
75
+ // Set up second user to join the same room
76
+ ctx.payload.username = "test2";
77
+ ctx.user = user2;
78
+ ctx.ws = ws2;
79
+ ctx.payload.roomId = ctx.payload.roomId?.toLowerCase();
80
+
81
+ testJoinRoom(2); // Second user joins the existing room
82
+ })
83
  });
server/test/socket/routes/send_touch.spec.ts CHANGED
@@ -24,13 +24,13 @@ describe("Send Vibration", () => {
24
  ctx = {
25
  ws: ws,
26
  user: user,
27
- payload: { username: "test", roomId: "testRoom" },
28
  server: server,
29
  };
30
  ctx2 = {
31
  ws: ws2,
32
  user: user2,
33
- payload: { username: "test2", roomId: "testRoom" },
34
  server: server,
35
  };
36
 
@@ -54,6 +54,8 @@ describe("Send Vibration", () => {
54
 
55
  it("should broadcast vibration", () => {
56
  JoinRoomHandler(ctx)
 
 
57
  JoinRoomHandler(ctx2)
58
  ws.sendData = "";
59
  ws2.sendData = "";
 
24
  ctx = {
25
  ws: ws,
26
  user: user,
27
+ payload: { username: "test" },
28
  server: server,
29
  };
30
  ctx2 = {
31
  ws: ws2,
32
  user: user2,
33
+ payload: { username: "test2" },
34
  server: server,
35
  };
36
 
 
54
 
55
  it("should broadcast vibration", () => {
56
  JoinRoomHandler(ctx)
57
+ const resData = JSON.parse(ws.sendData as string)
58
+ ctx2.payload.roomId = resData.roomId
59
  JoinRoomHandler(ctx2)
60
  ws.sendData = "";
61
  ws2.sendData = "";