#include "LibSip_SIPTypesAndValues.hh" #include "LibSip_Common.hh" #include "sip_codec_message_body.hh" #include "loggers.hh" #include "converter.hh" #include "urn_ietf_params_xml_ns_pidf.hh" #ifdef WIN32 #undef osip_malloc #undef osip_free #define osip_malloc(S) malloc(S) #define osip_free(P) { if (P!=NULL) { free(P);} } #endif int sip_codec_message_body::encode (const LibSip__MessageBodyTypes::MessageBody& msg, OCTETSTRING& data) { loggers::get_instance().log_msg(">>> sip_codec_message_body::encode: ", msg); TRACE_INITIALIZE(TRACE_LEVEL7, NULL); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, ">>> sip_codec_request::encode\n")); if (msg.ischosen(LibSip__MessageBodyTypes::MessageBody::ALT_sdpMessageBody)) { const LibSip__SDPTypes::SDP__Message& sdp = msg.sdpMessageBody(); sdp_message_t* sdp_body = nullptr; if (encode_sdp(sdp, &sdp_body) == -1) { loggers::get_instance().warning("sip_codec_message_body::encode: Failed to encode SDP message"); return -1; } char* buff = nullptr; ::sdp_message_to_str(sdp_body, &buff); if (buff != nullptr) { data = char2oct(CHARSTRING(buff)); osip_free(buff); sdp_message_free(sdp_body); } } else if (msg.ischosen(LibSip__MessageBodyTypes::MessageBody::ALT_textplain)) { data = char2oct(msg.textplain()); } else { loggers::get_instance().warning("sip_codec_message_body::encode: Unsupported variant"); return -1; } loggers::get_instance().log_msg("<<< sip_codec_message_body::encode: ", data); return 0; } int sip_codec_message_body::decode (const OCTETSTRING& data, LibSip__MessageBodyTypes::MessageBody& msg, params* p_params) { loggers::get_instance().log(">>> sip_codec_message_body::decode"); TRACE_INITIALIZE(TRACE_LEVEL7, NULL); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, ">>> sip_codec_request::decode\n")); loggers::get_instance().error("sip_codec_message_body::decode: Not implemented yet"); return -1; } int sip_codec_message_body::encode_message_body(const LibSip__MessageBodyTypes::MessageBody& p_message_body, osip_message_t* p_sip_message) { // TODO Rename into encode_message loggers::get_instance().log_msg(">>> sip_codec_message_body::encode_message_body: ", p_message_body); osip_content_length* content_length = ::osip_message_get_content_length(p_sip_message); loggers::get_instance().log("sip_codec_message_body::encode_message_body: content_length= %s", content_length->value); if (p_message_body.ischosen(LibSip__MessageBodyTypes::MessageBody::ALT_sdpMessageBody)) { const LibSip__SDPTypes::SDP__Message& sdp = p_message_body.sdpMessageBody(); sdp_message_t* sdp_body = nullptr; if (encode_sdp(sdp, &sdp_body) == -1) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Failed to decode SDP message"); return -1; } char* buff = nullptr; ::sdp_message_to_str(sdp_body, &buff); if (buff != nullptr) { ::osip_message_set_body(p_sip_message, buff, strlen(buff)); osip_free(buff); sdp_message_free(sdp_body); } } else if (p_message_body.ischosen(LibSip__MessageBodyTypes::MessageBody::ALT_textplain)) { const CHARSTRING& text = p_message_body.textplain(); ::osip_message_set_body(p_sip_message, static_cast(text), text.lengthof()); } else if (p_message_body.ischosen(LibSip__MessageBodyTypes::MessageBody::ALT_mimeMessageBody)) { ::osip_message_set_mime_version(p_sip_message, "2.0"); const LibSip__MessageBodyTypes::MIME__Message& mime = p_message_body.mimeMessageBody(); const LibSip__MessageBodyTypes::MimeEncapsulatedList& l = mime.mimeEncapsulatedList(); int pos = 0; while (pos < l.lengthof()) { const LibSip__MessageBodyTypes::MIME__Encapsulated__Part& p = l[pos]; loggers::get_instance().log_msg("sip_codec_message_body::encode_message_body: p: ", p); const LibSip__MessageBodyTypes::MIME__Encapsulated__Parts& ps = p.mime__encapsulated__part(); if (ps.ischosen(LibSip__MessageBodyTypes::MIME__Encapsulated__Parts::ALT_sdpMessageBody)) { const LibSip__SDPTypes::SDP__Message& sdp = ps.sdpMessageBody(); sdp_message_t* sdp_body = nullptr; if (encode_sdp(sdp, &sdp_body) == -1) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Failed to encode SDP message"); return -1; } char* buff = nullptr; ::sdp_message_to_str(sdp_body, &buff); if (buff != nullptr) { loggers::get_instance().log("sip_codec_message_body::encode_message_body: sdp encoded value: %s", buff); loggers::get_instance().log("sip_codec_message_body::encode_message_body: body list size: %d", ::osip_list_size(&p_sip_message->bodies)); if (::osip_message_set_body(p_sip_message, buff, strlen(buff)) != 0) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Failed to encode SDP message"); osip_free(buff); sdp_message_free(sdp_body); return -1; } loggers::get_instance().log("sip_codec_message_body::encode_message_body: new body list size: %d", ::osip_list_size(&p_sip_message->bodies)); osip_free(buff); sdp_message_free(sdp_body); // Retrive the new created body and add content type osip_body_t* body = nullptr; if (::osip_message_get_body(p_sip_message, ::osip_list_size(&p_sip_message->bodies) - 1, &body) != ::osip_list_size(&p_sip_message->bodies) - 1) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Failed to set XML body content-type"); return -1; } const char* ct = static_cast(p.content__type()); loggers::get_instance().log("sip_codec_message_body::encode_message_body: content-type: %s", ct); if (ct != nullptr) { ::osip_body_set_contenttype(body, ct); } else { // Use a default value ::osip_body_set_contenttype(body, "application/sdp"); } } } else if (ps.ischosen(LibSip__MessageBodyTypes::MIME__Encapsulated__Parts::ALT_xmlBody)) { const LibSip__XMLTypes::XmlBody& xml = ps.xmlBody(); osip_body_t* body; if (encode_xml(xml, &body) == -1) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Failed to encode XML message"); return -1; } loggers::get_instance().log("sip_codec_message_body::encode_message_body: xml encoded value: %s", body->body); loggers::get_instance().log("sip_codec_message_body::encode_message_body: body list size: %d", ::osip_list_size(&p_sip_message->bodies)); if (::osip_message_set_body(p_sip_message, body->body, body->length) != 0) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Failed to encode XML message"); osip_body_free(body); return -1; } loggers::get_instance().log("sip_codec_message_body::encode_message_body: new body list size: %d", ::osip_list_size(&p_sip_message->bodies)); osip_body_free(body); // Retrive the new created body and add content type body = nullptr; loggers::get_instance().log("sip_codec_message_body::encode_message_body: get item #%d", ::osip_list_size(&p_sip_message->bodies) - 1); if (::osip_message_get_body(p_sip_message, ::osip_list_size(&p_sip_message->bodies) - 1, &body) != ::osip_list_size(&p_sip_message->bodies) - 1) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Failed to set content-type"); return -1; } const char* ct = static_cast(p.content__type()); loggers::get_instance().log("sip_codec_message_body::encode_message_body: content-type: %s", ct); if (ct != nullptr) { ::osip_body_set_contenttype(body, ct); } else { // Use a default value ::osip_body_set_contenttype(body, "application/resource-lists+xml"); } } else if (ps.ischosen(LibSip__MessageBodyTypes::MIME__Encapsulated__Parts::ALT_msdBody)) { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Unsupported decoding of ALT_msdBody"); } else { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Unsupported decoding of encapulated parts"); } pos += 1; } // End of 'while' statement } else { loggers::get_instance().warning("sip_codec_message_body::encode_message_body: Unsupported variant"); return -1; } return 0; } // End of method encode_message_body int sip_codec_message_body::encode_sdp(const LibSip__SDPTypes::SDP__Message& p_sdp_message, sdp_message_t** p_sdp_body) { loggers::get_instance().log_msg(">>> sip_codec_message_body::encode_sdp: ", p_sdp_message); ::sdp_message_init(p_sdp_body); // Encode mandatory fields // Version INTEGER version = p_sdp_message.protocol__version(); ::sdp_message_v_version_set(*p_sdp_body, (char*)::strdup(std::to_string(static_cast(version)).c_str())); LibSip__SDPTypes::SDP__Origin origin = p_sdp_message.origin(); // Origin loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: origin: ", origin); ::sdp_message_o_origin_set( *p_sdp_body, (char*)::strdup(static_cast(origin.user__name())), (char*)::strdup(static_cast(origin.session__id())), (char*)::strdup(static_cast(origin.session__version())), (char*)::strdup(static_cast(origin.net__type())), (char*)::strdup(static_cast(origin.addr__type())), (char*)::strdup(static_cast(origin.addr())) ); // Session name ::sdp_message_s_name_set(*p_sdp_body, (char*)::strdup(static_cast(p_sdp_message.session__name()))); // Time, t ::sdp_message_s_name_set(*p_sdp_body, (char*)::strdup(static_cast(p_sdp_message.session__name()))); loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: times: ", p_sdp_message.times()); for (int i = 0; i < p_sdp_message.times().lengthof(); i++) { const LibSip__SDPTypes::SDP__time& time = p_sdp_message.times()[i]; loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: time: ", time); ::sdp_message_t_time_descr_add(*p_sdp_body, (char*)::strdup(static_cast(time.time__field().start__time())), (char*)::strdup(static_cast(time.time__field().stop__time()))); if (time.time__repeat().is_present()) { const LibSip__SDPTypes::SDP__repeat__list& l = static_cast&>(*time.time__repeat().get_opt_value()); loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: l: ", l); for (int j = 0; j < l.lengthof(); j++) { const LibSip__SDPTypes::SDP__repeat& r = l[j]; // TODO r.repeat__interval(); // TODO r.active(); for (int k = 0; k < r.offsets().lengthof(); k++) { const LibSip__SDPTypes::SDP__typed__time& s = r.offsets()[k]; // TODO ::sdp_message_r_repeat_add(p_sdp_body, k, char *value); } // End of 'for' statement // TODO ::sdp_message_r_repeat_add(p_sdp_body, int pos_time_descr, char *value) } // End of 'for' statement } } // End of 'for' statement // Encode optional fields // email, e loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: emails: ", p_sdp_message.emails()); if (p_sdp_message.emails().is_present()) { const LibSip__SDPTypes::SDP__email__list& l = static_cast(*p_sdp_message.emails().get_opt_value()); for (int j = 0; j < l.lengthof(); j++) { const LibSip__SDPTypes::SDP__contact& e = l[j]; std::string str; if (e.disp__name().is_present()) { str = static_cast(static_cast(*e.disp__name().get_opt_value())); str += " "; } str += static_cast(e.addr__or__phone()); ::sdp_message_e_email_add(*p_sdp_body, ::strdup(str.c_str())); } // End of 'for' statement } // Information, i loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: information: ", p_sdp_message.information()); if (p_sdp_message.information().is_present()) { ::sdp_message_i_info_set(*p_sdp_body, 0, ::strdup(static_cast(*p_sdp_message.information().get_opt_value()))); } // Media list, m loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: medias: ", p_sdp_message.media__list()); if (p_sdp_message.media__list().is_present()) { const LibSip__SDPTypes::SDP__media__desc__list& l = static_cast(*p_sdp_message.media__list().get_opt_value()); int i = 0; for ( ; i < l.lengthof(); i++) { const LibSip__SDPTypes::SDP__media__desc m = l[i]; loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: media: ", m); // Media field if (m.media__field().ports().num__of__ports().is_present()) { int p = static_cast(*m.media__field().ports().num__of__ports().get_opt_value()); ::sdp_message_m_media_add(*p_sdp_body, (char*)::strdup(static_cast(m.media__field().media())), (char*)::strdup(std::to_string(m.media__field().ports().port__number()).c_str()), (char*)::strdup(std::to_string(p).c_str()), (char*)::strdup(static_cast(m.media__field().transport()))); } else { ::sdp_message_m_media_add(*p_sdp_body, (char*)::strdup(static_cast(m.media__field().media())), (char*)::strdup(std::to_string(m.media__field().ports().port__number()).c_str()), NULL, (char*)::strdup(static_cast(m.media__field().transport()))); } // Format list const LibSip__SDPTypes::SDP__fmt__list& fmts = m.media__field().fmts(); std::string str; for (int j = 0; j < fmts.lengthof() - 1; j++) { str += static_cast(fmts[j]); str += " "; } // End of 'for' statement str += static_cast(fmts[fmts.lengthof() - 1]); // information if (m.information().is_present()) { str += " "; str += static_cast(static_cast(*m.information().get_opt_value())); } if (str.length() != 0) { ::sdp_message_m_payload_add(*p_sdp_body, i, (char*)::strdup(str.c_str())); } // Attribute list, a loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: attributes: ", m.attributes()); if (m.attributes().is_present()) { const LibSip__SDPTypes::SDP__attribute__list& al = static_cast(*m.attributes().get_opt_value()); for (int k = 0; k < al.lengthof(); k++) { const LibSip__SDPTypes::SDP__attribute a = al[k]; loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: attribute: ", a); if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_rtpmap)) { std::string str(static_cast(a.rtpmap().payload__type())); str += " "; str += static_cast(a.rtpmap().codec().encoding()); str += "/"; str += a.rtpmap().codec().clockrate(); if (a.rtpmap().codec().parameters().is_present()) { str += "/"; str += static_cast(static_cast(*a.rtpmap().codec().parameters().get_opt_value())); } loggers::get_instance().log("sip_codec_message_body::encode_sdp: attribute: media #%d: encode rtpmap:%s", i, str.c_str()); ::sdp_message_a_attribute_add(*p_sdp_body, i, (char*)::strdup("rtpmap"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_fmtp)) { std::string str(static_cast(a.fmtp().format())); str += " "; if (a.fmtp().params().ischosen(LibSip__SDPTypes::SDP__attribute__fmtp__format__specific__params::ALT_paramList)) { const LibSip__Common::SemicolonParam__List& sl = a.fmtp().params().paramList(); for (int k = 0; k < sl.lengthof(); k++) { str += static_cast(sl[k].id()); if (sl[k].paramValue().is_present()) { const LibSip__Common::GenValue& v = static_cast(*sl[k].paramValue().get_opt_value()); loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: attribute: fmtp: v: ", v); str += "="; if (v.ischosen(LibSip__Common::GenValue::ALT_tokenOrHost)) { str += static_cast(v.tokenOrHost()); } else { str += static_cast(v.quotedString()); } } // else, nothing to do str += ";"; } // End of 'for' statement } else { str += static_cast(a.fmtp().params().unstructured()); } ::sdp_message_a_attribute_add(*p_sdp_body, i, (char*)::strdup("fmtp"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_curr)) { std::string str(static_cast(a.curr().preconditionType())); str += " "; str += static_cast(a.curr().statusType()); str += " "; str += static_cast(a.curr().direction()); ::sdp_message_a_attribute_add(*p_sdp_body, i, (char*)::strdup("curr"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_des)) { std::string str(static_cast(a.des().preconditionType())); str += " "; str += static_cast(a.des().strength()); str += " "; str += static_cast(a.des().statusType()); str += " "; str += static_cast(a.des().direction()); ::sdp_message_a_attribute_add(*p_sdp_body, i, (char*)::strdup("des"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_maxptime)) { ::sdp_message_a_attribute_add(*p_sdp_body, i, (char*)::strdup("maxptime"), (char*)::strdup(static_cast(a.maxptime().attr__value()))); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_sendrecv)) { ::sdp_message_a_attribute_add(*p_sdp_body, i, (char*)::strdup("sendrecv"), nullptr); } else { loggers::get_instance().warning("sip_codec_message_body::encode_sdp: attribute not processed"); } } // End of 'for' statement } } // End of 'for' statement ::sdp_message_endof_media(*p_sdp_body, i); } // Attribute list, a loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: attributes: ", p_sdp_message.attributes()); if (p_sdp_message.attributes().is_present()) { const LibSip__SDPTypes::SDP__attribute__list& l = static_cast(*p_sdp_message.attributes().get_opt_value()); int i = 0; for ( ; i < l.lengthof(); i++) { const LibSip__SDPTypes::SDP__attribute a = l[i]; loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: attribute: ", a); if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_rtpmap)) { std::string str(static_cast(a.rtpmap().payload__type())); str += " "; str += static_cast(a.rtpmap().codec().encoding()); str += " "; str += a.rtpmap().codec().clockrate(); if (a.rtpmap().codec().parameters().is_present()) { str += "/"; str += static_cast(static_cast(*a.rtpmap().codec().parameters().get_opt_value())); } loggers::get_instance().log("sip_codec_message_body::encode_sdp: attribute: media #%d: encode rtpmap:%s", i, str.c_str()); ::sdp_message_a_attribute_add(*p_sdp_body, 0, (char*)::strdup("rtpmap"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_fmtp)) { std::string str(static_cast(a.fmtp().format())); str += " "; if (a.fmtp().params().ischosen(LibSip__SDPTypes::SDP__attribute__fmtp__format__specific__params::ALT_paramList)) { const LibSip__Common::SemicolonParam__List& sl = a.fmtp().params().paramList(); for (int k = 0; k < sl.lengthof(); k++) { str += static_cast(sl[k].id()); if (sl[k].paramValue().is_present()) { const LibSip__Common::GenValue& v = static_cast(*sl[k].paramValue().get_opt_value()); loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: attribute: fmtp: v: ", v); str += "="; if (v.ischosen(LibSip__Common::GenValue::ALT_tokenOrHost)) { str += static_cast(v.tokenOrHost()); } else { str += static_cast(v.quotedString()); } } // else, nothing to do str += ";"; } // End of 'for' statement } else { str += static_cast(a.fmtp().params().unstructured()); } ::sdp_message_a_attribute_add(*p_sdp_body, 0, (char*)::strdup("fmtp"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_curr)) { std::string str(static_cast(a.curr().preconditionType())); str += " "; str += static_cast(a.curr().statusType()); str += " "; str += static_cast(a.curr().direction()); ::sdp_message_a_attribute_add(*p_sdp_body, 0, (char*)::strdup("curr"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_des)) { std::string str(static_cast(a.des().preconditionType())); str += " "; str += static_cast(a.des().strength()); str += " "; str += static_cast(a.des().statusType()); str += " "; str += static_cast(a.des().direction()); ::sdp_message_a_attribute_add(*p_sdp_body, 0, (char*)::strdup("des"), (char*)::strdup(str.c_str())); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_maxptime)) { ::sdp_message_a_attribute_add(*p_sdp_body, 0, (char*)::strdup("maxptime"), (char*)::strdup(static_cast(a.maxptime().attr__value()))); } else if (a.ischosen(LibSip__SDPTypes::SDP__attribute::ALT_sendrecv)) { ::sdp_message_a_attribute_add(*p_sdp_body, 0, (char*)::strdup("sendrecv"), nullptr); } else { loggers::get_instance().warning("sip_codec_message_body::encode_sdp: attribute not processed"); } } // End of 'for' statement } // Bandwith, b loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: Bandwidth: ", p_sdp_message.bandwidth()); if (p_sdp_message.bandwidth().is_present()) { const LibSip__SDPTypes::SDP__bandwidth__list& l = static_cast(*p_sdp_message.bandwidth().get_opt_value()); int i = 0; for ( ; i < l.lengthof(); i++) { const LibSip__SDPTypes::SDP__bandwidth b = l[i]; loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: bandwidth: ", b); ::sdp_message_b_bandwidth_add(*p_sdp_body, i, (char*)::strdup(static_cast(b.modifier())), (char*)::strdup(std::to_string(b.bandwidth()).c_str())); } // End of 'for' statement } // Connection, c loggers::get_instance().log_msg("sip_codec_message_body::encode_sdp: Connection: ", p_sdp_message.connection()); if (p_sdp_message.connection().is_present()) { const LibSip__SDPTypes::SDP__connection& c = static_cast(*p_sdp_message.connection().get_opt_value()); ::sdp_message_c_connection_add(*p_sdp_body, 0, ::strdup(static_cast(c.net__type())), ::strdup(static_cast(c.addr__type())), ::strdup(static_cast(c.conn__addr().addr())), nullptr, nullptr); } // TODO To be continued loggers::get_instance().log("<<< sip_codec_message_body::encode_sdp"); return 0; } void sip_codec_message_body::decode_message_body(const osip_message_t* p_sip_message, OPTIONAL& p_message_body) { // TODO Rename into decode_message loggers::get_instance().log(">>> sip_codec_message_body::decode_message_body"); osip_content_length* content_length = ::osip_message_get_content_length(p_sip_message); loggers::get_instance().log("sip_codec_message_body::decode_message_body: content_length= %s", content_length->value); if (strcmp((const char*)content_length->value, "0") == 0) { p_message_body.set_to_omit(); return; } // TODO Align the body the content_length osip_content_type_t* content_type = ::osip_message_get_content_type(p_sip_message); osip_body_t* body; int result = ::osip_message_get_body(p_sip_message, 0, &body); if (result != 0) { loggers::get_instance().warning("sip_codec_message_body::decode_message_body: Failed to retrieve body"); p_message_body.set_to_omit(); return; } loggers::get_instance().log("sip_codec_message_body::decode_message_body: Body size: %d", body->length); loggers::get_instance().log("sip_codec_message_body::decode_message_body: Body content: %s", body->body); if (body->headers != nullptr) { loggers::get_instance().log("sip_codec_message_body::decode_message_body: Body headers size: %d", osip_list_size(body->headers)); } if (body->content_type != nullptr) { loggers::get_instance().log("sip_codec_message_body::decode_message_body: Body content-type: '%s'/'%s'/%p", body->content_type->type, body->content_type->subtype, body->content_type->gen_params.node); } if (::osip_list_size(body->headers) != 0) { loggers::get_instance().log("sip_codec_message_body::decode_message_body: Body header is present"); // TODO Process Content-ID and other headers } LibSip__MessageBodyTypes::MessageBody msg_body; if (content_type != nullptr) { loggers::get_instance().log("sip_codec_message_body::decode_message_body: content-type.type: '%s'/'%s'/%p", content_type->type, content_type->subtype, content_type->gen_params.node); if (std::string(content_type->type).compare("multipart") == 0) { const osip_list_t* p = &(p_sip_message->bodies); size_t size = osip_list_size(p); loggers::get_instance().log("sip_codec_message_body::decode_message_body: Multipart body size: %d\n", size); if (size == 0) { loggers::get_instance().warning("sip_codec_message_body::decode_message_body: Empty multipart content, fallback to textplain"); msg_body.textplain() = CHARSTRING(body->body); } else { LibSip__MessageBodyTypes::MIME__Message mime; if (content_type->gen_params.node != nullptr) { mime.boundary() = CHARSTRING("boundary1"/*(const char*)content_type->gen_params.node->element*/); // TODO How to get the boundary name? } else { mime.boundary() = CHARSTRING("boundary1"); } loggers::get_instance().log_msg("sip_codec_message_body::decode_message_body: Boundary: ", mime.boundary()); LibSip__MessageBodyTypes::MimeEncapsulatedList& l = mime.mimeEncapsulatedList(); size_t pos = 0; while (pos < size) { const osip_header_t* header = (const osip_header_t*)osip_list_get(p, pos); loggers::get_instance().log("sip_codec_message_body::decode_message_body: body content=%s", header->hname); if ((*header->hname == 'v') && (*(header->hname + 1) == '=') && (*(header->hname + 2) == '0')) { // SDP loggers::get_instance().log("sip_codec_message_body::decode_message_body: Decode SDP"); LibSip__MessageBodyTypes::MIME__Encapsulated__Part p; p.content__type() = CHARSTRING("application/sdp"); p.content__disposition().set_to_omit(); p.content__id().set_to_omit(); LibSip__SDPTypes::SDP__Message sdp_body; osip_body_t* body; ::osip_body_init(&body); body->body = ::strdup(header->hname); // TODO Check if strdup is needed body->length = strlen(header->hname); LibSip__MessageBodyTypes::MIME__Encapsulated__Parts& parts = p.mime__encapsulated__part(); if (decode_sdp(body, sdp_body) == 0) { parts.sdpMessageBody() = sdp_body; } else { parts.msdBody() = char2oct(CHARSTRING(header->hname)); } l[pos] = p; } else if ((*header->hname == '<') && (*(header->hname + 1) == '?') && (*(header->hname + 2) == 'x')) { // body = header->hname; body->length = strlen(header->hname); LibSip__MessageBodyTypes::MIME__Encapsulated__Parts& parts = p.mime__encapsulated__part(); if (decode_xml(body, xml_body) == 0) { parts.xmlBody() = xml_body; } else { parts.msdBody() = char2oct(CHARSTRING(header->hname)); } l[pos] = p; } else { // TODO loggers::get_instance().error("sip_codec_message_body::decode_message_body: Not implemented yet"); } pos += 1; } // End of 'while' statement msg_body.mimeMessageBody() = mime; } } else if ((std::string(content_type->type).compare("application") == 0) && (std::string(content_type->subtype).compare("sdp") == 0)) { LibSip__SDPTypes::SDP__Message sdp_body; if (decode_sdp(body, sdp_body) == 0) { // Set message body msg_body.sdpMessageBody() = sdp_body; } else { loggers::get_instance().warning("sip_codec_message_body::decode_message_body: sdp_message_parse failed, fallback to textplain"); msg_body.textplain() = CHARSTRING(body->body); } } else { loggers::get_instance().warning("sip_codec_message_body::decode_message_body: Unsuported content-type, fallback to textplain"); msg_body.textplain() = CHARSTRING(body->body); } p_message_body = OPTIONAL(msg_body); } else if ((body != nullptr) && (body->body != nullptr)) { msg_body.textplain() = CHARSTRING(body->body); p_message_body = OPTIONAL(msg_body); } else { p_message_body.set_to_omit(); } loggers::get_instance().log_msg("<<< sip_codec_message_body::decode_message_body: ", p_message_body); } // End of method decode_message_body int sip_codec_message_body::decode_sdp(const osip_body_t* p_body, LibSip__SDPTypes::SDP__Message& p_sdp_header) { loggers::get_instance().log(">>> sip_codec_message_body::decode_sdp: %s", p_body->body); sdp_message_t* sdp = nullptr; ::sdp_message_init(&sdp); std::string s(p_body->body); s += "\r\n\r\n"; if (::sdp_message_parse(sdp, s.c_str()/*p_body->body*/) == 0) { // Mandatroy fields // Version, v char *hvalue = ::sdp_message_v_version_get(sdp); if (hvalue != nullptr) { p_sdp_header.protocol__version() = std::stoi(hvalue); } // Origin, o p_sdp_header.origin() = LibSip__SDPTypes::SDP__Origin( ::sdp_message_o_username_get(sdp), ::sdp_message_o_sess_version_get(sdp), ::sdp_message_o_sess_version_get(sdp), ::sdp_message_o_nettype_get(sdp), ::sdp_message_o_addrtype_get(sdp), ::sdp_message_o_addr_get(sdp) ); // Session name, s if ((hvalue = ::sdp_message_s_name_get(sdp)) != nullptr) { p_sdp_header.session__name() = CHARSTRING(hvalue); } // Time, t int i = 0; if ((hvalue = ::sdp_message_t_start_time_get(sdp, i)) != nullptr) { LibSip__SDPTypes::SDP__time__list l; do { LibSip__SDPTypes::SDP__time t; LibSip__SDPTypes::SDP__time__field tf; tf.start__time() = CHARSTRING(hvalue); tf.stop__time() = CHARSTRING(sdp_message_t_stop_time_get(sdp, i)); t.time__field() = tf; t.time__repeat().set_to_omit(); // TODO l[i] = t; i += 1; } while ((hvalue = ::sdp_message_t_start_time_get(sdp, i)) != nullptr); p_sdp_header.times() = l; } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: No start time in sdp"); } // Optional fields // Emails, e i = 0; if ((hvalue = ::sdp_message_e_email_get(sdp, i)) != nullptr) { LibSip__SDPTypes::SDP__email__list l; do { LibSip__SDPTypes::SDP__contact e; e.addr__or__phone() = CHARSTRING(hvalue); e.disp__name().set_to_omit(); // TODO To be refined l[i] = e; i += 1; } while ((hvalue = ::sdp_message_e_email_get(sdp, i)) != nullptr); p_sdp_header.emails() = OPTIONAL(l); } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: No emails in sdp"); p_sdp_header.emails().set_to_omit(); } // Information, i i = 0; if ((hvalue = ::sdp_message_i_info_get(sdp, i)) != nullptr) { p_sdp_header.information() = OPTIONAL(CHARSTRING(hvalue)); } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: No information in sdp"); p_sdp_header.information().set_to_omit(); } // Media, m i = 0; if ((hvalue = ::sdp_message_m_media_get(sdp, i)) != nullptr) { LibSip__SDPTypes::SDP__media__desc__list l; do { loggers::get_instance().log("sip_codec_message_body::decode_sdp: Media='%s'", hvalue); // Media description LibSip__SDPTypes::SDP__media__field f; f.media() = CHARSTRING(hvalue); LibSip__SDPTypes::SDP__media__port p; hvalue = ::sdp_message_m_port_get(sdp, i); p.port__number() = std::stoi(hvalue); if ((hvalue = ::sdp_message_m_number_of_port_get(sdp, i)) == nullptr) { p.num__of__ports().set_to_omit(); } else { p.num__of__ports() = OPTIONAL(std::stoi(hvalue)); } f.ports() = p; f.transport() = CHARSTRING(::sdp_message_m_proto_get(sdp, i)); LibSip__SDPTypes::SDP__fmt__list fl; int j = 0; while ((hvalue = ::sdp_message_m_payload_get(sdp, i, j)) != nullptr) { fl[j++] = CHARSTRING(hvalue); } // End of 'for' statement f.fmts() = fl; LibSip__SDPTypes::SDP__media__desc m; m.media__field() = f; loggers::get_instance().log_msg("sip_codec_message_body::decode_sdp: m=", m); // TODO // Media attributes m.attributes().set_to_omit(); m.bandwidth().set_to_omit(); m.information().set_to_omit(); m.connections().set_to_omit(); m.key().set_to_omit(); l[i] = m; i += 1; } while ((hvalue = ::sdp_message_m_media_get(sdp, i)) != nullptr); p_sdp_header.media__list() = OPTIONAL(l); } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: No media in sdp"); p_sdp_header.media__list().set_to_omit(); } // Attributes, a i = 0; sdp_attribute_t* a; if ((a = ::sdp_message_attribute_get(sdp, 0, i)) != nullptr) { LibSip__SDPTypes::SDP__attribute__list l; int j = 0; do { loggers::get_instance().log("sip_codec_message_body::decode_sdp: Attributes#%d: '%s'='%s'", i, a->a_att_field, (a->a_att_value == nullptr) ? "(null)" : a->a_att_value); // Attribute description LibSip__SDPTypes::SDP__attribute f; if (strcmp(a->a_att_field, "rtpmap") == 0) { std::vector output = converter::get_instance().split(a->a_att_value, " "); LibSip__SDPTypes::SDP__attribute__rtpmap__codec c; std::vector o = converter::get_instance().split(output[1], "/"); c.encoding() = CHARSTRING(o[0].c_str()); c.clockrate() = CHARSTRING(o[1].c_str()); if (o.size() == 3) { c.parameters() = OPTIONAL(CHARSTRING(o[2].c_str())); } else { c.parameters().set_to_omit(); } f.rtpmap() = LibSip__SDPTypes::SDP__attribute__rtpmap(CHARSTRING(output[0].c_str()), c); } else if (strcmp(a->a_att_field, "fmtp") == 0) { // fmtp'='114 mode-change-capability=2;max-red=0' std::vector o = converter::get_instance().split(a->a_att_value, " "); LibSip__SDPTypes::SDP__attribute__fmtp fmtp; fmtp.format() = CHARSTRING(o[0].c_str()); LibSip__SDPTypes::SDP__attribute__fmtp__format__specific__params c; if (o[1].find(";") != std::string::npos) { loggers::get_instance().log("sip_codec_message_body::decode_sdp: Attributes#%d: param list='%s'", i, o[1].c_str()); o = converter::get_instance().split(o[1], ";"); LibSip__Common::SemicolonParam__List& sl = c.paramList(); for (unsigned int k = 0; k < o.size(); k++) { loggers::get_instance().log("sip_codec_headers::decode_semi_colon_params: Process param: %s", o[k].c_str()); size_t eq_pos = o[k].find("="); if (eq_pos == std::string::npos) { sl[k] = LibSip__Common::GenericParam(CHARSTRING(o[k].c_str()), OPTIONAL(OMIT_VALUE)); } else { loggers::get_instance().log("sip_codec_headers::decode_semi_colon_params: substrs: %s - %s", o[k].substr(0, eq_pos).c_str(), o[k].substr(eq_pos + 1).c_str()); LibSip__Common::GenValue g; g.tokenOrHost() = CHARSTRING(o[k].substr(eq_pos + 1).c_str()); sl[k] = LibSip__Common::GenericParam(CHARSTRING(o[k].substr(0, eq_pos).c_str()), g); } } // End of 'for'statement } else { c.unstructured() = CHARSTRING(o[1].c_str()); } fmtp.params() = c; f.fmtp() = fmtp; } else if (strcmp(a->a_att_field, "curr") == 0) { std::vector o = converter::get_instance().split(a->a_att_value, " "); if (o.size() == 3) { LibSip__SDPTypes::SDP__attribute__curr c; c.preconditionType() = CHARSTRING(o[0].c_str()); c.statusType() = CHARSTRING(o[1].c_str()); c.direction() = CHARSTRING(o[2].c_str()); f.curr() = c; } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: Wrong formatted curr SDP"); f.curr().set_to_omit(); } } else if (strcmp(a->a_att_field, "des") == 0) { std::vector o = converter::get_instance().split(a->a_att_value, " "); if (o.size() == 4) { LibSip__SDPTypes::SDP__attribute__des c; c.preconditionType() = CHARSTRING(o[0].c_str()); c.strength() = CHARSTRING(o[1].c_str()); c.statusType() = CHARSTRING(o[2].c_str()); c.direction() = CHARSTRING(o[3].c_str()); f.des() = c; } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: Wrong formatted des SDP"); f.des().set_to_omit(); } } else if (strcmp(a->a_att_field, "sendrecv") == 0) { f.sendrecv() = LibSip__SDPTypes::SDP__attribute__sendrecv(NULL_VALUE); } else if (strcmp(a->a_att_field, "maxptime") == 0) { LibSip__SDPTypes::SDP__attribute__maxptime m; f.maxptime() = LibSip__SDPTypes::SDP__attribute__maxptime(CHARSTRING((const char*)a->a_att_value)); } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: Unprocessed attributes#%d: '%s'='%s'", i, a->a_att_field, a->a_att_value); } loggers::get_instance().log_msg("sip_codec_message_body::decode_sdp: f: ", f); if (f.is_bound()) { l[j++] = f; } i += 1; } while ((a = ::sdp_message_attribute_get(sdp, 0, i)) != nullptr); loggers::get_instance().log_msg("sip_codec_message_body::decode_sdp: After Attribute loop: ", l); if (j == 0) { // Empty list p_sdp_header.attributes().set_to_omit(); } else { p_sdp_header.attributes() = OPTIONAL(l); } } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: No attributes in sdp"); p_sdp_header.attributes().set_to_omit(); } // Bandwith, b i = 0; sdp_bandwidth_t* b; if ((b = ::sdp_message_bandwidth_get(sdp, 0, i)) != nullptr) { LibSip__SDPTypes::SDP__bandwidth__list l; do { loggers::get_instance().log("sip_codec_message_body::decode_sdp: Bandwidths#%d: '%s'='%s'", i, b->b_bwtype, b->b_bandwidth); LibSip__SDPTypes::SDP__bandwidth a(b->b_bwtype, INTEGER(std::stoi(b->b_bandwidth))); loggers::get_instance().log_msg("sip_codec_message_body::decode_sdp_sdp: Bandwith: ", a); l[i] = a; i += 1; } while((b = ::sdp_message_bandwidth_get(sdp, 0, i)) != nullptr); p_sdp_header.bandwidth() = OPTIONAL(l); } else { p_sdp_header.bandwidth().set_to_omit(); } // Connection, c char* net__type; if ((net__type = ::sdp_message_c_nettype_get(sdp, 0, 0)) != nullptr) { loggers::get_instance().log("sip_codec_message_body::decode_sdp: Connections#%d: '%s'", 0, a); LibSip__SDPTypes::SDP__connection c; c.net__type() = CHARSTRING(net__type); c.addr__type() = CHARSTRING(::sdp_message_c_addrtype_get(sdp, 0, 0)); LibSip__SDPTypes::SDP__conn__addr a; a.addr() = CHARSTRING(::sdp_message_c_addr_get(sdp, 0, 0)); if (::sdp_message_c_addr_multicast_ttl_get(sdp, 0, 0) != nullptr) { a.ttl() = OPTIONAL(::stoi(::sdp_message_c_addr_multicast_ttl_get(sdp, 0, 0))); } else { a.ttl().set_to_omit(); } if (::sdp_message_c_addr_multicast_int_get(sdp, 0, 0) != nullptr) { a.num__of__addr() = OPTIONAL(::stoi(::sdp_message_c_addr_multicast_int_get(sdp, 0, 0))); } else { a.num__of__addr().set_to_omit(); } c.conn__addr() = a; loggers::get_instance().log_msg("sip_codec_message_body::decode_sdp_sdp: connection: ", c); p_sdp_header.connection() = OPTIONAL(c); } else { p_sdp_header.connection().set_to_omit(); } i = 0; // TODO p_sdp_header.uri().set_to_omit(); p_sdp_header.phone__numbers().set_to_omit(); p_sdp_header.timezone__adjustments().set_to_omit(); p_sdp_header.key().set_to_omit(); } else { loggers::get_instance().warning("sip_codec_message_body::decode_sdp: Failed to parse SDP"); return -1; } loggers::get_instance().log_msg("<<< sip_codec_message_body::decode_sdp: sdp: ", p_sdp_header); return 0; } int sip_codec_message_body::encode_xml(const LibSip__XMLTypes::XmlBody& p_message_body, osip_body_t** p_body) { loggers::get_instance().log_msg(">>> sip_codec_message_body::encode_xml: ", p_message_body); ::osip_body_init(p_body); TTCN_EncDec::clear_error(); TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); TTCN_Buffer encoding_buffer; CHARSTRING h("\n"); encoding_buffer.put_s(h.lengthof(), (const unsigned char*)static_cast(h)); if (p_message_body.ischosen(LibSip__XMLTypes::XmlBody::ALT_presence)) { // Held codec const urn__ietf__params__xml__ns__pidf::Presence& presence = p_message_body.presence(); loggers::get_instance().log_msg("sip_codec_message_body::encode_xml: Process Presence", (const Base_Type&)presence); presence.encode(urn__ietf__params__xml__ns__pidf::Presence_descr_, encoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED); } else { loggers::get_instance().warning("sip_codec_message_body::encode_xml: Unsupported variant"); return -1; } OCTETSTRING data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); if (p_message_body.ischosen(LibSip__XMLTypes::XmlBody::ALT_presence)) { // NG112-2021 Workaround for TITAN/XSD issue // TODO TITAN work-around, replace tq0003 namespace??? std::string s(static_cast(data), data.lengthof() + static_cast(data)); /*size_t idx = 0; std::string f("tq0000:"); std::string t(""); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign(":tq0000"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign("tq0001:"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign(":tq0001"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign("tq0002:"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign(":tq0002"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign("tq0003:"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign(":tq0003"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign("tq0004:"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement f.assign(":tq0004"); while ((idx = s.find(f)) != std::string::npos) { s.replace(idx, f.length(), t); idx += t.length(); } // End of 'while' statement */ data = OCTETSTRING(s.length(), (const unsigned char*)s.c_str()); } (*p_body)->body = ::strdup(static_cast(oct2char(data))); (*p_body)->length = strlen((*p_body)->body); loggers::get_instance().log("<<< sip_codec_message_body::encode_xml: %s", (*p_body)->body); return 0; } int sip_codec_message_body::decode_xml(const osip_body_t* p_body, LibSip__XMLTypes::XmlBody& p_xml_header) { loggers::get_instance().log(">>> sip_codec_message_body::decode_xml: %s", p_body->body); // TODO Unify held_codec for bothHttp & Sip: instead of LibHttp__XmlMessageBodyTypes::XmlBody, use a generic XmlBody common to LibItsHttp & LibSip TTCN_EncDec::clear_error(); TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); OCTETSTRING data(p_body->length, (const unsigned char*)p_body->body); TTCN_Buffer decoding_buffer(data); loggers::get_instance().log_to_hexa("sip_codec_message_body::decode_xml: decoding_buffer: ", decoding_buffer); if (strstr(p_body->body, "