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

Updated relay server #373

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 118 additions & 62 deletions websocket-relay.js
Original file line number Diff line number Diff line change
@@ -1,89 +1,145 @@
"use strict";
// Use the websocket-relay to serve a raw MPEG-TS over WebSockets. You can use
// ffmpeg to feed the relay. ffmpeg -> websocket-relay -> browser
// Example:
// node websocket-relay yoursecret 8081 8082
// node websocket-relay
// ffmpeg -i <some input> -f mpegts http://localhost:8081/yoursecret

var fs = require('fs'),
http = require('http'),
WebSocket = require('ws');

if (process.argv.length < 3) {
console.log(
'Usage: \n' +
'node websocket-relay.js <secret> [<stream-port> <websocket-port>]'
);
process.exit();
}
//Configs
var cfg = {
ssl: true,
host: 'localhost',
input_port: 8081,
output_port: 8082,
ssl_key: 'privkey.key',
ssl_cert: 'pubcert.crt',
stream_secret: 'yoursecret',
record_stream: false,
stream_path: 'recordings/'
};
process.title = 'Stream Server';

var STREAM_SECRET = process.argv[2],
STREAM_PORT = process.argv[3] || 8081,
WEBSOCKET_PORT = process.argv[4] || 8082,
RECORD_STREAM = false;
// Node Configs (Don't touch)
var fs = require('fs');
var http = require('http');
var https = require('https');
var websocket = require('ws');
var ws_input = false;
var ws_output = false;

// Websocket Server
var socketServer = new WebSocket.Server({port: WEBSOCKET_PORT, perMessageDeflate: false});
socketServer.connectionCount = 0;
socketServer.on('connection', function(socket, upgradeReq) {
socketServer.connectionCount++;
console.log(
'New WebSocket Connection: ',
(upgradeReq || socket.upgradeReq).socket.remoteAddress,
(upgradeReq || socket.upgradeReq).headers['user-agent'],
'('+socketServer.connectionCount+' total)'
);
socket.on('close', function(code, message){
socketServer.connectionCount--;
console.log(
'Disconnected WebSocket ('+socketServer.connectionCount+' total)'
);
});
});
socketServer.broadcast = function(data) {
socketServer.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
// Input
var handleInputConnection = function(){
var app = http.createServer(onRequestInput);
app.headersTimeout = 0;
app.listen(cfg.input_port, cfg.host);

ws_input = new websocket.Server({server:app, perMessageDeflate:false});
ws_input.on('connection', function(client){
client.ip = client._socket.remoteAddress;

client.on('close', function(reasonCode, description){
console.log('['+client.ip+'] closed');
});

console.log('Stream ['+client.ip+'] connected');
});
};

// HTTP Server to accept incomming MPEG-TS Stream from ffmpeg
var streamServer = http.createServer( function(request, response) {
var onRequestInput = function(request, response){
var params = request.url.substr(1).split('/');

if (params[0] !== STREAM_SECRET) {
console.log(
'Failed Stream Connection: '+ request.socket.remoteAddress + ':' +
request.socket.remotePort + ' - wrong secret.'
);
response.end();
if (params[0] !== cfg.stream_secret) {
console.log('Failed stream connection: '+request.socket.remoteAddress+':'+request.socket.remotePort+' - wrong secret');
return response.end();
}

response.connection.setTimeout(0);
console.log(
'Stream Connected: ' +
request.socket.remoteAddress + ':' +
request.socket.remotePort
);

request.on('data', function(data){
socketServer.broadcast(data);
if (request.socket.recording) {
ws_output.broadcast(data);
if(request.socket.recording){
request.socket.recording.write(data);
}
});
request.on('end',function(){
console.log('close');
console.log('Stream end');
if (request.socket.recording) {
request.socket.recording.close();
}
});

// Record the stream to a local file?
if (RECORD_STREAM) {
var path = 'recordings/' + Date.now() + '.ts';
// Record the stream to a local file
if (cfg.record_stream) {
var path = stream_path + Date.now() + '.ts';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stream_path should be cfg.stream_path

request.socket.recording = fs.createWriteStream(path);
}
}).listen(STREAM_PORT);

console.log('Stream connected');
};
handleInputConnection();

// Output
var handleOutputConnection = function(){
var app = false;
if(cfg.ssl){
app = https.createServer({
key: fs.readFileSync(cfg.ssl_key),
cert: fs.readFileSync(cfg.ssl_cert)
}, onRequestOutput);
}else{
app = http.createServer(onRequestOutput);
}
app.headersTimeout = 0;
app.listen(cfg.output_port, cfg.host);

ws_output = new websocket.Server({server:app, perMessageDeflate:false});
ws_output.on('connection', function(client){
client.ip = client._socket.remoteAddress;
client.isAlive = true; //ping check

client.on('close', function(reasonCode, description){
console.log('['+client.ip+'] closed.');
process.title = "("+ws_output.clients.size+") Stream Server";
});

client.on('error', function(e){
console.log('Erro, cliente desconectado: '+e);
process.title = "("+ws_output.clients.size+") Stream Server";
});

client.on('pong', function(e){
client.isAlive = true;
});

console.log('Client ['+client.ip+'] connected');
process.title = "("+ws_output.clients.size+") Stream Server";
});

ws_output.broadcast = function(data) {
ws_output.clients.forEach(function each(client){
if(client.readyState === websocket.OPEN){
client.send(data);
}
});
};
};
handleOutputConnection();
var onRequestOutput = function(request,response){
console.log('Client requesting connection');
response.end();
};

var nop = function(){};
var pingInterval = setInterval(function ping(){
ws_output.clients.forEach(function each(client){
if(client.isAlive){
client.isAlive = false;
client.ping(nop);
}else{
console.log('Client ['+client.ip+'] close, no ping response');
client.terminate();
}
});
}, 15000);

console.log('Listening for incomming MPEG-TS Stream on http://127.0.0.1:'+STREAM_PORT+'/<secret>');
console.log('Awaiting WebSocket connections on ws://127.0.0.1:'+WEBSOCKET_PORT+'/');
console.log('Listening for incomming MPEG-TS Stream');
console.log('Awaiting WebSocket connections');