Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature request: fork call and IPC #35

Open
zh99998 opened this issue Nov 5, 2016 · 1 comment
Open

feature request: fork call and IPC #35

zh99998 opened this issue Nov 5, 2016 · 1 comment

Comments

@zh99998
Copy link

zh99998 commented Nov 5, 2016

sometimes we want to execute elevated JavaScript script instead of external process.
if there is something like child_process.fork() call, it will be great.

documents about node.js native fork and ipc:

https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options

note that spawn support IPC too, just specific it in stdio

https://nodejs.org/api/child_process.html#child_process_options_stdio

and in child process
https://nodejs.org/api/process.html#process_process_send_message_sendhandle_options_callback
https://nodejs.org/api/process.html#process_event_message

I've done something to simulate this ipc. it's ugly and not robust, but works for me.

it will break normal stdin/stdout since I'm using this to transfer messages. I don't know what does node.js native child_process ipc implement, maybe unixsock or named pipe?

here is my code:

import {remote} from "electron";

const Sudo = require('electron-sudo').default;

Sudo.prototype.fork = async function (modulePath, args, options) {
    let child = await this.spawn(remote.app.getPath('exe'), ['-e', modulePath].concat(args), options);
    readline.createInterface({input: child.stdout}).on('line', (line) => {
        child.emit('message', JSON.parse(line));
    });
    child.send = (message, sendHandle, options, callback)=> {
        child.stdin.write(JSON.stringify(message) + os.EOL);
        if (callback) {
            callback()
        }
    };
    return child
};

in index.js

function handleElevate() {
    if (process.argv[1] == '-e') {
        app.dock.hide();
        const os = require('os');
        const readline = require('readline');
        process.send = (message, sendHandle, options, callback)=> process.stdout.write(JSON.stringify(message) + os.EOL, callback);
        process.stdin.on('end', ()=> process.emit('disconnect'));
        readline.createInterface({input: process.stdin}).on('line', (line) => process.emit('message', JSON.parse(line)));
        require("./" + process.argv[2]);
        return true;
    }
}

if (handleElevate()) {
    return;
}

in my elevated module maotama.js, I'm using this to send raw-socket

const raw = require("raw-socket");
let socket = raw.createSocket({protocol: raw.Protocol.UDP});

let connect = (local_port, remote_port, remote_address)=> {
    let buffer = new Buffer(9);
    buffer.writeUInt16BE(local_port, 0);
    buffer.writeUInt16BE(remote_port, 2);
    buffer.writeUInt16BE(buffer.length, 4);
    socket.send(buffer, 0, buffer.length, remote_address, (error, bytes) => {
        if (error) {
            throw(error);
        }
    })
};

process.on('message', (message)=> {
    connect(...message.arguments);
});

process.on('disconnect', process.exit);

and calling

let child = await new Sudo({name: 'MyCard'}).fork('maotama')

child.send({
    action: 'connect',
    arguments: [app.network.port, port, address]
})
@automation-stack
Copy link
Owner

@zh99998 looks good, i'll add it soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants