/* * This file is part of nzbget. See . * * Copyright (C) 2016 Andrey Prygunkov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "nzbget.h" #include "Thread.h" #include "Connection.h" #include "Log.h" #include "Util.h" #include "FileSystem.h" #include "NServFrontend.h" #include "NntpServer.h" #include "NzbGenerator.h" #include "Options.h" struct NServOpts { CString dataDir; int firstPort; int instances; CString logFile; CString secureCert; CString secureKey; BString<1024> logOpt; bool generateNzb; int segmentSize; bool quit; NServOpts(int argc, char* argv[], Options::CmdOptList& cmdOpts); }; void NServPrintUsage(const char* com); int NServMain(int argc, char* argv[]) { Log log; info("NServ %s (Test NNTP server)", Util::VersionRevision()); Options::CmdOptList cmdOpts; NServOpts opts(argc, argv, cmdOpts); if (opts.dataDir.Empty()) { NServPrintUsage(argv[0]); return 1; } Options options(&cmdOpts, nullptr); log.InitOptions(); Thread::Init(); Connection::Init(); #ifndef DISABLE_TLS TlsSocket::Init(); #endif NServFrontend frontend; frontend.Start(); if (opts.generateNzb) { NzbGenerator gen(opts.dataDir, opts.segmentSize); gen.Execute(); if (opts.quit) { return 0; } } std::vector> instances; for (int i = 0; i < opts.instances; i++) { instances.emplace_back(std::make_unique(i + 1, "0.0.0.0", opts.firstPort + i, opts.secureCert, opts.secureKey, opts.dataDir)); instances.back()->Start(); } info("Press Ctrl+C to quit"); while (getchar()) usleep(1000*200); for (std::unique_ptr& serv: instances) { serv->Stop(); } frontend.Stop(); bool hasRunning = false; do { hasRunning = frontend.IsRunning(); for (std::unique_ptr& serv : instances) { hasRunning |= serv->IsRunning(); } usleep(50 * 1000); } while (hasRunning); return 0; } void NServPrintUsage(const char* com) { printf("Usage:\n" " %s --nserv -d [optional switches] \n" " -d - directory whose files will be served\n" " Optional switches:\n" " -l - write into log-file (disabled by default)\n" " -i - number of server instances (default is 1)\n" " -p - port number for the first instance (default is 6791)\n" " -s - paths to SSL certificate and key files\n" " -v - verbosity level 0..3 (default is 2)\n" " -z - generate nzbs for all files in data-dir (size in bytes)\n" " -q - quit after generating nzbs (in combination with -z)\n" , FileSystem::BaseFileName(com)); } NServOpts::NServOpts(int argc, char* argv[], Options::CmdOptList& cmdOpts) { instances = 1; firstPort = 6791; generateNzb = false; segmentSize = 500000; quit = false; int verbosity = 2; char short_options[] = "d:l:p:i:s:v:z:q"; optind = 2; while (true) { int c = getopt(argc, argv, short_options); if (c == -1) break; switch (c) { case 'd': dataDir = optind > argc ? nullptr : argv[optind - 1]; break; case 'l': logFile = optind > argc ? nullptr : argv[optind - 1]; break; case 'p': firstPort = atoi(optind > argc ? "6791" : argv[optind - 1]); break; case 's': secureCert = optind > argc ? nullptr : argv[optind - 1]; optind++; secureKey = optind > argc ? nullptr : argv[optind - 1]; break; case 'i': instances = atoi(optind > argc ? "1" : argv[optind - 1]); break; case 'v': verbosity = atoi(optind > argc ? "1" : argv[optind - 1]); break; case 'z': generateNzb = true; segmentSize = atoi(optind > argc ? "500000" : argv[optind - 1]); break; case 'q': quit = true; break; } } if (logFile.Empty()) { cmdOpts.push_back("WriteLog=none"); } else { cmdOpts.push_back("WriteLog=append"); logOpt.Format("LogFile=%s", *logFile); cmdOpts.push_back(logOpt); } if (verbosity < 1) { cmdOpts.push_back("InfoTarget=none"); cmdOpts.push_back("WarningTarget=none"); cmdOpts.push_back("ErrorTarget=none"); } if (verbosity < 2) { cmdOpts.push_back("DetailTarget=none"); } if (verbosity > 2) { cmdOpts.push_back("DebugTarget=both"); } }