Ejemplo n.º 1
0
bool SocketImpl::Connect(const SocketAddress& address, const std::chrono::seconds& timeout /*= std::chrono::seconds(0)*/)
{
    if (INVALID_SOCKET == m_sockfd)
        Init(AF_INET);
    if (timeout.count() > 0)
        SetBlocking(false);
    bool bResult = false;
    do 
    {
        if (SOCKET_ERROR == connect(m_sockfd, address.GetAddress(), address.GetLength()))
        {
            if (timeout.count() == 0)
                break;
            int err = WSAGetLastError();
            if (WSAEINPROGRESS != err
                && WSAEWOULDBLOCK != err
                && WSAEISCONN != err)
                break;
            if (!Poll(timeout, SELECT_READ | SELECT_WRITE | SELECT_ERROR))
                break;
            if (GetSocketError() != 0)
                break;
        }
        bResult = true;
    } while (0);
    if (timeout.count() > 0)
        SetBlocking(true);
    return bResult;
}
Ejemplo n.º 2
0
int TCPSocket::Connect( unsigned short timeout )
{
    fd_set rd, wr;
    long status;
    struct timeval tv;
    char err;
    socklen_t len = sizeof ( int );

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

    FD_ZERO ( &rd );
    FD_SET ( mSockFd, &rd );
    FD_ZERO ( &wr );
    FD_SET ( mSockFd, &wr );

    SetBlocking ( false );

    if ( ( status = connect ( mSockFd, reinterpret_cast<struct sockaddr*> ( &mCa ), sizeof ( mCa ) ) ) == -1 )
    {
        if ( errno != EINPROGRESS )
        {
            return static_cast<int> ( status );
        }
    }

    status = select (mSockFd + 1, &rd, &wr, NULL, &tv);

    if ( !FD_ISSET ( mSockFd, &rd ) && !FD_ISSET ( mSockFd, &wr ) )
    {
        return -2;
    }

    if ( getsockopt ( mSockFd, SOL_SOCKET, SO_ERROR, &err, &len ) < 0)
    {
        return -2;
    }

    if ( err == 0 )
    {
        // TCP connection established.
        // Make the socket blocking again...

        SetBlocking ( true );

        // And return from the function.

        return 0;
    }

    return -1;
}
Ejemplo n.º 3
0
	Int32 TcpSocketWin32::Receive( void * p_pData, const SizeType p_Size, const Time & p_Timeout )
	{
		// Create a socket address storage
		sockaddr_in address;
		int addressSize = sizeof( address );

		// Set blocking status
		Bool blocking = GetBlocking( );
		if( blocking )
		{
			SetBlocking( false );
		}

		// Put the socket handle in a fdset
		fd_set fdset;
		FD_ZERO( &fdset );
		FD_SET( m_Handle, &fdset );

		// Set the time
		struct timeval tv;
		if( p_Timeout.AsMicroseconds( ) / 1000000ULL > g_MaxTimeout )
		{
			tv.tv_sec	= static_cast<long>( g_MaxTimeout );
			tv.tv_usec	= static_cast<long>( 0 );
		}
		else
		{
			tv.tv_sec	= static_cast<long>( p_Timeout.AsMicroseconds( ) / 1000000ULL );
			tv.tv_usec	= static_cast<long>( p_Timeout.AsMicroseconds( ) % 1000000ULL );
		}

		// Select from the fdset
		int status = 0;
		if( ( status = select( static_cast<int>( m_Handle ) + 1, &fdset, NULL, NULL, &tv ) ) > 0 )
		{
			// Receive the message
			int size = recv( m_Handle, reinterpret_cast<char*>( p_pData ), static_cast<int>( p_Size ), 0 );

			// Restore the block status
			SetBlocking( blocking );

			// return the received message's size
			return size;
		}

		// Reset the blocking status and return false
		SetBlocking( blocking );
		return status;
	}
Ejemplo n.º 4
0
NetworkInterface::ServiceSocketInterface& WindowsNetwork::NewServiceSocket(aushort port, aushort numPending) {
	addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;
	addrinfo *result = nullptr;
	ScopedFuncCall blast([result]() { if(result) freeaddrinfo(result); });
	char number[8]; // 64*1024+null
	if(port) _itoa_s(port, number, 10);
	if(getaddrinfo(NULL, port? number : NULL, &hints, &result)) throw std::exception("getaddrinfo failed.");
	SOCKET listener = INVALID_SOCKET;
	ScopedFuncCall clearSocket([&listener]() { if(listener != INVALID_SOCKET) closesocket(listener); });
	listener = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if(listener == INVALID_SOCKET) throw std::exception("Error creating new Service Socket, creation failed.");
    SetBlocking(listener, false);
	if(bind(listener, result->ai_addr, static_cast<int>(result->ai_addrlen)) == SOCKET_ERROR) throw std::exception("Error creating new Service Socket, could not bind.");
	if(listen(listener, numPending? numPending : SOMAXCONN) == SOCKET_ERROR) throw std::exception("Error creating new Service Socket, could enter listen state.");
	
	std::unique_ptr<ServiceSocket> add(new ServiceSocket(listener, port));
	clearSocket.Dont();
	servers.insert(std::make_pair(static_cast<SocketInterface*>(add.get()), add.get()));
	return *add.release();
}
Ejemplo n.º 5
0
////////////////////////////////////////////////////////////
/// Construct the socket from a socket descriptor
/// (for internal use only)
////////////////////////////////////////////////////////////
SocketTCP::SocketTCP(SocketHelper::SocketType Descriptor) :
mySocket           (Descriptor),
myPendingPacketSize(-1)
{
    // Set blocking by default (should always be the case anyway)
    SetBlocking(true);
}
Ejemplo n.º 6
0
////////////////////////////////////////////////////////////
/// Create the socket
////////////////////////////////////////////////////////////
void SocketTCP::Create(SocketHelper::SocketType Descriptor)
{
    // Use the given socket descriptor, or get a new one
    mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_STREAM, 0);
    myIsBlocking = true;

    // Reset the pending packet
    myPendingPacket.clear();
    myPendingPacketSize = -1;

    // Setup default options
    if (IsValid())
    {
        // To avoid the "Address already in use" error message when trying to bind to the same port
        int Yes = 1;
        if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
        {
            std::cerr << "Failed to set socket option \"SO_REUSEADDR\" ; "
                      << "binding to a same port may fail if too fast" << std::endl;
        }

        // Disable the Nagle algorithm (ie. removes buffering of TCP packets)
        if (setsockopt(mySocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
        {
            std::cerr << "Failed to set socket option \"TCP_NODELAY\" ; "
                      << "all your TCP packets will be buffered" << std::endl;
        }

        // Set blocking by default (should always be the case anyway)
        SetBlocking(true);
    }
}
Ejemplo n.º 7
0
////////////////////////////////////////////////////////////
/// Create the socket
////////////////////////////////////////////////////////////
void SocketUDP::Create(SocketHelper::SocketType Descriptor)
{
    // Use the given socket descriptor, or get a new one
    mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_DGRAM, 0);
    myIsBlocking = true;

    // Clear the last port used
    myPort = 0;

    // Reset the pending packet
    myPendingHeaderSize = 0;
    myPendingPacket.clear();
    myPendingPacketSize = -1;

    // Setup default options
    if (IsValid())
    {
        // To avoid the "Address already in use" error message when trying to bind to the same port
        int Yes = 1;
        if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
        {
            std::cerr << "Failed to set socket option \"reuse address\" ; "
                      << "binding to a same port may fail if too fast" << std::endl;
        }

        // Enable broadcast by default
        if (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
        {
            std::cerr << "Failed to enable broadcast on UDP socket" << std::endl;
        }

        // Set blocking by default (should always be the case anyway)
        SetBlocking(true);
    }
}
Ejemplo n.º 8
0
UDPConnectedSocket::UDPConnectedSocket(const std::string& server, const unsigned remoteport)
: Socket(DATAGRAM)
{
	sockaddr_in remoteAddr = ResolveHost(server, remoteport);
	if (connect(mySocket, (sockaddr*)&remoteAddr, sizeof(remoteAddr)) == SOCKET_ERROR)
	{
		throw network_error(std::string("Error while connecting: ") + GetErrorMsg());
	}
	SetBlocking(false);
}
Ejemplo n.º 9
0
bool plTcpSocket::ActiveOpenNonBlocking(plNetAddress & addr)
{
    SetSocket(plNet::NewTCP());
    if(fSocket == kBadSocket)
        return false;

    SetBlocking(false);

    if(plNet::Connect(fSocket, &addr.GetAddressInfo()) != 0)
        return ErrorClose();
    
    return true;
}
Ejemplo n.º 10
0
//
// NetListenSocket::InitScan			- Chapter X, page Y
//   Opens multiple ports to listen for connections.
//
void NetListenSocket::InitScan(int portnum_min, int portnum_max) 
{
	struct sockaddr_in sa;
	int portnum, x = 1;

	if ((m_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
	{
		EXIT_ASSERT
		exit(1);
	}

	if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&x, sizeof(x)) == SOCKET_ERROR) 
	{
		closesocket(m_sock);
		m_sock = INVALID_SOCKET;
		EXIT_ASSERT
		exit(1);
	}

	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	for (portnum = portnum_min; portnum < portnum_max; portnum++) 
	{
		sa.sin_port = htons(portnum);
		// bind to port
		if (bind(m_sock, (struct sockaddr *)&sa, sizeof(sa)) != SOCKET_ERROR)
			break;
	}

	if (portnum == portnum_max) 
	{
		closesocket(m_sock);
		m_sock = INVALID_SOCKET;
		EXIT_ASSERT
		exit(1);
	}

	// set nonblocking - accept() blocks under some odd circumstances otherwise
	SetBlocking(false);

	// start listening
	if (listen(m_sock, 8) == SOCKET_ERROR) 
	{
		closesocket(m_sock);
		m_sock = INVALID_SOCKET;
		EXIT_ASSERT
		exit(1);
	}

	port = portnum;
 }
Ejemplo n.º 11
0
NetworkInterface::ConnectedSocketInterface& WindowsNetwork::BeginConnection(ServiceSocketInterface &listener) {
	auto real(servers.find(&listener));
	if(real == servers.cend()) throw std::exception("Trying to create a connection from a socket not managed by this object.");
	SOCKET connSock = real->second->socket;
	SOCKET client = accept(connSock, NULL, NULL);
	if(client == INVALID_SOCKET) throw std::exception("Could not accept an incoming connection.");
	SetBlocking(client, false);
	ScopedFuncCall clearSocket([client]() { if(client) closesocket(client); });
	std::unique_ptr<ConnectedSocket> add(new ConnectedSocket(nullptr, nullptr));
	add->socket = client;
	clearSocket.Dont();
	connections.insert(std::make_pair(static_cast<SocketInterface*>(add.get()), add.get()));
	return *add.release();
}
Ejemplo n.º 12
0
		FDType GetSocket (bool is_v6) {
		
			//	Make a socket for the appropriate
			//	address family
			auto socket=::socket(
				is_v6 ? AF_INET6 : AF_INET,
				SOCK_STREAM,
				IPPROTO_TCP
			);
			
			//	Make sure it's non-blocking
			SetBlocking(socket,false);
			
			return socket;
		
		}
Ejemplo n.º 13
0
//
// NetListenSocket::Init						- Chapter 19, page 674
//
void NetListenSocket::Init(int portnum)
{
	struct sockaddr_in sa;
	int value = 1;

	if ((m_sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
	{
      LOG_ASSERT("NetListenSocket Error: Init failed to create socket handle");
	}

	if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(value))== SOCKET_ERROR) 
	{
		perror("NetListenSocket::Init: setsockopt");
		closesocket(m_sock);
		m_sock = INVALID_SOCKET;
		LOG_ASSERT("NetListenSocket Error: Init failed to set socket options");

	}
	
	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = ADDR_ANY;
	sa.sin_port = htons(portnum);

	// bind to port
	if (bind(m_sock, (struct sockaddr *)&sa, sizeof(sa)) == SOCKET_ERROR) 
	{
		perror("NetListenSocket::Init: bind");
		closesocket(m_sock);
		m_sock = INVALID_SOCKET;
		LOG_ASSERT("NetListenSocket Error: Init failed to bind");
	}

	// set nonblocking - accept() blocks under some odd circumstances otherwise
	SetBlocking(false);

	// start listening
	if (listen(m_sock, 256) == SOCKET_ERROR) 
	{
		closesocket(m_sock);
		m_sock = INVALID_SOCKET;
		LOG_ASSERT("NetListenSocket Error: Init failed to listen");
	}

	port = portnum;
}
Ejemplo n.º 14
0
////////////////////////////////////////////////////////////
/// Create the socket
////////////////////////////////////////////////////////////
void SocketTCP::Create()
{
    // Get a new socket descriptor
    mySocket = socket(PF_INET, SOCK_STREAM, 0);

    // To avoid the "Address already in use" error message when trying to bind to the same port
    char Yes = 1;
    if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int)) == -1)
    {
        std::cerr << "Failed to set socket option \"reuse address\" ; "
                  << "binding to a same port may fail if too fast" << std::endl;
    }

    // Set blocking by default (should always be the case anyway)
    SetBlocking(true);

    // Reset the pending packet
    myPendingPacket.Clear();
    myPendingPacketSize = -1;
}
Ejemplo n.º 15
0
////////////////////////////////////////////////////////////
/// Create the socket
////////////////////////////////////////////////////////////
void SocketTCP::Create(SocketHelper::SocketType Descriptor)
{
    // Use the given socket descriptor, or get a new one
    mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_STREAM, 0);
    myIsBlocking = true;

    // Reset the pending packet
    myPendingHeaderSize = 0;
    myPendingPacket.clear();
    myPendingPacketSize = -1;

    // Setup default options
    if (IsValid())
    {
		int Yes = 1;
#ifndef SFML_SYSTEM_WINDOWS
        /* We must disable this in order to detect if ports are being used by other apps, or 
           other instances of dolphin. This is also disabled in SFML 2.0, see
http://www.sfml-dev.org/forum/viewtopic.php?t=3388
           ...In fact, SO_REUSEADDR is only unsafe on Windows.  See:
           http://stackoverflow.com/questions/14388706
        */
        // To avoid the "Address already in use" error message when trying to bind to the same port
        if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
        {
            std::cerr << "Failed to set socket option \"SO_REUSEADDR\" ; "
                      << "binding to a same port may fail if too fast" << std::endl;
        }
#endif

        // Disable the Nagle algorithm (ie. removes buffering of TCP packets)
        if (setsockopt(mySocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
        {
            std::cerr << "Failed to set socket option \"TCP_NODELAY\" ; "
                      << "all your TCP packets will be buffered" << std::endl;
        }

        // Set blocking by default (should always be the case anyway)
        SetBlocking(true);
    }
}
Ejemplo n.º 16
0
void NetListenSocket::Init(int portnum) {
    struct sockaddr_in sa;
    int value = 1;

    if ((m_sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        GCC_ERROR("NetListenSocket Error: Init failed to created socket handle");
    }

    if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value)) == SOCKET_ERROR) {
        closesocket(m_sock);
        m_sock = INVALID_SOCKET;
        GCC_ERROR("NetListenSocket Error: Init failed to set socket options");
    }

    printf("Hey hey.  Here is the INADDR_ANY = %d\n", INADDR_ANY);
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = INADDR_ANY;
    sa.sin_port = htons(portnum);

    if (bind(m_sock, (struct sockaddr*)&sa, sizeof(sa)) == SOCKET_ERROR) {
        closesocket(m_sock);
        m_sock = INVALID_SOCKET;
        GCC_ERROR("NetListenSocket Error: Init failed to bind");
    }

    SetBlocking(false);

    if (listen(m_sock, 256) == SOCKET_ERROR) {
        closesocket(m_sock);
        m_sock = INVALID_SOCKET;
        GCC_ERROR("NetListenSocket Error: Init failed to listen");
    }

    port = portnum;
}
Ejemplo n.º 17
0
////////////////////////////////////////////////////////////
/// Connect to another computer on a specified port
////////////////////////////////////////////////////////////
Socket::Status SocketTCP::Connect(unsigned short Port, const IPAddress& HostAddress, float Timeout)
{
    // Make sure our socket is valid
    if (!IsValid())
        Create();

    // Build the host address
    sockaddr_in SockAddr;
    memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
    SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str());
    SockAddr.sin_family      = AF_INET;
    SockAddr.sin_port        = htons(Port);

    if (Timeout <= 0)
    {
        // ----- We're not using a timeout : just try to connect -----

        if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
        {
            // Failed to connect
            return SocketHelper::GetErrorStatus();
        }

        // Connection succeeded
        return Socket::Done;
    }
    else
    {
        // ----- We're using a timeout : we'll need a few tricks to make it work -----

        // Save the previous blocking state
        bool IsBlocking = myIsBlocking;

        // Switch to non-blocking to enable our connection timeout
        if (IsBlocking)
            SetBlocking(false);

        // Try to connect to host
        if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) >= 0)
        {
            // We got instantly connected! (it may no happen a lot...)
            return Socket::Done;
        }

        // Get the error status
        Socket::Status Status = SocketHelper::GetErrorStatus();

        // If we were in non-blocking mode, return immediatly
        if (!IsBlocking)
            return Status;

        // Otherwise, wait until something happens to our socket (success, timeout or error)
        if (Status == Socket::NotReady)
        {
            // Setup the selector
            fd_set Selector;
            FD_ZERO(&Selector);
            FD_SET(mySocket, &Selector);

            // Setup the timeout
            timeval Time;
            Time.tv_sec  = static_cast<long>(Timeout);
            Time.tv_usec = (static_cast<long>(Timeout * 1000) % 1000) * 1000;

            // Wait for something to write on our socket (would mean the connection has been accepted)
            if (select(static_cast<int>(mySocket + 1), NULL, &Selector, NULL, &Time) > 0)
            {
                // Connection succeeded
                Status = Socket::Done;
            }
            else
            {
                // Failed to connect before timeout is over
                Status = SocketHelper::GetErrorStatus();
            }
        }

        // Switch back to blocking mode
        SetBlocking(true);

        return Status;
    }
}
Ejemplo n.º 18
0
Socket::Status TcpSocket::Connect(const IpAddress& remoteAddress, unsigned short remotePort, Uint32 timeout)
{
    // Create the internal socket if it doesn't exist
    Create();

    // Create the remote address
    sockaddr_in address = priv::SocketImpl::CreateAddress(remoteAddress.ToInteger(), remotePort);

    if (timeout == 0)
    {
        // ----- We're not using a timeout: just try to connect -----

        // Connect the socket
        if (connect(GetHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
            return priv::SocketImpl::GetErrorStatus();

        // Connection succeeded
        return Done;
    }
    else
    {
        // ----- We're using a timeout: we'll need a few tricks to make it work -----

        // Save the previous blocking state
        bool blocking = IsBlocking();

        // Switch to non-blocking to enable our connection timeout
        if (blocking)
            SetBlocking(false);

        // Try to connect to the remote address
        if (connect(GetHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
        {
            // We got instantly connected! (it may no happen a lot...)
            return Done;
        }

        // Get the error status
        Status status = priv::SocketImpl::GetErrorStatus();

        // If we were in non-blocking mode, return immediatly
        if (!blocking)
            return status;

        // Otherwise, wait until something happens to our socket (success, timeout or error)
        if (status == Socket::NotReady)
        {
            // Setup the selector
            fd_set selector;
            FD_ZERO(&selector);
            FD_SET(GetHandle(), &selector);

            // Setup the timeout
            timeval time;
            time.tv_sec  = timeout / 1000;
            time.tv_usec = (timeout - time.tv_sec * 1000) * 1000;

            // Wait for something to write on our socket (which means that the connection request has returned)
            if (select(static_cast<int>(GetHandle() + 1), NULL, &selector, NULL, &time) > 0)
            {
                // At this point the connection may have been either accepted or refused.
                // To know whether it's a success or a failure, we must check the address of the connected peer
                if (GetRemoteAddress() != sf::IpAddress::None)
                {
                    // Connection accepted
                    status = Done;
                }
                else
                {
                    // Connection refused
                    status = priv::SocketImpl::GetErrorStatus();
                }
            }
            else
            {
                // Failed to connect before timeout is over
                status = priv::SocketImpl::GetErrorStatus();
            }
        }

        // Switch back to blocking mode
        SetBlocking(true);

        return status;
    }
}
Ejemplo n.º 19
0
	Bool TcpSocketWin32::Connect(const Address & p_Address, const Uint16 p_Port, const Time & p_Timeout, const Uint16 p_EndpointPort)
	{
		// Create the socket
		if ((m_Handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
		{
			bitLogNetErr(  "Can not create the socket. Error: " << static_cast<Int32>(GetLastError()) );
			return false;
		}

		// Bind the socket to a port
		sockaddr_in service;

		if (p_EndpointPort != 0)
		{
			service.sin_family = AF_INET;
			service.sin_addr.s_addr = htonl(INADDR_ANY);
			service.sin_port = htons(static_cast<u_short>(p_EndpointPort));

			const int optVal = 1;
			const int optLen = sizeof(optVal);
			int rtn = setsockopt(m_Handle, SOL_SOCKET, SO_REUSEADDR, (const char*)&optVal, optLen);
			if( rtn != 0 )
			{
				bitLogNetErr(  "Can not set reusable socket. Error: " << static_cast<Int32>(GetLastError()) );
				return false;
			}

			// Bind
			if (bind(m_Handle, reinterpret_cast<const sockaddr *>(&service), sizeof(service)) == SOCKET_ERROR)
			{
				bitLogNetErr(  "Can not bind the socket. Error: " << static_cast<Int32>(GetLastError()) );
				return false;
			}
		}
		
		// Create an object that's holding the host data
		service.sin_family = AF_INET;
		service.sin_addr.s_addr = htonl( static_cast<u_long>( p_Address.GetAddress( ) ) );
		service.sin_port = htons( static_cast<u_short>( p_Port ) );

		// We are using timeout
		// Get the blocking status and disable it.
		Bool blocking = GetBlocking( );
		SetBlocking( false );

		// Connect
		if( connect( m_Handle, ( const sockaddr * )&service, sizeof (sockaddr_in ) ) != 0 )
		{
		   // Ignore the WSAEWOULDBLOCK error
			DWORD lastError = GetLastError( );
			if( lastError != WSAEWOULDBLOCK )
			{
				Disconnect( );
				return false;
			}
		}

		// We failed to connect, but we are waiting for the connection to establish
		struct timeval tv;
		if( p_Timeout.AsMicroseconds( ) / 1000000ULL > g_MaxTimeout )
		{
			tv.tv_sec	= static_cast<long>( g_MaxTimeout );
			tv.tv_usec	= static_cast<long>( 0 );
		}
		else
		{
			tv.tv_sec	= static_cast<long>( p_Timeout.AsMicroseconds( ) / 1000000ULL );
			tv.tv_usec
			= static_cast<long>( p_Timeout.AsMicroseconds( ) % 1000000ULL );
		}

		// Create a FD_SET, and add the m_Handle to the set
		fd_set fdset;
		FD_ZERO(&fdset);
		FD_SET(m_Handle, &fdset);

		// Select from the set
		if (select(static_cast<int>(m_Handle)+1, NULL, &fdset, NULL, &tv) > 0)
		{
			// Check if the address is valid.
			Address address = GetPeerAddress( );
			if( address == p_Address )
			{
				// The address is not 0, we successfully connected.
				SetBlocking( blocking );
				return true;
			}
		}

		DWORD lastError = GetLastError();

		// Failed to connect. Close the socket.
		Disconnect( );

		// Failed.
		return false;
	}
Ejemplo n.º 20
0
void
CProxySessionManager::ProcessNewConnection( SOCKET Server )
{
    CProxySession* pSession = NULL;
    SOCKET Client;
    
    // SOCKADDR_STORAGE from;
    // на Vista изменили размер SOCKADDR_STORAGE. теперь 128 байт.
    // на вс¤кий случай делаю 256 ( вдруг еще раз измен¤т !? )
    // P.S. pigs !!!
    union _MY_SOCKADDR_STORAGE {
        SOCKADDR_STORAGE ss;
        char reserved[256];
    } from;

    int fromlen = sizeof ( from );

    char    DrvBuffer[512];
    int     RetVal;

    Client = accept(Server, (struct sockaddr *)&from, &fromlen);

    if ( Client == INVALID_SOCKET )
    {
        KLSTD_TRACE1( KLMC_TRACELEVEL, "ProcessNewConnection: accept error = %d", WSAGetLastError() );        
        return;    
    }
    
    KLSTD_TRACE0( KLMC_TRACELEVEL, "ProcessNewConnection: connection accepted. create Session" );

    SetBlocking( Client, true );

    RetVal = recv ( Client, DrvBuffer, 500, 0 );

	char Prefix[16];
	memset( Prefix, '.', sizeof(Prefix) );
    memcpy( Prefix, DrvBuffer, 10 );
    Prefix[15] = 0;

    KLSTD_TRACE3 (KLMC_TRACELEVEL, "CProxySessionManager::Run => recv %d bytes from server [%s]. err = %d", 
        RetVal, GetBinBufferTraceStringShort((const BYTE *)Prefix, sizeof(Prefix)).c_str(), WSAGetLastError() );

	if (RetVal == 0 || RetVal == INVALID_SOCKET)
	{
		// CLOSESOCKET(Client);
        closesocket( Client );
		return;
	}
    
    // обычный редирект через KAVSEND. ќставлено на вс¤ких случай, если не смогли переключитьс¤ на новую схему.
    if ( 0 == memcmp( DrvBuffer, KAVSEND_COMMAND, strlen( KAVSEND_COMMAND ) ) ) 
    {   
        KLSTD_TRACE0 (KLMC_TRACELEVEL, "CProxySessionManager::Run => KAVSEND" );

        pSession = new CProxySession(m_hParent, this, m_hStopEvent );

        if ( pSession )
        {
            KLSTD_TRACE1 (KLMC_TRACELEVEL, "CProxySessionManager::Run => KAVSEND create session(%p)", pSession );
            // тут клиентский сокет
            pSession->m_Flags |= FPS_GOT_KAVSEND;
            pSession->m_AcceptedSock = Client;
            pSession->ParseKavsendBuffer( DrvBuffer, RetVal );

            pSession->StartProtocollers();

            m_SessionList.push_back(pSession);  //ƒобавим в список запущенную сессию            
            if ( !pSession->StartClient() )
            {
                KLSTD_TRACE0 (KLMC_TRACELEVEL, "CProxySessionManager::Run => Unable to start thread after KAVSEND");
                AddClient( pSession );
            }
        }
        return;
    }

    // редирект по новой схеме KAVSVC
    if ( 0 == memcmp( DrvBuffer, KAVSVC_COMMAND, strlen( KAVSVC_COMMAND ) ))
    {
        // сервисное соединение. “ут должны указыватьс¤ параметры сервера,
        // куда выполн¤ем соединение. ѕрокси должна соединитьс¤ туда и 
        // создать ID сессии.
        pSession = new CProxySession(m_hParent, this, m_hStopEvent );

        KLSTD_TRACE1 (KLMC_TRACELEVEL, "CProxySessionManager::Run => KAVSVC. session = %p", pSession );

        if ( pSession )
        {
            pSession->m_AcceptedSock = Client; 
            pSession->m_Flags |= FPS_GOT_KAVSVC;
            pSession->ParseKavsvcBuffer( DrvBuffer, RetVal );
            
            m_SessionList.push_back(pSession); //ƒобавим в список запущенную сессию            
            if ( !pSession->StartClient() )
            {
                KLSTD_TRACE0 (KLMC_TRACELEVEL, "CProxySessionManager::Run => Unable to start thread after KAVSVC");
                AddClient( pSession );
            }
        }

        return;
    }

    // продолжение редиректа по новой схеме. ћы законнектились на сервер.
    // “еперь нужно найти сессию с установленным серверным соединением по указанному ID
    // !! TODO : можно избежать лишнего запуска потока. дл¤ этого нужно засинхронизировать
    //           уже работающий поток с серверным соединением с текущим потоком.
    if ( 0 == memcmp( DrvBuffer, KAVCONN_ID, strlen( KAVCONN_ID ) ) )
    {
        __int64 ID = *(__int64*) ( (PCHAR)DrvBuffer + 10 );

        KLSTD_TRACE1 (KLMC_TRACELEVEL, "CProxySessionManager::Run => KAVCONN_ID 0x%I64x", ID );

        if ( pSession  = FindSessionByID( ID ) )
        {
            KLSTD_TRACE1 (KLMC_TRACELEVEL, "CProxySessionManager::Run => Session %p found by KAVCONN_ID", pSession );
            // тут клиентский сокет
            
            pSession->m_client.AssignSocket( Client );
            pSession->m_client.PrepareSocket();

            GetLocalName( pSession->m_client.Socket(), pSession->m_Localhost, sizeof ( pSession->m_Localhost ) );

            pSession->m_Flags |= FPS_GOT_KAVCONN_ID | FPS_ESTABLISHED | FPS_CLIENT_CONNECTED;
            
            pSession->StartProtocollers();

            // запускаем поток сессии
            if ( !pSession->StartClient() )
            {
                KLSTD_TRACE0 (KLMC_TRACELEVEL, "CProxySessionManager::Run => Unable to start thread after KAVCONN_ID");
                AddClient( pSession );
            }
        }
        else
        {
            KLSTD_TRACE0 (KLMC_TRACELEVEL, "CProxySessionManager::Run => Session NOT found by KAVCONN_ID" );
        }

        return;
    }
}
Ejemplo n.º 21
0
void sfTcpSocket_SetBlocking(sfTcpSocket* socket, sfBool blocking)
{
    CSFML_CALL(socket, SetBlocking(blocking == sfTrue));
}
Ejemplo n.º 22
0
ProtoChannel::ProtoChannel()
 : listener(NULL), notifier(NULL), notify_flags(0), blocking_status(true),
#ifdef WIN32
   input_handle(INVALID_HANDLE), input_ready(false), 
   output_handle(INVALID_HANDLE), output_ready(false) 
#else
   descriptor(INVALID_HANDLE)
#endif // if/else WIN32/UNIX
{
    
}

ProtoChannel::~ProtoChannel()
{
    if (notifier) SetNotifier(NULL);
    if (listener)
    {
        delete listener;
        listener = NULL;  
    }
}


bool ProtoChannel::SetNotifier(ProtoChannel::Notifier* theNotifier)
{
    if (notifier != theNotifier)
    {
        if (IsOpen())
        {
            // 1) Detach old notifier, if any
            if (notifier)
            {
                notifier->UpdateChannelNotification(*this, 0);
                if (!theNotifier)
                {
                    // Reset channel to "blocking"
                    if(!SetBlocking(true))
                        PLOG(PL_ERROR, "ProtoChannel::SetNotifier() SetBlocking(true) error\n", GetErrorString());
                }
            }
            else
            {
                // Set channel to "non-blocking"
                if(!SetBlocking(false))
                {
                    PLOG(PL_ERROR, "ProtoChannel::SetNotifier() SetBlocking(false) error\n", GetErrorString());
                    return false;
                }
            }   
            // 2) Set and update new notifier (if applicable)
            notifier = theNotifier;
            if (!UpdateNotification())
            {
                notifier = NULL;  
                return false;
            } 
        }
        else
        {
            notifier = theNotifier;
        }
    }
    return true;
}  // end ProtoChannel::SetNotifier()


bool ProtoChannel::UpdateNotification()
{
    if (notifier)
    {
        if (IsOpen() && !SetBlocking(false))
        {
            PLOG(PL_ERROR, "ProtoChannel::UpdateNotification() SetBlocking() error\n");
            return false;  
        }
        return notifier->UpdateChannelNotification(*this, notify_flags);
    }
    return true;
}  // end ProtoChannel::UpdateNotification()

bool ProtoChannel::SetBlocking(bool blocking)
{
#ifdef UNIX
    if (IsOpen() && (blocking_status != blocking))
    {
        if (blocking)
        {
            if(-1 == fcntl(descriptor, F_SETFL, fcntl(descriptor, F_GETFL, 0) & ~O_NONBLOCK))
            {
                PLOG(PL_ERROR, "ProtoChannel::SetBlocking() fcntl(F_SETFL(~O_NONBLOCK)) error: %s\n", GetErrorString());
                return false;
            }
        }
        else
        {
            if(-1 == fcntl(descriptor, F_SETFL, fcntl(descriptor, F_GETFL, 0) | O_NONBLOCK))
            {
                PLOG(PL_ERROR, "ProtoChannel::SetBlocking() fcntl(F_SETFL(O_NONBLOCK)) error: %s\n", GetErrorString());
                return false;
            }
        }
        blocking_status = blocking;
    }
#endif // UNIX
    return true;  //Note: taken care automatically under Win32 by WSAAsyncSelect(), etc
}  // end ProtoChannel::SetBlocking(bool blocking)