first functional version that actually records + mirrors data

This commit is contained in:
Harald Welte 2016-07-29 14:26:50 +02:00
parent 0e91aa1ec5
commit b7e40238d7
4 changed files with 102 additions and 9 deletions

View File

@ -3,6 +3,7 @@
#include <osmocom/core/application.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
#include <osmocom/abis/abis.h>
#include <osmocom/abis/e1_input.h>
@ -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();

View File

@ -2,6 +2,7 @@
#include <stdbool.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/logging.h>
#include <osmocom/vty/command.h>
#include <osmocom/abis/e1_input.h>

View File

@ -1,20 +1,86 @@
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <osmocom/core/msgb.h>
#include <osmocom/abis/e1_input.h>
#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;
}

View File

@ -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);
}
}