diff --git a/src/mm-base-call.c b/src/mm-base-call.c index ab63a1d7a46aec343b1ff03016d9df021d05ef2d..dfbdb702191588815a2c0fed9ec83ace68de0a49 100644 --- a/src/mm-base-call.c +++ b/src/mm-base-call.c @@ -57,8 +57,37 @@ struct _MMBaseCallPrivate { /* Features */ gboolean supports_dialing_to_ringing; gboolean supports_ringing_to_active; + + guint incoming_timeout; }; +/*****************************************************************************/ +/* Incoming calls are reported via RING URCs. If the caller stops the call + * attempt before it has been answered, the only thing we would see is that the + * URCs are no longer received. So, we will start a timeout whenever a new RING + * URC is received, and we refresh the timeout any time a new URC arrives. If + * the timeout is expired (meaning no URCs were received in the last N seconds) + * then we assume the call attempt is finished and we transition to TERMINATED. + */ + +#define INCOMING_TIMEOUT_SECS 5 + +static gboolean +incoming_timeout_cb (MMBaseCall *self) +{ + self->priv->incoming_timeout = 0; + mm_base_call_change_state (self, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_TERMINATED); + return G_SOURCE_REMOVE; +} + +void +mm_base_call_incoming_refresh (MMBaseCall *self) +{ + if (self->priv->incoming_timeout) + g_source_remove (self->priv->incoming_timeout); + self->priv->incoming_timeout = g_timeout_add_seconds (INCOMING_TIMEOUT_SECS, (GSourceFunc)incoming_timeout_cb, self); +} + /*****************************************************************************/ /* Start call (DBus call handling) */ @@ -205,6 +234,10 @@ handle_accept_ready (MMBaseCall *self, mm_base_call_change_state (self, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_ERROR); g_dbus_method_invocation_take_error (ctx->invocation, error); } else { + if (ctx->self->priv->incoming_timeout) { + g_source_remove (ctx->self->priv->incoming_timeout); + ctx->self->priv->incoming_timeout = 0; + } mm_base_call_change_state (self, MM_CALL_STATE_ACTIVE, MM_CALL_STATE_REASON_ACCEPTED); mm_gdbus_call_complete_accept (MM_GDBUS_CALL (ctx->self), ctx->invocation); } @@ -305,8 +338,13 @@ handle_hangup_ready (MMBaseCall *self, if (!MM_BASE_CALL_GET_CLASS (self)->hangup_finish (self, res, &error)) g_dbus_method_invocation_take_error (ctx->invocation, error); - else + else { + if (ctx->self->priv->incoming_timeout) { + g_source_remove (ctx->self->priv->incoming_timeout); + ctx->self->priv->incoming_timeout = 0; + } mm_gdbus_call_complete_hangup (MM_GDBUS_CALL (ctx->self), ctx->invocation); + } handle_hangup_context_free (ctx); } @@ -963,6 +1001,11 @@ dispose (GObject *object) { MMBaseCall *self = MM_BASE_CALL (object); + if (self->priv->incoming_timeout) { + g_source_remove (self->priv->incoming_timeout); + self->priv->incoming_timeout = 0; + } + if (self->priv->connection) { /* If we arrived here with a valid connection, make sure we unexport * the object */ diff --git a/src/mm-base-call.h b/src/mm-base-call.h index da31a9b9d8b72d7b82d07923f2ab683b5840ac7d..5b8c06c670553c12baad11207a2a705992b76c88 100644 --- a/src/mm-base-call.h +++ b/src/mm-base-call.h @@ -97,13 +97,17 @@ MMBaseCall *mm_base_call_new_from_properties (MMBaseModem *modem, MMCallProperties *properties, GError **error); -void mm_base_call_export (MMBaseCall *self); -void mm_base_call_unexport (MMBaseCall *self); -const gchar *mm_base_call_get_path (MMBaseCall *self); -void mm_base_call_change_state (MMBaseCall *self, - MMCallState new_state, - MMCallStateReason reason); -void mm_base_call_received_dtmf (MMBaseCall *self, - const gchar *dtmf); +void mm_base_call_export (MMBaseCall *self); +void mm_base_call_unexport (MMBaseCall *self); +const gchar *mm_base_call_get_path (MMBaseCall *self); + +void mm_base_call_change_state (MMBaseCall *self, + MMCallState new_state, + MMCallStateReason reason); + +void mm_base_call_received_dtmf (MMBaseCall *self, + const gchar *dtmf); + +void mm_base_call_incoming_refresh (MMBaseCall *self); #endif /* MM_BASE_CALL_H */ diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 7b11cd437639af86a2f665c3cc757f8be322b2be..93a3a3e0732f24ca6fae1f321cb8529ee67a57df 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -6928,7 +6928,7 @@ ring_received (MMPortSerialAt *port, MMBroadbandModem *self) { mm_dbg ("Ringing"); - mm_iface_modem_voice_create_incoming_call (MM_IFACE_MODEM_VOICE (self)); + mm_iface_modem_voice_incoming_call (MM_IFACE_MODEM_VOICE (self)); } static void @@ -6945,7 +6945,7 @@ cring_received (MMPortSerialAt *port, mm_dbg ("Ringing (%s)", str); g_free (str); - mm_iface_modem_voice_create_incoming_call (MM_IFACE_MODEM_VOICE (self)); + mm_iface_modem_voice_incoming_call (MM_IFACE_MODEM_VOICE (self)); } static void diff --git a/src/mm-call-list.c b/src/mm-call-list.c index b1950e3ab57d37cb8e67af09c6dd8299c1a2b1e2..91ccc8d08a8992a2e940b22af08c970b3cd40ea6 100644 --- a/src/mm-call-list.c +++ b/src/mm-call-list.c @@ -84,36 +84,33 @@ mm_call_list_get_paths (MMCallList *self) /*****************************************************************************/ MMBaseCall * -mm_call_list_get_new_incoming (MMCallList *self) +mm_call_list_get_first_ringing_in_call (MMCallList *self) { - MMBaseCall *call = NULL; GList *l; for (l = self->priv->list; l; l = g_list_next (l)) { - + MMBaseCall *call; MMCallState state; - MMCallStateReason reason; - MMCallDirection direct; + MMCallDirection direction; - g_object_get (MM_BASE_CALL (l->data), - "state", &state, - "state-reason", &reason, - "direction", &direct, + call = MM_BASE_CALL (l->data); + + g_object_get (call, + "state", &state, + "direction", &direction, NULL); - if (direct == MM_CALL_DIRECTION_INCOMING && - state == MM_CALL_STATE_RINGING_IN && - reason == MM_CALL_STATE_REASON_INCOMING_NEW ) { - call = MM_BASE_CALL (l->data); - break; + if (direction == MM_CALL_DIRECTION_INCOMING && + state == MM_CALL_STATE_RINGING_IN) { + return call; } } - return call; + return NULL; } MMBaseCall * -mm_call_list_get_first_ringing_call (MMCallList *self) +mm_call_list_get_first_ringing_out_call (MMCallList *self) { MMBaseCall *call = NULL; GList *l; diff --git a/src/mm-call-list.h b/src/mm-call-list.h index 1c6685009b90d3ccfaf1b6fdfb9e99a1c6731e5b..53102d06107a4839a41b7d0cf575b2e225b3bc32 100644 --- a/src/mm-call-list.h +++ b/src/mm-call-list.h @@ -68,11 +68,11 @@ gboolean mm_call_list_delete_call (MMCallList *self, const gchar *call_path, GError **error); -MMBaseCall *mm_call_list_get_new_incoming (MMCallList *self); -MMBaseCall *mm_call_list_get_first_ringing_call (MMCallList *self); -MMBaseCall *mm_call_list_get_first_outgoing_dialing_call(MMCallList *self); -MMBaseCall *mm_call_list_get_first_non_terminated_call (MMCallList *self); -gboolean mm_call_list_send_dtmf_to_active_calls (MMCallList *self, - const gchar *dtmf); +MMBaseCall *mm_call_list_get_first_ringing_in_call (MMCallList *self); +MMBaseCall *mm_call_list_get_first_ringing_out_call (MMCallList *self); +MMBaseCall *mm_call_list_get_first_outgoing_dialing_call (MMCallList *self); +MMBaseCall *mm_call_list_get_first_non_terminated_call (MMCallList *self); +gboolean mm_call_list_send_dtmf_to_active_calls (MMCallList *self, + const gchar *dtmf); #endif /* MM_CALL_LIST_H */ diff --git a/src/mm-iface-modem-voice.c b/src/mm-iface-modem-voice.c index 844b83102e9a7a82a85efef5b43320d8df99742f..9cab1cdd276c8832bfdd5823ad0406bb3157ce95 100644 --- a/src/mm-iface-modem-voice.c +++ b/src/mm-iface-modem-voice.c @@ -46,8 +46,8 @@ mm_iface_modem_voice_create_call (MMIfaceModemVoice *self) return MM_IFACE_MODEM_VOICE_GET_INTERFACE (self)->create_call (self); } -MMBaseCall * -mm_iface_modem_voice_create_incoming_call (MMIfaceModemVoice *self) +void +mm_iface_modem_voice_incoming_call (MMIfaceModemVoice *self) { MMBaseCall *call = NULL; MMCallList *list = NULL; @@ -56,29 +56,36 @@ mm_iface_modem_voice_create_incoming_call (MMIfaceModemVoice *self) MM_IFACE_MODEM_VOICE_CALL_LIST, &list, NULL); - if (list) { - call = mm_call_list_get_new_incoming (list); - - if (!call) { - mm_dbg ("Creating new incoming call..."); - - call = mm_base_call_new (MM_BASE_MODEM (self)); - g_object_set (call, - "state", MM_CALL_STATE_RINGING_IN, - "state-reason", MM_CALL_STATE_REASON_INCOMING_NEW, - "direction", MM_CALL_DIRECTION_INCOMING, - NULL); - - /* Only export once properly created */ - mm_base_call_export (call); - mm_call_list_add_call (list, call); - g_object_unref (call); - } + if (!list) { + mm_warn ("Cannot create incoming call: missing call list"); + return; + } + + call = mm_call_list_get_first_ringing_in_call (list); + /* If call exists already, refresh its validity */ + if (call) { + mm_base_call_incoming_refresh (call); g_object_unref (list); + return; } - return call; + mm_dbg ("Creating new incoming call..."); + call = mm_base_call_new (MM_BASE_MODEM (self)); + g_object_set (call, + "state", MM_CALL_STATE_RINGING_IN, + "state-reason", MM_CALL_STATE_REASON_INCOMING_NEW, + "direction", MM_CALL_DIRECTION_INCOMING, + NULL); + + /* Start its validity timeout */ + mm_base_call_incoming_refresh (call); + + /* Only export once properly created */ + mm_base_call_export (call); + mm_call_list_add_call (list, call); + g_object_unref (call); + g_object_unref (list); } gboolean @@ -96,7 +103,7 @@ mm_iface_modem_voice_update_incoming_call_number (MMIfaceModemVoice *self, NULL); if (list) { - call = mm_call_list_get_new_incoming (list); + call = mm_call_list_get_first_ringing_in_call (list); if (call) { mm_gdbus_call_set_number (MM_GDBUS_CALL (call), number); @@ -153,7 +160,7 @@ mm_iface_modem_voice_call_ringing_to_active (MMIfaceModemVoice *self) NULL); if (list) { - call = mm_call_list_get_first_ringing_call (list); + call = mm_call_list_get_first_ringing_out_call (list); if (call) { mm_base_call_change_state (call, MM_CALL_STATE_ACTIVE, MM_CALL_STATE_REASON_ACCEPTED); diff --git a/src/mm-iface-modem-voice.h b/src/mm-iface-modem-voice.h index e182060a80bafab12741c789efd8b48bfec40722..229ebb5dad39eb5cfe115f6d061d871b64248d8b 100644 --- a/src/mm-iface-modem-voice.h +++ b/src/mm-iface-modem-voice.h @@ -118,7 +118,7 @@ void mm_iface_modem_voice_bind_simple_status (MMIfaceModemVoice *self, /* CALL creation */ MMBaseCall *mm_iface_modem_voice_create_call (MMIfaceModemVoice *self); -MMBaseCall *mm_iface_modem_voice_create_incoming_call (MMIfaceModemVoice *self); +void mm_iface_modem_voice_incoming_call (MMIfaceModemVoice *self); gboolean mm_iface_modem_voice_update_incoming_call_number (MMIfaceModemVoice *self, gchar *number, guint type,