diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index bd942c9aa..9837e8078 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -166,8 +166,7 @@ belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_reque void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming); -void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body); -bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody); +SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg); SalReason sal_reason_to_sip_code(SalReason r); diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 076421aad..42e636390 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -669,15 +669,19 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } }else{ - SalBody salbody; - if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) { - if (sal_body_has_type(&salbody,"application","dtmf-relay")){ + belle_sip_message_t *msg = BELLE_SIP_MESSAGE(req); + belle_sip_body_handler_t *body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, msg)); + if (body_handler) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + if (content_type + && (strcmp(belle_sip_header_content_type_get_type(content_type), "application") == 0) + && (strcmp(belle_sip_header_content_type_get_subtype(content_type), "dtmf-relay") == 0)) { char tmp[10]; - if (sal_lines_get_value(salbody.data, "Signal",tmp, sizeof(tmp))){ + if (sal_lines_get_value(belle_sip_message_get_body(msg), "Signal",tmp, sizeof(tmp))){ op->base.root->callbacks.dtmf_received(op,tmp[0]); } }else - op->base.root->callbacks.info_received(op,&salbody); + op->base.root->callbacks.info_received(op, (SalBodyHandler *)body_handler); } else { op->base.root->callbacks.info_received(op,NULL); } diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index 8b439eb9b..d41440d96 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -77,7 +77,7 @@ static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_ev static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { } -static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBody * body){ +static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){ SalSubscribeStatus sub_state; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); belle_sip_response_t* resp; @@ -89,7 +89,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *event } else sub_state=SalSubscribeActive; sal_op_ref(op); - op->base.root->callbacks.notify(op,sub_state,eventname,body); + op->base.root->callbacks.notify(op,sub_state,eventname,body_handler); resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); sal_op_unref(op); @@ -102,7 +102,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque belle_sip_dialog_state_t dialog_state; belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); belle_sip_header_t *event_header; - SalBody body; + belle_sip_body_handler_t *body_handler; belle_sip_response_t* resp; const char *eventname=NULL; const char *method=belle_sip_request_get_method(req); @@ -112,7 +112,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque op->pending_server_trans=server_transaction; event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event"); - sal_op_get_body(op,(belle_sip_message_t*)req,&body); + body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, BELLE_SIP_MESSAGE(req))); if (event_header==NULL){ ms_warning("No event header in incoming SUBSCRIBE."); @@ -132,7 +132,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque belle_sip_dialog_set_application_data(op->dialog, sal_op_ref(op)); ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); }else{ /*this is a NOTIFY*/ - handle_notify(op,req,eventname,&body); + handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); return; } } @@ -140,7 +140,10 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: { - op->base.root->callbacks.subscribe_received(op,eventname,body.type ? &body : NULL); + const char *type = NULL; + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); + if (content_type) type = belle_sip_header_content_type_get_type(content_type); + op->base.root->callbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL); break; } case BELLE_SIP_DIALOG_EARLY: @@ -149,7 +152,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque case BELLE_SIP_DIALOG_CONFIRMED: if (strcmp("NOTIFY",method)==0) { - handle_notify(op,req,eventname,&body); + handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); } else if (strcmp("SUBSCRIBE",method)==0) { /*either a refresh of an unsubscribe*/ if (expires && belle_sip_header_expires_get_expires(expires)>0) { @@ -185,7 +188,7 @@ void sal_op_subscribe_fill_cbs(SalOp*op) { } -int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ +int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ belle_sip_request_t *req=NULL; if (from) @@ -207,13 +210,13 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); - sal_op_add_body(op,(belle_sip_message_t*)req,body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener); }else if (op->refresher){ const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); /* modify last request to update body*/ - sal_op_add_body(op,(belle_sip_message_t*)last_req,body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler)); return belle_sip_refresher_refresh(op->refresher,expires); } ms_warning("sal_subscribe(): no dialog and no refresher ?"); @@ -224,7 +227,7 @@ int sal_unsubscribe(SalOp *op){ if (op->refresher){ const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - sal_op_add_body(op,(belle_sip_message_t*)last_req,NULL); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); belle_sip_refresher_refresh(op->refresher,0); return 0; } @@ -247,7 +250,7 @@ int sal_subscribe_decline(SalOp *op, SalReason reason){ return 0; } -int sal_notify(SalOp *op, const SalBody *body){ +int sal_notify(SalOp *op, const SalBodyHandler *body_handler){ belle_sip_request_t* notify; if (!op->dialog) return -1; @@ -258,8 +261,7 @@ int sal_notify(SalOp *op, const SalBody *body){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600))); - - sal_op_add_body(op,(belle_sip_message_t*)notify, body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler)); return sal_op_send_request(op,notify); } diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 5a55d2900..9f654902c 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -706,50 +706,17 @@ const char *sal_op_get_remote_contact(const SalOp *op){ return op->base.remote_contact; } -void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body){ - belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-type"); - belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-length"); - belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-encoding"); - belle_sip_message_set_body((belle_sip_message_t*)req,NULL,0); - 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); - if (body->encoding){ - belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*) - belle_sip_header_create("Content-encoding",body->encoding)); - } +SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg) { + belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg); + if (body_handler != NULL) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t); + belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding"); + if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type)); + if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length)); + if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding); } -} - - -bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){ - const char *body = NULL; - belle_sip_header_content_type_t *content_type; - belle_sip_header_content_length_t *clen=NULL; - belle_sip_header_t *content_encoding; - - content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t); - if (content_type){ - body=belle_sip_message_get_body(msg); - clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t); - } - content_encoding=belle_sip_message_get_header(msg,"Content-encoding"); - - memset(salbody,0,sizeof(SalBody)); - - 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); - if (content_encoding) - salbody->encoding=belle_sip_header_get_unparsed_value(content_encoding); - return TRUE; - } - return FALSE; + return (SalBodyHandler *)body_handler; } void sal_op_set_privacy(SalOp* op,SalPrivacyMask privacy) { diff --git a/coreapi/bellesip_sal/sal_op_info.c b/coreapi/bellesip_sal/sal_op_info.c index 3cffb8e55..3820c95ee 100644 --- a/coreapi/bellesip_sal/sal_op_info.c +++ b/coreapi/bellesip_sal/sal_op_info.c @@ -19,12 +19,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sal_impl.h" -int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){ +int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body_handler){ if (op->dialog){ belle_sip_request_t *req; belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking); req=belle_sip_dialog_create_queued_request(op->dialog,"INFO"); - sal_op_add_body(op,(belle_sip_message_t*)req,body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); return sal_op_send_request(op,req); } return -1; diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c index 17ef8e8db..a1dc85204 100644 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ b/coreapi/bellesip_sal/sal_op_publish.c @@ -96,7 +96,7 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expire } } -int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ +int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ belle_sip_request_t *req=NULL; if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { if (from) @@ -114,7 +114,7 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); - sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); if (expires!=-1) return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); else return sal_op_send_request(op,req); @@ -123,7 +123,11 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); /*update body*/ - sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? body : NULL); + if (expires == 0) { + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_publish), NULL, 0); + } else { + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_publish), BELLE_SIP_BODY_HANDLER(body_handler)); + } return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); } } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index a0035d2ed..b19f468f1 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -1276,9 +1276,9 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){ } } -static void info_received(SalOp *op, const SalBody *body){ +static void info_received(SalOp *op, SalBodyHandler *body_handler){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - linphone_core_notify_info_message(lc,op,body); + linphone_core_notify_info_message(lc,op,body_handler); } static void subscribe_response(SalOp *op, SalSubscribeStatus status){ @@ -1299,7 +1299,7 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){ } } -static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){ +static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalBodyHandler *body_handler){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); @@ -1308,7 +1308,7 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname); } { - LinphoneContent *ct=linphone_content_from_sal_body(body); + LinphoneContent *ct=linphone_content_from_sal_body_handler(body_handler); if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct); } if (st!=SalSubscribeNone){ @@ -1316,7 +1316,7 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons } } -static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){ +static void subscribe_received(SalOp *op, const char *eventname, const SalBodyHandler *body_handler){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); diff --git a/coreapi/chat_file_transfer.c b/coreapi/chat_file_transfer.c index cf5318da0..03190ce7f 100644 --- a/coreapi/chat_file_transfer.c +++ b/coreapi/chat_file_transfer.c @@ -215,8 +215,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data, linphone_content_get_subtype(msg->file_transfer_information))); /* insert it in a multipart body handler which will manage the boundaries of multipart msg */ - bh = belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, - first_part_bh); + bh = belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, first_part_bh, NULL); linphone_chat_message_ref(msg); _release_http_request(msg); diff --git a/coreapi/content.c b/coreapi/content.c index 9f5cd4fee..a5a66f1b9 100644 --- a/coreapi/content.c +++ b/coreapi/content.c @@ -22,23 +22,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { + if (content->body_handler != NULL) { + sal_body_handler_unref(content->body_handler); + content->body_handler = NULL; + } + content->body_handler = sal_body_handler_ref(body_handler); +} + +static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { + LinphoneContent *content = belle_sip_object_new(LinphoneContent); + belle_sip_object_ref(content); + content->owned_fields = TRUE; + content->cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ + if (body_handler == NULL) { + linphone_content_set_sal_body_handler(content, sal_body_handler_new()); + } else { + linphone_content_set_sal_body_handler(content, body_handler); + } + return content; +} + static void linphone_content_destroy(LinphoneContent *content) { if (content->owned_fields == TRUE) { - if (content->lcp.type) belle_sip_free(content->lcp.type); - if (content->lcp.subtype) belle_sip_free(content->lcp.subtype); - if (content->lcp.data) belle_sip_free(content->lcp.data); - if (content->lcp.encoding) belle_sip_free(content->lcp.encoding); - if (content->lcp.name) belle_sip_free(content->lcp.name); - if (content->lcp.key) belle_sip_free(content->lcp.key); + if (content->body_handler) sal_body_handler_unref(content->body_handler); + if (content->name) belle_sip_free(content->name); + if (content->key) belle_sip_free(content->key); /* note : crypto context is allocated/destroyed by the encryption function */ } } static void linphone_content_clone(LinphoneContent *obj, const LinphoneContent *ref) { obj->owned_fields = TRUE; - linphone_content_set_type(obj, linphone_content_get_type(ref)); - linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); - linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); + linphone_content_set_sal_body_handler(obj, sal_body_handler_new()); + if ((linphone_content_get_type(ref) != NULL) || (linphone_content_get_subtype(ref) != NULL)) { + linphone_content_set_type(obj, linphone_content_get_type(ref)); + linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); + } + if (linphone_content_get_encoding(ref) != NULL) { + linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); + } linphone_content_set_name(obj, linphone_content_get_name(ref)); linphone_content_set_key(obj, linphone_content_get_key(ref), linphone_content_get_key_size(ref)); if (linphone_content_get_buffer(ref) != NULL) { @@ -81,163 +104,138 @@ void linphone_content_set_user_data(LinphoneContent *content, void *ud) { } const char * linphone_content_get_type(const LinphoneContent *content) { - return content->lcp.type; + return sal_body_handler_get_type(content->body_handler); } void linphone_content_set_type(LinphoneContent *content, const char *type) { - if (content->lcp.type != NULL) { - belle_sip_free(content->lcp.type); - content->lcp.type = NULL; - } - if (type != NULL) { - content->lcp.type = belle_sip_strdup(type); - } + sal_body_handler_set_type(content->body_handler, type); } const char * linphone_content_get_subtype(const LinphoneContent *content) { - return content->lcp.subtype; + return sal_body_handler_get_subtype(content->body_handler); } void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { - if (content->lcp.subtype != NULL) { - belle_sip_free(content->lcp.subtype); - content->lcp.subtype = NULL; - } - if (subtype != NULL) { - content->lcp.subtype = belle_sip_strdup(subtype); - } + sal_body_handler_set_subtype(content->body_handler, subtype); } void * linphone_content_get_buffer(const LinphoneContent *content) { - return content->lcp.data; + return sal_body_handler_get_data(content->body_handler); } void linphone_content_set_buffer(LinphoneContent *content, const void *buffer, size_t size) { - content->lcp.size = size; - content->lcp.data = belle_sip_malloc(size + 1); - memcpy(content->lcp.data, buffer, size); - ((char *)content->lcp.data)[size] = '\0'; + void *data; + sal_body_handler_set_size(content->body_handler, size); + data = belle_sip_malloc(size + 1); + memcpy(data, buffer, size); + ((char *)data)[size] = '\0'; + sal_body_handler_set_data(content->body_handler, data); } const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - return (char *)content->lcp.data; + return (const char *)linphone_content_get_buffer(content); } void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - content->lcp.size = strlen(buffer); - content->lcp.data = belle_sip_strdup(buffer); + sal_body_handler_set_size(content->body_handler, strlen(buffer)); + sal_body_handler_set_data(content->body_handler, belle_sip_strdup(buffer)); } size_t linphone_content_get_size(const LinphoneContent *content) { - return content->lcp.size; + return sal_body_handler_get_size(content->body_handler); } void linphone_content_set_size(LinphoneContent *content, size_t size) { - content->lcp.size = size; + sal_body_handler_set_size(content->body_handler, size); } const char * linphone_content_get_encoding(const LinphoneContent *content) { - return content->lcp.encoding; + return sal_body_handler_get_encoding(content->body_handler); } void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - if (content->lcp.encoding != NULL) { - belle_sip_free(content->lcp.encoding); - content->lcp.encoding = NULL; - } - if (encoding != NULL) { - content->lcp.encoding = belle_sip_strdup(encoding); - } + sal_body_handler_set_encoding(content->body_handler, encoding); } const char * linphone_content_get_name(const LinphoneContent *content) { - return content->lcp.name; + return content->name; } void linphone_content_set_name(LinphoneContent *content, const char *name) { - if (content->lcp.name != NULL) { - belle_sip_free(content->lcp.name); - content->lcp.name = NULL; + if (content->name != NULL) { + belle_sip_free(content->name); + content->name = NULL; } if (name != NULL) { - content->lcp.name = belle_sip_strdup(name); + content->name = belle_sip_strdup(name); } } size_t linphone_content_get_key_size(const LinphoneContent *content) { - return content->lcp.keyLength; + return content->keyLength; } const char * linphone_content_get_key(const LinphoneContent *content) { - return content->lcp.key; + return content->key; } void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { - if (content->lcp.key != NULL) { - belle_sip_free(content->lcp.key); - content->lcp.key = NULL; + if (content->key != NULL) { + belle_sip_free(content->key); + content->key = NULL; } if (key != NULL) { - content->lcp.key = belle_sip_malloc(keyLength); - memcpy(content->lcp.key, key, keyLength); + content->key = belle_sip_malloc(keyLength); + memcpy(content->key, key, keyLength); } } /* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { - return &(content->lcp.cryptoContext); + return &(content->cryptoContext); +} + +bool_t linphone_content_is_multipart(const LinphoneContent *content) { + // TODO + return FALSE; +} + +LinphoneContent * linphone_content_get_part(const LinphoneContent *content) { + // TODO + return NULL; +} + +void linphone_content_add_part(LinphoneContent *content, LinphoneContent *part) { + // TODO +} + +const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { + // TODO + return NULL; +} + +void linphone_content_add_custom_header(LinphoneContent *content, const char *header_name, const char *header_value) { + // TODO } + LinphoneContent * linphone_content_new(void) { - LinphoneContent *content = belle_sip_object_new(LinphoneContent); - belle_sip_object_ref(content); - content->owned_fields = TRUE; - content->lcp.cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ - return content; + return linphone_content_new_with_body_handler(NULL); } LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); } -LinphoneContent * linphone_content_from_sal_body(const SalBody *ref) { - if (ref && ref->type) { - LinphoneContent *content = linphone_content_new(); - linphone_content_set_type(content, ref->type); - linphone_content_set_subtype(content, ref->subtype); - linphone_content_set_encoding(content, ref->encoding); - if (ref->data != NULL) { - linphone_content_set_buffer(content, ref->data, ref->size); - } else { - linphone_content_set_size(content, ref->size); - } - return content; +LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { + if (body_handler) { + return linphone_content_new_with_body_handler(body_handler); } return NULL; } -SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *content) { - if (content && linphone_content_get_type(content)) { - body->type = linphone_content_get_type(content); - body->subtype = linphone_content_get_subtype(content); - body->data = linphone_content_get_buffer(content); - body->size = linphone_content_get_size(content); - body->encoding = linphone_content_get_encoding(content); - return body; - } - return NULL; -} - - - -LinphoneContent * linphone_content_private_to_linphone_content(const LinphoneContentPrivate *lcp) { - LinphoneContent *content = belle_sip_object_new(LinphoneContent); - memcpy(&content->lcp, lcp, sizeof(LinphoneContentPrivate)); - content->owned_fields = FALSE; - return content; -} - -LinphoneContentPrivate * linphone_content_to_linphone_content_private(const LinphoneContent *content) { - return (LinphoneContentPrivate *)&content->lcp; +SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { + if (content == NULL) return NULL; + return content->body_handler; } diff --git a/coreapi/content.h b/coreapi/content.h index 1e21138eb..ea3eda32c 100644 --- a/coreapi/content.h +++ b/coreapi/content.h @@ -40,51 +40,6 @@ struct _LinphoneContent; **/ typedef struct _LinphoneContent LinphoneContent; -/** - * @deprecated Use LinphoneContent objects instead of this structure. - */ -struct _LinphoneContentPrivate{ - char *type; /**dir!=LinphoneSubscriptionOutgoing){ @@ -179,7 +179,8 @@ int linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneContent *bod lev->send_custom_headers=NULL; }else sal_op_set_sent_custom_header(lev->op,NULL); - err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,sal_body_from_content(&salbody,body)); + body_handler = sal_body_handler_from_content(body); + err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ if (lev->subscription_state==LinphoneSubscriptionNone) linphone_event_set_state(lev,LinphoneSubscriptionOutgoingInit); @@ -216,7 +217,7 @@ int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){ } int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){ - SalBody salbody; + SalBodyHandler *body_handler; if (lev->subscription_state!=LinphoneSubscriptionActive){ ms_error("linphone_event_notify(): cannot notify if subscription is not active."); return -1; @@ -225,7 +226,8 @@ int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){ ms_error("linphone_event_notify(): cannot notify if not an incoming subscription."); return -1; } - return sal_notify(lev->op,sal_body_from_content(&salbody,body)); + body_handler = sal_body_handler_from_content(body); + return sal_notify(lev->op, body_handler); } LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){ @@ -236,7 +238,7 @@ LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddr } static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneContent *body, bool_t notify_err){ - SalBody salbody; + SalBodyHandler *body_handler; int err; if (lev->dir!=LinphoneSubscriptionInvalidDir){ @@ -247,7 +249,8 @@ static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneConten sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers); lev->send_custom_headers=NULL; }else sal_op_set_sent_custom_header(lev->op,NULL); - err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,sal_body_from_content(&salbody,body)); + body_handler = sal_body_handler_from_content(body); + err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ linphone_event_set_publish_state(lev,LinphonePublishProgress); }else if (notify_err){ diff --git a/coreapi/info.c b/coreapi/info.c index f33a16997..87f1bd199 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -69,10 +69,10 @@ LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc){ * @param call the call * @param info the info message **/ -int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info){ - SalBody body; - sal_op_set_sent_custom_header(call->op,info->headers); - return sal_send_info(call->op,NULL, NULL, sal_body_from_content(&body,info->content)); +int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info) { + SalBodyHandler *body_handler = sal_body_handler_from_content(info->content); + sal_op_set_sent_custom_header(call->op, info->headers); + return sal_send_info(call->op,NULL, NULL, body_handler); } /** @@ -112,12 +112,12 @@ const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMess return (im->content && linphone_content_get_type(im->content)) ? im->content : NULL; } -void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body){ +void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body_handler){ LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); if (call){ LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1); info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); - if (body) info->content=linphone_content_from_sal_body(body); + if (body_handler) info->content=linphone_content_from_sal_body_handler(body_handler); linphone_core_notify_info_received(lc,call,info); linphone_info_message_destroy(info); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index fb3a39e9b..060856238 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -520,7 +520,7 @@ static void process_response_from_post_file_log_collection(void *data, const bel (belle_sip_header_t *)belle_sip_header_content_type_create(linphone_content_get_type(core->log_collection_upload_information), linphone_content_get_subtype(core->log_collection_upload_information))); /* Insert it in a multipart body handler which will manage the boundaries of multipart message */ - bh = belle_sip_multipart_body_handler_new(log_collection_upload_on_progress, core, (belle_sip_body_handler_t *)first_part_bh); + bh = belle_sip_multipart_body_handler_new(log_collection_upload_on_progress, core, (belle_sip_body_handler_t *)first_part_bh, NULL); ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version()); uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core)); req = belle_http_request_create("POST", uri, belle_sip_header_create("User-Agent", ua), NULL); diff --git a/coreapi/private.h b/coreapi/private.h index 5c2777f4e..e279c6bdd 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1071,10 +1071,10 @@ const char *linphone_core_create_uuid(LinphoneCore *lc); void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); void linphone_call_create_op(LinphoneCall *call); int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer); -void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body); +void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body); LinphoneContent * linphone_content_new(void); LinphoneContent * linphone_content_copy(const LinphoneContent *ref); -SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *content); +SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content); SalReason linphone_reason_to_sal(LinphoneReason reason); LinphoneReason linphone_reason_from_sal(SalReason reason); LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires); @@ -1086,14 +1086,18 @@ LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state); LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); -LinphoneContent *linphone_content_from_sal_body(const SalBody *ref); +LinphoneContent *linphone_content_from_sal_body_handler(SalBodyHandler *ref); void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); struct _LinphoneContent { belle_sip_object_t base; void *user_data; - struct _LinphoneContentPrivate lcp; + SalBodyHandler *body_handler; + char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */ + char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */ + size_t keyLength; /**< Length of key in bytes */ + void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ bool_t owned_fields; }; diff --git a/coreapi/sal.c b/coreapi/sal.c index 2c858298a..9ed121463 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -849,10 +849,101 @@ int sal_lines_get_value(const char *data, const char *key, char *value, size_t v return FALSE; } -int sal_body_has_type(const SalBody *body, const char *type, const char *subtype){ - return body->type && body->subtype - && strcmp(body->type,type)==0 - && strcmp(body->subtype,subtype)==0; +static belle_sip_header_t * sal_body_handler_find_header(const SalBodyHandler *body_handler, const char *header_name) { + belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(body_handler); + const belle_sip_list_t *l = belle_sip_body_handler_get_headers(bsbh); + for (; l != NULL; l = l->next) { + belle_sip_header_t *header = BELLE_SIP_HEADER(l->data); + if (strcmp(belle_sip_header_get_name(header), header_name) == 0) { + return header; + } + } + return NULL; +} + +SalBodyHandler * sal_body_handler_new(void) { + belle_sip_memory_body_handler_t *body_handler = belle_sip_memory_body_handler_new(NULL, NULL); + return (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(body_handler); +} + +SalBodyHandler * sal_body_handler_ref(SalBodyHandler *body_handler) { + return (SalBodyHandler *)belle_sip_object_ref(BELLE_SIP_OBJECT(body_handler)); +} + +void sal_body_handler_unref(SalBodyHandler *body_handler) { + belle_sip_object_unref(BELLE_SIP_OBJECT(body_handler)); +} + +const char * sal_body_handler_get_type(const SalBodyHandler *body_handler) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + return belle_sip_header_content_type_get_type(content_type); + } + return NULL; +} + +void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type == NULL) { + content_type = belle_sip_header_content_type_new(); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type)); + } + belle_sip_header_content_type_set_type(content_type, type); +} + +const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + return belle_sip_header_content_type_get_subtype(content_type); + } + return NULL; +} + +void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type == NULL) { + content_type = belle_sip_header_content_type_new(); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type)); + } + belle_sip_header_content_type_set_subtype(content_type, subtype); +} + +const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) { + belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); + if (content_encoding != NULL) { + return belle_sip_header_get_unparsed_value(content_encoding); + } + return NULL; +} + +void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding) { + belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); + if (content_encoding != NULL) { + belle_sip_body_handler_remove_header_from_ptr(BELLE_SIP_BODY_HANDLER(body_handler), content_encoding); + } + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), belle_sip_header_create("Content-Encoding", encoding)); +} + +void * sal_body_handler_get_data(const SalBodyHandler *body_handler) { + return belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler)); +} + +void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data) { + belle_sip_memory_body_handler_set_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler), data); +} + +size_t sal_body_handler_get_size(const SalBodyHandler *body_handler) { + return belle_sip_body_handler_get_size(BELLE_SIP_BODY_HANDLER(body_handler)); +} + +void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size) { + belle_sip_header_content_length_t *content_length = BELLE_SIP_HEADER_CONTENT_LENGTH(sal_body_handler_find_header(body_handler, "Content-Length")); + if (content_length == NULL) { + content_length = belle_sip_header_content_length_new(); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_length)); + } + belle_sip_header_content_length_set_content_length(content_length, size); + belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(body_handler), size); } belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) { diff --git a/include/sal/sal.h b/include/sal/sal.h index 6e1c4d068..468696b29 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -55,6 +55,10 @@ struct SalAddress; typedef struct SalAddress SalAddress; +struct SalBodyHandler; + +typedef struct SalBodyHandler SalBodyHandler; + struct SalCustomHeader; typedef struct SalCustomHeader SalCustomHeader; @@ -453,14 +457,6 @@ typedef struct SalAuthInfo{ SalCertificatesChain *certificates; }SalAuthInfo; -typedef struct SalBody{ - const char *type; - const char *subtype; - const void *data; - size_t size; - const char *encoding; -}SalBody; - typedef void (*SalOnCallReceived)(SalOp *op); typedef void (*SalOnCallRinging)(SalOp *op); typedef void (*SalOnCallAccepted)(SalOp *op); @@ -482,8 +478,8 @@ typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus); typedef void (*SalOnIsComposingReceived)(SalOp *op, const SalIsComposing *is_composing); typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state); typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status); -typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body); -typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBody *body); +typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, SalBodyHandler *body); +typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBodyHandler *body); typedef void (*SalOnSubscribeClosed)(SalOp *salop); typedef void (*SalOnParsePresenceRequested)(SalOp *salop, const char *content_type, const char *content_subtype, const char *content, SalPresenceModel **result); typedef void (*SalOnConvertPresenceToXMLRequested)(SalOp *salop, SalPresenceModel *presence, const char *contact, char **content); @@ -491,7 +487,7 @@ typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenc typedef void (*SalOnSubscribePresenceReceived)(SalOp *salop, const char *from); typedef void (*SalOnSubscribePresenceClosed)(SalOp *salop, const char *from); typedef void (*SalOnPingReply)(SalOp *salop); -typedef void (*SalOnInfoReceived)(SalOp *salop, const SalBody *body); +typedef void (*SalOnInfoReceived)(SalOp *salop, SalBodyHandler *body); typedef void (*SalOnPublishResponse)(SalOp *salop); typedef void (*SalOnExpire)(SalOp *salop); /*allows sal implementation to access auth info if available, return TRUE if found*/ @@ -739,16 +735,16 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expire int sal_ping(SalOp *op, const char *from, const char *to); /*info messages*/ -int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body); +int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body); /*generic subscribe/notify/publish api*/ -int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body); +int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body); int sal_unsubscribe(SalOp *op); int sal_subscribe_accept(SalOp *op); int sal_subscribe_decline(SalOp *op, SalReason reason); -int sal_notify(SalOp *op, const SalBody *body); +int sal_notify(SalOp *op, const SalBodyHandler *body); int sal_notify_close(SalOp *op); -int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBody *body); +int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBodyHandler *body); /*privacy, must be in sync with LinphonePrivacyMask*/ typedef enum _SalPrivacy { @@ -844,7 +840,21 @@ unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size); belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name); void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer); -int sal_body_has_type(const SalBody *body, const char *type, const char *subtype); +//SalBodyHandler * sal_body_handler_new(const char *type, const char *subtype, void *data, size_t size, const char *encoding); +SalBodyHandler * sal_body_handler_new(void); +SalBodyHandler * sal_body_handler_ref(SalBodyHandler *body_handler); +void sal_body_handler_unref(SalBodyHandler *body_handler); +const char * sal_body_handler_get_type(const SalBodyHandler *body_handler); +void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type); +const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler); +void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype); +const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler); +void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding); +void * sal_body_handler_get_data(const SalBodyHandler *body_handler); +void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data); +size_t sal_body_handler_get_size(const SalBodyHandler *body_handler); +void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size); + /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size);