Exemplo n.º 1
0
/*! Run a query based on a connection definition */
int curl_get_redirect(struct sip_msg* _m, const str *connection, str* result)
{
	curl_con_t *conn = NULL;
	curl_con_pkg_t *pconn = NULL;
	str rval;
	result->s = NULL;
	result->len = 0;

	/* Find connection if it exists */
	if (!connection) {
		LM_ERR("No cURL connection specified\n");
		return -1;
	}
	LM_DBG("******** CURL Connection %.*s\n", connection->len, connection->s);
	conn = curl_get_connection((str*)connection);
	if (conn == NULL) {
		LM_ERR("No cURL connection found: %.*s\n", connection->len, connection->s);
		return -1;
	}
	pconn = curl_get_pkg_connection(conn);
	if (pconn == NULL) {
		LM_ERR("No cURL connection data found: %.*s\n", connection->len, connection->s);
		return -1;
	}
		/* Create a STR object */
	rval.s = pconn->redirecturl;
	rval.len = strlen(pconn->redirecturl);
	/* Duplicate string to return */
	pkg_str_dup(result, &rval);
	LM_DBG("curl last redirect URL: Length %d %.*s \n", rval.len, rval.len, rval.s);

	return 1;
}
Exemplo n.º 2
0
int cl_get_my_sip_addr(int cluster_id, str *out_addr)
{
	cluster_info_t *cl;
	int rc;

	if (!cl_list_lock) {
		LM_ERR("cluster shutdown\n");
		memset(out_addr, 0, sizeof *out_addr);
		return -1;
	}
	lock_start_read(cl_list_lock);

	cl = get_cluster_by_id(cluster_id);
	if (!cl) {
		LM_ERR("unknown cluster id: %d\n", cluster_id);
		lock_stop_read(cl_list_lock);
		memset(out_addr, 0, sizeof *out_addr);
		return -1;
	}

	lock_get(cl->current_node->lock);
	if (ZSTR(cl->current_node->sip_addr)) {
		memset(out_addr, 0, sizeof *out_addr);
		rc = 0;
	} else {
		if (pkg_str_dup(out_addr, &cl->current_node->sip_addr) != 0) {
			LM_ERR("oom\n");
			memset(out_addr, 0, sizeof *out_addr);
			rc = -1;
		} else {
			rc = 0;
		}
	}

	lock_release(cl->current_node->lock);
	lock_stop_read(cl_list_lock);
	return rc;
}
Exemplo n.º 3
0
/**
 *  This function convert the rows returned in CQL query 
 *  and adds the values to the returning result structure.
 *
 * Handle CQLresult
 * \param _cql_res  handle for the CQLResult
 * \param _r result set for storage
 * \return zero on success, negative value on failure
 */
int cql_convert_row(oac::CqlResult& _cql_res, db1_res_t* _r)
{
	std::vector<oac::CqlRow>  res_cql_rows = _cql_res.rows;
	int rows_no = res_cql_rows.size();
	int cols_no = res_cql_rows[0].columns.size();
	str col_val;

	RES_ROW_N(_r) = rows_no;

	if (db_allocate_rows(_r) < 0) {
		LM_ERR("Could not allocate rows.\n");
		return -1; 
	}

	for(int ri=0; ri < rows_no; ri++) {
		if (db_allocate_row(_r, &(RES_ROWS(_r)[ri])) != 0) {
			LM_ERR("Could not allocate row.\n");
			return -2; 
		}

		/* complete the row with the columns */
		for(int col = 0; col< cols_no; col++) {
			RES_ROWS(_r)[ri].values[col].type = DB1_STR;

			col_val.s = (char*)res_cql_rows[ri].columns[col].value.c_str();
			col_val.len = strlen(col_val.s);
			pkg_str_dup(&RES_ROWS(_r)[ri].values[col].val.str_val, &col_val);
			RES_ROWS(_r)[ri].values[col].free  = 1;
			RES_ROWS(_r)[ri].values[col].nul  = 0;

			LM_DBG("Field index %d. %s = %s.\n", col,
				res_cql_rows[ri].columns[col].name.c_str(),
				res_cql_rows[ri].columns[col].value.c_str());
		}
	}
	return 0;
}
Exemplo n.º 4
0
static int cassa_convert_result_raw(db_val_t* sr_cell, str *col_val) {

	if(!col_val->s) {
		LM_DBG("Column not found in result - NULL\n");
		sr_cell->nul  = 1;
		return 0;
	}
	col_val->len = strlen(col_val->s);

	sr_cell->nul  = 0;
	sr_cell->free  = 0;

	switch (sr_cell->type) {
		case DB1_INT:
			if(str2int(col_val, (unsigned int*)&sr_cell->val.int_val) < 0) {
				LM_ERR("Wrong value [%s] - len=%d, expected integer\n", col_val->s, col_val->len);
				return -1;
			}
			break;
		case DB1_BIGINT:
			if(sscanf(col_val->s, "%lld", &sr_cell->val.ll_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val->s);
				return -1;
			}
			break;
		case DB1_DOUBLE:
			if(sscanf(col_val->s, "%lf", &sr_cell->val.double_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val->s);
				return -1;
			}
			break;
		case DB1_STR:
			pkg_str_dup(&sr_cell->val.str_val, col_val);
			sr_cell->free  = 1;
			break;
		case DB1_STRING:
			col_val->len++;
			pkg_str_dup(&sr_cell->val.str_val, col_val);
			sr_cell->val.str_val.len--;
			sr_cell->val.str_val.s[col_val->len-1]='\0';
			sr_cell->free  = 1;
			break;
		case DB1_BLOB:
			pkg_str_dup(&sr_cell->val.blob_val, col_val);
			sr_cell->free  = 1;
			break;
		case DB1_BITMAP:
			if(str2int(col_val, &sr_cell->val.bitmap_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val->s);
				return -1;
			}
			break;
		case DB1_DATETIME:
			if(sscanf(col_val->s, "%ld", (long int*)&sr_cell->val.time_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val->s);
				return -1;
			}
			break;
	}
	return 0;
}
Exemplo n.º 5
0
static int cassa_convert_result(db_key_t qcol, std::vector<oac::ColumnOrSuperColumn> result,
		int r_si, int r_fi, int prefix_len, db_val_t* sr_cell)
{
	str col_val;
	int idx_rescol;
	oac::Column res_col;

	idx_rescol = cassa_get_res_col(result, r_si, r_fi, prefix_len, qcol);
	if(idx_rescol< 0) {
		LM_DBG("Column not found in result %.*s\n", qcol->len, qcol->s);
		sr_cell->nul  = 1;
		return 0;
	}
	res_col = result[idx_rescol].column;

	col_val.s = (char*)res_col.value.c_str();

	if(!col_val.s) {
		LM_DBG("Column not found in result %.*s- NULL\n", qcol->len, qcol->s);
		sr_cell->nul  = 1;
		return 0;
	}
	col_val.len = strlen(col_val.s);

	sr_cell->nul  = 0;
	sr_cell->free  = 0;

	switch (sr_cell->type) {
		case DB1_INT:
			if(str2int(&col_val, (unsigned int*)&sr_cell->val.int_val) < 0) {
				LM_ERR("Wrong value [%s] - len=%d, expected integer\n", col_val.s, col_val.len);
				return -1;
			}
			break;
		case DB1_BIGINT:
			if(sscanf(col_val.s, "%lld", &sr_cell->val.ll_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val.s);
				return -1;
			}
			break;
		case DB1_DOUBLE:
			if(sscanf(col_val.s, "%lf", &sr_cell->val.double_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val.s);
				return -1;
			}
			break;
		case DB1_STR:
			pkg_str_dup(&sr_cell->val.str_val, &col_val);
			sr_cell->free  = 1;
			break;
		case DB1_STRING:
			col_val.len++;
			pkg_str_dup(&sr_cell->val.str_val, &col_val);
			sr_cell->val.str_val.len--;
			sr_cell->val.str_val.s[col_val.len-1]='\0';
			sr_cell->free  = 1;
			break;
		case DB1_BLOB:
			pkg_str_dup(&sr_cell->val.blob_val, &col_val);
			sr_cell->free  = 1;
			break;
		case DB1_BITMAP:
			if(str2int(&col_val, &sr_cell->val.bitmap_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val.s);
				return -1;
			}
			break;
		case DB1_DATETIME:
			if(sscanf(col_val.s, "%ld", (long int*)&sr_cell->val.time_val) < 0) {
				LM_ERR("Wrong value [%s], expected integer\n", col_val.s);
				return -1;
			}
			break;
	}
	return 0;
}
Exemplo n.º 6
0
/*
 * Insert or update the table for specified row key
 * _h: structure representing database connection
 * _k: key names
 * _op: operators
 * _v: values of the keys that must match
 * _uk: column names to update
 * _uv: values for the columns to update
 * _n: number of key=values pairs to compare
 * _un: number of columns to update
 */
int db_cassa_modify(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
		const db_key_t* _uk, const db_val_t* _uv, int _n, int _un)
{
	dbcassa_table_p tbc;
	char row_key[cassa_max_key_len];
	char sec_key[cassa_max_key_len];
	int64_t ts = 0;
	str ts_col_name={0, 0};
	int seckey_len;
	unsigned int curr_time = time(NULL);

	if (!_h || !CON_TABLE(_h) || !_k || !_v) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	LM_DBG("modify table=%s\n", _h->table->s);

	/** Lock table schema and construct primary and secondary key **/
	tbc = dbcassa_db_get_table(&CON_CASSA(_h)->db_name, CON_TABLE(_h));
	if(!tbc) {
		LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
		return -1;
	}
	if(tbc->ts_col)
		pkg_str_dup(&ts_col_name, (const str*)&tbc->ts_col->name);

	cassa_constr_key(_k, _v, _n, tbc->key_len, tbc->key, 0, row_key);
	cassa_constr_key(_k, _v, _n, tbc->seckey_len, tbc->sec_key, 0, sec_key);
	seckey_len = tbc->seckey_len;

	dbcassa_lock_release(tbc);

	/** Construct and send the query to Cassandra Cluster **/
	try {
		/* Set the columns */
		std::vector<oac::Mutation> mutations;
		for(int i=0; i< _un; i++) {
			if(_uv[i].nul)
				continue;

			std::stringstream out;
			std::string value;
			int cont = 0;

			switch(_uv[i].type) {
				case DB1_INT:	out << _uv[i].val.int_val;
								value = out.str();
								break;
				case DB1_BIGINT:out << _uv[i].val.ll_val;
								value = out.str();
								break;
				case DB1_DOUBLE:out << _uv[i].val.double_val;
								value = out.str();
								break;
				case DB1_BITMAP:out << _uv[i].val.bitmap_val;
								value = out.str();
								break;
				case DB1_STRING:value = _uv[i].val.string_val;
								break;
				case DB1_STR:	if(!_uv[i].val.str_val.s) {
									cont = 1;
									break;
								}
								value = std::string(_uv[i].val.str_val.s, _uv[i].val.str_val.len);
								break;
				case DB1_BLOB:	value = std::string(_uv[i].val.blob_val.s, _uv[i].val.blob_val.len);
								break;
				case DB1_DATETIME:	unsigned int exp_time = (unsigned int)_uv[i].val.time_val;
									out << exp_time;
									value = out.str();
									if(ts_col_name.s && ts_col_name.len==_uk[i]->len &&
											strncmp(ts_col_name.s, _uk[i]->s, ts_col_name.len)==0) {
										ts = exp_time;
										LM_DBG("Found timestamp col [%.*s]\n", ts_col_name.len, ts_col_name.s);
									}
									break;
			}
			if (cont)
				continue;

			LM_DBG("ADDED column [%.*s] type [%d], value [%s]\n", _uk[i]->len, _uk[i]->s,
				_uv[i].type, value.c_str());

			oac::Mutation mut;
			oac::ColumnOrSuperColumn col;
			if(seckey_len) {
				col.column.name = sec_key;
				col.column.name.push_back(cassa_key_delim);
				col.column.name.append(_uk[i]->s);
			}
			else
				col.column.name = _uk[i]->s;
			col.column.value = value;
			col.column.__isset.value = true;
			col.__isset.column = true;
			col.column.timestamp = curr_time;
			col.column.__isset.timestamp = true;
			mut.column_or_supercolumn = col;
			mut.__isset.column_or_supercolumn = true;
			mutations.push_back(mut);
		}
		if(ts_col_name.s)
			pkg_free(ts_col_name.s);
		ts_col_name.s = 0;

		if(ts) {
			int32_t ttl = ts - curr_time;
			LM_DBG("Set expires to %d seconds\n", ttl);
			for(size_t mi=0; mi< mutations.size(); mi++) {
				mutations[mi].column_or_supercolumn.column.ttl = ttl;
				mutations[mi].column_or_supercolumn.column.__isset.ttl = true;
			}
		}

		LM_DBG("Perform the mutation, add [%d] columns\n", (int)mutations.size());

		std::map<std::string, std::vector<oac::Mutation> > innerMap;
		innerMap.insert(std::pair<std::string, std::vector<oac::Mutation> > (_h->table->s, mutations));
		std::map <std::string, std::map<std::string, std::vector<oac::Mutation> > > CFMap;
		CFMap.insert(std::pair<std::string, std::map<std::string, std::vector<oac::Mutation> > >(row_key, innerMap));
		unsigned int retr = 0;

		do {
			if(CON_CASSA(_h)->con) {
				try{
					CON_CASSA(_h)->con->batch_mutate(CFMap, oac::ConsistencyLevel::ONE);
					return 0;
				}  catch (const att::TTransportException &tx) {
					LM_ERR("Failed to query: %s\n", tx.what());
				}
			}
			dbcassa_reconnect(CON_CASSA(_h));
		} while (cassa_auto_reconnect && retr++ < cassa_retries);
		LM_ERR("Failed to connect, retries exceeded.\n");
	} catch (const oac::InvalidRequestException ir) {
		LM_ERR("Failed Invalid query request: %s\n", ir.why.c_str());
	} catch (const at::TException &tx) {
		LM_ERR("Failed generic Thrift error: %s\n", tx.what());
	} catch (const std::exception &ex) {
		LM_ERR("Failed std error: %s\n", ex.what());
	} catch (...) {
		LM_ERR("Failed generic error\n");
	}

	LM_ERR("Insert/Update query failed\n");
	return -1;
}
Exemplo n.º 7
0
/**
 * @brief build a dmq node
 */
dmq_node_t *build_dmq_node(str *uri, int shm)
{
	dmq_node_t *ret = NULL;
	param_hooks_t hooks;
	param_t *params;

	/* For DNS-Lookups */
	static char hn[256];
	struct hostent *he;

	LM_DBG("build_dmq_node %.*s with %s memory\n", STR_FMT(uri),
			shm ? "shm" : "private");

	if(shm) {
		ret = shm_malloc(sizeof(dmq_node_t));
		if(ret == NULL) {
			LM_ERR("no more shm\n");
			goto error;
		}
		memset(ret, 0, sizeof(dmq_node_t));
		if(shm_str_dup(&ret->orig_uri, uri) < 0) {
			goto error;
		}
	} else {
		ret = pkg_malloc(sizeof(dmq_node_t));
		if(ret == NULL) {
			LM_ERR("no more pkg\n");
			goto error;
		}
		memset(ret, 0, sizeof(dmq_node_t));
		if(pkg_str_dup(&ret->orig_uri, uri) < 0) {
			goto error;
		}
	}
	set_default_dmq_node_params(ret);
	if(parse_uri(ret->orig_uri.s, ret->orig_uri.len, &ret->uri) < 0
			|| ret->uri.host.len > 254) {
		LM_ERR("error parsing uri\n");
		goto error;
	}
	/* if any parameters found, parse them */
	if(parse_params(&ret->uri.params, CLASS_ANY, &hooks, &params) < 0) {
		LM_ERR("error parsing params\n");
		goto error;
	}
	/* if any params found */
	if(params) {
		if(set_dmq_node_params(ret, params) < 0) {
			free_params(params);
			LM_ERR("error setting parameters\n");
			goto error;
		}
		free_params(params);
	} else {
		LM_DBG("no dmqnode params found\n");
	}
	/* resolve hostname */
	strncpy(hn, ret->uri.host.s, ret->uri.host.len);
	hn[ret->uri.host.len] = '\0';
	he = resolvehost(hn);
	if(he == 0) {
		LM_ERR("could not resolve %.*s\n", ret->uri.host.len, ret->uri.host.s);
		goto error;
	}
	hostent2ip_addr(&ret->ip_address, he, 0);

	return ret;

error:
	if(ret != NULL) {
		destroy_dmq_node(ret, shm);
	}
	return NULL;
}
Exemplo n.º 8
0
/*! Send query to server, optionally post data.
 */
static int curL_query_url(struct sip_msg* _m, const char* _url, str* _dst, const curl_query_t * const params)
{
	CURL *curl = NULL;;
	CURLcode res;  
	char *at = NULL;
	curl_res_stream_t stream;
	long stat;
	str rval;
	double download_size;
	struct curl_slist *headerlist = NULL;

	memset(&stream, 0, sizeof(curl_res_stream_t));
	stream.max_size = (size_t) params->maxdatasize;

	if(params->pconn) {
		LM_DBG("****** ##### We have a pconn - keep_connections: %d!\n", params->keep_connections);
		params->pconn->result_content_type[0] = '\0';
		params->pconn->redirecturl[0] = '\0';
		if (params->pconn->curl != NULL) {
			LM_DBG("         ****** ##### Reusing existing connection if possible\n");
			curl = params->pconn->curl;	/* Reuse existing handle */
			curl_easy_reset(curl);		/* Reset handle */
		}
	}


	if (curl == NULL) {
		curl = curl_easy_init();
	}
	if (curl == NULL) {
		LM_ERR("Failed to initialize curl connection\n");
		return -1;
	}

	LM_DBG("****** ##### CURL URL [%s] \n", _url);
	res = curl_easy_setopt(curl, CURLOPT_URL, _url);

	/* Limit to HTTP and HTTPS protocols */
	res = curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
	res = curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);

	if (params->post) {
		char ctype[256];

		ctype[0] = '\0';
		snprintf(ctype, sizeof(ctype), "Content-Type: %s", params->contenttype);

	    	/* Now specify we want to POST data */ 
		res |= curl_easy_setopt(curl, CURLOPT_POST, 1L);
		/* Set the content-type of the DATA */
		headerlist = curl_slist_append(headerlist, ctype);
		res |= curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);

		/* Tell CURL we want to upload using POST */

		res |= curl_easy_setopt(curl, CURLOPT_POSTFIELDS, params->post);

	} else {
		/* Reset post option */
		res |= curl_easy_setopt(curl, CURLOPT_POST, 0L);
	}

	if (params->maxdatasize) {
		/* Maximum data size to download - we always download full response, but
	   	cut it off before moving to pvar */
		LM_DBG("****** ##### CURL Max datasize %u\n", params->maxdatasize);
	}

	if (params->username) {
		res |= curl_easy_setopt(curl, CURLOPT_USERNAME, params->username);
		res |= curl_easy_setopt(curl, CURLOPT_HTTPAUTH, params->authmethod);
	}
	if (params->secret) {
		res |= curl_easy_setopt(curl, CURLOPT_PASSWORD, params->secret);
	}

	/* Client certificate */
	if (params->clientcert != NULL && params->clientkey != NULL) {
	    	res |= curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
	    	res |= curl_easy_setopt(curl, CURLOPT_SSLCERT, params->clientcert);

	    	res |= curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
	    	res |= curl_easy_setopt(curl, CURLOPT_SSLKEY, params->clientkey);
	}

	if (params->cacert != NULL) {
	    	res |= curl_easy_setopt(curl, CURLOPT_CAINFO, params->cacert);
	}

	if (params->tlsversion != CURL_SSLVERSION_DEFAULT) {
	    	res |= curl_easy_setopt(curl, CURLOPT_SSLVERSION, (long) params->tlsversion);
	}

	if (params->ciphersuites != NULL) {
	    	res |= curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, params->ciphersuites);
	}

	if (params->http_proxy  != NULL) {
		LM_DBG("****** ##### CURL proxy [%s] \n", params->http_proxy);
		res |= curl_easy_setopt(curl, CURLOPT_PROXY, params->http_proxy);
	 } else {
		LM_DBG("****** ##### CURL proxy NOT SET \n");
	 }

	if (params->http_proxy_port > 0) {
		res |= curl_easy_setopt(curl, CURLOPT_PROXYPORT, params->http_proxy_port);
	}


	res |= curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long) params->verify_peer);
	res |= curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (long) params->verify_host?2:0);

	res |= curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long) 1);
	res |= curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long) params->timeout);
	res |= curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, (long) params->http_follow_redirect);
	if (params->http_follow_redirect) {
		LM_DBG("****** ##### Following redirects for this request! \n");
	}


	res |= curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);
	res |= curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream);


	if (res != CURLE_OK) {
		/* PANIC */
		LM_ERR("Could not set CURL options. Library error \n");
	} else {
		double totaltime, connecttime;

		res = curl_easy_perform(curl);

		curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &totaltime);
		curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &connecttime);
		LM_DBG("**** HTTP Call performed in %f s (connect time %f) \n", totaltime, connecttime);
		if (params->pconn) {
			params->pconn->querytime = totaltime;
			params->pconn->connecttime = connecttime;
		}

	}

	/* Cleanup */
	if (headerlist) {
		curl_slist_free_all(headerlist);
	}

	if (res != CURLE_OK) {
		/* http://curl.haxx.se/libcurl/c/libcurl-errors.html */
		if (res == CURLE_COULDNT_CONNECT) {
			LM_WARN("failed to connect() to host\n");
		} else if ( res == CURLE_COULDNT_RESOLVE_HOST ) {
			LM_WARN("Couldn't resolve host\n");
		} else if ( res == CURLE_COULDNT_RESOLVE_PROXY ) {
			LM_WARN("Couldn't resolve http_proxy host\n");
		} else if ( res == CURLE_UNSUPPORTED_PROTOCOL ) {
			LM_WARN("URL Schema not supported by curl\n");
		} else if ( res == CURLE_URL_MALFORMAT ) {
			LM_WARN("Malformed URL used in http_client\n");
		} else if ( res == CURLE_OUT_OF_MEMORY ) {
			LM_WARN("Curl library out of memory\n");
		} else if ( res == CURLE_OPERATION_TIMEDOUT ) {
			LM_WARN("Curl library timed out on request\n");
		} else if ( res == CURLE_SSL_CONNECT_ERROR ) {
			LM_WARN("TLS error in curl connection\n");
		} else if ( res == CURLE_SSL_CERTPROBLEM ) {
			LM_WARN("TLS local certificate error\n");
		} else if ( res == CURLE_SSL_CIPHER ) {
			LM_WARN("TLS cipher error\n");
		} else if ( res == CURLE_SSL_CACERT ) {
			LM_WARN("TLS server certificate validation error (No valid CA cert)\n");
		} else if ( res == CURLE_SSL_CACERT_BADFILE ) {
			LM_WARN("TLS CA certificate read error \n");
		} else if ( res == CURLE_SSL_ISSUER_ERROR ) {
			LM_WARN("TLS issuer certificate check error \n");
		} else if ( res == CURLE_PEER_FAILED_VERIFICATION ) {
			LM_WARN("TLS verification error\n");
		} else if ( res == CURLE_TOO_MANY_REDIRECTS ) {
			LM_WARN("Too many redirects\n");
		} else {
			LM_ERR("failed to perform curl (%d)\n", res);
		}

		if (params->pconn) {
			params->pconn->last_result = res;
		}
		if (params->pconn && params->keep_connections) {
			params->pconn->curl = curl;	/* Save connection, don't close */
		} else {
			/* Cleanup and close - bye bye and thank you for all the bytes */
			curl_easy_cleanup(curl);
		}
		if(stream.buf) {
			pkg_free(stream.buf);
		}
		counter_inc(connfail);
		if (params->failovercon != NULL) {
			LM_ERR("FATAL FAILURE: Trying failover to curl con (%s)\n", params->failovercon);
			return (1000 + res);
		}
		return res;
	}

	/* HTTP_CODE CHANGED TO CURLINFO_RESPONSE_CODE in curl > 7.10.7 */
	curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &stat);
	if(res == CURLE_OK) {
		char *ct;
		char *url;

		/* ask for the content-type of the response */
		res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
		res |= curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);

		if(ct) {
	    		LM_DBG("We received Content-Type: %s\n", ct);
			if (params->pconn) {
				strncpy(params->pconn->result_content_type, ct, sizeof(params->pconn->result_content_type));
			}
	    	}
		if(url) {
	    		LM_DBG("We visited URL: %s\n", url);
			if (params->pconn) {
				strncpy(params->pconn->redirecturl, url , sizeof(params->pconn->redirecturl));
			}
	    	}
	}
	if (params->pconn) {
		params->pconn->last_result = stat;
	}

	if ((stat >= 200) && (stat < 500)) {
		double datasize = download_size;

		curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &download_size);
		LM_DBG("  -- curl download size: %u \n", (unsigned int)download_size);

		if (download_size > 0) {

			if (params->oneline) {
				/* search for line feed */
				at = memchr(stream.buf, (char)10, download_size);
				datasize = (double) (at - stream.buf);
				LM_DBG("  -- curl download size cut to first line: %d \n", (int) datasize);
			}
			if (at == NULL) {
				if (params->maxdatasize && ((unsigned int) download_size) > params->maxdatasize) {
					/* Limit at maximum data size */
					datasize = (double) params->maxdatasize;
					LM_DBG("  -- curl download size cut to maxdatasize : %d \n", (int) datasize);
				} else {
					/* Limit at actual downloaded data size */
					datasize = (double) download_size;
					LM_DBG("  -- curl download size cut to download_size : %d \n", (int) datasize);
	    				//at = stream.buf + (unsigned int) download_size;
				}
			}
			/* Create a STR object */
			rval.s = stream.buf;
			rval.len = datasize;
			/* Duplicate string to return */
			pkg_str_dup(_dst, &rval);
			LM_DBG("curl query result: Length %d %.*s \n", rval.len, rval.len, rval.s);
		} else {
			_dst->s = NULL;
			_dst->len = 0;
		}
	}
	if (stat == 200) {
		counter_inc(connok);
	} else {
		counter_inc(connfail);
		if (stat >= 500) {
			if (params->failovercon != NULL) {
				LM_ERR("FAILURE: Trying failover to curl con (%s)\n", params->failovercon);
				return (1000 + stat);
			}
		}
	}

	/* CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... ); */
	if (params->pconn && params->keep_connections) {
		params->pconn->curl = curl;	/* Save connection, don't close */
	} else {
		curl_easy_cleanup(curl);
	}
	if (stream.buf != NULL) {
		pkg_free(stream.buf);
	}
	return stat;
}
Exemplo n.º 9
0
/**
 * sngtc_caller_answer - attaches an SDP body to ACK requests
 */
static int sngtc_caller_answer(struct sip_msg *msg)
{
	char *p;
	str body;
	struct dlg_cell *dlg;
	struct lump *lump;
	struct sngtc_info *info;
	int len;

	LM_DBG("processing ACK\n");

	if (get_body(msg, &body) != 0 || body.len > 0) {
		LM_ERR("ACK should not contain a SDP body\n");
		return SNGTC_ERR;
	}

	dlg = dlg_binds.get_dlg();
	if (!dlg) {
		LM_ERR("failed to fetch current dialog\n");
		return SNGTC_ERR;
	}

	/* get the SDP body from the INVITE which was mangled at 200 OK */
	if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &body, 0) != 0) {
		LM_ERR("failed to fetch caller sdp\n");
		return SNGTC_ERR;
	}

	info = *(struct sngtc_info **)(body.s);

	/* duplicate the SDP in pkg mem for the lumps mechanism */
	if (pkg_str_dup(&body, &info->modified_caller_sdp) != 0) {
		LM_ERR("failed to dup in pkg mem\n");
		return SNGTC_ERR;
	}

	LM_DBG("Duplicated SDP: '%.*s'\n", body.len, body.s);

	lump = anchor_lump(msg, msg->content_length->name.s - msg->buf, 0);
	if (!lump) {
		LM_ERR("failed to insert anchor lump\n");
		return SNGTC_ERR;
	}

	p = pkg_malloc(SDP_CONTENT_TYPE_LEN);
	if (!p) {
		LM_ERR("no more pkg memory\n");
		return SNGTC_ERR;
	}

	/* add the Content-Type header */

	memcpy(p, "Content-Type: application/sdp\r\n", SDP_CONTENT_TYPE_LEN);

	if (!insert_new_lump_before(lump, p, SDP_CONTENT_TYPE_LEN, 0)) {
		LM_ERR("failed to insert Content-Type lump\n");
		return SNGTC_ERR;
	}

	LM_DBG("blen: %d\n", msg->content_length->body.len);

	lump = del_lump(msg, msg->content_length->body.s - msg->buf,
	                msg->content_length->body.len, HDR_OTHER_T);
	if (!lump) {
		LM_ERR("failed to insert del lump for the content length\n");
		return SNGTC_ERR;
	}

	p = pkg_malloc(CONTENT_LEN_DIGITS);
	if (!p) {
		LM_ERR("no more pkg memory\n");
		return SNGTC_ERR;
	}

	LM_DBG("len: %d\n", body.len);

	len = sprintf(p, "%d", body.len);

	if (!insert_new_lump_after(lump, p, len, HDR_OTHER_T)) {
		LM_ERR("failed to insert Content-Length lump\n");
		return SNGTC_ERR;
	}

	lump = anchor_lump(msg, msg->len - CRLF_LEN, 0);
	if (!lump) {
		LM_ERR("failed to insert anchor lump\n");
		return SNGTC_ERR;
	}

	if (!insert_new_lump_before(lump, body.s, body.len, 0)) {
		LM_ERR("failed to insert SDP body lump\n");
		return SNGTC_ERR;
	}

	return 1;
}
Exemplo n.º 10
0
/**
 * performs the following operations at 200 OK time (early neg <-> late neg):
 *
 * - alters the callee's 200 OK message (adds the final decided codec)
 * - alters the caller's SDP (in memory), so it can be attached @ ACK
 * - opens transcoding sessions on the card if necessary
 *
 * Note: assumes all streams are on corresponding positions in both SDPs
 */
static int process_session(struct sip_msg *msg, struct sngtc_info *info, str *src,
                           str *dst, struct sdp_session_cell *s1,
                           struct sdp_session_cell *s2)
{
	struct sdp_stream_cell *sm1, *sm2;
	struct sngtc_session_list *tc_session;
	struct sngtc_codec_request request;
	struct sngtc_codec_reply *reply = NULL;
	struct codec_pair pair;
	struct lump *lump, *nl;
	struct in_addr addr;
	int rc = 0, ret, tc_on = 0;
	int idx;
	char buf[INET_ADDRSTRLEN];
	str repl;

	if (s1->next && s2->next)
		rc = process_session(msg, info, src, dst, s1->next, s2->next);
	else if (s1->next || s2->next)
		LM_ERR("endpoints have a different number of SDP sessions"
		       " - choosing min number\n");

	if (rc != 0)
		goto out;

	tc_session = info->sessions;
	for (idx = MAX_STREAMS - 1, sm1 = s1->streams, sm2 = s2->streams; sm1 && sm2;
	     sm1 = sm1->next, sm2 = sm2->next, idx--) {

		ret = match_codecs(sm1, sm2, &pair);
		codec_matches[idx] = pair;

		switch (ret) {

		case SNGTC_OFF:

			LM_DBG("NO NEED FOR TRANSCODING\n");

			/* delete codecs from 200 OK; write endpoint A codec */
			/* ip and port stay the same */
			lump = remove_sdp_stream_attrs(msg, sm2);
			if (!lump) {
				LM_ERR("failed to clear sdp codecs\n");
				return SNGTC_SDP_ERR;
			}

			LM_DBG("sdp stream:\n");
			print_sdp_stream(sm2, L_DBG);

			ret = write_sdp_stream_attr(msg, lump, pair.att2, NULL);
			if (ret != 0) {
				LM_ERR("failed to write sdp stream codec\n");
				return ret;
			}

			break;

		case SNGTC_ON:

			tc_on = 1;

			if (is_processed(info))
				goto use_existing_sessions;

			LM_DBG("TRANSCODING ([%d] %.*s:%.*s <--> [%d] %.*s:%.*s)\n",
			       pair.tc1, s1->ip_addr.len, s1->ip_addr.s, sm1->port.len,
				   sm1->port.s, pair.tc2, s2->ip_addr.len, s2->ip_addr.s,
				   sm2->port.len, sm2->port.s);

			memset(&request, 0, sizeof(request));

			request.usr_priv = NULL;

			/* Codec, ms, IP and port for side A */
			request.a.codec_id = pair.tc1;
			request.a.ms = 0;
			sprintf(buf, "%.*s", s1->ip_addr.len, s1->ip_addr.s);
			ret = inet_pton(AF_INET, buf, &addr);
			if (ret != 1) {
				LM_ERR("failed to convert ip %s to binary form (%d)\n",
				       s1->ip_addr.s, ret);
				return SNGTC_ERR;
			}
			request.a.host_ip = htonl(addr.s_addr);
			request.a.host_netmask = (unsigned int)-1;
			if (str2int(&sm1->port, &request.a.host_udp_port) != 0)
				LM_ERR("Failed to parse integer stored in port str '%.*s'\n",
						sm1->port.len, sm1->port.s);

			/* Codec, ms, IP and port for side B */
			request.b.codec_id = pair.tc2;
			request.b.ms = 0;
			sprintf(buf, "%.*s", s2->ip_addr.len, s2->ip_addr.s);
			ret = inet_pton(AF_INET, buf, &addr);
			if (ret != 1) {
				LM_ERR("failed to convert ip %.*s to binary form (%d)\n",
				       s2->ip_addr.len, s2->ip_addr.s, ret);
				return SNGTC_ERR;
			}
			request.b.host_ip = htonl(addr.s_addr);
			request.b.host_netmask = (unsigned int)-1;
			if (str2int(&sm2->port, &request.b.host_udp_port) != 0)
				LM_ERR("Failed to parse integer stored in port str '%.*s'\n",
						sm2->port.len, sm2->port.s);

			LM_DBG("Transcoding request: %d:%d <--> %d:%d\n", request.a.host_ip,
			       request.a.host_udp_port, request.b.host_ip,
			       request.b.host_udp_port);

			reply = create_transcoding_session(&request, info);
			if (!reply) {
				LM_ERR("Failed to create a transcoding session on the card\n");
				return SNGTC_TC_ERR;
			}

use_existing_sessions:

			LM_DBG("NEW TC SESSION!\n");

			if (is_processed(info)) {
				reply = tc_session->reply;
				tc_session = tc_session->next;
			}

			codec_matches[idx].reply = reply;

			/**
			 * delete codecs from 200 OK
			 * write the common codec
			 * replace IP with ip of Sangoma card
			 * replace port with endpoint A newly opened port on card
			 */
			lump = remove_sdp_stream_attrs(msg, sm2);
			if (!lump) {
				LM_ERR("failed to clear sdp codecs\n");
				return SNGTC_SDP_ERR;
			}

			nl = del_lump(msg, s2->ip_addr.s - msg->buf, s2->ip_addr.len, 0);
			if (!nl) {
				LM_ERR("failed to add del lump\n");
				return SNGTC_ERR;
			}

			if (pkg_str_dup(&repl, &card_ip_b) != 0) {
				LM_ERR("failed to dup in pkg mem\n");
				return SNGTC_ERR;
			}

			if (!insert_new_lump_after(nl, repl.s, repl.len, HDR_OTHER_T)) {
				LM_ERR("failed to insert lump with codec result\n");
				return SNGTC_ERR;
			}

			if (replace_sdp_stream_port(msg, sm2,
			                            reply->a.codec_udp_port) != 0) {
				LM_ERR("failed to rewrite sdp stream port\n");
				return SNGTC_ERR;
			}

			if (write_sdp_stream_attr(msg, lump, pair.att1, reply) != 0) {
				LM_ERR("failed to write sdp stream codecs\n");
				return SNGTC_ERR;
			}

			break;

		case SNGTC_UNSUP_CODECS:

			LM_ERR("endpoints have no common codecs and at least one side "
			       "contains only unsupported Sangoma codecs\n");

			LM_ERR("caller:\n");
			print_sdp_stream(sm1, L_ERR);

			LM_ERR("callee:\n");
			print_sdp_stream(sm2, L_ERR);
			return SNGTC_SDP_ERR;

		case SNGTC_BAD_SDP:

			LM_ERR("received bogus sdp with no attributes\n");

			LM_ERR("caller:\n");
			print_sdp_stream(sm1, L_ERR);

			LM_ERR("callee:\n");
			print_sdp_stream(sm2, L_ERR);
			return SNGTC_SDP_ERR;
		}
	}

	if (tc_on) {
		LM_DBG("transcoding: ON\n");

		memcpy(dst->s + dst->len, src->s, s1->ip_addr.s - src->s);
		dst->len += s1->ip_addr.s - src->s;
		dst->len += sprintf(dst->s + dst->len, "%.*s",
		                    card_ip_a.len, card_ip_a.s);
		src->s += s1->ip_addr.s - src->s + s1->ip_addr.len;
	} else
		LM_DBG("transcoding: OFF\n");

	rc |= process_stream(s1->streams, s2->streams, src, dst, MAX_STREAMS - 1);
out:
	return rc;
}
Exemplo n.º 11
0
int parse_avp_db(char *s, struct db_param *dbp, int allow_scheme)
{
	str   tmp;
	str   s0;
	str *s1;
	char  have_scheme;
	char *p;
	char *p0;
	unsigned int flags;

	LM_DBG("parse: %s\n", s);
	tmp.s = s;
	/* parse the attribute name - check first if it's not an alias */
	p0=strchr(tmp.s, '/');
	if(p0!=NULL)
		*p0=0;
	if ( *s!='$')
	{
		if(strlen(s)<1)
		{
			LM_ERR("bad param - expected : $avp(name), *, s or i value\n");
			return E_UNSPEC;
		}
		switch(*s) {
			/* deteleted because of the new avp format */
			case 's': case 'S':
			case 'i': case 'I':
			case '*': case 'a': case 'A':
				dbp->a.opd = AVPOPS_VAL_NONE;
			break;
			default:
				LM_ERR("bad param - expected : *, s or i AVP flag\n");
			return E_UNSPEC;
		}
		/* flags */
		flags = 0;
		if(*(s+1)!='\0')
		{
			s0.s = s+1;
			s0.len = strlen(s0.s);
			if(str2int(&s0, &flags)!=0)
			{
				LM_ERR("error - bad avp flags\n");
				goto error;
			}
		}
		dbp->a.u.sval.pvp.pvn.u.isname.type |= (flags<<8)&0xff00;
		dbp->a.type = AVPOPS_VAL_NONE;
	} else {
		s0.s = s; s0.len = strlen(s0.s);
		p = pv_parse_spec(&s0, &dbp->a.u.sval);
		if (p==0 || *p!='\0' || dbp->a.u.sval.type!=PVT_AVP)
		{
			LM_ERR("bad param - expected : $avp(name) or int/str value\n");
			return E_UNSPEC;
		}
		dbp->a.type = AVPOPS_VAL_PVAR;
	}

	/* optimize and keep the attribute name as str also to
	 * speed up db querie builds */
	if (dbp->a.type == AVPOPS_VAL_PVAR)
	{
		dbp->a.opd = AVPOPS_VAL_PVAR;
		if(pv_has_iname(&dbp->a.u.sval))
		{
			s1 = get_avp_name_id(dbp->a.u.sval.pvp.pvn.u.isname.name.n);
			if (!s1)
			{
				LM_ERR("cannot find avp name\n");
				goto error;
			}
			dbp->sa.s=(char*)pkg_malloc(s1->len + 1);
			if (dbp->sa.s==0)
			{
				LM_ERR("no more pkg mem\n");
				goto error;
			}
			memcpy(dbp->sa.s, s1->s, s1->len);
			dbp->sa.len = s1->len;
			dbp->sa.s[dbp->sa.len] = 0;
			dbp->a.opd = AVPOPS_VAL_PVAR|AVPOPS_VAL_STR;
		}
	}

	/* restore '/' */
	if(p0)
		*p0 = '/';
	/* is there a table name ? */
	s = p0;
	if (s && *s)
	{
		s++;
		if (*s=='$')
		{
			if (allow_scheme==0)
			{
				LM_ERR("function doesn't support DB schemes\n");
				goto error;
			}
			if (dbp->a.opd&AVPOPS_VAL_NONE)
			{
				LM_ERR("inconsistent usage of "
					"DB scheme without complet specification of AVP name\n");
				goto error;
			}
			have_scheme = 1;
			s++;
		} else {
			have_scheme = 0;
		}
		tmp.s = s;
		tmp.len = 0;
		while ( *s ) s++;
		tmp.len = s - tmp.s;
		if (tmp.len==0)
		{
			LM_ERR("empty scheme/table name\n");
			goto error;
		}
		if (have_scheme)
		{
			dbp->scheme = avp_get_db_scheme( &tmp );
			if (dbp->scheme==0)
			{
				LM_ERR("scheme <%s> not found\n", tmp.s);
				goto error;
			}
			/* update scheme flags with AVP name type*/
			dbp->scheme->db_flags|=dbp->a.opd&AVPOPS_VAL_STR?AVP_NAME_STR:0;
		} else {
			/* duplicate table str into the db_param struct */
			pkg_str_dup( &dbp->table, &tmp);
		}
	}

	return 0;
error:
	return -1;
}
Exemplo n.º 12
0
int dlg_th_onreply(struct dlg_cell *dlg, struct sip_msg *rpl, int init_req, int dir)
{
	struct hdr_field *it;
	char* buf = rpl->buf;
	int peer_leg;
	struct lump* lmp;
	int size;
	char* route;
	str lv_str;
	struct dlg_leg* leg;

	LM_DBG("start\n");

	/* parse all headers to be sure that all RR and Contact hdrs are found */
	if (parse_headers(rpl, HDR_EOH_F, 0)< 0) {
		LM_ERR("Failed to parse reply\n");
		return -1;
	}

	/* replace contact */
	if(dlg_replace_contact(rpl, dlg) < 0) {
		LM_ERR("Failed to replace contact\n");
		return -1;
	}

	if(dir == DLG_DIR_UPSTREAM)
		peer_leg = DLG_CALLER_LEG;
	else
		peer_leg = callee_idx(dlg);
	leg = &dlg->legs[peer_leg];

	LM_DBG("peer_leg = %d\n", peer_leg);
	LM_DBG("first RR hdr = %p\n", rpl->record_route);
	/* delete record route */
	for (it=rpl->record_route; it; it=it->sibling) { /* changed here for contact - it was & it->sibling */
		/* skip the one added by this proxy */
		if ((lmp = del_lump(rpl, it->name.s - buf, it->len,HDR_RECORDROUTE_T)) == 0) {
			LM_ERR("del_lump failed \n");
			return -1;
		}
		LM_DBG("Delete record route: [%.*s]\n", it->len, it->name.s);
	}

	/* add Via headers */
	lmp = anchor_lump(rpl,rpl->headers->name.s - buf,0,0);
	if (lmp == 0)
	{
		LM_ERR("failed anchoring new lump\n");
		return -1;
	}
	if(pkg_str_dup(&lv_str, &leg->last_vias) < 0) {
		LM_ERR("Failed to duplicate memory\n");
		return 1;
	}
	if ((lmp = insert_new_lump_after(lmp, lv_str.s, lv_str.len, HDR_VIA_T)) == 0) {
		LM_ERR("failed inserting new vias\n");
		pkg_free(lv_str.s);
		return -1;
	}
	LM_DBG("Added Via headers [%.*s] leg=%p\n", lv_str.len, lv_str.s, leg);

	/* if dialog not confirmed and 200OK for Invite */
	/* pass the record route headers for this leg */
	if(init_req && dir == DLG_DIR_UPSTREAM && rpl->first_line.u.reply.statuscode==200
			&& leg->route_set.s) {

		/* changed here for contact ( take care to insert the routes after own) */

		/* pass record route headers */
		size = leg->route_set.len + RECORD_ROUTE_LEN + CRLF_LEN;
		route = pkg_malloc(size);
		if (route == NULL) {
			LM_ERR("no more pkg memory\n");
			return -1;
		}

		memcpy(route, RECORD_ROUTE, RECORD_ROUTE_LEN);
		memcpy(route+RECORD_ROUTE_LEN, leg->route_set.s, leg->route_set.len);
		memcpy(route+RECORD_ROUTE_LEN+leg->route_set.len, CRLF, CRLF_LEN);

		/* put after Via */
		if ((lmp = insert_new_lump_after(lmp, route, size, HDR_RECORDROUTE_T)) == 0) {
			LM_ERR("failed inserting new route set\n");
			pkg_free(route);
			return -1;
		}
		LM_DBG("Added record route [%.*s]\n", size, route);
	}

	return 0;
}