📄 nea_server.c
字号:
* @param nes pointer to notifier * @param local_target optional contact header * @param msg pointer to request message * @param sip pointer to SIP view to request message * * @return * The function nea_server_add() returns 0 if successful, -1 upon an * error. * */int nea_server_add(nea_server_t *nes, sip_contact_t const *local_target, msg_t *msg, sip_t *sip){ su_home_t *home = nes->nes_home; nea_sub_t *s = NULL; url_t target[1]; s = nea_sub_create(nes); s->s_from = sip_from_dup(home, sip->sip_from); if (local_target == NULL) local_target = nes->nes_eventity_uri; s->s_local = sip_contact_dup(nes->nes_home, local_target); *target = *local_target->m_url; s->s_leg = nta_leg_tcreate(nes->nes_agent, nea_sub_process_incoming, s, SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), /* local address */ SIPTAG_TO(sip->sip_from), /* remote address */ URLTAG_URL(target), TAG_END()); if (s->s_local && s->s_leg) { nta_leg_tag(s->s_leg, NULL); return 0; } else { nea_sub_destroy(s); return -1; }}#endifstaticint nea_server_callback(nea_sub_t *nes_as_sub, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip){ return nea_server_add_irq((nea_server_t *)nes_as_sub, leg, NULL, irq, sip);}/** Process incoming request */int nea_server_add_irq(nea_server_t *nes, nta_leg_t *leg, sip_contact_t const *local_target, nta_incoming_t *irq, sip_t const *sip){ nea_sub_t *s = NULL; s = nea_sub_create(nes); s->s_from = sip_from_dup(nes->nes_home, sip->sip_from); if (local_target == NULL) local_target = nes->nes_eventity_uri; s->s_local = sip_contact_dup(nes->nes_home, local_target); if (leg == NULL || leg == nes->nes_leg) { url_t target[1]; *target = *local_target->m_url; s->s_leg = nta_leg_tcreate(nes->nes_agent, nea_sub_process_incoming, s, SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), SIPTAG_CALL_ID(sip->sip_call_id), URLTAG_URL((url_string_t *)target), TAG_NULL()); } else { nta_leg_bind(s->s_leg = leg, nea_sub_process_incoming, s); } if (s->s_leg) { if (sip->sip_to->a_tag == NULL) { nta_leg_tag(s->s_leg, NULL); nta_incoming_tag(irq, nta_leg_get_tag(s->s_leg)); } nta_leg_server_route(s->s_leg, sip->sip_record_route, sip->sip_contact); return nea_sub_process_incoming(s, s->s_leg, irq, sip); } else { nea_sub_destroy(s); return 500; }}/* ----------------------------------------------------------------- *//**Process incoming transactions for event dialog. * * The nea_sub_process_incoming() processes the transactions for event * dialog. Currently, no other methods allowed beside SUBSCRIBE. The * SUBSCRIBE is processed by nea_sub_process_subscribe(). * * @param s pointer to subscriber object * @param leg pointer to NTA dialog object * @param irq pointer to NTA server transaction * @param sip pointer to structure containing SIP headers of the request * * The nea_sub_process_incoming() returns 0 if successful, SIP error code * otherwise. */int nea_sub_process_incoming(nea_sub_t *s, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip){ int retval; s->s_processing = 1; s->s_irq = irq; switch(sip->sip_request->rq_method) { case sip_method_subscribe: retval = nea_sub_process_subscribe(s, leg, irq, sip); break; default: nta_incoming_treply(irq, retval = SIP_405_METHOD_NOT_ALLOWED, SIPTAG_ALLOW_STR("SUBSCRIBE"), TAG_END()); retval = 405; } s->s_processing = 0; if (s->s_irq) nta_incoming_destroy(irq), s->s_irq = NULL; if (s->s_pending_flush || s->s_state == nea_embryonic) nea_sub_destroy(s); return retval;}/* ----------------------------------------------------------------- *//**Process incoming SUBSCRIBE transactions for event dialog. * * The function nea_sub_process_subscribe() processes the SUBSCRIBE * transactions for (possible) event dialog. * * @param s pointer to subscriber object * @param leg pointer to NTA dialog object * @param irq pointer to NTA server transaction * @param sip pointer to structure containing SIP headers of the request * * @return * The function nea_sub_process_subscribe() returns 0 if successful, and a * SIP error code otherwise. */int nea_sub_process_subscribe(nea_sub_t *s, nta_leg_t *leg, nta_incoming_t *irq, sip_t const *sip){ nea_server_t *nes = s->s_nes; su_home_t *home = nes->nes_home; nea_event_t *ev = NULL, *ev_maybe = NULL; nea_event_view_t *evv = NULL, *evv_maybe = NULL; sip_time_t delta = 0, now = sip_now(); sip_expires_t expires[1] = { SIP_EXPIRES_INIT() }; sip_unsupported_t *unsupported; sip_event_t const *o; sip_accept_t const *ac = NULL, *accept = NULL; sip_accept_t *a0 = NULL, *a, *a_next, **aa; sip_accept_t accept_default[1]; unsigned proposed_throttle; char const *type, *throttle; int once, what, supported_eventlist, require_eventlist; if (sip->sip_payload && !sip->sip_content_type) { nta_incoming_treply(irq, 400, "Missing Content-Type", SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); return 0; } if (sip->sip_expires && sip->sip_expires->ex_delta > 0 && sip->sip_expires->ex_delta < nes->nes_min_expires) { sip_min_expires_t me[1]; sip_min_expires_init(me); me->me_delta = nes->nes_min_expires; nta_incoming_treply(irq, 423, "Subscription Interval Too Small", SIPTAG_ACCEPT(accept), SIPTAG_MIN_EXPIRES(me), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); return 0; } /* Check features */ if (nes->nes_require) { unsupported = sip_has_unsupported2(nes->nes_home, sip->sip_supported, sip->sip_require, nes->nes_require); if (unsupported) { nta_incoming_treply(irq, SIP_421_EXTENSION_REQUIRED, SIPTAG_REQUIRE(nes->nes_require), SIPTAG_UNSUPPORTED(unsupported), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); su_free(nes->nes_home, unsupported); return 0; } } supported_eventlist = sip_has_feature(sip->sip_supported, "eventlist"); require_eventlist = sip_has_feature(sip->sip_require, "eventlist"); supported_eventlist = supported_eventlist || require_eventlist; if (s->s_id && (!sip->sip_event || str0cmp(s->s_id->o_type, sip->sip_event->o_type) != 0 || str0cmp(s->s_id->o_id, sip->sip_event->o_id))) { /* Multiple subscriptions per dialog are not supported. */ return nta_incoming_treply(irq, 501, "Multiple subscriptions not implemented", SIPTAG_SERVER_STR(nes->nes_server), TAG_NULL()); } /* Check that subscriber asks for a supported event */ for (once = 0; ev == NULL ;once++) { o = sip->sip_event; /* Check that we have a matching event */ if (o && o->o_type) { for (ev = nes->nes_events; ev; ev = ev->ev_next) { if (strcmp(o->o_type, ev->ev_event->o_type) == 0) { ev_maybe = ev; if (ev->ev_eventlist) { if (supported_eventlist) break; } else { if (!supported_eventlist) break; } } } } if (!ev && !require_eventlist) ev = ev_maybe; if (ev || once) break; /* Ask the application either to 1) add a new event or assing us an event/payload (0), 2) take care of transaction (positive), or 3) drop request (negative). */ if ((what = nes_new_event_callback(nes, &ev, &evv, irq, sip)) < 0) break; if (what > 0) { s->s_irq = NULL; return 0; } } if (ev_maybe == NULL && ev == NULL) { nta_incoming_treply(irq, SIP_489_BAD_EVENT, SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), NULL); return 0; } else if (ev == NULL) { ev = ev_maybe; unsupported = sip_has_unsupported(nes->nes_home, ev->ev_supported, sip->sip_require); nta_incoming_treply(irq, SIP_420_BAD_EXTENSION, SIPTAG_UNSUPPORTED(unsupported), SIPTAG_REQUIRE(ev->ev_require), SIPTAG_SUPPORTED(ev->ev_supported), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); su_free(nes->nes_home, unsupported); return 0; } if (sip->sip_accept) accept = sip->sip_accept; else if (evv && evv->evv_content_type) { /* Generate accept header from event view specified by application */ sip_accept_init(accept_default); accept_default->ac_type = evv->evv_content_type->c_type; accept_default->ac_subtype = evv->evv_content_type->c_subtype; accept = a0; } else accept = ev->ev_default; for (once = 0; evv == NULL ;once++) { /* If there are multiple accept values with different Q values, insertion sort by Q value */ for (ac = accept->ac_next; ac; ac = ac->ac_next) { if (ac->ac_q != accept->ac_q) { if ((a0 = sip_accept_dup(home, accept))) { /* Sort the accept list by Q values */ for (a = a0, accept = NULL; a; a = a_next) { a_next = a->ac_next; for (aa = (sip_accept_t **)&accept; *aa && sip_q_value((*aa)->ac_q) >= sip_q_value(a->ac_q); aa = &(*aa)->ac_next) ; a->ac_next = *aa; *aa = a; /* Insert */ } } break; } } /* Check that subscriber asks for a supported content type */ for (ac = accept; ac; ac = ac->ac_next) { int i; if (ac->ac_type == NULL || ac->ac_subtype == NULL) continue; /* Check all supported content types v. accept */ for (i = 0; (evv = ev->ev_views[i]); i++) { assert(evv->evv_content_type && evv->evv_content_type->c_type); if (strcmp(ac->ac_type, "*/*") == 0) break; type = evv->evv_content_type->c_type; if ((strcasecmp(ac->ac_type, type) == 0) || (strcasecmp(ac->ac_subtype, "*") == 0 && strncasecmp(ac->ac_type, type, ac->ac_subtype - ac->ac_type) == 0)) { if (evv_maybe == NULL) evv_maybe = evv; } } if (evv) /* Found */ break; } /* Free the sorted Accept list */ for (a = a0; a; a = a_next) a_next = a->ac_next, su_free(home, a); if (!evv) evv = evv_maybe; if (evv || once) break; /* Ask the application either to 1) add a new event view or assign us an event view (0), 2) take care of transaction (positive), or 3) drop request (negative). */ if ((what = nes_new_event_callback(nes, &ev, &evv, irq, sip)) < 0) break; if (what > 0) { s->s_irq = NULL; return 0; } } if (evv == NULL) { SU_DEBUG_3(("nea_server: event %s rejected %u %s\n", ev->ev_event->o_type, SIP_406_NOT_ACCEPTABLE)); /* There is no media acceptable to watcher */ return nta_incoming_treply(irq, SIP_406_NOT_ACCEPTABLE, SIPTAG_ACCEPT(ev->ev_accept), SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods), TAG_NULL()); } /* Do not change private view */ if (s->s_view && s->s_view->evv_primary == evv) evv = s->s_view; /* Set throttle */ if (sip->sip_event && (throttle = sip_params_find(sip->sip_event->o_params, "throttle="))) { proposed_throttle = strtoul(throttle, NULL, 10); if (proposed_throttle < evv->evv_min_throttle) proposed_throttle = evv->evv_min_throttle; } else proposed_throttle = evv->evv_throttle; s->s_throttle = proposed_throttle; /* Update route, store remote contact */ nta_leg_server_route(leg, sip->sip_record_route, sip->sip_contact); su_free(home, s->s_remote); s->s_remote = sip_contact_dup(home, sip->sip_contact); /* Store content-type and body */ if (sip->sip_content_type) { su_free(home, s->s_content_type); s->s_content_type = sip_content_type_dup(home, sip->sip_content_type); su_free(home, s->s_payload); s->s_payload = sip_payload_dup(home, sip->sip_payload); } /* Calculate expiration time for subscription */ delta = sip_contact_expires(NULL, sip->sip_expires, sip->sip_date, nes->nes_expires, now); if (delta > nes->nes_max_expires) delta = nes->nes_max_expires; expires->ex_delta = delta; if (s->s_subscribed == 0) s->s_subscribed = now; s->s_expires = now + delta; /* s->s_accept = sip_accept_dup(home, accept); */ if (s->s_id == NULL) s->s_id = sip_event_dup(home, sip->sip_event); s->s_event = ev; s->s_eventlist = supported_eventlist; nea_sub_assign_view(s, evv); s->s_updated = evv->evv_updated - 1; /* Force notify */ if (nes->nes_202_before_notify) { nta_incoming_treply(irq, SIP_202_ACCEPTED, SIPTAG_SERVER_STR(nes->nes_server), SIPTAG_ALLOW_EVENTS(nes->nes_allow_events), SIPTAG_ALLOW(nes->nes_allow_methods),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -