/*
========================
Net_SendUDPPacket
========================
*/
void Net_SendUDPPacket( int netSocket, int length, const void* data, const netadr_t to )
{
	int				ret;
	sockaddr_in		addr;
	
	if( !netSocket )
	{
		return;
	}
	
	Net_NetadrToSockadr( &to, &addr );
	
	if( usingSocks && to.type == NA_IP )
	{
		socksBuf[0] = 0;	// reserved
		socksBuf[1] = 0;
		socksBuf[2] = 0;	// fragment (not fragmented)
		socksBuf[3] = 1;	// address type: IPV4
		*( int* )&socksBuf[4] = addr.sin_addr.s_addr;
		*( short* )&socksBuf[8] = addr.sin_port;
		memcpy( &socksBuf[10], data, length );
		ret = sendto( netSocket, socksBuf, length + 10, 0, ( sockaddr* )&socksRelayAddr, sizeof( socksRelayAddr ) );
	}
	else
	{
		ret = sendto( netSocket, ( const char* )data, length, 0, ( sockaddr* )&addr, sizeof( addr ) );
	}
	if( ret == SOCKET_ERROR )
	{
		int err = Net_GetLastError();
		// some PPP links do not allow broadcasts and return an error
		if( ( err == D3_NET_EADDRNOTAVAIL ) && ( to.type == NA_BROADCAST ) )
		{
			return;
		}
		
		// NOTE: EWOULDBLOCK used to be silently ignored,
		// but that means the packet will be dropped so I don't feel it's a good thing to ignore
		idLib::Printf( "UDP sendto error - packet dropped: %s\n", NET_ErrorString() );
	}
}
	bool SocketIsReady( SOCKET sock )
	{
		timeval tv;
		fd_set mask;
		bool ready = false;

		do 
		{
			Net_SetLastError( 0 );

			FD_ZERO( &mask );
			FD_SET( sock, &mask );

			tv.tv_sec = 0;
			tv.tv_usec = 0;

			ready = select( sock + 1, &mask, 0, 0, &tv ) == 1;
		} while ( Net_GetLastError() == EINTR );

		return ready;
	}
/*
========================
Net_GetUDPPacket
========================
*/
bool Net_GetUDPPacket( int netSocket, netadr_t& net_from, char* data, int& size, int maxSize )
{
	int 			ret;
	sockaddr_in		from;
	socklen_t		fromlen;
	int				err;
	
	if( !netSocket )
	{
		return false;
	}
	
	fromlen = sizeof( from );
	ret = recvfrom( netSocket, data, maxSize, 0, ( sockaddr* )&from, &fromlen );
	if( ret == SOCKET_ERROR )
	{
		err = Net_GetLastError();
		
		if( err == D3_NET_EWOULDBLOCK || err == D3_NET_ECONNRESET )
		{
			return false;
		}
		
		idLib::Printf( "Net_GetUDPPacket: %s\n", NET_ErrorString() );
		return false;
	}
#if 0
	// TODO: WTF was this about?
	// DG: ip_socket is never initialized, so this is dead code
	// - and if netSocket is 0 (so this would be true) recvfrom above will already fail
	if( static_cast<unsigned int>( netSocket ) == ip_socket )
	{
		memset( from.sin_zero, 0, sizeof( from.sin_zero ) );
	}
	
	if( usingSocks && static_cast<unsigned int>( netSocket ) == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 )
	{
		if( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 )
		{
			return false;
		}
		net_from.type = NA_IP;
		net_from.ip[0] = data[4];
		net_from.ip[1] = data[5];
		net_from.ip[2] = data[6];
		net_from.ip[3] = data[7];
		net_from.port = *( short* )&data[8];
		memmove( data, &data[10], ret - 10 );
	}
	else
	{
#endif // 0
	
		Net_SockadrToNetadr( &from, &net_from );
#if 0 // this is ugly, but else astyle is confused
	}
#endif
	
	if( ret > maxSize )
	{
		idLib::Printf( "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) );
		return false;
	}
	
	size = ret;
	
	return true;
}