diff --git a/modules/mid_registrar/save.c b/modules/mid_registrar/save.c index 6ac2ac73c45..1799cf12ee7 100644 --- a/modules/mid_registrar/save.c +++ b/modules/mid_registrar/save.c @@ -1009,7 +1009,7 @@ int append_contacts(ucontact_t *contacts, struct sip_msg *msg) return 0; } -int trim_contacts(urecord_t *r, int trims) +int trim_contacts(urecord_t *r, int trims, const struct ct_match *match) { ucontact_t *uc; @@ -1020,7 +1020,7 @@ int trim_contacts(urecord_t *r, int trims) LM_DBG("overflow on inserting new contact -> removing <%.*s>\n", uc->c.len, uc->c.s); - if (ul.delete_ucontact(r, uc, 0) != 0) { + if (ul.delete_ucontact(r, uc, match, 0) != 0) { LM_ERR("failed to remove contact, aor: %.*s\n", r->aor.len, r->aor.s); return -1; @@ -1358,13 +1358,14 @@ static inline int save_restore_rpl_contacts(struct sip_msg *req, goto error; } - if (trim_contacts(r, vct - mri->max_contacts + 1) != 0) + if (trim_contacts(r, vct - mri->max_contacts + 1, &mri->cmatch)) goto error; } LM_DBG("INSERTING contact with expires %lu\n", ci->expires); - if (ul.insert_ucontact(r, &ctmap->req_ct_uri, ci, &c, 0) < 0) { + if (ul.insert_ucontact(r, &ctmap->req_ct_uri, ci, + &mri->cmatch, 0, &c) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); goto error; @@ -1389,7 +1390,7 @@ static inline int save_restore_rpl_contacts(struct sip_msg *req, } was_valid = VALID_CONTACT(c, get_act_time()); - if (ul.delete_ucontact(r, c, 0) < 0) { + if (ul.delete_ucontact(r, c, &mri->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to delete contact\n"); goto error; @@ -1412,7 +1413,7 @@ static inline int save_restore_rpl_contacts(struct sip_msg *req, goto error; } - if (trim_contacts(r, vct - mri->max_contacts) != 0) + if (trim_contacts(r, vct - mri->max_contacts, &mri->cmatch)) goto error; } @@ -1423,7 +1424,7 @@ static inline int save_restore_rpl_contacts(struct sip_msg *req, goto error; } - if (ul.update_ucontact(r, c, ci, 0) < 0) { + if (ul.update_ucontact(r, c, ci, &mri->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto error; @@ -1619,13 +1620,14 @@ static inline int save_restore_req_contacts(struct sip_msg *req, goto out_clear_err; } - if (trim_contacts(r, vct - mri->max_contacts + 1) != 0) + if (trim_contacts(r, vct - mri->max_contacts + 1, &mri->cmatch)) goto out_clear_err; } LM_DBG("INSERTING contact with expires %lu\n", ci->expires); - if (ul.insert_ucontact( r, &ctmap->req_ct_uri, ci, &c, 0) < 0) { + if (ul.insert_ucontact( r, &ctmap->req_ct_uri, ci, &mri->cmatch, + 0, &c) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); goto out_clear_err; @@ -1643,7 +1645,7 @@ static inline int save_restore_req_contacts(struct sip_msg *req, /* delete expired or stale contact (not present on main reg) */ if (ctmap->expires == 0 || !_c) { was_valid = VALID_CONTACT(c, get_act_time()); - if (ul.delete_ucontact(r, c, 0) < 0) { + if (ul.delete_ucontact(r, c, &mri->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto out_clear_err; @@ -1664,7 +1666,7 @@ static inline int save_restore_req_contacts(struct sip_msg *req, goto out_clear_err; } - if (trim_contacts(r, vct - mri->max_contacts) != 0) + if (trim_contacts(r, vct - mri->max_contacts, &mri->cmatch)) goto out_clear_err; } @@ -1674,7 +1676,7 @@ static inline int save_restore_req_contacts(struct sip_msg *req, goto out_clear_err; } - if (ul.update_ucontact( r, c, ci, 0) < 0) { + if (ul.update_ucontact( r, c, ci, &mri->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto out_clear_err; @@ -2226,7 +2228,7 @@ static int process_contacts_by_ct(struct sip_msg *msg, urecord_t *urec, if (!ul.put_ucontact_key(c, &ul_key_last_cseq, &value)) LM_ERR("failed to update CSeq - oom?\n"); - if (ul.update_ucontact(urec, c, ci, 0) < 0) { + if (ul.update_ucontact(urec, c, ci, &_sctx->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); return -1; @@ -2377,7 +2379,7 @@ static int process_contacts_by_aor(struct sip_msg *req, urecord_t *urec, return 1; } - if (ul.delete_ucontact(urec, c, 0) < 0) { + if (ul.delete_ucontact(urec, c, &_sctx->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; return -1; } @@ -2397,7 +2399,7 @@ static int process_contacts_by_aor(struct sip_msg *req, urecord_t *urec, return -1; } - if (trim_contacts(urec, vct - _sctx->max_contacts) != 0) + if (trim_contacts(urec, vct - _sctx->max_contacts, &_sctx->cmatch)) return -1; } @@ -2417,7 +2419,7 @@ static int process_contacts_by_aor(struct sip_msg *req, urecord_t *urec, return -1; } - if (ul.update_ucontact(urec, c, ci, 0) < 0) { + if (ul.update_ucontact(urec, c, ci, &_sctx->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); return -1; @@ -2435,7 +2437,7 @@ static int process_contacts_by_aor(struct sip_msg *req, urecord_t *urec, return -1; } - if (trim_contacts(urec, vct - _sctx->max_contacts + 1) != 0) + if (trim_contacts(urec, vct - _sctx->max_contacts + 1, &_sctx->cmatch)) return -1; } @@ -2450,7 +2452,8 @@ static int process_contacts_by_aor(struct sip_msg *req, urecord_t *urec, } ci->expires_out = e_out; - if (ul.insert_ucontact(urec, &ct->uri, ci, &c, 0) < 0) { + if (ul.insert_ucontact(urec, &ct->uri, ci, &_sctx->cmatch, + 0, &c) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); return -1; diff --git a/modules/registrar/save.c b/modules/registrar/save.c index 9940067bde9..a3831add6aa 100644 --- a/modules/registrar/save.c +++ b/modules/registrar/save.c @@ -244,7 +244,7 @@ static inline int insert_contacts(struct sip_msg* _m, contact_t* _c, rerrno = R_INTERNAL; goto error; } - if (ul.delete_ucontact( r, r->contacts, 0)!=0) { + if (ul.delete_ucontact( r, r->contacts, &_sctx->cmatch, 0)!=0) { LM_ERR("failed to remove contact\n"); rerrno = R_INTERNAL; goto error; @@ -279,13 +279,14 @@ static inline int insert_contacts(struct sip_msg* _m, contact_t* _c, if ( r->contacts==0 || ul.get_ucontact(r, &_c->uri, ci->callid, ci->cseq+1, &_sctx->cmatch, &c)!=0 ){ - if (ul.insert_ucontact( r, &_c->uri, ci, &c, 0) < 0) { + if (ul.insert_ucontact( r, &_c->uri, ci, &_sctx->cmatch, + 0, &c) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); goto error; } } else { - if (ul.update_ucontact( r, c, ci, 0) < 0) { + if (ul.update_ucontact( r, c, ci, &_sctx->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto error; @@ -429,7 +430,7 @@ static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, } LM_DBG("overflow on inserting new contact -> removing " "<%.*s>\n", c_last->c.len, c_last->c.s); - if (ul.delete_ucontact( _r, c_last, 0)!=0) { + if (ul.delete_ucontact( _r, c_last, &_sctx->cmatch, 0)!=0) { LM_ERR("failed to remove contact\n"); goto error; } @@ -449,7 +450,8 @@ static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, goto error; } - if (ul.insert_ucontact( _r, &_c->uri, ci, &c, 0) < 0) { + if (ul.insert_ucontact( _r, &_c->uri, ci, &_sctx->cmatch, + 0, &c) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); goto error; @@ -466,7 +468,7 @@ static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, c->flags &= ~FL_MEM; } - if (ul.delete_ucontact(_r, c, 0) < 0) { + if (ul.delete_ucontact(_r, c, &_sctx->cmatch, 0) < 0) { rerrno = R_UL_DEL_C; LM_ERR("failed to delete contact\n"); goto error; @@ -496,7 +498,7 @@ static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, } LM_DBG("overflow on update -> removing contact " "<%.*s>\n", c_last->c.len, c_last->c.s); - if (ul.delete_ucontact( _r, c_last, 0)!=0) { + if (ul.delete_ucontact( _r, c_last, &_sctx->cmatch, 0)!=0) { LM_ERR("failed to remove contact\n"); goto error; } @@ -516,7 +518,7 @@ static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, goto error; } - if (ul.update_ucontact(_r, c, ci, 0) < 0) { + if (ul.update_ucontact(_r, c, ci, &_sctx->cmatch, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto error; @@ -1010,7 +1012,7 @@ int _remove(struct sip_msg *msg, void *udomain, str *aor_uri, str *match_ct, continue; } - ul.delete_ucontact(record, contact, 0); + ul.delete_ucontact(record, contact, NULL, 0); } ul.release_urecord(record, 0); diff --git a/modules/registrar/test/test.c b/modules/registrar/test/test.c index cf82bf31ae6..0f353b31e8b 100644 --- a/modules/registrar/test/test.c +++ b/modules/registrar/test/test.c @@ -77,7 +77,7 @@ static void test_lookup(void) fill_ucontact_info(&ci); ci.methods = METHOD_UNDEF; - ok(ul.insert_ucontact(r, &ct2, &ci, &c, 0) == 0, "insert Contact"); + ok(ul.insert_ucontact(r, &ct2, &ci, NULL, 1, &c) == 0, "insert Contact"); ul.unlock_udomain(d, &aor); ok(reg_lookup(&msg, d, _str(""), NULL) == LOOKUP_OK, "lookup-2"); @@ -93,17 +93,17 @@ static void test_lookup(void) set_ruri(&msg, &aor_ruri); ok(reg_lookup(&msg, d, _str("m"), NULL) == LOOKUP_OK, "lookup-5"); - ok(ul.delete_ucontact(r, c, 0) == 0, "delete ucontact"); + ok(ul.delete_ucontact(r, c, NULL, 0) == 0, "delete ucontact"); fill_ucontact_info(&ci); ci.flags |= FL_PN_ON; /* this is needed until we rewrite to call save() */ - ok(ul.insert_ucontact(r, &ct1, &ci, &c, 0) == 0, "insert ct1 (PN)"); + ok(ul.insert_ucontact(r, &ct1, &ci, NULL, 1, &c) == 0, "insert ct1 (PN)"); set_ruri(&msg, &aor_ruri); ok(reg_lookup(&msg, d, _str(""), NULL) == LOOKUP_PN_SENT, "lookup-6"); fill_ucontact_info(&ci); - ok(ul.insert_ucontact(r, &ct2, &ci, &c, 0) == 0, "insert ct2 (normal)"); + ok(ul.insert_ucontact(r, &ct2, &ci, NULL, 1, &c) == 0, "insert ct2 (normal)"); set_ruri(&msg, &aor_ruri); ok(reg_lookup(&msg, d, _str(""), NULL) == LOOKUP_OK, "lookup-7"); diff --git a/modules/usrloc/dlist.c b/modules/usrloc/dlist.c index f7f20fe6985..570980c44ad 100644 --- a/modules/usrloc/dlist.c +++ b/modules/usrloc/dlist.c @@ -1205,7 +1205,7 @@ int delete_ucontact_from_coords(udomain_t *d, ucontact_coords ct_coords, } if (!skip_replication && location_cluster) - replicate_ucontact_delete(r, c); + replicate_ucontact_delete(r, c, NULL); if (exists_ulcb_type(UL_CONTACT_DELETE)) { run_ul_callbacks( UL_CONTACT_DELETE, c); diff --git a/modules/usrloc/ucontact.c b/modules/usrloc/ucontact.c index 21ec4e3fff5..93f40658522 100644 --- a/modules/usrloc/ucontact.c +++ b/modules/usrloc/ucontact.c @@ -966,7 +966,7 @@ static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c) * Update ucontact with new values */ int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci, - char skip_replication) + const struct ct_match *match, char skip_replication) { int ret, persist_kv_store = 1; @@ -986,7 +986,7 @@ int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci, else persist_kv_store = 0; - replicate_ucontact_update(_r, _c); + replicate_ucontact_update(_r, _c, match); } /* run callbacks for UPDATE event */ diff --git a/modules/usrloc/ucontact.h b/modules/usrloc/ucontact.h index b02146e177f..5061b3d64c4 100644 --- a/modules/usrloc/ucontact.h +++ b/modules/usrloc/ucontact.h @@ -300,7 +300,7 @@ struct urecord; * Update ucontact with new values */ int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci, - char skip_replication); + const struct ct_match *match, char skip_replication); /*! \brief * Fetch a key from the contact-level storage diff --git a/modules/usrloc/udomain.c b/modules/usrloc/udomain.c index ce3e5349340..7484f341e7e 100644 --- a/modules/usrloc/udomain.c +++ b/modules/usrloc/udomain.c @@ -1525,7 +1525,7 @@ int delete_urecord(udomain_t* _d, str* _aor, struct urecord* _r, while(c) { t = c; c = c->next; - if (delete_ucontact(_r, t, skip_replication) < 0) { + if (delete_ucontact(_r, t, NULL, skip_replication) < 0) { LM_ERR("deleting contact failed\n"); return -1; } diff --git a/modules/usrloc/ul_cluster.c b/modules/usrloc/ul_cluster.c index 0f57a46e629..cd81c878333 100644 --- a/modules/usrloc/ul_cluster.c +++ b/modules/usrloc/ul_cluster.c @@ -154,7 +154,52 @@ void replicate_urecord_delete(urecord_t *r) bin_free_packet(&packet); } -void bin_push_contact(bin_packet_t *packet, urecord_t *r, ucontact_t *c) +void bin_push_ctmatch(bin_packet_t *packet, const struct ct_match *match) +{ + str_list *param; + int np = 0; + + bin_push_int(packet, match->mode); + if (match->mode != CT_MATCH_PARAMS) + return; + + for (param = match->match_params; param; param = param->next, np++) {} + + bin_push_int(packet, np); + for (param = match->match_params; param; param = param->next) + bin_push_str(packet, ¶m->s); +} + +/* NOTICE: remember to free @match->match_params when done with it! */ +void bin_pop_ctmatch(bin_packet_t *packet, struct ct_match *match) +{ + int np; + + memset(match, 0, sizeof *match); + + bin_pop_int(packet, &match->mode); + if (match->mode != CT_MATCH_PARAMS) + return; + + bin_pop_int(packet, &np); + + for (; np > 0; np--) { + str_list *param = pkg_malloc(sizeof *param); + if (!param) { + LM_ERR("oom\n"); + free_pkg_str_list(match->match_params); + *match = (struct ct_match){CT_MATCH_CONTACT_CALLID, NULL}; + return; + } + memset(param, 0, sizeof *param); + + bin_pop_str(packet, ¶m->s); + add_last(param, match->match_params); + } +} + +void bin_push_contact(bin_packet_t *packet, urecord_t *r, ucontact_t *c, + const struct ct_match *match) { str st; @@ -194,9 +239,12 @@ void bin_push_contact(bin_packet_t *packet, urecord_t *r, ucontact_t *c) st = store_serialize(c->kv_storage); bin_push_str(packet, &st); store_free_buffer(&st); + + bin_push_ctmatch(packet, match); } -void replicate_ucontact_insert(urecord_t *r, str *contact, ucontact_t *c) +void replicate_ucontact_insert(urecord_t *r, str *contact, ucontact_t *c, + const struct ct_match *match) { int rc; bin_packet_t packet; @@ -207,7 +255,7 @@ void replicate_ucontact_insert(urecord_t *r, str *contact, ucontact_t *c) return; } - bin_push_contact(&packet, r, c); + bin_push_contact(&packet, r, c, match); if (cluster_mode == CM_FEDERATION_CACHEDB) rc = clusterer_api.send_all_having(&packet, location_cluster, @@ -235,7 +283,8 @@ void replicate_ucontact_insert(urecord_t *r, str *contact, ucontact_t *c) bin_free_packet(&packet); } -void replicate_ucontact_update(urecord_t *r, ucontact_t *ct) +void replicate_ucontact_update(urecord_t *r, ucontact_t *ct, + const struct ct_match *match) { str st; int rc; @@ -283,6 +332,8 @@ void replicate_ucontact_update(urecord_t *r, ucontact_t *ct) st.len = sizeof ct->contact_id; bin_push_str(&packet, &st); + bin_push_ctmatch(&packet, match); + if (cluster_mode == CM_FEDERATION_CACHEDB) rc = clusterer_api.send_all_having(&packet, location_cluster, NODE_CMP_EQ_SIP_ADDR); @@ -309,8 +360,10 @@ void replicate_ucontact_update(urecord_t *r, ucontact_t *ct) bin_free_packet(&packet); } -void replicate_ucontact_delete(urecord_t *r, ucontact_t *c) +void replicate_ucontact_delete(urecord_t *r, ucontact_t *c, + const struct ct_match *_match) { + struct ct_match match; int rc; bin_packet_t packet; @@ -320,11 +373,17 @@ void replicate_ucontact_delete(urecord_t *r, ucontact_t *c) return; } + if (!_match) + match = (struct ct_match){CT_MATCH_CONTACT_CALLID, NULL}; + else + match = *_match; + bin_push_str(&packet, r->domain); bin_push_str(&packet, &r->aor); bin_push_str(&packet, &c->c); bin_push_str(&packet, &c->callid); bin_push_int(&packet, c->cseq); + bin_push_ctmatch(&packet, &match); if (cluster_mode == CM_FEDERATION_CACHEDB) rc = clusterer_api.send_all_having(&packet, location_cluster, @@ -449,7 +508,8 @@ static int receive_ucontact_insert(bin_packet_t *packet) int rc, port, proto, sl; unsigned short _, clabel; unsigned int rlabel; - struct ct_match cmatch = {CT_MATCH_CONTACT_CALLID, NULL}; + struct ct_match cmatch = {CT_MATCH_NONE, NULL}; + short pkg_ver = get_bin_pkg_version(packet); memset(&ci, 0, sizeof ci); @@ -519,6 +579,11 @@ static int receive_ucontact_insert(bin_packet_t *packet) bin_pop_str(packet, &kv_str); ci.packed_kv_storage = &kv_str; + if (pkg_ver <= UL_BIN_V2) + cmatch = (struct ct_match){CT_MATCH_CONTACT_CALLID, NULL}; + else + bin_pop_ctmatch(packet, &cmatch); + if (skip_replicated_db_ops) ci.flags |= FL_MEM; @@ -551,6 +616,7 @@ static int receive_ucontact_insert(bin_packet_t *packet) rc = get_ucontact(record, &contact_str, &callid, ci.cseq, &cmatch, &contact); + switch (rc) { case -2: /* received data is consistent with what we have */ @@ -559,14 +625,14 @@ static int receive_ucontact_insert(bin_packet_t *packet) break; case 0: /* received data is newer than what we have */ - if (update_ucontact(record, contact, &ci, 1) != 0) { + if (update_ucontact(record, contact, &ci, NULL, 1) != 0) { LM_ERR("failed to update ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } break; case 1: - if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { + if (insert_ucontact(record, &contact_str, &ci, NULL, 1, &contact) != 0) { LM_ERR("failed to insert ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; @@ -575,9 +641,12 @@ static int receive_ucontact_insert(bin_packet_t *packet) } unlock_udomain(domain, &aor); + + free_pkg_str_list(cmatch.match_params); return 0; error: + free_pkg_str_list(cmatch.match_params); LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; @@ -594,7 +663,8 @@ static int receive_ucontact_update(bin_packet_t *packet) int port, proto, rc, sl; unsigned short _, clabel; unsigned int rlabel; - struct ct_match cmatch = {CT_MATCH_CONTACT_CALLID, NULL}; + struct ct_match cmatch = {CT_MATCH_NONE, NULL}; + short pkg_ver = get_bin_pkg_version(packet); memset(&ci, 0, sizeof ci); @@ -669,6 +739,11 @@ static int receive_ucontact_update(bin_packet_t *packet) unpack_indexes(ci.contact_id, &_, &rlabel, &clabel); + if (pkg_ver <= UL_BIN_V2) + cmatch = (struct ct_match){CT_MATCH_CONTACT_CALLID, NULL}; + else + bin_pop_ctmatch(packet, &cmatch); + lock_udomain(domain, &aor); /* failure in retrieving a urecord may be ok, because packet order in UDP @@ -688,7 +763,7 @@ static int receive_ucontact_update(bin_packet_t *packet) if (domain->table[sl].next_label <= record->label) domain->table[sl].next_label = record->label + 1; - if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { + if (insert_ucontact(record, &contact_str, &ci, NULL, 1, &contact) != 0) { LM_ERR("failed (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); goto error; @@ -703,7 +778,7 @@ static int receive_ucontact_update(bin_packet_t *packet) LM_INFO("contact '%.*s' not found, inserting new (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); - if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) { + if (insert_ucontact(record, &contact_str, &ci, NULL, 1, &contact) != 0) { LM_ERR("failed to insert ucontact (ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); @@ -714,7 +789,7 @@ static int receive_ucontact_update(bin_packet_t *packet) record->next_clabel = CLABEL_INC_AND_TEST(clabel); } else if (rc == 0) { - if (update_ucontact(record, contact, &ci, 1) != 0) { + if (update_ucontact(record, contact, &ci, NULL, 1) != 0) { LM_ERR("failed to update ucontact '%.*s' (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); @@ -726,9 +801,11 @@ static int receive_ucontact_update(bin_packet_t *packet) unlock_udomain(domain, &aor); + free_pkg_str_list(cmatch.match_params); return 0; error: + free_pkg_str_list(cmatch.match_params); LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; @@ -741,7 +818,8 @@ static int receive_ucontact_delete(bin_packet_t *packet) ucontact_t *contact; str d, aor, contact_str, callid; int cseq, rc; - struct ct_match cmatch = {CT_MATCH_CONTACT_CALLID, NULL}; + struct ct_match cmatch = {CT_MATCH_NONE, NULL}; + short pkg_ver = get_bin_pkg_version(packet); bin_pop_str(packet, &d); bin_pop_str(packet, &aor); @@ -754,6 +832,11 @@ static int receive_ucontact_delete(bin_packet_t *packet) bin_pop_str(packet, &callid); bin_pop_int(packet, &cseq); + if (pkg_ver <= UL_BIN_V2) + cmatch = (struct ct_match){CT_MATCH_CONTACT_CALLID, NULL}; + else + bin_pop_ctmatch(packet, &cmatch); + if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto error; @@ -768,7 +851,7 @@ static int receive_ucontact_delete(bin_packet_t *packet) LM_INFO("failed to fetch local urecord - ignoring request " "(ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); - return 0; + goto out; } /* simply specify a higher cseq and completely avoid any complications */ @@ -784,7 +867,7 @@ static int receive_ucontact_delete(bin_packet_t *packet) if (skip_replicated_db_ops) contact->flags |= FL_MEM; - if (delete_ucontact(record, contact, 1) != 0) { + if (delete_ucontact(record, contact, NULL, 1) != 0) { LM_ERR("failed to delete ucontact '%.*s' (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); @@ -793,9 +876,12 @@ static int receive_ucontact_delete(bin_packet_t *packet) unlock_udomain(domain, &aor); +out: + free_pkg_str_list(cmatch.match_params); return 0; error: + free_pkg_str_list(cmatch.match_params); LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; @@ -825,36 +911,48 @@ void receive_binary_packets(bin_packet_t *packet) bin_packet_t *pkt; for (pkt = packet; pkt; pkt = pkt->next) { + /* Supported smooth BIN transitions: + UL_BIN_V2 -> UL_BIN_V3: the "cmatch" has been added + (assume: CT_MATCH_CONTACT_CALLID if not present) + */ + short ver = get_bin_pkg_version(pkt); + LM_DBG("received a binary packet [%d]!\n", pkt->type); switch (pkt->type) { case REPL_URECORD_INSERT: - ensure_bin_version(pkt, UL_BIN_VERSION); + if (ver != UL_BIN_V2) + ensure_bin_version(pkt, UL_BIN_VERSION); rc = receive_urecord_insert(pkt); break; case REPL_URECORD_DELETE: - ensure_bin_version(pkt, UL_BIN_VERSION); + if (ver != UL_BIN_V2) + ensure_bin_version(pkt, UL_BIN_VERSION); rc = receive_urecord_delete(pkt); break; case REPL_UCONTACT_INSERT: - ensure_bin_version(pkt, UL_BIN_VERSION); + if (ver != UL_BIN_V2) + ensure_bin_version(pkt, UL_BIN_VERSION); rc = receive_ucontact_insert(pkt); break; case REPL_UCONTACT_UPDATE: - ensure_bin_version(pkt, UL_BIN_VERSION); + if (ver != UL_BIN_V2) + ensure_bin_version(pkt, UL_BIN_VERSION); rc = receive_ucontact_update(pkt); break; case REPL_UCONTACT_DELETE: - ensure_bin_version(pkt, UL_BIN_VERSION); + if (ver != UL_BIN_V2) + ensure_bin_version(pkt, UL_BIN_VERSION); rc = receive_ucontact_delete(pkt); break; case SYNC_PACKET_TYPE: - _ensure_bin_version(pkt, UL_BIN_VERSION, "usrloc sync packet"); + if (ver != UL_BIN_V2) + _ensure_bin_version(pkt, UL_BIN_VERSION, "usrloc sync packet"); rc = receive_sync_packet(pkt); break; @@ -870,6 +968,7 @@ void receive_binary_packets(bin_packet_t *packet) static int receive_sync_request(int node_id) { + struct ct_match cmatch = {CT_MATCH_CONTACT_CALLID, NULL}; bin_packet_t *sync_packet; dlist_t *dl; udomain_t *dom; @@ -909,7 +1008,7 @@ static int receive_sync_request(int node_id) /* ucontact in this chunk */ bin_push_int(sync_packet, 1); - bin_push_contact(sync_packet, r, c); + bin_push_contact(sync_packet, r, c, &cmatch); } } unlock_ulslot(dom, i); diff --git a/modules/usrloc/ul_cluster.h b/modules/usrloc/ul_cluster.h index 29f0869f4ec..97e183d69fc 100644 --- a/modules/usrloc/ul_cluster.h +++ b/modules/usrloc/ul_cluster.h @@ -38,7 +38,10 @@ #define REPL_UCONTACT_UPDATE 4 #define REPL_UCONTACT_DELETE 5 -#define UL_BIN_VERSION 2 +#define UL_BIN_V2 2 +#define UL_BIN_V3 3 // added "cmatch" (default: CT_MATCH_CONTACT_CALLID) + +#define UL_BIN_VERSION UL_BIN_V3 extern int location_cluster; extern struct clusterer_binds clusterer_api; @@ -55,9 +58,12 @@ int ul_init_cluster(void); /* duplicate local events to other OpenSIPS instances */ void replicate_urecord_insert(urecord_t *r); void replicate_urecord_delete(urecord_t *r); -void replicate_ucontact_insert(urecord_t *r, str *contact, ucontact_t *c); -void replicate_ucontact_update(urecord_t *r, ucontact_t *ct); -void replicate_ucontact_delete(urecord_t *r, ucontact_t *c); +void replicate_ucontact_insert(urecord_t *r, str *contact, ucontact_t *c, + const struct ct_match *match); +void replicate_ucontact_update(urecord_t *r, ucontact_t *ct, + const struct ct_match *match); +void replicate_ucontact_delete(urecord_t *r, ucontact_t *c, + const struct ct_match *match); void receive_binary_packets(bin_packet_t *packet); void receive_cluster_event(enum clusterer_event ev, int node_id); diff --git a/modules/usrloc/ul_mi.c b/modules/usrloc/ul_mi.c index ae045613f96..21a5a0de678 100644 --- a/modules/usrloc/ul_mi.c +++ b/modules/usrloc/ul_mi.c @@ -320,7 +320,7 @@ mi_response_t *mi_usrloc_rm_contact(const mi_params_t *params, return init_mi_error(404, MI_SSTR("Contact not found")); } - if (delete_ucontact(rec, con, 0) < 0) { + if (delete_ucontact(rec, con, NULL, 0) < 0) { unlock_udomain( dom, &aor); return 0; } @@ -468,6 +468,7 @@ mi_response_t *mi_usrloc_flush(const mi_params_t *params, mi_response_t *mi_usrloc_add(const mi_params_t *params, struct mi_handler *async_hdl) { + struct ct_match cmatch = {CT_MATCH_CONTACT_CALLID, NULL}; ucontact_info_t ci; urecord_t* r; ucontact_t* c; @@ -539,13 +540,13 @@ mi_response_t *mi_usrloc_add(const mi_params_t *params, /* update contact record */ ci.callid = &mi_ul_cid; ci.cseq = c->cseq; - if (update_ucontact( r, c, &ci, 0) < 0) + if (update_ucontact( r, c, &ci, &cmatch, 0) < 0) goto release_error; } else { /* new contact record */ ci.callid = &mi_ul_cid; ci.cseq = MI_UL_CSEQ; - if ( insert_ucontact( r, &contact, &ci, &c, 0) < 0 ) + if ( insert_ucontact( r, &contact, &ci, &cmatch, 0, &c) < 0 ) goto release_error; } diff --git a/modules/usrloc/urecord.c b/modules/usrloc/urecord.c index e78b52b086a..84bf438021c 100644 --- a/modules/usrloc/urecord.c +++ b/modules/usrloc/urecord.c @@ -849,7 +849,7 @@ void release_urecord(urecord_t* _r, char skip_replication) * into urecord */ int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci, - ucontact_t** _c, char skip_replication) + const struct ct_match *match, char skip_replication, ucontact_t** _c) { int first_contact = !_r->contacts; @@ -875,7 +875,7 @@ int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci, } if (!skip_replication && have_data_replication()) - replicate_ucontact_insert(_r, _contact, *_c); + replicate_ucontact_insert(_r, _contact, *_c, match); if (exists_ulcb_type(UL_CONTACT_INSERT)) run_ul_callbacks(UL_CONTACT_INSERT, *_c); @@ -901,10 +901,11 @@ int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci, /*! \brief * Delete ucontact from urecord */ -int delete_ucontact(urecord_t* _r, struct ucontact* _c, char skip_replication) +int delete_ucontact(urecord_t* _r, struct ucontact* _c, + const struct ct_match *match, char skip_replication) { if (!skip_replication && have_data_replication()) - replicate_ucontact_delete(_r, _c); + replicate_ucontact_delete(_r, _c, match); if (exists_ulcb_type(UL_CONTACT_DELETE)) run_ul_callbacks(UL_CONTACT_DELETE, _c); @@ -1019,8 +1020,9 @@ next_contact:; * -2 - found, but to be skipped (same cseq) */ int get_ucontact(urecord_t* _r, str* _c, str* _callid, int _cseq, - struct ct_match *match, struct ucontact** _co) + const struct ct_match *_match, struct ucontact** _co) { + struct ct_match match = *_match; ucontact_t* ptr; int no_callid; @@ -1028,11 +1030,11 @@ int get_ucontact(urecord_t* _r, str* _c, str* _callid, int _cseq, no_callid = 0; *_co = 0; - if (match->mode == CT_MATCH_NONE) - match->mode = matching_mode; + if (match.mode == CT_MATCH_NONE) + match.mode = matching_mode; - LM_DBG("using ct matching mode %d\n", match->mode); - switch (match->mode) { + LM_DBG("using ct matching mode %d\n", match.mode); + switch (match.mode) { case CT_MATCH_CONTACT_ONLY: ptr = contact_match(_r->contacts, _c); break; @@ -1041,10 +1043,10 @@ int get_ucontact(urecord_t* _r, str* _c, str* _callid, int _cseq, no_callid = 1; break; case CT_MATCH_PARAMS: - ptr = contact_params_match(_r->contacts, _c, match->match_params); + ptr = contact_params_match(_r->contacts, _c, match.match_params); break; default: - LM_CRIT("unknown contact matching mode %d\n", match->mode); + LM_CRIT("unknown contact matching mode %d\n", match.mode); return -1; } diff --git a/modules/usrloc/urecord.h b/modules/usrloc/urecord.h index 2346899729b..d5800efaebe 100644 --- a/modules/usrloc/urecord.h +++ b/modules/usrloc/urecord.h @@ -125,21 +125,22 @@ void release_urecord(urecord_t* _r, char skip_replication); /* * Insert new contact */ -int insert_ucontact(urecord_t* _r, str* _contact, - ucontact_info_t* _ci, ucontact_t** _c, char skip_replication); +int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci, + const struct ct_match *match, char skip_replication, ucontact_t** _c); /* * Delete ucontact from urecord */ -int delete_ucontact(urecord_t* _r, struct ucontact* _c, char skip_replication); +int delete_ucontact(urecord_t* _r, struct ucontact* _c, + const struct ct_match *match, char skip_replication); /* * Get pointer to ucontact with given contact */ int get_ucontact(urecord_t* _r, str* _c, str* _callid, int _cseq, - struct ct_match *match, struct ucontact** _co); + const struct ct_match *match, struct ucontact** _co); int get_simple_ucontact(urecord_t* _r, str* _c, struct ucontact** _co); diff --git a/modules/usrloc/usrloc.h b/modules/usrloc/usrloc.h index 842410472e6..4ae6c972f39 100644 --- a/modules/usrloc/usrloc.h +++ b/modules/usrloc/usrloc.h @@ -193,7 +193,7 @@ typedef struct usrloc_api { * @ct_uri: the contact URI to search * @callid: the SIP Call-ID of the pending REGISTER message * @cseq: the SIP CSeq of the pending REGISTER message - * @match: how to match the pending contact against existing bindings + * @match: how to match the contact against existing bindings * @c: will hold the returned contact if found or NULL * * Return: @@ -205,7 +205,7 @@ typedef struct usrloc_api { * one, so you should ignore this REGISTER (is it a retransmission?) */ int (*get_ucontact) (urecord_t *r, str *ct_uri, str *callid, int cseq, - struct ct_match *match, ucontact_t **c); + const struct ct_match *match, ucontact_t **c); /** * Fetch a ucontact from an usrloc domain using a contact ID. @@ -232,14 +232,17 @@ typedef struct usrloc_api { * @ct_uri: the SIP URI of the contact * @ci: various info pertaining to the contact, extract from the REGISTER * message (and not only!) - * @c: will hold the contact, once created + * @match: Required if @skip_replication is false, in order to instruct + * the replicas on how to match this contact * @skip_replication: set to true in order to avoid replicating an "insert" * event to neighboring cluster nodes + * @c: will hold the output contact, once created * * Return: 0 (success), negative otherwise */ int (*insert_ucontact) (urecord_t *r, str *ct_uri, ucontact_info_t *ci, - ucontact_t **c, char skip_replication); + const struct ct_match *match, char skip_replication, + ucontact_t **c); /** * Update the info of an existing usrloc contact, possibly on a re-REGISTER @@ -247,13 +250,15 @@ typedef struct usrloc_api { * @r: the usrloc record of the contact * @c: the usrloc contact to update * @ci: various info pertaining to the contact to update + * @match: Required if @skip_replication is false, in order to instruct + * the replicas on how to match this contact * @skip_replication: set to true in order to avoid replicating an "update" * event to neighboring cluster nodes * * Return: 0 (success), negative otherwise */ int (*update_ucontact) (urecord_t *r, ucontact_t *c, ucontact_info_t *ci, - char skip_replication); + const struct ct_match *match, char skip_replication); /** * Fetch a key from contact-level storage. @@ -292,7 +297,7 @@ typedef struct usrloc_api { * Return: 0 (success), negative otherwise */ int (*delete_ucontact) (urecord_t *r, ucontact_t *c, - char skip_replication); + const struct ct_match *match, char skip_replication); /** * Delete a contact from a given usrloc domain, using its hash table or