140 lines
5.2 KiB
C++
140 lines
5.2 KiB
C++
// Copyright 2016 Etix Labs
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "version.h" // versionning
|
|
#include <dispatcher.h> // program loop
|
|
#include <fs.h> // fs::home
|
|
#include <iostream> // iostream
|
|
#include <opt_parse.h> // parsing opt
|
|
|
|
namespace cmrdr = etix::cameradar;
|
|
|
|
void
|
|
print_version() {
|
|
std::cout << "Cameradar version " << CAMERADAR_VERSION << std::endl;
|
|
std::cout << "Build " << CAMERADAR_VERSION_BUILD << std::endl;
|
|
}
|
|
|
|
// Command line parsing
|
|
std::pair<bool, etix::tool::opt_parse>
|
|
parse_cmdline(int argc, char* argv[]) {
|
|
auto opt_parse = etix::tool::opt_parse{ argc, argv };
|
|
|
|
opt_parse.optional("-s", "Set subnets (e.g.: `172.16.0.0/24`)", true);
|
|
opt_parse.optional("-p", "Set ports (e.g.: `554,8554`)", true);
|
|
opt_parse.optional("-c", "Path to the configuration file (-c /path/to/conf)", true);
|
|
opt_parse.optional("-l", "Set log level (-l 4 will only show warnings and errors)", true);
|
|
opt_parse.optional("-d", "Launch the discovery tool on the given subnet", false);
|
|
opt_parse.optional("-b", "Launch the bruteforce tool on all discovered devices", false);
|
|
opt_parse.optional("-t", "Generate thumbnails from detected cameras", false);
|
|
opt_parse.optional("-g", "Check if the stream can be opened with GStreamer", false);
|
|
opt_parse.optional("-v", "Display Cameradar's version", false);
|
|
opt_parse.optional("-h", "Display this help", false);
|
|
opt_parse.optional(
|
|
"--gst-rtsp-server",
|
|
"Change the order of the bruteforce to match GST RTSP Server's implementation of "
|
|
"RTSP. Some cameras and RTSP servers will use this standard instead of the more "
|
|
"standard one. For more information, see the README.md file.",
|
|
false);
|
|
opt_parse.execute();
|
|
|
|
if (opt_parse.exist("-h")) {
|
|
opt_parse.print_help();
|
|
return std::make_pair(false, opt_parse);
|
|
} else if (opt_parse.exist("-v")) {
|
|
print_version();
|
|
return std::make_pair(false, opt_parse);
|
|
} else if (opt_parse.has_error()) {
|
|
std::cout << "Usage: ./cameradar [option]\n\toptions:\n" << std::endl;
|
|
opt_parse.print_help();
|
|
return std::make_pair(false, opt_parse);
|
|
}
|
|
|
|
return std::make_pair(true, opt_parse);
|
|
}
|
|
|
|
// Check if a folder exists, is readable and writable
|
|
bool
|
|
check_folder(const std::string& path) {
|
|
struct stat sb;
|
|
|
|
if ((stat(path.c_str(), &sb) == 0) && (S_ISDIR(sb.st_mode)) && (sb.st_mode & S_IRUSR) &&
|
|
(sb.st_mode & S_IWUSR)) {
|
|
LOG_INFO_("Folder " + path + " is available and has sufficient rights", "main");
|
|
return true;
|
|
}
|
|
LOG_ERR_("Folder " + path + " has insufficient rights, please check your configuration",
|
|
"main");
|
|
return false;
|
|
}
|
|
|
|
// Check if the storage path is available
|
|
bool
|
|
check_storage_path(const std::string& thumbnail_storage_path) {
|
|
LOG_INFO_("Checking if storage path exists and are usable", "main");
|
|
return (check_folder(thumbnail_storage_path));
|
|
}
|
|
|
|
int
|
|
main(int argc, char* argv[]) {
|
|
etix::tool::logger::get_instance("cameradar");
|
|
auto args = parse_cmdline(argc, argv);
|
|
if (not args.first) return EXIT_FAILURE;
|
|
|
|
print_version();
|
|
|
|
if (not args.second.exist("-l")) {
|
|
etix::tool::logger::get_instance("cameradar").set_level(etix::tool::loglevel::DEBUG);
|
|
LOG_INFO_("No log level set, using log level 1", "main");
|
|
} else {
|
|
try {
|
|
int level = std::stoi(args.second["-l"]);
|
|
etix::tool::logger::get_instance("cameradar")
|
|
.set_level(static_cast<etix::tool::loglevel>(level));
|
|
} catch (...) {
|
|
LOG_ERR_("Invalid log level format, log level should be 1, 2, 4, 5 or 6", "main");
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
// Try to load the configuration
|
|
auto conf = cmrdr::load(args);
|
|
if (not conf.first) { return EXIT_FAILURE; }
|
|
|
|
LOG_INFO_("Configuration successfully loaded", "main");
|
|
|
|
// If one of the path is invalid, exit
|
|
auto paths_ok = check_storage_path(conf.second.thumbnail_storage_path);
|
|
if (not paths_ok) { return EXIT_FAILURE; }
|
|
|
|
// Here we should get the cache manager but for now we will juste
|
|
// make a dumb cache manager
|
|
auto plug = std::make_shared<etix::cameradar::cache_manager>(conf.second.cache_manager_path,
|
|
conf.second.cache_manager_name);
|
|
|
|
if (not plug || not plug->make_instance()) {
|
|
LOG_ERR_(std::string("Invalid cache manager "), "cameradar");
|
|
return false;
|
|
}
|
|
|
|
LOG_INFO_("Launching Cameradar, press CTRL+C to gracefully stop", "main");
|
|
|
|
etix::cameradar::dispatcher disp(conf.second, plug, args);
|
|
|
|
disp.run();
|
|
|
|
LOG_WARN_("See ya !", "cameradar");
|
|
return EXIT_SUCCESS;
|
|
}
|