linphone-ios/src/sal/refer-op.cpp
2018-03-09 10:20:20 +01:00

114 lines
4.5 KiB
C++

/*
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*/
op->unref();
return;
}
SalAddress *referToAddr = sal_address_new(belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(refer_to)));
op->root->callbacks.refer_received(op, referToAddr);
/*the app is expected to reply in the callback*/
sal_address_unref(referToAddr);
op->unref();
}
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()));
belle_sip_header_address_t *address = BELLE_SIP_HEADER_ADDRESS(refer_to);
belle_sip_uri_t *uri = belle_sip_header_address_get_uri(address);
if (!belle_sip_uri_get_host(uri))
belle_sip_header_address_set_automatic(address, true);
belle_sip_header_refer_to_t *refer_to_header = belle_sip_header_refer_to_create(address);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(refer_to_header));
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