|
|
|
@ -35,6 +35,9 @@ struct pcap_format { |
|
|
|
static int check_main_spool_dir(const char *spoolpath); |
|
|
|
static char *recording_setup_file(struct recording *recording); |
|
|
|
static char *meta_setup_file(struct recording *recording); |
|
|
|
static int append_meta_chunk(struct recording *recording, const char *buf, unsigned int buflen, |
|
|
|
const char *label_fmt, ...) |
|
|
|
__attribute__((format(printf,4,5))); |
|
|
|
|
|
|
|
// pcap methods |
|
|
|
static int pcap_create_spool_dir(const char *dirpath); |
|
|
|
@ -58,6 +61,9 @@ static void kernel_info_proc(struct packet_stream *, struct rtpengine_target_inf |
|
|
|
|
|
|
|
static void pcap_eth_header(unsigned char *, struct packet_stream *); |
|
|
|
|
|
|
|
#define append_meta_chunk_str(r, str, f...) append_meta_chunk(r, (str)->s, (str)->len, f) |
|
|
|
#define append_meta_chunk_s(r, str, f...) append_meta_chunk(r, (str), strlen(str), f) |
|
|
|
#define append_meta_chunk_null(r,f...) append_meta_chunk(r, "", 0, f) |
|
|
|
|
|
|
|
|
|
|
|
static const struct recording_method methods[] = { |
|
|
|
@ -224,12 +230,26 @@ static void update_metadata(struct call *call, str *metadata) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// lock must be held |
|
|
|
static void recording_update_flags(struct call *call) { |
|
|
|
append_meta_chunk_null(call->recording, "RECORDING %u", call->recording_on ? 1 : 0); |
|
|
|
append_meta_chunk_null(call->recording, "FORWARDING %u", call->rec_forwarding ? 1 : 0); |
|
|
|
for (GList *l = call->streams.head; l; l = l->next) { |
|
|
|
struct packet_stream *ps = l->data; |
|
|
|
append_meta_chunk_null(call->recording, "STREAM %u FORWARDING %u", |
|
|
|
ps->unique_id, ps->media->monologue->rec_forwarding ? 1 : 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// lock must be held |
|
|
|
void recording_start(struct call *call, const char *prefix, str *metadata) { |
|
|
|
update_metadata(call, metadata); |
|
|
|
|
|
|
|
if (call->recording) // already active |
|
|
|
if (call->recording) { |
|
|
|
// already active |
|
|
|
recording_update_flags(call); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (!spooldir) { |
|
|
|
ilog(LOG_ERR, "Call recording requested, but no spool directory configured"); |
|
|
|
@ -267,11 +287,27 @@ void recording_start(struct call *call, const char *prefix, str *metadata) { |
|
|
|
__unkernelize(ps); |
|
|
|
ps->handler = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
recording_update_flags(call); |
|
|
|
} |
|
|
|
void recording_stop(struct call *call) { |
|
|
|
if (!call->recording) |
|
|
|
return; |
|
|
|
|
|
|
|
// check if all recording options are disabled |
|
|
|
if (call->recording_on || call->rec_forwarding) { |
|
|
|
recording_update_flags(call); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
for (GList *l = call->monologues.head; l; l = l->next) { |
|
|
|
struct call_monologue *ml = l->data; |
|
|
|
if (ml->rec_forwarding) { |
|
|
|
recording_update_flags(call); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ilog(LOG_NOTICE, "Turning off call recording."); |
|
|
|
recording_finish(call); |
|
|
|
} |
|
|
|
@ -628,10 +664,6 @@ static int vappend_meta_chunk_iov(struct recording *recording, struct iovec *in_ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int append_meta_chunk(struct recording *recording, const char *buf, unsigned int buflen, |
|
|
|
const char *label_fmt, ...) |
|
|
|
__attribute__((format(printf,4,5))); |
|
|
|
|
|
|
|
static int append_meta_chunk(struct recording *recording, const char *buf, unsigned int buflen, |
|
|
|
const char *label_fmt, ...) |
|
|
|
{ |
|
|
|
@ -646,8 +678,6 @@ static int append_meta_chunk(struct recording *recording, const char *buf, unsig |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
#define append_meta_chunk_str(r, str, f...) append_meta_chunk(r, (str)->s, (str)->len, f) |
|
|
|
#define append_meta_chunk_s(r, str, f...) append_meta_chunk(r, (str), strlen(str), f) |
|
|
|
|
|
|
|
static void proc_init(struct call *call) { |
|
|
|
struct recording *recording = call->recording; |
|
|
|
@ -694,8 +724,14 @@ static void finish_proc(struct call *call) { |
|
|
|
struct recording *recording = call->recording; |
|
|
|
if (!kernel.is_open) |
|
|
|
return; |
|
|
|
if (recording->u.proc.call_idx != UNINIT_IDX) |
|
|
|
if (recording->u.proc.call_idx != UNINIT_IDX) { |
|
|
|
kernel_del_call(recording->u.proc.call_idx); |
|
|
|
recording->u.proc.call_idx = UNINIT_IDX; |
|
|
|
} |
|
|
|
for (GList *l = call->streams.head; l; l = l->next) { |
|
|
|
struct packet_stream *ps = l->data; |
|
|
|
ps->recording.u.proc.stream_idx = UNINIT_IDX; |
|
|
|
} |
|
|
|
unlink(recording->meta_filepath); |
|
|
|
} |
|
|
|
|
|
|
|
|