unsigned int get_app_index(struct sip_msg* msg) { unsigned int appearance; struct hdr_field *call_info; struct call_info_body *callinfo_b; struct to_body *call_info_b; struct to_param *param; if (0 == parse_call_info_header(msg)) { call_info = msg->call_info; while (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, &appearance)<0) { LM_ERR("bad appearance-index" " [%.*s]\n", param->value.len, param->value.s); return 0; } LM_DBG("*** GOT APP-INDEX [%d]\n", appearance); return appearance; } param=param->next; } callinfo_b = callinfo_b->next; } call_info = call_info->sibling; } } else { LM_ERR("Unable to parse Call-Info header\n"); return 0; } LM_ERR("appearance index not found\n"); return 0; }
int sca_set_line(struct sip_msg *msg, str *line_s, int calling) { struct dlg_cell *dlg; unsigned int idx; struct sca_line *line; /* extract the index from the call-info line */ if ( parse_call_info_header( msg )!=0 ) { LM_ERR("missing or bogus Call-Info header in INVITE\n"); return -1; } idx = get_appearance_index(msg); if (idx==0) { LM_ERR("failed to extract line index from Call-Info hdr\n"); return -1; } LM_DBG("looking for line <%.*s>, idx %d, calling %d \n", line_s->len, line_s->s, idx, calling); /* search for the line (with no creation) */ line = get_sca_line( line_s, 0); if (line==NULL) { LM_ERR("used line <%.*s> not found in hash. Using without seizing?\n", line_s->len, line_s->s); return -1; } /* NOTE: the line is now locked !!!!! */ /* check if the index is seized */ if (calling) { if (line->seize_state!=idx) { LM_ERR("line not seized or seized for other index " "(idx=%d,seize=%d)\n",idx,line->seize_state); goto error; } } /* create and bind to the dialog */ if (dlgf.create_dlg(msg,0)< 0) { LM_ERR("failed to create dialog\n"); goto error; } dlg = dlgf.get_dlg(); LM_DBG("INVITE dialog created: using line <%.*s>\n", line_s->len, line_s->s); /* store the line variable into dialog */ if (calling) { if(dlgf.store_dlg_value(dlg, &calling_line_Dvar, line_s)< 0) { LM_ERR("Failed to store calling line\n"); goto error; } } else { if(dlgf.store_dlg_value(dlg, &called_line_Dvar, line_s)< 0) { LM_ERR("Failed to store called line\n"); goto error; } } /* register callbacks */ if (dlgf.register_dlgcb( dlg, DLGCB_FAILED| DLGCB_CONFIRMED | DLGCB_TERMINATED | DLGCB_EXPIRED | DLGCB_EARLY , sca_dialog_callback, (void*)(long)idx, 0) != 0) { LM_ERR("cannot register callbacks for dialog\n"); goto error; } /* STILL LOCKED HERE !! */ terminate_line_sieze(line); /* lock released by above function */ return 1; error: unlock_sca_line(line); 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; }