void b2b_sca_delete_call_record(int hash_index, b2b_sca_record_t *record, unsigned int appearance) { b2b_sca_call_t *call = b2b_sca_search_call_safe(record, appearance); if (call) { shm_free(call); record->call[appearance - 1] = NULL; } return; }
int sca_bridge_request(struct sip_msg* msg, str* p1, str* p2) { pv_value_t pv_val; str shared_line = {NULL, 0}; str publish_hdr = {NULL, 0}; int method_value, ret; //int entity_no; unsigned int hash_index; b2b_sca_record_t *record = NULL; b2b_sca_call_t *call; unsigned int appearance; if (p1 && (pv_get_spec_value(msg, (pv_spec_t *)p1, &pv_val) == 0)) { if (pv_val.flags & PV_VAL_STR) { LM_DBG("got shared_line:'%.*s'\n", pv_val.rs.len, pv_val.rs.s); shared_line = pv_val.rs; } else { LM_ERR("Unable to get shared_line from PV that is not a string\n"); return -1; } } else { LM_ERR("Unable to get shared_line from pv:%p\n", p1); return -1; } /* Get the hash index for the shared line. */ hash_index = core_hash(&shared_line, NULL, b2b_sca_hsize); LM_DBG("got hash_index=[%d] for shared line [%.*s]\n", hash_index, shared_line.len, shared_line.s); if (parse_headers(msg, HDR_EOH_F, 0) < 0) { LM_ERR("failed to parse message\n"); return -1; } method_value = msg->first_line.u.request.method_value; if (method_value != METHOD_INVITE) { LM_ERR("nonINVITE [%d] cannot bridge a call\n", method_value); return -1; } ret = tmb.t_newtran(msg); if(ret < 1) { if(ret == 0) { LM_DBG("It is a retransmission, drop\n"); tmb.unref_cell(tmb.t_gett()); } else { LM_ERR("Error when creating tm transaction\n"); } return 0; } if (!msg->call_info) { LM_ERR("No 'Call-Info' header\n"); return -1; } /* Extract required appearance from the received request */ appearance = get_app_index(msg); if (appearance==0) return -1; lock_get(&b2b_sca_htable[hash_index].lock); record = b2b_sca_search_record_safe(hash_index, &shared_line); if (record == NULL) { lock_release(&b2b_sca_htable[hash_index].lock); LM_ERR("record not found for shared line [%.*s] on hash index [%d]\n", shared_line.len, shared_line.s, hash_index); // FIXME: /* Build an empty PUBLISH header */ //if (build_publish_call_info_header(NULL, &publish_hdr) != 0) { // LM_ERR("Unable to build PUBLISH Call-Info header\n"); //} goto error; } b2b_sca_print_record(record); call = b2b_sca_search_call_safe(record, appearance); if (call == NULL) goto error; if (call->call_state != HELD_STATE) { LM_ERR("Improper call state [%d] for bridging\n", call->call_state); goto error; } /* What will happen if the b2b_logic entity doesn't exist anymore? */ LM_DBG("*** BRIDGING THE REQUEST to entity [%d] on tuple [%.*s]\n", call->shared_entity, call->b2bl_key.len, call->b2bl_key.s); ret = b2bl_api.bridge_msg(msg, &call->b2bl_key, call->shared_entity); if (ret != 0) { /* FIXME: * handle the error here */ LM_ERR("*** got ret [%d]\n", ret); goto error; } LM_DBG("*** got ret [%d]\n", ret); /* Set the state back to active */ call->call_state = ACTIVE_STATE; /* Reset the shared_entity */ call->shared_entity = 0; /* Prepare PUBLISH Call-Info header. */ if (build_publish_call_info_header(record, &publish_hdr) != 0) { lock_release(&b2b_sca_htable[hash_index].lock); LM_ERR("Unable to build PUBLISH Call-Info header\n"); return B2B_FOLLOW_SCENARIO_CB_RET; } /* Save the record to db. */ if (push_sca_info_to_db(record, appearance, 1) != 0) LM_ERR("db out of synch\n"); /* Notify the watchers. */ sca_publish(record, &publish_hdr); lock_release(&b2b_sca_htable[hash_index].lock); return 1; error: lock_release(&b2b_sca_htable[hash_index].lock); if (publish_hdr.s && publish_hdr.s != publish_call_info_hdr_buf) pkg_free(publish_hdr.s); return -1; }
int sca_logic_notify(b2bl_cb_params_t *params, unsigned int b2b_event) { int on_hold = 0; int sdp_session_num = 0, sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; struct sip_msg *msg = params->msg; b2bl_cb_ctx_t *cb_params = params->param; str *shared_line; unsigned int hash_index, appearance; b2b_sca_record_t *record; b2b_sca_call_t *call = NULL; str publish_hdr; unsigned int call_info_appearance; unsigned int call_info_appearance_state = 0; struct hdr_field *call_info; struct call_info_body *callinfo_b; struct to_body *call_info_b; struct to_param *param; if (b2b_sca_shutdown_completed) return B2B_FOLLOW_SCENARIO_CB_RET; if (params == NULL) { LM_ERR("callback event [%d] without cb params\n", b2b_event); return B2B_DROP_MSG_CB_RET; } shared_line = &cb_params->shared_line; hash_index = cb_params->hash_index; appearance = cb_params->appearance; LM_DBG("*** GOT NOTIFICATION TYPE [%d] WITH cb_params [%p]->[%.*s] appearance [%d] on hash index [%d]" " for b2bl entity [%d]\n", b2b_event, cb_params, shared_line->len, shared_line->s, appearance, hash_index, params->entity); if (msg && msg->call_info) { if (0 == parse_call_info_header(msg)) { call_info = msg->call_info; if (call_info) { LM_DBG("BODY=[%p]->[%.*s] sibling=[%p]\n", call_info, call_info->body.len, call_info->body.s, call_info->sibling); callinfo_b = call_info->parsed; while (callinfo_b) { call_info_b = &(callinfo_b->call_info_body); LM_DBG(". body=[%.*s] param_lst=[%p] last_param=[%p]\n", call_info_b->body.len, call_info_b->body.s, call_info_b->param_lst, call_info_b->last_param); param = call_info_b->param_lst; while (param) { LM_DBG(".. [%p]->[%d] [%.*s]=[%.*s]->[%p]\n", param, param->type, param->name.len, param->name.s, param->value.len, param->value.s, param->next); if (param->name.len==APPEARANCE_INDEX_LEN && strncmp(APPEARANCE_INDEX_STR, param->name.s, APPEARANCE_INDEX_LEN)==0) { if (strno2int(¶m->value,&call_info_appearance)<0) { LM_ERR("bad appearance-index [%.*s]\n", param->value.len, param->value.s); return -1; } if (appearance != call_info_appearance) { LM_ERR("got appearance[%d] while expecting[%d]\n", call_info_appearance, appearance); goto next_callinfo_b; } else { LM_DBG("*** GOT APP-INDEX [%d]\n", call_info_appearance); } } else if (param->name.len==APPEARANCE_STATE_LEN && strncmp(APPEARANCE_STATE_STR, param->name.s, APPEARANCE_STATE_LEN)==0) { LM_DBG("*** GOT APP-STATE [%.*s]\n", param->value.len, param->value.s); if (param->value.len == strlen(APP_STATE_HELD_PRIVATE) && strncmp(param->value.s, app_state[HELD_PRIVATE_STATE].s, param->value.len)==0) { call_info_appearance_state = HELD_PRIVATE_STATE; } } param=param->next; } goto handle_appearance; next_callinfo_b: callinfo_b = callinfo_b->next; } call_info = call_info->sibling; } } else { LM_ERR("Unable to parse Call-Info header\n"); return B2B_DROP_MSG_CB_RET; } } handle_appearance: lock_get(&b2b_sca_htable[hash_index].lock); record = b2b_sca_search_record_safe(hash_index, shared_line); if (record == NULL) { lock_release(&b2b_sca_htable[hash_index].lock); LM_ERR("record not found for shared line [%.*s] on hash index [%d]\n", shared_line->len, shared_line->s, hash_index); return B2B_DROP_MSG_CB_RET; } b2b_sca_print_record(record); switch(b2b_event){ case B2B_DESTROY_CB: /* Destroy the sca index record */ shm_free(params->param); b2b_sca_delete_call_record(hash_index, record, appearance); break; case B2B_RE_INVITE_CB: case B2B_CONFIRMED_CB: call = b2b_sca_search_call_safe(record, appearance); if (call == NULL) { LM_ERR("call record not found for shared line [%.*s] with index [%d]\n", shared_line->len, shared_line->s, appearance); lock_release(&b2b_sca_htable[hash_index].lock); return B2B_DROP_MSG_CB_RET; } if (0 == parse_sdp(msg)) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; if(sdp_stream->media.len==AUDIO_STR_LEN && strncmp(sdp_stream->media.s,AUDIO_STR,AUDIO_STR_LEN)==0 && sdp_stream->is_on_hold) { on_hold = 1; break; } sdp_stream_num++; } sdp_session_num++; } if (on_hold) { if (call_info_appearance_state) call->call_state = HELD_PRIVATE_STATE; else call->call_state = HELD_STATE; } else { call->call_state = ACTIVE_STATE; } break; default: LM_ERR("Unexpected event\n"); } /* Prepare PUBLISH Call-Info header. */ if (build_publish_call_info_header(record, &publish_hdr) != 0) { lock_release(&b2b_sca_htable[hash_index].lock); LM_ERR("Unable to build PUBLISH Call-Info header\n"); return B2B_FOLLOW_SCENARIO_CB_RET; } /* Save the record to db. */ if (push_sca_info_to_db(record, appearance, 1) != 0) LM_ERR("DB out of synch\n"); /* Notify the watchers. */ sca_publish(record, &publish_hdr); b2b_sca_delete_record_if_empty(record, hash_index); lock_release(&b2b_sca_htable[hash_index].lock); if (publish_hdr.s != publish_call_info_hdr_buf) pkg_free(publish_hdr.s); return B2B_FOLLOW_SCENARIO_CB_RET; }