linux-device
Advanced tools
Comparing version 2.0.10 to 2.0.11
@@ -6,5 +6,19 @@ "use strict"; | ||
const util = require('util'); | ||
const fs = require('fs'); | ||
const _fs = require('fs'); | ||
const tty = require('tty'); | ||
const net = require('net'); | ||
const FH = require('bindings')('DeviceHandle'); | ||
const fs = { | ||
open: util.promisify(_fs.open), | ||
close: util.promisify(_fs.close), | ||
writeFile: util.promisify(_fs.writeFile), | ||
fstat: util.promisify(_fs.fstat), | ||
createReadStream: _fs.createReadStream, | ||
createWriteStream: _fs.createWriteStream, | ||
constants: _fs.constants, | ||
}; | ||
const kSource = Symbol('source'); | ||
@@ -56,2 +70,3 @@ | ||
options = options || {}; | ||
if(typeof options === 'string') options = {path: options}; | ||
const mode = options.mode || CONSTANTS.O_RDWR; | ||
@@ -64,3 +79,2 @@ this[kSource] = { | ||
parser: options.parser || undefined, | ||
handle: new FH(options.path), | ||
reading: 0, | ||
@@ -72,2 +86,80 @@ forcedDataSize: options.absoluteSize, | ||
__onEnd(err) { | ||
if(err) this.close().catch(e => {}); | ||
} | ||
__onError(err) { | ||
if(err) this.close().catch(e => {}); | ||
this.emit(err); | ||
} | ||
__pushSmart(res) { | ||
let result = true; | ||
if(res && this[kSource].parser) { | ||
if(!this[kSource].emitter) { | ||
this[kSource].emitter = new EventEmitter(); | ||
this[kSource].emitter.on('data', (data) => this.push(data)); | ||
} | ||
this[kSource].parser(this[kSource].emitter, res); | ||
} if(res && this[kSource].forcedDataSize) { | ||
for(let i = 0; i < res.length; i+= this[kSource].forcedDataSize) { | ||
result = this.push(res.slice(i, i+this[kSource].forcedDataSize)); | ||
} | ||
} else { | ||
result = this.push(res); | ||
} | ||
return result; | ||
} | ||
async _createStreams() { | ||
if(tty.isatty(this.fd)) { | ||
if(this[kSource].readable) { | ||
this[kSource].inStream = new tty.ReadStream(this.fd); | ||
this[kSource].inStream.setRawMode(true); | ||
} | ||
if(this[kSource].writable) { | ||
this[kSource].outStream = new tty.WriteStream(this.fd); | ||
} | ||
} else { | ||
const fstat = await fs.fstat(this.fd); | ||
if(fstat.isFile() || fstat.isCharacterDevice() || fstat.isBlockDevice() ) { | ||
if(this[kSource].readable) | ||
this[kSource].inStream = fs.createReadStream(null, {fd: this.fd, autoClose: false}); | ||
if(this[kSource].writable) | ||
this[kSource].outStream = fs.createWriteStream(null, {fd: this.fd, autoClose: false}); | ||
} else if(fstat.isSocket()) { | ||
this[kSource].inStream = this[kSource].outStream | ||
= new net.Socket({ | ||
fd: this.fd, | ||
readable: this[kSource].readable, | ||
writable: this[kSource].writable, | ||
}) | ||
} else { | ||
throw new Error("unknown_type"); | ||
} | ||
} | ||
if(this[kSource].outStream && this[kSource].outStream != this[kSource].inStream) { | ||
this[kSource].outStream.on('error', err => this.__onError(err)); | ||
} | ||
if(this[kSource].inStream) { | ||
this[kSource].inStream.on('error', err => this.__onError(err)); | ||
this[kSource].inStream.on('end', err => this.__onEnd(err)); | ||
this[kSource].inStream.pause(); | ||
this[kSource].inStream.on('data', (data) => { | ||
if(!this.__pushSmart(data)) { | ||
this[kSource].inStream.pause(); | ||
} | ||
}); | ||
if(this[kSource].resumeOnCreate){ | ||
delete this[kSource].resumeOnCreate; | ||
this[kSource].inStream.resume(); | ||
} | ||
} | ||
} | ||
/** | ||
@@ -80,4 +172,5 @@ * Opens the device | ||
if(this[kSource].tainted) throw new Error('attempt to reuse closed DeviceHandle'); | ||
const res = await this[kSource].handle.open(this[kSource].mode | CONSTANTS.O_DSYNC); | ||
const res = await fs.open(this[kSource].path, this[kSource].mode); | ||
this.fd = res; | ||
await this._createStreams(); | ||
this.emit('open', res); | ||
@@ -94,9 +187,15 @@ if(this[kSource].reading) { | ||
async close() { | ||
if(this[kSource].outStream) { | ||
this[kSource].outStream.cork(); | ||
this[kSource].outStream.removeAllListeners(); | ||
delete this[kSource].outStream; | ||
} | ||
if(this[kSource].inStream) { | ||
this[kSource].inStream.pause(); | ||
this[kSource].inStream.removeAllListeners(); | ||
delete this[kSource].inStream; | ||
} | ||
if(!this.fd) return; | ||
await fs.close(this.fd); | ||
delete this.fd; | ||
if(this[kSource].readable) { | ||
this.push(null); | ||
this[kSource].tainted = true; | ||
} | ||
await this[kSource].handle.close(); | ||
this.emit('close'); | ||
@@ -122,3 +221,3 @@ } | ||
if(!this.fd) throw new Error('not_open'); | ||
await this[kSource].handle.ioctl(direction, type, cmd, data||Buffer.alloc(0)); | ||
await FH.ioctl(this.fd, direction, type, cmd, data||Buffer.alloc(0)); | ||
} | ||
@@ -133,3 +232,3 @@ | ||
if(!this.fd) throw new Error('not_open'); | ||
await this[kSource].handle.ioctlRaw(cmd, data||Buffer.alloc(0)); | ||
await FH.ioctlRaw(this.fd, cmd, data||Buffer.alloc(0)); | ||
} | ||
@@ -167,10 +266,4 @@ | ||
static async gpio(gpio, value) { | ||
return new Promise((resolve, reject) => { | ||
fs.writeFile( SYSFS_GPIO+'/export', ''+gpio, function(err) { | ||
fs.writeFile(SYSFS_GPIO+'/gpio'+gpio+'/direction', value ? 'high': 'low', function(err) { | ||
if(err) return reject(err); | ||
resolve(err); | ||
}); | ||
}); | ||
}); | ||
await fs.writeFile( SYSFS_GPIO+'/export', ''+gpio).catch(e => {}); | ||
await fs.writeFile(SYSFS_GPIO+'/gpio'+gpio+'/direction', value ? 'high': 'low'); | ||
}; | ||
@@ -192,2 +285,9 @@ | ||
_read(size) { | ||
if(this[kSource].inStream) | ||
this[kSource].inStream.resume(); | ||
else | ||
this[kSource].resumeOnCreate = true; | ||
} | ||
async _writePromise(chunk, encoding) { | ||
@@ -197,47 +297,8 @@ if(!this.fd) throw new Error('not_open'); | ||
if(chunk.interval && chunk.repetitions) { | ||
return await this[kSource].handle.writeRepeated(chunk, chunk.interval, chunk.repetitions); //retain chunks | ||
return await FH.writeRepeated(this.fd, chunk, chunk.interval, chunk.repetitions); //retain chunks | ||
} else { | ||
return await this[kSource].handle.write(chunk); //retain chunk | ||
return util.promisify(this[kSource].outStream.write).call(this[kSource].outStream, chunk, encoding); //retain chunk | ||
} | ||
} | ||
_read() { | ||
if(!this[kSource].readable) return; | ||
this[kSource].reading += 1; | ||
if(!this.fd) return; | ||
this[kSource].handle.read((err, res) => { | ||
if(!this.fd) return; | ||
if(err) { | ||
return process.nextTick(() => { | ||
this.destroy(err); | ||
}); | ||
} | ||
if(res && this[kSource].parser) { | ||
if(!this[kSource].emitter) { | ||
this[kSource].emitter = new EventEmitter(); | ||
this[kSource].emitter.on('data', (data) => this.push(data)); | ||
} | ||
this[kSource].parser(this[kSource].emitter, res); | ||
} else if(res && this[kSource].forcedDataSize) { | ||
for(let i = 0; i < res.length; i+= this[kSource].forcedDataSize) { | ||
this.push(res.slice(i, i+this[kSource].forcedDataSize)); | ||
} | ||
} else { | ||
this.push(res); | ||
} | ||
if(!res) return this[kSource].handle.stopReading(); | ||
this[kSource].reading -= 1; | ||
if(this[kSource].reading < 0) { | ||
this[kSource].reading = 0; | ||
this[kSource].handle.stopReading(); | ||
} | ||
}); | ||
} | ||
_destroy(error, callback) { | ||
@@ -244,0 +305,0 @@ if(!this.fd) return; |
{ | ||
"name": "linux-device", | ||
"version": "2.0.10", | ||
"version": "2.0.11", | ||
"description": "Native addon to communicate with linux devices (can also be used for sockets or FIFOs)", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
Sorry, the diff of this file is not supported yet
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
1132
1097366
2