blob: 07fd4a6da9382c5d3c20a9d3f50ddb3732dae845 [file] [log] [blame]
Harald Weltedf7a3062016-10-19 10:47:17 +02001#include <signal.h>
Harald Welte4dc14a72016-10-19 10:53:47 +02002#include <getopt.h>
Harald Welte2c5c0792019-12-04 11:35:14 +01003#include <errno.h>
Harald Weltedf7a3062016-10-19 10:47:17 +02004
Harald Welte39cfbf42016-07-28 09:04:11 +02005#include <osmocom/core/signal.h>
6#include <osmocom/core/logging.h>
7#include <osmocom/core/application.h>
8#include <osmocom/vty/vty.h>
9#include <osmocom/vty/telnet_interface.h>
Harald Welteb7e40232016-07-29 14:26:50 +020010#include <osmocom/vty/logging.h>
Harald Welte39cfbf42016-07-28 09:04:11 +020011
12#include <osmocom/abis/abis.h>
13#include <osmocom/abis/e1_input.h>
14
15#include "storage.h"
16#include "recorder.h"
17
18static enum osmo_e1cap_capture_mode ts2cap_mode(struct e1inp_ts *ts)
19{
20 switch (ts->type) {
21 case E1INP_TS_TYPE_RAW:
22 return OSMO_E1CAP_MODE_RAW;
Harald Welte13351132016-10-17 22:13:36 +020023 case E1INP_TS_TYPE_HDLC:
Harald Welte39cfbf42016-07-28 09:04:11 +020024 return OSMO_E1CAP_MODE_HDLC;
25 case E1INP_TS_TYPE_TRAU:
26 return OSMO_E1CAP_MODE_TRAU;
27 default:
28 OSMO_ASSERT(0);
29 }
30}
31
32/* receive a raw message frome the E1 timeslot */
33void e1ts_raw_recv(struct e1inp_ts *ts, struct msgb *msg)
34{
Harald Welte0e91aa12016-07-28 21:03:40 +020035 struct e1_recorder_line *rline = &g_recorder.line[ts->line->num];
Harald Welte39cfbf42016-07-28 09:04:11 +020036 enum osmo_e1cap_capture_mode cap_mode = ts2cap_mode(ts);
Harald Welte2ac78492016-10-19 10:47:41 +020037 int rc;
Harald Welte39cfbf42016-07-28 09:04:11 +020038
39 /* FIXME: special processing of TFP and PGSL */
40
Harald Welte2ac78492016-10-19 10:47:41 +020041 rc = e1frame_store(ts, msg, cap_mode);
42 if (rc < 0) {
43 LOGP(DMAIN, LOGL_FATAL, "Error writing E1/T1 frame to disk\n");
44 exit(1);
45 }
Harald Welte39cfbf42016-07-28 09:04:11 +020046
Harald Welte0e91aa12016-07-28 21:03:40 +020047 if (rline->mirror.enabled) {
Harald Welteb7e40232016-07-29 14:26:50 +020048 struct e1inp_line *other_line =
49 e1inp_line_find(rline->mirror.line_nr);
50 struct e1inp_ts *other_ts;
51 other_ts = &other_line->ts[ts->num-1];
Harald Welte4a92d0b2016-10-18 21:36:01 +020052 if (!other_ts) {
53 msgb_free(msg);
Harald Welteb7e40232016-07-29 14:26:50 +020054 return;
Harald Welte4a92d0b2016-10-18 21:36:01 +020055 }
Harald Welte39cfbf42016-07-28 09:04:11 +020056 /* forward data to destination line */
Harald Welteb7e40232016-07-29 14:26:50 +020057 OSMO_ASSERT(other_ts->type == ts->type);
58 msgb_enqueue(&other_ts->raw.tx_queue, msg);
Harald Welte4a92d0b2016-10-18 21:36:01 +020059 } else
60 msgb_free(msg);
Harald Welte39cfbf42016-07-28 09:04:11 +020061}
62
63static int inp_sig_cb(unsigned int subsys, unsigned int signal,
64 void *handler_data, void *signal_data)
65{
66 OSMO_ASSERT(subsys == SS_L_INPUT);
67
68 /* FIXME */
69
70 return 0;
71}
72
Harald Welte39cfbf42016-07-28 09:04:11 +020073static const struct log_info_cat recorder_categories[] = {
74 [DMAIN] = {
75 .name = "MAIN",
Harald Welteb7e40232016-07-29 14:26:50 +020076 .description = "Osmocom E1 Recorder",
Harald Welte39cfbf42016-07-28 09:04:11 +020077 .enabled = 1, .loglevel = LOGL_DEBUG,
78 },
79};
80static struct log_info info = {
81 .cat = recorder_categories,
82 .num_cat = ARRAY_SIZE(recorder_categories),
83};
84
85struct vty_app_info vty_info = {
86 .name = "osmo-e1-recorder",
87 .version = "0",
88 .copyright = "(C) 2016 by Harald Welte <laforge@gnumonks.org>\n",
89};
90
91static void *rec_tall_ctx;
92struct e1_recorder g_recorder;
Harald Welte4dc14a72016-10-19 10:53:47 +020093static char *g_config_file = "osmo-e1-recorder.cfg";
Harald Welte39cfbf42016-07-28 09:04:11 +020094
Harald Weltedf7a3062016-10-19 10:47:17 +020095static void signal_handler(int signo)
96{
97 switch (signo) {
98 case SIGHUP:
99 storage_close();
100 break;
101 case SIGUSR1:
102 talloc_report(rec_tall_ctx, stderr);
103 break;
104 }
105}
106
Harald Welte4dc14a72016-10-19 10:53:47 +0200107static void handle_options(int argc, char **argv)
108{
109 while (1) {
110 int option_index = 0, c;
111 static const struct option long_options[] = {
112 { "config-file", 1, 0, 'c' },
113 { 0, 0, 0, 0 }
114 };
115
116 c = getopt_long(argc, argv, "c:",
117 long_options, &option_index);
118 if (c == -1)
119 break;
120
121 switch (c) {
122 case 'c':
123 g_config_file = optarg;
124 break;
125 }
126 }
Harald Weltecbf23b62019-12-03 22:14:20 +0100127
128 if (argc > optind) {
129 fprintf(stderr, "Unsupported positional arguments on command line\n");
130 exit(2);
131 }
Harald Welte4dc14a72016-10-19 10:53:47 +0200132}
133
Harald Welte39cfbf42016-07-28 09:04:11 +0200134int main(int argc, char **argv)
135{
136 int rc;
137
138 rec_tall_ctx = talloc_named_const(NULL, 0, "recorder");
139
140 osmo_init_logging(&info);
141 vty_init(&vty_info);
Harald Welteb7e40232016-07-29 14:26:50 +0200142 logging_vty_add_cmds(&info);
Harald Welte39cfbf42016-07-28 09:04:11 +0200143 osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL);
144 libosmo_abis_init(rec_tall_ctx);
145 e1inp_vty_init();
146 recorder_vty_init();
147
Harald Weltedf7a3062016-10-19 10:47:17 +0200148 signal(SIGHUP, &signal_handler);
149 signal(SIGUSR1, &signal_handler);
150
Harald Welte4dc14a72016-10-19 10:53:47 +0200151 handle_options(argc, argv);
152
153 rc = vty_read_config_file(g_config_file, NULL);
Harald Welte2c5c0792019-12-04 11:35:14 +0100154 if (rc < 0) {
155 fprintf(stderr, "Cannot parse configuration file '%s': %s\n", g_config_file,
156 strerror(errno));
Harald Welte39cfbf42016-07-28 09:04:11 +0200157 exit(1);
Harald Welte2c5c0792019-12-04 11:35:14 +0100158 }
Harald Welte39cfbf42016-07-28 09:04:11 +0200159
160 /* start telne tafte reading config for vty_get_bind_adr() */
161 telnet_init_dynif(rec_tall_ctx, NULL, vty_get_bind_addr(), 4444);
162
163 while (1) {
164 osmo_select_main(0);
165 };
166}