|
@@ -35,20 +35,15 @@ export function startSocketServer(port: number): Observable<SocketForConnectedCl
|
|
|
export async function startClientSocketConnection(serverUrl: string): Promise<ClientSocket> {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
try {
|
|
|
- let clientSocket = io(serverUrl)
|
|
|
- // let clientSocket = io(serverUrl, {
|
|
|
- // reconnection: true, // Enable automatic reconnections
|
|
|
- // reconnectionAttempts: 100, // Retry up to 10 times
|
|
|
- // reconnectionDelay: 500, // Start with a 500ms delay
|
|
|
- // reconnectionDelayMax: 10000, // Delay can grow to a max of 10 seconds
|
|
|
- // randomizationFactor: 0.3,
|
|
|
- // })
|
|
|
-
|
|
|
- // Listen for a connection event
|
|
|
- clientSocket.on('connect', () => {
|
|
|
- console.log('Connected to the server:', clientSocket.id)
|
|
|
- resolve(clientSocket)
|
|
|
- });
|
|
|
+ // let clientSocket = io(serverUrl)
|
|
|
+ let clientSocket = io(serverUrl, {
|
|
|
+ reconnection: true, // Enable automatic reconnections
|
|
|
+ reconnectionAttempts: 1000, // Retry up to 10 times
|
|
|
+ reconnectionDelay: 500, // Start with a 500ms delay
|
|
|
+ reconnectionDelayMax: 10000, // Delay can grow to a max of 10 seconds
|
|
|
+ randomizationFactor: 0.3,
|
|
|
+ })
|
|
|
+ resolve(clientSocket)
|
|
|
}
|
|
|
catch (error) {
|
|
|
reject(error)
|
|
@@ -56,39 +51,37 @@ export async function startClientSocketConnection(serverUrl: string): Promise<Cl
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-// Specifically to write receiver profile information
|
|
|
-export async function writeFile(data: ReceiverProfile, filename: string): Promise<boolean> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- // Write JSON data to a file
|
|
|
- fs.writeFile(`${filename}.json`, JSON.stringify(data, null, 2), (err) => {
|
|
|
- if (err) {
|
|
|
- console.error('Error writing file', err);
|
|
|
- reject(false)
|
|
|
- } else {
|
|
|
- console.log('File has been written');
|
|
|
- resolve(true)
|
|
|
- }
|
|
|
- });
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
// After establishing connection to the server, set up the credentials, confirm whether or not if there's any credentials, if not ask for one from the server
|
|
|
export function handleClientSocketConnection(socket: ClientSocket, incomingMessage: Subject<TransportMessage>): Observable<TransportEventNotification> {
|
|
|
return new Observable((eventNotification: Observer<TransportEventNotification>) => {
|
|
|
+ let clientName!: string
|
|
|
let buffer: any[] = []
|
|
|
let receiverProfileInfo!: ReceiverProfile
|
|
|
- checkOwnClientInfo('client1').then((profile: ReceiverProfile) => {
|
|
|
- receiverProfileInfo = profile
|
|
|
- socket.emit('profile', {
|
|
|
- name: 'Old Client',
|
|
|
- data: profile
|
|
|
- })
|
|
|
- }).catch((error) => {
|
|
|
- socket.emit('profile', {
|
|
|
- name: 'New Client',
|
|
|
- data: null
|
|
|
- })
|
|
|
- })
|
|
|
+
|
|
|
+ // Listen for a connection event
|
|
|
+ socket.on('connect', () => {
|
|
|
+ console.log('Connected to the server:', socket.id)
|
|
|
+ if (clientName) {
|
|
|
+ checkOwnClientInfo(clientName).then((profile: ReceiverProfile) => {
|
|
|
+ receiverProfileInfo = profile
|
|
|
+ socket.emit('profile', {
|
|
|
+ name: 'Old Client',
|
|
|
+ data: profile
|
|
|
+ })
|
|
|
+ }).catch((error) => {
|
|
|
+ socket.emit('profile', {
|
|
|
+ name: 'New Client',
|
|
|
+ data: null
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ socket.emit('profile', {
|
|
|
+ name: 'New Client',
|
|
|
+ data: null
|
|
|
+ })
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
// Listen for messages from the server. Generally here's the responses
|
|
|
socket.on('message', (msg: any) => {
|
|
|
console.log(`Websocket Client Transport Receieve Msg`, msg.id)
|
|
@@ -97,7 +90,12 @@ export function handleClientSocketConnection(socket: ClientSocket, incomingMessa
|
|
|
event: 'New Message',
|
|
|
description: 'Received new message',
|
|
|
transportType: 'WEBSOCKET',
|
|
|
- data: msg
|
|
|
+ data: {
|
|
|
+ receiverID: receiverProfileInfo.uuid,
|
|
|
+ receiverName: receiverProfileInfo.name,
|
|
|
+ date: new Date(),
|
|
|
+ payload: msg
|
|
|
+ }
|
|
|
})
|
|
|
incomingMessage.next({
|
|
|
id: msg.header.MessageID,
|
|
@@ -117,30 +115,43 @@ export function handleClientSocketConnection(socket: ClientSocket, incomingMessa
|
|
|
if (data.name == 'New Profile') {
|
|
|
console.log(`Assigned client Name: ${(data.message as ReceiverProfile).name}`)
|
|
|
receiverProfileInfo = data.message as ReceiverProfile
|
|
|
- writeFile(data.message as ReceiverProfile, (data.message as ReceiverProfile).name).then(() => [
|
|
|
+ writeFile(data.message as ReceiverProfile, (data.message as ReceiverProfile).name).then(() => {
|
|
|
+ clientName = receiverProfileInfo.name
|
|
|
// broadcast event to allow retransmission to release buffer
|
|
|
eventNotification.next({
|
|
|
event: 'Connection',
|
|
|
description: 'Profile acquired || updated and stored',
|
|
|
transportType: 'WEBSOCKET',
|
|
|
+ data: {
|
|
|
+ receiverID: receiverProfileInfo.uuid,
|
|
|
+ receiverName: receiverProfileInfo.name,
|
|
|
+ date: new Date(),
|
|
|
+ payload: receiverProfileInfo
|
|
|
+ }
|
|
|
})
|
|
|
- ]).catch((error) => { }) // do nothing at the moment.
|
|
|
+ }).catch((error) => { }) // do nothing at the moment.
|
|
|
}
|
|
|
if (data.name == 'Adjusted Profile') {
|
|
|
console.log(`Assigned client Name: ${(data.message as ReceiverProfile).name}`)
|
|
|
receiverProfileInfo = data.message as ReceiverProfile
|
|
|
- writeFile(data.message as ReceiverProfile, (data.message as ReceiverProfile).name).then(() => [
|
|
|
+ writeFile(data.message as ReceiverProfile, (data.message as ReceiverProfile).name).then(() => {
|
|
|
// broadcast event to allow retransmission to release buffer
|
|
|
eventNotification.next({
|
|
|
event: 'Connection',
|
|
|
description: 'Profile acquired || updated and stored',
|
|
|
transportType: 'WEBSOCKET',
|
|
|
})
|
|
|
- ]).catch((error) => { }) // do nothing at the moment.
|
|
|
+ }).catch((error) => { }) // do nothing at the moment.
|
|
|
}
|
|
|
if (data.name == 'Error') {
|
|
|
console.log(`Server cannot find credentials`, data.message)
|
|
|
// logic to request for new credentials
|
|
|
+ setTimeout(() => {
|
|
|
+ socket.emit('profile', {
|
|
|
+ name: 'New Client',
|
|
|
+ data: null
|
|
|
+ })
|
|
|
+ }, 2000)
|
|
|
}
|
|
|
})
|
|
|
|
|
@@ -158,6 +169,84 @@ export function handleClientSocketConnection(socket: ClientSocket, incomingMessa
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// For SERVER Usage: set up socket listeners to start listening for different events
|
|
|
+export function handleNewSocketClient(socket: SocketForConnectedClient, socketReceiverProfile: ReceiverProfile[]): Observable<TransportEventNotification> {
|
|
|
+ return new Observable((event: Observer<TransportEventNotification>) => {
|
|
|
+ console.log(`Setting up listeners for socket:${socket.id}`)
|
|
|
+ // returns the socket client instance
|
|
|
+ // listen to receiver's initiotion first before assigning 'credentials'
|
|
|
+ socket.on(`profile`, (message: { name: string, data: ReceiverProfile }) => {
|
|
|
+ if (message.name == 'New Client') {
|
|
|
+ let receiverProfile: ReceiverProfile = {
|
|
|
+ uuid: uuidv4(),
|
|
|
+ name: `Client${uuidv4()}`,
|
|
|
+ dateCreated: new Date(),
|
|
|
+ transportType: `WEBSOCKET`,
|
|
|
+ eventNotification: new Subject(),
|
|
|
+ instance: socket
|
|
|
+ }
|
|
|
+ // publish first event notification
|
|
|
+ event.next({
|
|
|
+ event: 'Connection',
|
|
|
+ description: 'New Client Connected',
|
|
|
+ transportType: 'WEBSOCKET',
|
|
|
+ data: {
|
|
|
+ receiverID: receiverProfile.uuid,
|
|
|
+ receiverName: receiverProfile.name,
|
|
|
+ date: new Date(),
|
|
|
+ payload: receiverProfile
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // send to receiver for reference
|
|
|
+ socket.emit('profile', {
|
|
|
+ name: `New Profile`, message: {
|
|
|
+ uuid: receiverProfile.uuid,
|
|
|
+ name: receiverProfile.name,
|
|
|
+ dateCreated: receiverProfile.dateCreated,
|
|
|
+ transportType: `WEBSOCKET`,
|
|
|
+ eventNotification: null,
|
|
|
+ instance: null // have to put null, otherwise circular reference maximum stack error
|
|
|
+ }
|
|
|
+ })
|
|
|
+ socketReceiverProfile.push(receiverProfile)
|
|
|
+ startListening(socket, receiverProfile)
|
|
|
+ } else {
|
|
|
+ // update first
|
|
|
+ let receiverProfile: ReceiverProfile | undefined = socketReceiverProfile.find(obj => obj.uuid === message.data.uuid)
|
|
|
+ if (receiverProfile) {
|
|
|
+ console.log(`Profile ${receiverProfile.uuid} Found`)
|
|
|
+ receiverProfile.instance = socket
|
|
|
+ socket.emit('profile', { name: 'Adjusted Profile', message: receiverProfile })
|
|
|
+ // need to start listening again, because it's assigned a different socket instance this time round
|
|
|
+ startListening(socket, receiverProfile)
|
|
|
+ } else {
|
|
|
+ console.log(`Profile Not Found`)
|
|
|
+ socket.emit('profile', { name: 'Error', message: 'Receiver Profile Not found' })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Specifically to write receiver profile information
|
|
|
+export async function writeFile(data: ReceiverProfile, filename: string): Promise<boolean> {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ // Write JSON data to a file
|
|
|
+ fs.writeFile(`${filename}.json`, JSON.stringify(data, null, 2), (err) => {
|
|
|
+ if (err) {
|
|
|
+ console.error('Error writing file', err);
|
|
|
+ reject(false)
|
|
|
+ } else {
|
|
|
+ console.log('File has been written');
|
|
|
+ resolve(true)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
// Check if filename exists. Return profile information if there's any
|
|
|
export async function checkOwnClientInfo(filename: string): Promise<ReceiverProfile> {
|
|
|
return new Promise((resolve, reject) => {
|
|
@@ -188,62 +277,6 @@ export async function checkOwnClientInfo(filename: string): Promise<ReceiverProf
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-// For SERVER Usage: set up socket listeners to start listening for different events
|
|
|
-export function handleNewSocketClient(socket: SocketForConnectedClient, eventNotification: Subject<TransportEventNotification>, socketReceiverProfile: ReceiverProfile[]): void {
|
|
|
- console.log(`Setting up listeners for socket:${socket.id}`)
|
|
|
- // returns the socket client instance
|
|
|
- // listen to receiver's initiotion first before assigning 'credentials'
|
|
|
- socket.on(`profile`, (message: { name: string, data: ReceiverProfile }) => {
|
|
|
- if (message.name == 'New Client') {
|
|
|
- let receiverProfile: ReceiverProfile = {
|
|
|
- uuid: uuidv4(),
|
|
|
- name: `Client${uuidv4()}`,
|
|
|
- dateCreated: new Date(),
|
|
|
- transportType: `WEBSOCKET`,
|
|
|
- eventNotification: new Subject(),
|
|
|
- instance: socket
|
|
|
- }
|
|
|
- // publish first event notification
|
|
|
- eventNotification.next({
|
|
|
- event: 'Connection',
|
|
|
- description: 'New Client Connected',
|
|
|
- transportType: 'WEBSOCKET',
|
|
|
- data: {
|
|
|
- receiverID: receiverProfile.uuid,
|
|
|
- receiverName: receiverProfile.name,
|
|
|
- date: new Date(),
|
|
|
- payload: receiverProfile
|
|
|
- }
|
|
|
- })
|
|
|
- // send to receiver for reference
|
|
|
- socket.emit('profile', {
|
|
|
- name: `New Profile`, message: {
|
|
|
- uuid: receiverProfile.uuid,
|
|
|
- name: receiverProfile.name,
|
|
|
- dateCreated: receiverProfile.dateCreated,
|
|
|
- transportType: `WEBSOCKET`,
|
|
|
- eventNotification: null,
|
|
|
- instance: null // have to put null, otherwise circular reference maximum stack error
|
|
|
- }
|
|
|
- })
|
|
|
- socketReceiverProfile.push(receiverProfile)
|
|
|
- startListening(socket, receiverProfile)
|
|
|
- } else {
|
|
|
- // update first
|
|
|
- let receiverProfile: ReceiverProfile | undefined = socketReceiverProfile.find(obj => obj.uuid === message.data.uuid)
|
|
|
- if (receiverProfile) {
|
|
|
- receiverProfile.instance = socket
|
|
|
- socket.emit('profile', { name: 'Adjusted Profile', message: receiverProfile })
|
|
|
- // need to start listening again, because it's assigned a different socket instance this time round
|
|
|
- startListening(socket, receiverProfile)
|
|
|
- } else {
|
|
|
- socket.emit('profile', { name: 'Error', message: 'Receiver Profile Not found' })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
export function startListening(socket: SocketForConnectedClient, receiverProfile: ReceiverProfile): void {
|
|
|
/* Generally, we don't need this unless in the case of being the receiver */
|
|
|
socket.on('message', (message: any) => {
|
|
@@ -273,7 +306,7 @@ export function startListening(socket: SocketForConnectedClient, receiverProfile
|
|
|
receiverProfile.eventNotification.next(
|
|
|
{
|
|
|
event: 'Disconnection',
|
|
|
- description: `Existing Client ${socket.id} disonnected`,
|
|
|
+ description: `Existing Client ${receiverProfile.uuid} disonnected`,
|
|
|
transportType: `WEBSOCKET`,
|
|
|
data: {
|
|
|
receiverID: receiverProfile.uuid,
|