/*! * \brief Get pointer to ucontact with given contact * \param _r record where to search the contacts * \param _c contact string * \param _callid callid * \param _path path * \param _cseq CSEQ number * \param _co found contact * \return 0 - found, 1 - not found, -1 - invalid found, * -2 - found, but to be skipped (same cseq) - don't forget to release_ucontact so dec. the ref counter */ int get_scontact(str* _c, str* _callid, str* _path, int _cseq, struct ucontact** _co) { unsigned int sl; ucontact_t* ptr; int with_callid = 0; ptr = 0; *_co = 0; sl = core_hash(_c, 0, contact_list->size); LM_DBG("looking for contact [%.*s] in slot %d\n", _c->len, _c->s, sl); get_act_time(); lock_contact_slot_i(sl); switch (matching_mode) { case CONTACT_ONLY: ptr = contact_match(sl, _c); break; case CONTACT_CALLID: ptr = contact_callid_match(sl, _c, _callid); with_callid = 1; break; case CONTACT_PATH: ptr = contact_path_match(sl, _c, _path); break; case CONTACT_PORT_IP_ONLY: ptr = contact_port_ip_match(sl, _c); break; default: LM_CRIT("unknown matching_mode %d\n", matching_mode); unlock_contact_slot_i(sl); return -1; } if (ptr) { LM_DBG("have partially found a contact\n"); /* found -> check callid and cseq */ if (!with_callid || (_callid && ptr->callid.len == _callid->len && memcmp(_callid->s, ptr->callid.s, _callid->len) == 0)) { if (_cseq < ptr->cseq) { LM_DBG("cseq less than expected\n"); } } LM_DBG("contact found p=[%p], aor:[%.*s] and contact:[%.*s], state [%d]\n", ptr, ptr->aor.len, ptr->aor.s, ptr->c.len, ptr->c.s, ptr->state); ref_contact_unsafe(ptr); *_co = ptr; unlock_contact_slot_i(sl); /*TODO: we probably need to ref count here..... */ return 0; } unlock_contact_slot_i(sl); return 1; }
/*! + * \brief Match a contact record to a contact string and path + * \param ptr contact record + * \param _c contact string + * \param _path path + * \return ptr on successfull match, 0 when they not match + */ static inline struct ucontact* contact_path_match(ucontact_t* ptr, str* _c, str *_path) { /* if no path is preset (in REGISTER request) or use_path is not configured in registrar module, default to contact_match() */ if (_path == NULL) return contact_match(ptr, _c); while (ptr) { if ((_c->len == ptr->c.len) && (_path->len == ptr->path.len) && !memcmp(_c->s, ptr->c.s, _c->len) && !memcmp(_path->s, ptr->path.s, _path->len) ) { return ptr; } ptr = ptr->next; } return 0; }
/*! * \brief Get pointer to ucontact with given contact * \param _r record where to search the contacts * \param _c contact string * \param _callid callid * \param _path path * \param _cseq CSEQ number * \param _co found contact * \return 0 - found, 1 - not found, -1 - invalid found, * -2 - found, but to be skipped (same cseq) */ int get_ucontact(impurecord_t* _r, str* _c, str* _callid, str* _path, int _cseq, struct ucontact** _co) { ucontact_t* ptr; int no_callid; ptr = 0; no_callid = 0; *_co = 0; switch (matching_mode) { case CONTACT_ONLY: ptr = contact_match(_r->contacts, _c); break; case CONTACT_CALLID: ptr = contact_callid_match(_r->contacts, _c, _callid); no_callid = 1; break; case CONTACT_PATH: ptr = contact_path_match(_r->contacts, _c, _path); break; case CONTACT_PORT_IP_ONLY: ptr = contact_port_ip_match(_r->contacts, _c); break; default: LM_CRIT("unknown matching_mode %d\n", matching_mode); return -1; } if (ptr) { /* found -> check callid and cseq */ if (no_callid || (ptr->callid.len == _callid->len && memcmp(_callid->s, ptr->callid.s, _callid->len) == 0)) { if (_cseq < ptr->cseq) return -1; if (_cseq == ptr->cseq) { get_act_time(); return (ptr->last_modified + cseq_delay > act_time) ? -2 : -1; } } *_co = ptr; return 0; } return 1; }
/*! + * \brief Match a contact record to a contact string and path + * \param ptr contact record + * \param _c contact string + * \param _path path + * \return ptr on successfull match, 0 when they not match + */ static inline struct ucontact* contact_path_match(unsigned int slot, str* _c, str *_path) { ucontact_t* ptr = contact_list->slot[slot].first; /* if no path is preset (in REGISTER request) or use_path is not configured in registrar module, default to contact_match() */ if (_path == NULL) return contact_match(slot, _c); while (ptr) { if ((_c->len == ptr->c.len) && (_path->len == ptr->path.len) && !memcmp(_c->s, ptr->c.s, _c->len) && !memcmp(_path->s, ptr->path.s, _path->len) && VALID_CONTACT(ptr, act_time) ) { return ptr; } ptr = ptr->next; } return 0; }