📄 save.c
字号:
calc_contact_expires(_m, _c->expires, &e); /* Skip contacts with zero expires */ if (e == 0) continue; if (max_contacts && (num >= max_contacts)) { LOG(L_INFO,"INFO:registrar:insert_contacts: too many contacts " "(%d) for AOR <%.*s>\n", num, _a->len, _a->s); rerrno = R_TOO_MANY; goto error; } num++; if (r==0) { if (ul.insert_urecord(_d, _a, &r) < 0) { rerrno = R_UL_NEW_R; LOG(L_ERR, "ERROR:registrar:insert_contacts: failed to insert " "new record structure\n"); goto error; } } /* pack the contact_info */ if ( (ci=pack_ci( (ci==0)?_m:0, _c, e, flags, 0))==0 ) { LOG(L_ERR, "ERROR:registrar:insert_contacts: failed to extract " "contact info\n"); goto error; } if ( r->contacts==0 || ul.get_ucontact(r, &_c->uri, ci->callid, ci->cseq+1, &c)!=0 ) { if (ul.insert_ucontact( r, &_c->uri, ci, &c) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "ERROR:registrar:insert_contacts: failed to insert " "contact\n"); goto error; } } else { if (ul.update_ucontact( c, ci) < 0) { rerrno = R_UL_UPD_C; LOG(L_ERR, "ERROR:registrar:insert_contacts: failed to update " "contact\n"); goto error; } }#ifdef USE_TCP if (tcp_check) { /* parse contact uri to see if transport is TCP */ if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) { LOG(L_ERR,"ERROR:registrar:insert_contacts failed to parse " "contact <%.*s>\n", _c->uri.len, _c->uri.s); } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) { if (e_max) { LOG(L_WARN,"WARNING:registrar:insert_contacts: multiple " "TCP contacts on single REGISTER\n"); if (e>e_max) e_max = e; } else { e_max = e; } } }#endif } if (r) { if (r->contacts) build_contact(r->contacts); ul.release_urecord(r); }#ifdef USE_TCP if ( tcp_check && e_max>0 ) { e_max -= act_time; force_tcp_conn_lifetime( &_m->rcv , e_max + 10 ); }#endif return 0;error: if (r) ul.delete_urecord(_d, _a, r); return -1;}static int test_max_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c, ucontact_info_t *ci){ int num; int e; ucontact_t* ptr, *cont; int ret; num = 0; ptr = _r->contacts; while(ptr) { if (VALID_CONTACT(ptr, act_time)) { num++; } ptr = ptr->next; } DBG("DEBUG:registrar:test_max_contacts: %d valid contacts\n", num); for( ; _c ; _c = get_next_contact(_c) ) { /* calculate expires */ calc_contact_expires(_m, _c->expires, &e); ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &cont); if (ret==-1) { LOG(L_ERR,"ERROR:registrar:update_contacts: invalid cseq for aor " "<%.*s>\n",_r->aor.len,_r->aor.s); rerrno = R_INV_CSEQ; return -1; } else if (ret==-2) { continue; } if (ret > 0) { /* Contact not found */ if (e != 0) num++; } else { if (e == 0) num--; } } DBG("DEBUG:registrar:test_max_contacts: %d contacts after commit\n", num); if (num > max_contacts) { LOG(L_INFO,"INFO:registrar:test_max_contacts: too many contacts " "for AOR <%.*s>\n", _r->aor.len, _r->aor.s); rerrno = R_TOO_MANY; return -1; } return 0;}/* * Message contained some contacts and appropriate * record was found, so we have to walk through * all contacts and do the following: * 1) If contact in usrloc doesn't exists and * expires > 0, insert new contact * 2) If contact in usrloc exists and expires * > 0, update the contact * 3) If contact in usrloc exists and expires * == 0, delete contact */static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c){ ucontact_info_t *ci; ucontact_t* c; int e; int set, reset; unsigned int flags; int ret;#ifdef USE_TCP int e_max; int tcp_check; struct sip_uri uri;#endif /* is nated flag */ if (_m->flags&nat_flag) flags = FL_NAT; else flags = FL_NONE; /* nat type flag */ if (_m->flags&sip_natping_flag) flags |= FL_NAT_SIPPING; /* pack the contact_info */ if ( (ci=pack_ci( _m, 0, 0, 0, 0))==0 ) { LOG(L_ERR, "ERROR:registrar:update_contacts: failed to " "initial pack contact info\n"); goto error; } if (max_contacts && test_max_contacts(_m, _r, _c, ci) != 0 ) goto error;#ifdef USE_TCP if ( (_m->flags&tcp_persistent_flag) && (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) { e_max = -1; tcp_check = 1; } else { e_max = tcp_check = 0; }#endif for( ; _c ; _c = get_next_contact(_c) ) { /* calculate expires */ calc_contact_expires(_m, _c->expires, &e); /* search for the contact*/ ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &c); if (ret==-1) { LOG(L_ERR,"ERROR:registrar:update_contacts: invalid cseq for aor " "<%.*s>\n",_r->aor.len,_r->aor.s); rerrno = R_INV_CSEQ; goto error; } else if (ret==-2) { continue; } if ( ret > 0 ) { /* Contact not found -> expired? */ if (e==0) continue; /* pack the contact_info */ if ( (ci=pack_ci( 0, _c, e, flags, 0))==0 ) { LOG(L_ERR, "ERROR:registrar:update_contacts: failed to " "extract contact info\n"); goto error; } if (ul.insert_ucontact( _r, &_c->uri, ci, &c) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "ERROR:registrar:update_contacts: failed to insert " "contact\n"); goto error; } } else { /* Contact found */ if (e == 0) { /* it's expired */ if (mem_only) { c->flags |= FL_MEM; } else { c->flags &= ~FL_MEM; } if (ul.delete_ucontact(_r, c) < 0) { rerrno = R_UL_DEL_C; LOG(L_ERR, "ERROR:registrar:update_contacts: failed " "to delete contact\n"); goto error; } } else { /* do update */ set = flags | mem_only; reset = ~(flags | mem_only) & (FL_NAT|FL_MEM|FL_NAT_SIPPING); /* pack the contact specific info */ if ( (ci=pack_ci( 0, _c, e, set, reset))==0 ) { LOG(L_ERR, "ERROR:registrar:update_contacts: failed to " "pack contact specific info\n"); goto error; } if (ul.update_ucontact(c, ci) < 0) { rerrno = R_UL_UPD_C; LOG(L_ERR, "ERROR:registrar:update_contacts: failed to " "update contact\n"); goto error; } if (desc_time_order) { move_on_top(_r, c); } } }#ifdef USE_TCP if (tcp_check) { /* parse contact uri to see if transport is TCP */ if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) { LOG(L_ERR,"ERROR:registrar:update_contacts failed to parse " "contact <%.*s>\n", _c->uri.len, _c->uri.s); } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) { if (e_max>0) { LOG(L_WARN,"WARNING:registrar:update_contacts: multiple " "TCP contacts on single REGISTER\n"); } if (e>e_max) e_max = e; } }#endif if (e>e_max) e_max = e; }#ifdef USE_TCP if ( tcp_check && e_max>-1 ) { if (e_max) e_max -= act_time; force_tcp_conn_lifetime( &_m->rcv , e_max + 10 ); }#endif return 0;error: return -1;}/* * This function will process request that * contained some contact header fields */static inline int add_contacts(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _a){ int res; urecord_t* r; ul.lock_udomain(_d); res = ul.get_urecord(_d, _a, &r); if (res < 0) { rerrno = R_UL_GET_R; LOG(L_ERR, "ERROR:registrar:add_contacts: failed to retrieve record " "from usrloc\n"); ul.unlock_udomain(_d); return -2; } if (res == 0) { /* Contacts found */ if (update_contacts(_m, r, _c) < 0) { build_contact(r->contacts); ul.release_urecord(r); ul.unlock_udomain(_d); return -3; } build_contact(r->contacts); ul.release_urecord(r); } else { if (insert_contacts(_m, _c, _d, _a) < 0) { ul.unlock_udomain(_d); return -4; } } ul.unlock_udomain(_d); return 0;}/* * Process REGISTER request and save it's contacts */static inline int save_real(struct sip_msg* _m, udomain_t* _t, int doreply){ contact_t* c; int st; str aor; rerrno = R_FINE; if (parse_message(_m) < 0) { goto error; } if (check_contacts(_m, &st) > 0) { goto error; } get_act_time(); c = get_first_contact(_m); if (extract_aor(&get_to(_m)->uri, &aor) < 0) { LOG(L_ERR, "ERROR:registrar:save_real: failed to extract " "Address Of Record\n"); goto error; } if (c == 0) { if (st) { if (star(_t, &aor) < 0) goto error; } else { if (no_contacts(_t, &aor) < 0) goto error; } } else { if (add_contacts(_m, c, _t, &aor) < 0) goto error; } if (doreply && (send_reply(_m) < 0)) return -1; else return 1;error: if (doreply) send_reply(_m); return 0;}/* * Process REGISTER request and save it's contacts */int save(struct sip_msg* _m, char* _t, char* _s){ mem_only = FL_NONE; return save_real(_m, (udomain_t*)_t, 1);}/* * Process REGISTER request and save it's contacts, do not send any replies */int save_noreply(struct sip_msg* _m, char* _t, char* _s){ mem_only = FL_NONE; return save_real(_m, (udomain_t*)_t, 0);}/* * Update memory cache only */int save_memory(struct sip_msg* _m, char* _t, char* _s){ mem_only = FL_MEM; return save_real(_m, (udomain_t*)_t, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -