/* * Create and insert new contact * into urecord */ int insert_ucontact(urecord_t* _r, str* aor, str* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, unsigned int _flags, struct ucontact** _con, str* _ua, str* _recv, struct socket_info* sock, str* _inst, int sid) { if (mem_insert_ucontact(_r, aor, _c, _e, _q, _cid, _cs, _flags, _con, _ua, _recv, sock, _inst, sid) < 0) { LOG(L_ERR, "insert_ucontact(): Error while inserting contact\n"); return -1; } notify_watchers(_r, *_con, (_e > 0) ? PRES_ONLINE : PRES_OFFLINE); if (exists_ulcb_type(UL_CONTACT_INSERT)) { run_ul_callbacks( UL_CONTACT_INSERT, *_con); } save_reg_avps(*_con); if (db_mode == WRITE_THROUGH) { if (db_store_ucontact(*_con) < 0) { LOG(L_ERR, "insert_ucontact(): Error while inserting in database\n"); } (*_con)->state = CS_SYNC; } return 0; }
/*! * \brief Create and insert new contact into impurecord * \param _r record into the new contact should be inserted * \param _contact contact string * \param _ci contact information * \param _c new created contact * \return 0 on success, -1 on failure */ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucontact_t** _c) { //First check our constraints if (maxcontact > 0 && maxcontact_behaviour > 0) { ucontact_t* contact = _r->contacts; int numcontacts = 0; while (contact) { numcontacts++; contact = contact->next; } if (numcontacts >= maxcontact) { switch (maxcontact_behaviour) { case 1://reject LM_ERR("too many contacts already registered for IMPU <%.*s>\n", _r->public_identity.len, _r->public_identity.s); return -1; case 2://overwrite oldest LM_DBG("Too many contacts already registered, overwriting oldest for IMPU <%.*s>\n", _r->public_identity.len, _r->public_identity.s); //we can just remove the first one seeing the contacts are ordered on insertion with newest last and oldest first mem_delete_ucontact(_r, _r->contacts); break; default://unknown LM_ERR("unknown maxcontact behaviour..... ignoring\n"); break; } } } //at this stage we are safe to insert the new contact LM_DBG("INSERTing ucontact in usrloc module\n"); if (((*_c) = mem_insert_ucontact(_r, _contact, _ci)) == 0) { LM_ERR("failed to insert contact\n"); return -1; } /*DB?*/ if (db_mode == WRITE_THROUGH && db_insert_ucontact(_r, *_c) != 0) { LM_ERR("error inserting contact into db"); return -1; } if (exists_ulcb_type(NULL, UL_CONTACT_INSERT)) { run_ul_callbacks(NULL, UL_CONTACT_INSERT, _r, *_c); } if (exists_ulcb_type(_r->cbs, UL_IMPU_NEW_CONTACT)) { run_ul_callbacks(_r->cbs, UL_IMPU_NEW_CONTACT, _r, *_c); } return 0; }
/* * Create and insert new contact * into urecord */ int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, int _cs, unsigned int _flags, int _rep, struct ucontact** _con) { if (mem_insert_ucontact(_r, _c, _e, _q, _cid, _cs, _flags, _rep, _con) < 0) { LOG(L_ERR, "insert_ucontact(): Error while inserting contact\n"); return -1; } notify_watchers(_r, PRES_ONLINE); if (db_mode == WRITE_THROUGH) { if (db_insert_ucontact(*_con) < 0) { LOG(L_ERR, "insert_ucontact(): Error while inserting in database\n"); mem_delete_ucontact(_r, *_con); return -2; } (*_con)->state=CS_SYNC; } return 0; }
/*! * \brief Create and insert new contact into urecord * \param _r record into the new contact should be inserted * \param _contact contact string * \param _ci contact information * \param _c new created contact * \return 0 on success, -1 on failure */ int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci, ucontact_t** _c) { if ( ((*_c)=mem_insert_ucontact(_r, _contact, _ci)) == 0) { LM_ERR("failed to insert contact\n"); return -1; } if (exists_ulcb_type(UL_CONTACT_INSERT)) { run_ul_callbacks( UL_CONTACT_INSERT, *_c); } if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) { if (db_insert_ucontact(*_c) < 0) { LM_ERR("failed to insert in database\n"); return -1; } else { (*_c)->state = CS_SYNC; } } return 0; }
int preload_udomain(db_con_t* _c, udomain_t* _d) { char b[256]; db_key_t columns[11]; db_res_t* res; db_row_t* row; int i, cseq; unsigned int flags; struct socket_info* sock; str uid, contact, callid, ua, received, instance, aor; str* rec; time_t expires; qvalue_t q; urecord_t* r; ucontact_t* c; columns[0] = uid_col.s; columns[1] = contact_col.s; columns[2] = expires_col.s; columns[3] = q_col.s; columns[4] = callid_col.s; columns[5] = cseq_col.s; columns[6] = flags_col.s; columns[7] = user_agent_col.s; columns[8] = received_col.s; columns[9] = instance_col.s; columns[10] = aor_col.s; memcpy(b, _d->name->s, _d->name->len); b[_d->name->len] = '\0'; if (ul_dbf.use_table(_c, b) < 0) { LOG(L_ERR, "preload_udomain(): Error in use_table\n"); return -1; } if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, &res) < 0) { LOG(L_ERR, "preload_udomain(): Error while doing db_query\n"); return -1; } if (RES_ROW_N(res) == 0) { DBG("preload_udomain(): Table is empty\n"); ul_dbf.free_result(_c, res); return 0; } lock_udomain(_d); for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; uid.s = (char*)VAL_STRING(ROW_VALUES(row)); if (uid.s == 0) { LOG(L_CRIT, "preload_udomain: ERROR: bad uid " "record in table %s\n", b); LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n"); continue; } else { uid.len = strlen(uid.s); } contact.s = (char*)VAL_STRING(ROW_VALUES(row) + 1); if (contact.s == 0) { LOG(L_CRIT, "preload_udomain: ERROR: bad contact " "record in table %s\n", b); LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s\n", uid.len, uid.s); LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n"); continue; } else { contact.len = strlen(contact.s); } expires = VAL_TIME (ROW_VALUES(row) + 2); q = double2q(VAL_DOUBLE(ROW_VALUES(row) + 3)); cseq = VAL_INT (ROW_VALUES(row) + 5); callid.s = (char*)VAL_STRING(ROW_VALUES(row) + 4); if (callid.s == 0) { LOG(L_CRIT, "preload_udomain: ERROR: bad callid record in" " table %s\n", b); LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s," " contact %.*s\n", uid.len, uid.s, contact.len, contact.s); LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n"); continue; } else { callid.len = strlen(callid.s); } flags = VAL_BITMAP(ROW_VALUES(row) + 6); ua.s = (char*)VAL_STRING(ROW_VALUES(row) + 7); if (ua.s) { ua.len = strlen(ua.s); } else { ua.len = 0; } if (!VAL_NULL(ROW_VALUES(row) + 8)) { received.s = (char*)VAL_STRING(ROW_VALUES(row) + 8); if (received.s) { received.len = strlen(received.s); rec = &received; sock = find_socket(&received); } else { received.len = 0; rec = 0; sock = 0; } } else { received.s = 0; received.len = 0; rec = 0; sock = 0; } if (!VAL_NULL(ROW_VALUES(row) + 9)) { instance.s = (char*)VAL_STRING(ROW_VALUES(row) + 9); if (instance.s) { instance.len = strlen(instance.s); } else { instance.len = 0; } } else { instance.s = 0; instance.len = 0; } if (!VAL_NULL(ROW_VALUES(row) + 10)) { aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 10); if (aor.s) { aor.len = strlen(aor.s); } else { aor.len = 0; } } else { aor.s = 0; aor.len = 0; } if (get_urecord(_d, &uid, &r) > 0) { if (mem_insert_urecord(_d, &uid, &r) < 0) { LOG(L_ERR, "preload_udomain(): Can't create a record\n"); ul_dbf.free_result(_c, res); unlock_udomain(_d); return -2; } } if (mem_insert_ucontact(r, &aor, &contact, expires, q, &callid, cseq, flags, &c, &ua, rec, sock, &instance) < 0) { LOG(L_ERR, "preload_udomain(): Error while inserting contact\n"); ul_dbf.free_result(_c, res); unlock_udomain(_d); return -3; } db_read_reg_avps(_c, c); /* We have to do this, because insert_ucontact sets state to CS_NEW * and we have the contact in the database already * we also store zombies in database so we have to restore * the correct state */ c->state = CS_SYNC; } ul_dbf.free_result(_c, res); unlock_udomain(_d); return 0; }
/*! * \brief Loads from DB all contacts for a RUID * \param _c database connection * \param _d domain * \param _aor address of record * \return pointer to the record on success, 0 on errors or if nothing is found */ urecord_t* db_load_urecord_by_ruid(udomain_t* _d, str *_ruid) { ucontact_info_t *ci; db_key_t columns[18]; db_key_t keys[1]; db_key_t order; db_val_t vals[1]; db1_res_t* res = NULL; db_row_t *row; str contact; str aor; char aorbuf[512]; str domain; urecord_t* r; ucontact_t* c; keys[0] = &ruid_col; vals[0].type = DB1_STR; vals[0].nul = 0; vals[0].val.str_val = *_ruid; columns[0] = &contact_col; columns[1] = &expires_col; columns[2] = &q_col; columns[3] = &callid_col; columns[4] = &cseq_col; columns[5] = &flags_col; columns[6] = &cflags_col; columns[7] = &user_agent_col; columns[8] = &received_col; columns[9] = &path_col; columns[10] = &sock_col; columns[11] = &methods_col; columns[12] = &last_mod_col; columns[13] = &ruid_col; columns[14] = &instance_col; columns[15] = &user_col; columns[16] = ®_id_col; columns[17] = &domain_col; if (desc_time_order) order = &last_mod_col; else order = &q_col; if (ul_db_layer_query(_d, &vals[0].val.str_val, &vals[1].val.str_val, keys, 0, vals, columns, 1, 18, order, &res) < 0) { LM_ERR("db_query failed\n"); return 0; } if (RES_ROW_N(res) == 0) { LM_DBG("aor %.*s not found in table %.*s\n",_ruid->len, _ruid->s, _d->name->len, _d->name->s); ul_db_layer_free_result(_d, res); return 0; } r = 0; /* use first row - shouldn't be more */ row = RES_ROWS(res); ci = dbrow2info(ROW_VALUES(RES_ROWS(res)), &contact); if (ci==0) { LM_ERR("skipping record for %.*s in table %s\n", _ruid->len, _ruid->s, _d->name->s); goto done; } aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 15); aor.len = strlen(aor.s); if (use_domain) { domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 17); if (VAL_NULL(ROW_VALUES(row)+17) || domain.s==0 || domain.s[0]==0) { LM_CRIT("empty domain record for user %.*s...skipping\n", aor.len, aor.s); goto done; } domain.len = strlen(domain.s); if(aor.len + domain.len + 2 >= 512) { LM_ERR("AoR is too big\n"); goto done; } memcpy(aorbuf, aor.s, aor.len); aorbuf[aor.len] = '@'; memcpy(aorbuf + aor.len + 1, domain.s, domain.len); aor.len += 1 + domain.len; aor.s = aorbuf; aor.s[aor.len] = '\0'; } get_static_urecord( _d, &aor, &r); if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) { LM_ERR("mem_insert failed\n"); free_urecord(r); ul_db_layer_free_result(_d, res); return 0; } /* We have to do this, because insert_ucontact sets state to CS_NEW * and we have the contact in the database already */ c->state = CS_SYNC; done: ul_db_layer_free_result(_d, res); ; return r; }
/*! * \brief Loads from DB all contacts for an AOR * \param _c database connection * \param _d domain * \param _aor address of record * \return pointer to the record on success, 0 on errors or if nothing is found */ urecord_t* db_load_urecord(udomain_t* _d, str *_aor) { ucontact_info_t *ci; db_key_t columns[16]; db_key_t keys[2]; db_key_t order; db_val_t vals[2]; db1_res_t* res = NULL; str contact; char *domain; int i; urecord_t* r; ucontact_t* c; keys[0] = &user_col; vals[0].type = DB1_STR; vals[0].nul = 0; if (use_domain) { keys[1] = &domain_col; vals[1].type = DB1_STR; vals[1].nul = 0; domain = memchr(_aor->s, '@', _aor->len); vals[0].val.str_val.s = _aor->s; if (domain==0) { vals[0].val.str_val.len = 0; vals[1].val.str_val = *_aor; } else { vals[0].val.str_val.len = domain - _aor->s; vals[1].val.str_val.s = domain+1; vals[1].val.str_val.len = _aor->s + _aor->len - domain - 1; } } else { vals[0].val.str_val = *_aor; } columns[0] = &contact_col; columns[1] = &expires_col; columns[2] = &q_col; columns[3] = &callid_col; columns[4] = &cseq_col; columns[5] = &flags_col; columns[6] = &cflags_col; columns[7] = &user_agent_col; columns[8] = &received_col; columns[9] = &path_col; columns[10] = &sock_col; columns[11] = &methods_col; columns[12] = &last_mod_col; columns[13] = &ruid_col; columns[14] = &instance_col; columns[15] = ®_id_col; if (desc_time_order) order = &last_mod_col; else order = &q_col; if (ul_db_layer_query(_d, &vals[0].val.str_val, &vals[1].val.str_val, keys, 0, vals, columns, (use_domain)?2:1, 16, order, &res) < 0) { LM_ERR("db_query failed\n"); return 0; } if (RES_ROW_N(res) == 0) { LM_DBG("aor %.*s not found in table %.*s\n",_aor->len, _aor->s, _d->name->len, _d->name->s); ul_db_layer_free_result(_d, res); return 0; } r = 0; for(i = 0; i < RES_ROW_N(res); i++) { ci = dbrow2info( ROW_VALUES(RES_ROWS(res) + i), &contact); if (ci==0) { LM_ERR("skipping record for %.*s in table %s\n", _aor->len, _aor->s, _d->name->s); continue; } if ( r==0 ) get_static_urecord( _d, _aor, &r); if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) { LM_ERR("mem_insert failed\n"); free_urecord(r); ul_db_layer_free_result(_d, res); return 0; } /* We have to do this, because insert_ucontact sets state to CS_NEW * and we have the contact in the database already */ c->state = CS_SYNC; } ul_db_layer_free_result(_d, res); return r; }