diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 25967bcb8..f3554763d 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -668,20 +668,25 @@ static void on_expire(SalOp *op){ static void on_notify_response(SalOp *op){ LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); + if (!lev) + return; - if (lev==NULL) return; - /*this is actually handling out of dialogs notify - for the moment*/ - if (!lev->is_out_of_dialog_op) return; - switch (linphone_event_get_subscription_state(lev)){ - case LinphoneSubscriptionIncomingReceived: - if (op->get_error_info()->reason == SalReasonNone){ - linphone_event_set_state(lev, LinphoneSubscriptionTerminated); - }else{ - linphone_event_set_state(lev, LinphoneSubscriptionError); - } - break; - default: - ms_warning("Unhandled on_notify_response() case %s", linphone_subscription_state_to_string(linphone_event_get_subscription_state(lev))); + if (lev->is_out_of_dialog_op) { + switch (linphone_event_get_subscription_state(lev)) { + case LinphoneSubscriptionIncomingReceived: + if (op->get_error_info()->reason == SalReasonNone) + linphone_event_set_state(lev, LinphoneSubscriptionTerminated); + else + linphone_event_set_state(lev, LinphoneSubscriptionError); + break; + default: + ms_warning("Unhandled on_notify_response() case %s", + linphone_subscription_state_to_string(linphone_event_get_subscription_state(lev))); + break; + } + } else { + ms_warning("on_notify_response in dialog"); + _linphone_event_notify_notify_response(lev); } } diff --git a/coreapi/event.c b/coreapi/event.c index 950c4ca2c..582774843 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -76,6 +76,46 @@ LINPHONE_PUBLIC const char *linphone_publish_state_to_string(LinphonePublishStat return NULL; } + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneEventCbs); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneEventCbs, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +static LinphoneEventCbs *linphone_event_cbs_new(void) { + return belle_sip_object_new(LinphoneEventCbs); +} + +LinphoneEventCbs *linphone_event_cbs_ref(LinphoneEventCbs *cbs) { + belle_sip_object_ref(cbs); + return cbs; +} + +void linphone_event_cbs_unref(LinphoneEventCbs *cbs) { + belle_sip_object_unref(cbs); +} + +void *linphone_event_cbs_get_user_data(const LinphoneEventCbs *cbs) { + return cbs->user_data; +} + +void linphone_event_cbs_set_user_data(LinphoneEventCbs *cbs, void *ud) { + cbs->user_data = ud; +} + +LinphoneEventCbsNotifyResponseCb linphone_event_cbs_get_notify_response(const LinphoneEventCbs *cbs) { + return cbs->notify_response_cb; +} + +void linphone_event_cbs_set_notify_response(LinphoneEventCbs *cbs, LinphoneEventCbsNotifyResponseCb cb) { + cbs->notify_response_cb = cb; +} + + static void linphone_event_release(LinphoneEvent *lev){ if (lev->op) { /*this will stop the refresher*/ @@ -86,6 +126,7 @@ static void linphone_event_release(LinphoneEvent *lev){ static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, LinphonePrivate::SalEventOp *op){ LinphoneEvent *lev=belle_sip_object_new(LinphoneEvent); + lev->callbacks = linphone_event_cbs_new(); lev->lc=lc; lev->dir=dir; lev->op=op; @@ -446,6 +487,7 @@ static void linphone_event_destroy(LinphoneEvent *lev){ if (lev->to_address) linphone_address_unref(lev->to_address); if (lev->from_address) linphone_address_unref(lev->from_address); if (lev->remote_contact_address) linphone_address_unref(lev->remote_contact_address); + linphone_event_cbs_unref(lev->callbacks); ms_free(lev->name); } @@ -523,6 +565,16 @@ static belle_sip_error_code _linphone_event_marshall(belle_sip_object_t *obj, ch return err; } +void _linphone_event_notify_notify_response(const LinphoneEvent *lev) { + LinphoneEventCbsNotifyResponseCb cb = linphone_event_cbs_get_notify_response(lev->callbacks); + if (cb) + cb(lev); +} + +LinphoneEventCbs *linphone_event_get_callbacks(const LinphoneEvent *ev) { + return ev->callbacks; +} + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneEvent); BELLE_SIP_INSTANCIATE_VPTR(LinphoneEvent, belle_sip_object_t, diff --git a/coreapi/private_functions.h b/coreapi/private_functions.h index 4bd4d5fd8..e0e48308f 100644 --- a/coreapi/private_functions.h +++ b/coreapi/private_functions.h @@ -380,6 +380,7 @@ void linphone_event_set_internal(LinphoneEvent *lev, bool_t internal); bool_t linphone_event_is_internal(LinphoneEvent *lev); void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state); +void _linphone_event_notify_notify_response(const LinphoneEvent *lev); LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); LinphoneContent *linphone_content_from_sal_body_handler(SalBodyHandler *ref); void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h index 449609ba9..073598723 100644 --- a/coreapi/private_structs.h +++ b/coreapi/private_structs.h @@ -378,6 +378,14 @@ struct _LCCallbackObj { void *_user_data; }; +struct _LinphoneEventCbs { + belle_sip_object_t base; + void *user_data; + LinphoneEventCbsNotifyResponseCb notify_response_cb; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneEventCbs); + struct _LinphoneEvent{ belle_sip_object_t base; LinphoneErrorInfo *ei; @@ -389,6 +397,7 @@ struct _LinphoneEvent{ LinphonePublishState publish_state; void *userdata; char *name; + LinphoneEventCbs *callbacks; int expires; bool_t terminating; bool_t is_out_of_dialog_op; /*used for out of dialog notify*/ diff --git a/include/linphone/callbacks.h b/include/linphone/callbacks.h index 714dac323..7511a1d97 100644 --- a/include/linphone/callbacks.h +++ b/include/linphone/callbacks.h @@ -448,6 +448,21 @@ typedef LinphoneCoreCbsPublishStateChangedCb LinphoneCorePublishStateChangedCb; * @} **/ +/** + * @addtogroup event_api + * @{ + */ + +/** + * Callback used to notify the response to a sent NOTIFY + * @param ev The LinphoneEvent object that has sent the NOTIFY and for which we received a response +**/ +typedef void (*LinphoneEventCbsNotifyResponseCb)(const LinphoneEvent *ev); + +/** + * @} + */ + /** * @addtogroup buddy_list * @{ diff --git a/include/linphone/event.h b/include/linphone/event.h index c49ab0167..cdb63a6d7 100644 --- a/include/linphone/event.h +++ b/include/linphone/event.h @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef LINPHONE_EVENT_H_ #define LINPHONE_EVENT_H_ +#include "linphone/callbacks.h" #include "linphone/types.h" #ifdef __cplusplus @@ -203,6 +204,55 @@ LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_remote_contact (const **/ LINPHONE_PUBLIC LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev); +/** + * Get the LinphoneEventCbs object associated with a LinphoneEvent. + * @param[in] ev LinphoneEvent object + * @return The LinphoneEventCbs object associated with the LinphoneEvent. +**/ + +LINPHONE_PUBLIC LinphoneEventCbs *linphone_event_get_callbacks(const LinphoneEvent *ev); + +/** + * Acquire a reference to a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. + * @return The same LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC LinphoneEventCbs *linphone_event_cbs_ref(LinphoneEventCbs *cbs); + +/** + * Release a reference to a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC void linphone_event_cbs_unref(LinphoneEventCbs *cbs); + +/** + * Retrieve the user pointer associated with a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. + * @return The user pointer associated with the LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC void *linphone_event_cbs_get_user_data(const LinphoneEventCbs *cbs); + +/** + * Assign a user pointer to a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. + * @param[in] ud The user pointer to associate with the LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC void linphone_event_cbs_set_user_data(LinphoneEventCbs *cbs, void *ud); + +/** + * Get the notify response callback. + * @param[in] cbs LinphoneEventCbs object. + * @return The current notify response callback. +**/ +LINPHONE_PUBLIC LinphoneEventCbsNotifyResponseCb linphone_event_cbs_get_notify_response(const LinphoneEventCbs *cbs); + +/** + * Set the notify response callback. + * @param[in] cbs LinphoneEventCbs object. + * @param[in] cb The notify response callback to be used. +**/ +LINPHONE_PUBLIC void linphone_event_cbs_set_notify_response(LinphoneEventCbs *cbs, LinphoneEventCbsNotifyResponseCb cb); + /** * @} **/ diff --git a/include/linphone/types.h b/include/linphone/types.h index d3b03ce25..9a8ba46c9 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -420,6 +420,12 @@ typedef struct _LinphoneErrorInfo LinphoneErrorInfo; **/ typedef struct _LinphoneEvent LinphoneEvent; +/** + * An object to handle the callbacks for handling the LinphoneEvent operations. + * @ingroup event_api +**/ +typedef struct _LinphoneEventCbs LinphoneEventCbs; + /** * #LinphoneFactory is a singleton object devoted to the creation of all the object * of Liblinphone that cannot created by #LinphoneCore or #LinphoneCore itself. diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index 2e1260e5e..a1c2fd2df 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -87,6 +87,7 @@ BELLE_SIP_TYPE_ID(LinphoneContent), BELLE_SIP_TYPE_ID(LinphoneCoreCbs), BELLE_SIP_TYPE_ID(LinphoneErrorInfo), BELLE_SIP_TYPE_ID(LinphoneEvent), +BELLE_SIP_TYPE_ID(LinphoneEventCbs), BELLE_SIP_TYPE_ID(LinphoneFactory), BELLE_SIP_TYPE_ID(LinphoneFriend), BELLE_SIP_TYPE_ID(LinphoneFriendList), diff --git a/src/sal/event-op.cpp b/src/sal/event-op.cpp index 8e99fcd9e..89cbdb5e7 100644 --- a/src/sal/event-op.cpp +++ b/src/sal/event-op.cpp @@ -31,13 +31,10 @@ void SalSubscribeOp::subscribe_process_io_error_cb(void *user_ctx, const belle_s belle_sip_request_t* req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); const char *method=belle_sip_request_get_method(req); - if (!op->dialog) { - /*this is handling outgoing out-of-dialog notifies*/ - if (strcmp(method,"NOTIFY")==0){ - SalErrorInfo *ei=&op->error_info; - sal_error_info_set(ei,SalReasonIOError, "SIP", 0,NULL,NULL); - op->root->callbacks.on_notify_response(op); - } + if (strcmp(method,"NOTIFY")==0){ + SalErrorInfo *ei=&op->error_info; + sal_error_info_set(ei,SalReasonIOError, "SIP", 0,NULL,NULL); + op->root->callbacks.on_notify_response(op); } } } @@ -52,11 +49,9 @@ void SalSubscribeOp::subscribe_response_event_cb(void *op_base, const belle_sip_ req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); method = belle_sip_request_get_method(req); - if (!op->dialog) { - if (strcmp(method,"NOTIFY")==0){ - op->set_error_info_from_response(belle_sip_response_event_get_response(event)); - op->root->callbacks.on_notify_response(op); - } + if (strcmp(method,"NOTIFY")==0){ + op->set_error_info_from_response(belle_sip_response_event_get_response(event)); + op->root->callbacks.on_notify_response(op); } } @@ -70,13 +65,10 @@ void SalSubscribeOp::subscribe_process_timeout_cb(void *user_ctx, const belle_si req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); method = belle_sip_request_get_method(req); - if (!op->dialog) { - /*this is handling outgoing out-of-dialog notifies*/ - if (strcmp(method,"NOTIFY")==0){ - SalErrorInfo *ei=&op->error_info; - sal_error_info_set(ei,SalReasonRequestTimeout, "SIP", 0,NULL,NULL); - op->root->callbacks.on_notify_response(op); - } + if (strcmp(method,"NOTIFY")==0){ + SalErrorInfo *ei=&op->error_info; + sal_error_info_set(ei,SalReasonRequestTimeout, "SIP", 0,NULL,NULL); + op->root->callbacks.on_notify_response(op); } }