diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index deeb9d0e0..e94aa39fb 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -301,6 +301,12 @@ static void streams_parse(const char *s, GQueue *q) { i = 0; pcre_multi_match(streams_re, streams_ree, s, 3, streams_parse_func, &i, q); } +static void call_unlock_release(struct call **c) { + if (!*c) + return; + rwlock_unlock_w(&(*c)->master_lock); + obj_put(*c); +} @@ -381,7 +387,7 @@ str *call_delete_udp(char **out) { return str_sprintf("%s 0\n", out[RE_UDP_COOKIE]); } str *call_query_udp(char **out) { - struct call *c; + AUTO_CLEANUP_NULL(struct call *c, call_unlock_release); str *ret, callid, fromtag, totag; struct call_stats stats; @@ -410,14 +416,8 @@ str *call_query_udp(char **out) { goto out; err: - if (c) - rwlock_unlock_w(&c->master_lock); ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); - goto out; - out: - if (c) - obj_put(c); return ret; } @@ -2017,14 +2017,14 @@ found: // XXX these are all identical - unify and use a flags int and/or callback const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *output) { - struct call *call; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); struct call_monologue *monologue; const char *errstr = NULL; struct sdp_ng_flags flags; errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER); if (errstr) - goto out; + return errstr; if (monologue) { ilog(LOG_INFO, "Start forwarding for single party (tag '" STR_FORMAT_M "')", @@ -2037,25 +2037,18 @@ const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *outp } recording_start(call, NULL, &flags.metadata, NULL); - errstr = NULL; -out: - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - - return errstr; + return NULL; } const char *call_stop_forwarding_ng(bencode_item_t *input, bencode_item_t *output) { - struct call *call; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); struct call_monologue *monologue; const char *errstr = NULL; struct sdp_ng_flags flags; errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER); if (errstr) - goto out; + return errstr; if (monologue) { ilog(LOG_INFO, "Stop forwarding for single party (tag '" STR_FORMAT_M "')", @@ -2075,25 +2068,18 @@ const char *call_stop_forwarding_ng(bencode_item_t *input, bencode_item_t *outpu recording_stop(call, NULL); - errstr = NULL; -out: - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - return NULL; } const char *call_block_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { - struct call *call; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); struct call_monologue *monologue; const char *errstr = NULL; struct sdp_ng_flags flags; errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER); if (errstr) - goto out; + return errstr; if (monologue) { ilog(LOG_INFO, "Blocking directional DTMF (tag '" STR_FORMAT_M "')", @@ -2105,25 +2091,18 @@ const char *call_block_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { call->block_dtmf = 1; } - errstr = NULL; -out: - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - - return errstr; + return NULL; } const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { - struct call *call; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); struct call_monologue *monologue; const char *errstr = NULL; struct sdp_ng_flags flags; errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER); if (errstr) - goto out; + return errstr; if (monologue) { ilog(LOG_INFO, "Unblocking directional DTMF (tag '" STR_FORMAT_M "')", @@ -2141,25 +2120,18 @@ const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output) } } - errstr = NULL; -out: - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - return NULL; } const char *call_block_media_ng(bencode_item_t *input, bencode_item_t *output) { - struct call *call; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); struct call_monologue *monologue; const char *errstr = NULL; struct sdp_ng_flags flags; errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER); if (errstr) - goto out; + return errstr; if (monologue) { ilog(LOG_INFO, "Blocking directional media (tag '" STR_FORMAT_M "')", @@ -2173,25 +2145,18 @@ const char *call_block_media_ng(bencode_item_t *input, bencode_item_t *output) { __call_unkernelize(call); } - errstr = NULL; -out: - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - - return errstr; + return NULL; } const char *call_unblock_media_ng(bencode_item_t *input, bencode_item_t *output) { - struct call *call; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); struct call_monologue *monologue; const char *errstr = NULL; struct sdp_ng_flags flags; errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER); if (errstr) - goto out; + return errstr; if (monologue) { ilog(LOG_INFO, "Unblocking directional media (tag '" STR_FORMAT_M "')", @@ -2211,13 +2176,6 @@ const char *call_unblock_media_ng(bencode_item_t *input, bencode_item_t *output) __call_unkernelize(call); } - errstr = NULL; -out: - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - return NULL; } @@ -2248,15 +2206,15 @@ static const char *play_media_select_party(struct call **call, GQueue *monologue const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) { #ifdef WITH_TRANSCODING str str; - struct call *call; - GQueue monologues; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); + AUTO_CLEANUP(GQueue monologues, g_queue_clear); const char *err = NULL; long long db_id; long long repeat_times = 1; err = play_media_select_party(&call, &monologues, input); if (err) - goto out; + return err; for (GList *l = monologues.head; l; l = l->next) { struct call_monologue *monologue = l->data; @@ -2264,38 +2222,26 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) { if (!monologue->player) monologue->player = media_player_new(monologue); repeat_times = bencode_dictionary_get_int_str(input, "repeat-times", 1); - err = "No media file specified"; if (bencode_dictionary_get_str(input, "file", &str)) { - err = "Failed to start media playback from file"; if (media_player_play_file(monologue->player, &str,repeat_times)) - goto out; + return "Failed to start media playback from file"; } else if (bencode_dictionary_get_str(input, "blob", &str)) { - err = "Failed to start media playback from blob"; if (media_player_play_blob(monologue->player, &str,repeat_times)) - goto out; + return "Failed to start media playback from blob"; } else if ((db_id = bencode_dictionary_get_int_str(input, "db-id", 0)) > 0) { - err = "Failed to start media playback from database"; if (media_player_play_db(monologue->player, db_id,repeat_times)) - goto out; + return "Failed to start media playback from database"; } else - goto out; + return "No media file specified"; if (l == monologues.head && monologue->player->duration) bencode_dictionary_add_integer(output, "duration", monologue->player->duration); } - err = NULL; - -out: - g_queue_clear(&monologues); - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - return err; + return NULL; #else return "unsupported"; #endif @@ -2304,33 +2250,24 @@ out: const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) { #ifdef WITH_TRANSCODING - struct call *call; - GQueue monologues; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); + AUTO_CLEANUP(GQueue monologues, g_queue_clear); const char *err = NULL; err = play_media_select_party(&call, &monologues, input); if (err) - goto out; + return err; for (GList *l = monologues.head; l; l = l->next) { struct call_monologue *monologue = l->data; - err = "Not currently playing media"; if (!monologue->player) - goto out; + return "Not currently playing media"; media_player_stop(monologue->player); } - err = NULL; - -out: - g_queue_clear(&monologues); - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - return err; + return NULL; #else return "unsupported"; #endif @@ -2339,14 +2276,14 @@ out: const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { #ifdef WITH_TRANSCODING - struct call *call; - GQueue monologues; + AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); + AUTO_CLEANUP(GQueue monologues, g_queue_clear); str str; const char *err = NULL; err = play_media_select_party(&call, &monologues, input); if (err) - goto out; + return err; // validate input parameters @@ -2371,24 +2308,20 @@ const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { } long long code = bencode_dictionary_get_int_str(input, "code", -1); - err = "Out of range 'code' specified"; if (code == -1) { // try a string code - err = "No valid 'code' specified"; if (!bencode_dictionary_get_str(input, "code", &str)) - goto out; - err = "Given 'code' is not a single digit"; + return "No valid 'code' specified"; if (str.len != 1) - goto out; + return "Given 'code' is not a single digit"; code = dtmf_code_from_char(str.s[0]); - err = "Invalid 'code' character"; if (code == -1) - goto out; + return "Invalid 'code' character"; } else if (code < 0) - goto out; + return "Out of range 'code' specified"; else if (code > 15) - goto out; + return "Out of range 'code' specified"; long long volume = bencode_dictionary_get_int_str(input, "volume", 8); if (volume > 0) @@ -2408,9 +2341,8 @@ const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { goto found; } - err = "Monologue has no media capable of DTMF injection"; + return "Monologue has no media capable of DTMF injection"; // XXX fall back to generating a secondary stream - goto out; found: for (GList *k = monologue->subscribers.head; k; k = k->next) { @@ -2424,23 +2356,16 @@ found: goto found_sink; } - err = "Sink monologue has no media capable of DTMF playback"; - goto out; + return "Sink monologue has no media capable of DTMF playback"; found_sink: err = dtmf_inject(media, code, volume, duration, pause, sink); if (err) - break; + return err; } } -out: - g_queue_clear(&monologues); - if (call) { - rwlock_unlock_w(&call->master_lock); - obj_put(call); - } - return err; + return NULL; #else return "unsupported"; #endif