/* * DistributedEvents.cpp * * Copyright (C) 2017 by RStudio, Inc. * * Unless you have received this program directly from RStudio pursuant * to the terms of a commercial license agreement with RStudio, then * this program is licensed to you under the terms of version 3 of the * GNU Affero General Public License. This program is distributed WITHOUT * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. * */ #include #include #include #include #include using namespace rstudio::core; namespace rstudio { namespace core { namespace distributed_events { namespace { static DistributedEventAsyncHandler s_fireEventAsync; static DistributedEventSyncHandler s_fireEventSync; Error fireDistributedEventImpl(const std::string& requestBody, boost::function notification) { json::Value eventVal; // parse event value object from the request if (!json::parse(requestBody, &eventVal) || eventVal.type() != json::ObjectType) return Error(json::errc::ParseError, ERROR_LOCATION); // read the event from the object int eventType; std::string eventOrigin; json::Object eventData; Error error = json::readObject(eventVal.get_obj(), kDistEvtEventType, &eventType, kDistEvtEventData, &eventData, kDistEvtOrigin, &eventOrigin); if (error) return error; // fire to listeners if (notification) notification(DistributedEvent(static_cast(eventType), eventData, eventOrigin)); return Success(); } } // anonymous namespace Error fireDistributedEventAsync(boost::shared_ptr pConnection) { const http::Request& request = pConnection->request(); http::Response& response = pConnection->response(); if (s_fireEventAsync) { Error error = fireDistributedEventImpl(request.body(), boost::bind(s_fireEventAsync, _1, pConnection)); if (error) return error; } // acknowledge the event json::Object result; result["suceeded"] = true; std::ostringstream oss; json::write(result, oss); response.setStatusCode(http::status::Ok); response.setBody(oss.str()); pConnection->writeResponse(); return Success(); } Error fireDistributedEvent(const http::Request& request, http::Response* pResponse) { if (s_fireEventSync) { Error error = fireDistributedEventImpl(request.body(), s_fireEventSync); if (error) return error; } // acknowledge the event json::Object result; result["suceeded"] = true; std::ostringstream oss; json::write(result, oss); pResponse->setStatusCode(http::status::Ok); pResponse->setBody(oss.str()); return Success(); } Error emitDistributedEvent(const std::string& targetType, const std::string& target, const DistributedEvent& distEvt) { // construct the event to broadcast json::Object event; event[kDistEvtTargetType] = targetType; event[kDistEvtTarget] = target; event[kDistEvtEventType] = distEvt.type(); event[kDistEvtEventData] = distEvt.data(); event[kDistEvtOrigin] = distEvt.origin(); // and broadcast it! json::Value result; return socket_rpc::invokeRpc(FilePath(kServerRpcSocketPath), kDistributedEventsEndpoint, event, &result); } Error initializeAsync(DistributedEventAsyncHandler eventHandler) { s_fireEventAsync = eventHandler; return Success(); } Error initialize(DistributedEventSyncHandler eventHandler) { s_fireEventSync = eventHandler; return Success(); } } // distributed_events namespace } // core namespace } // rstudio namespace