support for Ipv6 (#2593) * started adding v6 support * added error checking and change messages to the user * fixed lsp caused issue * fixed formatting error * added error handling to https * fixed formatting errors * brought server starting into different func and added enable v6 and v4 * added error checking for disabling both v6 and v4. added option to prefer v6 for dns. added that stuff to the default config * fixed dumb bug * changed to settings named disable ipvx * fixed failed ips still showing as listening * fixed error handling * changed ip protocol config layout * small const name changes * fixed no error if only available protocol fails, and changed wording of some errors * fixed error handling saying 'non-fatal error' for protocol fail even when it's the only one enabled * moved more logic to listen error handler * fixed eslint issues * added more info on when to prefer ipv6 for dns * in conf changed one 'ipv6' to 'IPv6' for consistency * changed error message and redid how starting the server works * removed unneeded log * removed unneeded log * removed unneeded comments * fixed errors * fixed errors * fixed errors * changed the wording of ip related error messages * removed empty lines * changed to .finally(startServer); * removed some whitespace * disabled ipv6 by default ╯︿╰ and changed some message wording * added auto mode for autorun hostname and changed formatting for listening log and added goto message with autorun url * added autorun port override * removed debug log * changed formatting * added cli args to ipv6 and autorun stuff * moved cli args around * changed formatting * changed colors for ip * added avoidLocalhost cli arg * changed formatting * changed to not print protocol on listening * added config option for avoid localhost and changed formatting of messages * fixed avoid localhost config option * Fix ipv4 color --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -4,8 +4,18 @@ dataRoot: ./data | ||
| 4 | 4 | # -- SERVER CONFIGURATION -- |
| 5 | 5 | # Listen for incoming connections |
| 6 | 6 | listen: false |
| 7 | +# Enables IPv6 and/or IPv4 | |
| 8 | +protocol: | |
| 9 | + ipv4: true | |
| 10 | + ipv6: false | |
| 11 | +# Prefers IPv6 for dns, you should probably enable this on ISPs that don't have issues with IPv6 | |
| 12 | +dnsPreferIPv6: false | |
| 13 | +# the hostname that autorun opens probably best left on auto. use options like 'localhost', 'st.example.com' | |
| 14 | +autorunHostname: "auto" | |
| 7 | 15 | # Server port |
| 8 | 16 | port: 8000 |
| 17 | +# overrides the port for autorun with open your browser with this port and ignore what port the server is running on. -1 is use server port | |
| 18 | +autorunPortOverride: -1 | |
| 9 | 19 | # -- SECURITY CONFIGURATION -- |
| 10 | 20 | # Toggle whitelist mode |
| 11 | 21 | whitelistMode: true |
| @@ -13,6 +23,7 @@ whitelistMode: true | ||
| 13 | 23 | enableForwardedWhitelist: true |
| 14 | 24 | # Whitelist of allowed IP addresses |
| 15 | 25 | whitelist: |
| 26 | + - ::1 | |
| 16 | 27 | - 127.0.0.1 |
| 17 | 28 | # Toggle basic authentication for endpoints |
| 18 | 29 | basicAuthMode: false |
| @@ -35,6 +46,9 @@ securityOverride: false | ||
| 35 | 46 | # -- ADVANCED CONFIGURATION -- |
| 36 | 47 | # Open the browser automatically |
| 37 | 48 | autorun: true |
| 49 | +# Avoids using 'localhost' for autorun in auto mode. | |
| 50 | +# use if you don't have 'localhost' in your hosts file | |
| 51 | +avoidLocalhost: false | |
| 38 | 52 | # Disable thumbnail generation |
| 39 | 53 | disableThumbnails: false |
| 40 | 54 | # Thumbnail quality (0-100) |
| @@ -58,7 +58,7 @@ | ||
| 58 | 58 | }, |
| 59 | 59 | "devDependencies": { |
| 60 | 60 | "@types/jquery": "^3.5.29", |
| 61 | 61 | "eslint": "^8.5557.0", |
| 62 | 62 | "jquery": "^3.6.4" |
| 63 | 63 | }, |
| 64 | 64 | "engines": { |
| @@ -166,9 +166,9 @@ | ||
| 166 | 166 | "license": "MIT" |
| 167 | 167 | }, |
| 168 | 168 | "node_modules/@eslint/js": { |
| 169 | 169 | "version": "8.5557.0", |
| 170 | 170 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.5557.0.tgz", |
| 171 | 171 | "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLoYs+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/nvNMpJOaJATj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", |
| 172 | 172 | "dev": true, |
| 173 | 173 | "license": "MIT", |
| 174 | 174 | "engines": { |
| @@ -185,14 +185,15 @@ | ||
| 185 | 185 | } |
| 186 | 186 | }, |
| 187 | 187 | "node_modules/@humanwhocodes/config-array": { |
| 188 | 188 | "version": "0.11.1314", |
| 189 | 189 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.1314.tgz", |
| 190 | 190 | "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", |
| 191 | + "deprecated": "Use @eslint/config-array instead", | |
| 191 | 192 | "dev": true, |
| 192 | 193 | "license": "Apache-2.0", |
| 193 | 194 | "dependencies": { |
| 194 | 195 | "@humanwhocodes/object-schema": "^2.0.12", |
| 195 | 196 | "debug": "^4.13.1", |
| 196 | 197 | "minimatch": "^3.0.5" |
| 197 | 198 | }, |
| 198 | 199 | "engines": { |
| @@ -200,9 +201,9 @@ | ||
| 200 | 201 | } |
| 201 | 202 | }, |
| 202 | 203 | "node_modules/@humanwhocodes/config-array/node_modules/debug": { |
| 203 | 204 | "version": "4.3.46", |
| 204 | 205 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.46.tgz", |
| 205 | 206 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7GO/vCNNhehwxfkQ09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", |
| 206 | 207 | "dev": true, |
| 207 | 208 | "license": "MIT", |
| 208 | 209 | "dependencies": { |
| @@ -239,9 +240,10 @@ | ||
| 239 | 240 | } |
| 240 | 241 | }, |
| 241 | 242 | "node_modules/@humanwhocodes/object-schema": { |
| 242 | 243 | "version": "2.0.13", |
| 243 | 244 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.13.tgz", |
| 244 | 245 | "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+1GWiExi9QyzlD8x/yTvvLDHpoxLr0xxxeslWw08Zt7wIKcDcA==", |
| 246 | + "deprecated": "Use @eslint/object-schema instead", | |
| 245 | 247 | "dev": true, |
| 246 | 248 | "license": "BSD-3-Clause" |
| 247 | 249 | }, |
| @@ -2455,17 +2457,17 @@ | ||
| 2455 | 2457 | } |
| 2456 | 2458 | }, |
| 2457 | 2459 | "node_modules/eslint": { |
| 2458 | 2460 | "version": "8.5557.0", |
| 2459 | 2461 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5557.0.tgz", |
| 2460 | 2462 | "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdtdZ6+rCntju0xEH7teIABPwXpahftIaTdAmexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", |
| 2461 | 2463 | "dev": true, |
| 2462 | 2464 | "license": "MIT", |
| 2463 | 2465 | "dependencies": { |
| 2464 | 2466 | "@eslint-community/eslint-utils": "^4.2.0", |
| 2465 | 2467 | "@eslint-community/regexpp": "^4.6.1", |
| 2466 | 2468 | "@eslint/eslintrc": "^2.1.4", |
| 2467 | 2469 | "@eslint/js": "8.5557.0", |
| 2468 | 2470 | "@humanwhocodes/config-array": "^0.11.1314", |
| 2469 | 2471 | "@humanwhocodes/module-importer": "^1.0.1", |
| 2470 | 2472 | "@nodelib/fs.walk": "^1.2.8", |
| 2471 | 2473 | "@ungap/structured-clone": "^1.2.0", |
| @@ -90,7 +90,7 @@ | ||
| 90 | 90 | "main": "server.js", |
| 91 | 91 | "devDependencies": { |
| 92 | 92 | "@types/jquery": "^3.5.29", |
| 93 | 93 | "eslint": "^8.5557.0", |
| 94 | 94 | "jquery": "^3.6.4" |
| 95 | 95 | } |
| 96 | 96 | } |
| @@ -54,8 +54,9 @@ if (process.versions && process.versions.node && process.versions.node.match(/20 | ||
| 54 | 54 | if (net.setDefaultAutoSelectFamily) net.setDefaultAutoSelectFamily(false); |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | -// Set default DNS resolution order to IPv4 first | |
| 57 | + | |
| 58 | -dns.setDefaultResultOrder('ipv4first'); | |
| 58 | + | |
| 59 | + | |
| 59 | 60 | |
| 60 | 61 | const DEFAULT_PORT = 8000; |
| 61 | 62 | const DEFAULT_AUTORUN = false; |
| @@ -66,16 +67,46 @@ const DEFAULT_ACCOUNTS = false; | ||
| 66 | 67 | const DEFAULT_CSRF_DISABLED = false; |
| 67 | 68 | const DEFAULT_BASIC_AUTH = false; |
| 68 | 69 | |
| 70 | +const DEFAULT_ENABLE_IPV6 = false; | |
| 71 | +const DEFAULT_ENABLE_IPV4 = true; | |
| 72 | + | |
| 73 | +const DEFAULT_PREFER_IPV6 = false; | |
| 74 | + | |
| 75 | +const DEFAULT_AVOID_LOCALHOST = false; | |
| 76 | + | |
| 77 | +const DEFAULT_AUTORUN_HOSTNAME = 'auto'; | |
| 78 | +const DEFAULT_AUTORUN_PORT = -1; | |
| 79 | + | |
| 69 | 80 | const cliArguments = yargs(hideBin(process.argv)) |
| 70 | 81 | .usage('Usage: <your-start-script> <command> [options]') |
| 71 | 82 | .option('portenableIPv6', { |
| 83 | + type: 'boolean', | |
| 84 | + default: null, | |
| 85 | + describe: `Enables IPv6.\n[config default: ${DEFAULT_ENABLE_IPV6}]`, | |
| 86 | + }).option('enableIPv4', { | |
| 87 | + type: 'boolean', | |
| 88 | + default: null, | |
| 89 | + describe: `Enables IPv4.\n[config default: ${DEFAULT_ENABLE_IPV4}]`, | |
| 90 | + }).option('port', { | |
| 72 | 91 | type: 'number', |
| 73 | 92 | default: null, |
| 74 | 93 | describe: `Sets the port under which SillyTavern will run.\nIf not provided falls back to yaml config 'port'.\n[config default: ${DEFAULT_PORT}]`, |
| 94 | + }).option('dnsPreferIPv6', { | |
| 95 | + type: 'boolean', | |
| 96 | + default: null, | |
| 97 | + describe: `Prefers IPv6 for dns\nyou should probably have the enabled if you're on an IPv6 only network\nIf not provided falls back to yaml config 'preferIPv6'.\n[config default: ${DEFAULT_PREFER_IPV6}]`, | |
| 75 | 98 | }).option('autorun', { |
| 76 | 99 | type: 'boolean', |
| 77 | 100 | default: null, |
| 78 | 101 | describe: `Automatically launch SillyTavern in the browser.\nAutorun is automatically disabled if --ssl is set to true.\nIf not provided falls back to yaml config 'autorun'.\n[config default: ${DEFAULT_AUTORUN}]`, |
| 102 | + }).option('autorunHostname', { | |
| 103 | + type: 'string', | |
| 104 | + default: null, | |
| 105 | + describe: 'the autorun hostname, probably best left on \'auto\'.\nuse values like \'localhost\', \'st.example.com\'', | |
| 106 | + }).option('autorunPortOverride', { | |
| 107 | + type: 'string', | |
| 108 | + default: null, | |
| 109 | + describe: 'Overrides the port for autorun with open your browser with this port and ignore what port the server is running on. -1 is use server port', | |
| 79 | 110 | }).option('listen', { |
| 80 | 111 | type: 'boolean', |
| 81 | 112 | default: null, |
| @@ -108,6 +139,10 @@ const cliArguments = yargs(hideBin(process.argv)) | ||
| 108 | 139 | type: 'string', |
| 109 | 140 | default: null, |
| 110 | 141 | describe: 'Root directory for data storage', |
| 142 | + }).option('avoidLocalhost', { | |
| 143 | + type: 'boolean', | |
| 144 | + default: null, | |
| 145 | + describe: 'Avoids using \'localhost\' for autorun in auto mode.\nuse if you don\'t have \'localhost\' in your hosts file', | |
| 111 | 146 | }).option('basicAuthMode', { |
| 112 | 147 | type: 'boolean', |
| 113 | 148 | default: null, |
| @@ -138,6 +173,31 @@ const enableAccounts = getConfigValue('enableUserAccounts', DEFAULT_ACCOUNTS); | ||
| 138 | 173 | |
| 139 | 174 | const uploadsPath = path.join(dataRoot, require('./src/constants').UPLOADS_DIRECTORY); |
| 140 | 175 | |
| 176 | +const enableIPv6 = cliArguments.enableIPv6 ?? getConfigValue('protocol.ipv6', DEFAULT_ENABLE_IPV6); | |
| 177 | +const enableIPv4 = cliArguments.enableIPv4 ?? getConfigValue('protocol.ipv4', DEFAULT_ENABLE_IPV4); | |
| 178 | + | |
| 179 | +const autorunHostname = cliArguments.autorunHostname ?? getConfigValue('autorunHostname', DEFAULT_AUTORUN_HOSTNAME); | |
| 180 | +const autorunPortOverride = cliArguments.autorunPortOverride ?? getConfigValue('autorunPortOverride', DEFAULT_AUTORUN_PORT); | |
| 181 | + | |
| 182 | +const dnsPreferIPv6 = cliArguments.dnsPreferIPv6 ?? getConfigValue('dnsPreferIPv6', DEFAULT_PREFER_IPV6); | |
| 183 | + | |
| 184 | +const avoidLocalhost = cliArguments.avoidLocalhost ?? getConfigValue('avoidLocalhost', DEFAULT_AVOID_LOCALHOST); | |
| 185 | + | |
| 186 | +if (dnsPreferIPv6) { | |
| 187 | + // Set default DNS resolution order to IPv6 first | |
| 188 | + dns.setDefaultResultOrder('ipv6first'); | |
| 189 | + console.log('Preferring IPv6 for DNS resolution'); | |
| 190 | +} else { | |
| 191 | + // Set default DNS resolution order to IPv4 first | |
| 192 | + dns.setDefaultResultOrder('ipv4first'); | |
| 193 | + console.log('Preferring IPv4 for DNS resolution'); | |
| 194 | +} | |
| 195 | + | |
| 196 | +if (!enableIPv6 && !enableIPv4) { | |
| 197 | + console.error('error: You can\'t disable all internet protocols: at least IPv6 or IPv4 must be enabled.'); | |
| 198 | + process.exit(1); | |
| 199 | +} | |
| 200 | + | |
| 141 | 201 | // CORS Settings // |
| 142 | 202 | const CORS = cors({ |
| 143 | 203 | origin: 'null', |
| @@ -546,18 +606,19 @@ app.use('/api/speech', require('./src/endpoints/speech').router); | ||
| 546 | 606 | // Azure TTS |
| 547 | 607 | app.use('/api/azure', require('./src/endpoints/azure').router); |
| 548 | 608 | |
| 549 | 609 | const tavernUrltavernUrlV6 = new URL( |
| 550 | 610 | (cliArguments.ssl ? 'https://' : 'http://') + |
| 551 | 611 | (listen ? '0.0.0.0[::]' : '127.0.0.[::1]') + |
| 552 | 612 | (':' + server_port), |
| 553 | 613 | ); |
| 554 | 614 | |
| 555 | 615 | const autorunUrltavernUrl = new URL( |
| 556 | 616 | (cliArguments.ssl ? 'https://' : 'http://') + |
| 557 | 617 | (listen ? '0.0.0.0' : '127.0.0.1') + |
| 558 | 618 | (':' + server_port), |
| 559 | 619 | ); |
| 560 | 620 | |
| 621 | + | |
| 561 | 622 | /** |
| 562 | 623 | * Tasks that need to be run before the server starts listening. |
| 563 | 624 | */ |
| @@ -606,20 +667,83 @@ const preSetupTasks = async function () { | ||
| 606 | 667 | }); |
| 607 | 668 | }; |
| 608 | 669 | |
| 670 | +function removeColorFormatting(text) { | |
| 671 | + // ANSI escape codes for colors are usually in the format \x1b[<codes>m | |
| 672 | + return text.replace(/\x1b\[\d{1,2}(;\d{1,2})*m/g, ''); | |
| 673 | +} | |
| 674 | + | |
| 675 | +function getSeparator(n) { | |
| 676 | + return '='.repeat(n); | |
| 677 | +} | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | +function getAutorunHostname() { | |
| 682 | + | |
| 683 | + if (autorunHostname === 'auto') { | |
| 684 | + if (enableIPv6 && enableIPv4) { | |
| 685 | + if (avoidLocalhost) return '[::1]'; | |
| 686 | + return 'localhost'; | |
| 687 | + } | |
| 688 | + | |
| 689 | + if (enableIPv6) { | |
| 690 | + return '[::1]'; | |
| 691 | + } | |
| 692 | + | |
| 693 | + if (enableIPv4) { | |
| 694 | + return '127.0.0.1'; | |
| 695 | + } | |
| 696 | + } | |
| 697 | + | |
| 698 | + return autorunHostname; | |
| 699 | +} | |
| 700 | + | |
| 701 | + | |
| 609 | 702 | /** |
| 610 | 703 | * Tasks that need to be run after the server starts listening. |
| 611 | 704 | */ |
| 612 | 705 | const postSetupTasks = async function (v6Failed, v4Failed) { |
| 706 | + | |
| 707 | + | |
| 708 | + const autorunUrl = new URL( | |
| 709 | + (cliArguments.ssl ? 'https://' : 'http://') + | |
| 710 | + (getAutorunHostname()) + | |
| 711 | + (':') + | |
| 712 | + ((autorunPortOverride >= 0) ? autorunPortOverride : server_port), | |
| 713 | + ); | |
| 714 | + | |
| 715 | + | |
| 613 | 716 | console.log('Launching...'); |
| 614 | 717 | |
| 615 | 718 | if (autorun) open(autorunUrl.toString()); |
| 616 | 719 | |
| 617 | 720 | setWindowTitle('SillyTavern WebServer'); |
| 618 | 721 | |
| 619 | - console.log(color.green('SillyTavern is listening on: ' + tavernUrl)); | |
| 722 | + | |
| 723 | + let ipv6Color = color.green; | |
| 724 | + let ipv4Color = color.green; | |
| 725 | + let autorunColor = color.blue; | |
| 726 | + | |
| 727 | + let logListen = 'SillyTavern is listening on'; | |
| 728 | + | |
| 729 | + if (enableIPv6 && !v6Failed) { | |
| 730 | + logListen += ipv6Color(' IPv6: ' + tavernUrlV6.host); | |
| 731 | + } | |
| 732 | + | |
| 733 | + if (enableIPv4 && !v4Failed) { | |
| 734 | + logListen += ipv4Color(' IPv4: ' + tavernUrl.host); | |
| 735 | + } | |
| 736 | + | |
| 737 | + let goToLog = 'Go to: ' + autorunColor(autorunUrl) + ' to open SillyTavern'; | |
| 738 | + let plainGoToLog = removeColorFormatting(goToLog); | |
| 739 | + | |
| 740 | + console.log(logListen); | |
| 741 | + console.log('\n' + getSeparator(plainGoToLog.length) + '\n'); | |
| 742 | + console.log(goToLog); | |
| 743 | + console.log('\n' + getSeparator(plainGoToLog.length) + '\n'); | |
| 620 | 744 | |
| 621 | 745 | if (listen) { |
| 622 | 746 | console.log('\n0[::] or 0.0.0.0 means SillyTavern is listening on all network interfaces (Wi-Fi, LAN, localhost). If you want to limit it only to internal localhost ([::1] or 127.0.0.1), change the setting in config.yaml to "listen: false". Check "access.log" file in the SillyTavern directory if you want to inspect incoming connections.\n'); |
| 623 | 747 | } |
| 624 | 748 | |
| 625 | 749 | if (basicAuthMode) { |
| @@ -674,6 +798,102 @@ function logSecurityAlert(message) { | ||
| 674 | 798 | process.exit(1); |
| 675 | 799 | } |
| 676 | 800 | |
| 801 | + | |
| 802 | + | |
| 803 | +function handleServerListenFail(v6Failed, v4Failed) { | |
| 804 | + if (v6Failed && !enableIPv4) { | |
| 805 | + console.error('fatal error: Failed to start server on IPv6 and IPv4 disabled'); | |
| 806 | + process.exit(1); | |
| 807 | + } | |
| 808 | + | |
| 809 | + if (v4Failed && !enableIPv6) { | |
| 810 | + console.error('fatal error: Failed to start server on IPv4 and IPv6 disabled'); | |
| 811 | + process.exit(1); | |
| 812 | + } | |
| 813 | + | |
| 814 | + if (v6Failed && v4Failed) { | |
| 815 | + console.error('fatal error: Failed to start server on both IPv6 and IPv4'); | |
| 816 | + process.exit(1); | |
| 817 | + } | |
| 818 | +} | |
| 819 | + | |
| 820 | + | |
| 821 | +function createHttpsServer(url) { | |
| 822 | + return new Promise((resolve, reject) => { | |
| 823 | + const server = https.createServer( | |
| 824 | + { | |
| 825 | + cert: fs.readFileSync(cliArguments.certPath), | |
| 826 | + key: fs.readFileSync(cliArguments.keyPath), | |
| 827 | + }, app); | |
| 828 | + server.on('error', reject); | |
| 829 | + server.on('listening', resolve); | |
| 830 | + server.listen(url.port, url.hostname); | |
| 831 | + }); | |
| 832 | +} | |
| 833 | + | |
| 834 | +function createHttpServer(url) { | |
| 835 | + return new Promise((resolve, reject) => { | |
| 836 | + const server = http.createServer(app); | |
| 837 | + server.on('error', reject); | |
| 838 | + server.on('listening', resolve); | |
| 839 | + server.listen(url.port, url.hostname); | |
| 840 | + }); | |
| 841 | +} | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | +async function startHTTPorHTTPS() { | |
| 847 | + let v6Failed = false; | |
| 848 | + let v4Failed = false; | |
| 849 | + | |
| 850 | + let createFunc = createHttpServer; | |
| 851 | + if (cliArguments.ssl) { | |
| 852 | + createFunc = createHttpsServer; | |
| 853 | + } | |
| 854 | + | |
| 855 | + if (enableIPv6) { | |
| 856 | + try { | |
| 857 | + await createFunc(tavernUrlV6); | |
| 858 | + } catch(error) { | |
| 859 | + if (enableIPv4) { | |
| 860 | + console.error('non-fatal error: failed to start server on IPv6', error); | |
| 861 | + } | |
| 862 | + | |
| 863 | + v6Failed = true; | |
| 864 | + } | |
| 865 | + } | |
| 866 | + | |
| 867 | + if (enableIPv4) { | |
| 868 | + try { | |
| 869 | + await createFunc(tavernUrl); | |
| 870 | + } catch(error) { | |
| 871 | + if (enableIPv6) { | |
| 872 | + console.error('non-fatal error: failed to start server on IPv4', error); | |
| 873 | + } | |
| 874 | + | |
| 875 | + v4Failed = true; | |
| 876 | + } | |
| 877 | + } | |
| 878 | + return [v6Failed, v4Failed]; | |
| 879 | +} | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | +async function startServer() { | |
| 885 | + let v6Failed = false; | |
| 886 | + let v4Failed = false; | |
| 887 | + | |
| 888 | + | |
| 889 | + [v6Failed, v4Failed] = await startHTTPorHTTPS(); | |
| 890 | + | |
| 891 | + handleServerListenFail(v6Failed, v4Failed); | |
| 892 | + postSetupTasks(v6Failed, v4Failed); | |
| 893 | +} | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 677 | 897 | async function verifySecuritySettings() { |
| 678 | 898 | // Skip all security checks as listen is set to false |
| 679 | 899 | if (!listen) { |
| @@ -707,23 +927,4 @@ userModule.initUserStorage(dataRoot) | ||
| 707 | 927 | .then(userModule.migrateUserData) |
| 708 | 928 | .then(verifySecuritySettings) |
| 709 | 929 | .then(preSetupTasks) |
| 710 | 930 | .finally((startServer) => {; |
| 711 | - if (cliArguments.ssl) { | |
| 712 | - https.createServer( | |
| 713 | - { | |
| 714 | - cert: fs.readFileSync(cliArguments.certPath), | |
| 715 | - key: fs.readFileSync(cliArguments.keyPath), | |
| 716 | - }, app) | |
| 717 | - .listen( | |
| 718 | - Number(tavernUrl.port) || 443, | |
| 719 | - tavernUrl.hostname, | |
| 720 | - postSetupTasks, | |
| 721 | - ); | |
| 722 | - } else { | |
| 723 | - http.createServer(app).listen( | |
| 724 | - Number(tavernUrl.port) || 80, | |
| 725 | - tavernUrl.hostname, | |
| 726 | - postSetupTasks, | |
| 727 | - ); | |
| 728 | - } | |
| 729 | - }); | |