Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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(&param->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;
}