Add packaged DLP broker and protected Windows service foundation
This commit is contained in:
1 parent
95d23f4e0b
commit
7b5057901a
140 files changed
+11215
-60
No files matched your search
@@ -0,0 +1,68 @@
|
||||
'use strict';
|
||||
const {EventEmitter}=require('node:events');
|
||||
const {TextDecoder}=require('node:util');
|
||||
const SMALL=65536,LARGE=2097152;
|
||||
// Transport only: the native host and parent must authenticate their pipe peer
|
||||
// before constructing this channel. Framing does not grant policy authority.
|
||||
function createFramedChannel({readable,writable,inboundFirstLimit=SMALL,outboundFirstLimit=SMALL}={}){
|
||||
if(!readable||!writable||typeof readable.on!=='function'||typeof writable.write!=='function'||![SMALL,LARGE].includes(inboundFirstLimit)||![SMALL,LARGE].includes(outboundFirstLimit))throw Error('broker-channel-invalid');
|
||||
const channel=new EventEmitter(),decoder=new TextDecoder('utf-8',{fatal:true});
|
||||
let connected=true,firstRead=true,firstWrite=true,header=Buffer.alloc(4),headerBytes=0,payload,payloadBytes=0,pending=0;
|
||||
const outstanding=new Set();
|
||||
Object.defineProperty(channel,'connected',{get:()=>connected});
|
||||
function disconnect(){
|
||||
if(!connected)return;connected=false;header.fill(0);payload?.fill(0);payload=undefined;
|
||||
readable.off('data',data);readable.off('end',disconnect);readable.off('close',disconnect);
|
||||
// Keep bounded error listeners until destroyed streams settle.
|
||||
readable.destroy?.();if(writable!==readable)writable.destroy?.();
|
||||
for(const record of outstanding)record.notify(true);
|
||||
channel.emit('disconnect');
|
||||
}
|
||||
function data(chunk){
|
||||
if(!connected)return;
|
||||
try{
|
||||
if(!Buffer.isBuffer(chunk))throw Error();
|
||||
let offset=0;
|
||||
while(offset<chunk.length&&connected){
|
||||
if(!payload){
|
||||
const take=Math.min(4-headerBytes,chunk.length-offset);chunk.copy(header,headerBytes,offset,offset+take);headerBytes+=take;offset+=take;
|
||||
if(headerBytes!==4)continue;
|
||||
const length=header.readUInt32LE(0),limit=firstRead?inboundFirstLimit:SMALL;
|
||||
if(length<1||length>limit)throw Error();
|
||||
payload=Buffer.alloc(length);payloadBytes=0;headerBytes=0;header.fill(0);
|
||||
}
|
||||
const take=Math.min(payload.length-payloadBytes,chunk.length-offset);chunk.copy(payload,payloadBytes,offset,offset+take);payloadBytes+=take;offset+=take;
|
||||
if(payloadBytes===payload.length){
|
||||
const completed=payload;payload=undefined;payloadBytes=0;firstRead=false;
|
||||
let message;try{message=JSON.parse(decoder.decode(completed));}finally{completed.fill(0);}
|
||||
if(!message||typeof message!=='object'||Array.isArray(message))throw Error();
|
||||
channel.emit('message',message);
|
||||
}
|
||||
}
|
||||
}catch{disconnect();}
|
||||
}
|
||||
channel.send=(message,callback=()=>{})=>{
|
||||
if(typeof callback!=='function')throw Error('broker-channel-invalid');
|
||||
const notifyFailure=()=>{disconnect();try{callback(Error('broker-channel-unavailable'));}catch{}};
|
||||
if(!connected||pending>=8){notifyFailure();return;}
|
||||
let frame;
|
||||
try{
|
||||
if(!message||typeof message!=='object'||Array.isArray(message))throw Error();
|
||||
const text=JSON.stringify(message),bytes=Buffer.byteLength(text),limit=firstWrite?outboundFirstLimit:SMALL;
|
||||
if(bytes<1||bytes>limit)throw Error();
|
||||
frame=Buffer.alloc(bytes+4);frame.writeUInt32LE(bytes);frame.write(text,4);firstWrite=false;pending++;
|
||||
}catch{notifyFailure();return;}
|
||||
let settled=false,notified=false;
|
||||
const record={notify(error){if(notified)return;notified=true;try{callback(error?Error('broker-channel-unavailable'):undefined);}catch{disconnect();}}};
|
||||
outstanding.add(record);
|
||||
// Completion of the underlying write owns buffer release. Disconnect notifies
|
||||
// failure immediately, but cannot claim that an outstanding write has settled.
|
||||
const done=error=>{if(settled)return;settled=true;pending--;outstanding.delete(record);frame.fill(0);if(error)disconnect();record.notify(error||!connected);};
|
||||
try{writable.write(frame,done);}catch{done(Error());}
|
||||
};
|
||||
channel.disconnect=disconnect;
|
||||
readable.on('data',data);readable.once('end',disconnect);readable.once('close',disconnect);readable.on('error',disconnect);
|
||||
if(writable!==readable){writable.once('close',disconnect);writable.on('error',disconnect);}
|
||||
return channel;
|
||||
}
|
||||
module.exports={createFramedChannel};
|
||||
Reference in new issue
Block a user