#include #include #include #include #include #include #include #include #include #include #include #include "storage.h" #include "recorder.h" #include "config.h" static enum osmo_e1cap_capture_mode ts2cap_mode(struct e1inp_ts *ts) { switch (ts->type) { case E1INP_TS_TYPE_RAW: return OSMO_E1CAP_MODE_RAW; case E1INP_TS_TYPE_HDLC: return OSMO_E1CAP_MODE_HDLC; case E1INP_TS_TYPE_TRAU: return OSMO_E1CAP_MODE_TRAU; default: OSMO_ASSERT(0); } } static int sig_inp_cbfn(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { struct input_signal_data *isd = signal_data; struct e1_recorder_line *rline; OSMO_ASSERT(subsys == SS_L_INPUT); OSMO_ASSERT(isd->line && isd->line->num < ARRAY_SIZE(g_recorder.line)); switch (signal) { case S_L_INP_LINE_ALARM: LOGP(DMAIN, LOGL_NOTICE, "Line %u: ALARM\n", isd->line->num); rline = &g_recorder.line[isd->line->num]; rline->has_alarm = true; break; case S_L_INP_LINE_NOALARM: LOGP(DMAIN, LOGL_NOTICE, "Line %u: NOALARM\n", isd->line->num); rline = &g_recorder.line[isd->line->num]; rline->has_alarm = false; break; } return 0; } /* receive a raw message frome the E1 timeslot */ void e1ts_raw_recv(struct e1inp_ts *ts, struct msgb *msg) { struct e1_recorder_line *rline = &g_recorder.line[ts->line->num]; enum osmo_e1cap_capture_mode cap_mode = ts2cap_mode(ts); int rc; if (rline->has_alarm) { DEBUGP(DMAIN, "Skipping storage as line %u is in ALARM\n", ts->line->num); return; } /* FIXME: special processing of TFP and PGSL */ rc = e1frame_store(ts, msg, cap_mode); if (rc < 0) { LOGP(DMAIN, LOGL_FATAL, "Error writing E1/T1 frame to disk\n"); exit(1); } if (rline->mirror.enabled) { struct e1inp_line *other_line = e1inp_line_find(rline->mirror.line_nr); OSMO_ASSERT(other_line); struct e1inp_ts *other_ts; other_ts = &other_line->ts[ts->num-1]; if (!other_ts) { msgb_free(msg); return; } /* forward data to destination line */ OSMO_ASSERT(other_ts->type == ts->type); msgb_enqueue(&other_ts->raw.tx_queue, msg); } else msgb_free(msg); } static int inp_sig_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { OSMO_ASSERT(subsys == SS_L_INPUT); /* FIXME */ return 0; } static const struct log_info_cat recorder_categories[] = { [DMAIN] = { .name = "MAIN", .description = "Osmocom E1 Recorder", .enabled = 1, .loglevel = LOGL_DEBUG, }, }; static struct log_info info = { .cat = recorder_categories, .num_cat = ARRAY_SIZE(recorder_categories), }; struct vty_app_info vty_info = { .name = "osmo-e1-recorder", .version = PACKAGE_VERSION, .copyright = "(C) 2016-2019 by Harald Welte \n", }; static void *rec_tall_ctx; struct e1_recorder g_recorder; static char *g_config_file = "osmo-e1-recorder.cfg"; static void signal_handler(int signo) { switch (signo) { case SIGHUP: storage_close(); break; case SIGUSR1: talloc_report(rec_tall_ctx, stderr); break; } } static void print_help(void) { printf( " -h --help This help\n" " -V --version Print version of the program\n" " -c --config FILE Specify configuration file\n" ); } static void handle_options(int argc, char **argv) { while (1) { int option_index = 0, c; static const struct option long_options[] = { { "config-file", 1, 0, 'c' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "c:hV", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': g_config_file = optarg; break; case 'h': print_help(); exit(0); break; case 'V': print_version(1); exit(0); break; } } if (argc > optind) { fprintf(stderr, "Unsupported positional arguments on command line\n"); exit(2); } } int main(int argc, char **argv) { int rc; rec_tall_ctx = talloc_named_const(NULL, 0, "recorder"); osmo_init_logging2(rec_tall_ctx, &info); vty_init(&vty_info); logging_vty_add_cmds(); osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL); libosmo_abis_init(rec_tall_ctx); e1inp_vty_init(); recorder_vty_init(); signal(SIGHUP, &signal_handler); signal(SIGUSR1, &signal_handler); handle_options(argc, argv); osmo_signal_register_handler(SS_L_INPUT, sig_inp_cbfn, NULL); rc = vty_read_config_file(g_config_file, NULL); if (rc < 0) { fprintf(stderr, "Cannot parse configuration file '%s': %s\n", g_config_file, strerror(errno)); exit(1); } /* start telnet after reading config */ rc = telnet_init_default(rec_tall_ctx, NULL, 4444); if (rc < 0) { fprintf(stderr, "Cannot open telnet server port: %s\n", strerror(errno)); exit(1); } while (1) { osmo_select_main(0); }; }