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

📄 udpsocket.cpp.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
字号:
void UdpSocket::OnRead()
{
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	if (IsIpv6())
	{
		struct sockaddr_in6 sa;
		socklen_t sa_len = sizeof(sa);
		if (m_b_read_ts)
		{
			struct timeval ts;
			Utility::GetTime(&ts);
#if !defined(LINUX) && !defined(MACOSX)
			int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
#else
			int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
#endif
			if (n > 0)
			{
				this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
			}
			else
			if (n == -1)
			{
#ifdef _WIN32
				if (Errno != WSAEWOULDBLOCK)
#else
				if (Errno != EWOULDBLOCK)
#endif
					Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
			}
			return;
		}
		int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
		int q = m_retries; // receive max 10 at one cycle
		while (n > 0)
		{
			if (sa_len != sizeof(sa))
			{
				Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
			}
			this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
			if (!q--)
				break;
			//
			n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
		}
		if (n == -1)
		{
#ifdef _WIN32
			if (Errno != WSAEWOULDBLOCK)
#else
			if (Errno != EWOULDBLOCK)
#endif
				Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
		}
		return;
	}
#endif
#endif
	struct sockaddr_in sa;
	socklen_t sa_len = sizeof(sa);
	if (m_b_read_ts)
	{
		struct timeval ts;
		Utility::GetTime(&ts);
#if !defined(LINUX) && !defined(MACOSX)
		int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
#else
		int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
#endif
		if (n > 0)
		{
			this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
		}
		else
		if (n == -1)
		{
#ifdef _WIN32
			if (Errno != WSAEWOULDBLOCK)
#else
			if (Errno != EWOULDBLOCK)
#endif
				Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
		}
		return;
	}
	int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
	int q = m_retries;
	while (n > 0)
	{
		if (sa_len != sizeof(sa))
		{
			Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
		}
		this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
		if (!q--)
			break;
		//
		n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
	}
	if (n == -1)
	{
#ifdef _WIN32
		if (Errno != WSAEWOULDBLOCK)
#else
		if (Errno != EWOULDBLOCK)
#endif
			Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
	}
}


void UdpSocket::SetBroadcast(bool b)
{
	int one = 1;
	int zero = 0;

	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
	if (b)
	{
		if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one)) == -1)
		{
			Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
		}
	}
	else
	{
		if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &zero, sizeof(zero)) == -1)
		{
			Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
		}
	}
}


bool UdpSocket::IsBroadcast()
{
	int is_broadcast = 0;
	socklen_t size;

	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
	if (getsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *)&is_broadcast, &size) == -1)
	{
		Handler().LogError(this, "IsBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
	}
	return is_broadcast != 0;
}


void UdpSocket::SetMulticastTTL(int ttl)
{
	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
	if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(int)) == -1)
	{
		Handler().LogError(this, "SetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
	}
}


int UdpSocket::GetMulticastTTL()
{
	int ttl = 0;
	socklen_t size = sizeof(int);

	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
	if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, &size) == -1)
	{
		Handler().LogError(this, "GetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
	}
	return ttl;
}


void UdpSocket::SetMulticastLoop(bool x)
{
	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	if (IsIpv6())
	{
		int val = x ? 1 : 0;
		if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
		{
			Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
		}
		return;
	}
#endif
#endif
	int val = x ? 1 : 0;
	if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
	{
		Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
	}
}


bool UdpSocket::IsMulticastLoop()
{
	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	if (IsIpv6())
	{
		int is_loop = 0;
		socklen_t size = sizeof(int);
		if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
		{
			Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
		}
		return is_loop ? true : false;
	}
#endif
#endif
	int is_loop = 0;
	socklen_t size = sizeof(int);
	if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
	{
		Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
	}
	return is_loop ? true : false;
}


void UdpSocket::AddMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
{
	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	if (IsIpv6())
	{
		struct ipv6_mreq x;
		struct in6_addr addr;
		if (Utility::u2ip( group, addr ))
		{
			x.ipv6mr_multiaddr = addr;
			x.ipv6mr_interface = if_index;
			if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
			{
				Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
			}
		}
		return;
	}
#endif
#endif
	struct ip_mreq x; // ip_mreqn
	ipaddr_t addr;
	if (Utility::u2ip( group, addr ))
	{
		memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
		Utility::u2ip( local_if, addr);
		memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr));
//		x.imr_ifindex = if_index;
		if (setsockopt(GetSocket(), SOL_IP, IP_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
		{
			Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
		}
	}
}


void UdpSocket::DropMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
{
	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	if (IsIpv6())
	{
		struct ipv6_mreq x;
		struct in6_addr addr;
		if (Utility::u2ip( group, addr ))
		{
			x.ipv6mr_multiaddr = addr;
			x.ipv6mr_interface = if_index;
			if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
			{
				Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
			}
		}
		return;
	}
#endif
#endif
	struct ip_mreq x; // ip_mreqn
	ipaddr_t addr;
	if (Utility::u2ip( group, addr ))
	{
		memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
		Utility::u2ip( local_if, addr);
		memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr));
//		x.imr_ifindex = if_index;
		if (setsockopt(GetSocket(), SOL_IP, IP_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
		{
			Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
		}
	}
}


#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
void UdpSocket::SetMulticastHops(int hops)
{
	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
	if (!IsIpv6())
	{
		Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
		return;
	}
	if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, sizeof(int)) == -1)
	{
		Handler().LogError(this, "SetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
	}
}


int UdpSocket::GetMulticastHops()
{
	if (GetSocket() == INVALID_SOCKET)
	{
		CreateConnection();
	}
	if (!IsIpv6())
	{
		Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
		return -1;
	}
	int hops = 0;
	socklen_t size = sizeof(int);
	if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, &size) == -1)
	{
		Handler().LogError(this, "GetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
	}
	return hops;
}
#endif // IPPROTO_IPV6
#endif


bool UdpSocket::IsBound()
{
	return m_bind_ok;
}


void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len)
{
}


void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len, struct timeval *ts)
{
}


port_t UdpSocket::GetPort()
{
	return m_port;
}


int UdpSocket::GetLastSizeWritten()
{
	return m_last_size_written;
}


void UdpSocket::SetTimestamp(bool x)
{
	m_b_read_ts = x;
}


#ifdef SOCKETS_NAMESPACE
}
#endif


⌨️ 快捷键说明

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