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

📄 nathelper.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
		fd = socket(AF_LOCAL, SOCK_STREAM, 0);		if (fd < 0) {			LOG(L_ERR, "ERROR: send_rtpp_command: can't create socket\n");			return NULL;		}		if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {			close(fd);			LOG(L_ERR, "ERROR: send_rtpp_command: can't connect to RTP proxy\n");			return NULL;		}		do {			len = writev(fd, v + 1, vcnt - 1);		} while (len == -1 && errno == EINTR);		if (len <= 0) {			close(fd);			LOG(L_ERR, "ERROR: send_rtpp_command: can't send command to a RTP proxy\n");			return NULL;		}		do {			len = read(fd, buf, sizeof(buf) - 1);		} while (len == -1 && errno == EINTR);		close(fd);		if (len <= 0) {			LOG(L_ERR, "ERROR: send_rtpp_command: can't read reply from a RTP proxy\n");			return NULL;		}	} else {		fds[0].fd = controlfd;		fds[0].events = POLLIN;		fds[0].revents = 0;		/* Drain input buffer */		while ((poll(fds, 1, 0) == 1) &&		    ((fds[0].revents & POLLIN) != 0)) {			recv(controlfd, buf, sizeof(buf) - 1, 0);			fds[0].revents = 0;		}		v[0].iov_base = gencookie();		v[0].iov_len = strlen(v[0].iov_base);		for (i = 0; i < rtpproxy_retr; i++) {			do {				len = writev(controlfd, v, vcnt);			} while (len == -1 && (errno == EINTR || errno == ENOBUFS));			if (len <= 0) {				LOG(L_ERR, "ERROR: send_rtpp_command: "				    "can't send command to a RTP proxy\n");				return NULL;			}			while ((poll(fds, 1, rtpproxy_tout * 1000) == 1) &&			    (fds[0].revents & POLLIN) != 0) {				do {					len = recv(controlfd, buf, sizeof(buf) - 1, 0);				} while (len == -1 && errno == EINTR);				if (len <= 0) {					LOG(L_ERR, "ERROR: send_rtpp_command: "					    "can't read reply from a RTP proxy\n");					return NULL;				}				if (len >= (v[0].iov_len - 1) &&				    memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {					len -= (v[0].iov_len - 1);					cp += (v[0].iov_len - 1);					if (len != 0) {						len--;						cp++;					}					goto out;				}				fds[0].revents = 0;			}		}		if (i == rtpproxy_retr) {			LOG(L_ERR, "ERROR: send_rtpp_command: "			    "timeout waiting reply from a RTP proxy\n");			return NULL;		}	}out:	cp[len] = '\0';	return cp;}static intunforce_rtp_proxy_f(struct sip_msg* msg, char* str1, char* str2){	str callid, from_tag, to_tag;	struct iovec v[1 + 4 + 3] = {{NULL, 0}, {"D", 1}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};						/* 1 */   /* 2 */   /* 3 */    /* 4 */   /* 5 */    /* 6 */   /* 1 */	rtpproxy_disable = rtpp_test(rtpproxy_disable, 0);	if (rtpproxy_disable != 0) {		LOG(L_ERR, "ERROR: unforce_rtp_proxy: support for RTP proxy "		    "is disabled\n");		return -1;	}	if (get_callid(msg, &callid) == -1 || callid.len == 0) {		LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get Call-Id field\n");		return -1;	}	if (get_to_tag(msg, &to_tag) == -1) {		LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get To tag\n");		return -1;	}	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {		LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get From tag\n");		return -1;	}	STR2IOVEC(callid, v[3]);	STR2IOVEC(from_tag, v[5]);	STR2IOVEC(to_tag, v[7]);	send_rtpp_command(v, (to_tag.len > 0) ? 8 : 6);	return 1;}static intforce_rtp_proxy2_f(struct sip_msg* msg, char* str1, char* str2){	str body, body1, oldport, oldip, oldip1, newport, newip;	str callid, from_tag, to_tag, tmp;	int create, port, len, asymmetric, flookup, argc, proxied, real;	int oidx, pf, pf1, force;	char opts[16];	char *cp, *cp1;	char  *cpend, *next;	char **ap, *argv[10];	struct lump* anchor;	struct iovec v[1 + 6 + 5] = {{NULL, 0}, {NULL, 0}, {" ", 1}, {NULL, 0},		{" ", 1}, {NULL, 7}, {" ", 1}, {NULL, 1}, {" ", 1}, {NULL, 0},		{" ", 1}, {NULL, 0}};						/* 1 */    /* 2 */   /* 3 */    /* 4 */		/* 5 */    /* 6 */   /* 7 */    /* 8 */   /* 9 */    /* 10 */		/* 11 */	v[1].iov_base=opts;	asymmetric = flookup = force = real = 0;	oidx = 1;	for (cp = str1; *cp != '\0'; cp++) {		switch (*cp) {		case 'a':		case 'A':			opts[oidx++] = 'A';			asymmetric = 1;			real = 1;			break;		case 'i':		case 'I':			opts[oidx++] = 'I';			break;		case 'e':		case 'E':			opts[oidx++] = 'E';			break;		case 'l':		case 'L':			flookup = 1;			break;		case 'f':		case 'F':			force = 1;			break;		case 'r':		case 'R':			real = 1;			break;		default:			LOG(L_ERR, "ERROR: force_rtp_proxy2: unknown option `%c'\n", *cp);			return -1;		}	}	rtpproxy_disable = rtpp_test(rtpproxy_disable, 0);	if (rtpproxy_disable != 0) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: support for RTP proxy "		    "is disabled\n");		return -1;	}	if (msg->first_line.type == SIP_REQUEST &&	    msg->first_line.u.request.method_value == METHOD_INVITE) {		create = 1;	} else if (msg->first_line.type == SIP_REPLY) {		create = 0;	} else {		return -1;	}	/* extract_body will also parse all the headers in the message as	 * a side effect => don't move get_callid/get_to_tag in front of it	 * -- andrei */	if (extract_body(msg, &body) == -1) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract body "		    "from the message\n");		return -1;	}	if (get_callid(msg, &callid) == -1 || callid.len == 0) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get Call-Id field\n");		return -1;	}	if (get_to_tag(msg, &to_tag) == -1) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get To tag\n");		return -1;	}	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get From tag\n");		return -1;	}	if (flookup != 0) {		if (create == 0 || to_tag.len == 0)			return -1;		create = 0;		tmp = from_tag;		from_tag = to_tag;		to_tag = tmp;	}	proxied = 0;	for (cp = body.s; (len = body.s + body.len - cp) >= ANORTPPROXY_LEN;) {		cp1 = ser_memmem(cp, ANORTPPROXY, len, ANORTPPROXY_LEN);		if (cp1 == NULL)			break;		if (cp1[-1] == '\n' || cp1[-1] == '\r') {			proxied = 1;			break;		}		cp = cp1 + ANORTPPROXY_LEN;	}	if (proxied != 0 && force == 0)		return -1;	if (extract_mediaip(&body, &oldip, &pf) == -1) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract media IP "		    "from the message\n");		return -1;	}	if (asymmetric != 0 || real != 0) {		newip = oldip;	} else {		newip.s = ip_addr2a(&msg->rcv.src_ip);		newip.len = strlen(newip.s);	}	body1.s = oldip.s + oldip.len;	body1.len = body.s + body.len - body1.s;	if (extract_mediaip(&body1, &oldip1, &pf1) == -1) {		oldip1.len = 0;	}	if (oldip1.len > 0 && pf != pf1) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: mismatching address "		    "families in SDP\n");		return -1;	}	if (extract_mediaport(&body, &oldport) == -1) {		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract media port "		    "from the message\n");		return -1;	}	if (pf == AF_INET6) {		opts[oidx] = '6';		oidx++;	}	opts[0] = (create == 0) ? 'L' : 'U';	v[1].iov_len = oidx;	STR2IOVEC(callid, v[3]);	STR2IOVEC(newip, v[5]);	STR2IOVEC(oldport, v[7]);	STR2IOVEC(from_tag, v[9]);	STR2IOVEC(to_tag, v[11]);	cp = send_rtpp_command(v, (to_tag.len > 0) ? 12 : 10);	if (cp == NULL)		return -1;	argc = 0;	memset(argv, 0, sizeof(argv));	cpend=cp+strlen(cp);	next=eat_token_end(cp, cpend);	for (ap = argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){		*next=0;		if (*cp != '\0') {			*ap=cp;			argc++;			if ((char*)++ap >= ((char*)argv+sizeof(argv)))				break;		}	}	if (argc < 1)		return -1;	port = atoi(argv[0]);	if (port <= 0 || port > 65535)		return -1;	pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET;	if (isnulladdr(&oldip, pf)) {		if (pf1 == AF_INET6) {			newip.s = "::";			newip.len = 2;		} else {			newip.s = "0.0.0.0";			newip.len = 7;		}	} else {		newip.s = (argc < 2) ? str2 : argv[1];		newip.len = strlen(newip.s);	}	newport.s = int2str(port, &newport.len); /* beware static buffer */	if (alter_mediaip(msg, &body, &oldip, pf, &newip, pf1, 0) == -1)		return -1;	if (oldip1.len > 0 &&	    alter_mediaip(msg, &body1, &oldip1, pf, &newip, pf1, 0) == -1)		return -1;	if (alter_mediaport(msg, &body, &oldport, &newport, 0) == -1)		return -1;	if (proxied == 0) {		cp = pkg_malloc(ANORTPPROXY_LEN * sizeof(char));		if (cp == NULL) {			LOG(L_ERR, "ERROR: force_rtp_proxy2: out of memory\n");			return -1;		}		anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);		if (anchor == NULL) {			LOG(L_ERR, "ERROR: force_rtp_proxy2: anchor_lump failed\n");			pkg_free(cp);			return -1;		}		memcpy(cp, ANORTPPROXY, ANORTPPROXY_LEN);		if (insert_new_lump_after(anchor, cp, ANORTPPROXY_LEN, 0) == NULL) {			LOG(L_ERR, "ERROR: force_rtp_proxy2: insert_new_lump_after failed\n");			pkg_free(cp);			return -1;		}	}	return 1;}static intforce_rtp_proxy1_f(struct sip_msg* msg, char* str1, char* str2){	char *cp;	char newip[IP_ADDR_MAX_STR_SIZE];	cp = ip_addr2a(&msg->rcv.dst_ip);	strcpy(newip, cp);	return force_rtp_proxy2_f(msg, str1, newip);}static intforce_rtp_proxy0_f(struct sip_msg* msg, char* str1, char* str2){	char arg[1] = {'\0'};	return force_rtp_proxy1_f(msg, arg, NULL);}static voidtimer(unsigned int ticks, void *param){	int rval;	void *buf, *cp;	str c;	struct sip_uri curi;	union sockaddr_union to;	struct hostent* he;	struct socket_info* send_sock;	buf = NULL;	if (cblen > 0) {		buf = pkg_malloc(cblen);		if (buf == NULL) {			LOG(L_ERR, "ERROR: nathelper::timer: out of memory\n");			return;		}	}	rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0));	if (rval > 0) {		if (buf != NULL)			pkg_free(buf);		cblen = rval * 2;		buf = pkg_malloc(cblen);		if (buf == NULL) {			LOG(L_ERR, "ERROR: nathelper::timer: out of memory\n");			return;		}		rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0));		if (rval != 0) {			pkg_free(buf);			return;		}	}	if (buf == NULL)		return;	cp = buf;	while (1) {		memcpy(&(c.len), cp, sizeof(c.len));		if (c.len == 0)			break;		c.s = (char*)cp + sizeof(c.len);		cp =  (char*)cp + sizeof(c.len) + c.len;		if (parse_uri(c.s, c.len, &curi) < 0) {			LOG(L_ERR, "ERROR: nathelper::timer: can't parse contact uri\n");			continue;		}		if (curi.proto != PROTO_UDP && curi.proto != PROTO_NONE)			continue;		if (curi.port_no == 0)			curi.port_no = SIP_PORT;		he = sip_resolvehost(&curi.host, &curi.port_no, PROTO_UDP);		if (he == NULL){			LOG(L_ERR, "ERROR: nathelper::timer: can't resolve_hos\n");			continue;		}		hostent2su(&to, he, 0, curi.port_no);		send_sock=force_socket ? force_socket : 					get_send_socket(0, &to, PROTO_UDP);		if (send_sock == NULL) {			LOG(L_ERR, "ERROR: nathelper::timer: can't get sending socket\n");			continue;		}		udp_send(send_sock, (char *)sbuf, sizeof(sbuf), &to);	}	pkg_free(buf);}/* * Create received SIP uri that will be either * passed to registrar in an AVP or apended * to Contact header field as a parameter */static intcreate_rcv_uri(str* uri, struct sip_msg* m){	static char buf[MAX_URI_SIZE];	char* p;	str ip, port;	int len;	str proto;	if (!uri || !m) {		LOG(L_ERR, "create_rcv_uri: Invalid parameter value\n");		return -1;	}	ip.s = ip_addr2a(&m->rcv.src_ip);	ip.len = strlen(ip.s);	port.s = int2str(m->rcv.src_port, &port.len);	switch(m->rcv.proto) {	case PROTO_NONE:	case PROTO_UDP:		proto.s = 0; /* Do not add transport parameter, UDP is default */		proto.len = 0;		break;	case PROTO_TCP:		proto.s = "TCP";		proto.len = 3;		break;	case PROTO_TLS:		proto.s = "TLS";		proto.len = 3;		break;	case PROTO_SCTP:		proto.s = "SCTP";		proto.len = 4;		break;	default:		LOG(L_ERR, "BUG: create_rcv_uri: Unknown transport protocol\n");		return -1;	}	len = 4 + ip.len + 1 + port.len;	if (proto.s) {		len += TRANSPORT_PARAM_LEN;		len += proto.len;	}	if (len > MAX_URI_SIZE) {		LOG(L_ERR, "create_rcv_uri: Buffer too small\n");		return -1;	}	p = buf;	memcpy(p, "sip:", 4);	p += 4;		memcpy(p, ip.s, ip.len);	p += ip.len;	*p++ = ':';		memcpy(p, port.s, port.len);	p += port.len;	if (proto.s) {		memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);		p += TRANSPORT_PARAM_LEN;		memcpy(p, proto.s, proto.len);		p += proto.len;	}	uri->s = buf;	uri->len = len;	return 0;}/* * Add received parameter to Contacts for further * forwarding of the REGISTER requuest */static intadd_rcv_param_f(struct sip_msg* msg, char* str1, char* str2){	contact_t* c;	struct lump* anchor;	char* param;	str uri;	if (create_rcv_uri(&uri, msg) < 0) {		return -1;	}	if (contact_iterator(&c, msg, 0) < 0) {		return -1;	}	while(c) {		param = (char*)pkg_malloc(RECEIVED_LEN + 2 + uri.len);		if (!param) {			LOG(L_ERR, "add_rcv_param: No memory left\n");			return -1;		}		memcpy(param, RECEIVED, RECEIVED_LEN);		param[RECEIVED_LEN] = '\"';		memcpy(param + RECEIVED_LEN + 1, uri.s, uri.len);		param[RECEIVED_LEN + 1 + uri.len] = '\"';		anchor = anchor_lump(msg, c->name.s + c->len - msg->buf, 0, 0);		if (anchor == NULL) {			LOG(L_ERR, "add_rcv_param: anchor_lump failed\n");			return -1;		}				if (insert_new_lump_after(anchor, param, RECEIVED_LEN + 1 + uri.len + 1, 0) == 0) {			LOG(L_ERR, "add_rcv_param: insert_new_lump_after failed\n");			pkg_free(param);			return -1;		}		if (contact_iterator(&c, msg, c) < 0) {			return -1;		}	}	return 1;}/* * Create an AVP to be used by registrar with the source IP and port * of the REGISTER */static intfix_nated_register_f(struct sip_msg* msg, char* str1, char* str2){	str uri;	int_str val;	int_str rcv_avp;	if (create_rcv_uri(&uri, msg) < 0) {		return -1;	}	val.s = &uri;	rcv_avp.n=rcv_avp_no;	if (add_avp(AVP_VAL_STR, rcv_avp, val) < 0) {		LOG(L_ERR, "fix_nated_register: Error while creating AVP\n");		return -1;	}	return 1;}

⌨️ 快捷键说明

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