⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcr_mod.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 4 页
字号:
    uri_type scheme;    uri_transport transport;    struct ip_addr address;    str addr_str, port_str;    char *at, *prefix;    int_str val;    struct mi matched_gws[MAX_NO_OF_GWS + 1];    unsigned short strip_len, prefix_len, priority;    int randomizer_start, randomizer_end, randomizer_flag;    struct lcr_info lcr_rec;    /* Find Request-URI user */    if (parse_sip_msg_uri(_m) < 0) {	    LOG(L_ERR, "load_gws(): Error while parsing R-URI\n");	    return -1;    }    ruri_user = _m->parsed_uri.user;   /* Look for Caller RPID or From URI */    if (search_first_avp(rpid_avp_name_str, rpid_name, &val, 0) &&	val.s.s && val.s.len) {	/* Get URI user from RPID */	from_uri.len = val.s.len;	from_uri.s = val.s.s;    } else {	/* Get URI from From URI */	if ((!_m->from) && (parse_headers(_m, HDR_FROM_F, 0) == -1)) {	    LOG(L_ERR, "load_gws(): Error while parsing message\n");	    return -1;	}	if (!_m->from) {	    LOG(L_ERR, "load_gws(): FROM header field not found\n");	    return -1;	}	if ((!(_m->from)->parsed) && (parse_from_header(_m) < 0)) {	    LOG(L_ERR, "load_gws(): Error while parsing From body\n");	    return -1;	}	from_uri = get_from(_m)->uri;    }    if (from_uri.len < MAX_FROM_URI_LEN) {	strncpy(from_uri_str, from_uri.s, from_uri.len);	from_uri_str[from_uri.len] = '\0';    } else {	LOG(L_ERR, "load_gws(): from_uri to large\n");	return -1;    }    /*     * Check if the gws and lcrs were reloaded     */    if (reload_counter != *lcrs_ws_reload_counter) {	if (load_from_uri_regex() != 0) {	    return -1;	}    }	if (db_mode == 0) {		if(grp_id >= 0) {			q_len = snprintf(query, MAX_QUERY_SIZE, "SELECT %.*s.%.*s, %.*s.%.*s, %.*s.%.*s, %.*s.%.*s, %.*s.%.*s, %.*s.%.*s FROM %.*s, %.*s WHERE %.*s.%.*s = %d AND '%.*s' LIKE %.*s.%.*s AND '%.*s' LIKE CONCAT(%.*s.%.*s, '%%') AND %.*s.%.*s = %.*s.%.*s ORDER BY CHAR_LENGTH(%.*s.%.*s), %.*s.%.*s DESC, RAND()",				gw_table.len, gw_table.s, ip_addr_col.len, ip_addr_col.s,				gw_table.len, gw_table.s, port_col.len, port_col.s,				gw_table.len, gw_table.s, uri_scheme_col.len, uri_scheme_col.s,				gw_table.len, gw_table.s, transport_col.len, transport_col.s,				gw_table.len, gw_table.s, strip_col.len, strip_col.s,				gw_table.len, gw_table.s, prefix_col.len, prefix_col.s,				gw_table.len, gw_table.s, lcr_table.len, lcr_table.s,				lcr_table.len, lcr_table.s, grp_id_col.len, grp_id_col.s, grp_id,				from_uri.len, from_uri.s,				lcr_table.len, lcr_table.s, from_uri_col.len, from_uri_col.s,				ruri_user.len, ruri_user.s,				lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,				lcr_table.len, lcr_table.s, grp_id_col.len,  grp_id_col.s,				gw_table.len, gw_table.s, grp_id_col.len, grp_id_col.s,				lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,				lcr_table.len, lcr_table.s, priority_col.len, priority_col.s);		} else {			q_len = snprintf(query, MAX_QUERY_SIZE, "SELECT %.*s.%.*s, %.*s.%.*s, %.*s.%.*s, %.*s.%.*s, %.*s.%.*s, %.*s.%.*s FROM %.*s, %.*s WHERE '%.*s' LIKE %.*s.%.*s AND '%.*s' LIKE CONCAT(%.*s.%.*s, '%%') AND %.*s.%.*s = %.*s.%.*s ORDER BY CHAR_LENGTH(%.*s.%.*s), %.*s.%.*s DESC, RAND()",				gw_table.len, gw_table.s, ip_addr_col.len, ip_addr_col.s,				gw_table.len, gw_table.s, port_col.len, port_col.s,				gw_table.len, gw_table.s, uri_scheme_col.len, uri_scheme_col.s,				gw_table.len, gw_table.s, transport_col.len, transport_col.s,				gw_table.len, gw_table.s, strip_col.len, strip_col.s,				gw_table.len, gw_table.s, prefix_col.len, prefix_col.s,				gw_table.len, gw_table.s, lcr_table.len, lcr_table.s,				from_uri.len, from_uri.s,				lcr_table.len, lcr_table.s, from_uri_col.len, from_uri_col.s,				ruri_user.len, ruri_user.s,				lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,				lcr_table.len, lcr_table.s, grp_id_col.len,  grp_id_col.s,				gw_table.len, gw_table.s, grp_id_col.len, grp_id_col.s,				lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,				lcr_table.len, lcr_table.s, priority_col.len, priority_col.s);		}		if (q_len >= MAX_QUERY_SIZE) {			LOG(L_ERR, "load_gws(): Too long database query\n");			return -1;		}		if (lcr_dbf.raw_query(db_handle, query, &res) < 0) {			LOG(L_ERR, "load_gws(): Failed to query accept data\n");			return -1;		}		for (i = 0; i < RES_ROW_N(res); i++) {			row = RES_ROWS(res) + i;			if (VAL_NULL(ROW_VALUES(row)) == 1) {				LOG(L_ERR, "load_gws(): Gateway IP address is NULL\n");				goto skip1;			}			addr = (unsigned int)VAL_INT(ROW_VALUES(row));			for (j = i + 1; j < RES_ROW_N(res); j++) {				r = RES_ROWS(res) + j;				if (addr == (unsigned int)VAL_INT(ROW_VALUES(r)))					goto skip1;			}			if (VAL_NULL(ROW_VALUES(row) + 1) == 1) {				port = 0;			} else {				port = (unsigned int)VAL_INT(ROW_VALUES(row) + 1);			}			if (VAL_NULL(ROW_VALUES(row) + 2) == 1) {				scheme = SIP_URI_T;			} else {				scheme = (uri_type)VAL_INT(ROW_VALUES(row) + 2);			}			if (VAL_NULL(ROW_VALUES(row) + 3) == 1) {				transport = PROTO_NONE;			} else {				transport = (uri_transport)VAL_INT(ROW_VALUES(row) + 3);			}			if (VAL_NULL(ROW_VALUES(row) + 4) == 1) {				strip = 0;				strip_len = 1;			} else {				strip = VAL_INT(ROW_VALUES(row) + 4);				if (strip<10)					strip_len = 1;				else if (strip < 100)					strip_len = 2;				else					strip_len = 3;			}			if (VAL_NULL(ROW_VALUES(row) + 5) == 1) {				prefix_len = 0;				prefix = (char *)0;			} else {				prefix = (char *)VAL_STRING(ROW_VALUES(row) + 5);				prefix_len = strlen(prefix);			}			if (5 + prefix_len + 1 + strip_len + 1 + 15 + 1 + 5 + 1 + 14 >			MAX_URI_SIZE) {				LOG(L_ERR, "load_gws(): Request URI would be too long\n");				goto skip1;			}			at = (char *)&(ruri[0]);			if (scheme == SIP_URI_T) {				memcpy(at, "sip:", 4); at = at + 4;			} else if (scheme == SIPS_URI_T) {				memcpy(at, "sips:", 5); at = at + 5;			} else {				LOG(L_ERR, "load_gws(): Unknown or unsupported URI "					"scheme: %u\n", (unsigned int)scheme);				goto skip1;			}			if (prefix_len) {				memcpy(at, prefix, prefix_len);				at = at + prefix_len;			}			/* Add strip in this form |number. For example: |3 means 			 * strip first 3 characters */			*at = '|'; at = at + 1;			sprintf(at,"%d", strip);			at = at + strip_len;			*at = '@'; at = at + 1;			address.af = AF_INET;			address.len = 4;			address.u.addr32[0] = addr;			addr_str.s = ip_addr2a(&address);			addr_str.len = strlen(addr_str.s);			memcpy(at, addr_str.s, addr_str.len); at = at + addr_str.len;			if (port != 0) {				if (port > 65536) {					LOG(L_ERR, "load_gws(): Port of GW is too large: %u\n",						port);					goto skip1;				}				*at = ':'; at = at + 1;				port_str.s = int2str(port, &port_str.len);				memcpy(at, port_str.s, port_str.len); at = at + port_str.len;			}			if (transport != PROTO_NONE) {				memcpy(at, ";transport=", 11); at = at + 11;				if (transport == PROTO_UDP) {					memcpy(at, "udp", 3); at = at + 3;				} else if (transport == PROTO_TCP) {					memcpy(at, "tcp", 3); at = at + 3;				} else if (transport == PROTO_TLS) {					memcpy(at, "tls", 3); at = at + 3;				} else {					LOG(L_ERR, "load_gws(): Unknown or unsupported "						"transport: %u\n", (unsigned int)transport);					goto skip1;				}			}			value.s = (char *)&(ruri[0]);			value.len = at - value.s;			val.s = value;			add_avp(gw_uri_avp_name_str|AVP_VAL_STR, gw_uri_name, val);			DBG("load_gws(): DEBUG: Added gw_uri_avp <%.*s>\n",				value.len, value.s);skip1:			continue;		} /* end for */		lcr_dbf.free_result(db_handle, res);		return 1;	} else {		/* CACHE MODE */		/*		 * Let's match the gws:		 *  1. prefix matching		 *  2. from_uri matching		 *  3. grp_id matching		 *		 * Note: A gateway must be in the list _only_ once.		 */		gw_index = 0;		duplicated_gw = 0;		for (i = 0; i < MAX_NO_OF_LCRS; i++) {			lcr_rec = (*lcrs)[i];			if (lcr_rec.end_record != 0) {				break;			}	if ((lcr_rec.prefix_len <= ruri_user.len) &&	    (strncmp(lcr_rec.prefix, ruri_user.s, lcr_rec.prefix_len)==0)) {	    /* 1. Prefix matching is done */	    if ((lcr_rec.from_uri_len == 0) ||		(from_uri_reg[i].valid && (regexec(&(from_uri_reg[i].re), from_uri_str, 0, (regmatch_t *)NULL, 0) == 0))) {		/* 2. from_uri matching is done */		for (j = 0; j < MAX_NO_OF_GWS; j++) {		    if ((*gws)[j].ip_addr == 0) {			break;		    }		    if (lcr_rec.grp_id == (*gws)[j].grp_id && (grp_id < 0 || (*gws)[j].grp_id == grp_id)) {			/* 3. grp_id matching is done */			for (k = 0; k < gw_index; k++) {			    if ((*gws)[j].ip_addr ==				(*gws)[matched_gws[k].gw_index].ip_addr) {				/* Found the same gw in the list  */				/* Let's keep the one with higher */				/* match on prefix len            */				DBG("DEBUG:lcr:load_gws: duplicate gw for index"				    " %d [%d,%d] and current [%d,%d] \n",				    k, matched_gws[k].route_index,				    matched_gws[k].route_index, i, j);				duplicated_gw = 1;				if (lcr_rec.prefix_len >				    (*lcrs)[matched_gws[k].route_index].prefix_len) {				    /* Replace the old entry with the new one */				    DBG("DEBUG:lcr:load_gws: replace[%d,%d]"					" with [%d,%d] on index %d:"					" prefix reason %d>%d\n",					matched_gws[k].route_index,					matched_gws[k].gw_index, i, j, k,					lcr_rec.prefix_len,					(*lcrs)[matched_gws[k].route_index].prefix_len);				    matched_gws[k].route_index = i;				    matched_gws[k].gw_index = j;				    /* Stop searching in the matched_gws list */				    break;				} else if (lcr_rec.prefix_len ==					   (*lcrs)[matched_gws[k].route_index].prefix_len) {				    if (lcr_rec.priority >					(*lcrs)[matched_gws[k].route_index].priority) {					/* Replace the old entry with the new one */					DBG("DEBUG:lcr:load_gws: replace[%d,%d] with"					    " [%d,%d] on index %d:"					    " priority reason %d>%d\n",					    matched_gws[k].route_index,					    matched_gws[k].gw_index, i, j, k,					    lcr_rec.priority,					    (*lcrs)[matched_gws[k].route_index].priority);					matched_gws[k].route_index = i;					matched_gws[k].gw_index = j;					/* Stop searching in the matched_gws list */					break;				    }				}			    }			}			if (duplicated_gw == 0) {			    /* This is a new gw */			    matched_gws[gw_index].route_index = i;			    matched_gws[gw_index].gw_index = j;			    DBG("DEBUG:lcr:load_gws: add matched_gws[%d]=[%d,%d]\n",				gw_index, i, j);			    gw_index++;			} else {			    duplicated_gw = 0;			}		    }		}	    }	}    }    matched_gws[gw_index].route_index = -1;    matched_gws[gw_index].gw_index = -1;    /*     * Sort the gateways based on:     *  1. prefix len     *  2. priority     */    qsort(matched_gws, gw_index, sizeof(struct mi), comp_lcrs);	randomizer_start = 0;    /* Randomizing the gateways with same prefix_len and same priority */    randomizer_flag = 0;    prefix_len = (*lcrs)[matched_gws[0].route_index].prefix_len;    priority = (*lcrs)[matched_gws[0].route_index].priority;    for (i = 1; i < gw_index; i++) { 	if ( prefix_len == (*lcrs)[matched_gws[i].route_index].prefix_len && 	     priority == (*lcrs)[matched_gws[i].route_index].priority) {	    /* we have a match */	    if (randomizer_flag == 0) {		randomizer_flag = 1;		randomizer_start = i - 1;	    }	    matched_gws[i - 1].randomizer = rand(); 	}	else {	    if (randomizer_flag == 1) {		randomizer_end = i - 1;		randomizer_flag = 0;		qsort(&matched_gws[randomizer_start],		      randomizer_end - randomizer_start + 1,		      sizeof(struct mi), rand_lcrs);	    }	    prefix_len = (*lcrs)[matched_gws[i].route_index].prefix_len;	    priority = (*lcrs)[matched_gws[i].route_index].priority;	}    }    if (randomizer_flag == 1) {	randomizer_end = gw_index - 1;	matched_gws[i - 1].randomizer = rand();	qsort(&matched_gws[randomizer_start],	      randomizer_end - randomizer_start + 1,	      sizeof(struct mi), rand_lcrs);    }    for (i = 0; i < MAX_NO_OF_GWS; i++) {	index = matched_gws[i].gw_index;	if (index == -1) {	    break;	}      	addr = (*gws)[index].ip_addr;	port = (*gws)[index].port;	scheme = (*gws)[index].scheme;	transport = (*gws)[index].transport;	strip = (*gws)[index].strip;	if (strip<10) strip_len = 1;	else	    if (strip < 100)		strip_len = 2;	    else		strip_len = 3;	prefix_len = (*gws)[index].prefix_len;	prefix = (*gws)[index].prefix;	if (5 + prefix_len + 1 + strip_len + 1 + 15 + 1 + 5 + 1 + 14 >	    MAX_URI_SIZE) {	    LOG(L_ERR, "load_gws(): Request URI would be too long\n");	    goto skip;	}	at = (char *)&(ruri[0]);	if (scheme == SIP_URI_T) {	    memcpy(at, "sip:", 4); at = at + 4;	} else if (scheme == SIPS_URI_T) {	    memcpy(at, "sips:", 5); at = at + 5;	} else {	    LOG(L_ERR, "load_gws(): Unknown or unsupported URI scheme: %u\n",		(unsigned int)scheme);	    goto skip;	}	if (prefix_len) {	    memcpy(at, prefix, prefix_len); at = at + prefix_len;	}	//Add strip in this form |number. For example: |3 means strip first 3 characters	*at = '|'; at = at + 1;	sprintf(at,"%d", strip);	at = at + strip_len;		*at = '@'; at = at + 1;	address.af = AF_INET;	address.len = 4;	address.u.addr32[0] = addr;	addr_str.s = ip_addr2a(&address);	addr_str.len = strlen(addr_str.s);	memcpy(at, addr_str.s, addr_str.len); at = at + addr_str.len;	if (port != 0) {	    if (port > 65536) {		LOG(L_ERR, "load_gws(): Port of GW is too large: %u\n", port);		goto skip;	    }	    *at = ':'; at = at + 1;	    port_str.s = int2str(port, &port_str.len);	    memcpy(at, port_str.s, port_str.len); at = at + port_str.len;	}	if (transport != PROTO_NONE) {	    memcpy(at, ";transport=", 11); at = at + 11;	    if (transport == PROTO_UDP) {		memcpy(at, "udp", 3); at = at + 3;	    } else if (transport == PROTO_TCP) {		memcpy(at, "tcp", 3); at = at + 3;	    } else if (transport == PROTO_TLS) {		memcpy(at, "tls", 3); at = at + 3;	    } else {		LOG(L_ERR, "load_gws(): Unknown or unsupported transport: %u\n",		    (unsigned int)transport);		goto skip;	    }	}	value.s = (char *)&(ruri[0]);	value.len = at - value.s;	val.s = value;	add_avp(gw_uri_avp_name_str|AVP_VAL_STR, gw_uri_name, val);	DBG("load_gws(): DEBUG: Added gw_uri_avp <%.*s>\n",	    value.len, value.s);    skip:	continue;    }    return 1;    }}/* * Load info of matching GWs from database to gw_uri AVPs * taking into account the given group id. */int load_gws_grp(struct sip_msg* _m, char* _s1, char* _s2){    int grp_id;    grp_id = (int)(long)_s1;    return do_load_gws(_m, grp_id);}/* * Load info of matching GWs from database to gw_uri AVPs * ignoring the group id. */int load_gws(struct sip_msg* _m, char* _s1, char* _s2){    return do_load_gws(_m, -1);}/* * If called from request route block, rewrites scheme, host, port, and * transport parts of R-URI based on first gw_uri AVP value, which is then * destroyed.  Also saves R-URI user to ruri_user AVP for later use in * failure route block. * If called from failure route block, appends a new branch to request * where scheme, host, port, and transport of URI are taken from the first * gw_uri AVP value, which is then destroyed.  URI user is taken from * ruri_user AVP value saved earlier. * Returns 1 upon success and -1 upon failure. */int next_gw(struct sip_msg* _m, char* _s1, char* _s2){    int_str gw_uri_val, ruri_user_val, val;    struct action act;    int rval;    struct usr_avp *gw_uri_avp, *ruri_user_avp;    str new_ruri;    char *at, *at_char;    char *strip_char;    unsigned int strip;    gw_uri_avp = search_first_avp(gw_uri_avp_name_str,				  gw_uri_name, &gw_uri_val, 0);    if (!gw_uri_avp) return -1;    if (route_type == REQUEST_ROUTE) {	/* Create new Request-URI taking URI user from current Request-URI	   and other parts of from gw_uri AVP. */	if (parse_sip_msg_uri(_m) < 0) {	    LOG(L_ERR, "next_gw(): Parsing of R-URI failed.\n");	    return -1;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -