2023-11-02 03:17:20 +01:00
import { spawn } from "child_process" ;
import fs from "fs" ;
import PairDropServer from "./server.js" ;
import PairDropWsServer from "./ws-server.js" ;
// Handle SIGINT
process . on ( 'SIGINT' , ( ) => {
console . info ( "SIGINT Received, exiting..." )
process . exit ( 0 )
} )
// Handle SIGTERM
process . on ( 'SIGTERM' , ( ) => {
console . info ( "SIGTERM Received, exiting..." )
process . exit ( 0 )
} )
// Handle APP ERRORS
process . on ( 'uncaughtException' , ( error , origin ) => {
console . log ( '----- Uncaught exception -----' )
console . log ( error )
console . log ( '----- Exception origin -----' )
console . log ( origin )
} )
process . on ( 'unhandledRejection' , ( reason , promise ) => {
console . log ( '----- Unhandled Rejection at -----' )
console . log ( promise )
console . log ( '----- Reason -----' )
console . log ( reason )
} )
// Evaluate arguments for deployment with Docker and Node.js
let conf = { } ;
2023-12-15 21:22:33 +01:00
2023-11-02 03:17:20 +01:00
conf . debugMode = process . env . DEBUG _MODE === "true" ;
2023-12-15 21:22:33 +01:00
2023-11-02 03:17:20 +01:00
conf . port = process . env . PORT || 3000 ;
2023-12-15 21:22:33 +01:00
2023-11-02 03:17:20 +01:00
conf . wsFallback = process . argv . includes ( '--include-ws-fallback' ) || process . env . WS _FALLBACK === "true" ;
2023-12-15 21:22:33 +01:00
conf . rtcConfig = process . env . RTC _CONFIG && process . env . RTC _CONFIG !== "false"
2023-11-02 03:17:20 +01:00
? JSON . parse ( fs . readFileSync ( process . env . RTC _CONFIG , 'utf8' ) )
: {
"sdpSemantics" : "unified-plan" ,
"iceServers" : [
{
"urls" : "stun:stun.l.google.com:19302"
}
]
} ;
2023-12-15 21:22:33 +01:00
conf . signalingServer = process . env . SIGNALING _SERVER && process . env . SIGNALING _SERVER !== "false"
? process . env . SIGNALING _SERVER
: false ;
2023-11-08 20:31:57 +01:00
conf . ipv6Localize = parseInt ( process . env . IPV6 _LOCALIZE ) || false ;
2023-11-02 03:17:20 +01:00
let rateLimit = false ;
if ( process . argv . includes ( '--rate-limit' ) || process . env . RATE _LIMIT === "true" ) {
rateLimit = 5 ;
}
else {
let envRateLimit = parseInt ( process . env . RATE _LIMIT ) ;
if ( ! isNaN ( envRateLimit ) ) {
rateLimit = envRateLimit ;
}
}
conf . rateLimit = rateLimit ;
2023-12-15 21:22:33 +01:00
2023-12-13 17:40:48 +01:00
conf . buttons = {
"donation_button" : {
"active" : process . env . DONATION _BUTTON _ACTIVE ,
"link" : process . env . DONATION _BUTTON _LINK ,
"title" : process . env . DONATION _BUTTON _TITLE
} ,
"twitter_button" : {
"active" : process . env . TWITTER _BUTTON _ACTIVE ,
"link" : process . env . TWITTER _BUTTON _LINK ,
"title" : process . env . TWITTER _BUTTON _TITLE
} ,
"mastodon_button" : {
"active" : process . env . MASTODON _BUTTON _ACTIVE ,
"link" : process . env . MASTODON _BUTTON _LINK ,
"title" : process . env . MASTODON _BUTTON _TITLE
} ,
"bluesky_button" : {
"active" : process . env . BLUESKY _BUTTON _ACTIVE ,
"link" : process . env . BLUESKY _BUTTON _LINK ,
"title" : process . env . BLUESKY _BUTTON _TITLE
} ,
"custom_button" : {
"active" : process . env . CUSTOM _BUTTON _ACTIVE ,
"link" : process . env . CUSTOM _BUTTON _LINK ,
"title" : process . env . CUSTOM _BUTTON _TITLE
} ,
"privacypolicy_button" : {
"active" : process . env . PRIVACYPOLICY _BUTTON _ACTIVE ,
"link" : process . env . PRIVACYPOLICY _BUTTON _LINK ,
"title" : process . env . PRIVACYPOLICY _BUTTON _TITLE
}
} ;
2023-11-02 03:17:20 +01:00
// Evaluate arguments for deployment with Node.js only
conf . autoStart = process . argv . includes ( '--auto-restart' ) ;
2023-12-15 21:22:33 +01:00
2023-11-02 03:17:20 +01:00
conf . localhostOnly = process . argv . includes ( '--localhost-only' ) ;
2023-12-15 21:22:33 +01:00
2023-11-08 20:31:57 +01:00
// Validate configuration
if ( conf . ipv6Localize ) {
if ( ! ( 0 < conf . ipv6Localize && conf . ipv6Localize < 8 ) ) {
console . error ( "ipv6Localize must be an integer between 1 and 7" ) ;
process . exit ( 1 ) ;
}
console . log ( "IPv6 client IPs will be localized to" ,
conf . ipv6Localize ,
conf . ipv6Localize === 1 ? "segment" : "segments" ) ;
}
if ( conf . signalingServer ) {
const isValidUrl = /[a-z|0-9|\-._~:\/?#\[\]@!$&'()*+,;=]+$/ . test ( conf . signalingServer ) ;
const containsProtocol = /:\/\// . test ( conf . signalingServer )
const endsWithSlash = /\/$/ . test ( conf . signalingServer )
if ( ! isValidUrl || containsProtocol ) {
console . error ( "SIGNALING_SERVER must be a valid url without the protocol prefix.\n" +
"Examples of valid values: `pairdrop.net`, `pairdrop.example.com:3000`, `example.com/pairdrop`" ) ;
process . exit ( 1 ) ;
}
if ( ! endsWithSlash ) {
conf . signalingServer += "/" ;
}
if ( process . env . RTC _CONFIG || conf . wsFallback || conf . ipv6Localize ) {
console . error ( "SIGNALING_SERVER cannot be used alongside WS_FALLBACK, RTC_CONFIG or IPV6_LOCALIZE as these " +
"configurations are specified by the signaling server.\n" +
"To use this instance as the signaling server do not set SIGNALING_SERVER" ) ;
process . exit ( 1 ) ;
}
}
2023-11-02 03:17:20 +01:00
// Logs for debugging
if ( conf . debugMode ) {
console . log ( "DEBUG_MODE is active. To protect privacy, do not use in production." ) ;
console . debug ( "\n" ) ;
console . debug ( "----DEBUG ENVIRONMENT VARIABLES----" )
console . debug ( JSON . stringify ( conf , null , 4 ) ) ;
console . debug ( "\n" ) ;
}
// Start a new PairDrop instance when an uncaught exception occurs
if ( conf . autoStart ) {
process . on (
'uncaughtException' ,
( ) => {
process . once (
'exit' ,
( ) => spawn (
process . argv . shift ( ) ,
process . argv ,
{
cwd : process . cwd ( ) ,
detached : true ,
stdio : 'inherit'
}
)
) ;
process . exit ( ) ;
}
) ;
}
// Start server to serve client files
const pairDropServer = new PairDropServer ( conf ) ;
2023-11-08 20:31:57 +01:00
if ( ! conf . signalingServer ) {
// Start websocket server if SIGNALING_SERVER is not set
new PairDropWsServer ( pairDropServer . server , conf ) ;
} else {
console . log ( "This instance does not include a signaling server. Clients on this instance connect to the following signaling server:" , conf . signalingServer ) ;
}
2023-11-02 03:17:20 +01:00
2023-11-08 20:31:57 +01:00
console . log ( '\nPairDrop is running on port' , conf . port ) ;