diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 9e4cbf091..3e89c1b60 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "c-wrapper/internal/c-sal.h" #include "sal/call-op.h" #include "sal/message-op.h" +#include "sal/refer-op.h" #include "linphone/core.h" #include "private.h" @@ -385,7 +386,7 @@ static void dtmf_received(SalOp *op, char dtmf){ #endif } -static void refer_received(Sal *sal, SalOp *op, const char *referto){ +static void call_refer_received(SalOp *op, const SalAddress *referto){ #if 0 LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); @@ -713,6 +714,14 @@ static void on_notify_response(SalOp *op){ } } +static void refer_received(SalOp *op, const SalAddress *refer_to){ + /*if processing is ok*/ + dynamic_cast(op)->reply(SalReasonNone); + + /*otherwise*/ + //dynamic_cast(op)->reply(SalReasonDeclined); +} + Sal::Callbacks linphone_sal_callbacks={ call_received, call_rejected, @@ -725,12 +734,12 @@ Sal::Callbacks linphone_sal_callbacks={ call_failure, call_released, call_cancel_done, + call_refer_received, auth_failure, register_success, register_failure, vfu_request, dtmf_received, - refer_received, message_received, message_delivery_update, notify_refer, @@ -748,5 +757,6 @@ Sal::Callbacks linphone_sal_callbacks={ info_received, on_publish_response, on_expire, - on_notify_response + on_notify_response, + refer_received, }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 037092329..8928cc208 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -172,6 +172,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES sal/presence-op.cpp sal/register-op.cpp sal/sal.cpp + sal/refer-op.cpp utils/general.cpp utils/payload-type-handler.cpp utils/utils.cpp diff --git a/src/sal/call-op.cpp b/src/sal/call-op.cpp index 59c8a2e95..4929e6085 100644 --- a/src/sal/call-op.cpp +++ b/src/sal/call-op.cpp @@ -1438,7 +1438,6 @@ void SalCallOp::process_refer(const belle_sip_request_event_t *event, belle_sip_ belle_sip_header_referred_by_t *referred_by= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_referred_by_t); belle_sip_response_t* resp; belle_sip_uri_t* refer_to_uri; - char* refer_to_uri_str; ms_message("Receiving REFER request on op [%p]", this); if (refer_to) { @@ -1451,13 +1450,11 @@ void SalCallOp::process_refer(const belle_sip_request_event_t *event, belle_sip_ if (referred_by){ set_referred_by(referred_by); } - refer_to_uri_str=belle_sip_uri_to_string(refer_to_uri); resp = create_response_from_request(req,202); belle_sip_server_transaction_send_response(server_transaction,resp); - this->root->callbacks.refer_received(this->root,this,refer_to_uri_str); - belle_sip_free(refer_to_uri_str); + this->root->callbacks.call_refer_received(this,(SalAddress*)BELLE_SIP_HEADER_ADDRESS(refer_to)); } else { - ms_warning("cannot do anything with the refer without destination\n"); + ms_warning("cannot do anything with the refer without destination"); resp = create_response_from_request(req,400); belle_sip_server_transaction_send_response(server_transaction,resp); } diff --git a/src/sal/op.h b/src/sal/op.h index c183ade4c..06c009909 100644 --- a/src/sal/op.h +++ b/src/sal/op.h @@ -140,7 +140,8 @@ protected: Message, Presence, Publish, - Subscribe + Subscribe, + Refer /*for out of dialog refer only*/ }; static const char *to_string(const SalOp::Type type); diff --git a/src/sal/refer-op.cpp b/src/sal/refer-op.cpp new file mode 100644 index 000000000..6a28b197e --- /dev/null +++ b/src/sal/refer-op.cpp @@ -0,0 +1,104 @@ +/* + Linphone library + Copyright (C) 2017 Belledonne Communications SARL + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "sal/refer-op.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void SalReferOp::process_error() { + this->state=State::Terminated; +} + +void SalReferOp::process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalReferOp * op = (SalReferOp *)user_ctx; + sal_error_info_set(&op->error_info,SalReasonIOError, "SIP", 503,"IO Error",NULL); + op->process_error(); +} + +void SalReferOp::process_response_event_cb(void *op_base, const belle_sip_response_event_t *event) { + SalReferOp * op = (SalReferOp *)op_base; + op->set_error_info_from_response(belle_sip_response_event_get_response(event)); + /*the response is not notified to the app*/ + /*To be done when necessary*/ +} + +void SalReferOp::process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalReferOp * op=(SalReferOp *)user_ctx; + sal_error_info_set(&op->error_info,SalReasonRequestTimeout, "SIP", 408,"Request timeout",NULL); + op->process_error(); +} + +void SalReferOp::process_request_event_cb(void *op_base, const belle_sip_request_event_t *event) { + SalReferOp * op = (SalReferOp *)op_base; + belle_sip_request_t *req = belle_sip_request_event_get_request(event); + belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t); + belle_sip_server_transaction_t *server_transaction = belle_sip_provider_create_server_transaction(op->root->prov,belle_sip_request_event_get_request(event)); + + belle_sip_object_ref(server_transaction); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),op->ref()); + op->pending_server_trans = server_transaction; + + if (!refer_to){ + ms_warning("cannot do anything with the refer without destination"); + op->reply(SalReasonUnknown);/*is mapped on bad request*/ + return; + } + op->root->callbacks.refer_received(op, (SalAddress*)refer_to); + /*the app is expected to reply in the callback*/ +} + +void SalReferOp::fill_cbs() { + static belle_sip_listener_callbacks_t op_refer_callbacks = {0}; + if (op_refer_callbacks.process_io_error==NULL) { + op_refer_callbacks.process_io_error=process_io_error_cb; + op_refer_callbacks.process_response_event=process_response_event_cb; + op_refer_callbacks.process_timeout=process_timeout_cb; + op_refer_callbacks.process_request_event=process_request_event_cb; + } + this->callbacks=&op_refer_callbacks; + this->type=Type::Refer; +} + +SalReferOp::SalReferOp(Sal *sal) : SalOp(sal){ + fill_cbs(); +} + +int SalReferOp::send_refer(const SalAddress *refer_to) { + this->dir=Dir::Outgoing; + + belle_sip_request_t* req=build_request("REFER"); + if (req == NULL ) return -1; + if (get_contact_address()) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(create_contact())); + return send_request(req); +} + +int SalReferOp::reply(SalReason reason){ + if (this->pending_server_trans){ + int code=to_sip_code(reason); + belle_sip_response_t *resp = belle_sip_response_create_from_request( + belle_sip_transaction_get_request((belle_sip_transaction_t*)this->pending_server_trans),code); + belle_sip_server_transaction_send_response(this->pending_server_trans,resp); + return 0; + }else ms_error("SalReferOp::reply: no server transaction"); + return -1; +} + +LINPHONE_END_NAMESPACE diff --git a/src/sal/refer-op.h b/src/sal/refer-op.h new file mode 100644 index 000000000..a3197e7ca --- /dev/null +++ b/src/sal/refer-op.h @@ -0,0 +1,46 @@ +/* + Linphone library + Copyright (C) 2010-2017 Belledonne Communications SARL + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _SAL_REFER_OP_H_ +#define _SAL_REFER_OP_H_ + +#include "sal/op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalReferOp: public SalOp{ +public: + SalReferOp(Sal *sal); + + int send_refer(const SalAddress *refer_to); + int reply(SalReason reason); + +private: + virtual void fill_cbs() override; + void process_error(); + + static void process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event); + static void process_response_event_cb(void *op_base, const belle_sip_response_event_t *event); + static void process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event); + static void process_request_event_cb(void *op_base, const belle_sip_request_event_t *event); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _SAL_MESSAGE_OP_H_ diff --git a/src/sal/sal.cpp b/src/sal/sal.cpp index d29239442..2e2b8d86e 100644 --- a/src/sal/sal.cpp +++ b/src/sal/sal.cpp @@ -20,6 +20,7 @@ #include "sal/sal.h" #include "sal/call-op.h" #include "sal/presence-op.h" +#include "sal/refer-op.h" #include "sal/event-op.h" #include "sal/message-op.h" #include "bellesip_sal/sal_impl.h" @@ -104,7 +105,6 @@ void Sal::process_request_event_cb(void *ud, const belle_sip_request_event_t *ev if (strcmp("INVITE",method)==0) { op=new SalCallOp(sal); - op->dir=SalOp::Dir::Incoming; op->fill_cbs(); }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ @@ -112,11 +112,12 @@ void Sal::process_request_event_cb(void *ud, const belle_sip_request_event_t *ev } else { op=new SalSubscribeOp(sal); } - op->dir=SalOp::Dir::Incoming; op->fill_cbs(); }else if (strcmp("MESSAGE",method)==0) { op=new SalMessageOp(sal); - op->dir=SalOp::Dir::Incoming; + op->fill_cbs(); + }else if (strcmp("REFER",method)==0) { + op=new SalReferOp(sal); op->fill_cbs(); }else if (strcmp("OPTIONS",method)==0) { resp=belle_sip_response_create_from_request(req,200); @@ -147,6 +148,7 @@ void Sal::process_request_event_cb(void *ud, const belle_sip_request_event_t *ev belle_sip_provider_send_response(sal->prov,resp); return; } + op->dir=SalOp::Dir::Incoming; } if (!op->from_address) { diff --git a/src/sal/sal.h b/src/sal/sal.h index dda0b6e6d..eece42388 100644 --- a/src/sal/sal.h +++ b/src/sal/sal.h @@ -30,6 +30,7 @@ class SalCallOp; class SalMessageOp; class SalSubscribeOp; class SalPresenceOp; +class SalReferOp; class Sal{ public: @@ -50,7 +51,8 @@ public: typedef void (*OnRegisterFailureCb)(SalOp *op); typedef void (*OnVfuRequestCb)(SalOp *op); typedef void (*OnDtmfReceivedCb)(SalOp *op, char dtmf); - typedef void (*OnReferCb)(Sal *sal, SalOp *op, const char *referto); + typedef void (*OnCallReferCb)(SalOp *op, const SalAddress *referto); + typedef void (*OnReferCb)(SalOp *op, const SalAddress *referto); typedef void (*OnMessageReceivedCb)(SalOp *op, const SalMessage *msg); typedef void (*OnMessageDeliveryUpdateCb)(SalOp *op, SalMessageDeliveryStatus); typedef void (*OnNotifyReferCb)(SalOp *op, SalReferStatus state); @@ -81,12 +83,13 @@ public: OnCallFailureCb call_failure; OnCallReleasedCb call_released; OnCallCancelDoneCb call_cancel_done; + OnCallReferCb call_refer_received; OnAuthFailureCb auth_failure; OnRegisterSuccessCb register_success; OnRegisterFailureCb register_failure; OnVfuRequestCb vfu_request; OnDtmfReceivedCb dtmf_received; - OnReferCb refer_received; + OnMessageReceivedCb message_received; OnMessageDeliveryUpdateCb message_delivery_update; OnNotifyReferCb notify_refer; @@ -105,6 +108,7 @@ public: OnPublishResponseCb on_publish_response; OnExpireCb on_expire; OnNotifyResponseCb on_notify_response; + OnReferCb refer_received; /*for out of dialog refer*/ }; Sal(MSFactory *factory); @@ -309,6 +313,7 @@ private: friend class SalPresenceOp; friend class SalSubscribeOp; friend class SalPublishOp; + friend class SalReferOp; }; int to_sip_code(SalReason r);