Nodejs предоставляет довольно скромные возможности IPC в принципе, а для windows уж и подавно. Конечно, можно для коммуникации в пределах одной машины делать клиент-сервера на сокетах, если это windows. Так же можно юзать UNIX Sockets для линукса и прочих производных, которые это дело поддерживают. Так же известны костыли с mkfifo, но это *nix и потому нам не интересны. В официальной документации (на данный момент для версии v0.10.26) ничего про IPC винде не сказано в принципе. Можно юзать модуль CLUSTER, но мне это решение показалось топорным, так как идеальным для меня было бы некая IPC, от которой мог бы абстрагироваться класс Socket.
/* * Initialize a pipe. The last argument is a boolean to indicate if * this pipe will be used for handle passing between processes. */UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); /* * Opens an existing file descriptor or HANDLE as a pipe. */UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file); /* * Bind the pipe to a file path (UNIX) or a name (Windows.) * * Paths on UNIX get truncated to `sizeof(sockaddr_un.sun_path)` bytes, * typically between 92 and 108 bytes. */UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
открываем uv_pipe_open (src/win/pipe.c), видим классическую картину :
/* Creates a pipe server. */int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
uv_loop_t* loop = handle->loop;
int i, err, nameSize;
uv_pipe_accept_t* req;
// ---------8<--------------------
handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
// ---------8<--------------------
return uv_translate_sys_error(err);
}
То что надо. Все уже написано до нас. Осталось найти как это использовать.
В ноде этот код вызывается из pipe_wrap.cc :
Handle<Value> PipeWrap::Open(const Arguments& args) {
HandleScope scope;
UNWRAP(PipeWrap)
int fd = args[0]->IntegerValue();
uv_pipe_open(&wrap->handle_, fd);
return scope.Close(v8::Null());
}
Сам же PipeWrap проврапплен в жс под видом нативного модуля pipe_wrap и может быть найден простым вызовом require(‘pipe_wrap’) :
NODE_MODULE(node_pipe_wrap, node::PipeWrap::Initialize)
Следующий шаг — поиск pipe_wrap по модулям в папке node/lib/ Модуль используется по своему прямому назначению, в net.js для создания пайпа
// constructor for lazy loading
function createPipe() {
var Pipe = process.binding('pipe_wrap').Pipe;
return new Pipe();
}
// constructor for lazy loading
function createTCP() {
var TCP = process.binding('tcp_wrap').TCP;
return new TCP();
} и (ура!) он же используется в классе Socket, который так хотелось использовать в IPC :
Socket.prototype.connect = function(options, cb) {
if (this.write !== Socket.prototype.write)
this.write = Socket.prototype.write;
if (typeof options !== 'object') {
// Old API:
// connect(port, [host], [cb])
// connect(path, [cb]);
var args = normalizeConnectArgs(arguments);
return Socket.prototype.connect.apply(this, args);
}
if (this.destroyed) {
this._readableState.reading = false;
this._readableState.ended = false;
this._writableState.ended = false;
this._writableState.ending = false;
this._writableState.finished = false;
this.destroyed = false;
this._handle = null;
}
var self = this;
var pipe = !!options.path;
if (!this._handle) {
this._handle = pipe ? createPipe() : createTCP();
initSocketHandle(this);
} Но это для коннекта. Что касаемо серверной части кода, то тут не обойтись без костылей. Дело в том, что просто так не заставить ноду слушать именованный пайп, так как,
1) для начала, имя пайпа не очевидно. Оно по всем канонам windows обязано выглядеть как .pipepipe_name
2) Сервер (net.XXX) создает экземпляр пайпа только если в качестве порта и типа адреса (addressType) передано -1, о чем, опять таки можн узнать из кода :
var createServerHandle = exports._createServerHandle =
function(address, port, addressType, fd) {
var r = 0;
// assign handle in listen, and clean up if bind or listen fails
var handle;
if (typeof fd === 'number' && fd >= 0) {
try {
handle = createHandle(fd);
}
catch (e) {
// Not a fd we can listen on. This will trigger an error.
debug('listen invalid fd=' + fd + ': ' + e.message);
process._errno = 'EINVAL'; // hack, callers expect that errno is set
return null;
}
handle.open(fd);
handle.readable = true;
handle.writable = true;
return handle;
} else if (port == -1 && addressType == -1) { //!!! <------------------------------
handle = createPipe();
if (process.platform === 'win32') {
var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES);
if (!isNaN(instances)) {
handle.setPendingInstances(instances);
}
}
} else {
handle = createTCP();
}
if (address || port) {
debug('bind to ' + address);
if (addressType == 6) {
r = handle.bind6(address, port);
} else {
r = handle.bind(address, port);
}
}
if (r) {
handle.close();
handle = null;
}
return handle;
};
Пришло время экспериментов и итогов. Так как мы можем создать пайп и юзать его в Socket, то нам доступна вся сетевая подсистема ноды. То есть на том конце пайпа может быть, например, веб-сервер или просто сервер, ожидающий команд. Вот пример использования в качестве сервера:
var net = require('net');
var util = require('util');
var http = require('http');
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World');
}).listen('\.pipeteeest2', -1 /*!!!!!!*/, -1 /*!!!!!!*/);
console.log('Server running at ', '\.pipeteeest2'); И по все тойже причины (Socket), нам доступны и клиенты для такого локального хттп сервера. Для хттп нам заботливо предоставили Agent API, позволяя хукать открытие соединения и направлять сокет куда угодно:
var a = new http.Agent();
options = {
host: 'www.localhost.com',
port: 80,
path: '/index.html',
method: 'GET'
};
a.createConnection = function () {
return ((new net.Socket()).connect('\.pipeteeest2'));
};
var req = http.request(options, function (res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function (e) {
console.log("Got error " + e.message);
});
req.end();
На этом все. тему виндозного IPC считаю раскрытой.
Чтобы взломать сеть Wi-Fi с помощью Kali Linux, вам нужна беспроводная карта, поддерживающая режим мониторинга…
Работа с консолью считается более эффективной, чем работа с графическим интерфейсом по нескольким причинам.Во-первых, ввод…
Конечно, вы также можете приобрести подписку на соответствующую услугу, но наличие SSH-доступа к компьютеру с…
С тех пор как ChatGPT вышел на арену, возросла потребность в поддержке чата на базе…
Если вы когда-нибудь окажетесь в ситуации, когда вам нужно взглянуть на спектр беспроводной связи, будь…
Elastic Security стремится превзойти противников в инновациях и обеспечить защиту от новейших технологий злоумышленников. В…
View Comments
a - чет почти не используется, наверно вместо "http.request" хотели написать "a.request"...