int eXosip_call_find_by_replaces (struct eXosip_t *excontext, char *replaces_str) { eXosip_call_t *jc = NULL; eXosip_dialog_t *jd = NULL; char *call_id; char *to_tag; char *from_tag; char *early_flag; char *semicolon; char *totag_str = (char *) "to-tag="; char *fromtag_str = (char *) "from-tag="; char *earlyonly_str = (char *) "early-only"; /* copy replaces string */ if (replaces_str == NULL) return OSIP_SYNTAXERROR; call_id = osip_strdup (replaces_str); if (call_id == NULL) return OSIP_NOMEM; /* parse replaces string */ to_tag = strstr (call_id, totag_str); from_tag = strstr (call_id, fromtag_str); early_flag = strstr (call_id, earlyonly_str); if ((to_tag == NULL) || (from_tag == NULL)) { osip_free (call_id); return OSIP_SYNTAXERROR; } to_tag += strlen (totag_str); from_tag += strlen (fromtag_str); while ((semicolon = strrchr (call_id, ';')) != NULL) { *semicolon = '\0'; } for (jc = excontext->j_calls; jc != NULL; jc = jc->next) { for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog == NULL) { /* skip */ } else if (((0 == strcmp (jd->d_dialog->call_id, call_id)) && (0 == strcmp (jd->d_dialog->remote_tag, to_tag)) && (0 == strcmp (jd->d_dialog->local_tag, from_tag))) || ((0 == strcmp (jd->d_dialog->call_id, call_id)) && (0 == strcmp (jd->d_dialog->local_tag, to_tag)) && (0 == strcmp (jd->d_dialog->remote_tag, from_tag)))) { /* This dialog match! */ if (jd->d_dialog->state == DIALOG_CONFIRMED && early_flag != NULL) { osip_free (call_id); return OSIP_WRONG_STATE; /* confirmed dialog but already answered with 486 */ } if (jd->d_dialog->state == DIALOG_EARLY && jd->d_dialog->type == CALLEE) { osip_free (call_id); return OSIP_BADPARAMETER; /* confirmed dialog but already answered with 481 */ } osip_free (call_id); return jc->c_id; /* match anyway */ } // for calls in ringing-state only compare Call-ID and from-tag // (contained in the from-tag field of the replaces-header !) // if the call had been forked, multiple different to-tags have been received // by the caller in the 101..199 provisional responses else if (((0 == strcmp (jd->d_dialog->call_id, call_id)) && (0 == strcmp (jd->d_dialog->local_tag, to_tag))) || ((0 == strcmp (jd->d_dialog->call_id, call_id)) && (0 == strcmp (jd->d_dialog->remote_tag, to_tag)))) { /* This dialog match! */ if (jd->d_dialog->state == DIALOG_CONFIRMED && early_flag != NULL) { osip_free (call_id); return OSIP_WRONG_STATE; /* confirmed dialog but already answered with 486 */ } osip_free (call_id); return jc->c_id; /* match anyway */ } } } osip_free (call_id); return OSIP_NOTFOUND; /* answer with 481 */ }