From 7cb91467e0fee89fe8c810941582f1ef0a75954b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 6 Mar 2014 00:01:02 +0500 Subject: [PATCH] FS-5814 --resolve --- libs/sofia-sip/configure.ac | 6 +- libs/sofia-sip/libsofia-sip-ua/Makefile.am | 6 +- libs/sofia-sip/libsofia-sip-ua/nta/nta.c | 89 ++++++++++++++++++- .../sofia-sip/libsofia-sip-ua/nta/nta_check.c | 4 +- .../libsofia-sip-ua/tport/Makefile.am | 1 + .../libsofia-sip-ua/tport/tport_logging.c | 74 +++++++++------ src/mod/endpoints/mod_sofia/sofia_glue.c | 3 + 7 files changed, 151 insertions(+), 32 deletions(-) diff --git a/libs/sofia-sip/configure.ac b/libs/sofia-sip/configure.ac index f882bc76b4..e20ddcb4c6 100644 --- a/libs/sofia-sip/configure.ac +++ b/libs/sofia-sip/configure.ac @@ -255,7 +255,11 @@ fi AC_CHECK_HEADERS([fnmatch.h]) AC_CHECK_LIB(pthread, pthread_setschedparam, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPARAM, 1, [Define if you have pthread_setschedparam()])]) - +AC_CHECK_LIB(z, compress, [have_zlib=yes],[have_zlib=no]) +if test x"$have_zlib" = "xyes"; then + AC_DEFINE(HAVE_ZLIB_COMPRESS, 1, [Define if you have zlib compress]) +fi +AM_CONDITIONAL([HAVE_ZLIB], [test "x$have_zlib" = xyes]) dnl dl is currently used only in testing AC_CHECK_LIB([dl], [dlopen], [ diff --git a/libs/sofia-sip/libsofia-sip-ua/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/Makefile.am index 78a8307392..d2855be4bf 100644 --- a/libs/sofia-sip/libsofia-sip-ua/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/Makefile.am @@ -58,7 +58,11 @@ libsofia_sip_ua_la_LIBADD = bnf/libbnf.la \ # set the libtool version info version:revision:age for libsofia-sip-ua # - soname to 'libsofia-sip-ua.so.(CUR-AGE)' libsofia_sip_ua_la_LDFLAGS = \ - -version-info $(LIBVER_SOFIA_SIP_UA_CUR):$(LIBVER_SOFIA_SIP_UA_REV):$(LIBVER_SOFIA_SIP_UA_AGE) + -version-info $(LIBVER_SOFIA_SIP_UA_CUR):$(LIBVER_SOFIA_SIP_UA_REV):$(LIBVER_SOFIA_SIP_UA_AGE) + +if HAVE_ZLIB +libsofia_sip_ua_la_LDFLAGS += -lz +endif PHONY = doxygen built-sources diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 5c8a98df0b..358f52afed 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -47,7 +47,9 @@ */ #include "config.h" - +#ifdef HAVE_ZLIB_COMPRESS +#include +#endif #include /** @internal SU message argument structure type */ @@ -379,6 +381,7 @@ struct nta_leg_s * Request missing @To tag matches * a tagged leg even after tagging. */ + unsigned leg_compressed:1; unsigned:0; nta_request_f *leg_callback; nta_leg_magic_t *leg_magic; @@ -450,6 +453,7 @@ struct nta_incoming_s unsigned irq_must_100rel:1; /**< 100rel is required */ unsigned irq_extra_100:1; /**< 100 Trying should be sent */ unsigned irq_tag_set:1; /**< Tag is not from request */ + unsigned irq_compressed:1; unsigned :0; tp_name_t irq_tpn[1]; @@ -2788,6 +2792,66 @@ void agent_recv_message(nta_agent_t *agent, } } +#ifdef HAVE_ZLIB_COMPRESS +int sip_content_encoding_Xflate(msg_t *msg, sip_t *sip, int inflate, int check) +{ + char const *method_name; + unsigned cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0; + int ok = !check; + + if (sip->sip_request) { + method_name = sip->sip_request->rq_method_name; + } else if (sip->sip_cseq) { + method_name = sip->sip_cseq->cs_method_name; + } else { + method_name = "Unknown"; + } + + if (!ok) { + if (sip->sip_content_encoding && sip->sip_content_encoding->k_items && sip->sip_payload) { + const char *val = sip->sip_content_encoding->k_items[0]; + if (val && (!strcasecmp(val, "gzip") || !strcasecmp(val, "deflate"))) { + ok = 1; + } + } + } + + if (ok) { + unsigned long n = 0; + void *decoded = NULL; + const char *id = "N/A"; + const char *orig_payload = sip->sip_payload->pl_data; + + n = sip->sip_payload->pl_len * 10; + + decoded = su_alloc(msg_home(msg), n); + assert(decoded); + + if (inflate) { + uncompress(decoded, &n, (void *)sip->sip_payload->pl_data, (unsigned long)sip->sip_payload->pl_len); + } else { + compress(decoded, &n, (void *)sip->sip_payload->pl_data, (unsigned long)sip->sip_payload->pl_len); + } + + sip->sip_payload = sip_payload_create(msg_home(msg), decoded, n); + + if (sip->sip_call_id) { + id = sip->sip_call_id->i_id; + } + + if (inflate) { + SU_DEBUG_1(("nta: %s (%u) (%s) Inflating compressed body:\n%s\n", method_name, cseq, id, (char *)decoded)); + } else { + SU_DEBUG_1(("nta: %s (%u) (%s) Deflating compressed body:\n%s\n", method_name, cseq, id, orig_payload)); + } + + return 1; + } + + return 0; +} +#endif + /** @internal Handle incoming requests. */ static void agent_recv_request(nta_agent_t *agent, @@ -2802,6 +2866,7 @@ void agent_recv_request(nta_agent_t *agent, url_t url[1]; unsigned cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0; int insane, errors, stream; + unsigned compressed = 0; agent->sa_stats->as_recv_msg++; agent->sa_stats->as_recv_request++; @@ -2924,6 +2989,10 @@ void agent_recv_request(nta_agent_t *agent, return; } +#ifdef HAVE_ZLIB_COMPRESS + compressed = sip_content_encoding_Xflate(msg, sip, 1, 1); +#endif + /* First, try existing incoming requests */ irq = incoming_find(agent, sip, sip->sip_via, agent->sa_merge_482 && @@ -2986,6 +3055,7 @@ void agent_recv_request(nta_agent_t *agent, /* Try existing dialog */ SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "going to existing leg")); + leg->leg_compressed = compressed; leg_recv(leg, msg, sip, tport); return; } @@ -2994,6 +3064,7 @@ void agent_recv_request(nta_agent_t *agent, /* Dialogless legs - let application process transactions statefully */ SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "going to a dialogless leg")); + leg->leg_compressed = compressed; leg_recv(leg, msg, sip, tport); } else if (!agent->sa_is_stateless && (leg = agent->sa_default_leg)) { @@ -3009,6 +3080,7 @@ void agent_recv_request(nta_agent_t *agent, else { SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "going to a default leg")); + leg->leg_compressed = compressed; leg_recv(leg, msg, sip, tport); } } @@ -3280,6 +3352,10 @@ void agent_recv_response(nta_agent_t *agent, /* XXX - should check if msg should be discarded based on via? */ +#ifdef HAVE_ZLIB_COMPRESS + sip_content_encoding_Xflate(msg, sip, 1, 1); +#endif + if ((orq = outgoing_find(agent, msg, sip, sip->sip_via))) { SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is going to a transaction")); @@ -4767,6 +4843,7 @@ void leg_recv(nta_leg_t *leg, msg_t *msg, sip_t *sip, tport_t *tport) return; } + irq->irq_compressed = leg->leg_compressed; irq->irq_in_callback = 1; status = incoming_callback(leg, irq, sip); irq->irq_in_callback = 0; @@ -6566,6 +6643,12 @@ int nta_incoming_mreply(nta_incoming_t *irq, msg_t *msg) return -1; } +#ifdef HAVE_ZLIB_COMPRESS + if (irq->irq_compressed) { + sip_content_encoding_Xflate(msg, sip, 0, 0); + } +#endif + if (irq->irq_must_100rel && !sip->sip_rseq && status > 100 && status < 200) { /* This nta_reliable_t object will be destroyed by PRACK or timeout */ if (nta_reliable_mreply(irq, NULL, NULL, msg)) @@ -7738,6 +7821,10 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent, sip = sip_object(msg); home = msg_home(msg); +#ifdef HAVE_ZLIB_COMPRESS + sip_content_encoding_Xflate(msg, sip_object(msg), 0, 1); +#endif + if (!sip->sip_request || sip_complete_message(msg) < 0) { SU_DEBUG_3(("nta: outgoing_create: incomplete request\n" VA_NONE)); return NULL; diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c index 8d1d4d490c..d3c8094821 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c @@ -248,7 +248,9 @@ int nta_check_session_content(nta_incoming_t *irq, if (!sip->sip_content_encoding || !sip->sip_content_encoding->k_items || !sip->sip_content_encoding->k_items[0] || - !sip->sip_content_encoding->k_items[0][0]) + !sip->sip_content_encoding->k_items[0][0] || + !strcasecmp(sip->sip_content_encoding->k_items[0], "gzip") || + !strcasecmp(sip->sip_content_encoding->k_items[0], "deflate")) acceptable_encoding = 1; if (acceptable_type && acceptable_encoding) diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am index e9aec1c997..73cc4bd7a7 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am @@ -14,6 +14,7 @@ INCLUDES = -I$(srcdir)/../bnf -I../bnf \ -I$(srcdir)/../msg -I../msg \ -I$(srcdir)/../http -I../http \ -I$(srcdir)/../url -I../url \ + -I$(srcdir)/../sip -I../sip \ -I$(srcdir)/../su -I../su # ---------------------------------------------------------------------- diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c index acb8e186dc..6931ba13f3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c @@ -478,7 +478,7 @@ void tport_log_msg(tport_t *self, msg_t *msg, size_t i, iovlen = msg_iovec(msg, iov, 80); size_t linelen = 0, n, logged = 0, truncated = 0; int skip_lf = 0; - + int j, unprintable = 0; #define MSG_SEPARATOR \ "------------------------------------------------------------------------\n" @@ -496,39 +496,57 @@ void tport_log_msg(tport_t *self, msg_t *msg, if (skip_lf && s < end && s[0] == '\n') { s++; logged++; skip_lf = 0; } while (s < end) { - if (s[0] == '\0') { - truncated = logged; - break; - } + if (s[0] == '\0') { + truncated = logged; + break; + } - n = su_strncspn(s, end - s, "\r\n"); + n = su_strncspn(s, end - s, "\r\n"); - if (linelen + n > MAX_LINELEN) { - n = MAX_LINELEN - linelen; - truncated = logged + n; - } + if (linelen + n > MAX_LINELEN) { + n = MAX_LINELEN - linelen; + truncated = logged + n; + } + + if (!unprintable) { + for (j = 0; j < 4; j++) { + if (s[j] == 0) break; + if (s[j] != 9 && s[j] != 10 && s[j] != 13 && (s[j] < 32 || s[j] > 126)) { + unprintable++; + } + } + } - su_log("%s%.*s", linelen > 0 ? "" : " ", (int)n, s); - s += n, linelen += n, logged += n; + if (unprintable) { + if (unprintable == 1) + su_log("\n "); + unprintable++; + } else { + su_log("%s%.*s", linelen > 0 ? "" : " ", (int)n, s); + } - if (truncated) - break; - if (s == end) - break; + s += n, linelen += n, logged += n; - linelen = 0; - su_log("\n"); + if (truncated) + break; + if (s == end) + break; + + linelen = 0; + su_log("\n"); + + /* Skip eol */ + if (s[0] == '\r') { + s++, logged++; + if (s == end) { + skip_lf = 1; + continue; + } + } - /* Skip eol */ - if (s[0] == '\r') { - s++, logged++; - if (s == end) { - skip_lf = 1; - continue; - } - } - if (s[0] == '\n') - s++, logged++; + if (s[0] == '\n') { + s++, logged++; + } } } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index f2cbba1173..450b7e71d6 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -691,6 +691,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) const char *handle_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_handle_full_to"); const char *force_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_from"); const char *force_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_to"); + const char *content_encoding = switch_channel_get_variable(tech_pvt->channel, "sip_content_encoding"); char *mp = NULL, *mp_type = NULL; char *record_route = NULL; const char *recover_via = NULL; @@ -1255,6 +1256,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) TAG_IF(!zstr(route), SIPTAG_ROUTE_STR(route)), TAG_IF(tech_pvt->profile->minimum_session_expires, NUTAG_MIN_SE(tech_pvt->profile->minimum_session_expires)), TAG_IF(cseq, SIPTAG_CSEQ(cseq)), + TAG_IF(content_encoding, SIPTAG_CONTENT_ENCODING_STR(content_encoding)), TAG_IF(zstr(tech_pvt->mparams.local_sdp_str), SIPTAG_PAYLOAD_STR("")), TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_ADDRESS(tech_pvt->mparams.adv_sdp_audio_ip)), TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)), @@ -1291,6 +1293,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) TAG_IF(tech_pvt->profile->minimum_session_expires, NUTAG_MIN_SE(tech_pvt->profile->minimum_session_expires)), TAG_IF(!require_timer, NUTAG_TIMER_AUTOREQUIRE(0)), TAG_IF(cseq, SIPTAG_CSEQ(cseq)), + TAG_IF(content_encoding, SIPTAG_CONTENT_ENCODING_STR(content_encoding)), NUTAG_MEDIA_ENABLE(0), SIPTAG_CONTENT_TYPE_STR(mp_type ? mp_type : "application/sdp"), SIPTAG_PAYLOAD_STR(mp ? mp : tech_pvt->mparams.local_sdp_str), TAG_IF(rep, SIPTAG_REPLACES_STR(rep)), SOATAG_HOLD(holdstr), TAG_END());