106 lines
3.1 KiB
TypeScript
106 lines
3.1 KiB
TypeScript
//@template-ignore
|
|
import { VerificationError } from "./ts_base";
|
|
//@template-ignore
|
|
import { RequestObject, ResponseObject, ErrorCodes, Logging } from "./ts_service_base";
|
|
|
|
|
|
export type IMessageCallback = (data: any) => void;
|
|
|
|
export type ResponseListener = {
|
|
ok: (response:any)=>void;
|
|
err: (error: Error)=>void;
|
|
}
|
|
|
|
export class Service {
|
|
public _name: string = null as any;
|
|
|
|
constructor(protected _provider: ServiceProvider, name: string) {
|
|
this._name = name;
|
|
this._provider.services.set(name, this);
|
|
}
|
|
}
|
|
|
|
export class ServiceProvider {
|
|
services = new Map<string, Service>();
|
|
requests = new Map<string, ResponseListener>();
|
|
|
|
constructor(private sendPacket: IMessageCallback) {}
|
|
|
|
onPacket(msg: RequestObject | ResponseObject) {
|
|
Logging.log("CLIENT: Received message:", msg);
|
|
if("method" in msg) {
|
|
if(msg.id){
|
|
Logging.log("CLIENT: Determined type is Request");
|
|
// Request, which are not supported by client, so ignore
|
|
return;
|
|
} else {
|
|
Logging.log("CLIENT: Determined type is Notification");
|
|
//Notification. Send to Notification handler
|
|
const [srvName, fncName] = msg.method.split(".");
|
|
let service = this.services.get(srvName)
|
|
if(!service) {
|
|
Logging.log("CLIENT: Did not find Service wanted by Notification!", srvName);
|
|
} else {
|
|
//TODO: Implement Event thingy (or so :))
|
|
}
|
|
}
|
|
} else {
|
|
Logging.log("CLIENT: Determined type is Response");
|
|
// Response
|
|
let resListener = this.requests.get(msg.id);
|
|
if(!resListener) return; // Ignore wrong responses
|
|
if(msg.error) {
|
|
if(msg.error.data && msg.error.data.$ == "verification_error") {
|
|
resListener.err(new VerificationError(msg.error.data.type, msg.error.data.field, msg.error.data.value))
|
|
} else {
|
|
resListener.err(new Error(msg.error.message));
|
|
}
|
|
} else {
|
|
resListener.ok(msg.result);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
sendMessage(msg: RequestObject, res?: ResponseListener) {
|
|
Logging.log("CLIENT: Sending Messgage", msg);
|
|
if(msg.id) {
|
|
this.requests.set(msg.id, res);
|
|
}
|
|
this.sendPacket(msg)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
declare var require: any;
|
|
export const getRandomBytes = (
|
|
typeof self !== "undefined" && (self.crypto || (self as any).msCrypto)
|
|
? function () {
|
|
// Browsers
|
|
var crypto = self.crypto || (self as any).msCrypto;
|
|
var QUOTA = 65536;
|
|
return function (n: number) {
|
|
var a = new Uint8Array(n);
|
|
for (var i = 0; i < n; i += QUOTA) {
|
|
crypto.getRandomValues(
|
|
a.subarray(i, i + Math.min(n - i, QUOTA))
|
|
);
|
|
}
|
|
return a;
|
|
};
|
|
}
|
|
: function () {
|
|
// Node
|
|
return require("crypto").randomBytes;
|
|
}
|
|
)() as (cnt: number) => Uint8Array;
|
|
|
|
export const getRandomID = (length: number) => {
|
|
return btoa(String.fromCharCode.apply(null, getRandomBytes(length) as any));
|
|
};
|