|
@@ -1,11 +1,12 @@
|
|
-import { Observable, Observer, Subject } from 'rxjs';
|
|
|
|
|
|
+import { BehaviorSubject, Observable, Observer, Subject } from 'rxjs';
|
|
import { createServer } from 'http';
|
|
import { createServer } from 'http';
|
|
import { Server, Socket as SocketForConnectedClient } from 'socket.io';
|
|
import { Server, Socket as SocketForConnectedClient } from 'socket.io';
|
|
import { io, Socket as ClientSocket } from 'socket.io-client';
|
|
import { io, Socket as ClientSocket } from 'socket.io-client';
|
|
import * as fs from 'fs'
|
|
import * as fs from 'fs'
|
|
import { v4 as uuidv4 } from 'uuid'
|
|
import { v4 as uuidv4 } from 'uuid'
|
|
-import { TransportEvent } from '../interface/connector.interface';
|
|
|
|
|
|
+import { ConnectionState, Transport, TransportEvent, TransportMessage } from '../interface/connector.interface';
|
|
import { ConnectedClientSocket, ConnectedServerSocket } from '../transport/websocket';
|
|
import { ConnectedClientSocket, ConnectedServerSocket } from '../transport/websocket';
|
|
|
|
+import { EventMessage } from '../interface/transport.interface';
|
|
|
|
|
|
export function startSocketServer(port: number): Observable<SocketForConnectedClient> {
|
|
export function startSocketServer(port: number): Observable<SocketForConnectedClient> {
|
|
return new Observable((observer) => {
|
|
return new Observable((observer) => {
|
|
@@ -57,18 +58,13 @@ export function handleClientSocketConnection(socket: ClientSocket, serversConnec
|
|
return new Observable((eventNotification: Observer<TransportEvent>) => {
|
|
return new Observable((eventNotification: Observer<TransportEvent>) => {
|
|
let clientName!: string
|
|
let clientName!: string
|
|
let buffer: any[] = []
|
|
let buffer: any[] = []
|
|
- let receiverProfileInfo!: ConnectedClientSocket
|
|
|
|
|
|
+ let receiverProfileInfo!: ConnectedServerSocket
|
|
|
|
|
|
// Listen for a connection event
|
|
// Listen for a connection event
|
|
socket.on('connect', () => {
|
|
socket.on('connect', () => {
|
|
console.log('Connected to the server:', socket.id)
|
|
console.log('Connected to the server:', socket.id)
|
|
- serversConnected.push({
|
|
|
|
- id: uuidv4(),
|
|
|
|
- dateCreated: new Date(),
|
|
|
|
- socketInstance: socket
|
|
|
|
- })
|
|
|
|
if (clientName) {
|
|
if (clientName) {
|
|
- checkOwnClientInfo(clientName).then((profile: ConnectedClientSocket) => {
|
|
|
|
|
|
+ checkOwnClientInfo(clientName).then((profile: ConnectedServerSocket) => {
|
|
receiverProfileInfo = profile
|
|
receiverProfileInfo = profile
|
|
socket.emit('profile', {
|
|
socket.emit('profile', {
|
|
name: 'Old Client',
|
|
name: 'Old Client',
|
|
@@ -103,25 +99,49 @@ export function handleClientSocketConnection(socket: ClientSocket, serversConnec
|
|
socket.on('profile', (data: { name: string, message: any }) => {
|
|
socket.on('profile', (data: { name: string, message: any }) => {
|
|
// console.log(data)
|
|
// console.log(data)
|
|
if (data.name == 'New Profile') {
|
|
if (data.name == 'New Profile') {
|
|
- console.log(`Assigned client Name: ${(data.message as ConnectedClientSocket).id}`)
|
|
|
|
- receiverProfileInfo = data.message as ConnectedClientSocket
|
|
|
|
- writeFile(data.message as ConnectedClientSocket, (data.message as ConnectedClientSocket).id).then(() => {
|
|
|
|
|
|
+ console.log(`Assigned client Name: ${(data.message as ConnectedServerSocket).id}`)
|
|
|
|
+ receiverProfileInfo = data.message as ConnectedServerSocket
|
|
|
|
+ writeFile(data.message as ConnectedServerSocket, (data.message as ConnectedServerSocket).id).then(() => {
|
|
clientName = receiverProfileInfo.id
|
|
clientName = receiverProfileInfo.id
|
|
// broadcast event to allow retransmission to release buffer
|
|
// broadcast event to allow retransmission to release buffer
|
|
|
|
+ eventNotification.next({
|
|
|
|
+ id: uuidv4(),
|
|
|
|
+ event: `New Server`,
|
|
|
|
+ data: {
|
|
|
|
+ channelId: (data.message as ConnectedServerSocket).id,
|
|
|
|
+ message: `New Websocket Channel ${(data.message as ConnectedServerSocket).id} established.`
|
|
|
|
+ } as EventMessage
|
|
|
|
+ })
|
|
|
|
|
|
}).catch((error) => { }) // do nothing at the moment.
|
|
}).catch((error) => { }) // do nothing at the moment.
|
|
|
|
+ // Update websocket instance record
|
|
|
|
+ serversConnected.push({
|
|
|
|
+ id: (data.message as ConnectedServerSocket).id,
|
|
|
|
+ dateCreated: new Date(),
|
|
|
|
+ socketInstance: socket,
|
|
|
|
+ connectionState: new BehaviorSubject<ConnectionState>(`ONLINE`)
|
|
|
|
+ })
|
|
}
|
|
}
|
|
if (data.name == 'Adjusted Profile') {
|
|
if (data.name == 'Adjusted Profile') {
|
|
- console.log(`Assigned client Name: ${(data.message as ConnectedClientSocket).id}`)
|
|
|
|
- receiverProfileInfo = data.message as ConnectedClientSocket
|
|
|
|
- writeFile(data.message as ConnectedClientSocket, (data.message as ConnectedClientSocket).id).then(() => {
|
|
|
|
|
|
+ console.log(`Assigned client Name: ${(data.message as ConnectedServerSocket).id}`)
|
|
|
|
+ receiverProfileInfo = data.message as ConnectedServerSocket
|
|
|
|
+ writeFile(data.message as ConnectedServerSocket, (data.message as ConnectedServerSocket).id).then(() => {
|
|
// broadcast event to allow retransmission to release buffer
|
|
// broadcast event to allow retransmission to release buffer
|
|
eventNotification.next({
|
|
eventNotification.next({
|
|
id: uuidv4(),
|
|
id: uuidv4(),
|
|
event: 'Client Reconnected',
|
|
event: 'Client Reconnected',
|
|
- data: ''
|
|
|
|
|
|
+ data: {
|
|
|
|
+ channelId: (data.message as ConnectedServerSocket).id,
|
|
|
|
+ message: `Existing Websocket Channel ${(data.message as ConnectedServerSocket).id} re-established.`
|
|
|
|
+ } as EventMessage
|
|
})
|
|
})
|
|
}).catch((error) => { }) // do nothing at the moment.
|
|
}).catch((error) => { }) // do nothing at the moment.
|
|
|
|
+ // Update websocket instance record
|
|
|
|
+ let clientObj = serversConnected.find(obj => obj.id === (data.message as ConnectedServerSocket).id)
|
|
|
|
+ if (clientObj) {
|
|
|
|
+ clientObj.socketInstance = receiverProfileInfo.socketInstance
|
|
|
|
+ clientObj.connectionState.next('ONLINE')
|
|
|
|
+ }
|
|
}
|
|
}
|
|
if (data.name == 'Error') {
|
|
if (data.name == 'Error') {
|
|
console.log(`Server cannot find credentials`, data.message)
|
|
console.log(`Server cannot find credentials`, data.message)
|
|
@@ -142,8 +162,12 @@ export function handleClientSocketConnection(socket: ClientSocket, serversConnec
|
|
eventNotification.next({
|
|
eventNotification.next({
|
|
id: uuidv4(),
|
|
id: uuidv4(),
|
|
event: `Client Disconnected`,
|
|
event: `Client Disconnected`,
|
|
- data: ''
|
|
|
|
|
|
+ data: {
|
|
|
|
+ channelId: receiverProfileInfo.id,
|
|
|
|
+ message: `Server for Channel ${receiverProfileInfo.id} disconnected.`
|
|
|
|
+ } as EventMessage
|
|
})
|
|
})
|
|
|
|
+ receiverProfileInfo.connectionState.next(`OFFLINE`)
|
|
}
|
|
}
|
|
});
|
|
});
|
|
})
|
|
})
|
|
@@ -160,13 +184,18 @@ export function handleNewSocketClient(socket: SocketForConnectedClient, connecte
|
|
let clientInstance: ConnectedClientSocket = {
|
|
let clientInstance: ConnectedClientSocket = {
|
|
id: uuidv4(),
|
|
id: uuidv4(),
|
|
dateCreated: new Date(),
|
|
dateCreated: new Date(),
|
|
- socketInstance: socket
|
|
|
|
|
|
+ socketInstance: socket,
|
|
|
|
+ connectionState: new BehaviorSubject<ConnectionState>(`ONLINE`)
|
|
}
|
|
}
|
|
// publish first event notification
|
|
// publish first event notification
|
|
event.next({
|
|
event.next({
|
|
id: uuidv4(),
|
|
id: uuidv4(),
|
|
event: `New Client`,
|
|
event: `New Client`,
|
|
- data: clientInstance
|
|
|
|
|
|
+ data: {
|
|
|
|
+ channelId: clientInstance.id,
|
|
|
|
+ message: `New Client Connected. Channel ID assigned: ${clientInstance.id}`,
|
|
|
|
+ payload: clientInstance
|
|
|
|
+ } as EventMessage
|
|
})
|
|
})
|
|
// send to receiver for reference
|
|
// send to receiver for reference
|
|
socket.emit('profile', {
|
|
socket.emit('profile', {
|
|
@@ -183,6 +212,19 @@ export function handleNewSocketClient(socket: SocketForConnectedClient, connecte
|
|
socket.emit('profile', { name: 'Adjusted Profile', message: clientInstance })
|
|
socket.emit('profile', { name: 'Adjusted Profile', message: clientInstance })
|
|
// need to start listening again, because it's assigned a different socket instance this time round
|
|
// need to start listening again, because it's assigned a different socket instance this time round
|
|
startListening(socket, clientInstance, event)
|
|
startListening(socket, clientInstance, event)
|
|
|
|
+ event.next({
|
|
|
|
+ id: uuidv4(),
|
|
|
|
+ event: 'Client Reconnected',
|
|
|
|
+ data: {
|
|
|
|
+ channelId: clientInstance.id,
|
|
|
|
+ message: `Client ${clientInstance.id} connection re-established`,
|
|
|
|
+ payload: clientInstance
|
|
|
|
+ } as EventMessage
|
|
|
|
+ })
|
|
|
|
+ // Resume operation
|
|
|
|
+ if (clientInstance.connectionState.getValue() == 'OFFLINE') {
|
|
|
|
+ clientInstance.connectionState.next(`ONLINE`)
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
console.log(`Profile Not Found`)
|
|
console.log(`Profile Not Found`)
|
|
socket.emit('profile', { name: 'Error', message: 'Receiver Profile Not found' })
|
|
socket.emit('profile', { name: 'Error', message: 'Receiver Profile Not found' })
|
|
@@ -194,7 +236,7 @@ export function handleNewSocketClient(socket: SocketForConnectedClient, connecte
|
|
|
|
|
|
|
|
|
|
// Specifically to write receiver profile information
|
|
// Specifically to write receiver profile information
|
|
-export async function writeFile(data: ConnectedClientSocket, filename: string): Promise<boolean> {
|
|
|
|
|
|
+export async function writeFile(data: ConnectedServerSocket, filename: string): Promise<boolean> {
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
// Write JSON data to a file
|
|
// Write JSON data to a file
|
|
fs.writeFile(`${filename}.json`, JSON.stringify(data, null, 2), (err) => {
|
|
fs.writeFile(`${filename}.json`, JSON.stringify(data, null, 2), (err) => {
|
|
@@ -212,7 +254,7 @@ export async function writeFile(data: ConnectedClientSocket, filename: string):
|
|
|
|
|
|
|
|
|
|
// Check if filename exists. Return profile information if there's any
|
|
// Check if filename exists. Return profile information if there's any
|
|
-export async function checkOwnClientInfo(filename: string): Promise<ConnectedClientSocket> {
|
|
|
|
|
|
+export async function checkOwnClientInfo(filename: string): Promise<ConnectedServerSocket> {
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
// Check if the file exists
|
|
// Check if the file exists
|
|
if (fs.existsSync(`${filename}.json`)) {
|
|
if (fs.existsSync(`${filename}.json`)) {
|
|
@@ -248,36 +290,12 @@ export function startListening(socket: SocketForConnectedClient, client: Connect
|
|
id: uuidv4(),
|
|
id: uuidv4(),
|
|
event: 'New Message',
|
|
event: 'New Message',
|
|
data: {
|
|
data: {
|
|
- clientID: client.id,
|
|
|
|
- dateReceived: new Date(),
|
|
|
|
- payload: message
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- socket.on('request', (message: any) => {
|
|
|
|
- // here : Let's say there's a subcsription request here
|
|
|
|
- eventListener.next({
|
|
|
|
- id: uuidv4(),
|
|
|
|
- event: 'New Message',
|
|
|
|
- data: {
|
|
|
|
- clientID: client.id,
|
|
|
|
- dateReceived: new Date(),
|
|
|
|
|
|
+ id: uuidv4(),
|
|
|
|
+ dateCreated: new Date(),
|
|
|
|
+ transport: Transport.Websocket,
|
|
|
|
+ target: client.id, // this would have been assigned it's own adapter with the associated ID
|
|
payload: message
|
|
payload: message
|
|
- }
|
|
|
|
- })
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- socket.on('notification', (notification: any) => {
|
|
|
|
- // logic here
|
|
|
|
- eventListener.next({
|
|
|
|
- id: uuidv4(),
|
|
|
|
- event: `Notification`,
|
|
|
|
- data: {
|
|
|
|
- clientID: client.id,
|
|
|
|
- dateReceived: new Date(),
|
|
|
|
- payload: notification
|
|
|
|
- }
|
|
|
|
|
|
+ } as TransportMessage
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
|
|
@@ -295,4 +313,3 @@ export function startListening(socket: SocketForConnectedClient, client: Connect
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|