27 #include <libconfig.h++>
28 #include <boost/asio.hpp>
30 #include "spdlog/async.h"
31 #include "spdlog/spdlog.h"
32 #include "spdlog/sinks/syslog_sink.h"
39 using libconfig::Config;
40 using libconfig::FileIOException;
41 using libconfig::ParseException;
43 static void print_version(FILE *stream,
struct argp_state *state);
46 static char doc[] =
"FLUTE/ALC receiver demo";
48 static struct argp_option
options[] = {
49 {
"interface",
'i',
"IF", 0,
"IP address of the interface to bind flute receivers to (default: 0.0.0.0)", 0},
50 {
"target",
'm',
"IP", 0,
"Multicast address to receive on (default: 238.1.1.95)", 0},
51 {
"port",
'p',
"PORT", 0,
"Multicast port (default: 40085)", 0},
52 {
"ipsec-key",
'k',
"KEY", 0,
"To enable IPSec/ESP decryption of packets, provide a hex-encoded AES key here", 0},
53 {
"log-level",
'l',
"LEVEL", 0,
54 "Log verbosity: 0 = trace, 1 = debug, 2 = info, 3 = warn, 4 = error, 5 = "
55 "critical, 6 = none. Default: 2.",
57 {
"tsi",
'T',
"ID", 0,
"The TSI to use for the FLUTE session (default: 16)", 0},
58 {
"output-path",
'o',
"PATH", 0,
"Directory to save received files", 0},
59 {
nullptr, 0,
nullptr, 0,
nullptr, 0}};
79 static auto parse_opt(
int key,
char *arg,
struct argp_state *state) -> error_t {
80 auto arguments =
static_cast<struct
ft_arguments *
>(state->input);
86 arguments->flute_interface = arg;
89 arguments->aes_key = arg;
90 arguments->enable_ipsec =
true;
93 arguments->mcast_port =
static_cast<unsigned short>(strtoul(arg,
nullptr, 10));
96 arguments->log_level =
static_cast<unsigned>(strtoul(arg,
nullptr, 10));
99 arguments->tsi =
static_cast<uint64_t
>(strtoul(arg,
nullptr, 10));
102 arguments->output_path = arg;
105 return ARGP_ERR_UNKNOWN;
111 nullptr,
nullptr,
nullptr};
117 fprintf(stream,
"%s.%s.%s\n", std::to_string(VERSION_MAJOR).c_str(),
118 std::to_string(VERSION_MINOR).c_str(),
119 std::to_string(VERSION_PATCH).c_str());
131 auto main(
int argc,
char **argv) ->
int {
138 argp_parse(&
argp, argc, argv, 0,
nullptr, &arguments);
141 std::string ident =
"flute-receiver";
142 auto syslog_logger = spdlog::syslog_logger_mt(
"syslog", ident, LOG_PID | LOG_PERROR | LOG_CONS );
145 static_cast<spdlog::level::level_enum
>(arguments.
log_level));
146 spdlog::set_pattern(
"[%H:%M:%S.%f %z] [%^%l%$] [thr %t] %v");
148 spdlog::set_default_logger(syslog_logger);
149 spdlog::info(
"FLUTE receiver demo starting up");
153 boost::asio::io_context io;
171 std::string out_file = file->meta().content_location;
172 if (output_path && std::strlen(output_path) > 0) {
173 out_file = (std::filesystem::path(output_path) / std::filesystem::path(out_file).filename()).string();
176 spdlog::info(
"{} (TOI {}) has been received",
177 out_file, file->meta().toi);
183 std::filesystem::path out_path(out_file);
184 if (out_path.has_parent_path()) {
185 std::filesystem::create_directories(out_path.parent_path());
187 FILE *fd = fopen(out_file.c_str(),
"wb");
189 spdlog::warn(
"Failed to open {} for writing: {}", out_file, strerror(errno));
192 fwrite(file->buffer(), 1, file->length(), fd);
198 }
catch (std::exception ex ) {
199 spdlog::error(
"Exiting on unhandled exception: %s", ex.what());
void register_completion_callback(completion_callback_t cb)
Register a callback for file reception notifications.
void enable_ipsec(uint32_t spi, const std::string &aes_key)
Enable IPSEC ESP decryption of FLUTE payloads.
static void print_version(FILE *stream, struct argp_state *state)
Print the program version in MAJOR.MINOR.PATCH format.
auto main(int argc, char **argv) -> int
Main entry point for the program.
const char * argp_program_bug_address
static struct argp_option options[]
void(* argp_program_version_hook)(FILE *, struct argp_state *)
static auto parse_opt(int key, char *arg, struct argp_state *state) -> error_t
Parses the command line options into the arguments struct.
Holds all options passed on the command line.
unsigned log_level
log level
const char * mcast_target
unsigned short mcast_port
const char * flute_interface
file path of the config file.