📄 test_proxy.c
字号:
int status; auth_status_t *as; msg_t *msg; as = auth_status_new(p->home); if (!as) return 500; as->as_method = sip->sip_request->rq_method_name; msg = nta_incoming_getrequest(irq); as->as_source = msg_addrinfo(msg); as->as_user_uri = sip->sip_from->a_url; as->as_display = sip->sip_from->a_display; if (sip->sip_payload) as->as_body = sip->sip_payload->pl_data, as->as_bodylen = sip->sip_payload->pl_len; auth_mod_check_client(p->auth, as, sip->sip_proxy_authorization, proxy_challenger); if ((status = as->as_status)) { nta_incoming_treply(irq, as->as_status, as->as_phrase, SIPTAG_HEADER((void *)as->as_info), SIPTAG_HEADER((void *)as->as_response), TAG_END()); } else if (as->as_match) { msg_header_remove(msg, NULL, as->as_match); } msg_destroy(msg); su_home_unref(as->as_home); return status;} int proxy_ack_cancel(struct proxy_transaction *t, nta_incoming_t *irq, sip_t const *sip){ if (sip == NULL) { proxy_transaction_destroy(t); return 0; } if (sip->sip_request->rq_method == sip_method_cancel) { /* We don't care about response to CANCEL (or ACK) * so we give NULL as callback pointer (and nta immediately * destroys transaction object or marks it disposable) */ if (nta_outgoing_tcancel(t->client, NULL, NULL, TAG_END())) return 200; else return 500; } else { return 500; }}int proxy_response(struct proxy_transaction *t, nta_outgoing_t *client, sip_t const *sip){ int final; if (sip) { msg_t *response = nta_outgoing_getresponse(client); final = sip->sip_status->st_status >= 200; sip_via_remove(response, sip_object(response)); nta_incoming_mreply(t->server, response); } else { final = 1; nta_incoming_treply(t->server, SIP_408_REQUEST_TIMEOUT, TAG_END()); } if (final) proxy_transaction_destroy(t); return 0;}struct proxy_transaction *proxy_transaction_new(struct proxy *proxy){ struct proxy_transaction *t; t = su_zalloc(proxy->home, sizeof *t); if (t) { t->proxy = proxy; proxy_transaction_insert(&proxy->transactions, t); } return t;}staticvoid proxy_transaction_destroy(struct proxy_transaction *t){ if (t == t->proxy->stateless) return; proxy_transaction_remove(t); nta_incoming_destroy(t->server); nta_outgoing_destroy(t->client); su_free(t->proxy->home, t->rq); su_free(t->proxy->home, t);}LIST_BODIES(static, proxy_transaction, struct proxy_transaction, next, prev);/* ---------------------------------------------------------------------- */staticint domain_request(struct proxy *proxy, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip){ sip_method_t method = sip->sip_request->rq_method; if (method == sip_method_register) return process_register(proxy, irq, sip); if (method == sip_method_options) return process_options(proxy, irq, sip); return 501;}staticint process_options(struct proxy *proxy, nta_incoming_t *irq, sip_t const *sip){ nta_incoming_treply(irq, SIP_200_OK, SIPTAG_CONTACT(proxy->transport_contacts), TAG_END()); return 200;}/* ---------------------------------------------------------------------- */static int process_register2(struct proxy *p, auth_status_t *as, nta_incoming_t *irq, sip_t const *sip);static int set_status(auth_status_t *as, int status, char const *phrase);static int validate_contacts(struct proxy *p, auth_status_t *as, sip_t const *sip);static int check_out_of_order(struct proxy *p, auth_status_t *as, struct registration_entry *e, sip_t const *);static int binding_update(struct proxy *p, auth_status_t *as, struct registration_entry *e, sip_t const *sip);sip_contact_t *binding_contacts(su_home_t *home, struct binding *bindings);int process_register(struct proxy *proxy, nta_incoming_t *irq, sip_t const *sip){ auth_status_t *as; msg_t *msg; int status; as = auth_status_new(proxy->home); if (!as) return 500; as->as_method = sip->sip_request->rq_method_name; msg = nta_incoming_getrequest(irq); as->as_source = msg_addrinfo(msg); msg_destroy(msg); as->as_user_uri = sip->sip_from->a_url; as->as_display = sip->sip_from->a_display; if (sip->sip_payload) as->as_body = sip->sip_payload->pl_data, as->as_bodylen = sip->sip_payload->pl_len; process_register2(proxy, as, irq, sip); assert(as->as_status >= 200); nta_incoming_treply(irq, as->as_status, as->as_phrase, SIPTAG_HEADER((void *)as->as_info), SIPTAG_HEADER((void *)as->as_response), TAG_END()); status = as->as_status; su_home_unref(as->as_home); return status;}static int process_register2(struct proxy *p, auth_status_t *as, nta_incoming_t *irq, sip_t const *sip){ struct registration_entry *e = NULL; auth_mod_check_client(p->auth, as, sip->sip_authorization, registrar_challenger); if (as->as_status) return as->as_status; assert(as->as_response == NULL); if (validate_contacts(p, as, sip)) return as->as_status; e = registration_entry_find(p, sip->sip_to->a_url); if (!sip->sip_contact) { as->as_response = (msg_header_t *)e->contacts; return set_status(as, SIP_200_OK); } if (e && check_out_of_order(p, as, e, sip)) return as->as_status; if (!e) e = registration_entry_new(p, sip->sip_to->a_url); if (!e) return set_status(as, SIP_500_INTERNAL_SERVER_ERROR); if (binding_update(p, as, e, sip)) return as->as_status; msg_header_free(p->home, (void *)e->contacts); e->contacts = binding_contacts(p->home, e->bindings); as->as_response = (msg_header_t *)e->contacts; return set_status(as, SIP_200_OK);}static int set_status(auth_status_t *as, int status, char const *phrase){ return as->as_phrase = phrase, as->as_status = status;}static int validate_contacts(struct proxy *p, auth_status_t *as, sip_t const *sip){ sip_contact_t const *m; sip_time_t expires; sip_time_t now = sip_now(); for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type == url_any) { if (!sip->sip_expires || sip->sip_expires->ex_delta || sip->sip_expires->ex_time || sip->sip_contact->m_next) return set_status(as, SIP_400_BAD_REQUEST); else return 0; } expires = sip_contact_expires(m, sip->sip_expires, sip->sip_date, p->prefs.expires, now); if (expires > 0 && expires < p->prefs.min_expires) { as->as_response = (msg_header_t *) sip_min_expires_format(as->as_home, "%u", (unsigned)p->prefs.min_expires); return set_status(as, SIP_423_INTERVAL_TOO_BRIEF); } } return 0;}/** Check for out-of-order register request */staticint check_out_of_order(struct proxy *p, auth_status_t *as, struct registration_entry *e, sip_t const *sip){ struct binding const *b; sip_call_id_t const *id; sip_contact_t *m; if (e == NULL || !sip->sip_contact) return 0; id = sip->sip_call_id; /* RFC 3261 subsection 10.3 step 6 and step 7 (p. 66): */ /* Check for reordered register requests */ for (b = e->bindings; b; b = b->next) { if (binding_is_active(b) && strcmp(sip->sip_call_id->i_id, b->call_id->i_id) == 0 && sip->sip_cseq->cs_seq <= b->cseq) { for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type == url_any || url_cmp_all(m->m_url, b->contact->m_url) == 0) return set_status(as, SIP_500_INTERNAL_SERVER_ERROR); } } } return 0;}static struct registration_entry *registration_entry_find(struct proxy const *proxy, url_t const *uri){ struct registration_entry *e; /* Our routing table */ for (e = proxy->entries; e; e = e->next) { if (url_cmp(uri, e->aor) == 0) return e; } return NULL;}static struct registration_entry *registration_entry_new(struct proxy *proxy, url_t const *aor){ struct registration_entry *e; e = su_zalloc(proxy->home, sizeof *e); if (!e) return NULL; e->proxy = proxy; e->aor = url_hdup(proxy->home, aor); if (!e->aor) { su_free(proxy->home, e); return NULL; } registration_entry_insert(&proxy->entries, e); return e;}static voidregistration_entry_destroy(struct registration_entry *e){ if (e) { registration_entry_remove(e); su_free(e->proxy->home, e->aor); while (e->bindings) binding_destroy(e->proxy->home, e->bindings); msg_header_free(e->proxy->home, (void *)e->contacts); su_free(e->proxy->home, e); }}LIST_BODIES(static, registration_entry, struct registration_entry, next, prev);/* ---------------------------------------------------------------------- *//* Bindings */staticstruct binding *binding_new(su_home_t *home, sip_contact_t *contact, sip_call_id_t *call_id, uint32_t cseq, sip_time_t registered, sip_time_t expires){ struct binding *b; b = su_zalloc(home, sizeof *b); if (b) { sip_contact_t m[1]; *m = *contact; m->m_next = NULL; b->contact = sip_contact_dup(home, m); b->call_id = sip_call_id_dup(home, call_id); b->cseq = cseq; b->registered = registered; b->expires = expires; if (!b->contact || !b->call_id) binding_destroy(home, b), b = NULL; if (b) msg_header_remove_param(b->contact->m_common, "expires"); } return b;}staticvoid binding_destroy(su_home_t *home, struct binding *b){ if (b->prev) { if ((*b->prev = b->next)) b->next->prev = b->prev; } msg_header_free(home, (void *)b->contact); msg_header_free(home, (void *)b->call_id); su_free(home, b);}staticint binding_update(struct proxy *p, auth_status_t *as, struct registration_entry *e, sip_t const *sip){ struct binding *b, *old, *next, *last, *bindings = NULL, **bb = &bindings; sip_contact_t *m; sip_time_t expires; sip_time_t now = sip_now(); assert(sip->sip_contact); /* Create new bindings */ for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type == url_any) break; expires = sip_contact_expires(m, sip->sip_expires, sip->sip_date, p->prefs.expires, now); if (expires > p->prefs.max_expires) expires = p->prefs.max_expires; msg_header_remove_param(m->m_common, "expires"); b = binding_new(p->home, m, sip->sip_call_id, sip->sip_cseq->cs_seq, now, now + expires); if (!b) break; *bb = b, b->prev = bb, bb = &b->next; } last = NULL; if (m == NULL) { /* Merge new bindings with old ones */ for (old = e->bindings; old; old = next) { next = old->next; for (b = bindings; b != last; b = b->next) { if (url_cmp_all(old->contact->m_url, b->contact->m_url) != 0) continue; if (strcmp(old->call_id->i_id, b->call_id->i_id) == 0) { b->registered = old->registered; } binding_destroy(p->home, old); break; } } for (bb = &e->bindings; *bb; bb = &(*bb)->next) ; if ((*bb = bindings)) bindings->prev = bb; } else if (m->m_url->url_type == url_any) { /* Unregister all */ for (b = e->bindings; b; b = b->next) { b->expires = now; } } else { /* Infernal error */ for (old = bindings; old; old = next) { next = old->next; binding_destroy(p->home, old); } return set_status(as, SIP_500_INTERNAL_SERVER_ERROR); } return 0;}sip_contact_t *binding_contacts(su_home_t *home, struct binding *bindings){ sip_contact_t *retval = NULL, **mm = &retval; struct binding *b; sip_time_t now = sip_now(); for (b = bindings; b; b = b->next) { char const *expires; if (b->expires <= now) continue; *mm = sip_contact_copy(home, b->contact); if (*mm) { expires = su_sprintf(home, "expires=%u", (unsigned)(b->expires - now)); msg_header_add_param(home, (*mm)->m_common, expires); mm = &(*mm)->m_next; } } return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -