Esempio n. 1
0
inline bool
BSDTCPConnection::write (const Byte* bytes, Size size)
{
    assert(0 != bytes);
    assert(0 < size);

    do
    {
        ScopedProfiledTask _(ProfilerTask_SocketWriteLoop);
    
        report_false_if("connection: write: disconnecting", disconnecting);

        const int status = select_single_write(socket.fd, 100);

        if (0 == status)
        {
            continue; // Cannot write just yet.
        }
        else if (status < 0)
        {
            uplink_log_error("connection: write: select failed: %s", strerror(errno));

            return false;
        }

        const ssize_t count = ::write(socket.fd, bytes, size);

        if (0 == count)
        {
            uplink_log_error("connection: write failed: EOF");

            return false;
        }
        else if (count < 0)
        {
            uplink_log_error("connection: write failed: %s", strerror(errno));

            return false;
        }

        size  -= count;
        bytes += count;
    }
    while (0 < size);

    return true;
}
Esempio n. 2
0
inline bool
BSDTCPConnection::read (Byte* bytes, Size size)
{
    assert(0 != bytes);
    assert(0 < size);

    do
    {
        ScopedProfiledTask _(ProfilerTask_SocketReadLoop);
    
        report_false_if("connection: read: disconnecting", disconnecting);

        const int status = select_single_read(socket.fd, 100);

        if (0 == status)
        {
            continue; // Nothing to read, yet.
        }
        else if (status < 0)
        {
            uplink_log_error("connection: read: select: %s", strerror(errno));
            return false;
        }

        const ssize_t count = ::read(socket.fd, bytes, size);

        if (0 == count)
        {
            uplink_log_error("connection: read: EOF");
            return false;
        }
        else if (count < 0)
        {
            uplink_log_error("connection: read: %s", strerror(errno));
            return false;
        }

        size  -= count;
        bytes += count;
    }
    while (0 < size);

    return true;
}
Esempio n. 3
0
    Impl(That* that)
    : that(that)
    , mainWindow(0)
    , sharingWindow(0)
    {
        if (!glfwInit())
        {
            uplink_log_error("Failed to initialize GLFW.");
            abort();
        }

        mainWindow = glfwCreateWindow(
            initialWindowWidth,
            initialWindowHeight,
            "Uplink",
            0,
            0
        );

        // Create a sharing context with a hidden window in order to allow other threads to upload data independently from the rendering thread.
        sharingWindow = glfwCreateWindow(
            1,
            1,
            "",
            0,
            mainWindow
        );
        glfwHideWindow(sharingWindow);

        glfwSetWindowUserPointer(mainWindow, this);

        glfwSetWindowSizeCallback(mainWindow, resize_callback);
        glfwSetKeyCallback(mainWindow, key_callback);
        glfwSwapInterval(1);
        glfwSetTime(0.0);

        glfwMakeContextCurrent(mainWindow);
     
        glGenTextures(1, &colorTextureId);
        glGenTextures(1, &depthTextureId);
     
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glEnable(GL_TEXTURE_2D);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glClearColor(0., 0., 0., 0.);

        glfwMakeContextCurrent(0);
    }
Esempio n. 4
0
inline TCPConnection*
TCPConnection_connect (CString host, uint16 port)
{
    const int fd = socket(AF_INET, SOCK_STREAM, 0);

    report_zero_if(ERROR_MESSAGE("socket"), fd == -1);

    // Make it so that we can early-return from this scope using one-liners.
    struct Cleanup
    {
        explicit Cleanup (int fd)
            : ok(false), fd(fd)
        {}

        ~Cleanup ()
        {
            return_if(ok);

            close(fd);
        }

        bool ok;
        int  fd;
    }
    cleanup(fd);

    // FIXME: Use the IPv6-compliant getaddrinfo.
    struct hostent* ip = ::gethostbyname(host);

    report_zero_if(ERROR_MESSAGE("gethostbyname"), ip == NULL);

    sockaddr_in address;
    address.sin_family = AF_INET;
    memcpy(&address.sin_addr, ip->h_addr_list[0], ip->h_length);
    address.sin_port = htons(port);

    {
        // Put the socket into non-blocking mode.

        int flags = fcntl(fd, F_GETFL, 0);
        int status = fcntl(fd, F_SETFL, flags | O_NONBLOCK);

        report_zero_if(ERROR_MESSAGE("fcntl"), status < 0);
    }

    {
        // Perform the non-blocking connection dance.
    
        int status = 0;
        do
        {
            status = ::connect(fd, (sockaddr*) &address, sizeof(address));
            
        }
        while (-1 == status && EINTR == errno); // In the extreme case where connect got interrupted by a signal.

        if (0 != status) // TCPConnection did not immediately succeed.
        {
            switch (errno) // Investigate the error, and take action.
            {
                case EINPROGRESS: // The connection is in progress.
                {
                    static const int connectionTimeoutInMilliseconds = 500;
                
                    // Poll the socket for writing, with a timeout.
                    const int ret = select_single_write(fd, connectionTimeoutInMilliseconds);

                    // Select might actually have returned EINPROGRESS, here.
                    // Currently, we behave as if the connection failed when it times out.
                    // FIXME: Introduce an asynchronous callback connection mechanism in parallel to this blocking one.

                    // Abort if select failed.
                    report_zero_unless(ERROR_MESSAGE("select"), 0 < ret);
                    
                    // Also abort if select returned with a descriptor not ready for writing.
                    report_zero_if("Connection timed out.", 0 == ret);

                    // Make sure that the connection is error-free.
                    int       err = 0;
                    socklen_t len = sizeof(int);
                    report_zero_unless(ERROR_MESSAGE("getsockopt"), 0 == getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len));
                    report_zero_unless(formatted("connect: %s", strerror(err)).get(), 0 == err);

                    break; // The connection is now established.
                }
                
                default: // The connection failed for other reasons.
                {
                    uplink_log_error(ERROR_MESSAGE("connect"));

                    return 0;
                }
            }
        }
    }

    {
        // Put the socket back into blocking mode.
        
        int flags = fcntl(fd, F_GETFL, 0);
        int status = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);

        report_zero_if(ERROR_MESSAGE("fcntl"), status < 0);
    }

    cleanup.ok = true;

    return TCPConnection_create(fd);
}