/** Create a new outbound object */ outbound_t * outbound_new(outbound_owner_t *owner, outbound_owner_vtable const *owner_methods, su_root_t *root, nta_agent_t *agent, char const *instance) { outbound_t *ob; if (!owner || !owner_methods || !root || !agent) return NULL; ob = su_home_clone((su_home_t *)owner, sizeof *ob); if (ob) { su_md5_t md5[1]; uint8_t digest[SU_MD5_DIGEST_SIZE]; su_guid_t guid[1]; ob->ob_owner = owner; ob->ob_oo = owner_methods; ob->ob_root = root; ob->ob_nta = agent; if (instance) ob->ob_instance = su_sprintf(ob->ob_home, "+sip.instance=\"<%s>\"", instance); ob->ob_reg_id = 0; outbound_peer_info(ob, NULL); /* Generate a random cookie (used as Call-ID) for us */ su_md5_init(md5); su_guid_generate(guid); if (instance) su_md5_update(md5, (void *)instance, strlen(instance)); su_md5_update(md5, (void *)guid, sizeof guid); su_md5_digest(md5, digest); token64_e(ob->ob_cookie, sizeof ob->ob_cookie, digest, sizeof digest); if (instance && !ob->ob_instance) su_home_unref(ob->ob_home), ob = NULL; } return ob; }
static int nua_notify_client_init_etag(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { #if SU_HAVE_EXPERIMENTAL nua_handle_t *nh = cr->cr_owner; struct notifier_usage *nu = nua_dialog_usage_private(cr->cr_usage); nua_server_request_t *sr; if (nu->nu_tag) su_free(nh->nh_home, nu->nu_tag), nu->nu_tag = NULL; nu->nu_no_body = 0; if (sip->sip_etag) { nu->nu_appl_etags = 1; nu->nu_tag = su_strdup(nh->nh_home, sip->sip_etag->g_string); } else if (!nu->nu_appl_etags && nu->nu_etags) { su_md5_t md5[1]; unsigned char digest[SU_MD5_DIGEST_SIZE]; sip_payload_t pl[1] = { SIP_PAYLOAD_INIT() }; char token[2 * 16]; su_md5_init(md5); if (sip->sip_payload) *pl = *sip->sip_payload; if (pl->pl_len) su_md5_update(md5, pl->pl_data, pl->pl_len); su_md5_update(md5, &pl->pl_len, sizeof(pl->pl_len)); if (sip->sip_content_type) su_md5_striupdate(md5, sip->sip_content_type->c_type); su_md5_digest(md5, digest); token64_e(token, sizeof token, digest, sizeof digest); token[(sizeof token) - 1] = '\0'; nu->nu_tag = su_strdup(nh->nh_home, token); } if (!nu->nu_requested || !nu->nu_tag) return 0; /* Check if SUBSCRIBE had matching suppression */ for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) if (sr->sr_usage == cr->cr_usage && sr->sr_method == sip_method_subscribe) break; if (sr) { sip_t const *sip = sr->sr_request.sip; sip_suppress_body_if_match_t *sbim; sip_suppress_notify_if_match_t *snim; if (cr->cr_usage->du_ready) { snim = sip_suppress_notify_if_match(sip); if (snim && su_casematch(snim->snim_tag, nu->nu_tag)) { if (nu->nu_requested > nu->nu_expires) nu->nu_expires = nu->nu_requested; nu->nu_requested = 0; return nua_client_return(cr, 202, "NOTIFY Suppressed", msg); } } sbim = sip_suppress_body_if_match(sip); if (sbim && su_casematch(sbim->sbim_tag, nu->nu_tag)) nu->nu_no_body = 1; } #endif return 0; }