1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-10 21:33:38 +00:00

Much improved, better stability, lots of fixes

This commit is contained in:
Ylian Saint-Hilaire
2018-01-12 11:50:04 -08:00
parent becf71557f
commit 508646044e
69 changed files with 11803 additions and 4088 deletions

281
Debug/amt_heci.js Normal file
View File

@@ -0,0 +1,281 @@
var Q = require('queue');
function amt_heci() {
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci');
this._amt = heci.create();
this._amt.BiosVersionLen = 65;
this._amt.UnicodeStringLen = 20;
this._amt.rq = new Q();
this._amt.Parent = this;
this._amt.on('error', function (e) { this.Parent.emit('error', e); });
this._amt.on('connect', function () {
this.Parent.emit('connect');
this.on('data', function (chunk) {
//console.log("Received: " + chunk.length + " bytes");
var header = this.Parent.getCommand(chunk);
//console.log("CMD = " + header.Command + " (Status: " + header.Status + ") Response = " + header.IsResponse);
var user = this.rq.deQueue();
var params = user.optional;
var callback = user.func;
params.unshift(header);
callback.apply(this.Parent, params);
});
});
this._amt.connect(heci.GUIDS.AMT, { noPipeline: 1 });
this.getCommand = function (chunk) {
var command = chunk.length == 0 ? (this._amt.rq.peekQueue().cmd | 0x800000) : chunk.readUInt32LE(4);
var ret = { IsResponse: (command & 0x800000) == 0x800000 ? true : false, Command: (command & 0x7FFFFF), Status: chunk.length != 0 ? chunk.readUInt32LE(12) : -1, Data: chunk.length != 0 ? chunk.slice(16) : null };
return (ret);
};
this.sendCommand = function () {
if (arguments.length < 3 || typeof (arguments[0]) != 'number' || typeof (arguments[1]) != 'object' || typeof (arguments[2]) != 'function') { throw ('invalid parameters'); }
var args = [];
for (var i = 3; i < arguments.length; ++i) { args.push(arguments[i]); }
this._amt.rq.enQueue({ cmd: arguments[0], func: arguments[2], optional: args });
var header = Buffer.from('010100000000000000000000', 'hex');
header.writeUInt32LE(arguments[0] | 0x04000000, 4);
header.writeUInt32LE(arguments[1] == null ? 0 : arguments[1].length, 8);
this._amt.write(arguments[1] == null ? header : Buffer.concat([header, arguments[1]]));
}
this.getVersion = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(26, null, function (header, fn, opt) {
if (header.Status == 0) {
var i, CodeVersion = header.Data, val = { BiosVersion: CodeVersion.slice(0, this._amt.BiosVersionLen), Versions: [] }, v = CodeVersion.slice(this._amt.BiosVersionLen + 4);
for (i = 0; i < CodeVersion.readUInt32LE(this._amt.BiosVersionLen) ; ++i) {
val.Versions[i] = { Description: v.slice(2, v.readUInt16LE(0) + 2).toString(), Version: v.slice(4 + this._amt.UnicodeStringLen, 4 + this._amt.UnicodeStringLen + v.readUInt16LE(2 + this._amt.UnicodeStringLen)).toString() };
v = v.slice(4 + (2 * this._amt.UnicodeStringLen));
}
opt.unshift(val);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getProvisioningState = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(17, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.state = header.Data.readUInt32LE(0);
if (result.state < 3) { result.stateStr = ["PRE", "IN", "POST"][result.state]; }
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getProvisioningMode = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(8, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.mode = header.Data.readUInt32LE(0);
if (result.mode < 4) { result.modeStr = ["NONE", "ENTERPRISE", "SMALL_BUSINESS", "REMOTE_ASSISTANCE"][result.mode]; }
result.legacy = header.Data.readUInt32LE(4) == 0 ? false : true;
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getEHBCState = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(132, null, function (header, fn, opt) {
if (header.Status == 0) {
opt.unshift({ EHBC: header.Data.readUInt32LE(0) != 0 });
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getControlMode = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(107, null, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.controlMode = header.Data.readUInt32LE(0);
if (result.controlMode < 3) { result.controlModeStr = ["NONE_RPAT", "CLIENT", "ADMIN", "REMOTE_ASSISTANCE"][result.controlMode]; }
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getMACAddresses = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(37, null, function (header, fn, opt) {
if (header.Status == 0) {
opt.unshift({ DedicatedMAC: header.Data.slice(0, 6).toString('hex:'), HostMAC: header.Data.slice(6, 12).toString('hex:') });
} else { opt.unshift({ DedicatedMAC: null, HostMAC: null }); }
fn.apply(this, opt);
}, callback, optional);
};
this.getDnsSuffix = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(54, null, function (header, fn, opt) {
if (header.Status == 0) {
var resultLen = header.Data.readUInt16LE(0);
if (resultLen > 0) { opt.unshift(header.Data.slice(2, 2 + resultLen).toString()); } else { opt.unshift(null); }
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getHashHandles = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x2C, null, function (header, fn, opt) {
var result = [];
if (header.Status == 0) {
var resultLen = header.Data.readUInt32LE(0);
for (var i = 0; i < resultLen; ++i) {
result.push(header.Data.readUInt32LE(4 + (4 * i)));
}
}
opt.unshift(result);
fn.apply(this, opt);
}, callback, optional);
};
this.getCertHashEntry = function (handle, callback) {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
var data = new Buffer(4);
data.writeUInt32LE(handle, 0);
this.sendCommand(0x2D, data, function (header, fn, opt) {
if (header.Status == 0) {
var result = {};
result.isDefault = header.Data.readUInt32LE(0);
result.isActive = header.Data.readUInt32LE(4);
result.hashAlgorithm = header.Data.readUInt8(72);
if (result.hashAlgorithm < 4) {
result.hashAlgorithmStr = ["MD5", "SHA1", "SHA256", "SHA512"][result.hashAlgorithm];
result.hashAlgorithmSize = [16, 20, 32, 64][result.hashAlgorithm];
result.certificateHash = header.Data.slice(8, 8 + result.hashAlgorithmSize).toString('hex');
}
result.name = header.Data.slice(73 + 2, 73 + 2 + header.Data.readUInt16LE(73)).toString();
opt.unshift(result);
} else {
opt.unshift(null);
}
fn.apply(this, opt);
}, callback, optional);
};
this.getCertHashEntries = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.getHashHandles(function (handles, fn, opt) {
var entries = [];
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
}, callback, optional);
};
this._getHashEntrySink = function (result, fn, opt, entries, handles) {
entries.push(result);
if (handles.length > 0) {
this.getCertHashEntry(handles.shift(), this._getHashEntrySink, fn, opt, entries, handles);
} else {
opt.unshift(entries);
fn.apply(this, opt);
}
}
this.getLocalSystemAccount = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(103, Buffer.alloc(40), function (header, fn, opt) {
if (header.Data.length == 68) { opt.unshift({ user: header.Data.slice(0, 34).toString(), pass: header.Data.slice(34, 67).toString(), raw: header.Data }); } else { opt.unshift(null); }
fn.apply(this, opt);
}, callback, optional);
}
this.unprovision = function (mode, callback) {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
var data = new Buffer(4);
data.writeUInt32LE(mode, 0);
this.sendCommand(16, data, function (header, fn, opt) {
opt.unshift(header.Status);
fn.apply(this, opt);
}, callback, optional);
}
this.startConfiguration = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x29, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.stopConfiguration = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x5E, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.openUserInitiatedConnection = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x44, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.closeUserInitiatedConnection = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x45, data, function (header, fn, opt) { opt.unshift(header.Status); fn.apply(this, opt); }, callback, optional);
}
this.getRemoteAccessConnectionStatus = function () {
var optional = [];
for (var i = 2; i < arguments.length; ++i) { optional.push(arguments[i]); }
this.sendCommand(0x46, data, function (header, fn, opt) {
if (header.Status == 0) {
var hostname = v.slice(14, header.Data.readUInt16LE(12) + 14).toString()
opt.unshift({ status: header.Status, networkStatus: header.Data.readUInt32LE(0), remoteAccessStatus: header.Data.readUInt32LE(4), remoteAccessTrigger: header.Data.readUInt32LE(8), mpsHostname: hostname, raw: header.Data });
} else {
opt.unshift({ status: header.Status });
}
fn.apply(this, opt);
}, callback, optional);
}
this.getProtocolVersion = function (callback) {
var optional = [];
for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); }
heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) {
if (status == 0) {
var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString();
opt.unshift(result);
fn.apply(self, opt);
}
else {
opt.unshift(null);
fn.apply(self, opt);
}
}, this, callback, optional);
}
}
module.exports = amt_heci;

61
Debug/amt_test.js Normal file
View File

@@ -0,0 +1,61 @@
var amt_heci = require('amt_heci');
var amt = new amt_heci();
amt.getProtocolVersion(function (result)
{
console.log('protocol version = ' + result);
});
amt.on('error', function (e) { console.log(e);});
amt.on('connect', function()
{
console.log("Connected!");
this.getVersion(OnVersion);
this.getProvisioningState(OnProvisioningState);
this.getProvisioningMode(OnProvisioningMode);
this.getEHBCState(OnEHBC);
this.getControlMode(OnEHBC);
this.getMACAddresses(OnEHBC);
this.getDnsSuffix(OnDns);
this.getCertHashEntries(OnHashEntries);
//this.getHashHandles(OnGetHashHandles);
});
function OnGetHashHandles(handles)
{
console.log(handles.length + " HashHandles");
for (var i = 0; i < handles.length; ++i)
{
amt.getCertHashEntry(handles[i], OnEHBC);
}
}
function OnHashEntries(entries)
{
for(var i=0;i<entries.length;++i)
{
console.log(entries[i]);
}
}
function OnDns(dns)
{
console.log("Dns Suffix = " + dns);
}
function OnVersion(val)
{
console.log("Bios Version = " + val.BiosVersion.toString());
for(var version in val.Versions)
{
console.log(" " + val.Versions[version].Description + " = " + val.Versions[version].Version);
}
}
function OnProvisioningState(state)
{
console.log("ProvisioningState = " + state);
}
function OnProvisioningMode(result)
{
console.log("ProvisioningMode = " + result.mode + " [Legacy = " + result.legacy + "]");
}
function OnEHBC(result)
{
console.log(result);
}

View File

@@ -5,6 +5,39 @@ var js;
var sz = new Buffer(8);
var exeLen = 0;
var i;
var dependency = [];
var addOn = null;
for (i = 1; i < process.argv.length; ++i)
{
if(process.argv[i].startsWith('-i'))
{
try
{
dependency.push({ name:process.argv[i].slice(2,process.argv[i].indexOf('.js')), base64: fs.readFileSync(process.argv[i].slice(2)).toString('base64') });
process._argv.splice(i, 1);
i = 0;
}
catch(e)
{
console.log(e);
process.exit();
}
}
}
if (dependency.length > 0)
{
console.log("\nIntegrating Dependencies:")
addOn = "";
for(i=0;i<dependency.length;++i)
{
addOn += ("addModule('" + dependency[i].name + "', Buffer.from('" + dependency[i].base64 + "', 'base64'));\n");
console.log(" " + dependency[i].name);
}
console.log("");
}
if (process.argv0.endsWith('.js'))
{
console.log("Non-integrated executable");
@@ -47,6 +80,7 @@ else
console.log("Original Binary Size: " + exeLen);
}
if (addOn != null) { js = Buffer.concat([Buffer.from(addOn), js]); }
console.log("JavaScript Length: " + js.length);
w.write(exe.slice(0, exeLen), OnWroteExe);

36
Debug/heci.js Normal file
View File

@@ -0,0 +1,36 @@
var heci = require('heci');
var amt = null;
console.log("Starting HECI test...");
console.log("LME GUID = " + heci.GUIDS.LME.toString('hex'));
console.log("AMT GUID = " + heci.GUIDS.AMT.toString('hex'));
heci.doIoctl(heci.IOCTL.HECI_VERSION, null, new Buffer(16), OnVersion);
function OnVersion(status, buffer, arg)
{
if(status == 0)
{
console.log("HECI Driver Version = " + buffer[0] + "." + buffer[1]);
console.log("Attempting to create AMT/HECI connection");
amt = heci.create();
amt.connect(heci.GUIDS.AMT);
amt.on('connect', OnAMT);
amt.on('error', function (e) { console.log(e); });
}
else {
console.log("Could not determine HECI Driver Version");
}
}
function OnAMT()
{
console.log('AMT Connected');
amt.on('data', OnAMTData);
var header = Buffer.from('010100001A00000400000000', 'hex');
amt.write(header);
}
function OnAMTData(chunk)
{
console.log('Received ' + chunk.length + ' bytes of AMT Data');
}

56
Debug/httptest.js Normal file
View File

@@ -0,0 +1,56 @@
var http = require('http');
var https = require('https');
var WS;
console.log("Starting HTTP (Rewrite) Test");
var cert = https.generateCertificate('test');
var server = https.createServer();
server.on('request', function (imsg, rsp)
{
console.log('Received inbound request: ' + imsg.method + ' ' + imsg.url);
rsp.writeHead(200, 'OK', {'Content-Length': 0});
});
server.on('upgrade', function (imsg, sck, head)
{
console.log('Server On Upgrade');
WS = sck.upgradeWebSocket();
WS.on('pong', function () { console.log('Server received PONG'); WS.write('this is test'); WS.write(Buffer.from("This is a good day")); WS.end();});
WS.on('data', function (chunk) { console.log('Server received: ' + chunk); });
WS.ping();
});
server.listen({ port: 9095, pfx: cert, passphrase: 'test' });
//var req = http.get("http://127.0.0.1:9095/test.html");
//var req = http.get("ws://127.0.0.1:9095/test.html");
var req = http.request({ protocol: 'wss:', host: '127.0.0.1', port: 9095, method: 'GET', path: '/test.html', rejectUnauthorized: false})
req.end();
var req2 = http.request({ protocol: 'https:', host: '127.0.0.1', port: 9095, method: 'GET', path: '/test.html', rejectUnauthorized: false })
req2.end();
req.on('upgrade', function (imsg, sck, head)
{
console.log('client upgraded to WebSocket');
sck.on('ping', function () { console.log('Client received ping'); this.write('Client says hello');});
sck.on('data', function (chunk) { console.log('client received: ' + chunk, typeof (chunk)); });
sck.on('end', function () { console.log('Client side closed'); });
});
req.on('response', function (imsg)
{
console.log('received response', imsg.statusCode, imsg.statusMessage);
imsg.on('end', function () {
console.log('Done reading IncomingMessageStream');
});
})
req.on('error', function (err) { console.log('error received', err); });
req2.on('response', function (imsg) {
console.log('received response', imsg.statusCode, imsg.statusMessage);
imsg.on('end', function () {
console.log('Done reading IncomingMessageStream');
});
})
req2.on('error', function (err) { console.log('error received', err); });

355
Debug/lme_heci.js Normal file
View File

@@ -0,0 +1,355 @@
var MemoryStream = require('MemoryStream');
var lme_id = 0;
var APF_DISCONNECT = 1;
var APF_SERVICE_REQUEST = 5;
var APF_SERVICE_ACCEPT = 6;
var APF_USERAUTH_REQUEST = 50;
var APF_USERAUTH_FAILURE = 51;
var APF_USERAUTH_SUCCESS = 52;
var APF_GLOBAL_REQUEST = 80;
var APF_REQUEST_SUCCESS = 81;
var APF_REQUEST_FAILURE = 82;
var APF_CHANNEL_OPEN = 90;
var APF_CHANNEL_OPEN_CONFIRMATION = 91;
var APF_CHANNEL_OPEN_FAILURE = 92;
var APF_CHANNEL_WINDOW_ADJUST = 93;
var APF_CHANNEL_DATA = 94;
var APF_CHANNEL_CLOSE = 97;
var APF_PROTOCOLVERSION = 192;
function lme_object()
{
this.ourId = ++lme_id;
this.amtId = -1;
this.LME_CHANNEL_STATUS = 'LME_CS_FREE';
this.txWindow = 0;
this.rxWindow = 0;
this.localPort = 0;
this.errorCount = 0;
}
function stream_bufferedWrite()
{
var emitterUtils = require('events').inherits(this);
this.buffer = [];
this._readCheckImmediate = undefined;
// Writable Events
emitterUtils.createEvent('close');
emitterUtils.createEvent('drain');
emitterUtils.createEvent('error');
emitterUtils.createEvent('finish');
emitterUtils.createEvent('pipe');
emitterUtils.createEvent('unpipe');
// Readable Events
emitterUtils.createEvent('readable');
this.isEmpty = function ()
{
return (this.buffer.length == 0);
};
this.isWaiting = function ()
{
return (this._readCheckImmediate == undefined);
};
this.write = function (chunk)
{
for (var args in arguments)
{
if (typeof (arguments[args]) == 'function') { this.once('drain', arguments[args]); break; }
}
var tmp = Buffer.alloc(chunk.length);
chunk.copy(tmp);
this.buffer.push({ offset: 0, data: tmp });
this.emit('readable');
return (this.buffer.length == 0 ? true : false);
};
this.read = function ()
{
var size = arguments.length == 0 ? undefined : arguments[0];
var bytesRead = 0;
var list = [];
while((size == undefined || bytesRead < size) && this.buffer.length > 0)
{
var len = this.buffer[0].data.length - this.buffer[0].offset;
var offset = this.buffer[0].offset;
if(len > (size - bytesRead))
{
// Only reading a subset
list.push(this.buffer[0].data.slice(offset, offset + size - bytesRead));
this.buffer[0].offset += (size - bytesRead);
bytesRead += (size - bytesRead);
}
else
{
// Reading the entire thing
list.push(this.buffer[0].data.slice(offset));
bytesRead += len;
this.buffer.shift();
}
}
this._readCheckImmediate = setImmediate(function (buffered)
{
buffered._readCheckImmediate = undefined;
if(buffered.buffer.length == 0)
{
// drained
buffered.emit('drain');
}
else
{
// not drained
buffered.emit('readable');
}
}, this);
return (Buffer.concat(list));
};
}
function lme_heci()
{
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('error');
emitterUtils.createEvent('connect');
var heci = require('heci');
this.INITIAL_RXWINDOW_SIZE = 4096;
this._LME = heci.create();
this._LME.LMS = this;
this._LME.on('error', function (e) { this.Parent.emit('error', e); });
this._LME.on('connect', function ()
{
console.log('emitting connect');
this.LMS.emit('connect');
this.on('data', function (chunk)
{
// this = HECI
var cmd = chunk.readUInt8(0);
switch(cmd)
{
default:
//console.log('Received ' + chunk.length + ' bytes of data for LMS');
//console.log('Command = ' + cmd);
break;
case APF_SERVICE_REQUEST:
var nameLen = chunk.readUInt32BE(1);
var name = chunk.slice(5, nameLen + 5);
//console.log("Service Request for: " + name);
if (name == 'pfwd@amt.intel.com' || name == 'auth@amt.intel.com')
{
var outBuffer = Buffer.alloc(5 + nameLen);
outBuffer.writeUInt8(6, 0);
outBuffer.writeUInt32BE(nameLen, 1);
outBuffer.write(name.toString(), 5);
this.write(outBuffer);
//console.log('Answering APF_SERVICE_REQUEST');
}
else
{
//console.log('UNKNOWN APF_SERVICE_REQUEST');
}
break;
case APF_GLOBAL_REQUEST:
var nameLen = chunk.readUInt32BE(1);
var name = chunk.slice(5, nameLen + 5).toString();
switch(name)
{
case 'tcpip-forward':
var len = chunk.readUInt32BE(nameLen + 6);
var port = chunk.readUInt32BE(nameLen + 10 + len);
//console.log("[" + chunk.length + "/" + len + "] APF_GLOBAL_REQUEST for: " + name + " on port " + port);
if (this[name] == undefined)
{
this[name] = {};
}
this[name][port] = require('net').createServer();
this[name][port].HECI = this;
this[name][port].listen({ port: port });
this[name][port].on('connection', function (socket)
{
//console.log('New [' + socket.remoteFamily + '] TCP Connection on: ' + socket.remoteAddress + ' :' + socket.localPort);
this.HECI.LMS.bindDuplexStream(socket, socket.remoteFamily, socket.localPort);
});
var outBuffer = Buffer.alloc(5);
outBuffer.writeUInt8(81, 0);
outBuffer.writeUInt32BE(port, 1);
this.write(outBuffer);
break;
case 'cancel-tcpip-forward':
break;
case 'udp-send-to@amt.intel.com':
break;
default:
//console.log("Unknown APF_GLOBAL_REQUEST for: " + name);
break;
}
break;
case APF_CHANNEL_OPEN_CONFIRMATION:
var rChannel = chunk.readUInt32BE(1);
var sChannel = chunk.readUInt32BE(5);
var wSize = chunk.readUInt32BE(9);
//console.log('rChannel/' + rChannel + ', sChannel/' + sChannel + ', wSize/' + wSize);
if (this.sockets[rChannel] != undefined)
{
this.sockets[rChannel].lme.amtId = sChannel;
this.sockets[rChannel].lme.rxWindow = wSize;
this.sockets[rChannel].lme.txWindow = wSize;
this.sockets[rChannel].lme.LME_CHANNEL_STATUS = 'LME_CS_CONNECTED';
//console.log('LME_CS_CONNECTED');
this.sockets[rChannel].bufferedStream = new stream_bufferedWrite();
this.sockets[rChannel].bufferedStream.socket = this.sockets[rChannel];
this.sockets[rChannel].bufferedStream.on('readable', function ()
{
if(this.socket.lme.txWindow > 0)
{
var buffer = this.read(this.socket.lme.txWindow);
var packet = Buffer.alloc(9 + buffer.length);
packet.writeUInt8(APF_CHANNEL_DATA, 0);
packet.writeUInt32BE(this.socket.lme.amtId, 1);
packet.writeUInt32BE(buffer.length, 5);
buffer.copy(packet, 9);
this.socket.lme.txWindow -= buffer.length;
this.socket.HECI.write(packet);
}
});
this.sockets[rChannel].bufferedStream.on('drain', function ()
{
this.socket.resume();
});
this.sockets[rChannel].on('data', function (chunk)
{
if (!this.bufferedStream.write(chunk)) { this.pause(); }
});
this.sockets[rChannel].on('end', function ()
{
var outBuffer = Buffer.alloc(5);
outBuffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
outBuffer.writeUInt32BE(this.lme.amtId, 1);
this.HECI.write(outBuffer);
});
this.sockets[rChannel].resume();
}
break;
case APF_PROTOCOLVERSION:
var major = chunk.readUInt32BE(1);
var minor = chunk.readUInt32BE(5);
var reason = chunk.readUInt32BE(9);
var outBuffer = Buffer.alloc(93);
outBuffer.writeUInt8(192, 0);
outBuffer.writeUInt32BE(1, 1);
outBuffer.writeUInt32BE(0, 5);
outBuffer.writeUInt32BE(reason, 9);
//console.log('Answering PROTOCOL_VERSION');
this.write(outBuffer);
break;
case APF_CHANNEL_WINDOW_ADJUST:
var rChannelId = chunk.readUInt32BE(1);
var bytesToAdd = chunk.readUInt32BE(5);
if (this.sockets[rChannelId] != undefined)
{
this.sockets[rChannelId].lme.txWindow += bytesToAdd;
if (!this.sockets[rChannelId].bufferedStream.isEmpty() && this.sockets[rChannelId].bufferedStream.isWaiting())
{
this.sockets[rChannelId].bufferedStream.emit('readable');
}
}
else
{
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_WINDOW_ADJUST');
}
break;
case APF_CHANNEL_DATA:
var rChannelId = chunk.readUInt32BE(1);
var dataLen = chunk.readUInt32BE(5);
var data = chunk.slice(9, 9 + dataLen);
if (this.sockets[rChannelId] != undefined)
{
this.sockets[rChannelId].pendingBytes.push(data.length);
this.sockets[rChannelId].write(data, function ()
{
var written = this.pendingBytes.shift();
var outBuffer = Buffer.alloc(9);
outBuffer.writeUInt8(APF_CHANNEL_WINDOW_ADJUST, 0);
outBuffer.writeUInt32BE(this.lme.amtId, 1);
outBuffer.writeUInt32BE(written, 5);
this.HECI.write(outBuffer);
});
}
else
{
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_DATA');
}
break;
case APF_CHANNEL_CLOSE:
var rChannelId = chunk.readUInt32BE(1);
if (this.sockets[rChannelId] != undefined)
{
this.sockets[rChannelId].end();
var amtId = this.sockets[rChannelId].lme.amtId;
var buffer = Buffer.alloc(5);
delete this.sockets[rChannelId];
buffer.writeUInt8(APF_CHANNEL_CLOSE, 0);
buffer.writeUInt32BE(amtId, 1);
this.write(buffer);
}
else
{
//console.log('Unknown Recipient ID/' + rChannelId + ' for APF_CHANNEL_CLOSE');
}
break;
}
});
});
this.bindDuplexStream = function (duplexStream, remoteFamily, localPort)
{
var socket = duplexStream;
//console.log('New [' + remoteFamily + '] Virtual Connection/' + socket.localPort);
socket.pendingBytes = [];
socket.HECI = this._LME;
socket.LMS = this;
socket.lme = new lme_object();
socket.lme.Socket = socket;
var buffer = new MemoryStream();
buffer.writeUInt8(0x5A);
buffer.writeUInt32BE(15);
buffer.write('forwarded-tcpip');
buffer.writeUInt32BE(socket.lme.ourId);
buffer.writeUInt32BE(this.INITIAL_RXWINDOW_SIZE);
buffer.writeUInt32BE(0xFFFFFFFF);
for (var i = 0; i < 2; ++i)
{
if (remoteFamily == 'IPv6')
{
buffer.writeUInt32BE(3);
buffer.write('::1');
}
else
{
buffer.writeUInt32BE(9);
buffer.write('127.0.0.1');
}
buffer.writeUInt32BE(localPort);
}
this._LME.write(buffer.buffer);
if (this._LME.sockets == undefined) { this._LME.sockets = {}; }
this._LME.sockets[socket.lme.ourId] = socket;
socket.pause();
};
this._LME.connect(heci.GUIDS.LME, { noPipeline: 0 });
}
module.exports = lme_heci;

37
Debug/lme_test.js Normal file

File diff suppressed because one or more lines are too long

18
Debug/newstringtest.js Normal file
View File

@@ -0,0 +1,18 @@
var http = require('http');
console.log('starting client test');
console.log('Sending Request');
var req = http.request({host: '127.0.0.1', port: 9093, protocol: 'ws:'});
req.on('upgrade', function (res, sk, h)
{
sk.on('ping', function () { console.log('received ping'); });
sk.on('pong', function () { console.log('received pong'); });
this.websocket = sk;
console.log("Upgraded to WebSocket!"); sk.write(JSON.stringify({ a: 'hello' }));
});
//req.end();

205
Debug/parseXml.js Normal file
View File

@@ -0,0 +1,205 @@
Object.defineProperty(Array.prototype, "peek",
{
value: function ()
{
return (this.length > 0 ? this[this.length - 1] : undefined);
}
});
function _treeBuilder()
{
this.tree = [];
this.push = function (element)
{
this.tree.push(element);
};
this.pop = function ()
{
var element = this.tree.pop();
if(this.tree.length>0)
{
this.tree.peek().childNodes.push(element);
}
return (element);
};
this.peek = function()
{
return (this.tree.peek());
}
this.addNamespace = function(prefix, namespace)
{
this.tree.peek().nsTable[prefix] = namespace;
if(this.tree.peek().attributes.length > 0)
{
for(var i = 0; i<this.tree.peek().attributes; ++i)
{
var a = this.tree.peek().attributes[i];
if(prefix == '*' && a.name == a.localName)
{
a.namespace = namespace;
}
else if(prefix != '*' && a.name != a.localName)
{
var pfx = a.name.split(':')[0];
if(pfx == prefix)
{
a.namespace = namespace;
}
}
}
}
}
this.getNamespace = function(prefix)
{
for(var i=this.tree.length-1;i>=0;--i)
{
if(this.tree[i].nsTable[prefix] != undefined)
{
return (this.tree[i].nsTable[prefix]);
}
}
return ('undefined');
}
}
// This is a drop-in replacement to _turnToXml() that works without xml parser dependency.
function _turnToXml(text)
{
if (text == null) return null;
return ({ childNodes: [_turnToXmlRec(text)], getElementsByTagName: _getElementsByTagName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS });
}
function _getElementsByTagNameNS(ns, name)
{
var ret = []; _xmlTraverseAllRec(this.childNodes, function (node)
{
if (node.localName == name && (node.namespace == ns || ns == '*')) { ret.push(node); }
}); return ret;
}
function _getElementsByTagName(name)
{
var ret = []; _xmlTraverseAllRec(this.childNodes, function (node)
{
if (node.localName == name) { ret.push(node); }
}); return ret;
}
function _getChildElementsByTagName(name)
{
var ret = [];
if (this.childNodes != undefined)
{
for (var node in this.childNodes) {
if (this.childNodes[node].localName == name) { ret.push(this.childNodes[node]); }
}
}
return (ret);
}
function _getChildElementsByTagNameNS(ns, name)
{
var ret = [];
if (this.childNodes != undefined)
{
for (var node in this.childNodes)
{
if (this.childNodes[node].localName == name && (ns == '*' || this.childNodes[node].namespace == ns)) { ret.push(this.childNodes[node]); }
}
}
return (ret);
}
function _xmlTraverseAllRec(nodes, func) { for (var i in nodes) { func(nodes[i]); if (nodes[i].childNodes) { _xmlTraverseAllRec(nodes[i].childNodes, func); } } }
function _turnToXmlRec(text)
{
var elementStack = new _treeBuilder();
var lastElement = null;
var x1 = text.split('<'), ret = [], element = null, currentElementName = null;
for (var i in x1)
{
var x2 = x1[i].split('>'), x3 = x2[0].split(' '), elementName = x3[0];
if ((elementName.length > 0) && (elementName[0] != '?'))
{
if (elementName[0] != '/')
{
var localName;
var localname2 = elementName.split(' ')[0].split(':'), localName = (localname2.length > 1) ? localname2[1] : localname2[0];
var attributes = [];
Object.defineProperty(attributes, "get",
{
value: function ()
{
if (arguments.length == 1)
{
for (var a in this) { if (this[a].name == arguments[0]) { return (this[a]); } }
}
else if (arguments.length == 2)
{
for (var a in this) { if (this[a].name == arguments[1] && (arguments[0] == '*' || this[a].namespace == arguments[0])) { return (this[a]); } }
}
else
{
throw ('attributes.get(): Invalid number of parameters');
}
}
});
elementStack.push({ name: elementName, localName: localName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS, getChildElementsByTagNameNS: _getChildElementsByTagNameNS, attributes: attributes, childNodes: [], nsTable: {} });
// Parse Attributes
if (x3.length > 0)
{
var skip = false;
for (var j in x3)
{
if (x3[j] == '/')
{
// This is an empty Element
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
elementStack.peek().textContent = '';
lastElement = elementStack.pop();
skip = true;
break;
}
var k = x3[j].indexOf('=');
if (k > 0)
{
var attrName = x3[j].substring(0, k);
var attrValue = x3[j].substring(k + 2, x3[j].length - 1);
var attrNS = elementStack.getNamespace('*');
if (attrName == 'xmlns')
{
elementStack.addNamespace('*', attrValue);
attrNS = attrValue;
}
else if (attrName.startsWith('xmlns:'))
{
elementStack.addNamespace(attrName.substring(6), attrValue);
}
else
{
var ax = attrName.split(':');
if (ax.length == 2) { attrName = ax[1]; attrNS = elementStack.getNamespace(ax[0]); }
}
elementStack.peek().attributes.push({ name: attrName, value: attrValue, namespace: attrNS });
}
}
if (skip) { continue; }
}
elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
if (x2[1]) { elementStack.peek().textContent = x2[1]; }
}
else
{
lastElement = elementStack.pop();
}
}
}
return lastElement;
}
module.exports = _turnToXml;

243
Debug/serviceManager.js Normal file
View File

@@ -0,0 +1,243 @@
function parseServiceStatus(token)
{
var j = {};
var serviceType = token.Deref(0, 4).IntVal;
j.isFileSystemDriver = ((serviceType & 0x00000002) == 0x00000002);
j.isKernelDriver = ((serviceType & 0x00000001) == 0x00000001);
j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
switch (token.Deref((1 * 4), 4).IntVal)
{
case 0x00000005:
j.state = 'CONTINUE_PENDING';
break;
case 0x00000006:
j.state = 'PAUSE_PENDING';
break;
case 0x00000007:
j.state = 'PAUSED';
break;
case 0x00000004:
j.state = 'RUNNING';
break;
case 0x00000002:
j.state = 'START_PENDING';
break;
case 0x00000003:
j.state = 'STOP_PENDING';
break;
case 0x00000001:
j.state = 'STOPPED';
break;
}
var controlsAccepted = token.Deref((2 * 4), 4).IntVal
j.controlsAccepted = [];
if ((controlsAccepted & 0x00000010) == 0x00000010)
{
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDDISABLE');
}
if ((controlsAccepted & 0x00000008) == 0x00000008) { j.controlsAccepted.push('SERVICE_CONTROL_PARAMCHANGE'); }
if ((controlsAccepted & 0x00000002) == 0x00000002) { j.controlsAccepted.push('SERVICE_CONTROL_PAUSE'); j.controlsAccepted.push('SERVICE_CONTROL_CONTINUE'); }
if ((controlsAccepted & 0x00000100) == 0x00000100) { j.controlsAccepted.push('SERVICE_CONTROL_PRESHUTDOWN'); }
if ((controlsAccepted & 0x00000004) == 0x00000004) { j.controlsAccepted.push('SERVICE_CONTROL_SHUTDOWN'); }
if ((controlsAccepted & 0x00000001) == 0x00000001) { j.controlsAccepted.push('SERVICE_CONTROL_STOP'); }
if ((controlsAccepted & 0x00000020) == 0x00000020) { j.controlsAccepted.push('SERVICE_CONTROL_HARDWAREPROFILECHANGE'); }
if ((controlsAccepted & 0x00000040) == 0x00000040) { j.controlsAccepted.push('SERVICE_CONTROL_POWEREVENT'); }
if ((controlsAccepted & 0x00000080) == 0x00000080) { j.controlsAccepted.push('SERVICE_CONTROL_SESSIONCHANGE'); }
j.pid = token.Deref((7 * 4), 4).IntVal
return (j);
}
function serviceManager()
{
this.GM = require('_GenericMarshal');
this.proxy = this.GM.CreateNativeProxy('Advapi32.dll');
this.proxy.CreateMethod('OpenSCManagerA');
this.proxy.CreateMethod('EnumServicesStatusExA');
this.proxy.CreateMethod('OpenServiceA');
this.proxy.CreateMethod('QueryServiceStatusEx');
this.proxy.CreateMethod('ControlService');
this.proxy.CreateMethod('StartServiceA');
this.proxy.CreateMethod('CloseServiceHandle');
this.proxy.CreateMethod('CreateServiceA');
this.proxy.CreateMethod('ChangeServiceConfig2A');
this.proxy.CreateMethod('DeleteService');
this.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
this.proxy2.CreateMethod('GetLastError');
this.enumerateService = function()
{
var machineName = this.GM.CreatePointer();
var dbName = this.GM.CreatePointer();
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004);
var bytesNeeded = this.GM.CreateVariable(4);
var servicesReturned = this.GM.CreateVariable(4);
var resumeHandle = this.GM.CreateVariable(4);
//var services = this.proxy.CreateVariable(262144);
var success = this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, 0x00, 0x00, bytesNeeded, servicesReturned, resumeHandle, 0x00);
if(bytesNeeded.IntVal <= 0)
{
throw ('error enumerating services');
}
var sz = bytesNeeded.IntVal;
var services = this.GM.CreateVariable(sz);
this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, services, sz, bytesNeeded, servicesReturned, resumeHandle, 0x00);
console.log("servicesReturned", servicesReturned.IntVal, 'PtrSize = ' + dbName._size);
var ptrSize = dbName._size;
var blockSize = 36 + (2 * ptrSize);
console.log('blockSize', blockSize);
var retVal = [];
for (var i = 0; i < servicesReturned.IntVal; ++i)
{
var token = services.Deref(i * blockSize, blockSize);
var j = {};
j.name = token.Deref(0, ptrSize).Deref().String;
j.displayName = token.Deref(ptrSize, ptrSize).Deref().String;
j.status = parseServiceStatus(token.Deref(2 * ptrSize, 36));
retVal.push(j);
}
this.proxy.CloseServiceHandle(handle);
return (retVal);
}
this.getService = function(name)
{
var serviceName = this.GM.CreateVariable(name);
var ptr = this.GM.CreatePointer();
var bytesNeeded = this.GM.CreateVariable(ptr._size);
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004 | 0x0020 | 0x0010);
if (handle == 0) { throw ('could not open ServiceManager'); }
var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
if (h != 0)
{
var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
var status = this.GM.CreateVariable(bytesNeeded.IntVal);
success = this.proxy.QueryServiceStatusEx(h, 0, status, status._size, bytesNeeded);
if (success != 0)
{
retVal = {};
retVal.status = parseServiceStatus(status);
retVal._scm = handle;
retVal._service = h;
retVal._GM = this.GM;
retVal._proxy = this.proxy;
require('events').inherits(retVal);
retVal.on('~', function () { this._proxy.CloseServiceHandle(this); this._proxy.CloseServiceHandle(this._scm); });
retVal.name = name;
retVal.stop = function()
{
if(this.status.state == 'RUNNING')
{
var newstate = this._GM.CreateVariable(36);
var success = this._proxy.ControlService(this._service, 0x00000001, newstate);
if(success == 0)
{
throw (this.name + '.stop() failed');
}
}
else
{
throw ('cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
}
}
retVal.start = function()
{
if(this.status.state == 'STOPPED')
{
var success = this._proxy.StartServiceA(this._service, 0, 0);
if(success == 0)
{
throw (this.name + '.start() failed');
}
}
else
{
throw ('cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
}
}
return (retVal);
}
else
{
}
}
this.proxy.CloseServiceHandle(handle);
throw ('could not find service: ' + name);
}
this.installService = function(options)
{
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
if (handle == 0) { throw ('error opening SCManager'); }
var serviceName = this.GM.CreateVariable(options.name);
var displayName = this.GM.CreateVariable(options.displayName);
var allAccess = 0x000F01FF;
var serviceType;
var servicePath = this.GM.CreateVariable(options.servicePath);
switch(options.startType)
{
case 'BOOT_START':
serviceType = 0x00;
break;
case 'SYSTEM_START':
serviceType = 0x01;
break;
case 'AUTO_START':
serviceType = 0x02;
break;
case 'DEMAND_START':
serviceType = 0x03;
break;
default:
serviceType = 0x04; // Disabled
break;
}
var h = this.proxy.CreateServiceA(handle, serviceName, displayName, allAccess, 0x10 | 0x100, serviceType, 0, servicePath, 0, 0, 0, 0, 0);
if (h == 0) { this.proxy.CloseServiceHandle(handle); throw ('Error Creating Service'); }
if(options.description)
{
console.log(options.description);
var dscPtr = this.GM.CreatePointer();
dscPtr.Val = this.GM.CreateVariable(options.description);
if(this.proxy.ChangeServiceConfig2A(h, 1, dscPtr)==0)
{
this.proxy.CloseServiceHandle(h);
this.proxy.CloseServiceHandle(handle);
throw ('Unable to set description');
}
}
this.proxy.CloseServiceHandle(h);
this.proxy.CloseServiceHandle(handle);
return (this.getService(options.name));
}
this.uninstallService = function(name)
{
var service = this.getService(name);
if(service.status.state == 'STOPPED')
{
if (this.proxy.DeleteService(service._service) == 0) { throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError()); }
}
else
{
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
}
}
}
module.exports = serviceManager;

655
Debug/upnpcp.js Normal file
View File

@@ -0,0 +1,655 @@
var parseXml = require('parseXml');
var http = require('http');
var dgram = require('dgram');
var os = require('os');
var MemoryStream = require('MemoryStream');
var net = require('net');
//var networkMonitor = require('NetworkMonitor');
function upnpdevice(descriptionUrl, usn, cp)
{
var d = descriptionUrl.split('/');
this.BaseURL = d[0] + '//' + d[2];
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('bye');
emitterUtils.createEvent('error');
emitterUtils.createEvent('alive');
emitterUtils.createEvent('serviceLoaded');
this.pendingServices = 0;
this.usn = usn;
this.cp = cp;
this.req = http.get(descriptionUrl);
this.req.device = this;
this.req.on('error', function ()
{
this.device.emit('error', 'Error fetching Description Document from ' + this.device.BaseURL);
});
this.req.on('response', function (msg)
{
if (msg.statusCode == 200)
{
msg.device = this.device;
this.device.dd = new MemoryStream();
this.device.dd.device = this.device;
msg.pipe(this.device.dd);
this.device.dd.on('end', function ()
{
upnpdevice_parseXml.apply(this.device, [this.buffer.toString()]);
});
}
else
{
this.device.emit('error', 'Error (' + msg.statusCode + ') Fetching Description Document from: ' + this.device.BaseURL);
}
});
this.loadAllServices = function () { this.rootDevice.loadAllServices(); };
this.makeUrl = function (url)
{
if(url.startsWith('/'))
{
if (this.BaseURL.endsWith('/'))
{
return (this.BaseURL + url.substring(1));
}
else
{
return (this.BaseURL + url);
}
}
else
{
if (this.BaseURL.endsWith('/'))
{
return (this.BaseURL + url);
}
else
{
return (this.BaseURL + '/' + url);
}
}
};
this.on('~', upnpdevice_Cleanup);
this.on('serviceLoaded', function (svc)
{
if(--this.pendingServices == 0)
{
// All Services have been loaded
this.cp.emit('device', this);
}
});
this.getDevice = function (udn)
{
return (this.rootDevice.getDevice(udn));
};
}
function upnpdevice_Cleanup()
{
console.log('Finalizing: ' + this.rootDevice.friendlyName);
}
function upnpservice(parentDevice, xmlDoc)
{
var emitterUtils = require('events').inherits(this);
this.device = parentDevice;
this.serviceType = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'serviceType')[0].textContent;
this.serviceId = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'serviceId')[0].textContent;
this.controlURL = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'controlURL')[0].textContent;
this.eventSubURL = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'eventSubURL')[0].textContent;
this.SCPDURL = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'SCPDURL')[0].textContent;
if (!this.controlURL.startsWith('http:') && !this.controlURL.startsWith('https:')) { this.controlURL = this.device.rootDevice.makeUrl(this.controlURL); }
if (!this.eventSubURL.startsWith('http:') && !this.eventSubURL.startsWith('https:')) { this.eventSubURL = this.device.rootDevice.makeUrl(this.eventSubURL); }
if (!this.SCPDURL.startsWith('http:') && !this.SCPDURL.startsWith('https:')) { this.SCPDURL = this.device.rootDevice.makeUrl(this.SCPDURL); }
this.load = function ()
{
++this.device.rootDevice.pendingServices;
this.req = http.get(this.SCPDURL);
this.req.service = this;
this.req.on('error', function () { this.service.device.rootDevice.emit('error', 'Error fetching SCPD from: ' + this.service.SCPDURL); });
this.req.on('response', function (msg)
{
if (msg.statusCode == 200)
{
msg.service = this.service;
this.service.scpdxml = new MemoryStream();
this.service.scpdxml.service = this.service;
msg.pipe(this.service.scpdxml);
this.service.scpdxml.on('end', function ()
{
try
{
upnpservice_parseScpd.apply(this.service, [this.buffer.toString()]);
}
catch(e)
{
this.service.device.rootDevice.emit('error', 'error parsing SCPD: ' + e);
}
});
}
else
{
this.service.device.rootDevice.emit('error', 'Error loading SCPD from: ' + this.service.SCPDURL);
}
});
}
this.getAction = function(name)
{
for(var a in this.actions)
{
if (this.actions[a].name == name) { return (this.actions[a]); }
}
return (undefined);
}
}
function upnpargument(action, xmlDoc)
{
this.action = action;
this.name = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'name')[0].textContent;
this.direction = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'direction')[0].textContent;
this.relatedStateVariable = action.service.stateVariables.get(xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'relatedStateVariable')[0].textContent);
}
function post_response(msg)
{
if (msg.statusCode != 200)
{
var userArgs = this.args;
if (userArgs.length > 0 && typeof (userArgs[0] == 'function'))
{
var fn = userArgs.shift();
userArgs.unshift(msg.StatusCode ? msg.StatusCode : msg.url);
fn.apply(this.action, userArgs);
}
return;
}
var buff = new MemoryStream();
buff.req = this;
msg.pipe(buff);
buff.on('end', function ()
{
var body = {};
var xml = parseXml(this.buffer.toString());
var action = this.req.action;
var userArgs = this.req.args;
var actionResponse = xml.getElementsByTagNameNS(action.service.serviceType, action.name + 'Response')[0];
if(actionResponse)
{
for(var child in actionResponse.childNodes)
{
if(action.arguments.get(actionResponse.childNodes[child].name))
{
body[actionResponse.childNodes[child].name] = actionResponse.childNodes[child].textContent;
}
}
if(userArgs.length > 0 && typeof(userArgs[0]) == 'function')
{
var fn = userArgs.shift();
userArgs.unshift(body);
fn.apply(action, userArgs);
}
}
});
}
function upnpaction(service, xmlDoc)
{
this.pendingPosts = [];
this.arguments = []; Object.defineProperty(this.arguments, "get", { value: function (name) { for (var i in this) { if (this[i].name == name) { return (this[i]); } } return (undefined); } });
this.service = service;
this.name = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'name')[0].textContent;
var argumentList = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'argumentList')[0];
if (argumentList)
{
var arguments = argumentList.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'argument');
for (var i in arguments)
{
this.arguments.push(new upnpargument(this, arguments[i]));
}
}
else
{
//console.log(this.service.scpdxml.buffer.toString());
}
this.invoke = function (args)
{
var parameters = '';
for (var i in this.arguments)
{
if(this.arguments[i].direction == 'in' && args[this.arguments[i].name])
{
parameters += ('<u:' + this.arguments[i].name + '>' + args[this.arguments[i].name] + '</u:' + this.arguments[i].name + '>');
}
else if(this.arguments.direction == 'in')
{
throw ('missing parameter: [' + this.arguments[i].name + '] when invoking Action: ' + this.name);
}
}
var controlUri = http.parseUri(this.service.controlURL);
console.log(controlUri);
var headers = { HOST: (controlUri.host + ':' + controlUri.port), SOAPACTION: '"' + this.service.serviceType + '#' + this.name + '"', 'Content-Type': 'text/xml; charset="utf-8"' };
this.pendingPosts.push(http.request({ protocol: 'http', host: controlUri.host, port: controlUri.port, method: 'POST', path: controlUri.path, headers: headers }));
this.pendingPosts.peek().action = this;
this.pendingPosts.peek().args = [];
for (var i = 1; i < arguments.length; ++i)
{
this.pendingPosts.peek().args.push(arguments[i]);
}
this.pendingPosts.peek().on('response', post_response);
var txt = '<?xml version="1.0" encoding="utf-8"?>\r\n<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>';
this.pendingPosts.peek().write(txt);
console.log(txt);
txt = '<u:' + this.name + ' xmlns:u="' + this.service.serviceType + '">';
this.pendingPosts.peek().write(txt);
console.log(txt);
if (parameters != '')
{
this.pendingPosts.peek().write(parameters);
console.log(parameters);
}
this.pendingPosts.peek().write('</u:' + this.name + '>');
this.pendingPosts.peek().write('</s:Body></s:Envelope>');
console.log('</u:' + this.name + '>' + '</s:Body></s:Envelope>');
this.pendingPosts.peek().end();
};
this.invokeLegacy = function (args)
{
var controlUri = http.parseUri(this.service.controlURL);
var parameters = '';
for (var i in this.arguments) {
if (this.arguments[i].direction == 'in' && args[this.arguments[i].name]) {
parameters += ('<u:' + this.arguments[i].name + '>' + args[this.arguments[i].name] + '</u:' + this.arguments[i].name + '>');
}
else if (this.arguments.direction == 'in') {
throw ('missing parameter: [' + this.arguments[i].name + '] when invoking Action: ' + this.name);
}
}
this.pendingPosts.push(net.connect({ host: controlUri.host, port: controlUri.port }));
this.pendingPosts.peek().path = controlUri.path;
this.pendingPosts.peek().args = args;
this.pendingPosts.peek().parameters = parameters;
this.pendingPosts.peek().action = this;
this.pendingPosts.peek().headers = { HOST: (controlUri.host + ':' + controlUri.port), SOAPACTION: '"' + this.service.serviceType + '#' + this.name + '"', 'Content-Type': 'text/xml; charset="utf-8"' };
this.pendingPosts.peek().on('connect', function ()
{
console.log('legacy connected');
this.write('POST ' + this.path + ' HTTP/1.1\r\n');
var headers = this.headers;
this.write('HOST: ' + headers.HOST + '\r\n');
this.write('SOAPACTION: ' + headers.SOAPACTION + '\r\n');
this.write('Content-Type: ' + headers['Content-Type'] + '\r\n');
var txt = '<?xml version="1.0" encoding="utf-8"?>\r\n<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>';
txt += '<u:' + this.action.name + ' xmlns:u="' + this.action.service.serviceType + '">';
txt += this.parameters;
txt += ('</u:' + this.name + '>' + '</s:Body></s:Envelope>');
var b = Buffer.from(txt);
this.write('Content-Length: ' + b.length + '\r\n\r\n');
this.write(b);
});
this.pendingPosts.peek().http = http.createStream();
this.pendingPosts.peek().pipe(this.pendingPosts.peek().http);
this.pendingPosts.peek().http.on('response', post_response);
};
}
function upnpvariable(service, xmlDoc)
{
this.service = service;
this.name = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'name')[0].textContent;
this.dataType = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'dataType')[0].textContent;
this.evented = xmlDoc.attributes.get('sendEvents').value;
if (this.evented == 'yes')
{
this.currentValue = null;
}
}
function upnpservice_parseScpd(scpd)
{
this.stateVariables = []; Object.defineProperty(this.stateVariables, "get", { value: function (name) { for (var i in this) { if (this[i].name == name) { return (this[i]); } } return (undefined); } });
this.actions = []; Object.defineProperty(this.actions, "get", { value: function (name) { for (var i in this) { if (this[i].name == name) { return (this[i]); } } return (undefined); } });
var doc = parseXml(scpd);
var stateTable = doc.getElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'serviceStateTable')[0];
var variables = stateTable.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'stateVariable');
for (var i in variables)
{
this.stateVariables.push(new upnpvariable(this, variables[i]));
}
var actionList = doc.getElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'actionList')[0];
var actions = actionList.getChildElementsByTagNameNS('urn:schemas-upnp-org:service-1-0', 'action');
for (var i in actions)
{
try
{
this.actions.push(new upnpaction(this, actions[i]));
}
catch(e)
{
this.device.rootDevice.emit('error', 'error parsing SCPD/Action: ' + e);
return;
}
}
this.subscribe = function ()
{
};
this.device.rootDevice.emit('serviceLoaded', this);
}
function upnpdevice_child(rootDevice, xmlDoc)
{
this.rootDevice = rootDevice;
this.services = []; Object.defineProperty(this.services, "get", { value: function (id) { for (var i in this) { if (this[i].serviceType == id || this[i].serviceId == id) { return (this[i]); } } return (undefined); } });
this.embeddedDevices = []; Object.defineProperty(this.embeddedDevices, "get", { value: function (id) { for (var i in this) { if (this[i].UDN == id || this[i].deviceType == id) { return (this[i]); } } return (undefined); } });
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('bye');
emitterUtils.createEvent('error');
this.friendlyName = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'friendlyName')[0].textContent;
this.deviceType = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'deviceType')[0].textContent;
this.UDN = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'UDN')[0].textContent;
this.manufacturer = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'manufacturer')[0].textContent;
var serviceList = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'serviceList')[0]
for (var i in serviceList.childNodes)
{
if(serviceList.childNodes[i].namespace == 'urn:schemas-upnp-org:device-1-0')
{
this.services.push(new upnpservice(this, serviceList.childNodes[i]));
}
}
var deviceList = xmlDoc.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'deviceList')[0]
if (deviceList != null)
{
var devices = deviceList.getChildElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'device')
for (var device in devices)
{
this.embeddedDevices.push(new upnpdevice_child(rootDevice, devices[device]));
}
//console.log(devices);
}
this.loadAllServices = function () { for (var i in this.services) { this.services[i].load();} for (var i in this.embeddedDevices) { this.embeddedDevices[i].loadAllServices(); } };
this.getDevice = function (udn)
{
if (this.UDN == udn) { return (this); }
for(var ed in this.embeddedDevices)
{
var ret = this.embeddedDevices[ed].getDevice(udn);
if (ret) { return (ret); }
}
return (undefined);
};
this.getService = function(id)
{
for (var s in this.services)
{
if (this.services[s].serviceId == id) { return (this.services[s]); }
}
return (undefined);
}
}
function upnpdevice_parseXml(xml)
{
this.dd = null;
var doc = parseXml(xml);
//var URLBase = doc.getElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'URLBase')[0];
//if (URLBase != null) { console.log("old base: " + this.BaseURL); this.BaseURL = URLBase.textContent; }
var root = doc.getElementsByTagNameNS('urn:schemas-upnp-org:device-1-0', 'device')[0];
if (root != null)
{
this.rootDevice = new upnpdevice_child(this, root);
if (!this.cp.searchString.startsWith('ssdp:') && !this.cp.searchString.startsWith('upnp:') && !this.cp.searchString.startsWith('urn:') && !this.cp.searchString.startsWith('uuid:'))
{
// Friendly Name Search
if(this.rootDevice.friendlyName == this.cp.searchString)
{
//console.log(xml);
this.rootDevice.loadAllServices();
}
}
else
{
console.log(this.cp.searchString.split(':')[0]);
switch(this.cp.searchString.split(':')[0])
{
case 'ssdp':
break;
case 'upnp':
this.rootDevice.loadAllServices();
break;
case 'uuid':
break;
case 'urn':
break;
}
}
//console.log(this.rootDevice.friendlyName);
}
}
function upnpcp_onSearch(msg, rinfo)
{
var header = require('http-headers')(msg);
if (header.statusCode != 200) { return; }
var usn = header.headers.usn.split('::')[0];
if(this.cp.deviceTable[usn] == null)
{
this.cp.deviceTable[usn] = new upnpdevice(header.headers.location, usn, this.cp);
this.cp.deviceTable[usn].on('error', function (e) { console.log('Removing Device/' + this.usn + ' due to error: ' + e); this.cp.deviceTable[this.usn] = null; });
this.cp.deviceTable[usn].on('alive', function () { this.cp.emit('device', this); });
}
}
function upnpcp(search)
{
this.searchString = search;
if (!search.startsWith('ssdp:') && !search.startsWith('upnp:') && !search.startsWith('uuid:') && !search.startsWith('urn:'))
{
// Search by Friendly Name
search = 'upnp:rootdevice';
}
var MSEARCH = 'M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nST: ' + search + '\r\nMAN: "ssdp:discover"\r\nMX: 5\r\nContent-Length: 0\r\n\r\n';
var emitterUtils = require('events').inherits(this);
emitterUtils.createEvent('device');
this.searchSocket = dgram.createSocket({ type: 'udp4' });
this.searchSocket.cp = this;
this.searchSocket.bind({ port: 0, address:'0.0.0.0' });
this.deviceTable = {};
this.searchSocket.on('message', upnpcp_onSearch);
var interfaces = os.networkInterfaces();
for(var name in interfaces)
{
for (var i in interfaces[name])
{
if (interfaces[name][i].family == 'IPv4' && interfaces[name][i].status == 'up')
{
console.log('Sending Multicast on: ' + interfaces[name][i].address + ' to: 239.255.255.250:1900');
this.searchSocket.setMulticastTTL(1);
this.searchSocket.setMulticastLoopback(true);
this.searchSocket.setMulticastInterface(interfaces[name][i].address);
this.searchSocket.send(MSEARCH, 1900, '239.255.255.250');
}
}
}
}
//var testCP = new upnpcp("Samsung CLX-3300 Series (10.128.125.118)");
function display_device(dv)
{
if (!dv) { console.log('No match'); return; }
console.log('FriendlyName/ ' + dv.friendlyName);
console.log(' DeviceType/ ' + dv.deviceType);
console.log(' DeviceUDN/ ' + dv.UDN);
for (var svc in dv.services)
{
console.log(' ServiceID/ ' + dv.services[svc].serviceId);
}
for (var ed in dv.embeddedDevices)
{
console.log(' Embedded Device: ' + dv.embeddedDevices[ed].friendlyName + ' [' + dv.embeddedDevices[ed].UDN + ']');
}
}
function display_action(action)
{
var argString = null;
for (var arg in action.arguments)
{
if (action.arguments[arg].direction == 'in')
{
if (argString)
{
argString += (', ' + action.arguments[arg].name);
}
else
{
argString = action.arguments[arg].name;
}
}
}
console.log(' ' + action.name + '(' + (argString?argString:'') + ')');
}
function display_actionDetail(action)
{
if (!action) { console.log('no match'); return; }
console.log('Action: ' + action.name);
console.log(' Input Parameters:');
console.log(' {');
for (var arg in action.arguments)
{
if (action.arguments[arg].direction == 'in')
{
console.log(' [' + action.arguments[arg].relatedStateVariable.dataType + '] ' + action.arguments[arg].name);
}
}
console.log(' }');
console.log(' Output Parameters:');
console.log(' {');
for (var arg in action.arguments)
{
if (action.arguments[arg].direction == 'out')
{
console.log(' [' + action.arguments[arg].relatedStateVariable.dataType + '] ' + action.arguments[arg].name);
}
}
console.log(' }');
}
function display_service(svc)
{
if (!svc) { console.log('No match'); return; }
console.log('ServiceID/ ' + svc.serviceId);
console.log('ServiceType/ ' + svc.serviceType);
console.log('Actions:');
for(var action in svc.actions)
{
display_action(svc.actions[action]);
}
}
var testCP;
if (process.argv.length > 1)
{
if(process.argv[1].startsWith('discover='))
{
testCP = new upnpcp(process.argv[1].split('=')[1]);
}
}
if (!testCP) { process.exit(); }
testCP.on('device', function (dv)
{
var selectedDevice = null;
var selectedService = null;
var selectedAction = null;
console.log('');
console.log('Device Added: ');
display_device(dv.rootDevice);
console.log('');
for (var arg in process.argv)
{
if(process.argv[arg].startsWith('dv='))
{
var i = parseInt(process.argv[arg].split('=')[1]);
console.log('Selected Embedded Device: ' + i);
display_device(dv.rootDevice.embeddedDevices[i]);
selectedDevice = dv.rootDevice.embeddedDevices[i];
}
if(process.argv[arg].startsWith('udn='))
{
console.log('Selected Device: ' + process.argv[arg].split('=')[1]);
selectedDevice = dv.getDevice(process.argv[arg].split('=')[1]);
display_device(selectedDevice);
}
if(selectedDevice && process.argv[arg].startsWith('serviceId='))
{
selectedService = selectedDevice.getService(process.argv[arg].split('=')[1]);
display_service(selectedService);
}
if(selectedService && process.argv[arg].startsWith('action='))
{
selectedAction = selectedService.getAction(process.argv[arg].split('=')[1]);
display_actionDetail(selectedAction);
}
if(selectedAction && process.argv[arg].startsWith('invoke='))
{
var txt = process.argv[arg].split('=')[1];
console.log('Invoking with: ' + txt);
selectedAction.invoke(JSON.parse(process.argv[arg].split('=')[1]), function ()
{
console.log('Response: ', arguments[0]);
process.exit();
});
}
if (selectedAction && process.argv[arg].startsWith('invokeLegacy=')) {
var txt = process.argv[arg].split('=')[1];
console.log('Invoking with: ' + txt);
selectedAction.invokeLegacy(JSON.parse(process.argv[arg].split('=')[1]), function () {
console.log('Response: ', arguments[0]);
process.exit();
});
}
}
});

View File

@@ -36,10 +36,10 @@ SOURCES += microscript/duktape.c microscript/ILibAsyncSocket_Duktape.c microscri
SOURCES += microscript/ILibDuktape_http.c microscript/ILibDuktape_net.c microscript/ILibDuktape_ReadableStream.c microscript/ILibDuktape_WritableStream.c
SOURCES += microscript/ILibDuktapeModSearch.c microscript/ILibParsers_Duktape.c microscript/ILibWebClient_Duktape.c microscript/ILibDuktape_WebRTC.c
SOURCES += microscript/ILibWebServer_Duktape.c microscript/ILibDuktape_SimpleDataStore.c microscript/ILibDuktape_GenericMarshal.c
SOURCES += microscript/ILibDuktape_ProcessPipe.c microscript/ILibDuktape_fs.c microscript/ILibDuktape_SHA256.c microscript/ILibduktape_EventEmitter.c
SOURCES += microscript/ILibDuktape_fs.c microscript/ILibDuktape_SHA256.c microscript/ILibduktape_EventEmitter.c
SOURCES += microscript/ILibDuktape_EncryptionStream.c microscript/ILibDuktape_Polyfills.c microscript/ILibDuktape_Dgram.c
SOURCES += microscript/ILibDuktape_ScriptContainer.c microscript/ILibDuktape_MemoryStream.c microscript/ILibDuktape_NetworkMonitor.c
SOURCES += microscript/ILibDuktape_ChildProcess.c
SOURCES += microscript/ILibDuktape_ChildProcess.c microscript/ILibDuktape_HECI.c microscript/ILibDuktape_HttpStream.c
# Mesh Agent core
SOURCES += meshcore/agentcore.c meshconsole/main.c meshcore/meshinfo.c
@@ -192,8 +192,8 @@ ifneq ($(WatchDog),)
CWATCHDOG := -DILibChain_WATCHDOG_TIMEOUT=$(WatchDog)
endif
ifeq ($(NOSSL),1)
SOURCES += microstack/SHA256.c
ifeq ($(NOTLS),1)
SOURCES += microstack/sha384-512.c microstack/sha224-256.c
CFLAGS += -DMICROSTACK_NOTLS
LINUXSSL =
else
@@ -264,18 +264,18 @@ $(LIBNAME): $(OBJECTS) $(SOURCES)
# Compile on Raspberry Pi 2/3 with KVM
pi:
$(MAKE) EXENAME="meshagent_pi2" CFLAGS="-std=gnu99 -g -Wall -D_POSIX -DMICROSTACK_PROXY -D_LINKVM $(CWEBLOG) $(CWATCHDOG) -fno-strict-aliasing $(INCDIRS) -DMESH_AGENTID=25 -D_NOFSWATCHER -D_NOHECI" LDFLAGS="-Lopenssl/libstatic/linux/pi2 $(LDFLAGS) $(LDEXTRA)"
strip meshagent_pi2
$(MAKE) EXENAME="meshagent_pi" CFLAGS="-std=gnu99 -g -Wall -D_POSIX -DMICROSTACK_PROXY -D_LINKVM $(CWEBLOG) $(CWATCHDOG) -fno-strict-aliasing $(INCDIRS) -DMESH_AGENTID=25 -D_NOFSWATCHER -D_NOHECI" LDFLAGS="-Lopenssl/libstatic/linux/pi $(LDFLAGS) $(LDEXTRA)"
strip meshagent_pi
linux:
$(MAKE) EXENAME="$(EXENAME)_$(ARCHNAME)$(EXENAME2)" CFLAGS="-DMESH_AGENTID=$(ARCHID) $(CFLAGS) $(CEXTRA)" LDFLAGS="$(LINUXSSL) $(LDFLAGS) $(LDEXTRA)"
$(STRIP)
linux-nossl-64-library:
$(MAKE) LIBNAME="$(EXENAME)_x64.so" ADDITIONALSOURCES="$(KVMSOURCES)" CFLAGS="-Os -fPIC -DMICROSTACK_NOTLS $(CFLAGS) $(CEXTRA)" LDFLAGS="-shared $(LDFLAGS) $(LDEXTRA)"
#linux-nossl-64-library:
# $(MAKE) LIBNAME="$(EXENAME)_x64.so" ADDITIONALSOURCES="$(KVMSOURCES)" CFLAGS="-Os -fPIC -DMICROSTACK_NOTLS $(CFLAGS) $(CEXTRA)" LDFLAGS="-shared $(LDFLAGS) $(LDEXTRA)"
linux-64-library-debug:
$(MAKE) LIBNAME="$(EXENAME)_x64.so" ADDITIONALSOURCES="$(KVMSOURCES)" CFLAGS="-fPIC -D_DEBUG -DMICROSTACK_TLS_DETECT $(CFLAGS) $(CEXTRA)" LDFLAGS="-shared -L../../opentools/MeshManageability/openssl-static/x86-64 -lssl $(LDFLAGS) $(LDEXTRA)"
#linux-64-library-debug:
# $(MAKE) LIBNAME="$(EXENAME)_x64.so" ADDITIONALSOURCES="$(KVMSOURCES)" CFLAGS="-fPIC -D_DEBUG -DMICROSTACK_TLS_DETECT $(CFLAGS) $(CEXTRA)" LDFLAGS="-shared -L../../opentools/MeshManageability/openssl-static/x86-64 -lssl $(LDFLAGS) $(LDEXTRA)"
#mac-nossl-64:
# $(MAKE) $(MAKEFILE) EXENAME="$(EXENAME)_osx64" CFLAGS="-arch x86_64 -mmacosx-version-min=10.5 -framework IOKit -framework ApplicationServices -framework SystemConfiguration -framework CoreFoundation -fconstant-cfstrings -std=gnu99 -Os -Wall -D_AGENTID=16 -D_POSIX -D_NOHECI -D_DAEMON -DMICROSTACK_PROXY -DMICROSTACK_NOTLS -D__APPLE__ $(CWEBLOG) -fno-strict-aliasing $(INCDIRS)" LDFLAGS="-L. -lpthread -ldl -lz -lutil"

View File

@@ -24,12 +24,7 @@
<ClCompile Include="..\meshcore\KVM\Windows\kvm.c" />
<ClCompile Include="..\meshcore\KVM\Windows\tile.cpp" />
<ClCompile Include="..\meshcore\meshinfo.c" />
<ClCompile Include="..\microlms\heci\HECIWin.c" />
<ClCompile Include="..\microlms\heci\LMEConnection.c" />
<ClCompile Include="..\microlms\heci\PTHICommand.c" />
<ClCompile Include="..\microlms\lms\ILibLMS.c" />
<ClCompile Include="..\microscript\duktape.c" />
<ClCompile Include="..\microscript\ILibAsyncSocket_Duktape.c" />
<ClCompile Include="..\microscript\ILibDuktapeModSearch.c" />
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c" />
<ClCompile Include="..\microscript\ILibDuktape_Debugger.c" />
@@ -39,13 +34,14 @@
<ClCompile Include="..\microscript\ILibduktape_EventEmitter.c" />
<ClCompile Include="..\microscript\ILibDuktape_fs.c" />
<ClCompile Include="..\microscript\ILibDuktape_GenericMarshal.c" />
<ClCompile Include="..\microscript\ILibDuktape_HECI.c" />
<ClCompile Include="..\microscript\ILibDuktape_Helpers.c" />
<ClCompile Include="..\microscript\ILibDuktape_http.c" />
<ClCompile Include="..\microscript\ILibDuktape_HttpStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_MemoryStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_net.c" />
<ClCompile Include="..\microscript\ILibDuktape_NetworkMonitor.c" />
<ClCompile Include="..\microscript\ILibDuktape_Polyfills.c" />
<ClCompile Include="..\microscript\ILibDuktape_ProcessPipe.c" />
<ClCompile Include="..\microscript\ILibDuktape_ReadableStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_ScriptContainer.c" />
<ClCompile Include="..\microscript\ILibDuktape_SHA256.c" />
@@ -78,19 +74,8 @@
<ClInclude Include="..\meshcore\KVM\Windows\tile.h" />
<ClInclude Include="..\meshcore\meshdefines.h" />
<ClInclude Include="..\meshcore\meshinfo.h" />
<ClInclude Include="..\microlms\heci\HECIWin.h" />
<ClInclude Include="..\microlms\heci\HECI_if.h" />
<ClInclude Include="..\microlms\heci\LMEConnection.h" />
<ClInclude Include="..\microlms\heci\LMS_if.h" />
<ClInclude Include="..\microlms\heci\LMS_if_constants.h" />
<ClInclude Include="..\microlms\heci\mei.h" />
<ClInclude Include="..\microlms\heci\PTHICommand.h" />
<ClInclude Include="..\microlms\heci\StatusCodeDefinitions.h" />
<ClInclude Include="..\microlms\lms\ILibLMS-WebSite.h" />
<ClInclude Include="..\microlms\lms\ILibLMS.h" />
<ClInclude Include="..\microscript\duktape.h" />
<ClInclude Include="..\microscript\duk_config.h" />
<ClInclude Include="..\microscript\ILibAsyncSocket_Duktape.h" />
<ClInclude Include="..\microscript\ILibDuktapeModSearch.h" />
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h" />
<ClInclude Include="..\microscript\ILibDuktape_Debugger.h" />
@@ -100,12 +85,12 @@
<ClInclude Include="..\microscript\ILibDuktape_EventEmitter.h" />
<ClInclude Include="..\microscript\ILibDuktape_fs.h" />
<ClInclude Include="..\microscript\ILibDuktape_GenericMarshal.h" />
<ClInclude Include="..\microscript\ILibDuktape_HECI.h" />
<ClInclude Include="..\microscript\ILibDuktape_Helpers.h" />
<ClInclude Include="..\microscript\ILibDuktape_http.h" />
<ClInclude Include="..\microscript\ILibDuktape_net.h" />
<ClInclude Include="..\microscript\ILibDuktape_NetworkMonitor.h" />
<ClInclude Include="..\microscript\ILibDuktape_Polyfills.h" />
<ClInclude Include="..\microscript\ILibDuktape_ProcessPipe.h" />
<ClInclude Include="..\microscript\ILibDuktape_ReadableStream.h" />
<ClInclude Include="..\microscript\ILibDuktape_ScriptContainer.h" />
<ClInclude Include="..\microscript\ILibDuktape_SHA256.h" />

View File

@@ -13,9 +13,6 @@
<Filter Include="Meshcore\KVM">
<UniqueIdentifier>{ab71a2fa-eafc-44d7-9c35-62f7d60fee6a}</UniqueIdentifier>
</Filter>
<Filter Include="MicroLMS">
<UniqueIdentifier>{aeb98903-4a96-453a-8c67-7a824d947bcc}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\microscript\duk_config.h">
@@ -24,9 +21,6 @@
<ClInclude Include="..\microscript\duktape.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibAsyncSocket_Duktape.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_Debugger.h">
<Filter>Microscript</Filter>
</ClInclude>
@@ -105,9 +99,6 @@
<ClInclude Include="..\meshcore\meshdefines.h">
<Filter>Meshcore</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_ProcessPipe.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_fs.h">
<Filter>Microscript</Filter>
</ClInclude>
@@ -141,36 +132,6 @@
<ClInclude Include="..\microscript\ILibDuktape_WebRTC.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microlms\lms\ILibLMS.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\lms\ILibLMS-WebSite.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\HECI_if.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\HECIWin.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\LMEConnection.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\LMS_if.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\LMS_if_constants.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\mei.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\PTHICommand.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\StatusCodeDefinitions.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microstack\ILibMulticastSocket.h">
<Filter>Microstack</Filter>
</ClInclude>
@@ -190,14 +151,14 @@
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_HECI.h">
<Filter>Microscript</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\microscript\duktape.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibAsyncSocket_Duktape.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_Debugger.c">
<Filter>Microscript</Filter>
</ClCompile>
@@ -274,9 +235,6 @@
<Filter>Meshcore</Filter>
</ClCompile>
<ClCompile Include="main.c" />
<ClCompile Include="..\microscript\ILibDuktape_ProcessPipe.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_fs.c">
<Filter>Microscript</Filter>
</ClCompile>
@@ -310,18 +268,6 @@
<ClCompile Include="..\microscript\ILibDuktape_WebRTC.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microlms\lms\ILibLMS.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microlms\heci\HECIWin.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microlms\heci\LMEConnection.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microlms\heci\PTHICommand.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microstack\ILibMulticastSocket.c">
<Filter>Microstack</Filter>
</ClCompile>
@@ -343,6 +289,12 @@
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_HECI.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_HttpStream.c">
<Filter>Microscript</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="MeshConsole.rc" />

View File

@@ -75,7 +75,7 @@ int main(int argc, char **argv)
if (argc > 2 && memcmp(argv[1], "-faddr", 6) == 0)
{
uint64_t addrOffset;
util_hexToBuf(argv[2] + 2, strnlen_s(argv[2], 130) - 2, (char*)&addrOffset);
util_hexToBuf(argv[2] + 2, (int)(strnlen_s(argv[2], 130) - 2), (char*)&addrOffset);
ILibChain_DebugOffset(ILibScratchPad, sizeof(ILibScratchPad), addrOffset);
printf("%s", ILibScratchPad);
return(0);

View File

@@ -257,35 +257,36 @@ void kvm_send_display_list(ILibKVM_WriteHandler writeHandler, void *reserved)
// Not looked at the number of screens yet
if (SCREEN_COUNT == -1) return;
char *buffer = ILibMemory_AllocateA((5 + SCREEN_COUNT) * 2);
memset(buffer, 0xFF, ILibMemory_AllocateA_Size(buffer));
// Send the list of possible displays to remote
if (SCREEN_COUNT == 0 || SCREEN_COUNT == 1)
{
// Only one display, send empty
((unsigned short*)ILibScratchPad2)[0] = (unsigned short)htons((unsigned short)MNG_KVM_GET_DISPLAYS); // Write the type
((unsigned short*)ILibScratchPad2)[1] = (unsigned short)htons((unsigned short)(10 + (2 * SCREEN_COUNT))); // Write the size
((unsigned short*)ILibScratchPad2)[2] = (unsigned short)htons((unsigned short)(0)); // Screen Count
((unsigned short*)ILibScratchPad2)[2] = (unsigned short)htons((unsigned short)(0)); // Selected Screen
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_GET_DISPLAYS); // Write the type
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)(8)); // Write the size
((unsigned short*)buffer)[2] = (unsigned short)htons((unsigned short)(0)); // Screen Count
((unsigned short*)buffer)[3] = (unsigned short)htons((unsigned short)(0)); // Selected Screen
writeHandler(ILibScratchPad2, (10 + (2 * SCREEN_COUNT)), reserved);
writeHandler(buffer, 8, reserved);
}
else
{
// Many displays
((unsigned short*)ILibScratchPad2)[0] = (unsigned short)htons((unsigned short)MNG_KVM_GET_DISPLAYS); // Write the type
((unsigned short*)ILibScratchPad2)[1] = (unsigned short)htons((unsigned short)(10 + (2 * SCREEN_COUNT))); // Write the size
((unsigned short*)ILibScratchPad2)[2] = (unsigned short)htons((unsigned short)(SCREEN_COUNT + 1)); // Screen Count
((unsigned short*)ILibScratchPad2)[3] = (unsigned short)htons((unsigned short)(-1)); // Possible Screen (ALL)
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_GET_DISPLAYS); // Write the type
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)(10 + (2 * SCREEN_COUNT))); // Write the size
((unsigned short*)buffer)[2] = (unsigned short)htons((unsigned short)(SCREEN_COUNT + 1)); // Screen Count
((unsigned short*)buffer)[3] = (unsigned short)htons((unsigned short)(-1)); // Possible Screen (ALL)
for (i = 0; i < SCREEN_COUNT; i++) {
((unsigned short*)ILibScratchPad2)[4 + i] = (unsigned short)htons((unsigned short)(i + 1)); // Possible Screen
((unsigned short*)buffer)[4 + i] = (unsigned short)htons((unsigned short)(i + 1)); // Possible Screen
}
if (SCREEN_SEL == 0) {
((unsigned short*)ILibScratchPad2)[4 + i] = (unsigned short)htons((unsigned short)(-1)); // Selected Screen (All)
((unsigned short*)buffer)[4 + i] = (unsigned short)htons((unsigned short)(-1)); // Selected Screen (All)
} else {
((unsigned short*)ILibScratchPad2)[4 + i] = (unsigned short)htons((unsigned short)(SCREEN_SEL)); // Selected Screen
((unsigned short*)buffer)[4 + i] = (unsigned short)htons((unsigned short)(SCREEN_SEL)); // Selected Screen
}
writeHandler(ILibScratchPad2, (10 + (2 * SCREEN_COUNT)), reserved);
writeHandler(buffer, (10 + (2 * SCREEN_COUNT)), reserved);
}
}
@@ -378,6 +379,7 @@ void CheckDesktopSwitch(int checkres, ILibKVM_WriteHandler writeHandler, void *r
if (SCREEN_X != x || SCREEN_Y != y || SCREEN_WIDTH != w || SCREEN_HEIGHT != h || SCALING_FACTOR != SCALING_FACTOR_NEW)
{
printf("RESOLUTION CHANGED! (supposedly)\n");
SCREEN_X = x;
SCREEN_Y = y;
SCREEN_WIDTH = w;
@@ -617,6 +619,32 @@ int kvm_server_inputdata(char* block, int blocklen, ILibKVM_WriteHandler writeHa
return size;
}
typedef struct kvm_data_handler
{
ILibKVM_WriteHandler handler;
void *reserved;
int len;
char buffer[];
}kvm_data_handler;
//void __stdcall kvm_relay_feeddata_ex_APC(ULONG_PTR data)
//{
// kvm_data_handler *k = (kvm_data_handler*)data;
//
// k->handler(k->buffer, k->len, k->reserved);
// free((void*)data);
//}
//ILibTransport_DoneState kvm_relay_feeddata_ex(char *buf, int len, void *reserved)
//{
// kvm_data_handler *data = (kvm_data_handler*)ILibMemory_Allocate(sizeof(kvm_data_handler) + len, 0, NULL, NULL);
// data->handler = (ILibKVM_WriteHandler)((void**)reserved)[0];
// data->reserved = ((void**)reserved)[1];
// data->len = len;
// memcpy_s(data->buffer, len, buf, len);
//
// QueueUserAPC((PAPCFUNC)kvm_relay_feeddata_ex_APC, kvmthread, (ULONG_PTR)data);
//}
// Feed network data into the KVM. Return the number of bytes consumed.
// This method consumes as many input commands as it can.
int kvm_relay_feeddata(char* buf, int len, ILibKVM_WriteHandler writeHandler, void *reserved)
@@ -633,6 +661,7 @@ int kvm_relay_feeddata(char* buf, int len, ILibKVM_WriteHandler writeHandler, vo
#else
int len2 = 0;
int ptr = 0;
//while ((len2 = kvm_server_inputdata(buf + ptr, len - ptr, kvm_relay_feeddata_ex, (void*[]) {writeHandler, reserved})) != 0) { ptr += len2; }
while ((len2 = kvm_server_inputdata(buf + ptr, len - ptr, writeHandler, reserved)) != 0) { ptr += len2; }
return ptr;
#endif
@@ -889,7 +918,7 @@ DWORD WINAPI kvm_server_mainloop(LPVOID parm)
// We can't go full speed here, we need to slow this down.
height = FRAME_RATE_TIMER;
while (!g_shutdown && height > 0) { if (height > 50) { height -= 50; Sleep(50); } else { Sleep(height); height = 0; } }
while (!g_shutdown && height > 0) { if (height > 50) { height -= 50; Sleep(50); } else { Sleep(height); height = 0; } SleepEx(0, TRUE); }
}
KVMDEBUG("kvm_server_mainloop / end3", (int)GetCurrentThreadId());

View File

@@ -41,11 +41,6 @@ limitations under the License.
#include "microscript/ILibDuktape_ScriptContainer.h"
#include "../microstack/ILibIPAddressMonitor.h"
#ifndef _NOHECI
#include "microlms/lms/ILibLMS.h"
#endif
#ifdef _POSIX
#include <sys/stat.h>
#endif
@@ -114,13 +109,13 @@ typedef struct ScriptContainerSettings
typedef struct MeshCommand_BinaryPacket_ServerId
{
unsigned short command;
char serverId[UTIL_HASHSIZE];
char serverId[UTIL_SHA384_HASHSIZE];
}MeshCommand_BinaryPacket_ServerId;
typedef struct MeshCommand_BinaryPacket_AuthRequest
{
unsigned short command;
char serverHash[UTIL_HASHSIZE];
char serverNonce[UTIL_HASHSIZE];
char serverHash[UTIL_SHA384_HASHSIZE];
char serverNonce[UTIL_SHA384_HASHSIZE];
}MeshCommand_BinaryPacket_AuthRequest;
typedef struct MeshCommand_BinaryPacket_AuthVerify_Header
{
@@ -159,7 +154,7 @@ typedef struct MeshCommand_BinaryPacket_AuthInfo
unsigned int agentId;
unsigned int agentVersion;
unsigned int platformType;
char MeshID[UTIL_HASHSIZE];
char MeshID[UTIL_SHA384_HASHSIZE];
unsigned int capabilities;
unsigned short hostnameLen;
char hostname[];
@@ -168,7 +163,7 @@ typedef struct MeshCommand_BinaryPacket_CoreModule
{
unsigned short command;
unsigned short request;
char coreModuleHash[UTIL_HASHSIZE];
char coreModuleHash[UTIL_SHA384_HASHSIZE];
char coreModule[];
}MeshCommand_BinaryPacket_CoreModule;
#pragma pack(pop)
@@ -735,16 +730,20 @@ void ILibDuktape_MeshAgent_RemoteDesktop_EndSink(ILibDuktape_DuplexStream *strea
{
// Peer disconnected the data channel
RemoteDesktop_Ptrs *ptrs = (RemoteDesktop_Ptrs*)user;
if (ptrs->ctx != NULL)
{
duk_push_heapptr(ptrs->ctx, ptrs->MeshAgentObject); // [MeshAgent]
duk_del_prop_string(ptrs->ctx, -1, REMOTE_DESKTOP_STREAM);
duk_pop(ptrs->ctx); // ...
memset(ptrs, 0, sizeof(RemoteDesktop_Ptrs));
}
kvm_cleanup();
}
void ILibDuktape_MeshAgent_RemoteDesktop_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
//printf("KVM/PAUSE\n");
#ifdef _POSIX
ILibProcessPipe_Pipe_Pause(((RemoteDesktop_Ptrs*)user)->kvmPipe);
#else
@@ -753,6 +752,8 @@ void ILibDuktape_MeshAgent_RemoteDesktop_PauseSink(ILibDuktape_DuplexStream *sen
}
void ILibDuktape_MeshAgent_RemoteDesktop_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
//printf("KVM/RESUME\n");
#ifdef _POSIX
ILibProcessPipe_Pipe_Resume(((RemoteDesktop_Ptrs*)user)->kvmPipe);
#else
@@ -777,7 +778,7 @@ duk_ret_t ILibDuktape_MeshAgent_RemoteDesktop_Finalizer(duk_context *ctx)
}
return 0;
}
void ILibDuktape_MeshAgent_RemoteDesktop_PipeHook(ILibDuktape_readableStream *stream, void *user)
void ILibDuktape_MeshAgent_RemoteDesktop_PipeHook(ILibDuktape_readableStream *stream, void *wstream, void *user)
{
#ifdef _LINKVM
#ifdef WIN32
@@ -793,6 +794,11 @@ void ILibDuktape_MeshAgent_RemoteDesktop_PipeHook(ILibDuktape_readableStream *st
}
#endif
int ILibDuktape_MeshAgent_remoteDesktop_unshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
return(0);
}
duk_ret_t ILibDuktape_MeshAgent_getRemoteDesktop(duk_context *ctx)
{
#ifndef _LINKVM
@@ -816,6 +822,7 @@ duk_ret_t ILibDuktape_MeshAgent_getRemoteDesktop(duk_context *ctx)
duk_pop(ctx);
duk_push_object(ctx); // [MeshAgent][RemoteDesktop]
ILibDuktape_WriteID(ctx, "MeshAgent.kvmSession");
duk_dup(ctx, -1); // [MeshAgent][RemoteDesktop][RemoteDesktop]
duk_put_prop_string(ctx, -3, REMOTE_DESKTOP_STREAM); // [MeshAgent][RemoteDesktop]
duk_push_fixed_buffer(ctx, sizeof(RemoteDesktop_Ptrs)); // [MeshAgent][RemoteDesktop][buffer]
@@ -825,7 +832,7 @@ duk_ret_t ILibDuktape_MeshAgent_getRemoteDesktop(duk_context *ctx)
ptrs->MeshAgentObject = duk_get_heapptr(ctx, -2);
ptrs->ctx = ctx;
ptrs->object = duk_get_heapptr(ctx, -1);
ptrs->stream = ILibDuktape_DuplexStream_Init(ctx, ILibDuktape_MeshAgent_RemoteDesktop_WriteSink, ILibDuktape_MeshAgent_RemoteDesktop_EndSink, ILibDuktape_MeshAgent_RemoteDesktop_PauseSink, ILibDuktape_MeshAgent_RemoteDesktop_ResumeSink, ptrs);
ptrs->stream = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_MeshAgent_RemoteDesktop_WriteSink, ILibDuktape_MeshAgent_RemoteDesktop_EndSink, ILibDuktape_MeshAgent_RemoteDesktop_PauseSink, ILibDuktape_MeshAgent_RemoteDesktop_ResumeSink, ILibDuktape_MeshAgent_remoteDesktop_unshiftSink, ptrs);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_MeshAgent_RemoteDesktop_Finalizer);
ptrs->stream->readableStream->PipeHookHandler = ILibDuktape_MeshAgent_RemoteDesktop_PipeHook;
@@ -868,24 +875,7 @@ duk_ret_t ILibDuktape_MeshAgent_ConnectedServer(duk_context *ctx)
}
return 1;
}
#ifndef _NOHECI
duk_ret_t ILibDuktape_MeshAgent_MEInfo(duk_context *ctx)
{
char *data;
int len = ILibLMS_GetMeInformation(&data, 0);
if (len > 0)
{
duk_push_lstring(ctx, data, len);
duk_json_decode(ctx, -1);
free(data);
}
else
{
duk_push_null(ctx);
}
return 1;
}
#endif
duk_ret_t ILibDuktape_MeshAgent_NetInfo(duk_context *ctx)
{
char *data;
@@ -931,7 +921,24 @@ duk_ret_t ILibDuktape_MeshAgent_ServerUrl(duk_context *ctx)
duk_push_string(ctx, agent->serveruri); // [MeshAgent][ptr][uri]
return(1);
}
duk_ret_t ILibDuktape_MeshAgent_isControlChannelConnected(duk_context *ctx)
{
duk_push_this(ctx); // [agent]
duk_get_prop_string(ctx, -1, MESH_AGENT_PTR); // [agent][ptr]
MeshAgentHostContainer *agent = (MeshAgentHostContainer*)duk_get_pointer(ctx, -1);
duk_push_boolean(ctx, agent->serverAuthState == 3 ? 1 : 0);
return(1);
}
duk_ret_t ILibDuktape_MeshAgent_eval(duk_context *ctx)
{
duk_size_t evalStrLen;
char *evalStr = duk_get_lstring(ctx, 0, &evalStrLen);
printf("eval(): %s\n", evalStr);
duk_eval_string(ctx, evalStr);
return(1);
}
void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
{
MeshAgentHostContainer *agent;
@@ -985,6 +992,7 @@ void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
ILibDuktape_EventEmitter_CreateEvent(emitter, "Ready", &(ptrs->OnReady));
ILibDuktape_EventEmitter_CreateEvent(emitter, "Connected", &(ptrs->OnConnect));
ILibDuktape_CreateEventWithGetter(ctx, "isControlChannelConnected", ILibDuktape_MeshAgent_isControlChannelConnected);
ILibDuktape_EventEmitter_AddHook(emitter, "Ready", ILibDuktape_MeshAgent_Ready);
ILibDuktape_CreateEventWithGetter(ctx, "ConnectedServer", ILibDuktape_MeshAgent_ConnectedServer);
ILibDuktape_CreateEventWithGetter(ctx, "ServerUrl", ILibDuktape_MeshAgent_ServerUrl);
@@ -1001,15 +1009,9 @@ void ILibDuktape_MeshAgent_PUSH(duk_context *ctx, void *chain)
ILibDuktape_CreateReadonlyProperty_int(ctx, "hasKVM", 0);
#endif
#ifdef _NOHECI
ILibDuktape_CreateReadonlyProperty_int(ctx, "hasHECI", 0);
#else
ILibDuktape_CreateReadonlyProperty_int(ctx, "hasHECI", 1);
ILibDuktape_CreateEventWithGetter(ctx, "MEInfo", ILibDuktape_MeshAgent_MEInfo);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "lmsNotification");
#endif
ILibDuktape_CreateEventWithGetter(ctx, "NetInfo", ILibDuktape_MeshAgent_NetInfo);
ILibDuktape_CreateInstanceMethod(ctx, "ExecPowerState", ILibDuktape_MeshAgent_ExecPowerState, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "eval", ILibDuktape_MeshAgent_eval, 1);
Duktape_CreateEnum(ctx, "ContainerPermissions", (char*[]) { "DEFAULT", "NO_AGENT", "NO_MARSHAL", "NO_PROCESS_SPAWNING", "NO_FILE_SYSTEM_ACCESS", "NO_NETWORK_ACCESS" }, (int[]) { 0x00, 0x10000000, 0x08000000, 0x04000000, 0x00000001, 0x00000002 }, 6);
}
@@ -1265,6 +1267,10 @@ duk_context* ScriptEngine_Stop(MeshAgentHostContainer *agent, char *contextGUID)
duk_destroy_heap(oldCtx);
agent->meshCoreCtx = newCtx;
if (agent->proxyServer != NULL)
{
memcpy_s(&(ILibDuktape_GetNewGlobalTunnel(agent->meshCoreCtx)->proxyServer), sizeof(struct sockaddr_in6), agent->proxyServer, sizeof(struct sockaddr_in6));
}
return(newCtx);
}
@@ -1378,15 +1384,15 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
SHA384_Init(&c);
util_keyhash2(peer, ILibScratchPad);
SHA384_Update(&c, AuthRequest->serverHash, sizeof(AuthRequest->serverHash)); // Server web hash
SHA384_Update(&c, agent->serverNonce, UTIL_HASHSIZE); // Server nonce
SHA384_Update(&c, agent->agentNonce, UTIL_HASHSIZE); // Agent nonce
SHA384_Update(&c, agent->serverNonce, UTIL_SHA384_HASHSIZE); // Server nonce
SHA384_Update(&c, agent->agentNonce, UTIL_SHA384_HASHSIZE); // Agent nonce
SHA384_Final((unsigned char*)ILibScratchPad, &c);
// Place the signature & send
evp_prikey = agent->selfcert.pkey;
rsa_prikey = EVP_PKEY_get1_RSA(evp_prikey);
signLen = sizeof(ILibScratchPad2) - sizeof(MeshCommand_BinaryPacket_AuthVerify_Header) - rav->certLen;
if (RSA_sign(NID_sha384, (unsigned char*)ILibScratchPad, UTIL_HASHSIZE, (unsigned char*)(rav->data + rav->certLen), (unsigned int*)&signLen, rsa_prikey) == 1)
if (RSA_sign(NID_sha384, (unsigned char*)ILibScratchPad, UTIL_SHA384_HASHSIZE, (unsigned char*)(rav->data + rav->certLen), (unsigned int*)&signLen, rsa_prikey) == 1)
{
// Signature succesful, send the result to the server
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)rav, sizeof(MeshCommand_BinaryPacket_AuthVerify_Header) + rav->certLen + signLen, ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
@@ -1410,7 +1416,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
if (cmdLen > (int)(sizeof(MeshCommand_BinaryPacket_AuthVerify_Header) + AuthVerify->certLen))
{
int hashlen = UTIL_HASHSIZE;
int hashlen = UTIL_SHA384_HASHSIZE;
SHA512_CTX c;
X509* serverCert = NULL;
EVP_PKEY *evp_pubkey;
@@ -1421,7 +1427,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Check if this certificate public key hash matches what we want
X509_pubkey_digest(serverCert, EVP_sha384(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1, SHA384
if (memcmp(ILibScratchPad, agent->serverHash, UTIL_HASHSIZE) != 0) {
if (memcmp(ILibScratchPad, agent->serverHash, UTIL_SHA384_HASHSIZE) != 0) {
X509_pubkey_digest(serverCert, EVP_sha256(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1, SHA256 (For older .mshx policy file)
if (memcmp(ILibScratchPad, agent->serverHash, 32) != 0) {
printf("Server certificate mismatch\r\n"); break; // TODO: Disconnect
@@ -1431,15 +1437,15 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Compute the authentication hash
SHA384_Init(&c);
util_keyhash2(peer, ILibScratchPad);
SHA384_Update(&c, ILibScratchPad, UTIL_HASHSIZE);
SHA384_Update(&c, agent->agentNonce, UTIL_HASHSIZE);
SHA384_Update(&c, agent->serverNonce, UTIL_HASHSIZE);
SHA384_Update(&c, ILibScratchPad, UTIL_SHA384_HASHSIZE);
SHA384_Update(&c, agent->agentNonce, UTIL_SHA384_HASHSIZE);
SHA384_Update(&c, agent->serverNonce, UTIL_SHA384_HASHSIZE);
SHA384_Final((unsigned char*)ILibScratchPad, &c);
// Verify the hash signature using the server certificate
evp_pubkey = X509_get_pubkey(serverCert);
rsa_pubkey = EVP_PKEY_get1_RSA(evp_pubkey);
if (RSA_verify(NID_sha384, (unsigned char*)ILibScratchPad, UTIL_HASHSIZE, (unsigned char*)AuthVerify->signature, AuthVerify->signatureLen, rsa_pubkey) == 1)
if (RSA_verify(NID_sha384, (unsigned char*)ILibScratchPad, UTIL_SHA384_HASHSIZE, (unsigned char*)AuthVerify->signature, AuthVerify->signatureLen, rsa_pubkey) == 1)
{
int hostnamelen = (int)strnlen_s(agent->hostname, sizeof(agent->hostname));
// Server signature verified, we are good to go.
@@ -1447,7 +1453,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Send to the server information about this agent (TODO: Replace this with a struct)
MeshCommand_BinaryPacket_AuthInfo *info = (MeshCommand_BinaryPacket_AuthInfo*)ILibScratchPad2;
memset(info, 0, sizeof(MeshCommand_BinaryPacket_AuthInfo)); // Required because if hash are SHA256, they will not fully fill the struct.
memset(info, 0, sizeof(MeshCommand_BinaryPacket_AuthInfo)); // Required because if hash are SHA384, they will not fully fill the struct.
info->command = htons(MeshCommand_AuthInfo);
info->infoVersion = htonl(1);
info->agentId = htonl(MESH_AGENTID);
@@ -1558,13 +1564,13 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
if (cmdLen > sizeof(MeshCommand_BinaryPacket_CoreModule)) // Setup a new mesh core.
{
char *hashref = ILibSimpleDataStore_GetHash(agent->masterDb, "CoreModule"); // Get the reference to the SHA256 hash for the currently running code
char *hashref = ILibSimpleDataStore_GetHash(agent->masterDb, "CoreModule"); // Get the reference to the SHA384 hash for the currently running code
if (hashref == NULL || memcmp(hashref, cm->coreModuleHash, sizeof(cm->coreModuleHash)) != 0)
{
// If server sends us the same core, just do nothing.
// Server sent us a new core, start by storing it in the data store
ILibSimpleDataStore_PutEx(agent->masterDb, "CoreModule", 10, cm->coreModule, cmdLen - sizeof(MeshCommand_BinaryPacket_CoreModule)); // Store the JavaScript in the data store
hashref = ILibSimpleDataStore_GetHash(agent->masterDb, "CoreModule"); // Get the reference to the SHA256 hash
hashref = ILibSimpleDataStore_GetHash(agent->masterDb, "CoreModule"); // Get the reference to the SHA384 hash
if (memcmp(hashref, cm->coreModuleHash, sizeof(cm->coreModuleHash)) != 0)
{ // Check the hash for sanity
// Something went wrong, clear the data store
@@ -1577,7 +1583,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Tell the server we are no longer running a core module
MeshCommand_BinaryPacket_CoreModule *rcm = (MeshCommand_BinaryPacket_CoreModule*)ILibScratchPad2;
rcm->command = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA256 hash of the code module
rcm->command = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA384 hash of the code module
rcm->request = htons(requestid); // Request id
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)rcm, 4, ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
break;
@@ -1601,9 +1607,9 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Create the server confirmation message that we are running the new core
MeshCommand_BinaryPacket_CoreModule *rcm = (MeshCommand_BinaryPacket_CoreModule*)ILibScratchPad2;
((unsigned short*)ILibScratchPad2)[0] = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA256 hash of the code module
((unsigned short*)ILibScratchPad2)[0] = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA384 hash of the code module
((unsigned short*)ILibScratchPad2)[1] = htons(requestid); // Request id
memcpy_s(ILibScratchPad2 + 4, sizeof(ILibScratchPad2) - 4, hashref, UTIL_HASHSIZE); // SHA256 hash
memcpy_s(ILibScratchPad2 + 4, sizeof(ILibScratchPad2) - 4, hashref, UTIL_SHA384_HASHSIZE); // SHA384 hash
// Send the confirmation to the server
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)rcm, sizeof(MeshCommand_BinaryPacket_CoreModule), ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
@@ -1620,16 +1626,16 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Confirm to the server that we are not running any core
MeshCommand_BinaryPacket_CoreModule *rcm = (MeshCommand_BinaryPacket_CoreModule*)ILibScratchPad2;
rcm->command = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA256 hash of the code module
rcm->command = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA384 hash of the code module
rcm->request = htons(requestid); // Request id
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)rcm, 4, ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
}
break;
}
case MeshCommand_CoreModuleHash: // Request/return the SHA256 hash of the core module
case MeshCommand_CoreModuleHash: // Request/return the SHA384 hash of the core module
{
// Tell the server what core module we are running
char *hashref = ILibSimpleDataStore_GetHash(agent->masterDb, "CoreModule"); // Get the reference to the SHA256 hash
char *hashref = ILibSimpleDataStore_GetHash(agent->masterDb, "CoreModule"); // Get the reference to the SHA384 hash
int len = 4;
// If the agent is running with a local core, ignore this command
@@ -1637,9 +1643,9 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Confirm to the server what core we are running
MeshCommand_BinaryPacket_CoreModule *rcm = (MeshCommand_BinaryPacket_CoreModule*)ILibScratchPad2;
rcm->command = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA256 hash of the code module
rcm->command = htons(MeshCommand_CoreModuleHash); // MeshCommand_CoreModuleHash (11), SHA384 hash of the code module
rcm->request = htons(requestid); // Request id
if (hashref != NULL) { memcpy_s(rcm->coreModuleHash, sizeof(rcm->coreModuleHash), hashref, UTIL_HASHSIZE); len = sizeof(MeshCommand_BinaryPacket_CoreModule); }
if (hashref != NULL) { memcpy_s(rcm->coreModuleHash, sizeof(rcm->coreModuleHash), hashref, UTIL_SHA384_HASHSIZE); len = sizeof(MeshCommand_BinaryPacket_CoreModule); }
// Send the confirmation to the server
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)rcm, len, ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
@@ -1653,9 +1659,9 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// This is a request for the hash of the agent binary
// Built the response that includes our self hash
MeshCommand_BinaryPacket_CoreModule *rcm = (MeshCommand_BinaryPacket_CoreModule*)ILibScratchPad2;
rcm->command = htons(MeshCommand_AgentHash); // MeshCommand_AgentHash (12), SHA256 hash of the agent executable
rcm->command = htons(MeshCommand_AgentHash); // MeshCommand_AgentHash (12), SHA384 hash of the agent executable
rcm->request = htons(requestid); // Request id
memcpy_s(rcm->coreModuleHash, sizeof(rcm->coreModuleHash), agent->agentHash, UTIL_HASHSIZE);// SHA256 hash of the agent executable
memcpy_s(rcm->coreModuleHash, sizeof(rcm->coreModuleHash), agent->agentHash, UTIL_SHA384_HASHSIZE);// SHA384 hash of the agent executable
// Send the self hash back to the server
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)rcm, sizeof(MeshCommand_BinaryPacket_CoreModule), ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
@@ -1669,7 +1675,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
#else
char* updateFilePath = MeshAgent_MakeAbsolutePath(agent->exePath, ".update");
#endif
char updateFileHash[UTIL_HASHSIZE];
char updateFileHash[UTIL_SHA384_HASHSIZE];
MeshCommand_BinaryPacket_CoreModule *cm = (MeshCommand_BinaryPacket_CoreModule*)cmd;
if (cmdLen == 4) {
@@ -1717,7 +1723,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
}
// Confirm we got a mesh agent update block
((unsigned short*)ILibScratchPad2)[0] = htons(MeshCommand_AgentUpdateBlock); // MeshCommand_AgentHash (14), SHA256 hash of the agent executable
((unsigned short*)ILibScratchPad2)[0] = htons(MeshCommand_AgentUpdateBlock); // MeshCommand_AgentHash (14), SHA384 hash of the agent executable
((unsigned short*)ILibScratchPad2)[1] = htons(requestid); // Request id
ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, ILibScratchPad2, 4, ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
@@ -1740,7 +1746,7 @@ void MeshServer_ControlChannel_PongSink(ILibWebClient_StateObject WebStateObject
{
#ifdef _REMOTELOGGING
MeshAgentHostContainer *agent = (MeshAgentHostContainer*)user;
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost | ILibRemoteLogging_Modules_ConsolePrint, ILibRemoteLogging_Flags_VerbosityLevel_1, "AgentCore/MeshServer_ControlChannel_IdleTimeout(): Received Poing");
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost | ILibRemoteLogging_Modules_ConsolePrint, ILibRemoteLogging_Flags_VerbosityLevel_1, "AgentCore/MeshServer_ControlChannel_IdleTimeout(): Received Pong");
#endif
}
void MeshServer_OnResponse(ILibWebClient_StateObject WebStateObject, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, ILibWebClient_ReceiveStatus recvStatus, void *user1, void *user2, int *PAUSE)
@@ -2010,7 +2016,6 @@ void MeshServer_ConnectEx(MeshAgentHostContainer *agent)
ILibAddHeaderLine(req, "Host", 4, host, (int)strnlen_s(host, serverUrlLen));
free(path);
free(host);
if (meshServer.sin6_family != AF_UNSPEC)
{
@@ -2018,6 +2023,7 @@ void MeshServer_ConnectEx(MeshAgentHostContainer *agent)
reqToken = ILibWebClient_PipelineRequest(agent->httpClientManager, (struct sockaddr*)&meshServer, req, MeshServer_OnResponse, agent, NULL);
#ifndef MICROSTACK_NOTLS
ILibWebClient_Request_SetHTTPS(reqToken, result == ILibParseUriResult_TLS ? ILibWebClient_RequestToken_USE_HTTPS : ILibWebClient_RequestToken_USE_HTTP);
ILibWebClient_Request_SetSNI(reqToken, host, (int)strnlen_s(host, serverUrlLen));
#endif
if ((len = ILibSimpleDataStore_Get(agent->masterDb, "WebProxy", ILibScratchPad, sizeof(ILibScratchPad))) != 0)
{
@@ -2045,6 +2051,7 @@ void MeshServer_ConnectEx(MeshAgentHostContainer *agent)
{
ILibDestructPacket(req);
}
free(host);
}
void MeshServer_Connect(MeshAgentHostContainer *agent)
{
@@ -2214,67 +2221,8 @@ void MeshAgent_RunScriptOnly_Finalizer(duk_context *ctx, void *user)
}
void MeshAgent_CoreModule_UncaughtException(duk_context *ctx, char *msg, void *user)
{
printf("JavaCore UncaughtException: %s\n", msg);
}
#ifndef _NOHECI
void MicroLMS_OnNotificationEx(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
{
struct cimAlertIndication *values = (struct cimAlertIndication*)((void**)user)[0];
char *xml = (char*)((void**)user)[1];
int xmllen = ((int*)((void**)user)[2])[0];
if (Key1 == NULL && ((SCRIPT_ENGINE_ISOLATION*)Data)->reserved != 0)
{
// This is a regular Duktape Context
ILibDuktape_EventEmitter *emitter = MeshAgent_GetEventEmitter_FromCTX((duk_context*)Data);
if (emitter != NULL)
{
duk_push_heapptr(emitter->ctx, emitter->object); // [MeshAgent]
duk_get_prop_string(emitter->ctx, -1, "emit"); // [MeshAgent][emit]
duk_swap_top(emitter->ctx, -2); // [emit][this]
duk_push_string(emitter->ctx, "lmsNotification"); // [emit][this][event]
duk_push_object(emitter->ctx); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, values->MessageID.data, values->MessageID.dataLen); // [emit][this][event][obj][msgId]
duk_put_prop_string(emitter->ctx, -2, "messageId"); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, values->IndicationTime.data, values->IndicationTime.dataLen); // [emit][this][event][obj][time]
duk_put_prop_string(emitter->ctx, -2, "indicationTime"); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, values->MessageArguments.data, values->MessageArguments.dataLen);// [emit][this][event][obj][msg]
duk_put_prop_string(emitter->ctx, -2, "messageArguments"); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, xml, xmllen); // [emit][this][event][obj][rawXML]
duk_put_prop_string(emitter->ctx, -2, "rawXML"); // [emit][this][event][obj]
if (duk_pcall_method(emitter->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(emitter->ctx, "MeshAgent.onLmsNotification(): Error "); }
duk_pop(emitter->ctx); // ...
}
}
}
void MicroLMS_OnNotification(void *module, struct cimAlertIndication *values, char* xml, int xmllen)
{
MeshAgentHostContainer *agent = (MeshAgentHostContainer*)((void**)ILibMemory_GetExtraMemory(module, ILibMemory_ILibLMS_CONTAINERSIZE))[0];
if (agent->meshCoreCtx != NULL)
{
ILibDuktape_EventEmitter *emitter = MeshAgent_GetEventEmitter_FromCTX(agent->meshCoreCtx);
if (emitter != NULL)
{
duk_push_heapptr(emitter->ctx, emitter->object); // [MeshAgent]
duk_get_prop_string(emitter->ctx, -1, "emit"); // [MeshAgent][emit]
duk_swap_top(emitter->ctx, -2); // [emit][this]
duk_push_string(emitter->ctx, "lmsNotification"); // [emit][this][event]
duk_push_object(emitter->ctx); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, values->MessageID.data, values->MessageID.dataLen); // [emit][this][event][obj][msgId]
duk_put_prop_string(emitter->ctx, -2, "messageId"); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, values->IndicationTime.data, values->IndicationTime.dataLen); // [emit][this][event][obj][time]
duk_put_prop_string(emitter->ctx, -2, "indicationTime"); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, values->MessageArguments.data, values->MessageArguments.dataLen);// [emit][this][event][obj][msg]
duk_put_prop_string(emitter->ctx, -2, "messageArguments"); // [emit][this][event][obj]
duk_push_lstring(emitter->ctx, xml, xmllen); // [emit][this][event][obj][rawXML]
duk_put_prop_string(emitter->ctx, -2, "rawXML"); // [emit][this][event][obj]
if (duk_pcall_method(emitter->ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(emitter->ctx, "MeshAgent.onLmsNotification(): Error "); }
duk_pop(emitter->ctx); // ...
}
}
}
#endif
void MeshAgent_AgentMode_IPAddressChanged_Handler(ILibIPAddressMonitor sender, void *user)
{
MeshAgentHostContainer *agentHost = (MeshAgentHostContainer*)user;
@@ -2395,20 +2343,6 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
if (str != NULL) { ILibSimpleDataStore_PutEx(agentHost->masterDb, "WebProxy", 8, str, len); free(str); } else { ILibSimpleDataStore_DeleteEx(agentHost->masterDb, "WebProxy", 8); }
}
#ifndef _NOHECI
#ifdef WIN32
// Check if the LMS service is installed in the service manager
if (GetServiceState(TEXT("LMS")) == 100) {
// If not, setup MicroLMS (Intel AMT interface service) if it's needed
if ((agentHost->microLMS = ILibLMS_CreateEx(agentHost->chain, agentHost->exePath, MicroLMS_OnNotification, sizeof(void*))) != NULL) MSG("MicroLMS activated\r\n");
}
#else
// Setup MicroLMS (Intel AMT interface service) if it's needed
if ((agentHost->microLMS = ILibLMS_CreateEx(agentHost->chain, agentHost->exePath, MicroLMS_OnNotification, sizeof(void*))) != NULL) MSG("MicroLMS activated\r\n");
#endif
if (agentHost->microLMS != NULL) { ((void**)ILibMemory_GetExtraMemory(agentHost->microLMS, ILibMemory_ILibLMS_CONTAINERSIZE))[0] = agentHost; }
#endif
// Check to see if we need to import a settings file
importSettings(agentHost, MeshAgent_MakeAbsolutePath(agentHost->exePath, ".mshx"));
importSettings(agentHost, MeshAgent_MakeAbsolutePath(agentHost->exePath, ".msh"));
@@ -2427,11 +2361,11 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
#endif
{
// Save the NodeId
util_tohex(agentHost->g_selfid, UTIL_HASHSIZE, ILibScratchPad);
util_tohex(agentHost->g_selfid, UTIL_SHA384_HASHSIZE, ILibScratchPad);
RegSetValueExA(hKey, "NodeId", 0, REG_SZ, ILibScratchPad, (int)strlen(ILibScratchPad));
// Save the AgentHash
util_tohex(agentHost->agentHash, UTIL_HASHSIZE, ILibScratchPad);
util_tohex(agentHost->agentHash, UTIL_SHA384_HASHSIZE, ILibScratchPad);
RegSetValueExA(hKey, "AgentHash", 0, REG_SZ, ILibScratchPad, (int)strlen(ILibScratchPad));
// Save a bunch of values in the registry

View File

@@ -17,9 +17,6 @@ limitations under the License.
#ifndef __AGENTCORE__
#define __AGENTCORE__
#ifdef MICROSTACK_NOTLS
#define UTIL_HASHSIZE 32
#endif
typedef char JS_ENGINE_CONTEXT[16];
@@ -49,7 +46,6 @@ typedef char JS_ENGINE_CONTEXT[16];
#include "microscript/ILibDuktapeModSearch.h"
#include "microscript/ILibDuktape_GenericMarshal.h"
#include "microscript/ILibDuktape_SimpleDataStore.h"
#include "microscript/ILibDuktape_ProcessPipe.h"
#include "microscript/ILibDuktape_fs.h"
#include "microstack/ILibProcessPipe.h"
#include "microstack/ILibCrypto.h"
@@ -169,23 +165,25 @@ typedef struct MeshAgentHostContainer
int serverIndex;
int retryTime;
MeshAgentHost_BatteryInfo batteryState;
char meshId[UTIL_HASHSIZE];
char meshId[UTIL_SHA384_HASHSIZE];
int performSelfUpdate;
int disableUpdate;
char agentHash[UTIL_HASHSIZE];
char serverHash[UTIL_HASHSIZE];
char agentHash[UTIL_SHA384_HASHSIZE];
char serverHash[UTIL_SHA384_HASHSIZE];
#ifndef MICROSTACK_NOTLS
struct util_cert selfcert;
struct util_cert selftlscert;
struct util_cert selftlsclientcert;
char serverWebHash[UTIL_HASHSIZE];
char serverNonce[UTIL_HASHSIZE];
char agentNonce[UTIL_HASHSIZE];
int serverAuthState;
char serverWebHash[UTIL_SHA384_HASHSIZE];
#endif
char serverNonce[UTIL_SHA384_HASHSIZE];
char agentNonce[UTIL_SHA384_HASHSIZE];
int serverAuthState;
int controlChannel_idleTimeout_seconds;
char g_selfid[UTIL_HASHSIZE];
char g_selfid[UTIL_SHA384_HASHSIZE];
void* microLMS;
void* multicastDiscovery;
char* multicastServerUrl;

View File

@@ -17,7 +17,6 @@ limitations under the License.
#if !defined(__MeshDefines__)
#define __MeshDefined__
#define UTIL_HASHSIZE 48
#define MESH_AGENT_PORT 16990 //!< Default Mesh Agent Port
#define MESH_AGENT_STUN_PORT 16991 //!< Default Mesh Agent STUN Port
#define MESH_AGENT_VERSION 1 //!< Used for self-update system.

View File

@@ -61,7 +61,7 @@ IDI_ICON1 ICON "MeshService.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,2,0,3
FILEVERSION 0,2,1,3
PRODUCTVERSION 0,0,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
@@ -78,7 +78,7 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "Mesh Agent Service"
VALUE "FileVersion", "0.2.0.3"
VALUE "FileVersion", "0.2.1.3"
VALUE "InternalName", "MeshAgent"
VALUE "LegalCopyright", "Apache 2.0 License"
VALUE "OriginalFilename", "MeshAgent.exe"

View File

@@ -252,12 +252,7 @@
<ClCompile Include="..\meshcore\KVM\Windows\tile.cpp" />
<ClCompile Include="..\meshcore\meshinfo.c" />
<ClCompile Include="..\meshcore\signcheck.c" />
<ClCompile Include="..\microlms\heci\HECIWin.c" />
<ClCompile Include="..\microlms\heci\LMEConnection.c" />
<ClCompile Include="..\microlms\heci\PTHICommand.c" />
<ClCompile Include="..\microlms\lms\ILibLMS.c" />
<ClCompile Include="..\microscript\duktape.c" />
<ClCompile Include="..\microscript\ILibAsyncSocket_Duktape.c" />
<ClCompile Include="..\microscript\ILibDuktapeModSearch.c" />
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c" />
<ClCompile Include="..\microscript\ILibDuktape_Debugger.c" />
@@ -267,13 +262,14 @@
<ClCompile Include="..\microscript\ILibduktape_EventEmitter.c" />
<ClCompile Include="..\microscript\ILibDuktape_fs.c" />
<ClCompile Include="..\microscript\ILibDuktape_GenericMarshal.c" />
<ClCompile Include="..\microscript\ILibDuktape_HECI.c" />
<ClCompile Include="..\microscript\ILibDuktape_Helpers.c" />
<ClCompile Include="..\microscript\ILibDuktape_http.c" />
<ClCompile Include="..\microscript\ILibDuktape_HttpStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_MemoryStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_net.c" />
<ClCompile Include="..\microscript\ILibDuktape_NetworkMonitor.c" />
<ClCompile Include="..\microscript\ILibDuktape_Polyfills.c" />
<ClCompile Include="..\microscript\ILibDuktape_ProcessPipe.c" />
<ClCompile Include="..\microscript\ILibDuktape_ReadableStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_ScriptContainer.c" />
<ClCompile Include="..\microscript\ILibDuktape_SHA256.c" />
@@ -308,19 +304,8 @@
<ClInclude Include="..\meshcore\meshdefines.h" />
<ClInclude Include="..\meshcore\meshinfo.h" />
<ClInclude Include="..\meshcore\signcheck.h" />
<ClInclude Include="..\microlms\heci\HECIWin.h" />
<ClInclude Include="..\microlms\heci\HECI_if.h" />
<ClInclude Include="..\microlms\heci\LMEConnection.h" />
<ClInclude Include="..\microlms\heci\LMS_if.h" />
<ClInclude Include="..\microlms\heci\LMS_if_constants.h" />
<ClInclude Include="..\microlms\heci\mei.h" />
<ClInclude Include="..\microlms\heci\PTHICommand.h" />
<ClInclude Include="..\microlms\heci\StatusCodeDefinitions.h" />
<ClInclude Include="..\microlms\lms\ILibLMS-WebSite.h" />
<ClInclude Include="..\microlms\lms\ILibLMS.h" />
<ClInclude Include="..\microscript\duktape.h" />
<ClInclude Include="..\microscript\duk_config.h" />
<ClInclude Include="..\microscript\ILibAsyncSocket_Duktape.h" />
<ClInclude Include="..\microscript\ILibDuktapeModSearch.h" />
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h" />
<ClInclude Include="..\microscript\ILibDuktape_Debugger.h" />
@@ -330,12 +315,12 @@
<ClInclude Include="..\microscript\ILibDuktape_EventEmitter.h" />
<ClInclude Include="..\microscript\ILibDuktape_fs.h" />
<ClInclude Include="..\microscript\ILibDuktape_GenericMarshal.h" />
<ClInclude Include="..\microscript\ILibDuktape_HECI.h" />
<ClInclude Include="..\microscript\ILibDuktape_Helpers.h" />
<ClInclude Include="..\microscript\ILibDuktape_http.h" />
<ClInclude Include="..\microscript\ILibDuktape_net.h" />
<ClInclude Include="..\microscript\ILibDuktape_NetworkMonitor.h" />
<ClInclude Include="..\microscript\ILibDuktape_Polyfills.h" />
<ClInclude Include="..\microscript\ILibDuktape_ProcessPipe.h" />
<ClInclude Include="..\microscript\ILibDuktape_ReadableStream.h" />
<ClInclude Include="..\microscript\ILibDuktape_ScriptContainer.h" />
<ClInclude Include="..\microscript\ILibDuktape_SHA256.h" />

View File

@@ -17,9 +17,6 @@
<Filter Include="Meshcore\KVM">
<UniqueIdentifier>{074ddd93-a67c-44e2-b7d9-b84549b60522}</UniqueIdentifier>
</Filter>
<Filter Include="MicroLMS">
<UniqueIdentifier>{555848d8-baf6-4cf1-94d6-935c78f6fd48}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="MeshService.rc">
@@ -37,9 +34,6 @@
<ClCompile Include="..\microscript\duktape.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibAsyncSocket_Duktape.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_Debugger.c">
<Filter>Microscript</Filter>
</ClCompile>
@@ -118,9 +112,6 @@
<ClCompile Include="..\meshcore\signcheck.c">
<Filter>Meshcore</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_ProcessPipe.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_fs.c">
<Filter>Microscript</Filter>
</ClCompile>
@@ -151,18 +142,6 @@
<ClCompile Include="..\microscript\ILibDuktape_WebRTC.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microlms\lms\ILibLMS.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microlms\heci\HECIWin.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microlms\heci\LMEConnection.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microlms\heci\PTHICommand.c">
<Filter>MicroLMS</Filter>
</ClCompile>
<ClCompile Include="..\microstack\ILibMulticastSocket.c">
<Filter>Microstack</Filter>
</ClCompile>
@@ -187,6 +166,12 @@
<ClCompile Include="..\microscript\ILibDuktape_ChildProcess.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_HECI.c">
<Filter>Microscript</Filter>
</ClCompile>
<ClCompile Include="..\microscript\ILibDuktape_HttpStream.c">
<Filter>Microscript</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\microscript\duk_config.h">
@@ -195,9 +180,6 @@
<ClInclude Include="..\microscript\duktape.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibAsyncSocket_Duktape.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_Debugger.h">
<Filter>Microscript</Filter>
</ClInclude>
@@ -279,9 +261,6 @@
<ClInclude Include="..\meshcore\signcheck.h">
<Filter>Meshcore</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_ProcessPipe.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_fs.h">
<Filter>Microscript</Filter>
</ClInclude>
@@ -312,36 +291,6 @@
<ClInclude Include="..\microscript\ILibDuktape_WebRTC.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microlms\lms\ILibLMS.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\lms\ILibLMS-WebSite.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\HECI_if.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\HECIWin.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\LMEConnection.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\LMS_if.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\LMS_if_constants.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\mei.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\PTHICommand.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microlms\heci\StatusCodeDefinitions.h">
<Filter>MicroLMS</Filter>
</ClInclude>
<ClInclude Include="..\microstack\ILibMulticastSocket.h">
<Filter>Microstack</Filter>
</ClInclude>
@@ -364,5 +313,8 @@
<ClInclude Include="..\microscript\ILibDuktape_ChildProcess.h">
<Filter>Microscript</Filter>
</ClInclude>
<ClInclude Include="..\microscript\ILibDuktape_HECI.h">
<Filter>Microscript</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -48,9 +48,11 @@ int ClearWindowsFirewall(wchar_t* processname);
#define _CRTDBG_MAP_ALLOC
#endif
TCHAR* serviceFile = TEXT("Mesh Agent v2");
TCHAR* serviceName = TEXT("Mesh Agent v2 background service");
TCHAR* serviceFile = TEXT("Mesh Agent");
TCHAR* serviceFileOld = TEXT("Mesh Agent v2");
TCHAR* serviceName = TEXT("Mesh Agent background service");
TCHAR* serviceDesc = TEXT("Remote monitoring and management service.");
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
INT_PTR CALLBACK DialogHandler(HWND, UINT, WPARAM, LPARAM);
@@ -261,14 +263,14 @@ BOOL InstallService()
return r;
}
int UninstallService()
int UninstallService(TCHAR* serviceName)
{
int r = 0;
SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT);
if (serviceControlManager)
{
SC_HANDLE service = OpenService( serviceControlManager, serviceFile, SERVICE_QUERY_STATUS | DELETE );
SC_HANDLE service = OpenService( serviceControlManager, serviceName, SERVICE_QUERY_STATUS | DELETE );
if (service)
{
SERVICE_STATUS serviceStatusEx;
@@ -457,7 +459,8 @@ void fullinstall(int uninstallonly, char* proxy, int proxylen, char* tag, int ta
// Stop and remove the service
StopService(serviceFile);
UninstallService();
UninstallService(serviceFile);
UninstallService(serviceFileOld);
// Get our own executable
selfexelen = GetModuleFileNameA(NULL, selfexe, _MAX_PATH);
@@ -843,7 +846,8 @@ int main(int argc, char* argv[])
{
// Setup the service
StopService(serviceFile);
UninstallService();
UninstallService(serviceFile);
UninstallService(serviceFileOld);
if (InstallService() == TRUE) { printf("Mesh agent installed"); } else { printf("Failed to install mesh agent"); }
#ifndef _MINCORE
@@ -872,7 +876,8 @@ int main(int argc, char* argv[])
StopService(serviceFile);
// Remove the service
i = UninstallService();
UninstallService(serviceFileOld);
i = UninstallService(serviceFile);
if (i == 0) { printf("Failed to uninstall mesh agent"); }
else if (i == 1) { printf("Mesh agent uninstalled"); }
else if (i == 2) { printf("Mesh agent still running"); }
@@ -1042,6 +1047,7 @@ int main(int argc, char* argv[])
}
else
{
UninstallService(serviceFileOld);
if (argc > 1)
{
// See if we need to run as a script engine

View File

@@ -29,7 +29,7 @@ limitations under the License.
#include <crtdbg.h>
#endif
#define ILibDuktape_ModSearch_ModuleFile "0xFF"
#define ILibDuktape_ModSearch_ModuleFile (void*)0xFF
int ILibDuktape_ModSearch_AddModule(duk_context *ctx, char *id, char *module, int moduleLen)
{

View File

@@ -9,7 +9,6 @@
#include "ILibDuktape_WritableStream.h"
#include "ILibDuktape_EventEmitter.h"
#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
#define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process"
#define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf"
@@ -122,14 +121,23 @@ ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUS
ILibDuktape_CreateInstanceMethod(ctx, "kill", ILibDuktape_ChildProcess_Kill, 0);
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess.stdout");
duk_dup(ctx, -2);
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
retVal->stdOut = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdOut_OnPause, ILibDuktape_ChildProcess_SubProcess_StdOut_OnResume, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stdout");
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess.stderr");
duk_dup(ctx, -2);
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
retVal->stdErr = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdErr_OnPause, ILibDuktape_ChildProcess_SubProcess_StdErr_OnResume, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stderr");
duk_push_object(ctx);
ILibDuktape_WriteID(ctx, "childProcess.stdin");
duk_dup(ctx, -2);
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
retVal->stdIn = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdIn_WriteHandler, ILibDuktape_ChildProcess_SubProcess_StdIn_EndHandler, retVal);
ILibDuktape_CreateReadonlyProperty(ctx, "stdin");
@@ -163,12 +171,13 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
int i, x;
void *callback = NULL;
ILibProcessPipe_Process p = NULL;
ILibProcessPipe_SpawnTypes spawnType = ILibProcessPipe_SpawnTypes_DEFAULT;
for (i = 0; i < nargs; ++i)
{
if (duk_is_array(ctx, i) != 0)
{
int arrLen = duk_get_length(ctx, i);
int arrLen = (int)duk_get_length(ctx, i);
#ifdef WIN32
args = (char**)_alloca((arrLen + 1) * sizeof(char*));
#else
@@ -185,6 +194,11 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
{
callback = duk_get_heapptr(ctx, i);
}
else if (duk_is_object(ctx, i))
{
// Options
spawnType = (ILibProcessPipe_SpawnTypes)Duktape_GetIntPropertyValue(ctx, i, "type", (int)ILibProcessPipe_SpawnTypes_DEFAULT);
}
}
#ifdef WIN32
@@ -206,7 +220,7 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
}
#endif
p = ILibProcessPipe_Manager_SpawnProcess(manager, target, args);
p = ILibProcessPipe_Manager_SpawnProcessEx2(manager, target, args, spawnType, 0);
if (p == NULL)
{
return(ILibDuktape_Error(ctx, "child_process.execFile(): Could not exec [%s]", target));
@@ -222,6 +236,16 @@ void ILibDuktape_ChildProcess_PUSH(duk_context *ctx, void *chain)
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ChildProcess_Manager_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "execFile", ILibDuktape_ChildProcess_execFile, DUK_VARARGS);
duk_push_object(ctx);
duk_push_int(ctx, 0);
duk_put_prop_string(ctx, -2, "DEFAULT");
duk_push_int(ctx, 1);
duk_put_prop_string(ctx, -2, "USER");
duk_push_int(ctx, 2);
duk_put_prop_string(ctx, -2, "WINLOGON");
duk_push_int(ctx, 3);
duk_put_prop_string(ctx, -2, "TERM");
duk_put_prop_string(ctx, -2, "SpawnTypes");
}
void ILibDuktape_ChildProcess_Init(duk_context *ctx)
{

View File

@@ -2,6 +2,7 @@
#define __ILIBDUKTAPE_CHILDPROCESS__
#include "duktape.h"
#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
void ILibDuktape_ChildProcess_Init(duk_context *ctx);

View File

@@ -376,6 +376,29 @@ duk_ret_t ILibDuktape_DGram_setTTL(duk_context *ctx)
{
return ILibDuktape_Error(ctx, "Not implemented");
}
duk_ret_t ILibDuktape_DGram_setMulticastInterface(duk_context *ctx)
{
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
struct sockaddr_in addr;
char *str = (char*)duk_require_string(ctx, 0);
memset(&addr, 0, sizeof(struct sockaddr_in));
ILibInet_pton(AF_INET, str, &(addr.sin_addr));
ILibAsyncUDPSocket_SetMulticastInterface(ptrs->mSocket, (struct sockaddr*)&addr);
return(0);
}
duk_ret_t ILibDuktape_Dgram_socket_close(duk_context *ctx)
{
if (duk_get_top(ctx) > 0 && duk_is_function(ctx, 0)) { ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx), "close", duk_require_heapptr(ctx, 0)); }
duk_push_this(ctx); // [socket]
duk_get_prop_string(ctx, -1, ILibDuktape_DGRAM_SOCKET_NATIVE); // [socket][ptr]
ILibDuktape_DGRAM_DATA *data = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
ILibAsyncSocket_Disconnect(data->mSocket);
return(0);
}
duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
{
ILibDuktape_DGRAM_Config config = ILibDuktape_DGRAM_Config_NONE;
@@ -397,6 +420,7 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
/**************************************************************************************/
duk_push_object(ctx); // [socket]
ILibDuktape_WriteID(ctx, "dgram.socket");
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Dgram_Finalizer);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DGRAM_DATA)); // [socket][native]
ptrs = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
@@ -420,10 +444,13 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "add", "addMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "remove", "dropMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
ILibDuktape_CreateProperty_InstanceMethod(ctx, "close", ILibDuktape_Dgram_socket_close, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "send", ILibDuktape_DGram_send, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "setBroadcast", ILibDuktape_DGram_setBroadcast, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastLoopback", ILibDuktape_DGram_setMulticastLoopback, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastTTL", ILibDuktape_DGram_setMulticastTTL, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastInterface", ILibDuktape_DGram_setMulticastInterface, 1);
ILibDuktape_CreateInstanceMethod(ctx, "setTTL", ILibDuktape_DGram_setTTL, 1);
return 1;

View File

@@ -18,6 +18,7 @@ limitations under the License.
#include "ILibDuktape_Helpers.h"
#include "ILibDuktape_DuplexStream.h"
#define ILibDuktape_Transform_Data "\xFF_Transform_Data"
#ifdef __DOXY__
/*!
@@ -53,7 +54,19 @@ void ILibDuktape_DuplexStream_OnEnd(struct ILibDuktape_WritableStream *stream, v
if (ds->OnEnd != NULL) { ((ILibDuktape_DuplexStream_EndHandler)ds->OnEnd)(ds, ds->user); }
}
ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_Init(duk_context * ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void * user)
int ILibDuktape_DuplexStream_OnUnshift(ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_DuplexStream *ds = (ILibDuktape_DuplexStream*)user;
if (ds->unshiftHandler == NULL)
{
return(0);
}
else
{
return(((ILibDuktape_DuplexStream_UnshiftHandler)ds->unshiftHandler)(ds, unshiftBytes, ds->user));
}
}
ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_InitEx(duk_context * ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, ILibDuktape_DuplexStream_UnshiftHandler UnshiftHandler, void * user)
{
ILibDuktape_DuplexStream *retVal;
@@ -63,12 +76,94 @@ ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_Init(duk_context * ctx, ILib
memset(retVal, 0, sizeof(ILibDuktape_DuplexStream));
retVal->user = user;
retVal->readableStream = ILibDuktape_InitReadableStream(ctx, ILibDuktape_DuplexStream_OnPause, ILibDuktape_DuplexStream_OnResume, retVal);
retVal->readableStream = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_DuplexStream_OnPause, ILibDuktape_DuplexStream_OnResume, UnshiftHandler != NULL ? ILibDuktape_DuplexStream_OnUnshift : NULL, retVal);
retVal->writableStream = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_DuplexStream_OnWrite, ILibDuktape_DuplexStream_OnEnd, retVal);
retVal->OnEnd = EndHandler;
retVal->OnWrite = WriteHandler;
retVal->OnPause = PauseHandler;
retVal->OnResume = ResumeHandler;
retVal->ParentObject = duk_get_heapptr(ctx, -1);
retVal->unshiftHandler = UnshiftHandler;
return retVal;
}
ILibTransport_DoneState ILibDuktape_Transform_WriteSink(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
TF->writerEnded = stream->endBytes;
TF->On_NativeTransform(TF, TF->source->Reserved, stream->endBytes, buffer, bufferLen, TF->user);
return(TF->target->paused == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
}
void ILibDuktape_Transform_EndSink(struct ILibDuktape_WritableStream *stream, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
if (TF->writerEnded == 0)
{
TF->writerEnded = -1;
TF->On_NativeTransform(TF, 0, -1, NULL, 0, TF->user);
}
ILibDuktape_readableStream_WriteEnd(TF->target);
}
void ILibDuktape_Transform_PauseSink(struct ILibDuktape_readableStream *sender, void *user)
{
UNREFERENCED_PARAMETER(sender);
UNREFERENCED_PARAMETER(user);
// NO-OP, because it is handled in the WriteSink
}
void ILibDuktape_Transform_ResumeSink(struct ILibDuktape_readableStream *sender, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
ILibDuktape_WritableStream_Ready(TF->source);
}
void ILibDuktape_Transform_ReaderPipeHook(struct ILibDuktape_readableStream *sender, void *wstream, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
TF->readerIsPiped = 1;
if (TF->On_NativePipedSink != NULL) { TF->On_NativePipedSink(TF, TF->user); }
}
int ILibDuktape_Transform_UnshiftSink(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
return(TF->On_NativeUnshift(TF, unshiftBytes, TF->user));
}
ILibDuktape_Transform* ILibDuktape_Transform_InitEx(duk_context *ctx, ILibDuktape_TransformStream_TransformHandler transformHandler, ILibDuktape_TransformStream_UnShiftHandler unshiftHandler, ILibDuktape_TransformStream_TargetPipedHandler pipedHandler, void *user)
{
ILibDuktape_Transform *TF;
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_Transform)); // [buffer]
TF = (ILibDuktape_Transform*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_Transform_Data); // ...
TF->source = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_Transform_WriteSink, ILibDuktape_Transform_EndSink, TF);
if (unshiftHandler != NULL)
{
TF->target = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_Transform_PauseSink, ILibDuktape_Transform_ResumeSink, ILibDuktape_Transform_UnshiftSink, TF);
}
else
{
TF->target = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_Transform_PauseSink, ILibDuktape_Transform_ResumeSink, TF);
}
TF->target->PipeHookHandler = ILibDuktape_Transform_ReaderPipeHook;
TF->On_NativePipedSink = pipedHandler;
TF->On_NativeTransform = transformHandler;
TF->On_NativeUnshift = unshiftHandler;
TF->user = user;
return(TF);
}
ILibDuktape_WritableStream *ILibDuktape_DuplexStream_GetNativeWritable(duk_context *ctx, void *stream)
{
ILibDuktape_WritableStream *retVal = NULL;
duk_push_heapptr(ctx, stream); // [stream]
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
{
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [stream][ws]
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (retVal->JSCreated) { retVal = NULL; }
duk_pop(ctx); // [stream]
}
duk_pop(ctx); // ...
return(retVal);
}

View File

@@ -28,6 +28,7 @@ typedef struct ILibDuktape_DuplexStream
{
ILibDuktape_readableStream *readableStream;
ILibDuktape_WritableStream *writableStream;
void *unshiftHandler;
void *user;
void *ParentObject;
void *OnWrite;
@@ -36,9 +37,34 @@ typedef struct ILibDuktape_DuplexStream
void *OnResume;
}ILibDuktape_DuplexStream;
struct ILibDuktape_Transform;
typedef void(*ILibDuktape_TransformStream_TransformHandler)(struct ILibDuktape_Transform *sender, int Reserved, int flush, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_TransformStream_TargetPipedHandler)(struct ILibDuktape_Transform *sender, void *user);
typedef int(*ILibDuktape_TransformStream_UnShiftHandler)(struct ILibDuktape_Transform *sender, int unshiftBytes, void *user);
typedef struct ILibDuktape_Transform
{
duk_context *ctx;
ILibDuktape_WritableStream *source;
ILibDuktape_readableStream *target;
int readerIsPiped;
int writerEnded;
ILibDuktape_TransformStream_UnShiftHandler On_NativeUnshift;
ILibDuktape_TransformStream_TransformHandler On_NativeTransform;
ILibDuktape_TransformStream_TargetPipedHandler On_NativePipedSink;
void *user;
}ILibDuktape_Transform;
ILibDuktape_Transform* ILibDuktape_Transform_InitEx(duk_context *ctx, ILibDuktape_TransformStream_TransformHandler transformHandler, ILibDuktape_TransformStream_UnShiftHandler unshiftHandler, ILibDuktape_TransformStream_TargetPipedHandler pipedHandler, void *user);
#define ILibDuktape_Transform_Init(ctx, transformHandler, pipedHandler, user) ILibDuktape_Transform_InitEx(ctx, transformHandler, NULL, pipedHandler, user)
typedef ILibTransport_DoneState(*ILibDuktape_DuplexStream_WriteHandler)(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_DuplexStream_EndHandler)(ILibDuktape_DuplexStream *stream, void *user);
typedef void(*ILibDuktape_DuplexStream_PauseResumeHandler)(ILibDuktape_DuplexStream *sender, void *user);
typedef int(*ILibDuktape_DuplexStream_UnshiftHandler)(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user);
#define ILibDuktape_DuplexStream_Ready(duplexStream) ILibDuktape_WritableStream_Ready((duplexStream)->writableStream)
#define ILibDuktape_DuplexStream_WriteData(duplexStream, buffer, bufferLen) ILibDuktape_readableStream_WriteData((duplexStream)->readableStream, buffer, bufferLen)
@@ -46,7 +72,7 @@ typedef void(*ILibDuktape_DuplexStream_PauseResumeHandler)(ILibDuktape_DuplexStr
#define ILibDuktape_DuplexStream_WriteEnd(duplexStream) ILibDuktape_readableStream_WriteEnd((duplexStream)->readableStream)
#define ILibDuktape_DuplexStream_Closed(duplexStream) ILibDuktape_readableStream_Closed((duplexStream)->readableStream)
ILibDuktape_DuplexStream* ILibDuktape_DuplexStream_Init(duk_context *ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void *user);
ILibDuktape_DuplexStream* ILibDuktape_DuplexStream_InitEx(duk_context *ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, ILibDuktape_DuplexStream_UnshiftHandler UnshiftHandler, void *user);
#define ILibDuktape_DuplexStream_Init(ctx, WriteHandler, EndHandler, PauseHandler, ResumeHandler, user) ILibDuktape_DuplexStream_InitEx(ctx, WriteHandler, EndHandler, PauseHandler, ResumeHandler, NULL, user)
ILibDuktape_WritableStream *ILibDuktape_DuplexStream_GetNativeWritable(duk_context *ctx, void *stream);
#endif

View File

@@ -31,11 +31,13 @@ int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter,
int ILibDuktape_EventEmitter_AddSink(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_Handler handler); // Add Native Event Handler
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler 'once'
int ILibDuktape_EventEmitter_AddOnceEx(ILibDuktape_EventEmitter *emitter, char *eventName, duk_c_function func, duk_idx_t funcArgs);
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs);
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
int ILibDuktape_EventEmitter_AddOnceEx3(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func);
#define ILibDuktape_EventEmitter_AddOnceEx2(ctx, idx, eventName, func, argCount) ILibDuktape_EventEmitter_AddOnceEx3(ctx, idx, eventName, func)
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func);
void ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_HookHandler handler);
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName);
#endif

View File

@@ -41,6 +41,8 @@ limitations under the License.
#include <dlfcn.h>
#endif
#define ILibDuktape_GenericMarshal_VariableType "\xFF_GenericMarshal_VarType"
typedef PTRSIZE(APICALLTYPE *R0)();
typedef PTRSIZE(APICALLTYPE *R1)(PTRSIZE V1);
typedef PTRSIZE(APICALLTYPE *R2)(PTRSIZE V1, PTRSIZE V2);
@@ -52,6 +54,17 @@ typedef PTRSIZE(APICALLTYPE *R7)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4,
typedef PTRSIZE(APICALLTYPE *R8)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8);
typedef PTRSIZE(APICALLTYPE *R9)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9);
typedef PTRSIZE(APICALLTYPE *R10)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10);
typedef PTRSIZE(APICALLTYPE *R11)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11);
typedef PTRSIZE(APICALLTYPE *R12)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12);
typedef PTRSIZE(APICALLTYPE *R13)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13);
typedef PTRSIZE(APICALLTYPE *R14)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14);
typedef PTRSIZE(APICALLTYPE *R15)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15);
typedef PTRSIZE(APICALLTYPE *R16)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16);
typedef PTRSIZE(APICALLTYPE *R17)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17);
typedef PTRSIZE(APICALLTYPE *R18)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18);
typedef PTRSIZE(APICALLTYPE *R19)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18, PTRSIZE V19);
typedef PTRSIZE(APICALLTYPE *R20)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18, PTRSIZE V19, PTRSIZE V20);
typedef struct Duktape_GenericMarshal_Proxy
{
@@ -175,7 +188,6 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_SET(duk_context *ctx)
{
void *ptr;
int size;
int value = duk_require_int(ctx, 0);
duk_push_this(ctx); // [var]
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
@@ -183,19 +195,33 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_SET(duk_context *ctx)
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
size = duk_to_int(ctx, -1);
if (duk_is_number(ctx, 0))
{
switch (size)
{
case 2:
((unsigned short*)ptr)[0] = (unsigned short)value;
((unsigned short*)ptr)[0] = (unsigned short)duk_require_int(ctx, 0);
break;
case 4:
((unsigned int*)ptr)[0] = (unsigned int)value;
((unsigned int*)ptr)[0] = (unsigned int)duk_require_int(ctx, 0);
break;
default:
duk_push_string(ctx, "UNSUPPORTED VAL SIZE");
duk_push_string(ctx, "UNSUPPORTED VAL SIZE, with integral type");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
}
else if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, ILibDuktape_GenericMarshal_VariableType))
{
((void**)ptr)[0] = Duktape_GetPointerProperty(ctx, 0, "_ptr");
duk_push_this(ctx); // [var]
duk_dup(ctx, 0); // [var][var]
duk_put_prop_string(ctx, -2, "\xFF_ref");
}
else
{
return(ILibDuktape_Error(ctx, "Invalid Parameter"));
}
return 0;
}
@@ -292,6 +318,18 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_SetEx(duk_context *ctx)
}
return 0;
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_toBuffer(duk_context *ctx)
{
duk_push_this(ctx); // [variable]
void *buffer = Duktape_GetPointerProperty(ctx, -1, "_ptr");
int bufferLen = Duktape_GetIntPropertyValue(ctx, -1, "_size", 0);
duk_push_external_buffer(ctx); // [variable][ext]
duk_config_buffer(ctx, -1, buffer, (duk_size_t)bufferLen);
duk_push_buffer_object(ctx, -1, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int size)
{
duk_push_object(ctx); // [var]
@@ -299,7 +337,8 @@ void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int s
duk_put_prop_string(ctx, -2, "_ptr"); // [var]
duk_push_int(ctx, size); // [var][size]
duk_put_prop_string(ctx, -2, "_size"); // [var]
duk_push_true(ctx);
duk_put_prop_string(ctx, -2, ILibDuktape_GenericMarshal_VariableType);
ILibDuktape_CreateEventWithGetterAndSetterEx(ctx, "Val", ILibDuktape_GenericMarshal_Variable_Val_GET, ILibDuktape_GenericMarshal_Variable_Val_SET);
ILibDuktape_CreateEventWithGetterAndSetterWithIntMetaData(ctx, "_VarSize", 4, "IntVal", ILibDuktape_GenericMarshal_Variable_GetEx, ILibDuktape_GenericMarshal_Variable_SetEx);
@@ -310,6 +349,8 @@ void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int s
ILibDuktape_CreateEventWithGetter(ctx, "AnsiString", ILibDuktape_GenericMarshal_Variable_Val_ASTRING);
ILibDuktape_CreateEventWithGetter(ctx, "HexString", ILibDuktape_GenericMarshal_Variable_Val_HSTRING);
ILibDuktape_CreateEventWithGetter(ctx, "HexString2", ILibDuktape_GenericMarshal_Variable_Val_HSTRING2);
ILibDuktape_CreateInstanceMethod(ctx, "toBuffer", ILibDuktape_GenericMarshal_Variable_toBuffer, 0);
}
duk_ret_t ILibDuktape_GenericMarshal_Variable_Finalizer(duk_context *ctx)
{
@@ -330,9 +371,30 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Finalizer(duk_context *ctx)
duk_ret_t ILibDuktape_GenericMarshal_CreateVariable(duk_context *ctx)
{
char* ptr;
int size = duk_require_int(ctx, 0);
int size;
char *str = NULL;
duk_size_t strLen;
if (duk_is_number(ctx, 0))
{
size = duk_require_int(ctx, 0);
}
else if(duk_is_string(ctx, 0))
{
str = Duktape_GetBuffer(ctx, 0, &strLen);
size = (int)strLen + 1;
}
else
{
return(ILibDuktape_Error(ctx, "_GenericMarshal.CreateVariable(): Invalid Parameter"));
}
ptr = (char*)ILibMemory_Allocate(size, 0, NULL, NULL);
if (str != NULL)
{
memcpy_s(ptr, size, str, strLen);
ptr[strLen] = 0;
}
ILibDuktape_GenericMarshal_Variable_PUSH(ctx, ptr, size); // [var]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_GenericMarshal_Variable_Finalizer);
@@ -567,8 +629,9 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
void *fptr = NULL;
int parms = duk_get_top(ctx);
int i;
PTRSIZE vars[10];
int retVal = -1;
if (parms > 20) { return(ILibDuktape_Error(ctx, "Too many parameters")); }
PTRSIZE *vars = ILibMemory_AllocateA(sizeof(PTRSIZE)*parms);
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_address"); // [func][addr]
@@ -639,6 +702,36 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
case 10:
retVal = (int)((R10)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9]);
break;
case 11:
retVal = (int)((R11)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10]);
break;
case 12:
retVal = (int)((R12)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11]);
break;
case 13:
retVal = (int)((R13)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12]);
break;
case 14:
retVal = (int)((R14)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13]);
break;
case 15:
retVal = (int)((R15)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14]);
break;
case 16:
retVal = (int)((R16)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15]);
break;
case 17:
retVal = (int)((R17)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16]);
break;
case 18:
retVal = (int)((R18)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17]);
break;
case 19:
retVal = (int)((R19)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17], vars[18]);
break;
case 20:
retVal = (int)((R20)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17], vars[18], vars[19]);
break;
default:
duk_push_string(ctx, "INVALID NUMBER OF PARAMETERS, MAX of 10");
duk_throw(ctx);
@@ -726,6 +819,7 @@ duk_ret_t ILibDuktape_GenericMarshal_CreateVariableEx(duk_context *ctx)
return 1;
}
void ILibDuktape_GenericMarshal_Push(duk_context *ctx, void *chain)
{
duk_push_object(ctx); // [obj]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
#ifndef __DUKTAPEHECI__
#define __DUKTAPEHECI__
#include "duktape.h"
void ILibDuktape_HECI_Init(duk_context *ctx);
#endif

View File

@@ -245,6 +245,15 @@ void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_f
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndCustomProperty(duk_context *ctx, char *customPropName, char *propName, duk_c_function getterMethod)
{
duk_push_string(ctx, propName); // [obj][customProp][prop]
duk_push_c_function(ctx, getterMethod, 1); // [obj][customProp][prop][getFunc]
duk_dup(ctx, -3); // [obj][customProp][prop][getFunc][customProp]
duk_put_prop_string(ctx, -2, customPropName); // [obj][customProp][prop][getFunc]
duk_remove(ctx, -3); // [obj][prop][getFunc]
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
}
void ILibDuktape_CreateEventWithGetterAndSetterEx(duk_context *ctx, char *propName, duk_c_function getterMethod, duk_c_function setterMethod)
{
@@ -597,3 +606,127 @@ void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size)
return(retVal);
}
void *ILibDuktape_Memory_AllocEx(duk_context *ctx, duk_idx_t index, duk_size_t size)
{
char *retVal = NULL;
duk_dup(ctx, index); // [object]
ILibDuktape_Push_ObjectStash(ctx); // [object][stash]
duk_push_fixed_buffer(ctx, size); // [object][stash][buffer]
retVal = (char*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(retVal)); // [object][stash]
duk_pop_2(ctx); // ...
return(retVal);
}
void ILibDuktape_ValidatePointer(void *chain, void *ptr)
{
ILibHashtable_Put(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0, (void*)0xFFFF);
}
void ILibDuktape_InValidatePointer(void *chain, void *ptr)
{
ILibHashtable_Remove(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0);
}
int ILibDuktape_IsPointerValid(void *chain, void *ptr)
{
return(ILibHashtable_Get(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0) == NULL ? 0 : 1);
}
void ILibDuktape_PointerValidation_Finalizer(duk_context *ctx, void *obj)
{
void *chain = Duktape_GetChain(ctx);
ILibDuktape_InValidatePointer(chain, obj);
}
void ILibDuktape_PointerValidation_Init(duk_context *ctx)
{
void *chain = Duktape_GetChain(ctx);
if (!ILibDuktape_IsPointerValid(chain, duk_get_heapptr(ctx, -1)))
{
// Not set up yet, so set it up
ILibDuktape_ValidatePointer(chain, duk_get_heapptr(ctx, -1));
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_PointerValidation_Finalizer);
}
}
duk_ret_t ILibDuktape_Immediate_Sink(duk_context *ctx)
{
ILibDuktape_ImmediateHandler userCallback = (ILibDuktape_ImmediateHandler)duk_get_pointer(ctx, 0);
void **args = NULL;
int argsLen, i;
duk_push_this(ctx); // [immediate]
duk_dup(ctx, 1); // [immediate][array]
if ((argsLen = (int)duk_get_length(ctx, -1)) > 0)
{
args = ILibMemory_AllocateA(sizeof(void*)*argsLen);
for (i = 0; i < argsLen; ++i)
{
duk_get_prop_index(ctx, -1, i); // [immediate][array][arg]
args[i] = duk_get_pointer(ctx, -1);
duk_pop(ctx); // [immediate][array]
}
}
duk_push_heap_stash(ctx); // [immediate][array][stash]
duk_del_prop_string(ctx, -1, Duktape_GetStashKey(duk_get_heapptr(ctx, -3)));
if (userCallback != NULL) { userCallback(ctx, args, argsLen); }
return(0);
}
void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback)
{
int i = 0;
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "setImmediate"); // [g][setImmediate]
duk_swap_top(ctx, -2); // [setImmediate][this]
duk_push_c_function(ctx, ILibDuktape_Immediate_Sink, DUK_VARARGS); // [setImmediate][this][func]
duk_push_pointer(ctx, callback); // [setImmediate][this][func][userFunc]
duk_push_array(ctx); // [setImmediate][this][func][userFunc][array]
while (args[i] != NULL && i < argsLen)
{
duk_get_prop_string(ctx, -1, "push"); // [setImmediate][this][func][userFunc][array][push]
duk_dup(ctx, -2); // [setImmediate][this][func][userFunc][array][push][this]
duk_push_pointer(ctx, args[i]); // [setImmediate][this][func][userFunc][array][push][this][val]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => Array.push(): "); }
duk_pop(ctx); // [setImmediate][this][func][userFunc][array]
++i;
}
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => immediate(): "); duk_pop(ctx); return; }
// [immediate]
duk_push_heap_stash(ctx); // [immediate][stash]
duk_swap_top(ctx, -2); // [stash][immediate]
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1)));// [stash]
duk_pop(ctx); // ...
}
void ILibDuktape_CreateInstanceMethodWithProperties(duk_context *ctx, char *funcName, duk_c_function funcImpl, duk_idx_t numArgs, unsigned int propertyCount, ...)
{
unsigned int i;
char *name;
duk_idx_t valueIndex;
duk_push_c_function(ctx, funcImpl, numArgs); // [func]
va_list vlist;
va_start(vlist, propertyCount);
for (i = 0; i < propertyCount; ++i)
{
name = va_arg(vlist, char*);
valueIndex = va_arg(vlist, duk_idx_t);
duk_dup(ctx, valueIndex); // [func][value]
duk_put_prop_string(ctx, -2, name); // [func]
}
va_end(vlist);
while (propertyCount-- > 0) { duk_remove(ctx, -2); }
duk_put_prop_string(ctx, -2, funcName);
}
duk_idx_t duk_push_int_ex(duk_context *ctx, duk_int_t val)
{
return(duk_push_int(ctx, val), duk_get_top_index(ctx));
}

View File

@@ -32,6 +32,10 @@ typedef void(*ILibDuktape_HelperEvent)(duk_context *ctx, void *user);
#define ILibDuktape_MeshAgent_Cert_Server "\xFF_selftlscert"
#define CONTEXT_GUID_BUFFER "_CONTEXT_GUID"
#define ILibDuktape_Context_Chain "\xFF_chainptr"
#define ILibDuktape_OBJID "_ObjectID"
#define ILibDuktape_CR2HTTP "\xFF_CR2HTTP"
#define ILibDuktape_CR2Options "\xFF_CR2Options"
char* Duktape_GetContextGuidHex(duk_context *ctx);
void *Duktape_GetChain(duk_context *ctx);
@@ -62,6 +66,7 @@ int ILibDuktape_Process_GetExitCode(duk_context *ctx);
void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_function getterMethod);
void ILibDuktape_CreateEventWithGetterEx(duk_context *ctx, char *propName, void *heapptr);
void ILibDuktape_CreateEventWithGetterAndCustomProperty(duk_context *ctx, char *customPropName, char *propName, duk_c_function getterMethod);
void ILibDuktape_CreateEventWithSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr);
void ILibDuktape_CreateEventWithSetterEx(duk_context *ctx, char *propName, duk_c_function setterMethod);
void ILibDuktape_CreateEventWithGetterAndSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr, duk_c_function getterMethod);
@@ -74,6 +79,9 @@ void ILibDuktape_CreateEventWithGetterAndSetterWithMetaData(duk_context *ctx, ch
#define ILibDuktape_CreateInstanceMethodWithBooleanProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_boolean(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
#define ILibDuktape_CreateInstanceMethodWithIntProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_int(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
#define ILibDuktape_CreateInstanceMethodWithNumberProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_number(context, (propValue));duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
void ILibDuktape_CreateInstanceMethodWithProperties(duk_context *ctx, char *funcName, duk_c_function funcImpl, duk_idx_t numArgs, unsigned int propertyCount, ...);
duk_idx_t duk_push_int_ex(duk_context *ctx, duk_int_t val);
void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodName, duk_c_function impl, duk_idx_t argCount);
void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr);
void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
@@ -81,8 +89,21 @@ void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
#define ILibDuktape_CreateFinalizer(context, funcImpl) duk_push_c_function(context, funcImpl, 1); duk_set_finalizer(context, -2);
void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size);
void *ILibDuktape_Memory_AllocEx(duk_context *ctx, duk_idx_t index, duk_size_t size);
void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEvent handler, void *user);
void ILibDuktape_Push_ObjectStash(duk_context *ctx);
void ILibDuktape_PointerValidation_Init(duk_context *ctx);
void ILibDuktape_ValidatePointer(void *chain, void *ptr);
void ILibDuktape_InValidatePointer(void *chain, void *ptr);
int ILibDuktape_IsPointerValid(void *chain, void *ptr);
#define ILibDuktape_ValidateHeapPointer(ctx, objIdx) ILibDuktape_ValidatePointer(Duktape_GetChain(ctx), duk_get_heapptr(ctx, objIdx))
#define ILibDuktape_InValidateHeapPointer(ctx, objIdx) ILibDuktape_InValidatePointer(Duktape_GetChain(ctx), duk_get_heapptr(ctx, objIdx))
typedef void(*ILibDuktape_ImmediateHandler)(duk_context *ctx, void ** args, int argsLen);
void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback);
#define ILibDuktape_WriteID(ctx, id) duk_push_string(ctx, id);duk_put_prop_string(ctx, -2, ILibDuktape_OBJID)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -81,6 +81,7 @@ duk_ret_t ILibDuktape_MemoryStream_buffer(duk_context *ctx)
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, ms->buffer, ms->bufferLen);
duk_push_buffer_object(ctx, -1, 0, ms->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
@@ -93,6 +94,43 @@ duk_ret_t ILibDuktape_MemoryStream_Finalizer(duk_context *ctx)
return(0);
}
duk_ret_t ILibDuktape_MemoryStream_writeBE(duk_context *ctx)
{
duk_push_current_function(ctx);
int size = Duktape_GetIntPropertyValue(ctx, -1, "size", 0);
char buffer[16];
int value = duk_require_int(ctx, 0);
switch (size)
{
case 1:
buffer[0] = (char)value;
break;
case 2:
((unsigned short*)buffer)[0] = htons((unsigned short)value);
break;
case 4:
((unsigned int*)buffer)[0] = htonl((unsigned int)value);
break;
default:
break;
}
if (size > 0)
{
duk_push_this(ctx); // [ms]
duk_get_prop_string(ctx, -1, "write"); // [ms][write]
duk_swap_top(ctx, -2); // [write][this]
duk_push_external_buffer(ctx); // [write][this][buffer]
duk_config_buffer(ctx, -1, buffer, size);
duk_call_method(ctx, 1); // [retVal]
return(1);
}
else
{
return(ILibDuktape_Error(ctx, "MemoryStream.writeBE() Unknown Error"));
}
}
duk_ret_t ILibDuktape_MemoryStream_new(duk_context *ctx)
{
int initial = duk_get_top(ctx) > 0 ? duk_require_int(ctx, 0) : 4096;
@@ -110,6 +148,11 @@ duk_ret_t ILibDuktape_MemoryStream_new(duk_context *ctx)
ms->s = ILibDuktape_DuplexStream_Init(ctx, ILibDuktape_MemoryStream_OnWrite, ILibDuktape_MemoryStream_OnEnd, NULL, NULL, ms);
ILibDuktape_CreateEventWithGetter(ctx, "buffer", ILibDuktape_MemoryStream_buffer);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_MemoryStream_Finalizer);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 4, "writeUInt32BE", ILibDuktape_MemoryStream_writeBE, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 2, "writeUInt16BE", ILibDuktape_MemoryStream_writeBE, 1);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 1, "writeUInt8", ILibDuktape_MemoryStream_writeBE, 1);
return(1);
}
void ILibDuktape_MemoryStream_PUSH(duk_context *ctx, void *chain)

View File

@@ -108,14 +108,14 @@ void ILibDuktape_NetworkMonitor_EventSink(ILibIPAddressMonitor sender, void *use
}
duk_ret_t ILibDuktape_NetworkMonitor_Finalizer(duk_context *ctx)
{
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) != 0) { return(0); }
duk_get_prop_string(ctx, 0, ILibDuktape_NetworkMonitor_PTR);
ILibDuktape_NetworkMonitor *nm = (ILibDuktape_NetworkMonitor*)Duktape_GetBuffer(ctx, -1, NULL);
ILibChain_SafeRemoveEx(Duktape_GetChain(ctx), nm->addressMonitor);
if (nm->addressTable != NULL) { ILibHashtable_Destroy(nm->addressTable); }
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) != 0) { return(0); }
ILibChain_SafeRemoveEx(Duktape_GetChain(ctx), nm->addressMonitor);
return(0);
}
void ILibDuktape_NetworkMonitor_PUSH(duk_context *ctx, void *chain)

View File

@@ -1,11 +1,15 @@
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_DuplexStream.h"
#include "ILibDuktape_EventEmitter.h"
#include "../microstack/ILibParsers.h"
#include "../microstack/ILibCrypto.h"
#define ILibDuktape_Timer_Ptrs "\xFF_DuktapeTimer_PTRS"
#define ILibDuktape_Queue_Ptr "\xFF_Queue"
duk_ret_t ILibDuktape_Pollyfills_Buffer_slice(duk_context *ctx)
{
@@ -63,6 +67,13 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_toString(duk_context *ctx)
util_tohex(buffer, (int)bufferLen, tmpBuffer);
duk_push_string(ctx, tmpBuffer);
}
else if (strcmp(cType, "hex:") == 0)
{
duk_push_fixed_buffer(ctx, 1 + (bufferLen * 3));
tmpBuffer = Duktape_GetBuffer(ctx, -1, NULL);
util_tohex2(buffer, (int)bufferLen, tmpBuffer);
duk_push_string(ctx, tmpBuffer);
}
else
{
duk_push_string(ctx, "buffer.toString(): Unrecognized parameter");
@@ -84,11 +95,10 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
if (nargs == 1)
{
str = (char*)duk_get_lstring(ctx, 0, &strlength);
duk_push_fixed_buffer(ctx, strlength + 1);
duk_push_fixed_buffer(ctx, strlength);
buffer = Duktape_GetBuffer(ctx, -1, NULL);
memcpy_s(buffer, strlength + 1, str, strlength);
buffer[strlength] = 0;
duk_push_buffer_object(ctx, -1, 0, strlength+1, DUK_BUFOBJ_ARRAYBUFFER);
memcpy_s(buffer, strlength, str, strlength);
duk_push_buffer_object(ctx, -1, 0, strlength, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
else if(!(nargs == 2 && duk_is_string(ctx, 0) && duk_is_string(ctx, 1)))
@@ -107,14 +117,14 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
duk_push_fixed_buffer(ctx, ILibBase64DecodeLength((int)strlength));
buffer = Duktape_GetBuffer(ctx, -1, NULL);
bufferLen = ILibBase64Decode((unsigned char*)str, (int)strlength, (unsigned char**)&buffer);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
}
else if (strcmp(encoding, "hex") == 0)
{
duk_push_fixed_buffer(ctx, strlength / 2);
buffer = Duktape_GetBuffer(ctx, -1, NULL);
bufferLen = util_hexToBuf(str, (int)strlength, buffer);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
}
else
{
@@ -136,6 +146,15 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_readInt32BE(duk_context *ctx)
duk_push_int(ctx, ntohl(((int*)(buffer + offset))[0]));
return(1);
}
duk_ret_t ILibDuktape_Polyfills_Buffer_alloc(duk_context *ctx)
{
int sz = duk_require_int(ctx, 0);
duk_push_fixed_buffer(ctx, sz);
char *buffer = Duktape_GetBuffer(ctx, -1, NULL);
memset(buffer, 0, sz);
duk_push_buffer_object(ctx, -1, 0, sz, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
void ILibDuktape_Polyfills_Buffer(duk_context *ctx)
{
// Polyfill 'Buffer.slice'
@@ -144,8 +163,8 @@ void ILibDuktape_Polyfills_Buffer(duk_context *ctx)
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Pollyfills_Buffer_slice, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "slice"); // [g][Duktape][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_readInt32BE, DUK_VARARGS);
duk_put_prop_string(ctx, -2, "readInt32BE");
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_readInt32BE, DUK_VARARGS);// [g][Duktape][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "readInt32BE"); // [g][Duktape][Buffer][prototype]
duk_pop_3(ctx); // [g]
// Polyfill 'Buffer.toString()
@@ -160,7 +179,22 @@ void ILibDuktape_Polyfills_Buffer(duk_context *ctx)
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_from, DUK_VARARGS); // [g][Buffer][func]
duk_put_prop_string(ctx, -2, "from"); // [g][Buffer]
duk_pop(ctx);
duk_pop(ctx); // [g]
// Polyfill Buffer.alloc() for Node Buffers)
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_alloc, DUK_VARARGS); // [g][Buffer][func]
duk_put_prop_string(ctx, -2, "alloc"); // [g][Buffer]
duk_pop(ctx); // [g]
// Polyfill Buffer.toString() for Node Buffers
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
duk_get_prop_string(ctx, -1, "prototype"); // [g][Buffer][prototype]
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_toString, DUK_VARARGS); // [g][Buffer][prototype][func]
duk_put_prop_string(ctx, -2, "toString"); // [g][Buffer][prototype]
duk_pop_2(ctx); // [g]
}
duk_ret_t ILibDuktape_Polyfills_String_startsWith(duk_context *ctx)
{
@@ -379,6 +413,7 @@ void ILibDuktape_Polyfills_timer_elapsed(void *obj)
{
ILibDuktape_Timer *ptrs = (ILibDuktape_Timer*)obj;
int argCount, i;
duk_context *ctx = ptrs->ctx;
if (ptrs->timerType == ILibDuktape_Timer_Type_INTERVAL)
{
@@ -397,7 +432,7 @@ void ILibDuktape_Polyfills_timer_elapsed(void *obj)
}
duk_pop(ptrs->ctx); // [func][this][...arg...]
if (duk_pcall_method(ptrs->ctx, argCount) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "timers.onElapsed() callback handler"); }
duk_pop(ptrs->ctx); // ...
duk_pop(ctx); // ...
}
duk_ret_t ILibDuktape_Polyfills_timer_set(duk_context *ctx)
{
@@ -490,8 +525,245 @@ duk_ret_t ILibDuktape_Polyfills_addModule(duk_context *ctx)
}
return(0);
}
duk_ret_t ILibDuktape_Queue_Finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, ILibDuktape_Queue_Ptr);
ILibQueue_Destroy((ILibQueue)duk_get_pointer(ctx, -1));
return(0);
}
duk_ret_t ILibDuktape_Queue_EnQueue(duk_context *ctx)
{
ILibQueue Q;
int i;
int nargs = duk_get_top(ctx);
duk_push_this(ctx); // [queue]
duk_get_prop_string(ctx, -1, ILibDuktape_Queue_Ptr); // [queue][ptr]
Q = (ILibQueue)duk_get_pointer(ctx, -1);
duk_pop(ctx); // [queue]
ILibDuktape_Push_ObjectStash(ctx); // [queue][stash]
duk_push_array(ctx); // [queue][stash][array]
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [queue][stash][array][arg]
duk_put_prop_index(ctx, -2, i); // [queue][stash][array]
}
ILibQueue_EnQueue(Q, duk_get_heapptr(ctx, -1));
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [queue][stash]
return(0);
}
duk_ret_t ILibDuktape_Queue_DeQueue(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "peek");
int peek = duk_get_int(ctx, -1);
duk_push_this(ctx); // [Q]
duk_get_prop_string(ctx, -1, ILibDuktape_Queue_Ptr); // [Q][ptr]
ILibQueue Q = (ILibQueue)duk_get_pointer(ctx, -1);
void *h = peek == 0 ? ILibQueue_DeQueue(Q) : ILibQueue_PeekQueue(Q);
if (h == NULL) { return(ILibDuktape_Error(ctx, "Queue is empty")); }
duk_pop(ctx); // [Q]
ILibDuktape_Push_ObjectStash(ctx); // [Q][stash]
duk_push_heapptr(ctx, h); // [Q][stash][array]
int length = (int)duk_get_length(ctx, -1);
int i;
for (i = 0; i < length; ++i)
{
duk_get_prop_index(ctx, -i - 1, i); // [Q][stash][array][args]
}
if (peek == 0) { duk_del_prop_string(ctx, -length - 2, Duktape_GetStashKey(h)); }
return(length);
}
duk_ret_t ILibDuktape_Queue_new(duk_context *ctx)
{
duk_push_object(ctx); // [queue]
duk_push_pointer(ctx, ILibQueue_Create()); // [queue][ptr]
duk_put_prop_string(ctx, -2, ILibDuktape_Queue_Ptr); // [queue]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Queue_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "enQueue", ILibDuktape_Queue_EnQueue, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "peek", 0, "deQueue", ILibDuktape_Queue_DeQueue, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "peek", 1, "peekQueue", ILibDuktape_Queue_DeQueue, DUK_VARARGS);
return(1);
}
void ILibDuktape_Queue_Push(duk_context *ctx, void* chain)
{
duk_push_c_function(ctx, ILibDuktape_Queue_new, 0);
}
typedef struct ILibDuktape_DynamicBuffer_data
{
int start;
int end;
int unshiftBytes;
char *buffer;
int bufferLen;
}ILibDuktape_DynamicBuffer_data;
typedef struct ILibDuktape_DynamicBuffer_ContextSwitchData
{
void *chain;
void *heapptr;
ILibDuktape_DuplexStream *stream;
ILibDuktape_DynamicBuffer_data *data;
int bufferLen;
char buffer[];
}ILibDuktape_DynamicBuffer_ContextSwitchData;
ILibTransport_DoneState ILibDuktape_DynamicBuffer_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user);
void ILibDuktape_DynamicBuffer_WriteSink_ChainThread(void *chain, void *user)
{
ILibDuktape_DynamicBuffer_ContextSwitchData *data = (ILibDuktape_DynamicBuffer_ContextSwitchData*)user;
if (ILibDuktape_IsPointerValid(chain, data->heapptr) != 0)
{
ILibDuktape_DynamicBuffer_WriteSink(data->stream, data->buffer, data->bufferLen, data->data);
ILibDuktape_DuplexStream_Ready(data->stream);
}
free(user);
}
ILibTransport_DoneState ILibDuktape_DynamicBuffer_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)user;
if (ILibIsRunningOnChainThread(stream->readableStream->chain) == 0)
{
ILibDuktape_DynamicBuffer_ContextSwitchData *tmp = (ILibDuktape_DynamicBuffer_ContextSwitchData*)ILibMemory_Allocate(sizeof(ILibDuktape_DynamicBuffer_ContextSwitchData) + bufferLen, 0, NULL, NULL);
tmp->chain = stream->readableStream->chain;
tmp->heapptr = stream->ParentObject;
tmp->stream = stream;
tmp->data = data;
tmp->bufferLen = bufferLen;
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
ILibChain_RunOnMicrostackThread(tmp->chain, ILibDuktape_DynamicBuffer_WriteSink_ChainThread, tmp);
return(ILibTransport_DoneState_INCOMPLETE);
}
if ((data->bufferLen - data->start - data->end) < bufferLen)
{
if (data->end > 0)
{
// Move the buffer first
memmove_s(data->buffer, data->bufferLen, data->buffer + data->start, data->end);
data->start = 0;
}
if ((data->bufferLen - data->end) < bufferLen)
{
// Need to resize buffer first
int tmpSize = data->bufferLen;
while ((tmpSize - data->end) < bufferLen)
{
tmpSize += 4096;
}
data->buffer = (char*)realloc(data->buffer, tmpSize);
data->bufferLen = tmpSize;
}
}
memcpy_s(data->buffer + data->start + data->end, data->bufferLen - data->start - data->end, buffer, bufferLen);
data->end += bufferLen;
int unshifted = 0;
do
{
duk_push_heapptr(stream->readableStream->ctx, stream->ParentObject); // [ds]
duk_get_prop_string(stream->readableStream->ctx, -1, "emit"); // [ds][emit]
duk_swap_top(stream->readableStream->ctx, -2); // [emit][this]
duk_push_string(stream->readableStream->ctx, "readable"); // [emit][this][readable]
if (duk_pcall_method(stream->readableStream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(stream->readableStream->ctx, "DynamicBuffer.WriteSink => readable(): "); }
duk_pop(stream->readableStream->ctx); // ...
ILibDuktape_DuplexStream_WriteData(stream, data->buffer + data->start, data->end);
if (data->unshiftBytes == 0)
{
// All the data was consumed
data->start = data->end = 0;
}
else
{
unshifted = (data->end - data->unshiftBytes);
if (unshifted > 0)
{
data->start += unshifted;
data->end = data->unshiftBytes;
data->unshiftBytes = 0;
}
}
} while (unshifted != 0);
return(ILibTransport_DoneState_COMPLETE);
}
void ILibDuktape_DynamicBuffer_EndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_DuplexStream_WriteEnd(stream);
}
duk_ret_t ILibDuktape_DynamicBuffer_Finalizer(duk_context *ctx)
{
ILibDuktape_InValidateHeapPointer(ctx, 0);
duk_get_prop_string(ctx, 0, "\xFF_buffer");
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
free(data->buffer);
return(0);
}
int ILibDuktape_DynamicBuffer_unshift(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)user;
data->unshiftBytes = unshiftBytes;
return(unshiftBytes);
}
duk_ret_t ILibDuktape_DynamicBuffer_read(duk_context *ctx)
{
ILibDuktape_DynamicBuffer_data *data;
duk_push_this(ctx); // [DynamicBuffer]
duk_get_prop_string(ctx, -1, "\xFF_buffer"); // [DynamicBuffer][buffer]
data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_push_external_buffer(ctx); // [DynamicBuffer][buffer][extBuffer]
duk_config_buffer(ctx, -1, data->buffer + data->start, data->bufferLen - (data->start + data->end));
duk_push_buffer_object(ctx, -1, 0, data->bufferLen - (data->start + data->end), DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}
duk_ret_t ILibDuktape_DynamicBuffer_new(duk_context *ctx)
{
ILibDuktape_DynamicBuffer_data *data;
int initSize = 4096;
if (duk_get_top(ctx) != 0)
{
initSize = duk_require_int(ctx, 0);
}
duk_push_object(ctx); // [stream]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DynamicBuffer_data));
data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
memset(data, 0, sizeof(ILibDuktape_DynamicBuffer_data));
duk_put_prop_string(ctx, -2, "\xFF_buffer");
data->bufferLen = initSize;
data->buffer = (char*)malloc(initSize);
ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_DynamicBuffer_WriteSink, ILibDuktape_DynamicBuffer_EndSink, NULL, NULL, ILibDuktape_DynamicBuffer_unshift, data);
ILibDuktape_EventEmitter_CreateEventEx(ILibDuktape_EventEmitter_GetEmitter(ctx, -1), "readable");
ILibDuktape_CreateInstanceMethod(ctx, "read", ILibDuktape_DynamicBuffer_read, DUK_VARARGS);
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_DynamicBuffer_Finalizer);
ILibDuktape_ValidateHeapPointer(ctx, -1);
return(1);
}
void ILibDuktape_DynamicBuffer_Push(duk_context *ctx, void *chain)
{
duk_push_c_function(ctx, ILibDuktape_DynamicBuffer_new, DUK_VARARGS);
}
void ILibDuktape_Polyfills_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "queue", ILibDuktape_Queue_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "DynamicBuffer", ILibDuktape_DynamicBuffer_Push);
// Global Polyfills
duk_push_global_object(ctx); // [g]

View File

@@ -25,6 +25,7 @@ limitations under the License.
#define ILibDuktape_readableStream_WritePipes "\xFF_WritePipes"
#define ILibDuktape_readableStream_WritePipes_PTRBUFFER "\xFF_WritePipesPtrBuffer"
#define ILibDuktape_readableStream_WritePipes_Stream "\xFF_WritePipes_Stream"
#define ILibDuktape_readableStream_PipeArray "\xFF_RS_PipeArray"
#ifdef __DOXY__
/*!
@@ -124,39 +125,47 @@ void ILibDuktape_readableStream_WriteData_buffer(ILibDuktape_readableStream *str
}
tmp->Next = buffered;
}
if (stream->paused == 0)
{
stream->paused = 1;
stream->PauseHandler(stream, stream->user);
}
}
void ILibDuktape_readableStream_WriteData_OnData_ChainThread(void *chain, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
ILibDuktape_readableStream_bufferedData *data = (ILibDuktape_readableStream_bufferedData*)user;
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)data->Next;
stream->paused = 0;
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (stream->extBuffer_Reserved == 0)
if (data->Reserved == 0)
{
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
duk_push_external_buffer(stream->ctx); // [ext]
duk_config_buffer(stream->ctx, -1, data->buffer, data->bufferLen);
}
duk_push_heapptr(stream->ctx, stream->OnData); // [ext][func]
duk_push_heapptr(stream->ctx, stream->object); // [ext][func][this]
if (data->Reserved == 0)
{
duk_push_buffer_object(stream->ctx, -3, 0, data->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][func][this][buffer]
}
else
{
duk_push_lstring(stream->ctx, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
duk_push_lstring(stream->ctx, data->buffer, data->bufferLen); // [ext][func][this][buffer/string]
}
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
if (duk_pcall_method(stream->ctx, 1) != 0) // [...][retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
if (data->Reserved == 0)
{
duk_pop_2(stream->ctx); // ...
}
else
{
duk_pop(stream->ctx); // ...
}
free(data);
if (stream->paused == 0 && stream->ResumeHandler != NULL) { stream->ResumeHandler(stream, stream->user); }
}
void ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStream *ws, void *user)
int ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStream *ws, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
int unpipeInProgress = 0;
#ifdef WIN32
if(InterlockedDecrement(&(stream->pipe_pendingCount)) == 0)
@@ -169,144 +178,97 @@ void ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStrea
if(stream->pipe_pendingCount == 0)
#endif
{
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
sem_wait(&(stream->pipeLock));
stream->pipeInProgress = 0;
unpipeInProgress = stream->unpipeInProgress;
sem_post(&(stream->pipeLock));
if (unpipeInProgress == 0 && stream->ResumeHandler != NULL && stream->paused != 0) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
return(1);
}
return(0);
}
duk_ret_t ILibDuktape_readableStream_WriteData_Flush_JS(duk_context *ctx)
{
ILibDuktape_readableStream *stream;
duk_ret_t ILibDuktape_readableStream_WriteDataEx_Flush(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "readable");
stream = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
duk_get_prop_string(ctx, -1, "\xFF_STREAM");
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)duk_to_pointer(ctx, -1);
ILibDuktape_readableStream_WriteData_Flush(NULL, stream);
return 0;
return(0);
}
void ILibDuktape_readableStream_WriteData_ChainThread(void *chain, void *user)
{
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
ILibDuktape_readableStream_nextWriteablePipe *w;
int jsCount = 0;
sem_wait(&(stream->pipeLock));
w = stream->nextWriteable;
stream->pipe_pendingCount = 0;
int ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(ILibDuktape_readableStream *stream, void *ws, char *buffer, int bufferLen)
{
int retVal = 0;
duk_push_external_buffer(stream->ctx); // [ext]
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
duk_push_heapptr(stream->ctx, ws); // [ext][ws]
duk_get_prop_string(stream->ctx, -1, "write"); // [ext][ws][write]
duk_swap_top(stream->ctx, -2); // [ext][write][this]
duk_push_buffer_object(stream->ctx, -3, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][write][this][buffer]
duk_push_c_function(stream->ctx, ILibDuktape_readableStream_WriteDataEx_Flush, DUK_VARARGS);// [ext][write][this][buffer][flush]
duk_push_pointer(stream->ctx, stream); // [ext][write][this][buffer][flush][ptr]
duk_put_prop_string(stream->ctx, -2, "\xFF_STREAM"); // [ext][write][this][buffer][flush]
if (duk_pcall_method(stream->ctx, 2) != 0) // [ext][...]
{
ILibDuktape_Process_UncaughtExceptionEx(stream->ctx, "readable.write(): Error Piping ");
if (ILibDuktape_readableStream_WriteData_Flush(NULL, stream)) { retVal = 2; }
}
retVal = duk_to_boolean(stream->ctx, -1) ? 1 : 0;
duk_pop_2(stream->ctx);
return(retVal);
}
void ILibDuktape_readableStream_WriteDataEx_Chain(void *chain, void *user)
{
ILibDuktape_readableStream_bufferedData *data = (ILibDuktape_readableStream_bufferedData*)user;
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)data->Next;
ILibDuktape_readableStream_nextWriteablePipe *w = stream->nextWriteable;
while (w != NULL)
{
if (w->nativeWritable != NULL || w->writableStream != NULL) { stream->pipe_pendingCount++; }
w = w->next;
}
w = stream->nextWriteable;
while (w != NULL)
if (w->writableStream != NULL && w->nativeWritable == NULL)
{
if (w->nativeWritable != NULL)
{
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
switch (ws->WriteSink(ws, stream->extBuffer_buffer, stream->extBuffer_bufferLen, ws->WriteSink_User))
{
case ILibTransport_DoneState_INCOMPLETE:
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
ws->OnWriteFlushEx_User = stream;
break;
case ILibTransport_DoneState_COMPLETE:
ws->OnWriteFlushEx = NULL;
ws->OnWriteFlushEx_User = NULL;
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
case ILibTransport_DoneState_ERROR:
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
break;
}
}
else if(w->writableStream != NULL)
{
duk_push_heapptr(stream->ctx, w->writableStream); // [stream]
duk_get_prop_string(stream->ctx, -1, "write"); // [stream][func]
duk_swap_top(stream->ctx, -2); // [func][this]
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][chunk]
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
duk_push_c_function(stream->ctx, ILibDuktape_readableStream_WriteData_Flush_JS, DUK_VARARGS); // [func][this][chunk][callback]
duk_push_pointer(stream->ctx, stream); // [func][this][chunk][callback][user]
duk_put_prop_string(stream->ctx, -2, "readable"); // [func][this][chunk][callback]
if (duk_pcall_method(stream->ctx, 2) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
else
{
jsCount += duk_get_int(stream->ctx, -1);
}
duk_pop(stream->ctx);
if (ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(stream, w->writableStream, data->buffer, data->bufferLen) == 2) { break; }
}
w = w->next;
}
if (stream->paused != 0 && stream->pipe_pendingCount == 0)
{
sem_post(&(stream->pipeLock));
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
}
else
{
sem_post(&(stream->pipeLock));
}
free(data);
}
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen)
{
ILibDuktape_readableStream_nextWriteablePipe *w;
int nonNativeCount = 0;
int nativeCount = 0;
int dispatchedNonNative = 0;
int noContinue = 0;
int dispatched = 0;
int needPause = 0;
if (stream == NULL) { return(1); }
if (stream->paused != 0)
{
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
return(stream->paused);
}
if (stream->bypassValue == 0 || stream->bypassValue != streamReserved)
{
sem_wait(&(stream->pipeLock));
stream->pipeInProgress = 1;
sem_post(&(stream->pipeLock));
w = stream->nextWriteable;
stream->pipe_pendingCount = 0;
while (w != NULL)
{
if (w->nativeWritable == 0) { ++nonNativeCount; }
else { ++nativeCount; }
++stream->pipe_pendingCount;
w = w->next;
}
dispatched = stream->pipe_pendingCount;
w = stream->nextWriteable;
if (w != NULL)
{
if (nonNativeCount > 0)
{
// There are piped Pure JavaScript objects... We must context switch to Microstack Thread
stream->extBuffer_Reserved = streamReserved;
stream->extBuffer_buffer = buffer;
stream->extBuffer_bufferLen = bufferLen;
sem_post(&(stream->pipeLock));
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_ChainThread, stream);
return(stream->paused);
}
else
{
// All piped objects are native, so we can blast out a send
stream->pipe_pendingCount = nativeCount;
while (w != NULL)
{
if (w->nativeWritable != NULL)
@@ -318,60 +280,73 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
case ILibTransport_DoneState_INCOMPLETE:
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
ws->OnWriteFlushEx_User = stream;
needPause = 1;
break;
case ILibTransport_DoneState_COMPLETE:
ws->OnWriteFlushEx = NULL;
ws->OnWriteFlushEx_User = NULL;
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
if (ILibDuktape_readableStream_WriteData_Flush(ws, stream)) { noContinue = 1; }
break;
case ILibTransport_DoneState_ERROR:
#ifdef WIN32
InterlockedDecrement(&(stream->pipe_pendingCount));
#elif defined(__ATOMIC_SEQ_CST)
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
#else
--stream->pipe_pendingCount;
#endif
if (ILibDuktape_readableStream_WriteData_Flush(ws, stream)) { noContinue = 1; }
break;
}
if (noContinue != 0) { break; }
}
else if (w->writableStream != NULL && dispatchedNonNative == 0)
{
if (ILibIsRunningOnChainThread(stream->chain) == 0)
{
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL);
tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream;
tmp->Reserved = streamReserved;
tmp->bufferLen = bufferLen;
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
dispatchedNonNative = 1;
needPause = 1;
ILibChain_RunOnMicrostackThreadEx(stream->chain, ILibDuktape_readableStream_WriteDataEx_Chain, tmp);
}
else
{
// We're running on the Chain Thread, so we can directly dispatch into JS
switch (ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(stream, w->writableStream, buffer, bufferLen))
{
case 1: // Need to Pause
needPause = 1;
break;
case 2: // Complete
noContinue = 1;
break;
default: // NOP
break;
}
}
}
if (noContinue != 0) { break; }
w = w->next;
}
if (stream->pipe_pendingCount == 0)
}
if (dispatched == 0)
{
sem_wait(&(stream->pipeLock));
stream->pipeInProgress = 0;
sem_post(&(stream->pipeLock));
return(stream->paused);
}
else
{
sem_post(&(stream->pipeLock));
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
return(stream->paused);
}
}
}
else
{
sem_post(&(stream->pipeLock));
}
}
if (stream->OnData != NULL)
{
if (ILibIsRunningOnChainThread(stream->chain))
{
if (streamReserved == 0)
{
duk_push_external_buffer(stream->ctx); // [extBuffer]
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
}
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (streamReserved == 0)
{
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
duk_push_buffer_object(stream->ctx, -3, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][func][this][nodeBuffer]
}
else
{
@@ -381,32 +356,43 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
if (streamReserved == 0)
{
duk_pop_2(stream->ctx);
}
else
{
duk_pop(stream->ctx); // ...
}
}
else
{
// Need to PAUSE, and context switch to Chain Thread, so we can dispatch into JavaScript
sem_wait(&(stream->pipeLock));
stream->extBuffer_Reserved = streamReserved;
stream->extBuffer_buffer = buffer;
stream->extBuffer_bufferLen = bufferLen;
sem_post(&(stream->pipeLock));
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, stream);
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL);
tmp->bufferLen = bufferLen;
tmp->Reserved = streamReserved;
tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream;
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
needPause = 1;
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, tmp);
}
}
else if (stream->PauseHandler != NULL && stream->OnEnd == NULL)
{
// If we get here, it means we are writing data, but nobody is going to be receiving it...
// So we need to buffer the data, so when we are resumed later, we can retry
needPause = 1;
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
}
else if (stream->OnEnd != NULL)
{
return 0;
}
}
if (needPause)
{
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
}
return(stream->paused);
}
void ILibDuktape_readableStream_WriteEnd_ChainSink(void *chain, void *user)
@@ -426,18 +412,8 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
{
ILibDuktape_readableStream_nextWriteablePipe *next;
if (stream->OnEnd != NULL)
if (stream->noPropagateEnd == 0 && stream->nextWriteable != NULL)
{
duk_context *x = stream->ctx;
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(x); // ...
retVal = 0;
}
next = stream->nextWriteable;
while (next != NULL)
{
@@ -452,15 +428,28 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
next = next->next;
retVal = 0;
}
}
else if (stream->OnEnd != NULL)
{
duk_context *x = stream->ctx;
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
ILibDuktape_Process_UncaughtException(stream->ctx);
}
duk_pop(x); // ...
retVal = 0;
}
}
return retVal;
}
void ILibDuktape_readableStream_Closed(ILibDuktape_readableStream *stream)
{
ILibDuktape_readableStream_WriteEnd(stream);
if (stream->OnClose != NULL)
{
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
duk_push_heapptr(stream->ctx, stream->OnClose); // [func]
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
{
@@ -479,7 +468,14 @@ duk_ret_t ILibDuktape_readableStream_pause(duk_context *ctx)
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [stream]
if (ptr->PauseHandler != NULL) { ptr->paused = 1; ptr->PauseHandler(ptr, ptr->user); }
if (ptr->PauseHandler != NULL)
{
ptr->paused = 1; ptr->PauseHandler(ptr, ptr->user);
}
else
{
return(ILibDuktape_Error(ctx, "Pause Not Supported"));
}
return 1;
}
@@ -523,151 +519,240 @@ duk_ret_t ILibDuktape_readableStream_resume(duk_context *ctx)
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [stream]
if (ptr->ResumeHandler == NULL) { return(ILibDuktape_Error(ctx, "Resume not supported")); }
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
return 1;
}
void ILibDuktape_readableStream_pipe_resumeFromTimer(void *obj)
void ILibDuktape_ReadableStream_pipe_ResumeLater(duk_context *ctx, void **args, int argsLen)
{
ILibDuktape_readableStream* ptr = (ILibDuktape_readableStream*)((void**)obj)[0];
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
free(obj);
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)args[0];
if (ILibDuktape_readableStream_resume_flush(rs) == 0 && rs->ResumeHandler != NULL) { rs->paused = 0; rs->ResumeHandler(rs, rs->user); }
if (rs->PipeHookHandler != NULL) { rs->PipeHookHandler(rs, args[1], rs->user); }
}
void ILibDuktape_readableStream_pipe_resumeFromTimer2(void *obj)
void ILibDuktape_readableStream_pipe_later(duk_context *ctx, void **args, int argsLen)
{
free(obj);
duk_push_heapptr(ctx, args[0]); // [readable]
duk_get_prop_string(ctx, -1, "pipe"); // [readable][pipe]
duk_swap_top(ctx, -2); // [pipe][this]
duk_push_heapptr(ctx, args[1]); // [pipe][this][writable]
if (argsLen > 2) { duk_push_heapptr(ctx, args[2]); } // [pipe][this][writable][options]
if (duk_pcall_method(ctx, argsLen - 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readableStream.pipeLater(): "); }
duk_pop(ctx); // ...
}
duk_ret_t ILibDuktape_readableStream_pipe(duk_context *ctx)
{
ILibDuktape_readableStream *rstream;
ILibDuktape_readableStream_nextWriteablePipe *w;
ILibDuktape_readableStream_nextWriteablePipe *w, *tmp;
int nargs = duk_get_top(ctx);
duk_push_this(ctx); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
rstream = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable]
duk_pop_2(ctx); // ...
sem_wait(&(rstream->pipeLock));
if (rstream->pipeInProgress != 0)
{
// We must YIELD and try again later, becuase there is an active dispatch going on
duk_push_this(ctx);
ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, -1), duk_get_heapptr(ctx, 0), nargs > 1 ? duk_get_heapptr(ctx, 1) : NULL }, 1 + nargs, ILibDuktape_readableStream_pipe_later);
duk_dup(ctx, 0);
sem_post(&(rstream->pipeLock));
return(1);
}
else
{
// No Active Dispatch, so while we hold this lock, we can setup/add the pipe
duk_push_heapptr(ctx, rstream->pipeArray); // [pipeArray]
duk_get_prop_string(ctx, -1, "push"); // [pipeArray][push]
duk_swap_top(ctx, -2); // [push][this]
duk_dup(ctx, 0); // [push][this][dest]
ILibDuktape_Push_ObjectStash(ctx); // [push][this][dest][stash]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream_nextWriteablePipe)); // [push][this][dest][stash][buffer]
w = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [push][this][dest][stash]
duk_pop(ctx); // [push][this][dest]
duk_call_method(ctx, 1); duk_pop(ctx); // ...
memset(w, 0, sizeof(ILibDuktape_readableStream_nextWriteablePipe));
w->writableStream = duk_get_heapptr(ctx, 0);
if (duk_has_prop_string(ctx, 0, ILibDuktape_WritableStream_WSPTRS))
{
// This is one of our writable stream implementation... So we can keep everything native
duk_get_prop_string(ctx, 0, ILibDuktape_WritableStream_WSPTRS); // [wrsPTR]
w->nativeWritable = Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // ...
// If JSCreate is non-zero, it means this is actually a JS Stream, not a native one
if (((int*)w->nativeWritable)[0] != 0) { w->nativeWritable = NULL; }
}
// Now lets lets add this entry to the end of the list, so it can be dispatched without invoking into JS to access the array
if (rstream->nextWriteable == NULL)
{
rstream->nextWriteable = w;
}
else
{
tmp = rstream->nextWriteable;
while (tmp->next != NULL) { tmp = tmp->next; }
tmp->next = w;
w->previous = tmp;
}
}
if (nargs > 1 && duk_is_object(ctx, 1))
{
rstream->bypassValue = Duktape_GetIntPropertyValue(ctx, 1, "dataTypeSkip", 0);
rstream->noPropagateEnd = Duktape_GetBooleanProperty(ctx, 1, "end", 1) == 0 ? 1 : 0;
}
sem_post(&(rstream->pipeLock));
duk_push_object(ctx); // [readable][nextWriteable]
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream_nextWriteablePipe)); // [readable][nextWriteable][ptrBuffer]
w = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
memset(w, 0, sizeof(ILibDuktape_readableStream_nextWriteablePipe));
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable]
// Now we need to emit a 'pipe' event on the writable that we just attached
duk_push_heapptr(ctx, w->writableStream); // [dest]
duk_get_prop_string(ctx, -1, "emit"); // [dest][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "pipe"); // [emit][this][pipe]
duk_push_this(ctx); // [emit][this][pipe][readable]
duk_call_method(ctx, 2); duk_pop(ctx); // ...
if (duk_has_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes))
{
// There are already associated pipes
duk_get_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable][prevWriteable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable][prevWriteable][ptr]
w->next = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable][nextWriteable][prevWriteable]
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable]
}
duk_dup(ctx, 0); // [readable][nextWriteable][stream]
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
{
// This is one of our writable stream implementation... So we can keep everything native
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [readable][nextWriteable][stream][buffer]
w->nativeWritable = Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable][nextWriteable][stream]
}
w->writableStream = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_Stream); // [readable][nextWriteable]
rstream->nextWriteable = w;
// Save to the readableStream
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable]
duk_dup(ctx, 0); // [readable][writable]
if (duk_has_prop_string(ctx, -1, "emit"))
{
duk_push_string(ctx, "emit"); // [readable][writable][key]
duk_push_string(ctx, "pipe"); // [readable][writable][key][eventName]
duk_dup(ctx, -4); // [readable][writable][key][eventName][readable]
if (duk_pcall_prop(ctx, -4, 2) != 0) // [readable][writable][retVal/err]
{
ILibDuktape_Process_UncaughtException(ctx);
}
duk_pop_2(ctx); // [readable]
}
else
{
duk_pop(ctx);
}
if (rstream->paused != 0)
{
void *chain = Duktape_GetChain(ctx);
if (chain != NULL)
{
// We are paused, so we should yield and resume... We yield, so in case the user tries to chain multiple pipes, it will chain first
void **tmp = (void**)ILibMemory_Allocate(sizeof(void*), 0, NULL, NULL);
tmp[0] = rstream;
ILibLifeTime_AddEx(ILibGetBaseTimer(chain), tmp, 0, ILibDuktape_readableStream_pipe_resumeFromTimer, ILibDuktape_readableStream_pipe_resumeFromTimer2);
ILibDuktape_Immediate(ctx, (void*[]) { rstream, duk_get_heapptr(ctx, 0) }, 1, ILibDuktape_ReadableStream_pipe_ResumeLater);
}
else
{
// Oops
duk_push_string(ctx, "ILibParsers_Duktape *MISSING*");
duk_throw(ctx);
return(DUK_RET_ERROR);
}
if (rstream->PipeHookHandler != NULL) { rstream->PipeHookHandler(rstream, duk_get_heapptr(ctx, 0), rstream->user); }
}
if (rstream->PipeHookHandler != NULL) { rstream->PipeHookHandler(rstream, rstream->user); }
duk_dup(ctx, 0);
return 1;
}
void ILibDuktape_readableStream_unpipe_later(duk_context *ctx, void ** args, int argsLen)
{
ILibDuktape_readableStream *data;
ILibDuktape_readableStream_nextWriteablePipe *w;
int i;
duk_size_t arrayLen;
duk_push_heapptr(ctx, args[0]); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop_2(ctx); // ...
sem_wait(&(data->pipeLock));
if (data->pipeInProgress != 0)
{
// We must yield, and try again, because there's an active dispatch going on
ILibDuktape_Immediate(ctx, (void*[]) { args[0], args[1] }, argsLen, ILibDuktape_readableStream_unpipe_later);
sem_post(&(data->pipeLock));
return;
}
else
{
i = 0;
w = data->nextWriteable;
if (argsLen > 1)
{
// Specific stream was specified in 'unpipe'
while (w != NULL)
{
if (w->writableStream == args[1])
{
// Emit the 'unpipe' event
duk_push_heapptr(ctx, args[1]); // [ws]
duk_get_prop_string(ctx, -1, "emit"); // [ws][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "unpipe"); // [emit][this][unpipe]
duk_push_heapptr(ctx, args[0]); // [emit][this][unpipe][readable]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readable.unpipe(): "); }
duk_pop(ctx); // ...
if (w->previous != NULL)
{
w->previous->next = w->next;
}
else
{
data->nextWriteable = w->next;
}
duk_push_heapptr(ctx, data->pipeArray); // [array]
arrayLen = duk_get_length(ctx, -1);
for (i = 0; i < (int)arrayLen; ++i)
{
duk_get_prop_index(ctx, -1, i); // [array][ws]
ILibDuktape_Push_ObjectStash(ctx); // [array][ws][stash]
if (duk_has_prop_string(ctx, -1, Duktape_GetStashKey(args[1])))
{
// Removing the entry from the Array
duk_pop_2(ctx); // [array]
duk_get_prop_string(ctx, -1, "splice"); // [array][splice]
duk_swap_top(ctx, -2); // [splice][this]
duk_push_int(ctx, i); // [splice][this][i]
duk_push_int(ctx, 1); // [splice][this][i][1]
duk_call_method(ctx, 2); // [undefined]
duk_pop(ctx); // ...
break;
}
duk_pop_2(ctx); // [array]
}
duk_pop(ctx); // ...
break;
}
w = w->next;
}
}
else
{
// 'unpipe' all pipes
w = data->nextWriteable;
while (w != NULL)
{
duk_push_heapptr(ctx, w->writableStream); // [ws]
duk_get_prop_string(ctx, -1, "emit"); // [ws][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "unpipe"); // [emit][this][unpipe]
duk_push_heapptr(ctx, args[0]); // [emit][this][unpipe][readable]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readable.unpipe(): "); }
duk_pop(ctx); // ...
w = w->next;
}
data->nextWriteable = NULL;
duk_push_heapptr(ctx, args[0]); // [readable]
duk_del_prop_string(ctx, -1, ILibDuktape_readableStream_PipeArray);
duk_push_array(ctx); // [readable][array]
data->pipeArray = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_PipeArray); // [readable]
duk_pop(ctx); // ...
}
}
data->unpipeInProgress = 0;
sem_post(&(data->pipeLock));
}
duk_ret_t ILibDuktape_readableStream_unpipe(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
ILibDuktape_readableStream *data;
ILibDuktape_readableStream_nextWriteablePipe *w, *prev;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
duk_push_this(ctx); // [readable]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
duk_pop(ctx); // [readable]
if (nargs == 0)
{
duk_del_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes);
data->nextWriteable = NULL;
}
else if (data->nextWriteable != NULL)
{
w = data->nextWriteable;
prev = NULL;
while (w != NULL)
{
if (w->writableStream == duk_get_heapptr(ctx, 0))
{
memset(w, 0, 2 * sizeof(void*));
if (data->nextWriteable == w)
{
//printf("Unpiping object: %p\n", (void*)w);
data->nextWriteable = w->next;
break;
}
else
{
prev->next = w->next;
break;
}
}
else
{
prev = w;
w = w->next;
}
}
}
sem_wait(&(data->pipeLock));
data->unpipeInProgress = 1;
sem_post(&(data->pipeLock));
// We need to pause first
duk_push_this(ctx); // [readable]
duk_get_prop_string(ctx, -1, "pause"); // [readable][pause]
duk_dup(ctx, -2); // [readable][pause][this]
duk_call_method(ctx, 0); duk_pop(ctx); // [readable]
// We must yield, and do this on the next event loop, because we can't unpipe if we're called from a pipe'ed call
ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, -1), nargs == 1 ? duk_get_heapptr(ctx, 0) : NULL }, nargs + 1, ILibDuktape_readableStream_unpipe_later);
return 0;
}
duk_ret_t ILibDuktape_readableStream_isPaused(duk_context *ctx)
@@ -710,11 +795,31 @@ void ILibDuktape_ReadableStream_PipeLockFinalizer(duk_context *ctx, void *stream
sem_destroy(&(ptrs->pipeLock));
duk_pop_2(ctx);
}
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user)
duk_ret_t ILibDuktape_ReadableStream_unshift(duk_context *ctx)
{
ILibDuktape_readableStream *rs;
duk_push_this(ctx); // [stream]
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
rs = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (rs->UnshiftHandler == NULL)
{
return(ILibDuktape_Error(ctx, "readable.unshift(): Not Implemented"));
}
else
{
duk_size_t bufferLen;
Duktape_GetBuffer(ctx, 0, &bufferLen);
duk_push_int(ctx, rs->UnshiftHandler(rs, (int)bufferLen, rs->user));
return(1);
}
}
ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, ILibDuktape_readableStream_UnShiftHandler OnUnshift, void *user)
{
ILibDuktape_readableStream *retVal;
ILibDuktape_EventEmitter *emitter;
ILibDuktape_PointerValidation_Init(ctx);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream)); // [obj][buffer]
duk_dup(ctx, -1); // [obj][buffer][buffer]
duk_put_prop_string(ctx, -3, ILibDuktape_readableStream_RSPTRS); // [obj][buffer]
@@ -722,9 +827,10 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
memset(retVal, 0, sizeof(ILibDuktape_readableStream));
duk_pop(ctx); // [obj]
duk_push_external_buffer(ctx); // [obj][extBuffer]
retVal->extBuffer = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, "_extBuffer"); // [obj]
duk_push_array(ctx); // [obj][array]
retVal->pipeArray = duk_get_heapptr(ctx, -1);
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_PipeArray); // [obj]
retVal->ctx = ctx;
retVal->chain = Duktape_GetChain(ctx);
@@ -732,6 +838,7 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
retVal->user = user;
retVal->PauseHandler = OnPause;
retVal->ResumeHandler = OnResume;
retVal->UnshiftHandler = OnUnshift;
sem_init(&(retVal->pipeLock), 0, 1);
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_ReadableStream_PipeLockFinalizer);
@@ -743,7 +850,8 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
ILibDuktape_CreateInstanceMethod(ctx, "pause", ILibDuktape_readableStream_pause, 0);
ILibDuktape_CreateInstanceMethod(ctx, "resume", ILibDuktape_readableStream_resume, 0);
ILibDuktape_CreateEventWithGetter(ctx, "pipe", ILibDuktape_readableStream_pipe_getter);
ILibDuktape_CreateInstanceMethod(ctx, "unpipe", ILibDuktape_readableStream_unpipe, DUK_VARARGS);
ILibDuktape_CreateProperty_InstanceMethod(ctx, "unpipe", ILibDuktape_readableStream_unpipe, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "isPaused", ILibDuktape_readableStream_isPaused, 0);
ILibDuktape_CreateInstanceMethod(ctx, "unshift", ILibDuktape_ReadableStream_unshift, 1);
return retVal;
}

View File

@@ -24,12 +24,14 @@ limitations under the License.
struct ILibDuktape_readableStream;
typedef void(*ILibDuktape_readableStream_PauseResumeHandler)(struct ILibDuktape_readableStream *sender, void *user);
typedef void(*ILibDuktape_readableStream_MethodHookHandler)(struct ILibDuktape_readableStream *sender, void *user);
typedef void(*ILibDuktape_readableStream_MethodHookHandler)(struct ILibDuktape_readableStream *sender, void *writableStream, void *user);
typedef int(*ILibDuktape_readableStream_UnShiftHandler)(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user);
typedef struct ILibDuktape_readableStream_nextWriteablePipe
{
void *writableStream;
void *nativeWritable;
struct ILibDuktape_readableStream_nextWriteablePipe *next;
struct ILibDuktape_readableStream_nextWriteablePipe *previous, *next;
}ILibDuktape_readableStream_nextWriteablePipe;
typedef struct ILibDuktape_readableStream
@@ -40,11 +42,9 @@ typedef struct ILibDuktape_readableStream
void *OnClose;
void *OnData;
void *OnEnd;
void *extBuffer;
char *extBuffer_buffer;
int extBuffer_bufferLen, extBuffer_Reserved;
void *user;
void *pipeArray;
ILibDuktape_readableStream_nextWriteablePipe *nextWriteable;
sem_t pipeLock;
#if defined(WIN32)
@@ -54,16 +54,21 @@ typedef struct ILibDuktape_readableStream
#else
int pipe_pendingCount; // No Atomic Built-ins... Use a Mutex
#endif
int pipeInProgress;
int unpipeInProgress;
int bypassValue;
int noPropagateEnd;
int paused;
void *paused_data;
ILibDuktape_readableStream_PauseResumeHandler PauseHandler;
ILibDuktape_readableStream_PauseResumeHandler ResumeHandler;
ILibDuktape_readableStream_MethodHookHandler PipeHookHandler;
ILibDuktape_readableStream_UnShiftHandler UnshiftHandler;
}ILibDuktape_readableStream;
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user);
#define ILibDuktape_ReadableStream_Init(ctx, OnPause, OnResume, user) ILibDuktape_InitReadableStream(ctx, OnPause, OnResume, user)
ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, ILibDuktape_readableStream_UnShiftHandler OnUnshift, void *user);
#define ILibDuktape_InitReadableStream(ctx, OnPause, OnResume, user) ILibDuktape_ReadableStream_InitEx(ctx, OnPause, OnResume, NULL, user)
#define ILibDuktape_ReadableStream_Init(ctx, OnPause, OnResume, user) ILibDuktape_ReadableStream_InitEx(ctx, OnPause, OnResume, NULL, user)
#define ILibDuktape_readableStream_SetPauseResumeHandlers(stream, PauseFunc, ResumeFunc, userObj) ((ILibDuktape_readableStream*)stream)->PauseHandler = PauseFunc; ((ILibDuktape_readableStream*)stream)->ResumeHandler = ResumeFunc; ((ILibDuktape_readableStream*)stream)->user = userObj;
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen);

View File

@@ -40,7 +40,6 @@ limitations under the License.
#include "ILibDuktape_EventEmitter.h"
#include "ILibDuktape_Helpers.h"
#include "../microstack/ILibParsers.h"
#include "../microstack/ILibProcessPipe.h"
#include "../microstack/ILibRemoteLogging.h"
#include "../microstack/ILibCrypto.h"
@@ -49,7 +48,6 @@ limitations under the License.
#include "ILibDuktape_WebRTC.h"
#include "ILibDuktape_Dgram.h"
#include "ILibDuktape_GenericMarshal.h"
#include "ILibDuktape_ProcessPipe.h"
#include "ILibDuktape_fs.h"
#include "ILibDuktape_Polyfills.h"
#include "ILibDuktape_SimpleDataStore.h"
@@ -58,6 +56,7 @@ limitations under the License.
#include "ILibDuktape_SHA256.h"
#include "ILibDuktape_EncryptionStream.h"
#include "ILibDuktape_ChildProcess.h"
#include "ILibDuktape_HECI.h"
#ifdef _POSIX
extern char **environ;
@@ -198,11 +197,11 @@ void ILibDuktape_ScriptContainer_CheckEmbedded(char **argv, char **script, int *
if (ILibString_EndsWith(argv[0], -1, ".exe", 4) == 0)
{
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", argv[0]);
tmpFile = fopen(ILibScratchPad, "rb");
fopen_s(&tmpFile, ILibScratchPad, "rb");
}
else
{
tmpFile = fopen(argv[0], "rb");
fopen_s(&tmpFile, argv[0], "rb");
}
#else
tmpFile = fopen(argv[0], "rb");
@@ -290,15 +289,23 @@ duk_ret_t ILibDuktape_ScriptContainer_Process_Argv0(duk_context *ctx)
// Polyfill process object:
duk_ret_t ILibDuktape_ScriptContainer_Process_Argv(duk_context *ctx)
{
duk_push_current_function(ctx);
int readOnly = Duktape_GetIntPropertyValue(ctx, -1, "readOnly", 0);
duk_push_this(ctx); // [process]
if (duk_has_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_ArgArray))
{
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_ArgArray); // [process][array]
duk_dup(ctx, -1); // [process][array][array]
if (readOnly != 0) { duk_dup(ctx, -1); } // [process][array][array]
}
else
{
duk_push_array(ctx); // [process][array]
if (readOnly == 0)
{
duk_dup(ctx, -1); // [process][array][array]
duk_put_prop_string(ctx, -3, ILibDuktape_ScriptContainer_Process_ArgArray); // [process][array]
}
}
return 1;
}
@@ -404,7 +411,10 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
ILibDuktape_EventEmitter_CreateEventEx(emitter, "uncaughtException");
ILibDuktape_CreateEventWithGetter(ctx, "argv0", ILibDuktape_ScriptContainer_Process_Argv0);
ILibDuktape_CreateEventWithGetter(ctx, "argv", ILibDuktape_ScriptContainer_Process_Argv);
duk_push_int(ctx, 1);
ILibDuktape_CreateEventWithGetterAndCustomProperty(ctx, "readOnly", "argv", ILibDuktape_ScriptContainer_Process_Argv);
duk_push_int(ctx, 0);
ILibDuktape_CreateEventWithGetterAndCustomProperty(ctx, "readOnly", "_argv", ILibDuktape_ScriptContainer_Process_Argv);
duk_put_prop_string(ctx, -2, "process"); // [g]
duk_pop(ctx); // ...
@@ -762,7 +772,7 @@ void ILibDuktape_ScriptContainer_OS_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "os", ILibDuktape_ScriptContainer_OS_Push);
}
extern void ILibDuktape_HttpStream_Init(duk_context *ctx);
duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(SCRIPT_ENGINE_SECURITY_FLAGS securityFlags, unsigned int executionTimeout, void *chain, char **argList, ILibSimpleDataStore *db, char *exePath, ILibProcessPipe_Manager pipeManager, ILibDuktape_HelperEvent exitHandler, void *exitUser)
{
duk_context *ctx = duk_create_heap(ILibDuktape_ScriptContainer_Engine_malloc, ILibDuktape_ScriptContainer_Engine_realloc, ILibDuktape_ScriptContainer_Engine_free, NULL, ILibDuktape_ScriptContainer_Engine_fatal);
@@ -800,12 +810,19 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(SCRIPT_ENG
if ((securityFlags & SCRIPT_ENGINE_NO_NETWORK_ACCESS) == 0)
{
ILibDuktape_WebRTC_Init(ctx); // WebRTC library (browser api)
ILibDuktape_http_init(ctx, chain); // HTTP library (node api)
ILibDuktape_http_init(ctx, chain); // HTTP-Digest library (node api)
ILibDuktape_net_init(ctx, chain); // Network library (node api)
ILibDuktape_DGram_Init(ctx); // Datagram Sockets
ILibDuktape_HttpStream_Init(ctx); // HTTP Library (node api)
}
if ((securityFlags & SCRIPT_ENGINE_NO_GENERIC_MARSHAL_ACCESS) == 0) { ILibDuktape_GenericMarshal_init(ctx); }
if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0) { ILibDuktape_ProcessPipe_Init(ctx, chain); ILibDuktape_ChildProcess_Init(ctx); }
if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0)
{
ILibDuktape_ChildProcess_Init(ctx);
#ifndef _NOHECI
ILibDuktape_HECI_Init(ctx);
#endif
}
if ((securityFlags & SCRIPT_ENGINE_NO_FILE_SYSTEM_ACCESS) == 0) { ILibDuktape_fs_init(ctx); }

View File

@@ -0,0 +1,561 @@
#include "duktape.h"
#include "ILibDuktape_Helpers.h"
#include "ILibDuktapeModSearch.h"
#include "ILibDuktape_DuplexStream.h"
#include "ILibDuktape_EventEmitter.h"
#ifndef MICROSTACK_NOTLS
#include <openssl/err.h>
#include <openssl/ssl.h>
#endif
#include "../microstack/ILibCrypto.h"
#define ILibDuktape_TlsStream_Ptr "\xFF_ILibDuktape_TLSSTREAM_PTR"
#define ILibDuktape_TlsStream2Cert "\xFF_TLS_CERT"
#define MEMORYCHUNKSIZE 4096
int ILibDuktape_TlsStream_ctx2stream = -1;
typedef struct ILibDuktape_TlsStream_Data
{
duk_context *ctx;
void *tlsObject;
void *chain;
int isClient;
ILibDuktape_EventEmitter *emitter;
char *decryptedBuffer;
int decryptedBuffer_mallocSize;
int decryptedBuffer_beginPointer;
int decryptedBuffer_endPointer;
int decryptedBuffer_unshiftedBytes;
int decryptedBuffer_maxSize;
int rejectUnauthorized;
void *OnVerify;
void *OnServerSNI;
int ProcessEncryptedBuffer_Active;
SSL* ssl;
SSL_CTX *ssl_ctx;
BIO *readBio, *writeBio;
BUF_MEM *readBioBuffer, *writeBioBuffer;
int TLSHandshakeCompleted;
ILibDuktape_DuplexStream *clear;
ILibDuktape_DuplexStream *encrypted;
int encrypted_unshiftBytes;
}ILibDuktape_TlsStream_Data;
void ILibDuktape_TlsStream_X509_PUSH(duk_context *ctx, X509* cert)
{
char hash[UTIL_SHA384_HASHSIZE];
char fingerprint[150];
util_keyhash2(cert, hash);
util_tohex2(hash, UTIL_SHA384_HASHSIZE, fingerprint);
duk_push_object(ctx); // [cert]
duk_push_string(ctx, fingerprint); // [cert][fingerprint]
duk_put_prop_string(ctx, -2, "fingerprint"); // [cert]
}
ILibTransport_DoneState ILibDuktape_TlsStream_ProcessEncryptedBuffer(ILibDuktape_TlsStream_Data *tlsdata)
{
int j, first = 1;
if (tlsdata->ProcessEncryptedBuffer_Active == 0)
{
tlsdata->ProcessEncryptedBuffer_Active = 1;
tlsdata->encrypted_unshiftBytes = 0;
BIO_clear_retry_flags(tlsdata->writeBio);
while ((j = (int)tlsdata->writeBioBuffer->length) > 0 && tlsdata->encrypted->readableStream->paused == 0)
{
if (first == 1)
{
first = 0;
}
else
{
tlsdata->encrypted_unshiftBytes = 0;
BIO_clear_retry_flags(tlsdata->writeBio);
}
do
{
ILibDuktape_DuplexStream_WriteData(tlsdata->encrypted, tlsdata->writeBioBuffer->data, (int)tlsdata->writeBioBuffer->length);
} while (tlsdata->encrypted_unshiftBytes > 0);
if (tlsdata->encrypted_unshiftBytes == 0)
{
tlsdata->writeBioBuffer->data += (int)tlsdata->writeBioBuffer->length;
tlsdata->writeBioBuffer->length = 0;
}
}
tlsdata->ProcessEncryptedBuffer_Active = 0;
return(tlsdata->writeBioBuffer->length > 0 ? ILibTransport_DoneState_INCOMPLETE : ILibTransport_DoneState_COMPLETE);
}
else
{
return(ILibTransport_DoneState_ERROR);
}
}
ILibTransport_DoneState ILibDuktape_TlsStream_Clear_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
SSL_write(data->ssl, buffer, bufferLen);
return(ILibDuktape_TlsStream_ProcessEncryptedBuffer(data));
}
void ILibDuktape_TlsStream_Clear_EndSink(ILibDuktape_DuplexStream *stream, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (ILibIsRunningOnChainThread(data->chain) != 0 && data->encrypted->writableStream->pipedReadable != NULL)
{
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [stream]
duk_get_prop_string(data->ctx, -1, "end"); // [stream][end]
duk_swap_top(data->ctx, -2); // [end][this]
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.unencrypted.end(): Error dispatching 'end' upstream "); }
duk_pop(data->ctx); // ...
}
}
void ILibDuktape_TlsStream_Clear_PauseSink_Chain(void *chain, void *user)
{
if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; }
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable]
duk_get_prop_string(data->ctx, -1, "pause"); // [readable][pause]
duk_swap_top(data->ctx, -2); // [pause][this]
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.pause(): Error pausing upstream object "); };
duk_pop(data->ctx); // ...
}
void ILibDuktape_TlsStream_Clear_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->PauseHandler != NULL)
{
data->encrypted->writableStream->pipedReadable_native->paused = 1;
data->encrypted->writableStream->pipedReadable_native->PauseHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user);
}
else if (data->encrypted->writableStream->pipedReadable != NULL)
{
if (ILibIsRunningOnChainThread(data->chain) != 0)
{
ILibDuktape_TlsStream_Clear_PauseSink_Chain(NULL, data);
}
else
{
// We're on the wrong thread to resume the upstream object
ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_PauseSink_Chain, data);
}
}
}
void ILibDuktape_TlsStream_Clear_ResumeSink_Chain(void *chain, void *user)
{
if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; }
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable]
duk_get_prop_string(data->ctx, -1, "resume"); // [readable][resume]
duk_swap_top(data->ctx, -2); // [resume][this]
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.resume(): Error resuming upstream object "); };
duk_pop(data->ctx); // ...
}
void ILibDuktape_TlsStream_Clear_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->ResumeHandler != NULL)
{
data->encrypted->writableStream->pipedReadable_native->paused = 0;
data->encrypted->writableStream->pipedReadable_native->ResumeHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user);
}
else if (data->encrypted->writableStream->pipedReadable != NULL)
{
if (ILibIsRunningOnChainThread(data->chain) != 0)
{
ILibDuktape_TlsStream_Clear_ResumeSink_Chain(NULL, data);
}
else
{
// We're on the wrong thread to resume the upstream object
ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_ResumeSink_Chain, data);
}
}
}
int ILibDuktape_TlsStream_Clear_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (unshiftBytes == data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer)
{
data->decryptedBuffer_unshiftedBytes = -1;
}
else
{
data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer - unshiftBytes;
data->decryptedBuffer_unshiftedBytes = unshiftBytes;
}
return(unshiftBytes);
}
ILibTransport_DoneState ILibDuktape_TlsStream_Encrypted_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
int j;
//int len = BIO_write(data->writeBio, buffer, bufferLen);
BIO_write(SSL_get_rbio(data->ssl), buffer, bufferLen);
int sslerror;
if (data->TLSHandshakeCompleted == 0)
{
switch ((sslerror = SSL_do_handshake(data->ssl)))
{
case 0:
// Handshake Failed!
while ((sslerror = ERR_get_error()) != 0)
{
ERR_error_string_n(sslerror, ILibScratchPad, sizeof(ILibScratchPad));
}
// TODO: We should probably do something
break;
case 1:
data->TLSHandshakeCompleted = 1;
if (ILibIsRunningOnChainThread(data->chain) != 0)
{
// We're on the Duktape Thread
duk_push_heapptr(data->ctx, data->tlsObject); // [TLS]
duk_get_prop_string(data->ctx, -1, "emit"); // [TLS][emit]
duk_swap_top(data->ctx, -2); // [emit][this]
duk_push_string(data->ctx, "connect"); // [emit][this][connect]
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.connect(): "); }
duk_pop(data->ctx); // ...
}
else
{
// Need to context switch to the Duktape Thread
}
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
break;
default:
// SSL_WANT_READ most likely
sslerror = SSL_get_error(data->ssl, sslerror);
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
break;
}
return(ILibTransport_DoneState_COMPLETE);
}
else
{
while ((j = SSL_read(data->ssl, data->decryptedBuffer + data->decryptedBuffer_endPointer, data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer)) > 0)
{
// We got new TLS Data
if (j > 0)
{
data->decryptedBuffer_endPointer += j;
if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer == 0)
{
data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize);
if((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254);
}
}
}
if (j < 0)
{
sslerror = SSL_get_error(data->ssl, j);
if (data->writeBioBuffer->length > 0)
{
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
}
}
}
//
// Event data up the stack, to process any data that is available
//
do
{
data->decryptedBuffer_unshiftedBytes = 0;
ILibDuktape_DuplexStream_WriteData(data->clear, data->decryptedBuffer + data->decryptedBuffer_beginPointer, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer);
} while (data->decryptedBuffer_unshiftedBytes > 0);
if (data->decryptedBuffer_unshiftedBytes == 0) { data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer = 0; }
//
// Check to see if we need to move any data, to maximize buffer space
//
if (data->decryptedBuffer_beginPointer != 0)
{
//
// We can save some cycles by moving the data back to the top
// of the buffer, instead of just allocating more memory.
//
char *temp = data->decryptedBuffer + data->decryptedBuffer_beginPointer;
memmove_s(data->decryptedBuffer, data->decryptedBuffer_mallocSize, temp, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer);
data->decryptedBuffer_endPointer -= data->decryptedBuffer_beginPointer;
data->decryptedBuffer_beginPointer = 0;
}
//
// Check to see if we should grow the buffer
//
if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer < 1024 && (data->decryptedBuffer_maxSize == 0 || data->decryptedBuffer_mallocSize < data->decryptedBuffer_maxSize))
{
data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize);
if ((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254);
}
return(data->clear->readableStream->paused == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
}
void ILibDuktape_TlsStream_Encrypted_EndSink(ILibDuktape_DuplexStream *stream, void *user)
{
}
void ILibDuktape_TlsStream_Encrypted_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
{
// Don't need to do anythign, becuase the 'ILibDuktape_TlsStream_ProcessEncryptedBuffer' will exit the processing loop when paused
}
void ILibDuktape_TlsStream_Encrypted_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
}
int ILibDuktape_TlsStream_Encrypted_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
{
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
if (unshiftBytes == data->writeBioBuffer->length)
{
data->encrypted_unshiftBytes = -1;
}
else
{
data->writeBioBuffer->data += ((int)data->writeBioBuffer->length - unshiftBytes);
data->writeBioBuffer->length = unshiftBytes;
}
return(unshiftBytes);
}
int ILibDuktape_TlsStream_verify(int preverify_ok, X509_STORE_CTX *ctx)
{
STACK_OF(X509) *certChain = X509_STORE_CTX_get_chain(ctx);
SSL *ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(ssl, ILibDuktape_TlsStream_ctx2stream);
int i;
int retVal = 0;
if (data->rejectUnauthorized != 0) { return(preverify_ok); }
if (data->OnVerify == NULL) { return 1; }
duk_push_heapptr(data->ctx, data->OnVerify); // [func]
duk_push_heapptr(data->ctx, data->emitter->object); // [func][this]
duk_push_array(data->ctx); // [func][this][certs]
for (i = 0; i < sk_X509_num(certChain); ++i)
{
ILibDuktape_TlsStream_X509_PUSH(data->ctx, sk_X509_value(certChain, i)); // [func][this][certs][cert]
duk_put_prop_index(data->ctx, -2, i); // [func][this][certs]
}
retVal = duk_pcall_method(data->ctx, 1) == 0 ? 1 : 0; // [undefined]
duk_pop(data->ctx); // ...
return retVal;
}
duk_ret_t ILibDuktape_TlsStream_Finalizer(duk_context *ctx)
{
void *chain = Duktape_GetChain(ctx);
duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream_Ptr);
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL);
struct util_cert *cert = NULL;
if (data->ssl != NULL) { SSL_free(data->ssl); }
if (data->ssl_ctx != NULL) { SSL_CTX_free(data->ssl_ctx); }
if (data->decryptedBuffer != NULL) { free(data->decryptedBuffer); }
if (duk_has_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert))
{
duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert);
cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
util_freecert(cert);
}
ILibDuktape_InValidatePointer(chain, data);
return(0);
}
duk_ret_t ILibDuktape_TlsStream_serverSNI_cb(duk_context *ctx)
{
duk_push_current_function(ctx);
duk_get_prop_string(ctx, -1, "\xFF_ptr");
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)duk_get_pointer(ctx, -1);
if (duk_has_prop_string(ctx, 1, "pfx") && duk_has_prop_string(ctx, 1, "passphrase"))
{
char *passphrase = Duktape_GetStringPropertyValue(ctx, 1, "passphrase", "");
char *pfx;
duk_size_t pfxLen;
duk_get_prop_string(ctx, 1, "pfx");
pfx = (char*)Duktape_GetBuffer(ctx, -1, &pfxLen);
duk_push_heapptr(ctx, data->tlsObject); // [TLS]
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][cert]
struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); }
SSL_CTX *newCTX = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_set_options(newCTX, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
SSL_CTX_set_verify(newCTX, SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */
SSL_CTX_use_certificate(newCTX, cert->x509);
SSL_CTX_use_PrivateKey(newCTX, cert->pkey);
SSL_set_SSL_CTX(data->ssl, newCTX);
duk_get_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS][cert][oldCert]
util_freecert((struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL));
duk_pop(ctx); // [TLS][cert]
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS]
SSL_CTX_free(data->ssl_ctx);
data->ssl_ctx = newCTX;
}
return(0);
}
static int ILibDuktape_TlsStream_serverSNI_callback(SSL *s, int *ad, void *arg)
{
const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(s, ILibDuktape_TlsStream_ctx2stream);
int retVal = SSL_TLSEXT_ERR_OK;
duk_push_heapptr(data->ctx, data->OnServerSNI); // [func]
duk_push_heapptr(data->ctx, data->tlsObject); // [func][this]
duk_push_string(data->ctx, servername); // [func][this][servername]
duk_push_c_function(data->ctx, ILibDuktape_TlsStream_serverSNI_cb, 2); // [func][this][servername][cb]
duk_push_pointer(data->ctx, data); // [func][this][servername][cb][ptr]
duk_put_prop_string(data->ctx, -2, "\xFF_ptr"); // [func][this][servername][cb]
if (duk_pcall_method(data->ctx, 2) != 0)
{
ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.serverSNI(): Error dispatching callback ");
retVal = SSL_TLSEXT_ERR_NOACK;
}
duk_pop(data->ctx); // ...
return(retVal);
}
duk_ret_t ILibDuktape_TlsStream_create(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
char *sniHost = NULL;
void *chain = Duktape_GetChain(ctx);
int status, requestCert;
duk_push_current_function(ctx);
int isClient = Duktape_GetIntPropertyValue(ctx, -1, "isClient", 0);
ILibDuktape_TlsStream_Data *data;
duk_push_object(ctx); // [TLS]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_TlsStream_Finalizer);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_TlsStream_Data)); // [TLS][struct]
data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream_Ptr); // [TLS]
memset(data, 0, sizeof(ILibDuktape_TlsStream_Data));
ILibDuktape_ValidatePointer(chain, data);
data->emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "connect");
data->tlsObject = duk_get_heapptr(ctx, -1);
data->decryptedBuffer_mallocSize = MEMORYCHUNKSIZE;
data->decryptedBuffer = (char*)ILibMemory_Allocate(data->decryptedBuffer_mallocSize, 0, NULL, NULL);
data->rejectUnauthorized = Duktape_GetIntPropertyValue(ctx, 0, "rejectUnauthorized", 1);
requestCert = Duktape_GetIntPropertyValue(ctx, 0, "requestCert", 0);
data->OnVerify = Duktape_GetHeapptrProperty(ctx, 0, isClient != 0 ? "checkServerIdentity" : "checkClientIdentity");
duk_push_object(ctx); // [TLS][clear]
ILibDuktape_WriteID(ctx, "TlsStream.decrypted");
data->clear = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Clear_WriteSink, ILibDuktape_TlsStream_Clear_EndSink,
ILibDuktape_TlsStream_Clear_PauseSink, ILibDuktape_TlsStream_Clear_ResumeSink, ILibDuktape_TlsStream_Clear_UnshiftSink, data);
ILibDuktape_CreateReadonlyProperty(ctx, "clear"); // [TLS]
duk_push_object(ctx); // [TLS][encrypted]
ILibDuktape_WriteID(ctx, "TlsStream.encrypted");
data->encrypted = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Encrypted_WriteSink, ILibDuktape_TlsStream_Encrypted_EndSink,
ILibDuktape_TlsStream_Encrypted_PauseSink, ILibDuktape_TlsStream_Encrypted_ResumeSink, ILibDuktape_TlsStream_Encrypted_UnshiftSink, data);
ILibDuktape_CreateReadonlyProperty(ctx, "encrypted"); // [TLS]
data->ctx = ctx;
data->chain = Duktape_GetChain(ctx);
data->ssl_ctx = isClient != 0 ? SSL_CTX_new(SSLv23_client_method()) : SSL_CTX_new(SSLv23_server_method());
SSL_CTX_set_options(data->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
if (isClient != 0 || requestCert != 0) { SSL_CTX_set_verify(data->ssl_ctx, isClient != 0 ? SSL_VERIFY_PEER : SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */ }
if (nargs > 0 && duk_is_object(ctx, 0))
{
sniHost = Duktape_GetStringPropertyValue(ctx, 0, "host", NULL);
data->OnServerSNI = Duktape_GetHeapptrProperty(ctx, 0, "SNICallback");
if (duk_has_prop_string(ctx, 0, "pfx") && duk_has_prop_string(ctx, 0, "passphrase"))
{
// PFX certificate was passed in thru Options
char *pfx, *passphrase;
duk_size_t pfxLen, passphraseLen;
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][buff]
struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS]
duk_get_prop_string(ctx, 0, "pfx"); // [pfx]
duk_get_prop_string(ctx, 0, "passphrase"); // [pfx][passphrase]
pfx = (char*)Duktape_GetBuffer(ctx, -2, &pfxLen);
passphrase = (char*)Duktape_GetBuffer(ctx, -1, &passphraseLen);
if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); }
SSL_CTX_use_certificate(data->ssl_ctx, cert->x509);
SSL_CTX_use_PrivateKey(data->ssl_ctx, cert->pkey);
duk_pop_2(ctx);
}
}
data->ssl = SSL_new(data->ssl_ctx);
data->TLSHandshakeCompleted = 0;
data->readBio = BIO_new(BIO_s_mem());
data->writeBio = BIO_new(BIO_s_mem());
BIO_get_mem_ptr(data->readBio, &(data->readBioBuffer));
BIO_get_mem_ptr(data->writeBio, &(data->writeBioBuffer));
BIO_set_mem_eof_return(data->readBio, -1);
BIO_set_mem_eof_return(data->writeBio, -1);
data->readBioBuffer->length = 0;
SSL_set_bio(data->ssl, data->readBio, data->writeBio);
if (ILibDuktape_TlsStream_ctx2stream < 0)
{
ILibDuktape_TlsStream_ctx2stream = SSL_get_ex_new_index(0, "ILibDuktape_TlsStream index", NULL, NULL, NULL);
}
SSL_set_ex_data(data->ssl, ILibDuktape_TlsStream_ctx2stream, data);
if (isClient != 0)
{
if (sniHost != NULL) { SSL_set_tlsext_host_name(data->ssl, sniHost); }
SSL_set_connect_state(data->ssl);
status = SSL_do_handshake(data->ssl);
if (status <= 0) { status = SSL_get_error(data->ssl, status); }
if (status == SSL_ERROR_WANT_READ)
{
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
// We're going to drop out now, becuase we need to check for received data
}
}
else
{
if (data->OnServerSNI != NULL)
{
SSL_CTX_set_tlsext_servername_callback(data->ssl_ctx, ILibDuktape_TlsStream_serverSNI_callback);
}
SSL_set_accept_state(data->ssl); // Setup server SSL state
}
return(1);
}
void ILibDuktape_TlsStream_PUSH(duk_context *ctx, void *chain)
{
duk_push_object(ctx);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 1, "createClient", ILibDuktape_TlsStream_create, DUK_VARARGS);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 0, "createServer", ILibDuktape_TlsStream_create, DUK_VARARGS);
}
void ILibDuktape_TlsStream_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "TlsStream", ILibDuktape_TlsStream_PUSH);
}

View File

@@ -235,6 +235,7 @@ duk_ret_t ILibDuktape_WritableStream_End(duk_context *ctx)
duk_dup(ctx, 2); // [stream][flush]
duk_put_prop_string(ctx, -2, "_Finish"); // [stream]
}
stream->endBytes = (int)bufferLen;
if (stream->WriteSink(stream, buffer, (int)bufferLen, stream->WriteSink_User) == ILibTransport_DoneState_INCOMPLETE)
{
// Incomplete, wait for SendOK
@@ -265,11 +266,40 @@ duk_ret_t ILibDuktape_WritableStream_End_Getter(duk_context *ctx)
duk_push_c_function(ctx, ILibDuktape_WritableStream_End, DUK_VARARGS);
return 1;
}
duk_ret_t ILibDuktape_WritableStream_UnPipeSink(duk_context *ctx)
{
duk_dup(ctx, 0);
duk_push_this(ctx);
//printf("UNPIPE: [%s] => X => [%s]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"));
return(0);
}
duk_ret_t ILibDuktape_WritableStream_PipeSink(duk_context *ctx)
{
ILibDuktape_WritableStream *ws;
duk_push_this(ctx); // [writable]
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS);
ws = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
if (duk_has_prop_string(ctx, 0, "\xFF_ReadableStream_PTRS"))
{
duk_get_prop_string(ctx, 0, "\xFF_ReadableStream_PTRS"); // [writable][rs]
ws->pipedReadable_native = (struct ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
}
ws->pipedReadable = duk_get_heapptr(ctx, 0);
duk_dup(ctx, 0);
duk_push_this(ctx);
//printf("PIPE: [%s] => [%s]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"));
return(0);
}
ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, ILibDuktape_WritableStream_WriteHandler WriteHandler, ILibDuktape_WritableStream_EndHandler EndHandler, void *user)
{
ILibDuktape_WritableStream *retVal;
ILibDuktape_EventEmitter *emitter;
ILibDuktape_PointerValidation_Init(ctx);
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_WritableStream)); // [obj][buffer]
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL); // [obj][buffer]
memset(retVal, 0, sizeof(ILibDuktape_WritableStream));
@@ -283,7 +313,8 @@ ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, IL
retVal->WriteSink_User = user;
emitter = ILibDuktape_EventEmitter_Create(ctx);
ILibDuktape_EventEmitter_CreateEvent(emitter, "pipe", &(retVal->OnPipe));
ILibDuktape_EventEmitter_CreateEventEx(emitter, "pipe");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "unpipe");
ILibDuktape_EventEmitter_CreateEvent(emitter, "drain", &(retVal->OnDrain));
ILibDuktape_EventEmitter_CreateEvent(emitter, "finish", &(retVal->OnFinish));
ILibDuktape_EventEmitter_CreateEvent(emitter, "error", &(retVal->OnError));
@@ -291,5 +322,7 @@ ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, IL
ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_WritableStream_Write, DUK_VARARGS);
ILibDuktape_CreateEventWithGetter(ctx, "end", ILibDuktape_WritableStream_End_Getter);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "pipe", ILibDuktape_WritableStream_PipeSink);
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "unpipe", ILibDuktape_WritableStream_UnPipeSink);
return retVal;
}

View File

@@ -23,16 +23,19 @@ limitations under the License.
struct ILibDuktape_WritableStream;
typedef ILibTransport_DoneState(*ILibDuktape_WritableStream_WriteHandler)(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user);
typedef void(*ILibDuktape_WritableStream_EndHandler)(struct ILibDuktape_WritableStream *stream, void *user);
typedef void(*ILibDuktape_WriteableStream_WriteFlushNative)(struct ILibDuktape_WritableStream *stream, void *user);
typedef int(*ILibDuktape_WriteableStream_WriteFlushNative)(struct ILibDuktape_WritableStream *stream, void *user);
typedef void(*ILibDuktape_WritableStream_PipeHandler)(struct ILibDuktape_WritableStream *stream, void *readableSource, void *user);
struct ILibDuktape_readableStream;
typedef struct ILibDuktape_WritableStream
{
int JSCreated;
duk_context *ctx;
void *obj;
void *OnDrain;
void *OnWriteFlush;
void *OnPipe;
ILibDuktape_WriteableStream_WriteFlushNative OnWriteFlushEx;
void *OnWriteFlushEx_User;
@@ -42,8 +45,12 @@ typedef struct ILibDuktape_WritableStream
ILibDuktape_WritableStream_WriteHandler WriteSink;
ILibDuktape_WritableStream_EndHandler EndSink;
ILibDuktape_WritableStream_PipeHandler PipeSink;
void *pipedReadable;
struct ILibDuktape_readableStream* pipedReadable_native;
void *WriteSink_User;
int endBytes;
int Reserved;
} ILibDuktape_WritableStream;

View File

@@ -1229,6 +1229,7 @@ duk_ret_t ILibDuktape_fs_readFileSync(duk_context *ctx)
duk_push_fixed_buffer(ctx, (duk_size_t)fileLen);
ignore_result(fread(Duktape_GetBuffer(ctx, -1, NULL), 1, (size_t)fileLen, f));
fclose(f);
duk_push_buffer_object(ctx, -1, 0, (duk_size_t)fileLen, DUK_BUFOBJ_NODEJS_BUFFER);
return(1);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,7 @@ limitations under the License.
#include "microstack/ILibParsers.h"
#define ILibDuktape_SOCKET2OPTIONS "\xFF_NET_SOCKET2OPTIONS"
void ILibDuktape_net_init(duk_context *ctx, void *chain);
typedef struct ILibDuktape_globalTunnel_data

View File

@@ -182,7 +182,7 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
duk_pop_2(ctx); // [this]
self = duk_get_heapptr(ctx, -1);
if (data->eventTable == NULL) { return 0; } // This probably means the finalizer was already run on the eventEmitter
if (data->eventTable == NULL) { duk_push_false(ctx); return(1); } // This probably means the finalizer was already run on the eventEmitter
eventList = ILibHashtable_Get(data->eventTable, NULL, name, (int)nameLen);
if (eventList == NULL) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Event '%s' not found", name); }
@@ -245,8 +245,8 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
}
duk_pop(ctx); // ...
}
return 0;
duk_push_boolean(ctx, i > 1 ? 1 : 0);
return(1);
}
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
{
@@ -261,13 +261,13 @@ int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *ev
return retVal;
}
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs)
int ILibDuktape_EventEmitter_AddOnceEx3(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
{
int retVal = 1;
duk_dup(ctx, idx); // [obj]
ILibDuktape_Push_ObjectStash(ctx); // [obj][stash]
duk_push_c_function(ctx, func, funcArgs); // [obj][stash][func]
duk_push_c_function(ctx, func, DUK_VARARGS); // [obj][stash][func]
duk_dup(ctx, -1); // [obj][stash][func][func]
duk_put_prop_string(ctx, -3, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [obj][stash][func]
duk_get_prop_string(ctx, -3, "once"); // [obj][stash][func][once]
@@ -316,10 +316,12 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
ILibDuktape_EventEmitter *data;
int once;
void *eventList, *node, *dispatcher, **hptr;
int i, count;
int i, count, prepend;
duk_push_current_function(ctx);
once = Duktape_GetIntPropertyValue(ctx, -1, "once", 0);
prepend = Duktape_GetIntPropertyValue(ctx, -1, "prepend", 0);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject);
@@ -334,7 +336,7 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
dispatcher = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_SetterFunc, propName, (int)propNameLen);
if (dispatcher == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.on(): Internal error with Event '%s'", propName)); }
node = ILibLinkedList_AddTail(eventList, callback);
node = prepend ? ILibLinkedList_AddHead(eventList, callback) : ILibLinkedList_AddTail(eventList, callback);
((int*)ILibLinkedList_GetExtendedMemory(node))[0] = once;
data->totalListeners[0]++;
@@ -462,8 +464,11 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
retVal->object = duk_get_heapptr(ctx, -1);
retVal->eventTable = ILibHashtable_Create();
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 1, "once", ILibDuktape_EventEmitter_on, 2);
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 0, "on", ILibDuktape_EventEmitter_on, 2);
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "once", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 1), "prepend", duk_push_int_ex(ctx, 0));
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "on", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 0), "prepend", duk_push_int_ex(ctx, 0));
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "prependOnceListener", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 1), "prepend", duk_push_int_ex(ctx, 1));
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "prependListener", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 0), "prepend", duk_push_int_ex(ctx, 1));
ILibDuktape_CreateInstanceMethod(ctx, "removeListener", ILibDuktape_EventEmitter_removeListener, 2);
ILibDuktape_CreateInstanceMethod(ctx, "removeAllListeners", ILibDuktape_EventEmitter_removeAllListeners, DUK_VARARGS);
ILibDuktape_CreateInstanceMethod(ctx, "emit", ILibDuktape_EventEmitter_emit, DUK_VARARGS);
@@ -816,6 +821,15 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits_addMethod(duk_context *ctx)
ILibDuktape_CreateProperty_InstanceMethodEx(ctx, (char*)duk_require_string(ctx, 0), duk_require_heapptr(ctx, 1));
return(0);
}
duk_ret_t ILibDuktape_EventEmitter_EmitterUtils_Finalizer(duk_context *ctx)
{
duk_get_prop_string(ctx, 0, "\xFF_MainObject"); // [obj]
duk_get_prop_string(ctx, -1, "emit"); // [obj][emit]
duk_swap_top(ctx, -2); // [emit][this]
duk_push_string(ctx, "~"); // [emit][this][~]
duk_call_method(ctx, 1);
return(0);
}
duk_ret_t ILibDuktape_EventEmitter_Inherits(duk_context *ctx)
{
ILibDuktape_EventEmitter *emitter;
@@ -823,12 +837,16 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits(duk_context *ctx)
duk_dup(ctx, 0); // [target]
emitter = ILibDuktape_EventEmitter_Create(ctx);
duk_push_object(ctx); // [target][emitterUtils]
duk_dup(ctx, -2); // [target][emitterUtils][target]
duk_put_prop_string(ctx, -2, "\xFF_MainObject"); // [target][emitterUtils]
duk_dup(ctx, -1); // [target][emitterUtils][dup]
duk_put_prop_string(ctx, -3, "\xFF_emitterUtils"); // [target][emitterUtils]
duk_push_pointer(ctx, emitter); // [target][emitterUtils][ptr]
duk_put_prop_string(ctx, -2, "emitter"); // [target][emitterUtils]
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_EventEmitter_EmitterUtils_Finalizer);
ILibDuktape_CreateInstanceMethod(ctx, "createEvent", ILibDuktape_EventEmitter_Inherits_createEvent, 1);
ILibDuktape_CreateInstanceMethod(ctx, "addMethod", ILibDuktape_EventEmitter_Inherits_addMethod, 2);
ILibDuktape_EventEmitter_CreateEventEx(emitter, "~");
return 1;
}
void ILibDuktape_EventEmitter_PUSH(duk_context *ctx, void *chain)
@@ -840,3 +858,54 @@ void ILibDuktape_EventEmitter_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "events", ILibDuktape_EventEmitter_PUSH);
}
duk_ret_t ILibDuktape_EventEmitter_ForwardEvent_Sink(duk_context *ctx)
{
int nargs = duk_get_top(ctx);
int i;
char *name;
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "targetObject"); // [func][obj]
duk_get_prop_string(ctx, -1, "emit"); // [func][obj][emit]
duk_swap_top(ctx, -2); // [func][emit][this]
duk_get_prop_string(ctx, -3, "targetName"); // [func][emit][this][name]
name = (char*)duk_get_string(ctx, -1);
for (i = 0; i < nargs; ++i)
{
duk_dup(ctx, i); // [func][emit][this][name][...args...]
}
if (duk_pcall_method(ctx, 1 + nargs) != 0) { return(ILibDuktape_Error(ctx, "EventEmitter.ForwardEvent() [%s]: %s", name, duk_safe_to_string(ctx, -1))); }
return(0);
}
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName)
{
void *target;
duk_dup(ctx, eventTargetIndex); // [targetObject]
target = duk_get_heapptr(ctx, -1);
duk_pop(ctx); // ...
duk_dup(ctx, eventSourceIndex); // [sourceObject]
duk_get_prop_string(ctx, -1, "on"); // [sourceObject][on]
duk_swap_top(ctx, -2); // [on][this]
duk_push_string(ctx, sourceEventName); // [on][this][name]
duk_push_c_function(ctx, ILibDuktape_EventEmitter_ForwardEvent_Sink, DUK_VARARGS); // [on][this][name][sink]
duk_push_heapptr(ctx, target); // [on][this][name][sink][targetObject]
duk_put_prop_string(ctx, -2, "targetObject"); // [on][this][name][sink]
duk_push_string(ctx, targetEventName); // [on][this][name][sink][targetName]
duk_put_prop_string(ctx, -2, "targetName"); // [on][this][name][sink]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "EventEmitter_ForwardEvent(): "); }
duk_pop(ctx); // ...
}
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
{
int retVal = 1;
duk_dup(ctx, idx); // [object]
duk_get_prop_string(ctx, -1, "on"); // [object][on]
duk_swap_top(ctx, -2); // [on][this]
duk_push_string(ctx, eventName); // [on][this][name]
duk_push_c_function(ctx, func, DUK_VARARGS); // [on][this][name][func]
if (duk_pcall_method(ctx, 2) != 0) { retVal = 0; }
duk_pop(ctx); // ...
return(retVal);
}

View File

@@ -621,15 +621,9 @@ void ILibAsyncServerSocket_RemoveFromChain(ILibAsyncServerSocket_ServerModule se
*/
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(void *Chain, int MaxConnections, unsigned short PortNumber, int initialBufferSize, int loopbackFlag, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize)
{
int i;
int ra = 1;
int off = 0;
int receivingAddressLength = sizeof(struct sockaddr_in6);
struct sockaddr_in6 localif;
struct sockaddr_in6 localAddress;
struct ILibAsyncServerSocketModule *RetVal;
memset(&localif, 0, sizeof(struct sockaddr_in6));
if (loopbackFlag != 2 && ILibDetectIPv6Support())
{
// Setup the IPv6 any or loopback address, this socket will also work for IPv4 traffic on IPv6 stack
@@ -641,7 +635,7 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(v
{
// IPv4-only detected
localif.sin6_family = AF_INET;
#ifdef WINSOCK2
#ifdef WIN32
((struct sockaddr_in*)&localif)->sin_addr.S_un.S_addr = htonl((loopbackFlag != 0 ? INADDR_LOOPBACK : INADDR_ANY));
#else
((struct sockaddr_in*)&localif)->sin_addr.s_addr = htonl((loopbackFlag != 0 ? INADDR_LOOPBACK : INADDR_ANY));
@@ -649,6 +643,17 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(v
((struct sockaddr_in*)&localif)->sin_port = htons(PortNumber);
}
return(ILibCreateAsyncServerSocketModuleWithMemoryEx(Chain, MaxConnections, initialBufferSize, (struct sockaddr*)&localif, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK, ServerUserMappedMemorySize, SessionUserMappedMemorySize));
}
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx(void *Chain, int MaxConnections, int initialBufferSize, struct sockaddr *local, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize)
{
int i;
int ra = 1;
int off = 0;
int receivingAddressLength = sizeof(struct sockaddr_in6);
struct ILibAsyncServerSocketModule *RetVal;
struct sockaddr_in6 localAddress;
// Instantiate a new AsyncServer module
RetVal = (struct ILibAsyncServerSocketModule*)ILibChain_Link_Allocate(sizeof(struct ILibAsyncServerSocketModule), ServerUserMappedMemorySize);
@@ -664,15 +669,14 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(v
RetVal->MaxConnection = MaxConnections;
RetVal->AsyncSockets = (void**)malloc(MaxConnections * sizeof(void*));
if (RetVal->AsyncSockets == NULL) { free(RetVal); ILIBMARKPOSITION(253); return NULL; }
RetVal->portNumber = (unsigned short)PortNumber;
RetVal->loopbackFlag = loopbackFlag;
RetVal->initialPortNumber = PortNumber;
RetVal->portNumber = ntohs(((struct sockaddr_in6*)local)->sin6_port);
RetVal->initialPortNumber = RetVal->portNumber;
// Get our listening socket
if ((RetVal->ListenSocket = socket(localif.sin6_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { free(RetVal->AsyncSockets); free(RetVal); return 0; }
if ((RetVal->ListenSocket = socket(((struct sockaddr_in6*)local)->sin6_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { free(RetVal->AsyncSockets); free(RetVal); return 0; }
// Setup the IPv6 & IPv4 support on same socket
if (localif.sin6_family == AF_INET6) if (setsockopt(RetVal->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
if (((struct sockaddr_in6*)local)->sin6_family == AF_INET6) if (setsockopt(RetVal->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
#ifdef SO_NOSIGPIPE
setsockopt(RetVal->ListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&ra, sizeof(int)); // Turn off SIGPIPE if writing to disconnected socket
@@ -688,9 +692,9 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(v
// Bind the socket
#if defined(WIN32)
if (bind(RetVal->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { closesocket(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { closesocket(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
#else
if (bind(RetVal->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
#endif
// Fetch the local port number

View File

@@ -114,6 +114,8 @@ extern const int ILibMemory_ASYNCSERVERSOCKET_CONTAINERSIZE;
#define ILibCreateAsyncServerSocketModule(Chain, MaxConnections, PortNumber, initialBufferSize, loopbackFlag, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK) ILibCreateAsyncServerSocketModuleWithMemory(Chain, MaxConnections, PortNumber, initialBufferSize, loopbackFlag, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK, 0, 0)
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(void *Chain, int MaxConnections, unsigned short PortNumber, int initialBufferSize, int loopbackFlag, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize);
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx(void *Chain, int MaxConnections, int initialBufferSize, struct sockaddr* local, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize);
void *ILibAsyncServerSocket_GetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule);
void ILibAsyncServerSocket_SetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *user);

View File

@@ -1960,7 +1960,7 @@ void ILibAsyncSocket_ModuleOnConnect(ILibAsyncSocket_SocketModule socketModule)
\param ssl_ctx SSL_CTX Context object
\param server ILibAsyncSocket_TLS_Mode Configuration
*/
SSL* ILibAsyncSocket_SetSSLContext(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server)
SSL* ILibAsyncSocket_SetSSLContextEx(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server, char *hostName)
{
if (socketModule != NULL)
{
@@ -1992,6 +1992,7 @@ SSL* ILibAsyncSocket_SetSSLContext(ILibAsyncSocket_SocketModule socketModule, SS
SSL_set_bio(module->ssl, module->readBio, module->writeBio);
if (server == ILibAsyncSocket_TLS_Mode_Client)
{
if (hostName != NULL) { SSL_set_tlsext_host_name(module->ssl, hostName); }
SSL_set_connect_state(module->ssl);
status = SSL_do_handshake(module->ssl);
if (status <= 0) { status = SSL_get_error(module->ssl, status); }

View File

@@ -212,7 +212,8 @@ typedef enum ILibAsyncSocket_TLS_Mode
#endif
}ILibAsyncSocket_TLS_Mode;
SSL* ILibAsyncSocket_SetSSLContext(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server);
SSL* ILibAsyncSocket_SetSSLContextEx(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server, char *hostname);
#define ILibAsyncSocket_SetSSLContext(socketModule, ssl_ctx, tlsMode) ILibAsyncSocket_SetSSLContextEx(socketModule, ssl_ctx, tlsMode, NULL)
SSL_CTX *ILibAsyncSocket_GetSSLContext(ILibAsyncSocket_SocketModule socketModule);
#endif

View File

@@ -21,6 +21,7 @@
#else
#include "md5.h"
#include "sha1.h"
#include "microstack/sha.h"
#include <time.h>
#endif
@@ -561,10 +562,10 @@ int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, i
X509_NAME *cname = NULL;
X509 **x509p = NULL;
EVP_PKEY **pkeyp = NULL;
int hashlen = UTIL_HASHSIZE;
char hash[UTIL_HASHSIZE];
int hashlen = UTIL_SHA384_HASHSIZE;
char hash[UTIL_SHA384_HASHSIZE];
char serial[8];
char nameStr[(UTIL_HASHSIZE * 2) + 2];
char nameStr[(UTIL_SHA384_HASHSIZE * 2) + 2];
BIGNUM *oBigNbr;
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
@@ -616,7 +617,7 @@ int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, i
//util_sha256((char*)x->cert_info->key->public_key->data, x->cert_info->key->public_key->length, hash); // OpenSSL 1.0
X509_pubkey_digest(x, EVP_sha384(), (unsigned char*)hash, (unsigned int*)&hashlen); // OpenSSL 1.1
util_tohex(hash, UTIL_HASHSIZE, nameStr);
util_tohex(hash, UTIL_SHA384_HASHSIZE, nameStr);
X509_NAME_add_entry_by_txt(cname, "CN", MBSTRING_ASC, (unsigned char*)nameStr, -1, -1, 0);
}
else
@@ -682,7 +683,7 @@ err:
int __fastcall util_keyhash(struct util_cert cert, char* result)
{
int hashlen = UTIL_HASHSIZE;
int hashlen = UTIL_SHA384_HASHSIZE;
if (cert.x509 == NULL) return -1;
//util_sha256((char*)(cert.x509->cert_info->key->public_key->data), cert.x509->cert_info->key->public_key->length, result); // OpenSSL 1.0
X509_pubkey_digest(cert.x509, EVP_sha384(), (unsigned char*)result,(unsigned int *) &hashlen); // OpenSSL 1.1
@@ -691,7 +692,7 @@ int __fastcall util_keyhash(struct util_cert cert, char* result)
int __fastcall util_keyhash2(X509* cert, char* result)
{
int hashlen = UTIL_HASHSIZE;
int hashlen = UTIL_SHA384_HASHSIZE;
if (cert == NULL) return -1;
//util_sha256((char*)(cert->cert_info->key->public_key->data), cert->cert_info->key->public_key->length, result); // OpenSSL 1.0
X509_pubkey_digest(cert, EVP_sha384(), (unsigned char*)result, (unsigned int*)&hashlen); // OpenSSL 1.1
@@ -702,11 +703,11 @@ int __fastcall util_keyhash2(X509* cert, char* result)
int __fastcall util_sign(struct util_cert cert, char* data, int datalen, char** signature)
{
int size = 0;
unsigned int hashsize = UTIL_HASHSIZE;
unsigned int hashsize = UTIL_SHA384_HASHSIZE;
BIO *in = NULL;
PKCS7 *message = NULL;
*signature = NULL;
if (datalen <= UTIL_HASHSIZE) return 0;
if (datalen <= UTIL_SHA384_HASHSIZE) return 0;
// Add hash of the certificate to start of data
X509_digest(cert.x509, EVP_sha384(), (unsigned char*)data, &hashsize);
@@ -730,7 +731,7 @@ int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert,
BIO *out = NULL;
PKCS7 *message = NULL;
char* data2 = NULL;
char hash[UTIL_HASHSIZE];
char hash[UTIL_SHA256_HASHSIZE];
STACK_OF(X509) *st = NULL;
cert->x509 = NULL;
@@ -750,7 +751,7 @@ int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert,
// If data block contains less than 32 bytes, fail.
size = (unsigned int)BIO_get_mem_data(out, &data2);
if (size <= UTIL_HASHSIZE) goto error;
if (size <= UTIL_SHA256_HASHSIZE) goto error;
// Copy the data block
*data = (char*)malloc(size + 1);
@@ -764,11 +765,11 @@ int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert,
sk_X509_free(st);
// Get a full certificate hash of the signer
r = UTIL_HASHSIZE;
r = UTIL_SHA256_HASHSIZE;
X509_digest(cert->x509, EVP_sha256(), (unsigned char*)hash, &r);
// Check certificate hash with first 32 bytes of data.
if (memcmp(hash, *data, UTIL_HASHSIZE) != 0) goto error;
if (memcmp(hash, *data, UTIL_SHA256_HASHSIZE) != 0) goto error;
// Approved, cleanup and return.
BIO_free(out);

View File

@@ -35,18 +35,31 @@ BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _I
void __fastcall util_random(int length, char* result);
void __fastcall util_randomtext(int length, char* result);
#define UTIL_HASHSIZE 48
#define NONCE_SIZE 48
#define UTIL_MD5_HASHSIZE 16
#define UTIL_SHA1_HASHSIZE 20
#define UTIL_SHA256_HASHSIZE 32
#define UTIL_SHA384_HASHSIZE 48
#define UTIL_SHA512_HASHSIZE 64
#ifdef MICROSTACK_NOTLS
#include "md5.h"
#include "sha1.h"
#include "microstack/SHA256.h"
#include "microstack/SHA.h"
#define SHA256_CTX struct sha256_ctx
#define SHA256_Init(ctx) __sha256_init_ctx(ctx)
#define SHA256_Update(ctx, data, len) __sha256_process_bytes(data, len, ctx)
#define SHA256_Final(md, ctx) __sha256_finish_ctx(ctx, md)
#define SHA256_CTX SHA256Context
#define SHA512_CTX SHA512Context
#define SHA256_Init(ctx) SHA256Reset (ctx)
#define SHA256_Update(ctx, data, len) SHA256Input(ctx, (uint8_t*)data, len)
#define SHA256_Final(md, ctx) SHA256Result (ctx, md)
#define SHA384_Init(ctx) SHA384Reset (ctx)
#define SHA384_Update(ctx, data, len) SHA384Input(ctx, (uint8_t*)data, len)
#define SHA384_Final(md, ctx) SHA384Result (ctx, md)
#define SHA512_Init(ctx) SHA512Reset (ctx)
#define SHA512_Update(ctx, data, len) SHA512Input(ctx, (uint8_t*)data, len)
#define SHA512_Final(md, ctx) SHA512Result (ctx, md)
#endif

View File

@@ -41,7 +41,7 @@ void CALLBACK ILibIPAddressMonitor_dispatch(
IN DWORD dwFlags
)
{
if (dwError == 0)
if (dwError == 0 && lpOverlapped->hEvent != NULL)
{
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)lpOverlapped->hEvent;
ILibChain_RunOnMicrostackThread(obj->chainLink.ParentChain, ILibIPAddressMonitor_MicrostackThreadDispatch, obj);
@@ -60,6 +60,7 @@ void ILibIPAddressMonitor_Destroy(void *object)
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)object;
#ifdef WIN32
obj->reserved.hEvent = NULL;
closesocket(obj->mSocket);
obj->mSocket = INVALID_SOCKET;
#elif defined(_POSIX)

View File

@@ -5104,10 +5104,18 @@ ILibParseUriResult ILibParseUriEx (const char* URI, size_t URILen, char** Addr,
TempStringLength2 = TempStringLength-result2->FirstResult->datalength;
if (Path != NULL)
{
if ((*Path = (char*)malloc(TempStringLength2 + 1)) == NULL) ILIBCRITICALEXIT(254);
memcpy_s(*Path, TempStringLength2 + 1, TempString + (result2->FirstResult->datalength), TempStringLength2);
if ((*Path = (char*)malloc(TempStringLength2 + 2)) == NULL) ILIBCRITICALEXIT(254);
if (TempStringLength2 == 0)
{
(*Path)[0] = '/';
(*Path)[1] = '\0';
}
else
{
memcpy_s(*Path, TempStringLength2 + 2, TempString + (result2->FirstResult->datalength), TempStringLength2);
(*Path)[TempStringLength2] = '\0';
}
}
// Parse Port Number
result3 = ILibParseString(result2->FirstResult->data, 0, result2->FirstResult->datalength, ":", 1);
@@ -5333,7 +5341,7 @@ void ILibSetDirective(struct packetheader *packet, char* Directive, int Directiv
if (packet->ReservedMemory != NULL)
{
if (ILibMemory_AllocateA_Size(packet->ReservedMemory) > (DirectiveLength + DirectiveObjLength + 2))
if (ILibMemory_AllocateA_Size(packet->ReservedMemory) > (unsigned int)(DirectiveLength + DirectiveObjLength + 2))
{
packet->Directive = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)DirectiveLength + 1);
packet->DirectiveObj = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)DirectiveObjLength + 1);

View File

@@ -306,10 +306,10 @@ int ILibIsRunningOnChainThread(void* chain);
#else
#define ILibMemory_AllocateA(bufferLen) ILibMemory_AllocateA_InitMem(alloca(8+bufferLen+sizeof(void*)), (size_t)(8+bufferLen+sizeof(void*)))
#endif
#define ILibMemory_AllocateA_Size(buffer) (((int*)((char*)(buffer)-4))[0])
#define ILibMemory_AllocateA_Size(buffer) (((unsigned int*)((char*)(buffer)-4))[0])
#define ILibMemory_AllocateA_Next(buffer) (((void**)((char*)(buffer)-4-sizeof(void*)))[0])
#define ILibMemory_AllocateA_Raw(buffer) ((void*)((char*)(buffer)-4-sizeof(void*)-4))
#define ILibMemory_AllocateA_RawSize(buffer) (((int*)((char*)(buffer)-4-sizeof(void*)-4))[0])
#define ILibMemory_AllocateA_RawSize(buffer) (((unsigned int*)((char*)(buffer)-4-sizeof(void*)-4))[0])
void* ILibMemory_AllocateA_Get(void *buffer, size_t sz);
void* ILibMemory_AllocateA_InitMem(void *buffer, size_t bufferLen);

View File

@@ -162,6 +162,10 @@ typedef struct ILibProcessPipe_WaitHandle
void *user;
ILibProcessPipe_WaitHandle_Handler callback;
}ILibProcessPipe_WaitHandle;
HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr)
{
return(((ILibProcessPipe_Manager_Object*)mgr)->workerThread);
}
int ILibProcessPipe_Manager_WindowsWaitHandles_Remove_Comparer(void *source, void *matchWith)
{
@@ -181,6 +185,7 @@ void __stdcall ILibProcessPipe_WaitHandle_Remove_APC(ULONG_PTR obj)
waiter = (ILibProcessPipe_WaitHandle*)ILibLinkedList_GetDataFromNode(node);
free(waiter);
ILibLinkedList_Remove(node);
SetEvent(manager->updateEvent);
}
free((void*)obj);
}
@@ -497,21 +502,36 @@ ILibProcessPipe_PipeObject* ILibProcessPipe_CreatePipe(ILibProcessPipe_Manager m
return retVal;
}
void ILibProcessPipe_Process_Destroy(ILibProcessPipe_Process_Object *p)
#ifdef WIN32
void __stdcall ILibProcessPipe_Process_Destroy_WinRunThread(ULONG_PTR obj)
{
ILibProcessPipe_Process_Object *p = (ILibProcessPipe_Process_Object*)obj;
if (p->exiting != 0) { return; }
if (p->stdIn != NULL) { ILibProcessPipe_FreePipe(p->stdIn); }
if (p->stdOut != NULL) { ILibProcessPipe_FreePipe(p->stdOut); }
if (p->stdErr != NULL) { ILibProcessPipe_FreePipe(p->stdErr); }
free(p);
}
#ifndef WIN32
void ILibProcessPipe_Process_BrokenPipeSink(ILibProcessPipe_PipeObject* sender)
#endif
void ILibProcessPipe_Process_Destroy(ILibProcessPipe_Process_Object *p)
{
ILibProcessPipe_Process_Object *p = sender->mProcess;
#ifdef WIN32
// We can't destroy this now, because we're on the MicrostackThread. We must destroy this on the WindowsRunLoop Thread.
QueueUserAPC((PAPCFUNC)ILibProcessPipe_Process_Destroy_WinRunThread, p->parent->workerThread, (ULONG_PTR)p);
#else
if (p->exiting != 0) { return; }
if (p->stdIn != NULL) { ILibProcessPipe_FreePipe(p->stdIn); }
if (p->stdOut != NULL) { ILibProcessPipe_FreePipe(p->stdOut); }
if (p->stdErr != NULL) { ILibProcessPipe_FreePipe(p->stdErr); }
free(p);
#endif
}
#ifndef WIN32
void ILibProcessPipe_Process_BrokenPipeSink(ILibProcessPipe_Pipe sender)
{
ILibProcessPipe_Process_Object *p = ((ILibProcessPipe_PipeObject*)sender)->mProcess;
int status;
if (ILibIsRunningOnChainThread(sender->manager->ChainLink.ParentChain) != 0)
if (ILibIsRunningOnChainThread(((ILibProcessPipe_PipeObject*)sender)->manager->ChainLink.ParentChain) != 0)
{
// This was called from the Reader
if (p->exitHandler != NULL)
@@ -685,13 +705,14 @@ ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx2(ILibProcessPipe_
retVal->stdIn = ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(pipeManager, pipe, extraMemorySize);
retVal->stdIn->mProcess = retVal;
retVal->stdOut = ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(pipeManager, pipe, extraMemorySize);
ILibProcessPipe_Pipe_SetBrokenPipeHandler(retVal->stdOut, ILibProcessPipe_Process_BrokenPipeSink);
retVal->stdOut->mProcess = retVal;
}
else
{
retVal->stdIn = ILibProcessPipe_CreatePipe(pipeManager, 4096, NULL, extraMemorySize);
retVal->stdIn->mProcess = retVal;
retVal->stdOut = ILibProcessPipe_CreatePipe(pipeManager, 4096, &ILibProcessPipe_Process_BrokenPipeSink, extraMemorySize);
retVal->stdOut = ILibProcessPipe_CreatePipe(pipeManager, 4096, (ILibProcessPipe_GenericBrokenPipeHandler) ILibProcessPipe_Process_BrokenPipeSink, extraMemorySize);
retVal->stdOut->mProcess = retVal;
pid = vfork();
}
@@ -859,7 +880,6 @@ void ILibProcessPipe_Process_ReadHandler(void* user)
#endif
ILibLinkedList_Remove(ILibLinkedList_GetNode_Search(pipeObject->manager->ActivePipes, NULL, pipeObject));
if (pipeObject->brokenPipeHandler != NULL)
{
((ILibProcessPipe_GenericBrokenPipeHandler)pipeObject->brokenPipeHandler)(pipeObject);
@@ -1240,6 +1260,11 @@ void ILibProcessPipe_Process_PipeHandler_StdIn(void *user1, void *user2)
}
#ifdef WIN32
void __stdcall ILibProcessPipe_Process_OnExit_ChainSink_DestroySink(ULONG_PTR obj)
{
ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)obj;
if (j->exiting == 0) { ILibProcessPipe_Process_Destroy(j); }
}
void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user)
{
ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)user;
@@ -1251,7 +1276,8 @@ void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user)
j->exitHandler(j, exitCode, j->userObject);
j->exiting ^= 1;
if (j->exiting == 0) { ILibProcessPipe_Process_Destroy(j); }
// We can't destroy this now, because we're on the MicrostackThread. We must destroy this on the WindowsRunLoop Thread.
QueueUserAPC((PAPCFUNC)ILibProcessPipe_Process_OnExit_ChainSink_DestroySink, j->parent->workerThread, (ULONG_PTR)j);
}
BOOL ILibProcessPipe_Process_OnExit(HANDLE event, void* user)
{

View File

@@ -50,6 +50,7 @@ typedef enum ILibProcessPipe_Pipe_ReaderHandleType
ILibProcessPipe_Pipe_ReaderHandleType_NotOverLapped = 0, //!< Spawn a I/O processing thread
ILibProcessPipe_Pipe_ReaderHandleType_Overlapped = 1 //!< Use Overlapped I/O
}ILibProcessPipe_Pipe_ReaderHandleType;
HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr);
#endif
ILibTransport_DoneState ILibProcessPipe_Pipe_Write(ILibProcessPipe_Pipe writePipe, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership);

View File

@@ -247,6 +247,7 @@ typedef struct ILibWebClientDataObject
#ifndef MICROSTACK_NOTLS
ILibWebClient_RequestToken_HTTPS requestMode;
char *sniHost;
#endif
char* CertificateHashPtr; // Points to the certificate hash (next field) if set
@@ -342,7 +343,15 @@ void ILibWebClient_DestroyWebRequest(struct ILibWebRequest *wr)
if (wr == NULL) return;
if (wr != NULL && wr->connectionCloseWasSpecified != 0 && wr->DisconnectSink != NULL) { wr->DisconnectSink(wr->requestToken); }
if (wr->buffered != NULL) { free(wr->buffered); }
if (wr->buffered != NULL)
{
while (wr->buffered != NULL)
{
ILibWebRequest_buffer * rb = wr->buffered->next;
free(wr->buffered);
wr->buffered = rb;
}
}
if (wr->streamedState != NULL)
{
while (ILibQueue_IsEmpty(wr->streamedState->BufferQueue) == 0)
@@ -472,6 +481,9 @@ void ILibWebClient_DestroyWebClientDataObject(ILibWebClient_StateObject token)
ILibQueue_Destroy(wcdo->RequestQueue);
if (wcdo->DigestData != NULL) { free(ILibMemory_AllocateA_Raw(wcdo->DigestData)); }
#ifndef MICROSTACK_NOTLS
if (wcdo->sniHost != NULL) { free(wcdo->sniHost); }
#endif
free(wcdo);
}
@@ -739,8 +751,11 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
SEM_TRACK(WebClient_TrackLock("ILibWebClient_FinishedResponse", 1, wcdo->Parent);)
sem_wait(&(wcdo->Parent->QLock));
wr = (struct ILibWebRequest*)ILibQueue_DeQueue(wcdo->RequestQueue);
if (wr != NULL)
{
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
}
SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_FinishedResponse", 2, wcdo->Parent);)
sem_post(&(wcdo->Parent->QLock));
return;
@@ -795,12 +810,12 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
//
ILibAsyncSocket_Send(wcdo->SOCK, wr->Buffer[i], wr->BufferLength[i], ILibAsyncSocket_MemoryOwnership_STATIC);
}
while (wr->buffered != NULL)
b = wr->buffered;
while (b != NULL)
{
b = wr->buffered->next;
ILibAsyncSocket_Send(wcdo->SOCK, wr->buffered->buffer, wr->buffered->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
free(wr->buffered);
wr->buffered = b;
ILibAsyncSocket_Send(wcdo->SOCK, b->buffer, b->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
b = b->next;
}
}
}
@@ -1140,7 +1155,7 @@ void ILibWebClient_ProcessChunk(ILibAsyncSocket_SocketModule socketModule, struc
wcdo->NeedFlush = 0;
ILibWebClient_FinishedResponse_Server(wcdo);
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
//
// Free the resources associated with this chunk
@@ -1556,7 +1571,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wcdo->source.sin_addr.s_addr = ILibAsyncSocket_GetRemoteInterface(socketModule);
wcdo->source.sin_port = htons(ILibAsyncSocket_GetRemotePort(socketModule));
*/
ILibAsyncSocket_GetRemoteInterface(socketModule, (struct sockaddr*)(&wcdo->source));
if (socketModule != NULL) { ILibAsyncSocket_GetRemoteInterface(socketModule, (struct sockaddr*)(&wcdo->source)); }
wcdo->HeaderLength = i + 4;
wcdo->WaitForClose = 1;
@@ -1654,7 +1669,14 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
}
if (wcdo->header->StatusCode >= 100 && wcdo->header->StatusCode <= 199)
{
if (wcdo->header->StatusCode == 101 && wr->requestToken->WebSocketKey != NULL)
if (wr->requestToken == NULL)
{
int zro = 0;
if (wr->OnResponse != NULL) { wr->OnResponse(wcdo, 0, wcdo->header, NULL, &zro, 0, ILibWebClient_ReceiveStatus_Connection_Established, wr->user1, wr->user2, &(wcdo->PAUSE)); }
*p_beginPointer += wcdo->HeaderLength;
return;
}
else if (wcdo->header->StatusCode == 101 && wr->requestToken->WebSocketKey != NULL)
{
// WebSocket
char* skey = ILibGetHeaderLine(wcdo->header, "Sec-WebSocket-Accept", 20);
@@ -1812,7 +1834,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wr->user2,
&(wcdo->PAUSE));
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
wcdo->HeaderLength = 0;
*p_beginPointer = i+4+zero;
@@ -1856,15 +1878,6 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wr->user1,
wr->user2,
&(wcdo->PAUSE));
if (ILibAsyncSocket_IsFree(socketModule)!=0)
{
//
// The user closed the socket, so just return
//
return;
}
else
{
if (wcdo->FinHeader == 0)
{
//
@@ -1880,6 +1893,12 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
*p_beginPointer = i + 4;
return;
}
if (socketModule != NULL && ILibAsyncSocket_IsFree(socketModule)!=0)
{
//
// The user closed the socket, so just return
//
return;
}
}
@@ -1950,7 +1969,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wr->user2,
&(wcdo->PAUSE));
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
if (wcdo->WaitForClose==0)
{
@@ -1979,7 +1998,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
}
//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}}
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
//
// If the user said to pause this connection, do so
@@ -2054,12 +2073,11 @@ void ILibWebClient_OnConnect(ILibAsyncSocket_SocketModule socketModule, int Conn
ILibAsyncSocket_Send(socketModule, r->Buffer[i], r->BufferLength[i], (enum ILibAsyncSocket_MemoryOwnership)-1);
}
while (r->buffered != NULL)
{
ILibAsyncSocket_Send(socketModule, r->buffered->buffer, r->buffered->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
b = r->buffered;
r->buffered = r->buffered->next;
free(b);
while (b != NULL)
{
ILibAsyncSocket_Send(socketModule, b->buffer, b->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
b = b->next;
}
if (r->streamedState != NULL)
{
@@ -2214,27 +2232,6 @@ void ILibWebClient_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, v
wr->user2,
&(wcdo->PAUSE));
if (ILibAsyncSocket_IsFree(socketModule) != 0)
{
//
// If the underlying socket is gone, then Finished Response won't clear
// the pending request
//
SEM_TRACK(WebClient_TrackLock("ILibWebClient_OnDisconnect", 5, wcdo->Parent);)
sem_wait(&(wcdo->Parent->QLock));
wr = (struct ILibWebRequest*)ILibQueue_DeQueue(wcdo->RequestQueue);
SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_OnDisconnect", 6, wcdo->Parent);)
sem_post(&(wcdo->Parent->QLock));
if (wr != NULL)
{
if (wcdo->IsWebSocket != 0)
{
free(((ILibWebClient_WebSocketState*)wr->Buffer[0])->WebSocketFragmentBuffer);
}
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
}
}
if (wcdo->IsOrphan != 0 || wcdo->IsWebSocket != 0)
{
ILibWebClient_FinishedResponse(socketModule, wcdo);
@@ -2244,20 +2241,6 @@ void ILibWebClient_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, v
{
ILibWebClient_FinishedResponse(socketModule, wcdo);
}
//SEM_TRACK(WebClient_TrackLock("ILibWebClient_OnDisconnect", 7, wcdo->Parent);)
//sem_wait(&(wcdo->Parent->QLock));
//wr = (struct ILibWebRequest*)ILibQueue_PeekQueue(wcdo->RequestQueue);
//SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_OnDisconnect", 8, wcdo->Parent);)
//sem_post(&(wcdo->Parent->QLock));
//if (wr == NULL)
//{
// if (wcdo->IsWebSocket != 0)
// {
// // This was a websocket, so we must destroy the WCDO object, because it won't be destroyed anywhere else
// ILibWebClient_DestroyWebClientDataObject(wcdo);
// }
// return;
//}
}
// Make Another Connection and Continue
@@ -2357,7 +2340,7 @@ void ILibWebClient_PreProcess(void* WebClientModule, fd_set *readset, fd_set *wr
#ifndef MICROSTACK_NOTLS
if (wcm->ssl_ctx != NULL && wcdo->requestMode == ILibWebClient_RequestToken_USE_HTTPS)
{
SSL* ssl = ILibAsyncSocket_SetSSLContext(wcdo->SOCK, wcm->ssl_ctx, 0);
SSL* ssl = ILibAsyncSocket_SetSSLContextEx(wcdo->SOCK, wcm->ssl_ctx, 0, wcdo->sniHost);
if (ssl != NULL && ILibWebClientDataObjectIndex >= 0)
{
SSL_set_ex_data(ssl, ILibWebClientDataObjectIndex, wcdo);
@@ -3256,7 +3239,7 @@ ILibTransport_DoneState ILibWebClient_StreamRequestBody(
if (t != NULL && t->wcdo != NULL)
{
wr = (struct ILibWebRequest*)ILibQueue_PeekTail(t->wcdo->RequestQueue);
wr = t->parent;
if (t->wcdo->SOCK == NULL || ILibQueue_GetCount(t->wcdo->RequestQueue)>1)
{
// Connection not established yet, so buffer the data
@@ -3583,6 +3566,12 @@ void ILibWebClient_Request_SetHTTPS(ILibWebClient_RequestToken reqToken, ILibWeb
{
((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->requestMode = requestMode;
}
void ILibWebClient_Request_SetSNI(ILibWebClient_RequestToken reqToken, char *host, int hostLen)
{
((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->sniHost = ILibMemory_Allocate(hostLen + 1, 0, NULL, NULL);
memcpy_s(((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->sniHost, hostLen, host, hostLen);
((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->sniHost[hostLen] = 0;
}
#endif
int ILibWebClient_GetLocalInterface(void* socketModule, struct sockaddr *localAddress)

View File

@@ -257,9 +257,7 @@ void* ILibWebClient_GetChainFromWebStateObject(ILibWebClient_StateObject wcdo);
typedef enum ILibWebClient_RequestToken_HTTPS
{
#ifndef MICROSTACK_NOTLS
ILibWebClient_RequestToken_USE_HTTPS = 0,
#endif
ILibWebClient_RequestToken_USE_HTTP = 1
}ILibWebClient_RequestToken_HTTPS;
@@ -267,6 +265,7 @@ typedef enum ILibWebClient_RequestToken_HTTPS
void ILibWebClient_SetTLS(ILibWebClient_RequestManager manager, void *ssl_ctx, ILibWebClient_OnSslConnection OnSslConnection);
int ILibWebClient_EnableHTTPS(ILibWebClient_RequestManager manager, struct util_cert* leafCert, X509* nonLeafCert, ILibWebClient_OnHttpsConnection OnHttpsConnection);
void ILibWebClient_Request_SetHTTPS(ILibWebClient_RequestToken reqToken, ILibWebClient_RequestToken_HTTPS requestMode);
void ILibWebClient_Request_SetSNI(ILibWebClient_RequestToken reqToken, char *host, int hostLen);
#endif
// Added methods

View File

@@ -1141,7 +1141,7 @@ int ILibWebServer_Digest_ParseAuthenticationHeader2(char* value, int valueLen, c
*token = value;
len = ILibTrimString(token, i);
(*token)[len] = 0;
//(*token)[len] = 0;
*tokenLen = len;
*tokenValue = value + i + 1;
@@ -1157,7 +1157,7 @@ int ILibWebServer_Digest_ParseAuthenticationHeader2(char* value, int valueLen, c
{
len -= 1;
}
(*tokenValue)[len] = 0;
//(*tokenValue)[len] = 0;
*tokenValueLen = len;
return 0;
}
@@ -1190,7 +1190,7 @@ int ILibWebServer_Digest_IsCorrectRealmAndNonce(struct ILibWebServer_Session *se
int userRealmLen;
char* nonce = NULL;
char* opaque = NULL;
int opaqueLen;
int opaqueLen, nonceLen;
long long current;
char expiration[8];
char calculatedNonce[33];
@@ -1205,7 +1205,7 @@ int ILibWebServer_Digest_IsCorrectRealmAndNonce(struct ILibWebServer_Session *se
ILibWebServer_Digest_ParseAuthenticationHeader(ILibWebServer_Session_GetSystemData(session)->DigestTable, auth, authLen);
ILibGetEntryEx(ILibWebServer_Session_GetSystemData(session)->DigestTable, "realm", 5, (void**)&userRealm, &userRealmLen);
nonce = (char*)ILibGetEntry(ILibWebServer_Session_GetSystemData(session)->DigestTable, "nonce", 5);
ILibGetEntryEx(ILibWebServer_Session_GetSystemData(session)->DigestTable, "nonce", 5, (void**)&nonce, &nonceLen);
ILibGetEntryEx(ILibWebServer_Session_GetSystemData(session)->DigestTable, "opaque", 6, (void**)&opaque, &opaqueLen);
if (opaque != NULL && userRealm != NULL && userRealmLen == realmLen && strncmp(userRealm, realm, realmLen) == 0)
@@ -1217,7 +1217,7 @@ int ILibWebServer_Digest_IsCorrectRealmAndNonce(struct ILibWebServer_Session *se
if (((long long*)expiration)[0] < current) { return 0; } // Opaque Block Expired
ILibWebServer_Digest_CalculateNonce(session, ((long long*)expiration)[0], calculatedNonce);
return(strcmp(nonce, calculatedNonce) == 0 ? 1 : 0);
return((nonceLen == 32 && strncmp(nonce, calculatedNonce, 32)) == 0 ? 1 : 0);
}
else
{
@@ -1304,7 +1304,7 @@ ILibExportMethod int ILibWebServer_Digest_ValidatePassword(struct ILibWebServer_
MD5_Final((unsigned char*)val, &mctx);
util_tohex_lower(val, 16, result3);
retVal = strcmp(result3, response) == 0 ? 1 : 0;
retVal = (responseLen == 32 && strncmp(result3, response, 32)) == 0 ? 1 : 0;
// if (retVal == 0) { ILibWebServer_Digest_SendUnauthorized(session, realm, strlen(realm)); }
return retVal;

View File

@@ -59,8 +59,8 @@ typedef struct
struct util_cert selftlscert;
struct util_cert selftlsclientcert;
SSL_CTX* ctx;
char tlsServerCertThumbprint[32];
char g_selfid[UTIL_HASHSIZE];
char tlsServerCertThumbprint[UTIL_SHA256_HASHSIZE];
char g_selfid[UTIL_SHA256_HASHSIZE];
ILibWebRTC_TURN_ConnectFlags mTurnSetting;
struct sockaddr_in6 mTurnServer;

61
microstack/sha-private.h Normal file
View File

@@ -0,0 +1,61 @@
/*************************** sha-private.h ***************************/
/*
https://github.com/Yubico/yubico-c-client
Copyright (c) 2006-2013 Yubico AB
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/********************** See RFC 4634 for details *********************/
#ifndef _SHA_PRIVATE__H
#define _SHA_PRIVATE__H
/*
* These definitions are defined in FIPS-180-2, section 4.1.
* Ch() and Maj() are defined identically in sections 4.1.1,
* 4.1.2 and 4.1.3.
*
* The definitions used in FIPS-180-2 are as follows:
*/
#ifndef USE_MODIFIED_MACROS
#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* USE_MODIFIED_MACROS */
/*
* The following definitions are equivalent and potentially faster.
*/
#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#endif /* USE_MODIFIED_MACROS */
#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
#endif /* _SHA_PRIVATE__H */

303
microstack/sha.h Normal file
View File

@@ -0,0 +1,303 @@
/**************************** sha.h ****************************/
/*
https://github.com/Yubico/yubico-c-client
Copyright (c) 2006-2013 Yubico AB
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/******************* See RFC 4634 for details ******************/
#ifndef _SHA_H_
#define _SHA_H_
/*
* Description:
* This file implements the Secure Hash Signature Standard
* algorithms as defined in the National Institute of Standards
* and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
* published on August 1, 2002, and the FIPS PUB 180-2 Change
* Notice published on February 28, 2004.
*
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf
*
* The five hashes are defined in these sizes:
* SHA-1 20 byte / 160 bit
* SHA-224 28 byte / 224 bit
* SHA-256 32 byte / 256 bit
* SHA-384 48 byte / 384 bit
* SHA-512 64 byte / 512 bit
*/
#include <stdint.h>
/*
* If you do not have the ISO standard stdint.h header file, then you
* must typedef the following:
* name meaning
* uint64_t unsigned 64 bit integer
* uint32_t unsigned 32 bit integer
* uint8_t unsigned 8 bit integer (i.e., unsigned char)
* int_least16_t integer of >= 16 bits
*
*/
#ifndef _SHA_enum_
#define _SHA_enum_
/*
* All SHA functions return one of these values.
*/
enum
{
shaSuccess = 0,
shaNull, /* Null pointer parameter */
shaInputTooLong, /* input data too long */
shaStateError, /* called Input after FinalBits or Result */
shaBadParam /* passed a bad parameter */
};
#endif /* _SHA_enum_ */
/*
* These constants hold size information for each of the SHA
* hashing operations
*/
enum
{
SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
SHA512_Message_Block_Size = 128,
USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
SHA384HashSize = 48, SHA512HashSize = 64,
USHAMaxHashSize = SHA512HashSize,
SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
};
/*
* These constants are used in the USHA (unified sha) functions.
*/
typedef enum SHAversion
{
SHA1, SHA224, SHA256, SHA384, SHA512
} SHAversion;
/*
* This structure will hold context information for the SHA-1
* hashing operation.
*/
typedef struct SHA1Context
{
uint32_t Intermediate_Hash[SHA1HashSize / 4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */
uint8_t Message_Block[SHA1_Message_Block_Size];
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */
} SHA1Context;
/*
* This structure will hold context information for the SHA-256
* hashing operation.
*/
typedef struct SHA256Context
{
uint32_t Intermediate_Hash[SHA256HashSize / 4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */
uint8_t Message_Block[SHA256_Message_Block_Size];
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */
} SHA256Context;
/*
* This structure will hold context information for the SHA-512
* hashing operation.
*/
typedef struct SHA512Context
{
#ifdef USE_32BIT_ONLY
uint32_t Intermediate_Hash[SHA512HashSize / 4]; /* Message Digest */
uint32_t Length[4]; /* Message length in bits */
#else /* !USE_32BIT_ONLY */
uint64_t Intermediate_Hash[SHA512HashSize / 8]; /* Message Digest */
uint64_t Length_Low, Length_High; /* Message length in bits */
#endif /* USE_32BIT_ONLY */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 1024-bit message blocks */
uint8_t Message_Block[SHA512_Message_Block_Size];
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */
} SHA512Context;
/*
* This structure will hold context information for the SHA-224
* hashing operation. It uses the SHA-256 structure for computation.
*/
typedef struct SHA256Context SHA224Context;
/*
* This structure will hold context information for the SHA-384
* hashing operation. It uses the SHA-512 structure for computation.
*/
typedef struct SHA512Context SHA384Context;
/*
* This structure holds context information for all SHA
* hashing operations.
*/
typedef struct USHAContext
{
int whichSha; /* which SHA is being used */
union
{
SHA1Context sha1Context;
SHA224Context sha224Context;
SHA256Context sha256Context;
SHA384Context sha384Context;
SHA512Context sha512Context;
} ctx;
} USHAContext;
/*
* This structure will hold context information for the HMAC
* keyed hashing operation.
*/
typedef struct HMACContext
{
int whichSha; /* which SHA is being used */
int hashSize; /* hash size of SHA being used */
int blockSize; /* block size of SHA being used */
USHAContext shaContext; /* SHA context */
unsigned char k_opad[USHA_Max_Message_Block_Size];
/* outer padding - key XORd with opad */
} HMACContext;
/*
* Function Prototypes
*/
/* SHA-1 */
extern int SHA1Reset(SHA1Context *);
extern int SHA1Input(SHA1Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA1FinalBits(SHA1Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize]);
/* SHA-224 */
extern int SHA224Reset(SHA224Context *);
extern int SHA224Input(SHA224Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA224FinalBits(SHA224Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA224Result(SHA224Context *,
uint8_t Message_Digest[SHA224HashSize]);
/* SHA-256 */
extern int SHA256Reset(SHA256Context *);
extern int SHA256Input(SHA256Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA256FinalBits(SHA256Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA256Result(SHA256Context *,
uint8_t Message_Digest[SHA256HashSize]);
/* SHA-384 */
extern int SHA384Reset(SHA384Context *);
extern int SHA384Input(SHA384Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA384FinalBits(SHA384Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA384Result(SHA384Context *,
uint8_t Message_Digest[SHA384HashSize]);
/* SHA-512 */
extern int SHA512Reset(SHA512Context *);
extern int SHA512Input(SHA512Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA512FinalBits(SHA512Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA512Result(SHA512Context *,
uint8_t Message_Digest[SHA512HashSize]);
/* Unified SHA functions, chosen by whichSha */
extern int USHAReset(USHAContext *, SHAversion whichSha);
extern int USHAInput(USHAContext *,
const uint8_t * bytes, unsigned int bytecount);
extern int USHAFinalBits(USHAContext *,
const uint8_t bits, unsigned int bitcount);
extern int USHAResult(USHAContext *,
uint8_t Message_Digest[USHAMaxHashSize]);
extern int USHABlockSize(enum SHAversion whichSha);
extern int USHAHashSize(enum SHAversion whichSha);
extern int USHAHashSizeBits(enum SHAversion whichSha);
/*
* HMAC Keyed-Hashing for Message Authentication, RFC2104,
* for all SHAs.
* This interface allows a fixed-length text input to be used.
*/
extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */
const unsigned char *text, /* pointer to data stream */
int text_len, /* length of data stream */
const unsigned char *key, /* pointer to authentication key */
int key_len, /* length of authentication key */
uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
/*
* HMAC Keyed-Hashing for Message Authentication, RFC2104,
* for all SHAs.
* This interface allows any length of text input to be used.
*/
extern int hmacReset(HMACContext * ctx, enum SHAversion whichSha,
const unsigned char *key, int key_len);
extern int hmacInput(HMACContext * ctx, const unsigned char *text,
int text_len);
extern int hmacFinalBits(HMACContext * ctx, const uint8_t bits,
unsigned int bitcount);
extern int hmacResult(HMACContext * ctx, uint8_t digest[USHAMaxHashSize]);
#endif /* _SHA_H_ */

636
microstack/sha224-256.c Normal file
View File

@@ -0,0 +1,636 @@
/*************************** sha224-256.c ***************************/
/*
https://github.com/Yubico/yubico-c-client
Copyright (c) 2006-2013 Yubico AB
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/********************* See RFC 4634 for details *********************/
/*
* Description:
* This file implements the Secure Hash Signature Standard
* algorithms as defined in the National Institute of Standards
* and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
* published on August 1, 2002, and the FIPS PUB 180-2 Change
* Notice published on February 28, 2004.
*
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf
*
* The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
* message digests for a given data stream. It should take about
* 2**n steps to find a message with the same digest as a given
* message and 2**(n/2) to find any two messages with the same
* digest, when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a
* "fingerprint" for a message.
*
* Portability Issues:
* SHA-224 and SHA-256 are defined in terms of 32-bit "words".
* This code uses <stdint.h> (included via "sha.h") to define 32
* and 8 bit unsigned integer types. If your C compiler does not
* support 32 bit unsigned integers, this code is not
* appropriate.
*
* Caveats:
* SHA-224 and SHA-256 are designed to work with messages less
* than 2^64 bits long. This implementation uses SHA224/256Input()
* to hash the bits that are a multiple of the size of an 8-bit
* character, and then uses SHA224/256FinalBits() to hash the
* final few bits of the input.
*/
#include "sha.h"
#include "sha-private.h"
/* Define the SHA shift, rotate left and rotate right macro */
#define SHA256_SHR(bits,word) ((word) >> (bits))
#define SHA256_ROTL(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
#define SHA256_ROTR(bits,word) \
(((word) >> (bits)) | ((word) << (32-(bits))))
/* Define the SHA SIGMA and sigma macros */
#define SHA256_SIGMA0(word) \
(SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
#define SHA256_SIGMA1(word) \
(SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
#define SHA256_sigma0(word) \
(SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
#define SHA256_sigma1(word) \
(SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
/*
* add "length" to the length
*/
static uint32_t addTemp;
#define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? 1 : 0)
/* Local Function Prototypes */
static void SHA224_256Finalize(SHA256Context * context, uint8_t Pad_Byte);
static void SHA224_256PadMessage(SHA256Context * context, uint8_t Pad_Byte);
static void SHA224_256ProcessMessageBlock(SHA256Context * context);
static int SHA224_256Reset(SHA256Context * context, uint32_t * H0);
static int SHA224_256ResultN(SHA256Context * context,
uint8_t Message_Digest[], int HashSize);
/* Initial Hash Values: FIPS-180-2 Change Notice 1 */
static uint32_t SHA224_H0[SHA256HashSize / 4] = {
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
};
/* Initial Hash Values: FIPS-180-2 section 5.3.2 */
static uint32_t SHA256_H0[SHA256HashSize / 4] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};
/*
* SHA224Reset
*
* Description:
* This function will initialize the SHA384Context in preparation
* for computing a new SHA224 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*/
int
SHA224Reset(SHA224Context * context)
{
return SHA224_256Reset(context, SHA224_H0);
}
/*
* SHA224Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_array: [in]
* An array of characters representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array
*
* Returns:
* sha Error Code.
*
*/
int
SHA224Input(SHA224Context * context, const uint8_t * message_array,
unsigned int length)
{
return SHA256Input(context, message_array, length);
}
/*
* SHA224FinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int
SHA224FinalBits(SHA224Context * context,
const uint8_t message_bits, unsigned int length)
{
return SHA256FinalBits(context, message_bits, length);
}
/*
* SHA224Result
*
* Description:
* This function will return the 224-bit message
* digest into the Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 28th element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*/
int
SHA224Result(SHA224Context * context, uint8_t Message_Digest[SHA224HashSize])
{
return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
}
/*
* SHA256Reset
*
* Description:
* This function will initialize the SHA256Context in preparation
* for computing a new SHA256 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*/
int
SHA256Reset(SHA256Context * context)
{
return SHA224_256Reset(context, SHA256_H0);
}
/*
* SHA256Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_array: [in]
* An array of characters representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array
*
* Returns:
* sha Error Code.
*/
int
SHA256Input(SHA256Context * context, const uint8_t * message_array,
unsigned int length)
{
if (!length)
return shaSuccess;
if (!context || !message_array)
return shaNull;
if (context->Computed)
{
context->Corrupted = shaStateError;
return shaStateError;
}
if (context->Corrupted)
return context->Corrupted;
while (length-- && !context->Corrupted)
{
context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF);
if (!SHA224_256AddLength(context, 8) &&
(context->Message_Block_Index == SHA256_Message_Block_Size))
SHA224_256ProcessMessageBlock(context);
message_array++;
}
return shaSuccess;
}
/*
* SHA256FinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int
SHA256FinalBits(SHA256Context * context,
const uint8_t message_bits, unsigned int length)
{
uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
};
uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
};
if (!length)
return shaSuccess;
if (!context)
return shaNull;
if ((context->Computed) || (length >= 8) || (length == 0))
{
context->Corrupted = shaStateError;
return shaStateError;
}
if (context->Corrupted)
return context->Corrupted;
SHA224_256AddLength(context, length);
SHA224_256Finalize(context, (uint8_t)
((message_bits & masks[length]) | markbit[length]));
return shaSuccess;
}
/*
* SHA256Result
*
* Description:
* This function will return the 256-bit message
* digest into the Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 32nd element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*/
int
SHA256Result(SHA256Context * context, uint8_t Message_Digest[])
{
return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
}
/*
* SHA224_256Finalize
*
* Description:
* This helper function finishes off the digest calculations.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*/
static void
SHA224_256Finalize(SHA256Context * context, uint8_t Pad_Byte)
{
int i;
SHA224_256PadMessage(context, Pad_Byte);
/* message may be sensitive, so clear it out */
for (i = 0; i < SHA256_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
context->Length_Low = 0; /* and clear length */
context->Length_High = 0;
context->Computed = 1;
}
/*
* SHA224_256PadMessage
*
* Description:
* According to the standard, the message must be padded to an
* even 512 bits. The first padding bit must be a '1'. The
* last 64 bits represent the length of the original message.
* All bits in between should be 0. This helper function will pad
* the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
*/
static void
SHA224_256PadMessage(SHA256Context * context, uint8_t Pad_Byte)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index >= (SHA256_Message_Block_Size - 8))
{
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA256_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA224_256ProcessMessageBlock(context);
}
else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA256_Message_Block_Size - 8))
context->Message_Block[context->Message_Block_Index++] = 0;
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
context->Message_Block[59] = (uint8_t)(context->Length_High);
context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t)(context->Length_Low);
SHA224_256ProcessMessageBlock(context);
}
/*
* SHA224_256ProcessMessageBlock
*
* Description:
* This function will process the next 512 bits of the message
* stored in the Message_Block array.
*
* Parameters:
* context: [in/out]
* The SHA context to update
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this code, especially the
* single character names, were used because those were the
* names used in the publication.
*/
static void
SHA224_256ProcessMessageBlock(SHA256Context * context)
{
/* Constants defined in FIPS-180-2, section 4.2.2 */
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
int t, t4; /* Loop counter */
uint32_t temp1, temp2; /* Temporary word value */
uint32_t W[64]; /* Word sequence */
uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for (t = t4 = 0; t < 16; t++, t4 += 4)
W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
(((uint32_t)context->Message_Block[t4 + 1]) << 16) |
(((uint32_t)context->Message_Block[t4 + 2]) << 8) |
(((uint32_t)context->Message_Block[t4 + 3]));
for (t = 16; t < 64; t++)
W[t] = SHA256_sigma1(W[t - 2]) + W[t - 7] +
SHA256_sigma0(W[t - 15]) + W[t - 16];
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
F = context->Intermediate_Hash[5];
G = context->Intermediate_Hash[6];
H = context->Intermediate_Hash[7];
for (t = 0; t < 64; t++)
{
temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
temp2 = SHA256_SIGMA0(A) + SHA_Maj(A, B, C);
H = G;
G = F;
F = E;
E = D + temp1;
D = C;
C = B;
B = A;
A = temp1 + temp2;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Intermediate_Hash[5] += F;
context->Intermediate_Hash[6] += G;
context->Intermediate_Hash[7] += H;
context->Message_Block_Index = 0;
}
/*
* SHA224_256Reset
*
* Description:
* This helper function will initialize the SHA256Context in
* preparation for computing a new SHA256 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
* H0
* The initial hash value to use.
*
* Returns:
* sha Error Code.
*/
static int
SHA224_256Reset(SHA256Context * context, uint32_t * H0)
{
if (!context)
return shaNull;
context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;
context->Intermediate_Hash[0] = H0[0];
context->Intermediate_Hash[1] = H0[1];
context->Intermediate_Hash[2] = H0[2];
context->Intermediate_Hash[3] = H0[3];
context->Intermediate_Hash[4] = H0[4];
context->Intermediate_Hash[5] = H0[5];
context->Intermediate_Hash[6] = H0[6];
context->Intermediate_Hash[7] = H0[7];
context->Computed = 0;
context->Corrupted = 0;
return shaSuccess;
}
/*
* SHA224_256ResultN
*
* Description:
* This helper function will return the 224-bit or 256-bit message
* digest into the Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 28th/32nd element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest: [out]
* Where the digest is returned.
* HashSize: [in]
* The size of the hash, either 28 or 32.
*
* Returns:
* sha Error Code.
*/
static int
SHA224_256ResultN(SHA256Context * context,
uint8_t Message_Digest[], int HashSize)
{
int i;
if (!context || !Message_Digest)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (!context->Computed)
SHA224_256Finalize(context, 0x80);
for (i = 0; i < HashSize; ++i)
Message_Digest[i] = (uint8_t)
(context->Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
return shaSuccess;
}

1090
microstack/sha384-512.c Normal file

File diff suppressed because it is too large Load Diff