コード例 #1
0
ファイル: det_nat.c プロジェクト: lidongliangfly/p2p
//stun_server: 
//		xxx.xxx.xxx[:port]
//return: bits 0~3: nat type
//	  bit 4: hairpin
//	  bit 5: preserve port
int detect_nat(const char *stun_server)
{
	StunAddress4 stunServerAddr;

	stunServerAddr.addr=0;
	if(!stunParseServerName( stun_server, &stunServerAddr)) return -1;


	BOOL presPort=FALSE;
	BOOL hairpin=FALSE;

	int stype = stunNatType( &stunServerAddr, &presPort, &hairpin, 0, NULL );
	if(presPort) stype |= 0x10;
	if(hairpin) stype |= 0x20;

	return stype;
}
コード例 #2
0
NatType get_nat_type(const char *stun_server)
{
	static const int CTRL_PORT = 3478;

	initNetwork();

	StunAddress4 stunServerAddr;
	stunServerAddr.addr = 0;

	StunAddress4 sAddr[1];
	sAddr[0].addr = 0;
	sAddr[0].port = 0;

	bool ret = stunParseServerName((char *) stun_server, stunServerAddr, CTRL_PORT);
	if (!ret) {
		return StunTypeFailure;
	}

	bool presPort = false;
	bool hairpin = false;
	return stunNatType(stunServerAddr, true, & presPort, & hairpin, 0, & sAddr[0]);
}
コード例 #3
0
bool stun_discover_nat(t_phone_user *pu, string &err_msg) {
	t_user *user_config = pu->get_user_profile();

	// By default enable STUN. If for some reason we cannot perform
	// NAT discovery, then enable STUN. It will not harm, but only
	// create non-needed STUN transactions if we are not behind a NAT.
	pu->use_stun = true;
	pu->use_nat_keepalive = true;

	list<t_ip_port> destinations = 
		user_config->get_stun_server().get_h_ip_srv("udp");

	if (destinations.empty()) {
		// Cannot resolve STUN server address.
		log_file->write_header("::main", LOG_NORMAL, LOG_CRITICAL);
		log_file->write_raw("Failed to resolve: ");
		log_file->write_raw(user_config->get_stun_server().encode());
		log_file->write_endl();
		log_file->write_footer();

		err_msg = TRANSLATE("Cannot resolve STUN server: %1");
		err_msg = replace_first(err_msg, "%1", user_config->get_stun_server().encode());
		return false;
	}

	while (!destinations.empty()) {
		StunAddress4 stun_ip4;
		stun_ip4.addr = destinations.front().ipaddr;
		stun_ip4.port = destinations.front().port;
		
		NatType nat_type = stunNatType(stun_ip4, false);
		log_file->write_header("::main");
		log_file->write_raw("STUN NAT type discovery for ");
		log_file->write_raw(user_config->get_profile_name());
		log_file->write_endl();
		log_file->write_raw("NAT type: ");
		log_file->write_raw(stunNatType2Str(nat_type));
		log_file->write_endl();
		log_file->write_footer();
		
		switch (nat_type) {
		case StunTypeOpen:
			// STUN is not needed.
			pu->use_stun = false;
			pu->use_nat_keepalive = false;
			return true;
		case StunTypeSymNat:
			err_msg = TRANSLATE("You are behind a symmetric NAT.\nSTUN will not work.\nConfigure a public IP address in the user profile\nand create the following static bindings (UDP) in your NAT.");
			err_msg += "\n\n";
			err_msg += TRANSLATE("public IP: %1 --> private IP: %2 (SIP signaling)");
			err_msg = replace_first(err_msg, "%1", int2str(sys_config->get_sip_port()));
			err_msg = replace_first(err_msg, "%2", int2str(sys_config->get_sip_port()));
			err_msg += "\n";
			err_msg += TRANSLATE("public IP: %1-%2 --> private IP: %3-%4 (RTP/RTCP)");
			err_msg = replace_first(err_msg, "%1", int2str(sys_config->get_rtp_port()));
			err_msg = replace_first(err_msg, "%2", int2str(sys_config->get_rtp_port() + 5));
			err_msg = replace_first(err_msg, "%3", int2str(sys_config->get_rtp_port()));
			err_msg = replace_first(err_msg, "%4", int2str(sys_config->get_rtp_port() + 5));
			
			pu->use_stun = false;
			pu->use_nat_keepalive = false;
			return false;
		case StunTypeSymFirewall:
			// STUN is not needed as we are on a pubic IP.
			// NAT keep alive is needed however to keep the firewall open.
			pu->use_stun = false;
			return true;
		case StunTypeBlocked:
			destinations.pop_front();
			
			// The code for NAT type discovery does not handle
			// ICMP errors. So if the conclusion is that the network
			// connection is blocked, it might be due to a down STUN
			// server. Try alternative destination if avaliable.
		
			if (destinations.empty()) {
				err_msg = TRANSLATE("Cannot reach the STUN server: %1");
				err_msg = replace_first(err_msg, "%1",
						user_config->get_stun_server().encode());
				err_msg += "\n\n";
				err_msg += TRANSLATE("If you are behind a firewall then you need to open the following UDP ports.");
				err_msg += "\n";
				err_msg += TRANSLATE("Port %1 (SIP signaling)");
				err_msg = replace_first(err_msg, "%1",
						int2str(sys_config->get_sip_port()));
				err_msg += "\n";
				err_msg += TRANSLATE("Ports %1-%2 (RTP/RTCP)");
				err_msg = replace_first(err_msg, "%1",
						int2str(sys_config->get_rtp_port()));
				err_msg = replace_first(err_msg, "%2",
						int2str(sys_config->get_rtp_port() + 5));
						
				return false;
			}
			
			log_file->write_report("Failover to next destination.",
				"::stun_discover_nat");			
			break;
		case StunTypeFailure:
			destinations.pop_front();
			log_file->write_report("Failover to next destination.",
				"::stun_discover_nat");
			break;
		default:
			// Use STUN.
			return true;
		}
	}

	err_msg = TRANSLATE("NAT type discovery via STUN failed.");	
	return false;
}
コード例 #4
0
ファイル: stun-resolver.cpp プロジェクト: zhenyouluo/p2p-17
STUN_NAT_TYPE_T StunResolver::ResolveInternal(const std::string &server)
{
	STUN_NAT_TYPE_T type = STUN_NAT_TYPE_UNKNOWN;
	do {
		StunAddress4 stunServerAddr;
		stunServerAddr.addr = 0;

		// resolve server address
		bool ret = stunParseServerName(const_cast<char *>(server.c_str()), stunServerAddr);
		if (!ret || 0 == stunServerAddr.addr) {
			LOGE("Cannot parser stun server address: %s", server.c_str());
			break;
		}

		int srcPort = stunRandomPort();

		bool presPort = false;
		bool hairpin = false;
		StunAddress4 sAddr;
		sAddr.addr = 0;
		sAddr.port = 0;

		NatType stype = stunNatType(stunServerAddr, false,
			&presPort, &hairpin, srcPort, &sAddr);

		switch (stype)
		{
		case StunTypeIndependentFilter:
			LOGD("Independent Mapping, Independent Filter: presPort %d hairpin %d", presPort, hairpin);
			type = STUN_NAT_TYPE_CONE;
			break;
		case StunTypeDependentFilter:
			LOGD("Independent Mapping, Address Dependent Filter: presPort %d hairpin %d", presPort, hairpin);
			type = STUN_NAT_TYPE_RESTRICTED;
			break;
		case StunTypePortDependedFilter:
			LOGD("Independent Mapping, Port Dependent Filter: presPort %d hairpin %d", presPort, hairpin);
			type = STUN_NAT_TYPE_PORT_RESTRICTED;
			break;
		case StunTypeDependentMapping:
			LOGD("Dependent Mapping: presPort %d hairpin %d", presPort, hairpin);
			type = STUN_NAT_TYPE_SYM;
			break;
		case StunTypeFailure:
			LOGE("Some stun error detetecting NAT type");
			break;
		case StunTypeUnknown:
			LOGE("Some unknown type error detetecting NAT type");
			break;
		case StunTypeOpen:
			LOGE("Open stun type");
			break;
		case StunTypeFirewall:
			cout << "Firewall";
			break;
		case StunTypeBlocked:
			cout << "Blocked or could not reach STUN server";
			break;
		default:
			LOGD("Unknown NAT stype: %d", stype);
			break;
		}
	} while (false);

	return type;
}