📄 nua_publish.c
字号:
int nua_stack_publish(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags){ return nua_client_create(nh, e, &nua_publish_client_methods, tags);}static int nua_publish_client_template(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags){ nua_dialog_usage_t *du; if (cr->cr_event == nua_r_publish) return 0; du = nua_dialog_usage_get(cr->cr_owner->nh_ds, nua_publish_usage, NULL); if (du && du->du_cr) { if (nua_client_set_target(cr, du->du_cr->cr_target) < 0) return -1; *return_msg = msg_copy(du->du_cr->cr_msg); return 1; } return 0;}static int nua_publish_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; struct publish_usage *pu; if (cr->cr_event == nua_r_publish) { du = nua_dialog_usage_add(nh, nh->nh_ds, nua_publish_usage, NULL); if (!du) return -1; pu = nua_dialog_usage_private(du); pu->pu_published = 0; if (sip->sip_if_match) { pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_if_match); if (!pu->pu_etag) return -1; sip_header_remove(msg, sip, (sip_header_t *)sip->sip_if_match); } } else du = nua_dialog_usage_get(nh->nh_ds, nua_publish_usage, NULL); cr->cr_usage = du; return 0;}staticint nua_publish_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags){ nua_dialog_usage_t *du = cr->cr_usage; int un, done; sip_etag_t const *etag = NULL; un = cr->cr_terminating || cr->cr_event != nua_r_publish || (du && du->du_shutdown) || (sip->sip_expires && sip->sip_expires->ex_delta == 0); cr->cr_terminating = un; done = un; if (du) { struct publish_usage *pu = nua_dialog_usage_private(du); if (nua_client_bind(cr, du) < 0) return -1; if (pu->pu_published) done = 1; etag = pu->pu_etag; } return nua_base_client_trequest(cr, msg, sip, SIPTAG_IF_MATCH(etag), TAG_IF(done, SIPTAG_PAYLOAD(NONE)), TAG_IF(done, SIPTAG_CONTENT_TYPE(NONE)), TAG_IF(un, SIPTAG_EXPIRES_STR("0")), TAG_NEXT(tags));}static int nua_publish_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip){ char const *restarting = NULL; if (cr->cr_terminating || !cr->cr_usage) ; else if (status == 412) restarting = phrase; else if (200 <= status && status < 300 && sip->sip_expires && sip->sip_expires->ex_delta == 0) restarting = "Immediate re-PUBLISH"; if (restarting) { struct publish_usage *pu = nua_dialog_usage_private(cr->cr_usage); if (pu) { pu->pu_published = 0; su_free(cr->cr_owner->nh_home, pu->pu_etag), pu->pu_etag = NULL; if (nua_client_restart(cr, 100, restarting)) return 0; } } return nua_base_client_check_restart(cr, status, phrase, sip);}static int nua_publish_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; if (!cr->cr_terminated && du && sip) { struct publish_usage *pu = nua_dialog_usage_private(du); sip_expires_t const *ex = sip->sip_expires; /* Reset state */ pu->pu_published = 0; if (pu->pu_etag) su_free(nh->nh_home, pu->pu_etag), pu->pu_etag = NULL; if (status < 300) { pu->pu_published = 1; pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_etag); if (!ex || ex->ex_delta == 0 || !pu->pu_etag) { cr->cr_terminated = 1; if (!ex || ex->ex_delta == 0) SET_STATUS(900, "Received Invalid Expiration Time"); else SET_STATUS1(NUA_ERROR_AT(__FILE__, __LINE__)); } else nua_dialog_usage_set_refresh(du, ex->ex_delta); } } return nua_base_client_response(cr, status, phrase, sip, NULL);}static void nua_publish_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now){ nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 0) >= 0) return; } nua_stack_event(nh->nh_nua, nh, NULL, nua_r_publish, NUA_ERROR_AT(__FILE__, __LINE__), NULL); nua_dialog_usage_remove(nh, ds, du, NULL, NULL);}/** @interal Shut down PUBLISH usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */static int nua_publish_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du){ nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 1) >= 0) return 0; } /* XXX - report to user */ nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200;}/* ---------------------------------------------------------------------- *//* Server side *//** @NUA_EVENT nua_i_publish * * Incoming PUBLISH request. * * In order to receive #nua_i_publish events, the application must enable * both the PUBLISH method with NUTAG_ALLOW() tag and the acceptable SIP * events with nua_set_params() tag NUTAG_ALLOW_EVENTS(). * * The nua_response() call responding to a PUBLISH request must have * NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag. Note that * a successful response to PUBLISH @b MUST include @Expires and @SIPETag * headers. * * The PUBLISH request does not create a dialog. Currently the processing * of incoming PUBLISH creates a new handle for each incoming request which * is not assiciated with an existing dialog. If the handle @a nh is not * bound, you should probably destroy it after responding to the PUBLISH * request. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with the incoming request * @param hmagic application context associated with the call * (usually NULL) * @param sip incoming PUBLISH request * @param tags empty * * @sa @RFC3903, nua_respond(), * @Expires, @SIPETag, @SIPIfMatch, @Event, * nua_subscribe(), #nua_i_subscribe, * nua_notifier(), #nua_i_subscription, * * @since First used in @VERSION_1_12_4 * * @END_NUA_EVENT */int nua_publish_server_init(nua_server_request_t *sr);nua_server_methods_t const nua_publish_server_methods = { SIP_METHOD_PUBLISH, nua_i_publish, /* Event */ { 0, /* Do not create dialog */ 0, /* Initial request */ 0, /* Not a target refresh request */ 1, /* Add Contact */ }, nua_publish_server_init, nua_base_server_preprocess, nua_base_server_params, nua_base_server_respond, nua_base_server_report, };int nua_publish_server_init(nua_server_request_t *sr){ sip_allow_events_t *allow_events = NH_PGET(sr->sr_owner, allow_events); sip_event_t *o = sr->sr_request.sip->sip_event; char const *event = o ? o->o_type : NULL; if (!allow_events) return SR_STATUS1(sr, SIP_501_NOT_IMPLEMENTED); else if (!event || !msg_header_find_param(allow_events->k_common, event)) return SR_STATUS1(sr, SIP_489_BAD_EVENT); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -