示例#1
0
void Gosu::MessageSocket::update()
{
    std::vector<char> buffer(maxMessageSize());

    sockaddr_in addr;
    socklen_t size = sizeof addr;

    for (;;)
    {
        int received = ::recvfrom(pimpl->socket.handle(), &buffer.front(),
            buffer.size(), 0, reinterpret_cast<sockaddr*>(&addr),
            &size);

        if (received != SOCKET_ERROR && onReceive)
        {
            onReceive(ntohl(addr.sin_addr.s_addr),
                ntohs(addr.sin_port), &buffer.front(), received);
        }
        else switch (lastSocketError())
        {
            // Ignore some of the errors.
            case GOSU_SOCK_ERR(EWOULDBLOCK):
            case GOSU_SOCK_ERR(ENETDOWN):
            case GOSU_SOCK_ERR(ENETRESET):
            case GOSU_SOCK_ERR(ETIMEDOUT):
            case GOSU_SOCK_ERR(ECONNRESET):
                return;

            // Everything else is unexpected.
            default:
                throwLastSocketError();
        }
    }
}
示例#2
0
void Gosu::CommSocket::update()
{
    sendPendingData();

    if (!connected())
        return;

    for (;;)
    {
        char buffer[1024];
        int received = ::recv(pimpl->socket.handle(), buffer, sizeof buffer, 0);

        if (received > 0 && received <= static_cast<int>(sizeof buffer))
        {
            // Data arrived and fit into the buffer.
            pimpl->appendBuffer(buffer, received, onReceive);
        }
        else if (received == 0)
        {
            // The other side has gracefully closed the connection.
            disconnect();
            return;
        }
        else if (received == SOCKET_ERROR)
        {
            switch (lastSocketError())
            {
                // Arriving data didn't fit into the buffer.
                case GOSU_SOCK_ERR(EMSGSIZE):
                    pimpl->appendBuffer(buffer, sizeof buffer, onReceive);
                    break;

                // There simply was no data.
                case GOSU_SOCK_ERR(EWOULDBLOCK):
                    return;

                // Connection was reset or is invalid.
                case GOSU_SOCK_ERR(ENETDOWN):
                case GOSU_SOCK_ERR(ENOTCONN):
                case GOSU_SOCK_ERR(ENETRESET):
                case GOSU_SOCK_ERR(ECONNABORTED):
                case GOSU_SOCK_ERR(ETIMEDOUT):
                case GOSU_SOCK_ERR(ECONNRESET):
				#ifndef GOSU_IS_WIN
				// UNIX specific, rare error
                case GOSU_SOCK_ERR(EPIPE):
				#endif
                    disconnect();
                    return;

                // Everything else is unexpected.
                default:
                    throwLastSocketError();
            }
        }
        else assert(false);
    }
}
示例#3
0
void Gosu::CommSocket::sendPendingData()
{
    if (pendingBytes() == 0 || !connected())
        return;

    int sent = ::send(pimpl->socket.handle(), &pimpl->outbox.front(),
        pendingBytes(), 0);

    if (sent >= 0)
    {
        // Remove sent data from the outbox.
        if (sent >= static_cast<int>(pendingBytes()))
            pimpl->outbox.clear();
        else
            pimpl->outbox.erase(pimpl->outbox.begin(),
                pimpl->outbox.begin() + sent);
    }
    else
    {
        switch (lastSocketError())
        {
            // These error codes basically mean "try again later".
            case GOSU_SOCK_ERR(ENOBUFS):
            case GOSU_SOCK_ERR(EWOULDBLOCK):
            case GOSU_SOCK_ERR(EHOSTUNREACH):
                break;

            // And these tell us we're disconnected.
            case GOSU_SOCK_ERR(ENETDOWN):
            case GOSU_SOCK_ERR(ENETRESET):
            case GOSU_SOCK_ERR(ENOTCONN):
            case GOSU_SOCK_ERR(ECONNABORTED):
            case GOSU_SOCK_ERR(ECONNRESET):
            case GOSU_SOCK_ERR(ETIMEDOUT):
			#ifndef GOSU_IS_WIN
			// UNIX-specific, rare error
            case GOSU_SOCK_ERR(EPIPE):
			#endif
                disconnect();
                break;

            // Everything else is unexpected.
            default:
                throwLastSocketError();
        }
    }
}
示例#4
0
 T socketCheck(T retVal)
 {
     if (retVal == SOCKET_ERROR &&
         lastSocketError() != GOSU_SOCK_ERR(EWOULDBLOCK))
     {
         throwLastSocketError();
     }
     
     return retVal;
 }
示例#5
0
void Gosu::MessageSocket::send(SocketAddress address, SocketPort port,
    const void* buffer, std::size_t size)
{
    sockaddr_in addr;
    std::memset(&addr, 0, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(address);
    addr.sin_port = htons(port);

    int sent = ::sendto(pimpl->socket.handle(),
        reinterpret_cast<const char*>(buffer), size, 0,
        reinterpret_cast<sockaddr*>(&addr), sizeof addr);

    if (sent == static_cast<int>(size))
        return; // Yay, did it!

    assert(sent == SOCKET_ERROR); // Don't expect partial sends.

    switch (lastSocketError())
    {
        // Just ignore a lot of errors... this is UDP, right?
        case GOSU_SOCK_ERR(ENETDOWN):
        case GOSU_SOCK_ERR(ENETRESET):
        case GOSU_SOCK_ERR(ENOBUFS):
        case GOSU_SOCK_ERR(EWOULDBLOCK):
        case GOSU_SOCK_ERR(EHOSTUNREACH):
        case GOSU_SOCK_ERR(ECONNABORTED):
        case GOSU_SOCK_ERR(ECONNRESET):
        case GOSU_SOCK_ERR(ENETUNREACH):
        case GOSU_SOCK_ERR(ETIMEDOUT):
            break;

        // Everything else means more than just another lost packet, though.
        default:
            throwLastSocketError();
    }
}