diff --git a/config/default.toml b/config/default.toml index ae6c269..4b8079c 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,3 +1,5 @@ +#DO NOT EDIT THIS FILE +#ALL CHANGES SHOULD GO IN LOCAL.TOML [bcrypt] saltRounds = 12 diff --git a/package-lock.json b/package-lock.json index 2e31502..4b95026 100644 --- a/package-lock.json +++ b/package-lock.json @@ -141,11 +141,6 @@ "supports-color": "^5.3.0" } }, - "check-localhost": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/check-localhost/-/check-localhost-0.0.1.tgz", - "integrity": "sha1-5EBBSdDrQr52SE/EnHTTIYOgC60=" - }, "chownr": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", diff --git a/package.json b/package.json index 3970e30..7e5a059 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "license": "AGPL-3.0", "author": "knotteye", "scripts": { - "start": "node build/controller.js" + "start": "node build/controller.js", + "build": "tsc" }, "repository": { "type": "git", @@ -13,7 +14,6 @@ }, "dependencies": { "bcrypt": "^3.0.6", - "check-localhost": "0.0.1", "config": "^3.2.2", "irc": "^0.5.2", "mysql": "^2.17.1", diff --git a/src/server.ts b/src/server.ts index b99329d..3e20b8c 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,8 +1,7 @@ import * as NodeMediaServer from "node-media-server"; import { mkdir } from "fs"; import * as db from "./database"; -//import { transcode } from "buffer"; -const isLocal = require("check-localhost"); +//import { transcode } from "buffer"; why is this here? const { exec } = require('child_process'); function boot (mediaconfig: any, satyrconfig: any) { @@ -10,39 +9,42 @@ function boot (mediaconfig: any, satyrconfig: any) { nms.run(); nms.on('postPublish', (id, StreamPath, args) => { - //this is unreadable, add some comments console.log("[NodeMediaServer] Prepublish Hook for stream:",id); let session = nms.getSession(id); let app: string = StreamPath.split("/")[1]; let key: string = StreamPath.split("/")[2]; - if (StreamPath.split("/").length > 3){ + //disallow urls not formatted exactly right + if (StreamPath.split("/").length !== 3){ console.log("[NodeMediaServer] Malformed URL, closing connection for stream:",id); session.reject(); return false; } - if(app === mediaconfig.trans.tasks.app) { - isLocal(session.ip).then( (local) => { - if(local) { - console.log("[NodeMediaServer] Local publish, stream:",`${id} ok.`); - } - else{ - console.log("[NodeMediaServer] Non-local Publish to public endpoint, rejecting stream:",id); - session.reject(); - } - }); + if(app === mediaconfig.trans.tasks[0].app) { + //only allow publish to public endpoint from localhost + //this is NOT a comprehensive way of doing this, but I'm ignoring it + //until satyr releases and someone opens an issue + if(session.ip.includes('127.0.0.1') || session.ip === '::1') { + console.log("[NodeMediaServer] Local publish, stream:",`${id} ok.`); + } + else{ + console.log("[NodeMediaServer] Non-local Publish to public endpoint, rejecting stream:",id); + session.reject(); + } console.log("[NodeMediaServer] Public endpoint, checking record flag."); - db.raw.query('select username,record_flag from users where username=\''+key+'\' and record_flag=true limit 1', (error, results, fields) => { + //if this stream is from the public endpoint, stream + db.raw.query('select username from users where username=\''+key+'\' and record_flag=true limit 1', (error, results, fields) => { if (error) {throw error;} - if(results[0] && satyrconfig.record){ + if(results[0].username && satyrconfig.record){ console.log('[NodeMediaServer] Initiating recording for stream:',id); - mkdir(mediaconfig.http.mediaroot+'/'+mediaconfig.trans.tasks.app+'/'+results[0].username, { recursive : true }, (err) => { + mkdir(mediaconfig.http.mediaroot+'/'+mediaconfig.trans.tasks[0].app+'/'+results[0].username, { recursive : true }, (err) => { if (err) throw err; - let subprocess = exec('ffmpeg -i rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+mediaconfig.trans.tasks.app+'/'+results[0].username+' -vcodec copy -acodec copy '+mediaconfig.http.mediaroot+'/'+mediaconfig.trans.tasks.app+'/'+results[0].username+'/$(date +%d%b%Y-%H%M).mp4',{ + let subprocess = exec('ffmpeg -i rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+mediaconfig.trans.tasks[0].app+'/'+results[0].username+' -vcodec copy -acodec copy '+mediaconfig.http.mediaroot+'/'+mediaconfig.trans.tasks[0].app+'/'+results[0].username+'/$(date +%d%b%Y-%H%M).mp4',{ detached : true, stdio : 'inherit' }); subprocess.unref(); //spawn an ffmpeg process to record the stream, then detach it completely + //ffmpeg can then finalize the recording if satyr crashes mid-stream }); } else { @@ -57,10 +59,13 @@ function boot (mediaconfig: any, satyrconfig: any) { session.reject(); return false; } + //if the url is formatted correctly and the user is streaming to the correct private endpoint + //grab the username from the database and redirect the stream there if the key is valid + //otherwise kill the session db.raw.query('select username from users where stream_key=\''+key+'\' limit 1', (error, results, fields) => { if (error) {throw error;} if(results[0]){ - exec('ffmpeg -analyzeduration 0 -i rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key+' -vcodec copy -acodec copy -crf 18 -f flv rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+mediaconfig.trans.tasks.app+'/'+results[0].username); + exec('ffmpeg -analyzeduration 0 -i rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key+' -vcodec copy -acodec copy -crf 18 -f flv rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+mediaconfig.trans.tasks[0].app+'/'+results[0].username); console.log('[NodeMediaServer] Stream key okay for stream:',id); } else{ @@ -73,21 +78,22 @@ function boot (mediaconfig: any, satyrconfig: any) { let session = nms.getSession(id); let app: string = StreamPath.split("/")[1]; let key: string = StreamPath.split("/")[2]; - if (StreamPath.split("/").length > 3){ + //correctly formatted urls again + if (StreamPath.split("/").length !== 3){ console.log("[NodeMediaServer] Malformed URL, closing connection for stream:",id); session.reject(); return false; } + //disallow playing from the private endpoint for anyone except localhost + //(this will be the ffmpeg instance redirecting the stream) if(app === satyrconfig.privateEndpoint) { - isLocal(session.ip).then( (local) => { - if(local) { - console.log("[NodeMediaServer] Local play, client:",`${id} ok.`); - } - else{ - console.log("[NodeMediaServer] Non-local Play from private endpoint, rejecting client:",id); - session.reject(); - } - }); + if(session.ip.includes('127.0.0.1') || session.ip === '::1') { + console.log("[NodeMediaServer] Local play, client:",`${id} ok.`); + } + else{ + console.log("[NodeMediaServer] Non-local Play from private endpoint, rejecting client:",id); + session.reject(); + } } }); }