From b7e40238d75754a00ac5dd57627b08980d032cbe Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 29 Jul 2016 14:26:50 +0200 Subject: first functional version that actually records + mirrors data --- src/e1_recorder.c | 13 ++++++++-- src/recorder.h | 1 + src/storage.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/vty.c | 21 +++++++++++++-- 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/src/e1_recorder.c b/src/e1_recorder.c index 5c53205..d8dccfe 100644 --- a/src/e1_recorder.c +++ b/src/e1_recorder.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,15 @@ void e1ts_raw_recv(struct e1inp_ts *ts, struct msgb *msg) e1frame_store(ts, msg, cap_mode); if (rline->mirror.enabled) { + struct e1inp_line *other_line = + e1inp_line_find(rline->mirror.line_nr); + struct e1inp_ts *other_ts; + other_ts = &other_line->ts[ts->num-1]; + if (!other_ts) + return; /* forward data to destination line */ + OSMO_ASSERT(other_ts->type == ts->type); + msgb_enqueue(&other_ts->raw.tx_queue, msg); } } @@ -49,11 +58,10 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal, return 0; } -// e1inp_ts_config_raw(ts, line, &e1ts_raw_recv); - static const struct log_info_cat recorder_categories[] = { [DMAIN] = { .name = "MAIN", + .description = "Osmocom E1 Recorder", .enabled = 1, .loglevel = LOGL_DEBUG, }, }; @@ -79,6 +87,7 @@ int main(int argc, char **argv) osmo_init_logging(&info); vty_init(&vty_info); + logging_vty_add_cmds(&info); osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL); libosmo_abis_init(rec_tall_ctx); e1inp_vty_init(); diff --git a/src/recorder.h b/src/recorder.h index eaa5eab..12bc993 100644 --- a/src/recorder.h +++ b/src/recorder.h @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/src/storage.c b/src/storage.c index 571a043..2b9fb9f 100644 --- a/src/storage.c +++ b/src/storage.c @@ -1,20 +1,86 @@ +#include +#include +#include +#include +#include +#include + #include #include #include "storage.h" +#include "recorder.h" + +static int g_out_fd = -1;; +static uint64_t g_written_bytes; + +static const char *storage_gen_filename(void) +{ + static char buf[32]; + time_t t; + struct tm *tmp; + + t = time(NULL); + tmp = localtime(&t); + strftime(buf, sizeof(buf), "%Y%m%d%H%M%S.e1cap", tmp); + return buf; +} + +static int storage_reopen_if_needed(void) +{ + if (g_written_bytes / (1024*1024) >= g_recorder.max_file_size_mb) { + close(g_out_fd); + g_out_fd = -1; + } + + if (g_out_fd < 0) { + int rc; + const char *fname = storage_gen_filename(); + rc = chdir(g_recorder.storage_path); + if (rc < 0) { + LOGP(DMAIN, LOGL_ERROR, "Unable to chdir(%s): %s\n", + g_recorder.storage_path, strerror(errno)); + return -1; + } + g_out_fd = open(fname, O_WRONLY|O_CREAT, 0664); + if (g_out_fd < 0) { + LOGP(DMAIN, LOGL_ERROR, "Unable to open(%s): %s\n", + fname, strerror(errno)); + } + g_written_bytes = 0; + } + + return g_out_fd; +} int e1frame_store(struct e1inp_ts *ts, struct msgb *msg, enum osmo_e1cap_capture_mode mode) { - struct osmo_e1cap_pkthdr *h; - uint32_t len = msg->len; + struct osmo_e1cap_pkthdr _h, *h = &_h; + int rc; + struct iovec iov[2] = { + { + .iov_base = h, + .iov_len = sizeof(*h), + }, { + .iov_base = msg->data, + .iov_len = msg->len, + } + }; - h = (struct osmo_e1cap_pkthdr *) msgb_push(msg, sizeof(*h)); - h->len = htonl(len); + h->len = htonl(msg->len); + gettimeofday(&h->ts, NULL); h->line_nr = ts->line->num; h->ts_nr = ts->num; h->capture_mode = mode; h->flags = 0; - /* FIXME: Write */ + storage_reopen_if_needed(); + + rc = writev(g_out_fd, iov, ARRAY_SIZE(iov)); + if (rc < 0) + return rc; + + g_written_bytes += rc; + return 0; } diff --git a/src/vty.c b/src/vty.c index 694dab1..ae032fb 100644 --- a/src/vty.c +++ b/src/vty.c @@ -15,8 +15,14 @@ DEFUN(cfg_recorder, cfg_recorder_cmd, return CMD_SUCCESS; } +static const struct e1inp_line_ops dummy_e1i_line_ops = { + .sign_link_up = NULL, + .sign_link_down = NULL, + .sign_link = NULL, +}; + DEFUN(cfg_rec_line_ts_mode, cfg_rec_line_ts_mode_cmd, - "line <0-255> ts <0-31> mode (none|signalling|trau|raw)", + "line <0-255> ts <1-31> mode (none|signalling|trau|raw)", LINE_STR "E1/T1 Timeslot Number\n" "E1/T1 Timeslot Number\n" @@ -46,8 +52,10 @@ DEFUN(cfg_rec_line_ts_mode, cfg_rec_line_ts_mode_cmd, vty_out(vty, "Timeslot %d is too large%s", ts_nr, VTY_NEWLINE); return CMD_WARNING; } - ts = &line->ts[ts_nr]; + ts = &line->ts[ts_nr-1]; + e1inp_line_bind_ops(line, &dummy_e1i_line_ops); + vty_out(vty, "Line %u TS %u mode %u%s", line_nr, ts_nr, mode, VTY_NEWLINE); switch (mode) { case E1INP_TS_TYPE_NONE: /* TOOD: have eqinp_ts_config_none ? */ @@ -59,6 +67,9 @@ DEFUN(cfg_rec_line_ts_mode, cfg_rec_line_ts_mode_cmd, case E1INP_TS_TYPE_RAW: e1inp_ts_config_raw(ts, line, &e1ts_raw_recv); break; + default: + vty_out(vty, "Unknown mode %u ?!?%s", mode, VTY_NEWLINE); + break; } /* notify driver of change */ @@ -157,6 +168,12 @@ static void config_write_recorder_line(struct vty *vty, unsigned int lnr) for (i = 0; i < line->num_ts; i++) { struct e1inp_ts *ts = &line->ts[i]; + const char *mode_str; + + mode_str = get_value_string(e1inp_ts_type_names, ts->type); + + vty_out(vty, " line %u ts %u mode %s%s", + lnr, ts->num, mode_str, VTY_NEWLINE); } } -- cgit v1.2.3