Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
robmoffat committed May 10, 2024
1 parent cacdeca commit c452674
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 105 deletions.
6 changes: 3 additions & 3 deletions packages/da-server/src/handlers/BroadcastHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export type ChannelState = { [channelId: string]: ContextElement[] }

export class BroadcastHandler implements MessageHandler {

private regs: ListenerRegistration[] = []
private readonly state: ChannelState = {}
private readonly desktopAgentName: string
protected regs: ListenerRegistration[] = []
protected readonly state: ChannelState = {}
protected readonly desktopAgentName: string

constructor(name: string, initialChannelState: ChannelState) {
this.desktopAgentName = name
Expand Down
7 changes: 3 additions & 4 deletions packages/sail2/src/client/state/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { DirectoryApp } from "da-server"
import { WebAppDetails } from "da-server/src/directory/DirectoryInterface"
import { GridStackPosition } from "gridstack"
import { v4 as uuid } from 'uuid'

const STORAGE_KEY = "sail-client-state"

Expand Down Expand Up @@ -34,7 +33,7 @@ export interface ClientState {
getPanels(): AppPanel[]

/** Apps */
open(details: DirectoryApp): AppPanel | null
open(instanceId: string, details: DirectoryApp): AppPanel | null

/** Callback */
addStateChangeCallback(cb: () => void): void
Expand Down Expand Up @@ -100,7 +99,7 @@ abstract class AbstractClientState implements ClientState {
this.saveState()
}

open(detail: DirectoryApp): AppPanel | null {
open(instanceId: string, detail: DirectoryApp): AppPanel | null {
if (detail.type == 'web') {
const url = (detail.details as WebAppDetails).url
const ap = {
Expand All @@ -110,7 +109,7 @@ abstract class AbstractClientState implements ClientState {
h: 4,
title: detail.title,
tabId: this.activeTabId,
id: uuid(),
id: instanceId,
url
} as AppPanel

Expand Down
5 changes: 0 additions & 5 deletions packages/sail2/src/message-types.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { BasicDirectory } from "da-server/src/directory/BasicDirectory";
import { DirectoryApp } from "da-server/src/directory/DirectoryInterface";
import fs from 'node:fs/promises';


function loadRemotely(u: string): Promise<any> {
return fetch(u).then((response) => response.json());
}
Expand All @@ -24,7 +23,7 @@ const convertToDirectoryList = (data: any) => {
return data.applications as DirectoryApp[];
}

export class FDC3_2_1_JSONDirectory extends BasicDirectory {
export class SailDirectory extends BasicDirectory {

constructor() {
super([])
Expand All @@ -34,4 +33,11 @@ export class FDC3_2_1_JSONDirectory extends BasicDirectory {
this.allApps.push(...await load(url));
}

/**
* Replaces the loaded apps with new ones
*/
async replace(url: string[]) {
this.allApps = []
url.forEach(u => load(u))
}
}
93 changes: 93 additions & 0 deletions packages/sail2/src/server/da/DesktopAgentService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Server } from "http";
import { APP_HELLO, DA_HELLO, FDC3_APP_EVENT, HelloArgs } from "./message-types";
import { Socket } from "socket.io";
import { AppIdentifier } from "@finos/fdc3";
import { SailFDC3Server } from "./SailFDC3Server";
import { SailServerContext } from "./SailServerContext";

type FDC3Session = {
fdc3Server: SailFDC3Server,
serverContext: SailServerContext
}

export function initDesktopAgentService(httpServer: Server): void {

const io = new Server(httpServer)

const sessions: Map<string, FDC3Session> = new Map()

io.on('connection', (socket: Socket) => {

var myInstance: FDC3Session | undefined
var myId: string | undefined

socket.on(DA_HELLO, function (data: HelloArgs) {
myId = data.id
if (sessions.get(myId)) {
console.log("Need to reconfigure desktop agent")
}

myInstance = sessions.get(myId)
if (myInstance) {
// reconfiguring current session
myInstance.fdc3Server.getBroadcastHandler().updateChannels(data.channels)
myInstance.fdc3Server.getDirectory().replace(data.directories)
console.log("updated desktop agent channels and directories" + sessions.size)
} else {
// starting session
const serverContext = new SailServerContext(socket)
const fdc3Server = new SailFDC3Server(serverContext, data)
myInstance = {
serverContext,
fdc3Server
}
sessions.set(myId, myInstance)
console.log("created agent session. Running sessions " + sessions.size)
}
})

socket.on(APP_HELLO, function (id: string, appID: AppIdentifier) {
myId = appID.instanceId!!
const instance = sessions.get(id)

if (instance != undefined) {
console.log("An app connected: " + id)
instance.serverContext.connect(myId, socket)
myInstance = instance
} else {
console.log("App Tried Connecting to non-existent DA Instance " + id + " " + appID.appId + " " + appID.instanceId)
}
})

socket.on(FDC3_APP_EVENT, function (data, from): void {
// message from app to da
console.log(JSON.stringify(data))

// if ((myInstance == null) && (data.type == 'intentResolutionChoice')) {
// // message from app's intent resolver
// myInstance = Array.from(instances.values()).find(cw => cw.apps.get(from.instanceId))
// }

// if ((myInstance == null) && (data.type == 'channelSelectionChoice')) {
// // message from app's channelSelector
// myInstance = Array.from(instances.values()).find(cw => cw.apps.get(from.instanceId))
// }

if (myInstance != undefined) {
myInstance!!.fdc3Server.receive(data, from)
}
})

socket.on("disconnect", function (): void {
if (myInstance) {
if (myInstance.serverContext.serverSocket.id == socket.id) {
sessions.delete(myId!!)
} else {
myInstance.serverContext.disconnect(socket)
console.log(`Apparent disconnect: ${myInstance.serverContext.apps.size} remaining`)
}
}
})
})

}
34 changes: 34 additions & 0 deletions packages/sail2/src/server/da/ReconfigurableBroadcastHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { BroadcastHandler, ChannelState } from "da-server/src/handlers/BroadcastHandler";
import { ChannelMetadata } from "./message-types";


export class ReconfigurableBroadcastHandler extends BroadcastHandler {

private channelMetadata: ChannelMetadata[]

constructor(name: string, cm: ChannelMetadata[]) {
const state: ChannelState = {}
cm.forEach(item => {
state[item.id] = []
})

super(name, state)
this.channelMetadata = cm
}

updateChannels(cm: ChannelMetadata[]) {
cm.forEach(item => {
if (!this.state[item.id]) {
// create the new channel
this.state[item.id] = []
}
})

this.channelMetadata = cm
}

getChannelMetadata(): ChannelMetadata[] {
return this.channelMetadata
}

}
37 changes: 37 additions & 0 deletions packages/sail2/src/server/da/SailFDC3Server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { BasicFDC3Server, ServerContext } from "da-server";
import { SailDirectory } from "../appd/SailDirectory";
import { ReconfigurableBroadcastHandler } from "./ReconfigurableBroadcastHandler";
import { IntentHandler } from "da-server/src/handlers/IntentHandler";
import { OpenHandler } from "da-server/src/handlers/OpenHandler";
import { ChannelMetadata, HelloArgs } from "./message-types";

/**
* Extends BasicFDC3Server to allow for more detailed (and changeable) user channel metadata
* as well as user-configurable SailDirectory.
*/
export class SailFDC3Server extends BasicFDC3Server {

protected readonly directory: SailDirectory
protected readonly broadcastHandler: ReconfigurableBroadcastHandler

constructor(sc: ServerContext, helloArgs: HelloArgs) {
const dir = new SailDirectory()
const bh = new ReconfigurableBroadcastHandler("Sail", helloArgs.channels)
const ih = new IntentHandler(dir, 200000)
const oh = new OpenHandler(dir)

super([bh, ih, oh], sc)
dir.replace(helloArgs.directories)

this.directory = dir
this.broadcastHandler = bh
}

getDirectory() {
return this.directory
}

getBroadcastHandler() {
return this.broadcastHandler
}
}
88 changes: 88 additions & 0 deletions packages/sail2/src/server/da/SailServerContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { AppMetadata } from "@finos/fdc3/dist/bridging/BridgingTypes";
import { ServerContext } from "da-server";
import { Socket } from "socket.io";
import { v4 as uuidv4 } from 'uuid'
import { DA_OPEN, FDC3_APP_EVENT } from "./message-types";



export class SailServerContext implements ServerContext {

readonly serverSocket: Socket
readonly apps: Map<AppMetadata, Socket> = new Map()

constructor(socket: Socket) {
this.serverSocket = socket;
}

createUUID(): string {
return uuidv4()
}

async post(message: object, to: AppMetadata): Promise<void> {
const ent = Array.from(this.apps.entries()).find(e => this.matches(e[0], to))
if (ent) {
ent[1].emit(FDC3_APP_EVENT, message)
} else {
this.log(`Can't find app: ${JSON.stringify(to)}`)
}
}

async open(appId: string): Promise<AppMetadata> {
const instanceId = uuidv4()
const metadata = {
appId,
instanceId
} as AppMetadata
this.serverSocket.emit(DA_OPEN, metadata)
return metadata
}

getOpenApps(): Promise<AppMetadata[]> {
return Promise.resolve(Array.from(this.apps.keys()))
}

matches(a: AppMetadata, b: AppMetadata): boolean {
return (a.appId == b.appId) && (a.instanceId == b.instanceId)
}

async isAppOpen(app: AppMetadata): Promise<boolean> {
const openApps = await this.getOpenApps()
const found = openApps.find(a => this.matches(app, a))
return found != null
}

log(message: string): void {
console.log(message)
}

provider(): string {
return "FDC3 Sail"
}

providerVersion(): string {
return "2.0"
}

fdc3Version(): string {
return "2.0"
}

/**
* Called when an app connects to the server
*/
connect(appId: AppMetadata, socket: Socket) {
this.apps.set(appId, socket)
}

/**
* Called when an app disconnects from the server
*/
disconnect(socket: Socket) {
const ent = Array.from(this.apps.entries()).find(e => e[1].id == socket.id)
if (ent) {
this.apps.delete(ent[0])
}
}

}
18 changes: 18 additions & 0 deletions packages/sail2/src/server/da/message-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

export const DA_HELLO = 'da-hello'
export const APP_HELLO = 'app-hello'
export const FDC3_APP_EVENT = 'fdc3-app-event'
export const DA_OPEN = 'da-open'

export type ChannelMetadata = {
id: string
displayName: string,
color: string,
icon: string
}

export type HelloArgs = {
id: string,
directories: string[],
channels: ChannelMetadata[]
}
Loading

0 comments on commit c452674

Please sign in to comment.