diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index a8319e07e..01a51f5bc 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1757,10 +1757,11 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t chopper = sdp_chopper_new(&sdp); bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper); - detect_setup_recording(call, &flags.record_call_str, &flags.metadata); + update_metadata_monologue(dialogue[0], &flags.metadata); + detect_setup_recording(call, &flags.record_call_str); if (flags.record_call) { call->recording_on = 1; - recording_start(call, NULL, &flags.metadata, NULL); + recording_start(call, NULL, NULL); } if (flags.drop_traffic_start) { @@ -2242,7 +2243,7 @@ const char *call_list_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_start_recording_ng(bencode_item_t *input, bencode_item_t *output) { - str callid; + str callid, fromtag; struct call *call; str metadata; str output_dest; @@ -2255,8 +2256,23 @@ const char *call_start_recording_ng(bencode_item_t *input, bencode_item_t *outpu if (!call) return "Unknown call-id"; + struct call_monologue *ml = NULL; + + if (bencode_dictionary_get_str(input, "from-tag", &fromtag)) { + if (fromtag.s) { + ml = call_get_monologue(call, &fromtag); + if (!ml) + ilog(LOG_WARN, "Given from-tag " STR_FORMAT_M " not found", STR_FMT_M(&fromtag)); + } + } + + if (ml) + update_metadata_monologue(ml, &metadata); + else + update_metadata_call(call, &metadata); + call->recording_on = 1; - recording_start(call, NULL, &metadata, &output_dest); + recording_start(call, NULL, &output_dest); rwlock_unlock_w(&call->master_lock); obj_put(call); @@ -2265,7 +2281,7 @@ const char *call_start_recording_ng(bencode_item_t *input, bencode_item_t *outpu } const char *call_stop_recording_ng(bencode_item_t *input, bencode_item_t *output) { - str callid; + str callid, fromtag; struct call *call; str metadata; @@ -2276,8 +2292,23 @@ const char *call_stop_recording_ng(bencode_item_t *input, bencode_item_t *output if (!call) return "Unknown call-id"; + struct call_monologue *ml = NULL; + + if (bencode_dictionary_get_str(input, "from-tag", &fromtag)) { + if (fromtag.s) { + ml = call_get_monologue(call, &fromtag); + if (!ml) + ilog(LOG_WARN, "Given from-tag " STR_FORMAT_M " not found", STR_FMT_M(&fromtag)); + } + } + + if (ml) + update_metadata_monologue(ml, &metadata); + else + update_metadata_call(call, &metadata); + call->recording_on = 0; - recording_stop(call, &metadata); + recording_stop(call); rwlock_unlock_w(&call->master_lock); obj_put(call); @@ -2434,7 +2465,12 @@ const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *outp call->rec_forwarding = 1; } - recording_start(call, NULL, &flags.metadata, NULL); + if (monologue) + update_metadata_monologue(monologue, &flags.metadata); + else + update_metadata_call(call, &flags.metadata); + + recording_start(call, NULL, NULL); return NULL; } @@ -2464,7 +2500,12 @@ const char *call_stop_forwarding_ng(bencode_item_t *input, bencode_item_t *outpu } } - recording_stop(call, NULL); + if (monologue) + update_metadata_monologue(monologue, &flags.metadata); + else + update_metadata_call(call, &flags.metadata); + + recording_stop(call); return NULL; } diff --git a/daemon/recording.c b/daemon/recording.c index 1ad636b02..437d860e8 100644 --- a/daemon/recording.c +++ b/daemon/recording.c @@ -235,8 +235,8 @@ static int rec_pcap_create_spool_dir(const char *spoolpath) { } // lock must be held -static void update_metadata(struct call *call, str *metadata) { - if (!metadata || !metadata->s) +void update_metadata_call(struct call *call, str *metadata) { + if (!metadata || !metadata->s || !call) return; if (str_cmp_str(metadata, &call->metadata)) { @@ -246,6 +246,22 @@ static void update_metadata(struct call *call, str *metadata) { } } +// lock must be held +void update_metadata_monologue(struct call_monologue *ml, str *metadata) { + if (!metadata || !metadata->s || !ml) + return; + + struct call *call = ml->call; + + if (str_cmp_str(metadata, &ml->metadata)) { + call_str_cpy(call, &ml->metadata, metadata); + if (call->recording) + append_meta_chunk_str(call->recording, metadata, "METADATA-TAG %u", ml->unique_id); + } + + update_metadata_call(call, metadata); +} + static void update_output_dest(struct call *call, str *output_dest) { if (!output_dest || !output_dest->s || !call->recording) return; @@ -267,9 +283,7 @@ static void recording_update_flags(struct call *call) { } // lock must be held -void recording_start(struct call *call, const char *prefix, str *metadata, str *output_dest) { - update_metadata(call, metadata); - +void recording_start(struct call *call, const char *prefix, str *output_dest) { update_output_dest(call, output_dest); if (call->recording) { @@ -321,13 +335,10 @@ void recording_start(struct call *call, const char *prefix, str *metadata, str * recording_update_flags(call); } -void recording_stop(struct call *call, str *metadata) { +void recording_stop(struct call *call) { if (!call->recording) return; - if (metadata) - update_metadata(call, metadata); - // check if all recording options are disabled if (call->recording_on || call->rec_forwarding) { recording_update_flags(call); @@ -356,19 +367,17 @@ void recording_stop(struct call *call, str *metadata) { * * Returns a boolean for whether or not the call is being recorded. */ -void detect_setup_recording(struct call *call, const str *recordcall, str *metadata) { - update_metadata(call, metadata); - +void detect_setup_recording(struct call *call, const str *recordcall) { if (!recordcall || !recordcall->s) return; if (!str_cmp(recordcall, "yes") || !str_cmp(recordcall, "on")) { call->recording_on = 1; - recording_start(call, NULL, NULL, NULL); + recording_start(call, NULL, NULL); } else if (!str_cmp(recordcall, "no") || !str_cmp(recordcall, "off")) { call->recording_on = 0; - recording_stop(call, NULL); + recording_stop(call); } else ilog(LOG_INFO, "\"record-call\" flag "STR_FORMAT" is invalid flag.", STR_FMT(recordcall)); @@ -825,6 +834,8 @@ static void setup_monologue_proc(struct call_monologue *ml) { append_meta_chunk_str(recording, &ml->tag, "TAG %u", ml->unique_id); if (ml->label.len) append_meta_chunk_str(recording, &ml->label, "LABEL %u", ml->unique_id); + if (ml->metadata.len) + append_meta_chunk_str(recording, &ml->metadata, "METADATA-TAG %u", ml->unique_id); } static void setup_media_proc(struct call_media *media) { diff --git a/daemon/redis.c b/daemon/redis.c index 3df6cd209..ab262bd50 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1426,6 +1426,8 @@ static int redis_tags(struct call *c, struct redis_list *tags, JsonReader *root_ __monologue_viabranch(ml, &s); if (!redis_hash_get_str(&s, rh, "label")) call_str_cpy(c, &ml->label, &s); + if (!redis_hash_get_str(&s, rh, "metadata")) + update_metadata_monologue(ml, &s); redis_hash_get_time_t(&ml->deleted, rh, "deleted"); if (!redis_hash_get_int(&ii, rh, "block_dtmf")) ml->block_dtmf = ii; @@ -2005,7 +2007,8 @@ static void json_restore_call(struct redis *r, const str *callid, bool foreign) if (!redis_hash_get_str(&s, &call, "recording_meta_prefix")) { // coverity[check_return : FALSE] redis_hash_get_str(&meta, &call, "recording_metadata"); - recording_start(c, s.s, &meta, NULL); + update_metadata_call(c, &meta); + recording_start(c, s.s, NULL); } err = NULL; @@ -2413,6 +2416,8 @@ char* redis_encode_json(struct call *c) { JSON_SET_SIMPLE_STR("via-branch",&ml->viabranch); if (ml->label.s) JSON_SET_SIMPLE_STR("label",&ml->label); + if (ml->metadata.s) + JSON_SET_SIMPLE_STR("metadata", &ml->metadata); } json_builder_end_object (builder); diff --git a/include/call.h b/include/call.h index a2d22c679..d77dfc7f5 100644 --- a/include/call.h +++ b/include/call.h @@ -469,6 +469,7 @@ struct call_monologue { char *sdp_username; char *sdp_session_name; struct ssrc_hash *ssrc_hash; + str metadata; // DTMF blocking/replacement stuff: enum block_dtmf_mode block_dtmf; diff --git a/include/recording.h b/include/recording.h index 012ff47f3..a900dbfe1 100644 --- a/include/recording.h +++ b/include/recording.h @@ -116,10 +116,12 @@ void recording_fs_free(void); * * Returns a boolean for whether or not the call is being recorded. */ -void detect_setup_recording(struct call *call, const str *recordcall, str *metadata); +void detect_setup_recording(struct call *call, const str *recordcall); +void update_metadata_call(struct call *call, str *metadata); +void update_metadata_monologue(struct call_monologue *ml, str *metadata); -void recording_start(struct call *call, const char *prefix, str *metadata, str *output_dest); -void recording_stop(struct call *call, str *metadata); +void recording_start(struct call *call, const char *prefix, str *output_dest); +void recording_stop(struct call *call); /** diff --git a/recording-daemon/decoder.c b/recording-daemon/decoder.c index 1342c0777..3c04c0e38 100644 --- a/recording-daemon/decoder.c +++ b/recording-daemon/decoder.c @@ -18,6 +18,7 @@ #include "streambuf.h" #include "main.h" #include "packet.h" +#include "tag.h" int resample_audio; @@ -148,8 +149,17 @@ no_recording: ssrc_tls_state(ssrc); if (!ssrc->sent_intro) { - if (metafile->metadata) { - dbg("Writing metadata header to TLS"); + tag_t *tag = NULL; + + if (ssrc->stream) + tag = tag_get(metafile, ssrc->stream->tag); + + if (tag && tag->metadata) { + dbg("Writing tag metadata header to TLS"); + streambuf_write(ssrc->tls_fwd_stream, tag->metadata, strlen(tag->metadata) + 1); + } + else if (metafile->metadata) { + dbg("Writing call metadata header to TLS"); streambuf_write(ssrc->tls_fwd_stream, metafile->metadata, strlen(metafile->metadata) + 1); } else { diff --git a/recording-daemon/metafile.c b/recording-daemon/metafile.c index 1c32358f1..da5012dc3 100644 --- a/recording-daemon/metafile.c +++ b/recording-daemon/metafile.c @@ -184,6 +184,8 @@ static void meta_section(metafile_t *mf, char *section, char *content, unsigned meta_ptime(mf, lu, i); else if (sscanf_match(section, "TAG %lu", &lu) == 1) tag_name(mf, lu, content); + else if (sscanf_match(section, "METADATA-TAG %lu", &lu) == 1) + tag_metadata(mf, lu, content); else if (sscanf_match(section, "LABEL %lu", &lu) == 1) tag_label(mf, lu, content); else if (sscanf_match(section, "RECORDING %u", &u) == 1) diff --git a/recording-daemon/tag.c b/recording-daemon/tag.c index c7664d97c..23f0327e3 100644 --- a/recording-daemon/tag.c +++ b/recording-daemon/tag.c @@ -28,6 +28,11 @@ void tag_label(metafile_t *mf, unsigned long t, const char *str) { tag->label = g_string_chunk_insert(mf->gsc, str); } +void tag_metadata(metafile_t *mf, unsigned long t, const char *str) { + tag_t *tag = tag_get(mf, t); + tag->metadata = g_string_chunk_insert(mf->gsc, str); +} + void tag_free(tag_t *tag) { g_slice_free1(sizeof(*tag), tag); } diff --git a/recording-daemon/tag.h b/recording-daemon/tag.h index ffec554cf..1398d5a08 100644 --- a/recording-daemon/tag.h +++ b/recording-daemon/tag.h @@ -6,6 +6,7 @@ tag_t *tag_get(metafile_t *mf, unsigned long id); void tag_name(metafile_t *mf, unsigned long t, const char *); void tag_label(metafile_t *mf, unsigned long t, const char *); +void tag_metadata(metafile_t *mf, unsigned long t, const char *); void tag_free(tag_t *); #endif diff --git a/recording-daemon/types.h b/recording-daemon/types.h index 6acbb5d37..5b478dc23 100644 --- a/recording-daemon/types.h +++ b/recording-daemon/types.h @@ -100,6 +100,7 @@ struct tag_s { unsigned long id; char *name; char *label; + char *metadata; }; typedef struct tag_s tag_t;