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(); }
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); }