|
@@ -1,85 +1,80 @@
|
|
import { Observable, Subject } from "rxjs";
|
|
import { Observable, Subject } from "rxjs";
|
|
-import { io, Socket, Socket as SocketClient } from "socket.io-client";
|
|
|
|
-import { Socket as SocketServer } from "socket.io"
|
|
|
|
|
|
+import { Socket, Socket as ClientSocket } from "socket.io-client";
|
|
|
|
+import { Socket as SocketForConnectedClient } from "socket.io"
|
|
import { startClientSocketConnection, startSocketServer } from "../utils/socket.utils";
|
|
import { startClientSocketConnection, startSocketServer } from "../utils/socket.utils";
|
|
-import { ITransport, ReceiverProfile, TransportEventNotification, TransportSettings } from "../interface/ITransport.interface";
|
|
|
|
-import { error } from "console";
|
|
|
|
|
|
+import { ITransportReceiving, ITransportTransmitting, ReceiverProfile, TransmitterProfile, TransportEventNotification, TransportMessage, TransportSettings } from "../interface/ITransport.interface";
|
|
import { v4 as uuidv4 } from 'uuid'
|
|
import { v4 as uuidv4 } from 'uuid'
|
|
|
|
|
|
-export class WebsocketTransportService implements ITransport {
|
|
|
|
- private websocketRole!: 'Server' | 'Client' | null
|
|
|
|
- private clientSocket!: SocketClient
|
|
|
|
- private connectedClient: ReceiverProfile[] = []
|
|
|
|
- private responseSubject: Subject<any> = new Subject()
|
|
|
|
|
|
+/* Just code in the context that this websocket service will be handling multiple UI clients. Can think about the server communication at a later time. */
|
|
|
|
+export class WebsocketTransportService implements ITransportTransmitting, ITransportReceiving {
|
|
|
|
+ private transmitterProfile!: TransmitterProfile | null
|
|
|
|
+ private socketReceiverProfile: ReceiverProfile[] = []
|
|
|
|
+ private clientSocket!: ClientSocket
|
|
|
|
+ private incomingMessage: Subject<TransportMessage> = new Subject()
|
|
private eventNotification: Subject<TransportEventNotification> = new Subject()
|
|
private eventNotification: Subject<TransportEventNotification> = new Subject()
|
|
|
|
|
|
constructor(setting: TransportSettings) {
|
|
constructor(setting: TransportSettings) {
|
|
- this.websocketRole == setting.role
|
|
|
|
- if (setting.role == 'Server') {
|
|
|
|
- startSocketServer(setting.profileInfo.port as number).subscribe({
|
|
|
|
- next: (connectedClient: SocketServer) => {
|
|
|
|
- // returns the socket client instance
|
|
|
|
- let receiverProfile: ReceiverProfile = {
|
|
|
|
- uuid: uuidv4(),
|
|
|
|
- name: `Client`,
|
|
|
|
- dateCreated: new Date(),
|
|
|
|
- data: connectedClient
|
|
|
|
- }
|
|
|
|
- this.eventNotification.next({ event: 'WebsocketClientConnection', description: 'New Client Connected', data: receiverProfile })
|
|
|
|
- this.connectedClient.push(receiverProfile)
|
|
|
|
-
|
|
|
|
- // put here first, but can me mgirated to other parts of the code
|
|
|
|
- connectedClient.on('disconnect', () => {
|
|
|
|
- this.eventNotification.next({ event: 'WebscoketClientConnection', description: `Existing Client ${connectedClient.id} disonnected`, data: receiverProfile })
|
|
|
|
- })
|
|
|
|
- },
|
|
|
|
- error: error => console.error(error),
|
|
|
|
- complete: () => { } // should not complete. Keep listening to new client connection
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
- // just focus on receiving.
|
|
|
|
- if (setting.role == 'Client') {
|
|
|
|
- startClientSocketConnection(setting.profileInfo.url as string).then((client: Socket) => {
|
|
|
|
- this.clientSocket = client
|
|
|
|
- // Need to open to listen to incoming responses
|
|
|
|
- this.clientSocket.on('message', (message) => {
|
|
|
|
- // console.log(message)
|
|
|
|
- this.responseSubject.next(message)
|
|
|
|
- })
|
|
|
|
- this.clientSocket.on('notification', (notification) => {
|
|
|
|
- // console.log(notification)
|
|
|
|
- if (notification.header.messageName == 'NotificationMessage') {
|
|
|
|
- this.eventNotification.next({ event: 'Server Notification', description: 'Notification from server', data: notification })
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- this.clientSocket.on('disconnect', () => {
|
|
|
|
- this.eventNotification.next({ event: 'Websocket Client Connection Status', description: 'Server disconnected' })
|
|
|
|
- })
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
|
|
+ startSocketServer(setting.profileInfo.port as number).subscribe({
|
|
|
|
+ next: (connectedClient: SocketForConnectedClient) => {
|
|
|
|
+ this.handleNewSocketClient(connectedClient)
|
|
|
|
+ },
|
|
|
|
+ error: error => console.error(error),
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
|
|
- // to be used to emulate request response. But only for sending request, since all the response are to be redirected to another output
|
|
|
|
- send(message: any, target?: string): void {
|
|
|
|
- let socket = this.connectedClient.find(object => object.uuid === target)
|
|
|
|
- if (socket) {
|
|
|
|
- socket.data.emit('message', message)
|
|
|
|
- }
|
|
|
|
|
|
+ // for transmission(Server Only, not applicable for client Socket)
|
|
|
|
+ public async transmit(message: TransportMessage): Promise<string> {
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
+ let receiverInstance = this.socketReceiverProfile.find(obj => obj.uuid === message.receiverID);
|
|
|
|
+ if (receiverInstance) {
|
|
|
|
+ (receiverInstance?.instance as SocketForConnectedClient).emit(message.event, message.payload)
|
|
|
|
+ resolve('Message called for delivery...')
|
|
|
|
+ } else {
|
|
|
|
+ reject(`Receiver cannot be found or doesn't exist...`)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
|
|
- emit(event: string, message: any): void {
|
|
|
|
- // for now just assume everyone is subscribed to this broacdcast
|
|
|
|
- this.connectedClient.forEach(client => {
|
|
|
|
- client.data.emit(event, message)
|
|
|
|
- });
|
|
|
|
|
|
+ public getEventNotification(): Observable<TransportEventNotification> {
|
|
|
|
+ return this.eventNotification as Observable<TransportEventNotification>
|
|
}
|
|
}
|
|
|
|
|
|
- getResponse(): Observable<any> {
|
|
|
|
- return this.responseSubject.asObservable()
|
|
|
|
- }
|
|
|
|
|
|
+ // Set up socket listeners to start listening for different events
|
|
|
|
+ private handleNewSocketClient(socket: SocketForConnectedClient): void {
|
|
|
|
+ console.log(`Setting up listeners for socket:${socket.id}`)
|
|
|
|
+ // returns the socket client instance
|
|
|
|
+ let receiverProfile: ReceiverProfile = {
|
|
|
|
+ uuid: uuidv4(),
|
|
|
|
+ name: `Client`,
|
|
|
|
+ dateCreated: new Date(),
|
|
|
|
+ transportType: `WEBSOCKET`,
|
|
|
|
+ eventNotification: new Subject(),
|
|
|
|
+ instance: socket
|
|
|
|
+ }
|
|
|
|
+ this.eventNotification.next({ event: 'Connection', description: 'New Client Connected', transportType: `WEBSOCKET`, data: receiverProfile })
|
|
|
|
+ this.socketReceiverProfile.push(receiverProfile)
|
|
|
|
|
|
- getEventNotification(): Observable<TransportEventNotification> {
|
|
|
|
- return this.eventNotification as Observable<TransportEventNotification>
|
|
|
|
|
|
+ /* Generally, we don't need this unless in the case of being the receiver */
|
|
|
|
+ socket.on('message', (message: any) => {
|
|
|
|
+ // here
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ socket.on('request', (request: any) => {
|
|
|
|
+ // here
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ socket.on('notification', (notification: any) => {
|
|
|
|
+ // logic here
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ socket.on('disconnect', () => {
|
|
|
|
+ receiverProfile.eventNotification.next({ event: 'Connection', description: `Existing Client ${socket.id} disonnected`, transportType: `WEBSOCKET`, data: receiverProfile })
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
|
|
-}
|
|
|
|
|
|
+
|
|
|
|
+ // for client UI eg
|
|
|
|
+ public receive(): Observable<any> {
|
|
|
|
+ return this.incomingMessage.asObservable()
|
|
|
|
+ }
|
|
|
|
+}
|