Transfer UDP socket in node.js from Application to HTTP - http

Is it possible to transfer a Socket coming from a application to http via NodeJS?
I send my socket with a application (in c++) in UDP or TCP(if impossible in UDP...) to NodeJS.
My script from NodeJS:
var server = dgram.createSocket("udp4");
server.on("message", function (content, rinfo)
{
console.log("socket: " + content + " from " + rinfo.address + ":" + rinfo.port); });
server.on("listening", function () {
});
server.bind(7788);
Up to now does that function, but then how to transfer my socket to Socket.io for example?
I would like to send the socket to Socket.io (for example) for transfer the socket to HTTP. By using a function like this for example, but without renew a establishing a connection to socket.io :
io.sockets.on('connection', function (socket) {
socket.emit(content);
});
Thanks you for your help.
++ Metra.

Here's a complete example with a socket.io server, a web server sending out a very simple page (it will just log all messages to console) and an UDP socket listening for messages, passing them to all connected clients:
var http = require('http'),
dgram = require('dgram'),
socketio = require('socket.io');
var app = http.createServer(handleRequest),
io = socketio.listen(app),
socket = dgram.createSocket('udp4');
socket.on('message', function(content, rinfo) {
console.log('got message', content, 'from', rinfo.address, rinfo.port);
io.sockets.emit('udp message', content.toString());
});
function handleRequest(req, res) {
res.writeHead(200, {'content-type': 'text/html'});
res.end("<!doctype html> \
<html><head> \
<script src='/socket.io/socket.io.js'></script> \
<script> \
var socket = io.connect('localhost', {port: 8000}); \
socket.on('udp message', function(message) { console.log(message) }); \
</script></head></html>");
}
socket.bind(7788);
app.listen(8000);
Update: As io.sockets.emit shows, all messages received on the UDP port 7788 are sent to all connected clients. If you want to route them based on some data in the message or similar, you could use Socket.IO's "room" feature: io.sockets.of(someRoom).emit. In the connection handler for Socket.IO, you can join each client to some room.

Related

Fail to connect to socket.io server on Window Server in dotnet core

I host a very simple node socket IO application on my Window Server, below are the code sample.
// socket.io 3.1.2"
const port = 30080;
const httpServer = require("http").createServer();
const io = require("socket.io")(httpServer, {
cors: {
origin: '*',
methods: ["GET", "POST"],
allowedHeaders: ["Access-Control-Allow-Origin"],
credentials: false
}
});
io.on("connection", socket => {
console.log('On Connection');
io.emit("message", 'Welcome to Socket Io.');
});
And I wrote some code to try connect to my socket IO server in a HTML File and work well. below are the code sample.
// <script src="https://cdn.socket.io/3.1.3/socket.io.min.js"></script>
const socket = io("http://myserverip:30080", {
withCredentials: false,
extraHeaders: {
"Access-Control-Allow-Origin": "*"
}
});
socket.on("connect", () => {
console.log('connect');
});
socket.on("message", (message) => {
console.log(message);
});
But when I try to use those above code in my .NET Core web application, I get the error "ERR_SSL_PROTOCOL_ERROR". Even I publish my web application on the Window Server still getting the same error message.
I have tried http, https, ws and wss protocol. None of these work. How can I get this possibly working?
I do not see the following in your server side code:
httpServer.listen()
Do you have a reverse proxy between your client and the server?
I would expect no SSL related error based on you code.
I would also use socket.io version 4 just for future maintenance reasons.

How to connect meteor server to another tcp server via tcp socket

I want to create a meteor application that connect meteor server to another tcp server,
that is meteor server is client side and another tcp server is server side.
1.It like WebSocket of browser ,but I want use it on meteor server ,not on meteor client .
WebSocket using like :
var tcpServer = "ws://some.tcpServer.org/";
socket = new WebSocket(tcpServer,options);
socket.onopen = function(evt) { onOpen(evt) };
socket.onclose = function(evt) { onClose(evt) };
socket.onmessage = function(evt) { onMessage(evt) };
socket.onerror = function(evt) { onError(evt) };
2.Maybe as follow :
if (Meteor.isServer) {
Meteor.startup(function () {
var tcpServer = "ws://some.tcpServer.org/";
socket = new socketClient(tcpServer,options);
socket.onopen = function(evt) { onOpen(evt) };
socket.onclose = function(evt) { onClose(evt) };
socket.onmessage = function(evt) { onMessage(evt) };
socket.onerror = function(evt) { onError(evt) };
})
}
3.Or ...
var net = Npm.require('net');
net.createServer(function(socket){...} is for server side , not fit for my idea.
Maybe like net.createClient(function(tcpServer, options ){...} , but no this method.
I had been looking around but i do not see a method for Meteor. Can anyone give any pointers for me to start?
Thank a lot !
There are several problems with what you described.
WebSocket, which works over HTTP, and TCP are completely different protocols. You will not be able to open a WebSocket connection to a TCP server.
To have the Meteor server communicate with another server over TCP, you'll want to use Node's net API. To use this with Meteor, you'll need to use async callbacks in a way that is compatible with Fibers; see this blog post for an overview and https://stackoverflow.com/a/21542356/586086.
Here you have link to working plugin:
websocketify on atmosphere.com

node.js HTTP request parsing (using net module)

Writing an HTTP simple server on top of Net node.js module, not using HTTP module.
I have a server listening at localhost:port with a socket opened.
socket.on('data', function(data){
clientMsg += data;
});
Once I type the address in the browser I can see the GET request is in clientMsg.
In order to return a response I use:
socket.on('close', function(){ something response generating here});
But this is not working well as it sends the response only once I click ESC or STOP in the browser.
So the question is, how can I know the browser finished sending the message and waits for a response, without closing the connection?
You would use the event connection instead of close.
Event: 'connection'
Also, this is the structure that is documented for such a server:
var net = require('net');
var server = net.createServer(function(c) { //'connection' listener
console.log('server connected');
c.on('end', function() {
console.log('server disconnected');
});
c.write('hello\r\n');
c.pipe(c);
});
server.listen(8124, function() { //'listening' listener
console.log('server bound');
});

HTTPS Proxy Server in node.js

I am developing a node.js proxy server application and I want it to support HTTP and HTTPS(SSL) protocols (as server).
I'm currently using node-http-proxy like this:
const httpProxy = require('http-proxy'),
http = require('http');
var server = httpProxy.createServer(9000, 'localhost', function(req, res, proxy) {
console.log(req.url);
proxy.proxyRequest(req, res);
});
http.createServer(function(req, res) {
res.end('hello!');
}).listen(9000);
server.listen(8000);
I setup my browser to use HTTP proxy on localhost:8000 and it works. I also want to catch HTTPS requests (ie. setup my browser to use localhost:8000 as HTTPS proxy as well and catch the requests in my application). Could you please help me how can I do that?
PS:
If I subscribe to upgrade event of httpProxy server object I can get the requests but I don't know how to forward the request and send response to client:
server.on('upgrade', function(req, socket, head) {
console.log(req.url);
// I don't know how to forward the request and send the response to client
});
Any helps would be appreciated.
Solutions barely exist for this, and the documentation is poor at best for supporting both on one server. The trick here is to understand that client proxy configurations may send https requests to an http proxy server. This is true for Firefox if you specify an HTTP proxy and then check "same for all protocols".
You can handle https connections sent to an HTTP server by listening for the "connect" event. Note that you won't have access to the response object on the connect event, only the socket and bodyhead. Data sent over this socket will remain encrypted to you as the proxy server.
In this solution, you don't have to make your own certificates, and you won't have certificate conflicts as a result. The traffic is simply proxied, not intercepted and rewritten with different certificates.
// Install npm dependencies first
// npm init
// npm install --save url#0.10.3
// npm install --save http-proxy#1.11.1
var httpProxy = require("http-proxy");
var http = require("http");
var url = require("url");
var net = require('net');
var server = http.createServer(function (req, res) {
var urlObj = url.parse(req.url);
var target = urlObj.protocol + "//" + urlObj.host;
console.log("Proxy HTTP request for:", target);
var proxy = httpProxy.createProxyServer({});
proxy.on("error", function (err, req, res) {
console.log("proxy error", err);
res.end();
});
proxy.web(req, res, {target: target});
}).listen(8080); //this is the port your clients will connect to
var regex_hostport = /^([^:]+)(:([0-9]+))?$/;
var getHostPortFromString = function (hostString, defaultPort) {
var host = hostString;
var port = defaultPort;
var result = regex_hostport.exec(hostString);
if (result != null) {
host = result[1];
if (result[2] != null) {
port = result[3];
}
}
return ( [host, port] );
};
server.addListener('connect', function (req, socket, bodyhead) {
var hostPort = getHostPortFromString(req.url, 443);
var hostDomain = hostPort[0];
var port = parseInt(hostPort[1]);
console.log("Proxying HTTPS request for:", hostDomain, port);
var proxySocket = new net.Socket();
proxySocket.connect(port, hostDomain, function () {
proxySocket.write(bodyhead);
socket.write("HTTP/" + req.httpVersion + " 200 Connection established\r\n\r\n");
}
);
proxySocket.on('data', function (chunk) {
socket.write(chunk);
});
proxySocket.on('end', function () {
socket.end();
});
proxySocket.on('error', function () {
socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
socket.end();
});
socket.on('data', function (chunk) {
proxySocket.write(chunk);
});
socket.on('end', function () {
proxySocket.end();
});
socket.on('error', function () {
proxySocket.end();
});
});
Here is my NO-dependencies solution (pure NodeJS system libraries):
const http = require('http')
const port = process.env.PORT || 9191
const net = require('net')
const url = require('url')
const requestHandler = (req, res) => { // discard all request to proxy server except HTTP/1.1 CONNECT method
res.writeHead(405, {'Content-Type': 'text/plain'})
res.end('Method not allowed')
}
const server = http.createServer(requestHandler)
const listener = server.listen(port, (err) => {
if (err) {
return console.error(err)
}
const info = listener.address()
console.log(`Server is listening on address ${info.address} port ${info.port}`)
})
server.on('connect', (req, clientSocket, head) => { // listen only for HTTP/1.1 CONNECT method
console.log(clientSocket.remoteAddress, clientSocket.remotePort, req.method, req.url)
if (!req.headers['proxy-authorization']) { // here you can add check for any username/password, I just check that this header must exist!
clientSocket.write([
'HTTP/1.1 407 Proxy Authentication Required',
'Proxy-Authenticate: Basic realm="proxy"',
'Proxy-Connection: close',
].join('\r\n'))
clientSocket.end('\r\n\r\n') // empty body
return
}
const {port, hostname} = url.parse(`//${req.url}`, false, true) // extract destination host and port from CONNECT request
if (hostname && port) {
const serverErrorHandler = (err) => {
console.error(err.message)
if (clientSocket) {
clientSocket.end(`HTTP/1.1 500 ${err.message}\r\n`)
}
}
const serverEndHandler = () => {
if (clientSocket) {
clientSocket.end(`HTTP/1.1 500 External Server End\r\n`)
}
}
const serverSocket = net.connect(port, hostname) // connect to destination host and port
const clientErrorHandler = (err) => {
console.error(err.message)
if (serverSocket) {
serverSocket.end()
}
}
const clientEndHandler = () => {
if (serverSocket) {
serverSocket.end()
}
}
clientSocket.on('error', clientErrorHandler)
clientSocket.on('end', clientEndHandler)
serverSocket.on('error', serverErrorHandler)
serverSocket.on('end', serverEndHandler)
serverSocket.on('connect', () => {
clientSocket.write([
'HTTP/1.1 200 Connection Established',
'Proxy-agent: Node-VPN',
].join('\r\n'))
clientSocket.write('\r\n\r\n') // empty body
// "blindly" (for performance) pipe client socket and destination socket between each other
serverSocket.pipe(clientSocket, {end: false})
clientSocket.pipe(serverSocket, {end: false})
})
} else {
clientSocket.end('HTTP/1.1 400 Bad Request\r\n')
clientSocket.destroy()
}
})
I tested this code with Firefox Proxy Settings (it even asks for username and password!). I entered IP address of machine where this code is runned and 9191 port as you can see in the code. I also set "Use this proxy server for all protocols". I run this code locally and on VPS - in both cases works!
You can test your NodeJS proxy with curl:
curl -x http://username:password#127.0.0.1:9191 https://www.google.com/
I have created a http/https proxy with the aid of the http-proxy module: https://gist.github.com/ncthis/6863947
Code as of now:
var fs = require('fs'),
http = require('http'),
https = require('https'),
httpProxy = require('http-proxy');
var isHttps = true; // do you want a https proxy?
var options = {
https: {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('key-cert.pem')
}
};
// this is the target server
var proxy = new httpProxy.HttpProxy({
target: {
host: '127.0.0.1',
port: 8080
}
});
if (isHttps)
https.createServer(options.https, function(req, res) {
console.log('Proxying https request at %s', new Date());
proxy.proxyRequest(req, res);
}).listen(443, function(err) {
if (err)
console.log('Error serving https proxy request: %s', req);
console.log('Created https proxy. Forwarding requests from %s to %s:%s', '443', proxy.target.host, proxy.target.port);
});
else
http.createServer(options.https, function(req, res) {
console.log('Proxying http request at %s', new Date());
console.log(req);
proxy.proxyRequest(req, res);
}).listen(80, function(err) {
if (err)
console.log('Error serving http proxy request: %s', req);
console.log('Created http proxy. Forwarding requests from %s to %s:%s', '80', proxy.target.host, proxy.target.port);
});
The node-http-proxy docs contain examples of this. Look for "Proxying to HTTPS from HTTPS" at https://github.com/nodejitsu/node-http-proxy The configuration process is slightly different in every browser. Some have the option to use your proxy settings for all protocols; some you need to configure the SSL proxy separately.

Keep run into "ETIMEOUT, Timeout while contacting DNS servers" error when making http request in node.js

This error happens whenever the node process make a http request to get user's information from a web API.
The scenario is :
I'm running a TCP server using node, and when it get "login" request from a client, it will send a http GET request to another web API to retrieve the user's information.
While users increasing, the node process starts to throw the "ETIMEOUT" error when retrieving user's info. And once if the error happened, all the request after that will throw the same error.
I've tried to perform the same request with wget but everything is fine, so I think maybe it's not a network problem.
And strangely, after increasing the open file limit to 10,0000 using ulimit -n, it goes well until the next level user increment.
The fetch function is here:
fetchUserInfo = function(callback) {
var http = require('http');
var opt = {
agent: false,
host: 'www.someapi.net',
port: 80,
path: '/userInfo.php'
}
var body = '';
var req = http.request(opt, function(res) {
res.setEncoding('utf8');
res.on('data', function(chunk){
body += chunk;
});
res.on('end', function() {
if(callback) {
callback(body);
}
});
});
req.on('error', function(e) {
sys.log("User info fetch error: " + e.message);
if(callback) {
callback();
}
});
req.end();
}
My environment is Debian GNU/Linux 6.0 with node v0.4.10.

Resources