Example #1
0
int set_call_leg( struct sip_msg *msg, struct cc_call *call, str *new_leg)
{
	str* id;

	LM_DBG("call %p moving to %.*s , state %d\n", call,
		new_leg->len, new_leg->s, call->state);

	if (call->b2bua_id.len==0) {
		/* b2b instance not initialized yet =>
		 * create new b2bua instance */
		call->ref_cnt++;
		id = b2b_api.init( msg, &b2b_scenario, &new_leg, b2bl_callback_customer,
				(void*)call, B2B_DESTROY_CB|B2B_REJECT_CB|B2B_BYE_CB, NULL /* custom_hdrs */ );
		if (id==NULL || id->len==0 || id->s==NULL) {
			LM_ERR("failed to init new b2bua call (empty ID received)\n");
			return -2;
		}
		
		call->b2bua_id.s = (char*)shm_malloc(id->len);
		if (call->b2bua_id.s==NULL) {
			LM_ERR("failed to allocate b2bua ID\n");
			return -1;
		}
		memcpy( call->b2bua_id.s, id->s, id->len);
		/* this must be the last, as we use it as marker for checking
         * if b2b entity is initialized */
		call->b2bua_id.len = id->len;
	} else {
		/* call already ongoing */
		if(b2b_api.bridge( &call->b2bua_id, new_leg, &call->caller_dn, 0) < 0) {
			LM_ERR("bridging failed\n");
			b2b_api.terminate_call(&call->b2bua_id);
			return -1;
		}
	}
	/* remember last time when the call started */
	call->last_start = get_ticks();
	//b2b_api.set_state(&call->b2bua_id, call->state);
	return 0;
}
Example #2
0
static int load_sca_info_from_db(void)
{
	db_res_t * res = NULL;
	db_val_t * values;
	db_row_t * rows;
	int i, j, nr_rows;
	unsigned int valid_record;
	unsigned int n_result_cols = 0;
	unsigned int shared_line_col, watchers_col;
	unsigned int app_shared_entity_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_state_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_appearance_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_b2bl_key_col[MAX_APPEARANCE_INDEX];
	db_key_t q_cols[SCA_TABLE_TOTAL_COL_NO];

	str shared_line, watchers_csv;
	//str_lst_t *watchers;
	//unsigned int size, watcher_size, watchers_no;
	//unsigned int size;
	unsigned int hash_index;
	//char *p;
	b2b_sca_record_t *record;
	b2b_sca_call_t *call;
	unsigned int shared_entity, appearance_index, call_state;
	str call_info_uri, call_info_apperance_uri, b2bl_key;
	b2bl_cb_ctx_t *cb_params;

	if(use_sca_table()) return -1;

	q_cols[shared_line_col = n_result_cols++] = &shared_line_column;
	q_cols[watchers_col = n_result_cols++] = &watchers_column;

	for (i=0; i<MAX_APPEARANCE_INDEX; i++) {
		q_cols[app_shared_entity_col[i]	= n_result_cols++] = &app_shared_entity_column[i];
		q_cols[app_call_state_col[i] = n_result_cols++] = &app_call_state_column[i];
		q_cols[app_call_info_uri_col[i] = n_result_cols++] = &app_call_info_uri_column[i];
		q_cols[app_call_info_appearance_uri_col[i] = n_result_cols++] =
						&app_call_info_appearance_uri_column[i];
		q_cols[app_b2bl_key_col[i] = n_result_cols++] = &app_b2bl_key_column[i];
	}

	/* select the whole tabel and all the columns */
	if (DB_CAPABILITY(sca_dbf, DB_CAP_FETCH)) {
		if(sca_dbf.query(sca_db_handle, 0, 0, 0, q_cols, 0,
				SCA_TABLE_TOTAL_COL_NO, 0, 0) < 0) {
			LM_ERR("Error while querying (fetch) database\n");
			return -1;
		}
		if(sca_dbf.fetch_result(sca_db_handle, &res, SCA_FETCH_SIZE)<0){
			LM_ERR("fetching rows failed\n");
			return -1;
		}
	} else {
		if(sca_dbf.query(sca_db_handle, 0, 0, 0, q_cols, 0,
				SCA_TABLE_TOTAL_COL_NO, 0, &res) < 0) {
			LM_ERR("Error while querying database\n");
			return -1;
		}
	}

	nr_rows = RES_ROW_N(res);

	do {
		LM_DBG("loading [%i] records from db\n", nr_rows);
		rows = RES_ROWS(res);
		/* for every row/record */
		for(i=0; i<nr_rows; i++){
			values = ROW_VALUES(rows + i);
			if (VAL_NULL(values+shared_line_col) || VAL_NULL(values+watchers_col)) {
				LM_ERR("columns [%.*s] or/and [%.*s] cannot be null -> skipping\n",
					shared_line_column.len, shared_line_column.s,
					watchers_column.len, watchers_column.s);
				continue;
			}
			shared_line.s = (char*)values[shared_line_col].val.string_val;
			shared_line.len = strlen(shared_line.s);

			watchers_csv.s = (char*)values[watchers_col].val.string_val;
			watchers_csv.len = strlen(watchers_csv.s);

			record = restore_record(&shared_line, &watchers_csv);
			if (record == NULL)
				goto error;
			hash_index = core_hash(&shared_line, NULL, b2b_sca_hsize);

			j = 0;
			while (j < MAX_APPEARANCE_INDEX) {
				if(	VAL_NULL(values + app_shared_entity_col[j]) ||
					VAL_NULL(values + app_call_state_col[j]) ||
					VAL_NULL(values + app_call_info_uri_col[j]) ||
					VAL_NULL(values + app_call_info_appearance_uri_col[j]) ||
					VAL_NULL(values + app_b2bl_key_col[j]) ) {
					goto cont;
				}
				appearance_index = j + 1;
				/* 1 - get shared_entity */
				shared_entity = values[app_shared_entity_col[j]].val.int_val;
				if (shared_entity!=0 && shared_entity!=1) {
					LM_ERR("Unexpected shared_entity [%d] "
						"for shared_line [%.*s]\n",
						shared_entity, shared_line.len, shared_line.s);
					goto cont;
				}
				/* 2 - get call_state */
				call_state = values[app_call_state_col[j]].val.int_val;
				if (call_state == IDLE_STATE) {
					LM_DBG("empty call[%d]\n", appearance_index);
					goto cont;
				}
				if (call_state > MAX_INDEX_STATE) {
					LM_ERR("Unexpected call_state [%d] for shared_line [%.*s]\n",
						call_state, shared_line.len, shared_line.s);
					goto cont;
				}
				/* 3 - get call_info_uri */
				call_info_uri.s =
					(char*)values[app_call_info_uri_col[j]].val.string_val;
				if (call_info_uri.s)
					call_info_uri.len = strlen(call_info_uri.s);
				else {
					LM_ERR("Missing call_info_uri for shared_line [%.*s][%d]\n",
						shared_line.len, shared_line.s, appearance_index);
					goto cont;
				}
				LM_DBG("call_info_uri=[%.*s]\n",
					call_info_uri.len, call_info_uri.s);
				/* 4 - get call_info_apperance_uri */
				call_info_apperance_uri.s =
					(char*)
					values[app_call_info_appearance_uri_col[j]].val.string_val;
				if (call_info_apperance_uri.s)
					call_info_apperance_uri.len =
						strlen(call_info_apperance_uri.s);
				else {
					LM_ERR("Missing call_info_apperance_uri for "
						"shared_line [%.*s][%d]\n",
						shared_line.len, shared_line.s, appearance_index);
					goto cont;
				}
				LM_DBG("call_info_apperance_uri=[%.*s]\n",
					call_info_apperance_uri.len, call_info_apperance_uri.s);
				/* 5 - get b2bl_key */
				b2bl_key.s = (char*)values[app_b2bl_key_col[j]].val.string_val;
				if (b2bl_key.s) {
					b2bl_key.len = strlen(b2bl_key.s);
					if (b2bl_key.len > B2BL_MAX_KEY_LEN) {
						LM_ERR("buffer overflow on b2bl_key [%.*s]"
							" for shared_line [%.*s][%d]\n",
							b2bl_key.len, b2bl_key.s,
							shared_line.len, shared_line.s,
							appearance_index);
						goto cont;
					}
					LM_DBG("b2bl_key=[%.*s]\n", b2bl_key.len, b2bl_key.s);
				} else {
					LM_ERR("Missing b2bl_key for shared_line [%.*s][1]\n",
						shared_line.len, shared_line.s);
					goto cont;
				}
				/* restore the call */
				call = restore_call(record, appearance_index,
					shared_entity, call_state,
					&call_info_uri, &call_info_apperance_uri);
				if (call == NULL) {
					goto error;
				}
				/* update record */
				if (0!=b2b_sca_update_call_record_key(call, &b2bl_key)) {
					LM_ERR("Unable to update b2bl_key [%.*s]\n",
						b2bl_key.len, b2bl_key.s);
					shm_free(call);
					call = NULL;
					record->call[appearance_index-1] = NULL;
					goto cont;
				}
				/* Prepare b2b_logic callback params. */
				cb_params = build_cb_params(hash_index,
							&shared_line, appearance_index);
				if (cb_params == NULL) {
					LM_ERR("Unable to build cb_params\n");
					goto error;
				}
				/* re-register callbacks */
				if(b2bl_api.register_cb(&b2bl_key, &sca_logic_notify, cb_params,
					B2B_RE_INVITE_CB|B2B_CONFIRMED_CB|B2B_DESTROY_CB) != 0){
					LM_ERR("Unable register b2b cb\n");
					shm_free(call);
					call = NULL;
					record->call[appearance_index-1] = NULL;
					goto cont;
				}
cont:
				j++;
			}

			valid_record = j = 0;
			while (j < MAX_APPEARANCE_INDEX) {
				if (record->call[j]) {
					valid_record = 1;
					goto check_valid_record;
				}
				j++;
			}
check_valid_record:
			if (valid_record) {
				b2b_sca_print_record(record);
				insert_record(hash_index, record);
			} else {
				LM_DBG("removing the record from db!\n");
				delete_sca_info_from_db(record);
			}
			LM_DBG("Done\n");
		}

		/* any more data to be fetched ?*/
		if (DB_CAPABILITY(sca_dbf, DB_CAP_FETCH)) {
			if (sca_dbf.fetch_result(sca_db_handle, &res, SCA_FETCH_SIZE)<0) {
				LM_ERR("fetching more rows failed\n");
				goto error;
			}
			nr_rows = RES_ROW_N(res);
		} else {
			nr_rows = 0;
		}
	}while (nr_rows>0);

	sca_dbf.free_result(sca_db_handle, res);
	return 0;
error:
	sca_dbf.free_result(sca_db_handle, res);
	return -1;
}
Example #3
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 #4
0
int sca_init_request(struct sip_msg* msg, str* p1, str* p2)
{
	int method_value, ret;
	//unsigned int size, hash_index, shared_entity;
	unsigned int hash_index, shared_entity, app_index;
	str *b2bl_key, *host, *port, *display, *uri, *shared_line;
	//char *p;
	//uri_type scheme;
	struct to_body *appearance_name_addr_body;
	pv_value_t pv_val;
	b2b_sca_record_t *record = NULL;
	b2b_sca_call_t *call = NULL;
	b2bl_cb_ctx_t *cb_params;

	str publish_hdr = {NULL, 0};
	str custom_hdr = {NULL, 0};
	str call_info_uri = {NULL, 0};
	str call_info_apperance_uri = {NULL, 0};

	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 initiate 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 (p1 && (pv_get_spec_value(msg, (pv_spec_t *)p1, &pv_val) == 0)) {
		if (pv_val.flags & PV_VAL_INT) {
			shared_entity = pv_val.ri;
			LM_DBG("got shared_entity %d\n", shared_entity);
		} else if (pv_val.flags & PV_VAL_STR) {
			if(str2int(&(pv_val.rs), (unsigned int*)&shared_entity) != 0) {
				LM_ERR("Unable to get entity_no from pv '%.*s'\n",
				pv_val.rs.len, pv_val.rs.s);
				return -1;
			}
		} else {
			LM_ERR("shared entity not a str or int type\n");
			return -1;
		}
	} else {
		LM_ERR("Unable to get shared entity from pv:%p\n", p1);
		return -1;
	}

	switch (shared_entity) {
	case 0:
		LM_DBG("Incoming call from shared line\n");
		break;
	case 1:
		LM_DBG("Outgoing call via a shared line\n");
		break;
	default:
		LM_ERR("shared line entity should be 0 or 1\n");
		return -1;
	}

	/* Get the hash index for the shared line.  */
	if (get_hash_index_and_shared_line(msg, &hash_index, &shared_line)<0)
		return -1;
	LM_DBG("got hash_index=[%d] for shared line [%.*s]\n",
			hash_index, shared_line->len, shared_line->s);

	/* Get the appearance name-addr for this call.  */
	appearance_name_addr_body = get_appearance_name_addr(msg);
	if (appearance_name_addr_body == NULL) {
		LM_ERR("unable to get apperance of this call\n");
		return -1;
	}
	//scheme = appearance_name_addr_body->parsed_uri.type;
	host = &appearance_name_addr_body->parsed_uri.host;
	port = &appearance_name_addr_body->parsed_uri.port;
	display = &appearance_name_addr_body->display;
	uri = &appearance_name_addr_body->uri;
	LM_DBG("display uri [%.*s][%.*s] from host:port [%.*s]:[%.*s]\n",
			display->len, display->s, uri->len, uri->s,
			host->len, host->s, port->len, port->s);


	/* Prepare absoluteURI for Call-Info header.
	 */
	if (build_absoluteURI(host, port, &call_info_uri) != 0)
		goto error1;

	/* Prepare appearanceURI param for Call-Info header.  */
	if (build_appearanceURI(display, uri, &call_info_apperance_uri) != 0)
		goto error1;

	/* Extract required appearance from the received request */
	app_index = get_app_index(msg);

	/* Adding call to the sca_table.  */
	lock_get(&b2b_sca_htable[hash_index].lock);
	if (b2b_sca_add_call_record(hash_index, shared_line, shared_entity, app_index,
			&call_info_uri, &call_info_apperance_uri, &record, &call) != 0) {
		LM_ERR("unable to add record to sca htable\n");
		goto error2;
	}

	/* Prepare INVITE Call-Info header.  */
	if (build_invite_call_info_header(call, &call_info_uri, &custom_hdr) != 0)
		goto error2;

	/* Prepare PUBLISH Call-Info header.  */
	if (build_publish_call_info_header(record, &publish_hdr) != 0) {
		LM_ERR("Unable to build PUBLISH Call-Info header\n");
		goto error2;
	}

	/* Prepare b2b_logic callback params. */
	cb_params = build_cb_params(hash_index, shared_line, call->appearance_index);
	if (cb_params == NULL)
		goto error2;

	LM_DBG("*** INITIALIZING \"top hiding\" SCENARIO with cb_params [%p]\n", cb_params);
	/* release the lock here to avoid deadlock while getting callback notifications */
	lock_release(&b2b_sca_htable[hash_index].lock);
	b2bl_key = b2bl_api.init(msg, &scenario, NULL, &sca_logic_notify, (void *)cb_params,
			B2B_RE_INVITE_CB|B2B_CONFIRMED_CB|B2B_DESTROY_CB, &custom_hdr);
	lock_get(&b2b_sca_htable[hash_index].lock);

	if (!b2bl_key || !b2bl_key->s || !b2bl_key->len)
		goto error2;
	else if (b2b_sca_update_call_record_key(call, b2bl_key) != 0)
		goto error3;

	/* Save the record to db. */
	if (push_sca_info_to_db(record, call->appearance_index, 0) != 0)
		goto error3;

	/* Notify the watchers. */
	sca_publish(record, &publish_hdr);

	lock_release(&b2b_sca_htable[hash_index].lock);


	if (publish_hdr.s != publish_call_info_hdr_buf)
		pkg_free(publish_hdr.s);
	if (custom_hdr.s != invite_call_info_hdr_buf)
		pkg_free(custom_hdr.s);
	if (call_info_uri.s != call_info_uri_buf)
		pkg_free(call_info_uri.s);
	if (call_info_apperance_uri.s != call_info_apperance_uri_buf)
		pkg_free(call_info_apperance_uri.s);

	return 1;

error3:
	/* Release the call */
	b2bl_api.terminate_call(b2bl_key);
error2:
	lock_release(&b2b_sca_htable[hash_index].lock);
error1:
	if (publish_hdr.s != publish_call_info_hdr_buf)
		pkg_free(publish_hdr.s);
	if (custom_hdr.s != invite_call_info_hdr_buf)
		pkg_free(custom_hdr.s);
	if (call_info_uri.s != call_info_uri_buf)
		pkg_free(call_info_uri.s);
	if (call_info_apperance_uri.s != call_info_apperance_uri_buf)
		pkg_free(call_info_apperance_uri.s);

	return -1;
}