/* * Parse Event header. */ static pjsip_hdr *parse_hdr_event(pjsip_parse_ctx *ctx) { pjsip_event_hdr *hdr = pjsip_event_hdr_create(ctx->pool); const pj_str_t id_param = { "id", 2 }; const pjsip_parser_const_t *pc = pjsip_parser_const(); pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->event_type); while (*ctx->scanner->curptr == ';') { pj_str_t pname, pvalue; pj_scan_get_char(ctx->scanner); pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0); if (pj_stricmp(&pname, &id_param)==0) { hdr->id_param = pvalue; } else { pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); param->name = pname; param->value = pvalue; pj_list_push_back(&hdr->other_param, param); } } pjsip_parse_end_hdr_imp( ctx->scanner ); return (pjsip_hdr*)hdr; }
static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool, const pjsip_event_hdr *rhs) { pjsip_event_hdr *hdr = pjsip_event_hdr_create(pool); pj_strdup(pool, &hdr->event_type, &rhs->event_type); pj_strdup(pool, &hdr->id_param, &rhs->id_param); pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param); return hdr; }
static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flags) { struct unsolicited_mwi_data *mwi_data = arg; struct mwi_subscription *sub = mwi_data->sub; struct ast_sip_endpoint *endpoint = mwi_data->endpoint; pjsip_evsub_state state = mwi_data->state; const struct ast_sip_body *body = mwi_data->body; struct ast_sip_contact *contact = obj; const char *state_name; pjsip_tx_data *tdata; pjsip_sub_state_hdr *sub_state; pjsip_event_hdr *event; const pjsip_hdr *allow_events = pjsip_evsub_get_allow_events_hdr(NULL); if (ast_sip_create_request("NOTIFY", NULL, endpoint, NULL, contact, &tdata)) { ast_log(LOG_WARNING, "Unable to create unsolicited NOTIFY request to endpoint %s URI %s\n", sub->id, contact->uri); return 0; } if (!ast_strlen_zero(endpoint->subscription.mwi.fromuser)) { pjsip_fromto_hdr *from = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, NULL); pjsip_name_addr *from_name_addr = (pjsip_name_addr *) from->uri; pjsip_sip_uri *from_uri = pjsip_uri_get_uri(from_name_addr->uri); pj_strdup2(tdata->pool, &from_uri->user, endpoint->subscription.mwi.fromuser); } switch (state) { case PJSIP_EVSUB_STATE_ACTIVE: state_name = "active"; break; case PJSIP_EVSUB_STATE_TERMINATED: default: state_name = "terminated"; break; } sub_state = pjsip_sub_state_hdr_create(tdata->pool); pj_cstr(&sub_state->sub_state, state_name); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) sub_state); event = pjsip_event_hdr_create(tdata->pool); pj_cstr(&event->event_type, "message-summary"); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event); pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_shallow_clone(tdata->pool, allow_events)); ast_sip_add_body(tdata, body); ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL); return 0; }
/* * Create transferee (receiver of REFER request). * */ PJ_DEF(pj_status_t) pjsip_xfer_create_uas( pjsip_dialog *dlg, const pjsip_evsub_user *user_cb, pjsip_rx_data *rdata, pjsip_evsub **p_evsub ) { pjsip_evsub *sub; pjsip_xfer *xfer; const pj_str_t STR_EVENT = {"Event", 5 }; pjsip_event_hdr *event_hdr; pj_status_t status; /* Check arguments */ PJ_ASSERT_RETURN(dlg && rdata && p_evsub, PJ_EINVAL); /* Must be request message */ PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG, PJSIP_ENOTREQUESTMSG); /* Check that request is REFER */ PJ_ASSERT_RETURN(pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_refer_method())==0, PJSIP_ENOTREFER); /* Lock dialog */ pjsip_dlg_inc_lock(dlg); /* The evsub framework expects an Event header in the request, * while a REFER request conveniently doesn't have one (pun intended!). * So create a dummy Event header. */ if (pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_EVENT, NULL)==NULL) { event_hdr = pjsip_event_hdr_create(rdata->tp_info.pool); event_hdr->event_type = STR_REFER; pjsip_msg_add_hdr(rdata->msg_info.msg, (pjsip_hdr*)event_hdr); } /* Create server subscription */ status = pjsip_evsub_create_uas( dlg, &xfer_user, rdata, PJSIP_EVSUB_NO_EVENT_ID, &sub); if (status != PJ_SUCCESS) goto on_return; /* Create server xfer subscription */ xfer = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_xfer); xfer->dlg = dlg; xfer->sub = sub; if (user_cb) pj_memcpy(&xfer->user_cb, user_cb, sizeof(pjsip_evsub_user)); /* Attach to evsub */ pjsip_evsub_set_mod_data(sub, mod_xfer.id, xfer); /* Done: */ *p_evsub = sub; on_return: pjsip_dlg_dec_lock(dlg); return status; }
/* * Create UAC subscription. */ PJ_DEF(pjsip_event_sub*) pjsip_event_sub_create( pjsip_endpoint *endpt, const pj_str_t *from, const pj_str_t *to, const pj_str_t *event, int expires, int accept_cnt, const pj_str_t accept[], void *user_data, const pjsip_event_sub_cb *cb) { pjsip_tx_data *tdata; pj_pool_t *pool; const pjsip_hdr *hdr; pjsip_event_sub *sub; PJ_USE_EXCEPTION; PJ_LOG(5,(THIS_FILE, "Creating event subscription %.*s to %.*s", event->slen, event->ptr, to->slen, to->ptr)); /* Create pool for the event subscription. */ pool = pjsip_endpt_create_pool(endpt, "esub", SUB_POOL_SIZE, SUB_POOL_INC); if (!pool) { return NULL; } /* Init subscription. */ sub = pj_pool_calloc(pool, 1, sizeof(*sub)); sub->pool = pool; sub->endpt = endpt; sub->role = PJSIP_ROLE_UAC; sub->state = PJSIP_EVENT_SUB_STATE_PENDING; sub->state_str = state[sub->state]; sub->user_data = user_data; sub->timer.id = 0; sub->default_interval = expires; pj_memcpy(&sub->cb, cb, sizeof(*cb)); pj_list_init(&sub->auth_sess); pj_list_init(&sub->route_set); sub->mutex = pj_mutex_create(pool, "esub", PJ_MUTEX_RECURSE); if (!sub->mutex) { pjsip_endpt_destroy_pool(endpt, pool); return NULL; } /* The easiest way to parse the parameters is to create a dummy request! */ tdata = pjsip_endpt_create_request( endpt, &SUBSCRIBE, to, from, to, from, NULL, -1, NULL); if (!tdata) { pj_mutex_destroy(sub->mutex); pjsip_endpt_destroy_pool(endpt, pool); return NULL; } /* * Duplicate headers in the request to our structure. */ PJ_TRY { int i; /* From */ hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, NULL); pj_assert(hdr != NULL); sub->from = pjsip_hdr_clone(pool, hdr); /* To */ hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_TO, NULL); pj_assert(hdr != NULL); sub->to = pjsip_hdr_clone(pool, hdr); /* Contact. */ sub->contact = pjsip_contact_hdr_create(pool); sub->contact->uri = sub->from->uri; /* Call-ID */ hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CALL_ID, NULL); pj_assert(hdr != NULL); sub->call_id = pjsip_hdr_clone(pool, hdr); /* CSeq */ sub->cseq = pj_rand() % 0xFFFF; /* Event. */ sub->event = pjsip_event_hdr_create(sub->pool); pj_strdup(pool, &sub->event->event_type, event); /* Expires. */ sub->uac_expires = pjsip_expires_hdr_create(pool); sub->uac_expires->ivalue = expires; /* Accept. */ sub->local_accept = pjsip_accept_hdr_create(pool); for (i=0; i<accept_cnt && i < PJSIP_MAX_ACCEPT_COUNT; ++i) { sub->local_accept->count++; pj_strdup(sub->pool, &sub->local_accept->values[i], &accept[i]); } /* Register to hash table. */ create_subscriber_key( &sub->key, pool, PJSIP_ROLE_UAC, &sub->call_id->id, &sub->from->tag); pj_mutex_lock( mgr.mutex ); pj_hash_set( pool, mgr.ht, sub->key.ptr, sub->key.slen, sub); pj_mutex_unlock( mgr.mutex ); } PJ_DEFAULT { PJ_LOG(4,(THIS_FILE, "event_sub%p (%s): caught exception %d during init", sub, state[sub->state].ptr, PJ_GET_EXCEPTION())); pjsip_tx_data_dec_ref(tdata); pj_mutex_destroy(sub->mutex); pjsip_endpt_destroy_pool(endpt, sub->pool); return NULL; } PJ_END; /* All set, delete temporary transmit data as we don't need it. */ pjsip_tx_data_dec_ref(tdata); PJ_LOG(4,(THIS_FILE, "event_sub%p (%s): client created, target=%.*s, event=%.*s", sub, state[sub->state].ptr, to->slen, to->ptr, event->slen, event->ptr)); return sub; }