Refactor WebSocket message interfaces
Changes:
- Replace AccountTextMessage with an extendable ContactMessage interface
- Add accountId parameter to server-side WebSocket callbacks
- Set the accountId for WebRTC messages on server-side for security
- Rename all WebRTC and SDP variables to proper camelCase or PascalCase
GitLab: #147
Change-Id: I125b5431821b03ef4d46b751eb1c13830017ccff
diff --git a/server/src/websocket/webrtc-handler.ts b/server/src/websocket/webrtc-handler.ts
index abef6e7..da4a374 100644
--- a/server/src/websocket/webrtc-handler.ts
+++ b/server/src/websocket/webrtc-handler.ts
@@ -15,51 +15,39 @@
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
-import { WebSocketMessageTable, WebSocketMessageType } from 'jami-web-common';
+import { ContactMessage, WebSocketMessageType } from 'jami-web-common';
import log from 'loglevel';
import { Container } from 'typedi';
import { Jamid } from '../jamid/jamid.js';
import { WebSocketServer } from './websocket-server.js';
-const jamid = Container.get(Jamid);
-const webSocketServer = Container.get(WebSocketServer);
-
-const webRTCWebSocketMessageTypes = [
- WebSocketMessageType.IceCandidate,
- WebSocketMessageType.WebRTCOffer,
- WebSocketMessageType.WebRTCAnswer,
+const webRtcWebSocketMessageTypes = [
WebSocketMessageType.CallBegin,
WebSocketMessageType.CallAccept,
WebSocketMessageType.CallRefuse,
WebSocketMessageType.CallEnd,
+ WebSocketMessageType.WebRtcOffer,
+ WebSocketMessageType.WebRtcAnswer,
+ WebSocketMessageType.WebRtcIceCandidate,
] as const;
-type WebRTCWebSocketMessageType = typeof webRTCWebSocketMessageTypes[number];
+const jamid = Container.get(Jamid);
+const webSocketServer = Container.get(WebSocketServer);
-function sendWebRTCData<T extends WebRTCWebSocketMessageType>(
- type: WebRTCWebSocketMessageType,
- data: Partial<WebSocketMessageTable[T]>
-) {
- if (data.from === undefined || data.to === undefined) {
- log.warn('Message is not a valid AccountTextMessage (missing from or to fields)');
- return;
- }
- log.info('Handling WebRTC message of type:', type);
- jamid.sendAccountTextMessage(
- data.from,
- data.to,
- JSON.stringify({
- type,
- data,
- })
- );
-}
-
-export function bindWebRTCCallbacks() {
- for (const messageType of webRTCWebSocketMessageTypes) {
- webSocketServer.bind(messageType, (data) => {
- sendWebRTCData(messageType, data);
+export function bindWebRtcCallbacks() {
+ for (const messageType of webRtcWebSocketMessageTypes) {
+ webSocketServer.bind(messageType, (accountId, data) => {
+ sendWebRtcData(messageType, accountId, data);
});
}
}
+
+function sendWebRtcData(type: WebSocketMessageType, accountId: string, data: Partial<ContactMessage>) {
+ if (data.contactId === undefined) {
+ log.warn('Message is not a valid ContactMessage (missing contactId field)');
+ return;
+ }
+
+ jamid.sendAccountTextMessage(accountId, data.contactId, JSON.stringify({ type, data }));
+}
diff --git a/server/src/websocket/websocket-server.ts b/server/src/websocket/websocket-server.ts
index ff28bb9..c1b9904 100644
--- a/server/src/websocket/websocket-server.ts
+++ b/server/src/websocket/websocket-server.ts
@@ -18,14 +18,7 @@
import { IncomingMessage } from 'node:http';
import { Duplex } from 'node:stream';
-import {
- buildWebSocketCallbacks,
- WebSocketCallback,
- WebSocketCallbacks,
- WebSocketMessage,
- WebSocketMessageTable,
- WebSocketMessageType,
-} from 'jami-web-common';
+import { WebSocketMessage, WebSocketMessageTable, WebSocketMessageType } from 'jami-web-common';
import log from 'loglevel';
import { Service } from 'typedi';
import { URL } from 'whatwg-url';
@@ -33,13 +26,24 @@
import { verifyJwt } from '../utils/jwt.js';
+type WebSocketCallback<T extends WebSocketMessageType> = (accountId: string, data: WebSocketMessageTable[T]) => void;
+
+type WebSocketCallbacks = {
+ [key in WebSocketMessageType]: Set<WebSocketCallback<key>>;
+};
+
@Service()
export class WebSocketServer {
private wss = new WebSocket.WebSocketServer({ noServer: true });
private sockets = new Map<string, WebSocket.WebSocket[]>();
- private callbacks: WebSocketCallbacks = buildWebSocketCallbacks();
+ private callbacks: WebSocketCallbacks;
constructor() {
+ this.callbacks = {} as WebSocketCallbacks;
+ for (const messageType of Object.values(WebSocketMessageType)) {
+ this.callbacks[messageType] = new Set<WebSocketCallback<typeof messageType>>();
+ }
+
this.wss.on('connection', (ws: WebSocket.WebSocket, _request: IncomingMessage, accountId: string) => {
log.info('New connection for account', accountId);
const accountSockets = this.sockets.get(accountId);
@@ -63,7 +67,7 @@
const callbacks = this.callbacks[message.type];
for (const callback of callbacks) {
- callback(message.data);
+ callback(accountId, message.data);
}
});