Browse Source

Merge branch 'master' of https://github.com/smititelu/rtpengine

Change-Id: I12d530f2d44edcb77fbdb23a0f30fec03161468b
pull/1525/head
Richard Fuchs 3 years ago
parent
commit
9c28951e40
4 changed files with 94 additions and 19 deletions
  1. +1
    -1
      daemon/main.c
  2. +85
    -14
      daemon/recording.c
  3. +5
    -2
      daemon/rtpengine.pod
  4. +3
    -2
      include/recording.h

+ 1
- 1
daemon/main.c View File

@ -512,7 +512,7 @@ static void options(int *argc, char ***argv) {
{ "homer-protocol",0,0,G_OPTION_ARG_STRING, &homerproto, "Transport protocol for Homer (default udp)", "udp|tcp" }, { "homer-protocol",0,0,G_OPTION_ARG_STRING, &homerproto, "Transport protocol for Homer (default udp)", "udp|tcp" },
{ "homer-id", 0, 0, G_OPTION_ARG_INT, &rtpe_config.homer_id, "'Capture ID' to use within the HEP protocol", "INT" }, { "homer-id", 0, 0, G_OPTION_ARG_INT, &rtpe_config.homer_id, "'Capture ID' to use within the HEP protocol", "INT" },
{ "recording-dir", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.spooldir, "Directory for storing pcap and metadata files", "FILE" }, { "recording-dir", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.spooldir, "Directory for storing pcap and metadata files", "FILE" },
{ "recording-method",0, 0, G_OPTION_ARG_STRING, &rtpe_config.rec_method, "Strategy for call recording", "pcap|proc" },
{ "recording-method",0, 0, G_OPTION_ARG_STRING, &rtpe_config.rec_method, "Strategy for call recording", "pcap|proc|all" },
{ "recording-format",0, 0, G_OPTION_ARG_STRING, &rtpe_config.rec_format, "File format for stored pcap files", "raw|eth" }, { "recording-format",0, 0, G_OPTION_ARG_STRING, &rtpe_config.rec_format, "File format for stored pcap files", "raw|eth" },
#ifdef WITH_IPTABLES_OPTION #ifdef WITH_IPTABLES_OPTION
{ "iptables-chain",0,0, G_OPTION_ARG_STRING, &rtpe_config.iptables_chain,"Add explicit firewall rules to this iptables chain","STRING" }, { "iptables-chain",0,0, G_OPTION_ARG_STRING, &rtpe_config.iptables_chain,"Add explicit firewall rules to this iptables chain","STRING" },


+ 85
- 14
daemon/recording.c View File

@ -39,6 +39,14 @@ static int append_meta_chunk(struct recording *recording, const char *buf, unsig
const char *label_fmt, ...) const char *label_fmt, ...)
__attribute__((format(printf,4,5))); __attribute__((format(printf,4,5)));
// all methods
static int create_spool_dir_all(const char *spoolpath);
static void init_all(struct call *call);
static void sdp_after_all(struct recording *recording, GString *str, struct call_monologue *ml,
enum call_opmode opmode);
static void dump_packet_all(struct media_packet *mp, const str *s);
static void finish_all(struct call *call);
// pcap methods // pcap methods
static int rec_pcap_create_spool_dir(const char *dirpath); static int rec_pcap_create_spool_dir(const char *dirpath);
static void rec_pcap_init(struct call *); static void rec_pcap_init(struct call *);
@ -68,15 +76,23 @@ static void rec_pcap_eth_header(unsigned char *, struct packet_stream *);
#define append_meta_chunk_null(r,f...) append_meta_chunk(r, "", 0, f) #define append_meta_chunk_null(r,f...) append_meta_chunk(r, "", 0, f)
static const struct recording_method methods[] = {
const struct recording_method methods[] = {
{ {
.name = "pcap", .name = "pcap",
.kernel_support = 0, .kernel_support = 0,
.create_spool_dir = rec_pcap_create_spool_dir, .create_spool_dir = rec_pcap_create_spool_dir,
.init_struct = rec_pcap_init, .init_struct = rec_pcap_init,
.sdp_before = NULL,
.sdp_after = sdp_after_pcap, .sdp_after = sdp_after_pcap,
.meta_chunk = NULL,
.update_flags = NULL,
.dump_packet = dump_packet_pcap, .dump_packet = dump_packet_pcap,
.finish = finish_pcap, .finish = finish_pcap,
.init_stream_struct = NULL,
.setup_stream = NULL,
.setup_media = NULL,
.setup_monologue = NULL,
.stream_kernel_info = NULL,
.response = response_pcap, .response = response_pcap,
}, },
{ {
@ -95,6 +111,25 @@ static const struct recording_method methods[] = {
.setup_media = setup_media_proc, .setup_media = setup_media_proc,
.setup_monologue = setup_monologue_proc, .setup_monologue = setup_monologue_proc,
.stream_kernel_info = kernel_info_proc, .stream_kernel_info = kernel_info_proc,
.response = NULL,
},
{
.name = "all",
.kernel_support = 0,
.create_spool_dir = create_spool_dir_all,
.init_struct = init_all,
.sdp_before = sdp_before_proc,
.sdp_after = sdp_after_all,
.meta_chunk = meta_chunk_proc,
.update_flags = update_flags_proc,
.dump_packet = dump_packet_all,
.finish = finish_all,
.init_stream_struct = init_stream_proc,
.setup_stream = setup_stream_proc,
.setup_media = setup_media_proc,
.setup_monologue = setup_monologue_proc,
.stream_kernel_info = kernel_info_proc,
.response = response_pcap,
}, },
}; };
@ -425,14 +460,14 @@ static char *meta_setup_file(struct recording *recording) {
} }
char *meta_filepath = file_path_str(recording->meta_prefix, "/tmp/rtpengine-meta-", ".tmp"); char *meta_filepath = file_path_str(recording->meta_prefix, "/tmp/rtpengine-meta-", ".tmp");
recording->meta_filepath = meta_filepath;
recording->meta_filepath_pcap = meta_filepath;
FILE *mfp = fopen(meta_filepath, "w"); FILE *mfp = fopen(meta_filepath, "w");
// coverity[check_return : FALSE] // coverity[check_return : FALSE]
chmod(meta_filepath, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); chmod(meta_filepath, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
if (mfp == NULL) { if (mfp == NULL) {
ilog(LOG_ERROR, "Could not open metadata file: %s%s%s", FMT_M(meta_filepath)); ilog(LOG_ERROR, "Could not open metadata file: %s%s%s", FMT_M(meta_filepath));
free(meta_filepath); free(meta_filepath);
recording->meta_filepath = NULL;
recording->meta_filepath_pcap = NULL;
return NULL; return NULL;
} }
recording->u.pcap.meta_fp = mfp; recording->u.pcap.meta_fp = mfp;
@ -513,10 +548,10 @@ static int rec_pcap_meta_finish_file(struct call *call) {
// and move it to the finished file location. // and move it to the finished file location.
// Rename extension to ".txt". // Rename extension to ".txt".
int fn_len; int fn_len;
char *meta_filename = strrchr(recording->meta_filepath, '/');
char *meta_filename = strrchr(recording->meta_filepath_pcap, '/');
char *meta_ext = NULL; char *meta_ext = NULL;
if (meta_filename == NULL) { if (meta_filename == NULL) {
meta_filename = recording->meta_filepath;
meta_filename = recording->meta_filepath_pcap;
} }
else { else {
meta_filename = meta_filename + 1; meta_filename = meta_filename + 1;
@ -529,13 +564,13 @@ static int rec_pcap_meta_finish_file(struct call *call) {
char new_metapath[prefix_len + fn_len + ext_len + 1]; char new_metapath[prefix_len + fn_len + ext_len + 1];
snprintf(new_metapath, prefix_len+fn_len+1, "%s/metadata/%s", spooldir, meta_filename); snprintf(new_metapath, prefix_len+fn_len+1, "%s/metadata/%s", spooldir, meta_filename);
snprintf(new_metapath + prefix_len+fn_len, ext_len+1, ".txt"); snprintf(new_metapath + prefix_len+fn_len, ext_len+1, ".txt");
return_code = return_code || rename(recording->meta_filepath, new_metapath);
return_code = return_code || rename(recording->meta_filepath_pcap, new_metapath);
if (return_code != 0) { if (return_code != 0) {
ilog(LOG_ERROR, "Could not move metadata file \"%s\" to \"%s/metadata/\"", ilog(LOG_ERROR, "Could not move metadata file \"%s\" to \"%s/metadata/\"",
recording->meta_filepath, spooldir);
recording->meta_filepath_pcap, spooldir);
} else { } else {
ilog(LOG_INFO, "Moved metadata file \"%s\" to \"%s/metadata\"", ilog(LOG_INFO, "Moved metadata file \"%s\" to \"%s/metadata\"",
recording->meta_filepath, spooldir);
recording->meta_filepath_pcap, spooldir);
} }
mutex_destroy(&recording->u.pcap.recording_lock); mutex_destroy(&recording->u.pcap.recording_lock);
@ -672,7 +707,8 @@ void recording_finish(struct call *call) {
free(recording->meta_prefix); free(recording->meta_prefix);
free(recording->escaped_callid); free(recording->escaped_callid);
free(recording->meta_filepath);
free(recording->meta_filepath_pcap);
free(recording->meta_filepath_proc);
g_slice_free1(sizeof(*(recording)), recording); g_slice_free1(sizeof(*(recording)), recording);
call->recording = NULL; call->recording = NULL;
@ -687,10 +723,10 @@ void recording_finish(struct call *call) {
static int open_proc_meta_file(struct recording *recording) { static int open_proc_meta_file(struct recording *recording) {
int fd; int fd;
fd = open(recording->meta_filepath, O_WRONLY | O_APPEND | O_CREAT, 0666);
fd = open(recording->meta_filepath_proc, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd == -1) { if (fd == -1) {
ilog(LOG_ERR, "Failed to open recording metadata file '%s' for writing: %s", ilog(LOG_ERR, "Failed to open recording metadata file '%s' for writing: %s",
recording->meta_filepath, strerror(errno));
recording->meta_filepath_proc, strerror(errno));
return -1; return -1;
} }
return fd; return fd;
@ -756,8 +792,8 @@ static void proc_init(struct call *call) {
} }
ilog(LOG_DEBUG, "kernel call idx is %u", recording->u.proc.call_idx); ilog(LOG_DEBUG, "kernel call idx is %u", recording->u.proc.call_idx);
recording->meta_filepath = file_path_str(recording->meta_prefix, "/", ".meta");
unlink(recording->meta_filepath); // start fresh XXX good idea?
recording->meta_filepath_proc = file_path_str(recording->meta_prefix, "/", ".meta");
unlink(recording->meta_filepath_proc); // start fresh XXX good idea?
append_meta_chunk_str(recording, &call->callid, "CALL-ID"); append_meta_chunk_str(recording, &call->callid, "CALL-ID");
append_meta_chunk_s(recording, recording->meta_prefix, "PARENT"); append_meta_chunk_s(recording, recording->meta_prefix, "PARENT");
@ -791,7 +827,7 @@ static void finish_proc(struct call *call) {
struct packet_stream *ps = l->data; struct packet_stream *ps = l->data;
ps->recording.u.proc.stream_idx = UNINIT_IDX; ps->recording.u.proc.stream_idx = UNINIT_IDX;
} }
unlink(recording->meta_filepath);
unlink(recording->meta_filepath_proc);
} }
static void init_stream_proc(struct packet_stream *stream) { static void init_stream_proc(struct packet_stream *stream) {
@ -904,3 +940,38 @@ static void kernel_info_proc(struct packet_stream *stream, struct rtpengine_targ
static void meta_chunk_proc(struct recording *recording, const char *label, const str *data) { static void meta_chunk_proc(struct recording *recording, const char *label, const str *data) {
append_meta_chunk_str(recording, data, "%s", label); append_meta_chunk_str(recording, data, "%s", label);
} }
static int create_spool_dir_all(const char *spoolpath) {
int ret1, ret2;
ret1 = rec_pcap_create_spool_dir(spoolpath);
ret2 = check_main_spool_dir(spoolpath);
if (ret1 == FALSE || ret2 == FALSE) {
return FALSE;
}
return TRUE;
}
static void init_all(struct call *call) {
rec_pcap_init(call);
proc_init(call);
}
static void sdp_after_all(struct recording *recording, GString *str, struct call_monologue *ml,
enum call_opmode opmode)
{
sdp_after_pcap(recording, str, ml, opmode);
sdp_after_proc(recording, str, ml, opmode);
}
static void dump_packet_all(struct media_packet *mp, const str *s) {
dump_packet_pcap(mp, s);
dump_packet_proc(mp, s);
}
static void finish_all(struct call *call) {
finish_pcap(call);
finish_proc(call);
}

+ 5
- 2
daemon/rtpengine.pod View File

@ -603,11 +603,11 @@ Since call recording via this method happens entirely in userspace,
in-kernel packet forwarding cannot be used for calls that are currently in-kernel packet forwarding cannot be used for calls that are currently
being recorded and packet forwarding will thus be done in userspace only. being recorded and packet forwarding will thus be done in userspace only.
=item B<--recording-method=>B<pcap>|B<proc>
=item B<--recording-method=>B<pcap>|B<proc>|B<all>
Multiple methods of call recording are supported and this option can be Multiple methods of call recording are supported and this option can be
used to select one. used to select one.
Currently supported are the method B<pcap> and B<proc>.
Currently supported are the method B<pcap>, B<proc> and B<all>.
The default method is B<pcap> and is the one described above. The default method is B<pcap> and is the one described above.
The recording method B<proc> works by writing metadata files directly into The recording method B<proc> works by writing metadata files directly into
@ -629,6 +629,9 @@ any purpose or not.
In-kernel packet forwarding is fully supported with this recording method In-kernel packet forwarding is fully supported with this recording method
even for calls being recorded. even for calls being recorded.
The recording method B<all> will enable both B<pcap> and B<proc>
at the same time.
=item B<--recording-format=>B<raw>|B<eth> =item B<--recording-format=>B<raw>|B<eth>
When recording to pcap file in B<raw> (default) format, there is no When recording to pcap file in B<raw> (default) format, there is no


+ 3
- 2
include/recording.h View File

@ -44,14 +44,15 @@ struct recording_stream_proc {
}; };
struct recording { struct recording {
union {
struct {
struct recording_pcap pcap; struct recording_pcap pcap;
struct recording_proc proc; struct recording_proc proc;
} u; } u;
char *escaped_callid; // call-id with dangerous characters escaped char *escaped_callid; // call-id with dangerous characters escaped
char *meta_prefix; // escaped call-id plus random suffix char *meta_prefix; // escaped call-id plus random suffix
char *meta_filepath; // full file path
char *meta_filepath_proc; // full file path
char *meta_filepath_pcap; // full file path
}; };
struct recording_stream { struct recording_stream {


Loading…
Cancel
Save