How to implement client side multiplexing using thrift in nodejs?
I tried the below code, but in vain.
var transport = thrift.TBufferedTransport;
var protocol = thrift.TBinaryProtocol;
var multiplexer = thrift.Multiplexer;
var ip = 'localhost';
var port = 9090;
var connection = thrift.createConnection(ip, port, {
transport : transport,
protocol : protocol
});
multiplexer();
var client = multiplexer.prototype.createClient(
"myServiceName", myServiceClient, connection
);
When I use the above client and call a method/function that is defined in my service,
connection is being made smoothly (no connection error) and
service method/function runs smoothly and returns the output.
But upon receiving the data (buffered) connection.js in thrift npm module throws "Cannot set property '0' of undefined" error.
On further investigation I found that seqid which is set on each client creation, is not being set.
Can someone please help me on this?
I found this to be the solution for the client:
var transport = thrift.TBufferedTransport;
var protocol = thrift.TBinaryProtocol;
var multiplexer = thrift.Multiplexer;
var ip = 'localhost';
var port = 9090;
var connection = thrift.createConnection(ip, port, {
transport : transport,
protocol : protocol
});
var multiplexer = new thrift.Multiplexer();
var client = multiplexer.createClient(
"myServiceName", myServiceClient, connection
);
Related
I am trying to create a TCP game server (for an old version of Minecraft), and I want to use Node.js as the server software. I have created a basic socket server, and I am wondering what the best way to go about parsing the data buffers would be?
Here's my code right now:
const net = require('net')
const serialize = require('node-serialize');
const server = net.createServer();
server.on('connection', (socket) => {
socket.on('data', (buffer) => {
let packetID = buffer.readUInt8(0);
console.log(`Packet ID: ${packetID}`)
switch (packetID) {
case 1:
// Login Request
// Log some info about the request
let protocol = buffer.readUIntBE(2, 3)
let playername = buffer.slice(7, buffer.length).toString()
console.log(`Player name: ${playername}`)
console.log(`Client protocol version: ${protocol}`)
console.log(buffer)
// Send login confirmation packet
var packetInfo = [0x01, 0]
var entityID = intToByteArray(1298)
var seed = intToByteArray(971768181197178410)
var mode = [0]
var dimension = [0]
var difficulty = [1]
var height = [128]
var maxPlayers = [8]
var buff = Buffer.from([].concat.apply([], [packetInfo, entityID, seed, mode, dimension, difficulty, height, maxPlayers]))
console.log(`Bytes: ${buff.byteLength}`)
//socket.write(buff)
// Disconnect/Kick Packet
var buffr = stringToByteArray("§eKicked from the server (cause world doesn't load yet)")
var packetbugger = [0xFF, 0, buffr.length / 2, 0]
var finalbuffr = Buffer.from([].concat.apply([], [packetbugger, buffr]))
socket.write(finalbuffr)
case 2:
// Handshake
// Sends a "-"
console.log(serialize.unserialize(buffer).Username);
socket.write(Buffer.from([0x02, 0, 1, 0, 0x2d]))
}
})
socket.on('error', (error) => {
console.error(error)
})
})
server.listen("25565", "localhost")
I think that there's probably a better way to parse packets than what I am doing. Every packet that Minecraft sends to the server has it's own id, as detailed on wiki.vg. Here's a sample packet structure for a server to client packet:
How would I be able to retrieve the readable data from a packet buffer in Node.js? For example, I'd like to be able to extract the player name string from the packet. However, the most important thing for me would be extracting the packet ID in hex form. I have tried, but I am unable to do so. Any help or suggestions as to how to go about this would be massively appreciated.
Also, how would I be able to craft my own packet in the same format as the picture above? All of these are questions I am struggling to find good answers to.
I'm building a simple, STARTTLS capable POP3 Proxy in Node.JS and I'm having quite a hard time.
The proxy serves as a front-end for many back-end servers, so it must load their certificates dynamically, depending on the Client's connection.
I'm trying to use the SNICallback, which brings me the servername the client uses, but I can't set the right certificate after this, because I need one certificate before I have this call, when I create the secure context.
The code is as bellow:
// Load libraries
var net = require('net');
var tls = require('tls');
var fs = require('fs');
// Load certificates (created with openssl)
var certs = [];
for (var i = 1; i <= 8; i++) {
var hostName = 'localhost' + i;
certs[hostName] = {
key : fs.readFileSync('./private-key.pem'),
cert : fs.readFileSync('./public-cert' + i + '.pem'),
}
}
var server = net.createServer(function(socket) {
socket.write('+OK localhost POP3 Proxy Ready\r\n');
socket.on('data', function(data) {
if (data == "STLS\r\n") {
socket.write("+OK begin TLS negotiation\r\n");
upgradeSocket(socket);
} else if (data == "QUIT\r\n") {
socket.write("+OK Logging out.\r\n");
socket.end();
} else {
socket.write("-ERR unknown command.\r\n");
}
});
}).listen(10110);
and upgradeSocket() is as follows:
function upgradeSocket(socket) {
// I need this 'details' or handshake will fail with a message:
// SSL routines:ssl3_get_client_hello:no shared cipher
var details = {
key : fs.readFileSync('./private-key.pem'),
cert : fs.readFileSync('./public-cert1.pem'),
}
var options = {
isServer : true,
server : server,
SNICallback : function(serverName) {
return tls.createSecureContext(certs[serverName]);
},
}
sslcontext = tls.createSecureContext(details);
pair = tls.createSecurePair(sslcontext, true, false, false, options);
pair.encrypted.pipe(socket);
socket.pipe(pair.encrypted);
pair.fd = socket.fd;
pair.on("secure", function() {
console.log("TLS connection secured");
});
}
It handshakes correctly but the certificate I use is the static one in 'details', not the one I get in the SNICallback.
To test it I'm running the server and using gnutls-cli as a Client:
~$ gnutls-cli -V -s -p 10110 --crlf --insecure -d 5 localhost3
STLS
^D (Control+D)
The above command is supposed to get me the 'localhost3' certificate but it's getting the 'localhost1' because it's defined in 'details' var;
There are just too many examples throughout the internet with HTTPS or for TLS Clients, which it's a lot different from what I have here, and even for Servers as well but they're not using SNI. Any help will be appreciated.
Thanks in advance.
The answer is quite simple using tls.TLSSocket, though there is a gotcha with the listeners.
You have to remove all the listeners from the regular net.Socket you have, instantiate a new tls.TLSSocket using your net.Socket and put the listeners back on the tls.TLSSocket.
To achieve this easily, use a wrapper like Haraka's tls_socket pluggableStream over the regular net.Socket and replace the "upgrade"
function to something like:
pluggableStream.prototype.upgrade = function(options) {
var self = this;
var socket = self;
var netSocket = self.targetsocket;
socket.clean();
var secureContext = tls.createSecureContext(options)
var tlsSocket = new tls.TLSSocket(netSocket, {
// ...
secureContext : secureContext,
SNICallback : options.SNICallback
// ...
});
self.attach(tlsSocket);
}
and your options object would have the SNICallback defined as:
var options {
// ...
SNICallback : function(serverName, callback){
callback(null, tls.createSecureContext(getCertificateFor(serverName));
// ...
}
}
Trying to cluster Socket.io using net.createServer. All examples are using IP to split what connection goes to witch node. However I'm using 4 servers with a load balancer that points ip;s to the different servers.
So in node cluster I would like to use an unique id to point the connection to a specific cluster.
Figure that each user that wants to connect can add a parameter to the connection url ws://localhost/socket.io?id=xxyyzz
How can I get the connection url in net.createServer
todays code for ip:
var server = net.createServer({ pauseOnConnect: true }, function(connection) {
// We received a connection and need to pass it to the appropriate
// worker. Get the worker for this connection's source IP and pass
// it the connection.
var remote = connection.remoteAddress;
var local = connection.localAddress;
var ip = (remote+local).match( /[0-9]+/g )[0].replace(/,/g, '');
var wIndex = ip % num_processes;
var worker = workers[wIndex];
worker.send('sticky-session:connection', connection);
});
I am planning to implement a server using Bluetooth API using J2ME. I want multiple clients to be able to connect to it at the same time but I could not find much on the NET.
UUID uuid = new UUID("1101", false);
String SurveyAnswer="";
//Create the service url
String connectionString = "btspp://localhost:" + uuid + ";name=xyz";
//open server url
StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier) Connector.open(connectionString);
//Wait for client connection
System.out.println("\nServer Started. Waiting for clients to connect...");
while(true){
StreamConnection connection = streamConnNotifier.acceptAndOpen();
}
How do I modify these codes in order for it to work as a multi client server?
That's a standard problem. When the StreamConnection connection = streamConnNotifier.acceptAndOpen(); returns you have to spawn a Thread which uses the connection. The main Thread then reenters the accept and waits for next connection.
UUID uuid = new UUID("1101", false); String SurveyAnswer="";
//Create the service url
String connectionString = "btspp://localhost:" + uuid + ";name=xyz";
//open server url
StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier)
Connector.open(connectionString);
//Wait for client connection
System.out.println("\nServer Started. Waiting for clients to connect...");
while(true){
StreamConnection connection = streamConnNotifier.acceptAndOpen();
System.out.println("Client connected starting communication");
new CommunicationThread(connection).start();
}
In the class CommunicationThreads run method you can then get the streams and communicate.
hello all
I looked at the at the redis-node-client source (relevant part is shown bellow) and I see that it connects to redis via the 'net' package, which is TCP based.
line 370
exports.createClient = function (port, host, options) {
var port = port || exports.DEFAULT_PORT;
var host = host || exports.DEFAULT_HOST;
var client = new Client(net.createConnection(port, host), options);
client.port = port;
client.host = host;
return client;
};
I was wondering if there's a more direct client for redis, preferably via domain-sockets or something of that sort. Im using redis localy, as cache, without going over the wire so its unnecessary to encode/decode messages with TCP headers...
thank you
Unix Domain Socket support appears to have landed in Redis as of Nov 4th.
http://code.google.com/p/redis/issues/detail?id=231
To connect to a Unix Domain Socket, you need to supply the pathname to net.createConnection. Maybe something like this in redis-node-client:
exports.createSocketClient = function (path, options) {
var client = new Client(net.createConnection(path), options);
client.path = path;
return client;
};