From 58702c80c0da0759f2de576cb68c4e0e92922f67 Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Mon, 28 May 2007 17:26:00 +0000 Subject: [PATCH] *** empty log message *** --- ChangeLog | 6 -- RELNOTES | 1 - doc/siproxd.conf.example | 25 ------- src/proxy.c | 55 ++------------ src/sip_utils.c | 154 +++++++++++++++++++++++++++++++++++++++ src/siproxd.h | 1 + 6 files changed, 160 insertions(+), 82 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11d6698..8231c26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,5 @@ 0.6.0 ===== - 27-May-2007: - new feature: "Obscure Loops" does modify the Call-IDs in - outgoing requests and thus allows incoming calls forked - off such an outgoing call (redirect, transfer, ...) back - to the same UA where the initial call did originate. - This even seems to fix some issues with Asterisks - Loop detection... :-) 25-May-2007: - Just discovered some patches originating from Debian project - included most of them as they make sense. (Hint: People, if you get fixes, please drop me a note diff --git a/RELNOTES b/RELNOTES index ae739dc..e373d83 100644 --- a/RELNOTES +++ b/RELNOTES @@ -7,7 +7,6 @@ Major changes since 0.5.13: after the RTP timeout period. - Can now masquerade the User-agent header, too - Support for adding ;rport to Via headers (RFC3581) - - "Obscure" SIP Loops (Calls redirected back to me work better) General Overview: - SIP (RFC3261) Proxy for SIP based softphones hidden behind a diff --git a/doc/siproxd.conf.example b/doc/siproxd.conf.example index 4017896..df7833b 100644 --- a/doc/siproxd.conf.example +++ b/doc/siproxd.conf.example @@ -257,31 +257,6 @@ debug_port = 0 # # use_rport = 0 -###################################################################### -# Obscure SIP Loops -# -# By default, Siproxd can not handle the situation where a call -# from an UA is made back to the *same* UA. -# -# E.g. -# -# UA ----- siproxd ----- Registrar -# -# and UA is registered with two accounts (A & B) at "Registrar". -# If UA (account A) now initiates a Call to its second account (B) -# this will result in a "loop" (if you use Asterisk as UA above, it -# will react with an "482 Loop detected" error and does not accept the -# call). Siproxd can not handle the RTP audio stream properly in such -# a situation - you will most likely only hear silence. -# -# This expirmental feature does "obscure" this loop - well, actually -# it does modify the OUTGOING Call-Id - and when the INVITE comes back, -# it actually looks like a second (independend) call. This even makes -# Asterisk work in the situation mentioned above. -# -# Default is disabled. -# obscure_loops=1 - ###################################################################### # Outbound proxy # diff --git a/src/proxy.c b/src/proxy.c index 1aa53e7..631272f 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -205,6 +205,7 @@ int proxy_request (sip_ticket_t *ticket) { sts = proxy_rewrite_invitation_body(ticket, DIR_INCOMING); } +sts=sip_obscure_callid(ticket); break; /* @@ -262,29 +263,7 @@ int proxy_request (sip_ticket_t *ticket) { rtp_stop_fwd(osip_message_get_call_id(request), DIR_OUTGOING); } - /* - * "Obscure" SIP Loops - modify Call-IDs on outgoing REQs, so calls - * forked / redirected from a Call originating here may be - * passed back without breaking things - */ - if (configuration.obscure_loops) { - osip_call_id_t *CID=NULL; - char *tmp; - - CID=osip_message_get_call_id(request); - if (CID) { - /* does CID->number already exist? */ - if (CID->number) { /* accoridng to RFC3261, this part is mandatory */ - /* modify it */ - tmp=osip_malloc(strlen(CID->number)+7+1); - sprintf(tmp,"%s-siproxd",CID->number); - osip_free(CID->number); - CID->number=tmp; - } else { - WARN("CID without number part received, not RFC3261 conform!"); - } - } - } +sts=sip_obscure_callid(ticket); break; @@ -584,34 +563,8 @@ int proxy_response (sip_ticket_t *ticket) { response->from->url->username? response->from->url->username:"*NULL*", response->from->url->host? response->from->url->host : "*NULL*"); - /* - * "Obscure" SIP Loops - modify Call-IDs on incoming RESs, so calls - * forked / redirected from a Call originating here may be - * passed back without breaking things - */ - if (configuration.obscure_loops) { - osip_call_id_t *CID=NULL; - char *tmp, *tmp2; +sts=sip_obscure_callid(ticket); - CID=osip_message_get_call_id(response); - if (CID) { - /* does CID->number already exist? */ - if (CID->number) { /* accoridng to RFC3261, this part is mandatory */ - /* modify it back*/ - tmp=strstr(CID->number,"-siproxd"); - if (tmp) { - /* make sure to cut only the last marker - in case - of multiple siproxd instances... */ - for (;(tmp2=strstr(tmp+1, "-siproxd")) != NULL;) { - tmp=tmp2; - } - tmp[0]='\0'; - } - } else { - WARN("CID without number part received, not RFC3261 conform!"); - } - } - } /* * Response for INVITE - deal with RTP data in body and @@ -691,6 +644,8 @@ int proxy_response (sip_ticket_t *ticket) { response->from->url->host ? response->from->url->host : "*NULL*"); +sts=sip_obscure_callid(ticket); + /* Rewrite Contact header to represent the masqued address */ sip_rewrite_contact(ticket, DIR_OUTGOING); diff --git a/src/sip_utils.c b/src/sip_utils.c index 223b6e6..3b5d85d 100644 --- a/src/sip_utils.c +++ b/src/sip_utils.c @@ -1177,3 +1177,157 @@ int sip_fixup_asterisk(char *buff, int *buflen) { } +/* + * SIP_OBSCURE_CALLID + * + 27-May-2007: - new feature: "Obscure Loops" does modify the Call-IDs in + outgoing requests and thus allows incoming calls forked + off such an outgoing call (redirect, transfer, ...) back + to the same UA where the initial call did originate. + This even seems to fix some issues with Asterisks + Loop detection... :-) +Needs more thinking. The logic about call termination is quite tricky - +calls can be terminated from either side... It is not stratigh forward +when and how to modify CIDs for call cancellation... + * ... + * + * RETURNS + * STS_SUCCESS on success + */ +int sip_obscure_callid(sip_ticket_t *ticket) { + static char myident[]="-siproxd"; + int myidentlen=sizeof(myident)-1; /* a static strlen() of myident */ + + osip_message_t *sipmsg; + osip_from_t *from; + osip_to_t *to; + osip_uri_param_t *fromtag, *totag; /* gname, gvalue */ + + osip_call_id_t *CID=NULL; + + char *tmp, *tmp2; + + + /* feature enabled? */ + if (!configuration.obscure_loops) return STS_SUCCESS; + + sipmsg=ticket->sipmsg; + + + if (MSG_IS_REQUEST(sipmsg) && + MSG_IS_REGISTER(sipmsg)) return STS_SUCCESS; + if (MSG_IS_RESPONSE(sipmsg) && + MSG_IS_RESPONSE_FOR(sipmsg,"REGISTER")) return STS_SUCCESS; + + from=sipmsg->from; + osip_from_get_tag(from, &fromtag); + + to=sipmsg->to; + osip_to_get_tag(to, &totag); + + /* at lest the From Tag must be present, otherwise out Logic does + not work. Is MANDATORY according to RFC3261 */ + if (!fromtag || !fromtag->gvalue || strlen(fromtag->gvalue)==0) { + WARN("sip_obscure_callid: no From-Tag, not RFC3261 conform!"); + return STS_FAILURE; + } + + CID=osip_message_get_call_id(sipmsg); + + /* does CID->number exist? According to RFC3261, this part is mandatory */ + if (!CID || !CID->number) { + WARN("sip_obscure_callid: invalid Call-ID received, not RFC3261 conform!"); + return STS_FAILURE; + } + + DEBUGC(DBCLASS_PROXY, "sip_obscure_callid: current Callid#=%s Direction=%i", + CID->number, ticket->direction); + + switch (ticket->direction) { + + /* Outgoing Request */ + case REQTYP_OUTGOING: + /* also need testing for "normal" incoming call that is present and + now we SEND a cancel for this call */ + tmp=strstr(CID->number, myident); + if (tmp==NULL) { + /* no obscuring present yet, must be a new call, modify it */ + tmp=osip_malloc(strlen(CID->number) + myidentlen + + strlen(fromtag->gvalue) + 1); + sprintf(tmp,"%s%s%s",CID->number,myident,fromtag->gvalue); + osip_free(CID->number); + CID->number=tmp; + } else { + /* Obscuring is present, do nothing. */ + } + break; + + /* Incoming Response */ + case RESTYP_INCOMING: + tmp=strstr(CID->number,myident); + /* modify it back if existing */ + if (tmp) { + /* make sure to cut only the last marker - in case + of multiple siproxd instances... + I dont know if this actually would work (multiple instances...)*/ + for (;(tmp2=strstr(tmp+1, myident)) != NULL;) { + tmp=tmp2; + } + tmp[0]='\0'; + } + break; + + /* Incoming Request */ + case REQTYP_INCOMING: + tmp=strstr(CID->number, myident); + if (tmp==NULL) { + /* no obscuring present yet, must be a new incoming call, do nothing */ + } else { + /* if BYE or CANCEL, check if obscuring present. + * if From-Tag different than in CID stored, modify back CID */ +DEBUGC(DBCLASS_PROXY, "tmp+myidentlen=[%s], FromTag=[%s]", + tmp+myidentlen, fromtag->gvalue); + + if (strcmp(tmp+myidentlen, fromtag->gvalue) != 0) { + tmp[0]='\0'; + } else { + /* if From-Tag equal to in CID stored, do nothing */ + } + } + break; + + /* Outgoing Response */ + case RESTYP_OUTGOING: + if (MSG_IS_RESPONSE_FOR(sipmsg,"BYE")) { + tmp=strstr(CID->number, myident); + if ((tmp==NULL)&& totag && totag->gvalue) { + /* no obscuring present yet, must be a new call, modify it */ + tmp=osip_malloc(strlen(CID->number) + myidentlen + + strlen(fromtag->gvalue) + 1); + sprintf(tmp,"%s%s%s",CID->number,myident,totag->gvalue); + osip_free(CID->number); + CID->number=tmp; + } else { + /* Obscuring is present, do nothing. */ + } +} +// tmp=strstr(CID->number, myident); +// /* modify it back if existing*/ +// if (tmp) { +// /* make sure to cut only the last marker - in case +// of multiple siproxd instances... */ +// for (;(tmp2=strstr(tmp+1, myident)) != NULL;) { +// tmp=tmp2; +// } +// tmp[0]='\0'; +// } + break; + + } + + DEBUGC(DBCLASS_PROXY, "sip_obscure_callid: new Callid#=%s",CID->number); + + return STS_SUCCESS; +} + + diff --git a/src/siproxd.h b/src/siproxd.h index 61ea7a8..31ba5a3 100644 --- a/src/siproxd.h +++ b/src/siproxd.h @@ -181,6 +181,7 @@ int sip_find_outbound_proxy(sip_ticket_t *ticket, struct in_addr *addr, int *port); /*X*/ int sip_find_direction(sip_ticket_t *ticket, int *urlidx); /*X*/ int sip_fixup_asterisk(char *buff, int *buflen); /*X*/ +int sip_obscure_callid(sip_ticket_t *ticket); /*X*/ /* readconf.c */ int read_config(char *name, int search); /*X*/