diff --git a/coreapi/bellesip_sal/sal_op_info.c b/coreapi/bellesip_sal/sal_op_info.c new file mode 100644 index 000000000..41f39008d --- /dev/null +++ b/coreapi/bellesip_sal/sal_op_info.c @@ -0,0 +1,79 @@ +/* +linphone +Copyright (C) 2012 Belledonne Communications, Grenoble, France + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "sal_impl.h" + +static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ +} + +static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { +} + +static void process_response_event(void *op_base, const belle_sip_response_event_t *event){ +} + +static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { + SalOp* op = (SalOp*)op_base; + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); + belle_sip_header_content_type_t* content_type; + belle_sip_header_content_length_t *clen=NULL; + belle_sip_response_t* resp; + SalBody salbody; + const char *body; + + content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); + if (content_type){ + body=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); + clen=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_length_t); + } + + if (content_type && body && clen) { + salbody.type=belle_sip_header_content_type_get_type(content_type); + salbody.subtype=belle_sip_header_content_type_get_subtype(content_type); + salbody.data=body; + salbody.size=belle_sip_header_content_length_get_content_length(clen); + op->base.root->callbacks.info_received(op,&salbody); + } else { + op->base.root->callbacks.info_received(op,NULL); + } + resp = belle_sip_response_create_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + sal_op_release(op); +} + +int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){ + belle_sip_request_t *req=sal_op_build_request(op,"INFO"); + sal_op_info_fill_cbs(op); + if (body && body->type && body->subtype && body->data){ + belle_sip_message_add_header((belle_sip_message_t*)req, + (belle_sip_header_t*)belle_sip_header_content_type_create(body->type,body->subtype)); + belle_sip_message_add_header((belle_sip_message_t*)req, + (belle_sip_header_t*)belle_sip_header_content_length_create(body->size)); + belle_sip_message_set_body((belle_sip_message_t*)req,(const char*)body->data,body->size); + } + return sal_op_send_request(op,req); +} + +void sal_op_info_fill_cbs(SalOp*op) { + op->callbacks.process_io_error=process_io_error; + op->callbacks.process_response_event=process_response_event; + op->callbacks.process_timeout=process_timeout; + op->callbacks.process_request_event=process_request_event; + op->type=SalOpInfo; +} diff --git a/coreapi/info.c b/coreapi/info.c new file mode 100644 index 000000000..6ab5f5837 --- /dev/null +++ b/coreapi/info.c @@ -0,0 +1,184 @@ +/*************************************************************************** + * info.c + * + * Thu May 16 11:48:01 2013 + * Copyright 2013 Belledonne Communications SARL + * Author Simon Morlat + * Email simon dot morlat at linphone dot org + ****************************************************************************/ + +/* + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "linphonecore.h" +#include "private.h" +#include "lpconfig.h" + + +struct _LinphoneInfoMessage{ + LinphoneContent content; + SalOp *op; + SalCustomHeader *headers; +}; + +#define SET_STRING(ptr,field,val) \ + if (ptr->field) { \ + ms_free(ptr->field); \ + ptr->field=NULL; \ + } \ + if (val){ \ + ptr->field=ms_strdup(val); \ + } + +static void linphone_content_copy(LinphoneContent *obj, const LinphoneContent *ref){ + SET_STRING(obj,type,ref->type); + SET_STRING(obj,subtype,ref->subtype); + if (obj->data) { + ms_free(obj->data); + obj->data=NULL; + } + if (ref->data){ + obj->data=ms_malloc(ref->size+1); + memcpy(obj->data, ref->data, ref->size); + ((char*)obj->data)[ref->size]='\0'; + } + obj->size=ref->size; +} + +static void linphone_content_uninit(LinphoneContent * obj){ + if (obj->type) ms_free(obj->type); + if (obj->subtype) ms_free(obj->subtype); + if (obj->data) ms_free(obj->data); +} + +static LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref){ + SET_STRING(obj,type,ref->type); + SET_STRING(obj,subtype,ref->subtype); + if (obj->data) { + ms_free(obj->data); + obj->data=NULL; + } + if (ref->data){ + obj->data=ms_malloc(ref->size+1); + memcpy(obj->data, ref->data, ref->size); + ((char*)obj->data)[ref->size]='\0'; + } + obj->size=ref->size; + return obj; +} + +static SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc){ + if (lc->type){ + body->type=lc->type; + body->subtype=lc->subtype; + body->data=lc->data; + body->size=lc->size; + return body; + } + return NULL; +} + +/** + * Destroy a LinphoneInfoMessage +**/ +void linphone_info_message_destroy(LinphoneInfoMessage *im){ + /* FIXME: op is leaked. If we release it now, there is a high risk that the request won't be resent with authentication*/ + /*if (im->op) sal_op_release(im->op);*/ + linphone_content_uninit(&im->content); + sal_custom_header_free(im->headers); + ms_free(im); +} + +/** + * Creates an empty info message. + * @param lc the LinphoneCore object. + * @return a new LinphoneInfoMessage. + * + * The info message can later be filled with information using linphone_info_message_add_header() or linphone_info_message_set_content(), + * and finally sent with linphone_core_send_info_message(). +**/ +LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc){ + LinphoneInfoMessage *im=ms_new0(LinphoneInfoMessage,1); + im->op=sal_op_new(lc->sal); + return im; +} + +/** + * Send a LinphoneInfoMessage to a specified address. + * @param lc the LinphoneCore + * @param info the info message + * @param addr the destination address +**/ +int linphone_core_send_info_message(LinphoneCore *lc, const LinphoneInfoMessage *info, const LinphoneAddress *addr){ + SalBody body; + linphone_configure_op(lc,info->op,addr,info->headers,FALSE); + return sal_send_info(info->op,NULL, NULL, sal_body_from_content(&body,&info->content)); +} + +/** + * Add a header to an info message to be sent. + * @param im the info message + * @param name the header'name + * @param value the header's value +**/ +void linphone_info_message_add_header(LinphoneInfoMessage *im, const char *name, const char *value){ + im->headers=sal_custom_header_append(im->headers, name, value); +} + +/** + * Obtain a header value from a received info message. + * @param im the info message + * @param name the header'name + * @return the corresponding header's value, or NULL if not exists. +**/ +const char *linphone_info_message_get_header(const LinphoneInfoMessage *im, const char *name){ + const SalCustomHeader *ch=sal_op_get_recv_custom_header(im->op); + return sal_custom_header_find(ch,name); +} + +/** + * Returns origin of received LinphoneInfoMessage +**/ +const char *linphone_info_message_get_from(LinphoneInfoMessage *im){ + return sal_op_get_from(im->op); +} + +/** + * Assign a content to the info message. + * @param im the linphone info message + * @param content the content described as a #LinphoneContent structure. + * All fields of the LinphoneContent are copied, thus the application can destroy/modify/recycloe the content object freely ater the function returns. +**/ +void linphone_info_message_set_content(LinphoneInfoMessage *im, const LinphoneContent *content){ + linphone_content_copy(&im->content,content); +} + +/** + * Returns the info message's content as a #LinphoneContent structure. +**/ +const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMessage *im){ + return im->content.type ? &im->content : NULL; +} + +void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body){ + LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1); + info->op=sal_op_ref(op); + info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); + if (body) linphone_content_copy_from_sal_body(&info->content,body); + if (lc->vtable.info_received) + lc->vtable.info_received(lc,info); + linphone_info_message_destroy(info); +}