예제 #1
0
void WebEventServiceImpl::shutdownImpl(Poco::SharedPtr<Poco::Net::WebSocket> pWS, Poco::UInt16 statusCode, const std::string& statusMessage, bool passive)
{
    //_pContext->logger().notice("Shutting down WebSocket.");
    try
    {
        pWS->shutdown(statusCode, statusMessage);
    }
    catch (Poco::Exception& exc)
    {
        _pContext->logger().notice("Error while shutting down WebSocket: " + exc.displayText());
        passive = true; // don't wait for client confirmation
    }
    if (!passive)
    {
        if (pWS->poll(Poco::Timespan(WEBEVENT_SHUTDOWN_TIMEOUT, 0), Poco::Net::Socket::SELECT_READ))
        {
            Poco::Buffer<char> buffer(4096);
            int flags;
            pWS->receiveFrame(buffer.begin(), buffer.size(), flags);
            if (flags & Poco::Net::WebSocket::FRAME_OP_CLOSE)
            {
                pWS->close();
                return;
            }
        }
        _pContext->logger().notice("Client failed to confirm shutdown.");
    }
    pWS->close();
}
예제 #2
0
void WebEventServiceImpl::receiveImpl(Poco::SharedPtr<Poco::Net::WebSocket> pWS)
{
    try
    {
        Poco::Buffer<char> buffer(4096);
        int flags;
        int n = pWS->receiveFrame(buffer.begin(), buffer.size(), flags);
        _pContext->logger().debug(Poco::format("Frame received (length=%d, flags=0x%x).", n, unsigned(flags)));

        if (flags & Poco::Net::WebSocket::FRAME_OP_PONG)
        {
            _pContext->logger().debug("Received unsolicited PONG frame - ignoring.");
            _mainQueue.enqueueNotification(new WatchSocketNotification(*this, *pWS));
            return;
        }

        if ((flags & Poco::Net::WebSocket::FRAME_OP_CLOSE) || n == 0)
        {
            removeSubscriber(pWS, true);
            return;
        }

        const char* it  = buffer.begin();
        const char* end = buffer.begin() + n;
        std::string verb;
        while (it != end && *it != ' ') verb += *it++;
        if (verb == SUBSCRIBE || verb == UNSUBSCRIBE || verb == NOTIFY)
        {
            while (it != end && *it == ' ') ++it;
            std::set<std::string> subjectNames;
            while (it != end && *it != ' ')
            {
                std::string subject;
                while (it != end && *it != ',' && *it != ' ') subject += *it++;
                if (it != end)
                {
                    subjectNames.insert(subject);
                    if (*it == ',') it++; // skip ','
                }
            }
            while (it != end && *it == ' ') ++it;
            std::string version;
            while (it != end && *it != '\r' && *it != '\n') version += *it++;
            if (it != end && *it == '\r') ++it;
            if (it != end && *it == '\n') ++it;
            if (version == VERSION)
            {
                if (verb == SUBSCRIBE)
                {
                    subscribe(pWS, subjectNames);
                }
                else if (verb == UNSUBSCRIBE)
                {
                    unsubscribe(pWS, subjectNames);
                }
                else if (verb == NOTIFY)
                {
                    std::string data;
                    while (it != end) data += *it++;
                    for (std::set<std::string>::const_iterator it = subjectNames.begin(); it != subjectNames.end(); ++it)
                    {
                        if (*it == SYSTEM_PING)
                        {
                            std::string pong(NOTIFY);
                            pong += ' ';
                            pong += SYSTEM_PONG;
                            pong += ' ';
                            pong += VERSION;
                            pong += "\r\n";
                            pong += data;
                            send(pWS, pong);
                        }
                        else
                        {
                            notify(*it, data);
                        }
                    }
                }
                _mainQueue.enqueueNotification(new WatchSocketNotification(*this, *pWS));
                return;
            }
        }
        _pContext->logger().notice("Client protocol violation. Closing WebSocket.");
    }
    catch (Poco::Exception& exc)
    {
        _pContext->logger().error("Error while receiving frame: " + exc.displayText());
    }
    removeSubscriber(pWS, false);
}