Browse Source

receiver can also be transmitting. SOme more enhancments

Enzo 1 month ago
parent
commit
7baca40161

+ 0 - 3
00d7df06-395d-4ccd-9473-dd26d58535d6.json

@@ -1,3 +0,0 @@
-{
-  "id": "00d7df06-395d-4ccd-9473-dd26d58535d6"
-}

+ 0 - 3
5975a712-9d61-4bc2-81af-2c05c772b59f.json

@@ -1,3 +0,0 @@
-{
-  "id": "5975a712-9d61-4bc2-81af-2c05c772b59f"
-}

+ 0 - 3
b2a18219-ee84-4872-bc64-e6f8a7afa6e4.json

@@ -1,3 +0,0 @@
-{
-  "id": "b2a18219-ee84-4872-bc64-e6f8a7afa6e4"
-}

+ 0 - 26
clients.json

@@ -1,26 +0,0 @@
-[
-  {
-    "id": "5975a712-9d61-4bc2-81af-2c05c772b59f",
-    "dateCreated": "2024-11-14T02:53:13.306Z",
-    "connectionState": null,
-    "socketInstance": null
-  },
-  {
-    "id": "b2a18219-ee84-4872-bc64-e6f8a7afa6e4",
-    "dateCreated": "2024-11-14T02:55:35.822Z",
-    "connectionState": null,
-    "socketInstance": null
-  },
-  {
-    "id": "00d7df06-395d-4ccd-9473-dd26d58535d6",
-    "dateCreated": "2024-11-14T03:20:30.133Z",
-    "connectionState": null,
-    "socketInstance": null
-  },
-  {
-    "id": "d6ff43cc-6a52-497c-9af5-ca3b9e21be7b",
-    "dateCreated": "2024-11-14T03:22:33.808Z",
-    "connectionState": null,
-    "socketInstance": null
-  }
-]

+ 0 - 3
d6ff43cc-6a52-497c-9af5-ca3b9e21be7b.json

@@ -1,3 +0,0 @@
-{
-  "id": "d6ff43cc-6a52-497c-9af5-ca3b9e21be7b"
-}

+ 11 - 4
doc/explanation.txt

@@ -16,7 +16,7 @@ Retransmission will be implemented at the transmission level.
 Please note that the current code is only tested with one on one, which means only 1 server and 1 client, and it's a one way communication at the moment. I have yet to test it with
 Please note that the current code is only tested with one on one, which means only 1 server and 1 client, and it's a one way communication at the moment. I have yet to test it with
 multiple clients, but the current test is working so far with the retransmission. To emulate internet disruption without manually shutting down both the server and the client, I 
 multiple clients, but the current test is working so far with the retransmission. To emulate internet disruption without manually shutting down both the server and the client, I 
 came up with an idea of writing another middle-man. or a proxy if you would, to simluate internet disruption by just shutting off the proxy, so that the socket on each side of the 
 came up with an idea of writing another middle-man. or a proxy if you would, to simluate internet disruption by just shutting off the proxy, so that the socket on each side of the 
-party can pick up the event, and notify/broadcast the information to the parties concerned. That's where the retranismission can shine.
+party can pick up the event, and notify/broadcast the information to the parties concerned. That's where the retransmission can shine.
 
 
 
 
 Things to do:
 Things to do:
@@ -32,7 +32,7 @@ Final ii) Clean Code (Usually this is done after prototype is functionally accep
 
 
 As of 14/11/2024 <Since there's no slot for meeting for the rest of the week>
 As of 14/11/2024 <Since there's no slot for meeting for the rest of the week>
 Things to consider:
 Things to consider:
-i) Multi Client test.
+i) Multi Client test. <Based on chin, this is out of my scope, but will do anyways.>
 -Make sure it can work with multiple clients. And yes, more proxy will need to be prepared to simulate that.
 -Make sure it can work with multiple clients. And yes, more proxy will need to be prepared to simulate that.
 ii) Request Response simulation. Make sure the receiver can make request and acquire response (Not referring to request Response adapter. Just use the existing two channel)
 ii) Request Response simulation. Make sure the receiver can make request and acquire response (Not referring to request Response adapter. Just use the existing two channel)
 -Enable the response generator aspect to simulate such cases. Also, there is a need for a counter so to speak, so that the message
 -Enable the response generator aspect to simulate such cases. Also, there is a need for a counter so to speak, so that the message
@@ -44,8 +44,15 @@ iii) Http Transport service
 iv) Think about requestresponse transmission and it's associated adapter's implementation
 iv) Think about requestresponse transmission and it's associated adapter's implementation
 -Do this when I have too much time to waste
 -Do this when I have too much time to waste
 
 
-Discussion Points:
+Discussion Points: (Do these first)
 i) Explore multiple traffic concept
 i) Explore multiple traffic concept
 -To make use of different ports as well as multi ISP to stream data. Eg: External Netword card.
 -To make use of different ports as well as multi ISP to stream data. Eg: External Netword card.
 -See how I can talk to underlying OS network configuration to make use of the network stream and delegate ports to it
 -See how I can talk to underlying OS network configuration to make use of the network stream and delegate ports to it
-ii) Move transport service instantiation to adapterManager
+ii) Move transport service instantiation to adapterManager
+ExtraNotes: In some cases, servers can only be transmitting. Although this program allows for dual roles if there's a need for me.
+
+Note for 19/11/2024:
+i) Move the instantiation of transport service to adapterManager
+ii) Test multi client. Make sure they can be recognized. Will have to have multi proxies to be set up.
+iii) Also test if the server can also receives instead of just transmitting, and responds accordingly.
+iv) Modify the code to start using wrapped messages to allow message ordering

+ 7 - 7
package-lock.json

@@ -20,7 +20,7 @@
         "@types/express": "^5.0.0",
         "@types/express": "^5.0.0",
         "@types/node": "^22.7.4",
         "@types/node": "^22.7.4",
         "@types/uuid": "^10.0.0",
         "@types/uuid": "^10.0.0",
-        "typescript": "^5.6.2"
+        "typescript": "^5.6.3"
       }
       }
     },
     },
     "node_modules/@socket.io/component-emitter": {
     "node_modules/@socket.io/component-emitter": {
@@ -1108,9 +1108,9 @@
       }
       }
     },
     },
     "node_modules/typescript": {
     "node_modules/typescript": {
-      "version": "5.6.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
-      "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
+      "version": "5.6.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
+      "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
       "dev": true,
       "dev": true,
       "license": "Apache-2.0",
       "license": "Apache-2.0",
       "bin": {
       "bin": {
@@ -1969,9 +1969,9 @@
       }
       }
     },
     },
     "typescript": {
     "typescript": {
-      "version": "5.6.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
-      "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
+      "version": "5.6.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
+      "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
       "dev": true
       "dev": true
     },
     },
     "undici-types": {
     "undici-types": {

+ 3 - 2
package.json

@@ -6,6 +6,7 @@
   "scripts": {
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
     "test": "echo \"Error: no test specified\" && exit 1",
     "build": "tsc",
     "build": "tsc",
+    "watch": "tsc --watch",
     "start": "node dist/index.js",
     "start": "node dist/index.js",
     "proxy": "node dist/test/proxy.js",
     "proxy": "node dist/test/proxy.js",
     "transmitter": "node dist/test/transmitter.js",
     "transmitter": "node dist/test/transmitter.js",
@@ -17,7 +18,7 @@
     "@types/express": "^5.0.0",
     "@types/express": "^5.0.0",
     "@types/node": "^22.7.4",
     "@types/node": "^22.7.4",
     "@types/uuid": "^10.0.0",
     "@types/uuid": "^10.0.0",
-    "typescript": "^5.6.2"
+    "typescript": "^5.6.3"
   },
   },
   "dependencies": {
   "dependencies": {
     "dotenv": "^16.4.5",
     "dotenv": "^16.4.5",
@@ -27,4 +28,4 @@
     "socket.io-client": "^4.8.0",
     "socket.io-client": "^4.8.0",
     "uuid": "^10.0.0"
     "uuid": "^10.0.0"
   }
   }
-}
+}

+ 2 - 3
src/connector/connector.receiver.ts

@@ -23,7 +23,7 @@ export class ReceiverConnectionAdapter extends ConnectionAdapter implements Rece
     }
     }
 
 
     getMessageBus(bus: Bus): Observable<TransportEvent> {
     getMessageBus(bus: Bus): Observable<TransportEvent> {
-        return new Observable((observable: Observer<any>) => {
+        return new Observable((observable: Observer<TransportEvent>) => {
             if (bus == Bus.GeneralBus) {
             if (bus == Bus.GeneralBus) {
                 const subscription: Subscription = this.connector.subscribe().pipe(
                 const subscription: Subscription = this.connector.subscribe().pipe(
                     filter((message: TransportEvent) => message.event === 'New Message'),
                     filter((message: TransportEvent) => message.event === 'New Message'),
@@ -36,8 +36,7 @@ export class ReceiverConnectionAdapter extends ConnectionAdapter implements Rece
                         }
                         }
                         return shouldTake;
                         return shouldTake;
                     }),
                     }),
-                    map(message => message.data as TransportMessage)
-                ).subscribe((message: TransportMessage) => {
+                ).subscribe((message: TransportEvent) => {
                     observable.next(message);
                     observable.next(message);
                 });
                 });
 
 

+ 2 - 1
src/connector/connector.transmitter.ts

@@ -4,6 +4,7 @@ import { ConnectionAdapter } from "./connector.base";
 import { AdapterProfile, AdaptorTransmissionRole, ConnectionState, TransmitterConnectionAdapter as TransmitterConnectionAdapterInterface, Transport, TransportEvent, TransportMessage, TransportService } from '../interface/connector.interface';
 import { AdapterProfile, AdaptorTransmissionRole, ConnectionState, TransmitterConnectionAdapter as TransmitterConnectionAdapterInterface, Transport, TransportEvent, TransportMessage, TransportService } from '../interface/connector.interface';
 import { BehaviorSubject, Observable, Observer, Subject } from 'rxjs';
 import { BehaviorSubject, Observable, Observer, Subject } from 'rxjs';
 import { v4 as uuidv4 } from 'uuid'
 import { v4 as uuidv4 } from 'uuid'
+import { WrappedMessage } from '../utils/message.ordering';
 
 
 dotenv.config();
 dotenv.config();
 /* This transport manager will be instantiating the necessary transport to deal with tranmission and receiving from different receivers
 /* This transport manager will be instantiating the necessary transport to deal with tranmission and receiving from different receivers
@@ -18,7 +19,7 @@ export class TransmitterConnectionAdapter extends ConnectionAdapter implements T
         this.setAdapterProfile(adapterId, adapterType)
         this.setAdapterProfile(adapterId, adapterType)
     }
     }
 
 
-    emit(message: FisMessage): void {
+    emit(message: FisMessage | WrappedMessage): void {
        // logic here
        // logic here
         this.connector.emit({
         this.connector.emit({
             id: this.connectorProfile.id,
             id: this.connectorProfile.id,

+ 3 - 2
src/interface/connector.interface.ts

@@ -1,5 +1,6 @@
 import { BehaviorSubject, Observable, Subject } from "rxjs"
 import { BehaviorSubject, Observable, Subject } from "rxjs"
 import { Bus, FisMessage, ReceiverProfile, TransmissionMessage, TransmissionProfile, TransmitterProfile } from "./transport.interface"
 import { Bus, FisMessage, ReceiverProfile, TransmissionMessage, TransmissionProfile, TransmitterProfile } from "./transport.interface"
+import { WrappedMessage } from "../utils/message.ordering"
 
 
 
 
 export type TYPE = {
 export type TYPE = {
@@ -36,7 +37,7 @@ export interface ConnectionAdaptorBase {
 
 
 
 
 export interface TransmitterConnectionAdapter extends ConnectionAdaptorBase {
 export interface TransmitterConnectionAdapter extends ConnectionAdaptorBase {
-    emit(message: FisMessage): void
+    emit(message: FisMessage | WrappedMessage): void
 }
 }
 
 
 export interface ReceiverConnectionAdapter extends ConnectionAdaptorBase {
 export interface ReceiverConnectionAdapter extends ConnectionAdaptorBase {
@@ -75,7 +76,7 @@ export interface TransportEvent {
     data: any
     data: any
 }
 }
 
 
-export type Event = 'Server Started' | 'New Client' | 'Client Disconnected' | 'Client Reconnected' | `Server Disconnected` | 'New Message' | `Notification` | `New Server` | `New Transport` | 'New Adapter'
+export type Event = 'Server Started' | 'New Client' | 'Client Disconnected' | 'Client Reconnected' | `Server Disconnected` | 'New Message' | `Notification` | `New Server` | `Server Reconnected` | `New Transport` | 'New Adapter'
 
 
 export interface TransportService {
 export interface TransportService {
     getInfo(): Transport
     getInfo(): Transport

+ 2 - 2
src/test/proxy.ts

@@ -11,8 +11,8 @@ startClientSocketConnection('http://localhost:3000')
 consoleLog()
 consoleLog()
 
 
 function consoleLog(): void {
 function consoleLog(): void {
-    fromServer.subscribe(message => console.log(`From Server`, message.event, message.payload?.header?.messageID ?? 'undefined message'))
-    toServer.subscribe(message => console.log(`To Server`, message.event, message.payload?.header?.messageID ?? 'undefined message'))
+    fromServer.subscribe(message => console.log(`From Server`, message.event, message.payload?.thisMessageID ?? 'undefined message'))
+    toServer.subscribe(message => console.log(`To Server`, message.event, message.payload?.thisMessageID ?? 'undefined message'))
 }
 }
 
 
 function startSocketServer(port: number): void {
 function startSocketServer(port: number): void {

+ 63 - 27
src/test/receiver.ts

@@ -7,58 +7,94 @@ import { io, Socket } from "socket.io-client";
 import { handleClientSocketConnection } from "../utils/socket.utils";
 import { handleClientSocketConnection } from "../utils/socket.utils";
 import { ConnectedServerSocket } from "../transport/websocket";
 import { ConnectedServerSocket } from "../transport/websocket";
 import { v4 as uuidv4 } from 'uuid'
 import { v4 as uuidv4 } from 'uuid'
-import { filter, interval, Observable, Observer, Subject } from "rxjs";
-import { TransportEvent, TransportMessage } from "../interface/connector.interface";
-import { FisMessage } from "../interface/transport.interface";
+import { filter, interval, map, Observable, Observer, Subject, Subscription, takeWhile } from "rxjs";
+import { TransportEvent } from "../interface/connector.interface";
+import { EventMessage, FisMessage } from "../interface/transport.interface";
+import { checkMessage, WrappedMessage } from "../utils/message.ordering";
+import { RetransmissionService } from "../utils/retransmission.service";
 
 
 class SocketClient {
 class SocketClient {
-    private socket: Socket;
+    private currentSocketId!: string
+    private socket!: Socket;
     private connectedServerSocket: ConnectedServerSocket[] = []
     private connectedServerSocket: ConnectedServerSocket[] = []
+    private requestMessages: Subject<any> = new Subject()
     private event: Subject<TransportEvent> = new Subject()
     private event: Subject<TransportEvent> = new Subject()
+    private retransmission: RetransmissionService = new RetransmissionService()
 
 
     constructor(url: string) {
     constructor(url: string) {
+        this.setUpClientServerConnection(url)
+    }
+
+    private setUpClientServerConnection(url: string) {
         // Connect to the serve
         // Connect to the serve
         this.socket = io(url);
         this.socket = io(url);
         // use the existing socket handler
         // use the existing socket handler
         handleClientSocketConnection(this.socket, this.connectedServerSocket).subscribe(this.event)
         handleClientSocketConnection(this.socket, this.connectedServerSocket).subscribe(this.event)
         this.startListening(this.event)
         this.startListening(this.event)
-        // interval(5000).subscribe(time => {
-        //     let requestId: string = uuidv4()
-        //     this.sendMessage(requestId).subscribe({
-        //         next: (message: FisMessage) => console.log(`Incoming Response`, message.header.messageID),
-        //         error: error => console.error(error),
-        //         complete: () => console.log(`Completed Response for ${requestId}`)
-        //     })
-        // })
     }
     }
 
 
     private startListening(event: Subject<TransportEvent>): void {
     private startListening(event: Subject<TransportEvent>): void {
-        event.subscribe((event: TransportEvent) => console.log(event))
+        event.subscribe((event: TransportEvent) => {
+            // console.log(event)
+            if (event.event == `New Server`) {
+                this.currentSocketId = (event.data as EventMessage).clientId
+
+                let currentClientSocket: ConnectedServerSocket | undefined = this.connectedServerSocket.find(obj => obj.id === this.currentSocketId)
+                if (currentClientSocket) {
+                    // so retransmission is working as usual
+                    this.retransmission.implementRetransmission(this.requestMessages, currentClientSocket.connectionState, true)
+                    this.startGeneratingRequest(1000, this.requestMessages)
+                    this.retransmission.returnSubjectForBufferedItems().subscribe((message: WrappedMessage) => {
+                        this.sendMessage(message).subscribe({
+                            next: message => console.log(message),
+                            complete: () => console.log(`Request Completed for ${message.thisMessageID}`)
+                        })
+                    })
+                }
+            }
+        })
     }
     }
 
 
-    private sendMessage(requestId: string): Observable<any> {
-        return new Observable((response: Observer<FisMessage>) => {
+    private startGeneratingRequest(intervalDuration: number, requestsPipe: Subject<FisMessage>) {
+        interval(intervalDuration).subscribe(time => {
             let message: FisMessage = {
             let message: FisMessage = {
                 header: {
                 header: {
-                    messageID: requestId,
+                    messageID: uuidv4(),
                     messageName: 'RequestMessage'
                     messageName: 'RequestMessage'
                 },
                 },
                 data: 'Data'
                 data: 'Data'
             }
             }
+            requestsPipe.next(message)
+        })
+    }
+
+    private sendMessage(message: WrappedMessage): Observable<WrappedMessage> {
+        return new Observable((response: Observer<WrappedMessage>) => {
+            console.log(`Emitting: ${message.thisMessageID}`)
             this.socket.emit('message', message)
             this.socket.emit('message', message)
+            let onHold = new Subject<WrappedMessage>()
+            let toBeReleased = new Subject<WrappedMessage>()
 
 
-            this.event.pipe(
-                filter(obj => obj.event == 'New Message'),
-                filter(obj => (obj.data as FisMessage).header.messageID == message.header.messageID)
-            ).subscribe({
-                next: (event: TransportEvent) => {
-                    if ((event.data as FisMessage).data == 'Complete') {
-                        response.complete()
-                    }
+            let subscription: Subscription = toBeReleased.subscribe(message => {
+                if ((message.payload as FisMessage).data == 'Complete') {
+                    onHold.complete()
+                    toBeReleased.complete()
+                    subscription.unsubscribe()
+                    response.complete()
+                } else {
                     response.next(message)
                     response.next(message)
-                },
-                error: error => response.error(error),
-                complete: () => { }
+                }
+            })
+
+            this.event.pipe(
+                filter(event => event.event == 'New Message'),
+                filter(event => ((event.data as EventMessage).payload as WrappedMessage).thisMessageID === message.thisMessageID),
+                takeWhile(event => (((event.data as EventMessage).payload as WrappedMessage).payload as FisMessage).data == 'Complete'),
+                map(event => ((event.data as EventMessage).payload as WrappedMessage)),
+            ).subscribe((message: WrappedMessage) => {
+                checkMessage(message, onHold).then(() => {
+                    toBeReleased.next(message)
+                })
             })
             })
         })
         })
     }
     }

+ 5 - 4
src/test/transmitter.ts

@@ -3,6 +3,7 @@ import { Bus, FisMessage, MessageTransmission, TransmissionMessage } from "../in
 import { v4 as uuidv4 } from 'uuid'
 import { v4 as uuidv4 } from 'uuid'
 import { MessageTransmissionManager } from "../transmission/msg.transmission.manager";
 import { MessageTransmissionManager } from "../transmission/msg.transmission.manager";
 import { TransportEvent, TransportMessage } from "../interface/connector.interface";
 import { TransportEvent, TransportMessage } from "../interface/connector.interface";
+import { WrappedMessage } from "../utils/message.ordering";
 
 
 class Supervisor {
 class Supervisor {
     private clientIncomingMessage: Subject<FisMessage> = new Subject()
     private clientIncomingMessage: Subject<FisMessage> = new Subject()
@@ -27,8 +28,8 @@ class Supervisor {
     private handleClientActivity(messageTransmission: MessageTransmission): void {
     private handleClientActivity(messageTransmission: MessageTransmission): void {
         // start listening to incoming messages from this client
         // start listening to incoming messages from this client
         messageTransmission.receiver.getMessageBus(Bus.GeneralBus).subscribe((event: TransportEvent) => {
         messageTransmission.receiver.getMessageBus(Bus.GeneralBus).subscribe((event: TransportEvent) => {
-            console.log(event)
-            let requestMessage: FisMessage = (event.data as TransportMessage).payload as FisMessage
+            console.log(event) 
+            let requestMessage: FisMessage = ((event.data as TransportMessage).payload as WrappedMessage).payload as FisMessage
             this.clientIncomingMessage.next(requestMessage)
             this.clientIncomingMessage.next(requestMessage)
             this.messageProducer.getOutgoingMessages().pipe(
             this.messageProducer.getOutgoingMessages().pipe(
                 filter(message => message.header.messageID === requestMessage.header.messageID)
                 filter(message => message.header.messageID === requestMessage.header.messageID)
@@ -55,7 +56,7 @@ class MessageProducer {
         console.log(`Contructing Application....`)
         console.log(`Contructing Application....`)
         this.incomingMessageBus = incomingMessageBus
         this.incomingMessageBus = incomingMessageBus
 
 
-        this.generateNotifcation().subscribe(this.generalNotification)
+        // this.generateNotifcation().subscribe(this.generalNotification)
         this.handleIncomingRequests(this.incomingMessageBus.asObservable(), this.outgoingMessageBus)
         this.handleIncomingRequests(this.incomingMessageBus.asObservable(), this.outgoingMessageBus)
     }
     }
 
 
@@ -70,7 +71,7 @@ class MessageProducer {
     // this is called no problem
     // this is called no problem
     private handleIncomingRequests(requests: Observable<FisMessage>, outgoingMessageBus: Subject<FisMessage>): void {
     private handleIncomingRequests(requests: Observable<FisMessage>, outgoingMessageBus: Subject<FisMessage>): void {
         requests.subscribe((request: FisMessage) => {
         requests.subscribe((request: FisMessage) => {
-            console.log(`Generating response for new request ${request.header.messageID}`)
+            // console.log(`Generating response for new request ${request.header.messageID}`)
             this.generateMessage(10).subscribe({
             this.generateMessage(10).subscribe({
                 next: message => outgoingMessageBus.next(message),
                 next: message => outgoingMessageBus.next(message),
                 error: error => console.error(error),
                 error: error => console.error(error),

+ 1 - 1
src/transmission/msg.transmission.base.ts

@@ -14,7 +14,7 @@ export class MessageTransmissionBase implements MessageTransmissionBaseInterface
     transmissionService: any;
     transmissionService: any;
     adapterService!: ConnectionAdapter | undefined
     adapterService!: ConnectionAdapter | undefined
 
 
-    constructor(event: Observable<TransportEvent>) { 
+    constructor(event: Observable<TransportEvent>) {
         // logic here
         // logic here
     }
     }
 
 

+ 2 - 1
src/transmission/msg.transmission.manager.ts

@@ -27,7 +27,8 @@ export class MessageTransmissionManager implements MessageTransmissionManagerInt
             this.setUpTransportService(set, event)
             this.setUpTransportService(set, event)
         })
         })
 
 
-        this.event.subscribe(event => console.log(`event`, event))
+        // temporarily off for now
+        // this.event.subscribe(event => console.log(`event`, event))
 
 
         // note that if this server is down, all these instances of transmission and connector would be lost as well. SO cannot just simply find "instances" and reuse them. Must reinstantiate them again
         // note that if this server is down, all these instances of transmission and connector would be lost as well. SO cannot just simply find "instances" and reuse them. Must reinstantiate them again
         this.handleEvent(`Client Disconnected` as Event, event)
         this.handleEvent(`Client Disconnected` as Event, event)

+ 13 - 7
src/transmission/msg.transmission.receiver.ts

@@ -1,13 +1,14 @@
-import { filter, map, Observable, Observer, PartialObserver, Subject, Subscriber, Subscription, takeWhile, Unsubscribable } from 'rxjs';
-import { AdapterProfile, AdapterSet, AdaptorTransmissionRole, Transport, TransportEvent, TransportMessage } from '../interface/connector.interface';
+import { filter, Observable, Observer, Subject, Subscription } from 'rxjs';
+import { AdapterSet, Transport, TransportEvent, TransportMessage } from '../interface/connector.interface';
 import { MessageTransmissionBase } from './msg.transmission.base';
 import { MessageTransmissionBase } from './msg.transmission.base';
-import { Bus, EventMessage, FisMessage, MessageReceiver as MessageReceiverInterface, ReceiverProfile, TransmissionMessage, TransmitterProfile } from '../interface/transport.interface'
-import { ConnectionAdapter } from '../connector/connector.base';
+import { Bus, EventMessage, MessageReceiver as MessageReceiverInterface, ReceiverProfile } from '../interface/transport.interface'
 import { v4 as uuidv4 } from 'uuid'
 import { v4 as uuidv4 } from 'uuid'
 import { ReceiverConnectionAdapter } from '../connector/connector.receiver';
 import { ReceiverConnectionAdapter } from '../connector/connector.receiver';
-import { ConnectionManager } from '../connector/connector.manager';
+import { checkMessage, WrappedMessage } from '../utils/message.ordering';
 
 
 export class MessageTransmissionReceiver extends MessageTransmissionBase implements MessageReceiverInterface {
 export class MessageTransmissionReceiver extends MessageTransmissionBase implements MessageReceiverInterface {
+    private onHoldMessage: Subject<WrappedMessage> = new Subject()
+    // private toBePassedOver: Subject<WrappedMessage> = new Subject()
     receiverProfile!: ReceiverProfile;
     receiverProfile!: ReceiverProfile;
 
 
     constructor(profile: ReceiverProfile, adapterSets: AdapterSet[], event: Observable<TransportEvent>) {
     constructor(profile: ReceiverProfile, adapterSets: AdapterSet[], event: Observable<TransportEvent>) {
@@ -29,9 +30,14 @@ export class MessageTransmissionReceiver extends MessageTransmissionBase impleme
                 // SAMPLE: This adapterArray.forEach(adapter => { ... })
                 // SAMPLE: This adapterArray.forEach(adapter => { ... })
                 const subscription: Subscription = (this.adapterService as ReceiverConnectionAdapter).getMessageBus(Bus.GeneralBus).pipe(
                 const subscription: Subscription = (this.adapterService as ReceiverConnectionAdapter).getMessageBus(Bus.GeneralBus).pipe(
                     filter((event: TransportEvent) => event.event == 'New Message'),
                     filter((event: TransportEvent) => event.event == 'New Message'),
-                    // map((event: TransportEvent) => event.data as TransportMessage)
                 ).subscribe((event: TransportEvent) => {
                 ).subscribe((event: TransportEvent) => {
-                    observable.next(event);
+                    // console.log(event) // data is transportMessage instead of eventmessage
+                    this.onHoldMessage.next(((event.data as TransportMessage).payload as WrappedMessage))
+                    checkMessage(((event.data as TransportMessage).payload as WrappedMessage), this.onHoldMessage).then(() => {
+                        // only release the message before it exists
+                        console.log(`This one passes. Does have previousID. Case for message ordering`) 
+                        observable.next(event);
+                    }).catch((error) => console.error(error))
                 });
                 });
 
 
                 // Clean up on unsubscription
                 // Clean up on unsubscription

+ 6 - 3
src/transmission/msg.transmission.transmitter.ts

@@ -5,6 +5,7 @@ import { v4 as uuidv4 } from 'uuid'
 import { TransmitterConnectionAdapter } from "../connector/connector.transmitter";
 import { TransmitterConnectionAdapter } from "../connector/connector.transmitter";
 import { BehaviorSubject, filter, map, Observable, Subject } from "rxjs";
 import { BehaviorSubject, filter, map, Observable, Subject } from "rxjs";
 import { RetransmissionService } from "../utils/retransmission.service";
 import { RetransmissionService } from "../utils/retransmission.service";
+import { WrappedMessage } from "../utils/message.ordering";
 
 
 /* Take in all the messages that needs to be transported, and divide them accordingly. So the connector instances will do just that
 /* Take in all the messages that needs to be transported, and divide them accordingly. So the connector instances will do just that
 connectors or adapters will have their own identifier*/
 connectors or adapters will have their own identifier*/
@@ -38,9 +39,12 @@ export class MessageTransmissionTransmitter extends MessageTransmissionBase impl
         ).subscribe((signal: ConnectionState) => {
         ).subscribe((signal: ConnectionState) => {
             connectionStateEvent.next(signal)
             connectionStateEvent.next(signal)
         })
         })
-        this.retransmission.implementRetransmission(this.messageToBeTransmitted, connectionStateEvent)
+        this.retransmission.implementRetransmission(this.messageToBeTransmitted, connectionStateEvent, true)
         // automatically subscribe to allow released bffered messages to be released
         // automatically subscribe to allow released bffered messages to be released
-        this.retransmission.returnSubjectForBufferedItems().subscribe(message => (this.adapterService as TransmitterConnectionAdapter).emit(message.payload))
+        this.retransmission.returnSubjectForBufferedItems().subscribe((message: WrappedMessage) => {
+            // need to work with wrapped messages
+            (this.adapterService as TransmitterConnectionAdapter).emit(message)
+        })
     }
     }
 
 
     setTransmitter(transmitterProfile: TransmitterProfile): void {
     setTransmitter(transmitterProfile: TransmitterProfile): void {
@@ -50,7 +54,6 @@ export class MessageTransmissionTransmitter extends MessageTransmissionBase impl
     emit(message: FisMessage): void {
     emit(message: FisMessage): void {
         // for now only use one adapter
         // for now only use one adapter
         this.messageToBeTransmitted.next(message)
         this.messageToBeTransmitted.next(message)
-        // (this.adapterService as TransmitterConnectionAdapter).emit(message)
     }
     }
 
 
     setUpAdapter(adapterSets: AdapterSet[]) {
     setUpAdapter(adapterSets: AdapterSet[]) {

+ 32 - 4
src/utils/socket.utils.ts

@@ -6,7 +6,7 @@ import * as fs from 'fs'
 import { v4 as uuidv4 } from 'uuid'
 import { v4 as uuidv4 } from 'uuid'
 import { ConnectionState, Transport, TransportEvent, TransportMessage } 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, FisMessage } from '../interface/transport.interface';
+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) => {
@@ -95,7 +95,10 @@ export function handleClientSocketConnection(socket: ClientSocket, serversConnec
                 eventNotification.next({
                 eventNotification.next({
                     id: uuidv4(),
                     id: uuidv4(),
                     event: 'New Message',
                     event: 'New Message',
-                    data: msg
+                    data: {
+                        clientId: receiverProfileInfo.id,
+                        payload: msg
+                    } as EventMessage
                 })
                 })
             } else {
             } else {
                 // Do nothing. just store in local array first. Cannot process without information. but then again, don['t need information if acting as client
                 // Do nothing. just store in local array first. Cannot process without information. but then again, don['t need information if acting as client
@@ -138,7 +141,7 @@ export function handleClientSocketConnection(socket: ClientSocket, serversConnec
                     // 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: 'Server Reconnected',
                         data: {
                         data: {
                             clientId: (data.message as ConnectedServerSocket).id,
                             clientId: (data.message as ConnectedServerSocket).id,
                             message: `Existing Websocket Channel ${(data.message as ConnectedServerSocket).id} re-established.`
                             message: `Existing Websocket Channel ${(data.message as ConnectedServerSocket).id} re-established.`
@@ -165,13 +168,38 @@ export function handleClientSocketConnection(socket: ClientSocket, serversConnec
             }
             }
         })
         })
 
 
+        /* https://socket.io/docs/v3/client-socket-instance/
+            this is no differnt from the 'connect' handler */
+        // socket.on(`reconnect`, () => {
+        //     console.log('Connected to the server:', socket.id)
+        //     if (clientName) {
+        //         checkOwnClientInfo(clientName).then((profile: ConnectedServerSocket) => {
+        //             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
+        //         })
+        //     }
+        // })
+
         // Handle disconnection
         // Handle disconnection
         socket.on('disconnect', () => {
         socket.on('disconnect', () => {
             console.log('Websocket Client disconnected from the server');
             console.log('Websocket Client disconnected from the server');
             if (receiverProfileInfo) {
             if (receiverProfileInfo) {
                 eventNotification.next({
                 eventNotification.next({
                     id: uuidv4(),
                     id: uuidv4(),
-                    event: `Client Disconnected`,
+                    event: `Server Disconnected`,
                     data: {
                     data: {
                         clientId: receiverProfileInfo.id,
                         clientId: receiverProfileInfo.id,
                         message: `Server for Channel ${receiverProfileInfo.id} disconnected.`
                         message: `Server for Channel ${receiverProfileInfo.id} disconnected.`