/*! \brief Helper function which retrieves or allocates a T.38 state information datastore */ static struct t38_state *t38_state_get_or_alloc(struct ast_sip_session *session) { RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "t38"), ao2_cleanup); struct t38_state *state; /* While the datastore refcount is decremented this is operating in the serializer so it will remain valid regardless */ if (datastore) { return datastore->data; } if (!(datastore = ast_sip_session_alloc_datastore(&t38_datastore, "t38")) || !(datastore->data = ast_calloc(1, sizeof(struct t38_state))) || ast_sip_session_add_datastore(session, datastore)) { return NULL; } state = datastore->data; /* This will get bumped up before scheduling */ state->timer.user_data = session; state->timer.cb = t38_automatic_reject_timer_cb; datastore->data = state; return state; }
/*! * \internal * \brief Session supplement callback on an incoming INVITE request * * Retrieve the header_datastore from the session or create one if it doesn't exist. * Create and initialize the list if needed. * Insert the headers. */ static int incoming_request(struct ast_sip_session *session, pjsip_rx_data * rdata) { pj_pool_t *pool = session->inv_session->dlg->pool; RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup); if (!datastore) { if (!(datastore = ast_sip_session_alloc_datastore(&header_datastore, header_datastore.type)) || !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list))) || ast_sip_session_add_datastore(session, datastore)) { ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n"); return 0; } AST_LIST_HEAD_INIT((struct hdr_list *) datastore->data); } insert_headers(pool, (struct hdr_list *) datastore->data, rdata->msg_info.msg); return 0; }
/*! * \internal * \brief Implements PJSIP_HEADER 'add' by inserting the specified header into thge list. * * Retrieve the header_datastore from the session or create one if it doesn't exist. * Create and initialize the list if needed. * Create the pj_strs for name and value. * Create pjsip_msg and hdr_list_entry. * Add the entry to the list. */ static int add_header(void *obj) { struct header_data *data = obj; struct ast_sip_session *session = data->channel->session; pj_pool_t *pool = session->inv_session->dlg->pool; pj_str_t pj_header_name; pj_str_t pj_header_value; struct hdr_list_entry *le; struct hdr_list *list; RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup); if (!datastore) { if (!(datastore = ast_sip_session_alloc_datastore(&header_datastore, header_datastore.type)) || !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list))) || ast_sip_session_add_datastore(session, datastore)) { ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n"); return -1; } AST_LIST_HEAD_INIT((struct hdr_list *) datastore->data); } ast_debug(1, "Adding header %s with value %s\n", data->header_name, data->header_value); pj_cstr(&pj_header_name, data->header_name); pj_cstr(&pj_header_value, data->header_value); le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry)); le->hdr = (pjsip_hdr *) pjsip_generic_string_hdr_create(pool, &pj_header_name, &pj_header_value); list = datastore->data; AST_LIST_INSERT_TAIL(list, le, nextptr); return 0; }
static int handle_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata) { struct ast_datastore *sip_session_datastore; struct ast_channel *other_party; int has_feature; int has_reason; if (!session->channel) { return 0; } has_feature = has_call_feature(rdata); has_reason = has_diversion_reason(rdata); if (!has_feature && !has_reason) { /* If we don't have a call feature or diversion reason or if it's not a feature this module is related to then there is nothing to do. */ return 0; } /* Check bridge status... */ other_party = ast_channel_bridge_peer(session->channel); if (!other_party) { /* The channel wasn't in a two party bridge */ ast_log(LOG_WARNING, "%s (%s) attempted to transfer to voicemail, " "but was not in a two party bridge.\n", ast_sorcery_object_get_id(session->endpoint), ast_channel_name(session->channel)); send_response(session, 400, rdata); return -1; } sip_session_datastore = ast_sip_session_alloc_datastore( &call_feature_info, DATASTORE_NAME); if (!sip_session_datastore) { ast_channel_unref(other_party); send_response(session, 500, rdata); return -1; } sip_session_datastore->data = other_party; if (ast_sip_session_add_datastore(session, sip_session_datastore)) { ast_channel_unref(other_party); ao2_ref(sip_session_datastore, -1); send_response(session, 500, rdata); return -1; } ao2_ref(sip_session_datastore, -1); if (has_feature) { pbx_builtin_setvar_helper(other_party, SEND_TO_VM_HEADER, SEND_TO_VM_HEADER_VALUE); } if (has_reason) { pbx_builtin_setvar_helper(other_party, SEND_TO_VM_REDIRECT, SEND_TO_VM_REDIRECT_VALUE); } return 0; }