Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4792519

Browse files
committed
Merge branch 'master' into bugfix/terminal-misc
2 parents 0aff71f + de033d8 commit 4792519

File tree

7 files changed

+424
-3
lines changed

7 files changed

+424
-3
lines changed

src/cpp/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ if (UNIX)
240240

241241
if(RSTUDIO_SERVER)
242242
set(CORE_SOURCE_FILES ${CORE_SOURCE_FILES}
243+
DistributedEvents.cpp
244+
SocketRpc.cpp
243245
system/PosixCrypto.cpp
244246
system/Pam.cpp
245247
)

src/cpp/core/DistributedEvents.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* DistributedEvents.cpp
3+
*
4+
* Copyright (C) 2017 by RStudio, Inc.
5+
*
6+
* Unless you have received this program directly from RStudio pursuant
7+
* to the terms of a commercial license agreement with RStudio, then
8+
* this program is licensed to you under the terms of version 3 of the
9+
* GNU Affero General Public License. This program is distributed WITHOUT
10+
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11+
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12+
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13+
*
14+
*/
15+
16+
#include <core/Error.hpp>
17+
#include <core/json/JsonRpc.hpp>
18+
#include <core/r_util/RSessionContext.hpp>
19+
#include <core/SocketRpc.hpp>
20+
21+
#include <core/DistributedEvents.hpp>
22+
23+
using namespace rstudio::core;
24+
25+
namespace rstudio {
26+
namespace core {
27+
namespace distributed_events {
28+
29+
namespace {
30+
31+
static DistributedEventAsyncHandler s_fireEventAsync;
32+
static DistributedEventSyncHandler s_fireEventSync;
33+
34+
Error fireDistributedEventImpl(const std::string& requestBody,
35+
boost::function<void (const DistributedEvent&)> notification)
36+
{
37+
json::Value eventVal;
38+
39+
// parse event value object from the request
40+
if (!json::parse(requestBody, &eventVal) ||
41+
eventVal.type() != json::ObjectType)
42+
return Error(json::errc::ParseError, ERROR_LOCATION);
43+
44+
// read the event from the object
45+
int eventType;
46+
std::string eventOrigin;
47+
json::Object eventData;
48+
Error error = json::readObject(eventVal.get_obj(),
49+
kDistEvtEventType, &eventType,
50+
kDistEvtEventData, &eventData,
51+
kDistEvtOrigin, &eventOrigin);
52+
if (error)
53+
return error;
54+
55+
// fire to listeners
56+
if (notification)
57+
notification(DistributedEvent(static_cast<DistEvtType>(eventType), eventData, eventOrigin));
58+
59+
return Success();
60+
}
61+
62+
} // anonymous namespace
63+
64+
Error fireDistributedEventAsync(boost::shared_ptr<http::AsyncConnection> pConnection)
65+
{
66+
const http::Request& request = pConnection->request();
67+
http::Response& response = pConnection->response();
68+
69+
if (s_fireEventAsync)
70+
{
71+
Error error = fireDistributedEventImpl(request.body(), boost::bind(s_fireEventAsync,
72+
_1,
73+
pConnection));
74+
if (error)
75+
return error;
76+
}
77+
78+
// acknowledge the event
79+
json::Object result;
80+
result["suceeded"] = true;
81+
std::ostringstream oss;
82+
json::write(result, oss);
83+
84+
response.setStatusCode(http::status::Ok);
85+
response.setBody(oss.str());
86+
pConnection->writeResponse();
87+
88+
return Success();
89+
}
90+
91+
Error fireDistributedEvent(const http::Request& request,
92+
http::Response* pResponse)
93+
{
94+
if (s_fireEventSync)
95+
{
96+
Error error = fireDistributedEventImpl(request.body(), s_fireEventSync);
97+
if (error)
98+
return error;
99+
}
100+
101+
// acknowledge the event
102+
json::Object result;
103+
result["suceeded"] = true;
104+
std::ostringstream oss;
105+
json::write(result, oss);
106+
107+
pResponse->setStatusCode(http::status::Ok);
108+
pResponse->setBody(oss.str());
109+
110+
return Success();
111+
}
112+
113+
Error emitDistributedEvent(const std::string& targetType,
114+
const std::string& target,
115+
const DistributedEvent& distEvt)
116+
{
117+
// construct the event to broadcast
118+
json::Object event;
119+
event[kDistEvtTargetType] = targetType;
120+
event[kDistEvtTarget] = target;
121+
event[kDistEvtEventType] = distEvt.type();
122+
event[kDistEvtEventData] = distEvt.data();
123+
event[kDistEvtOrigin] = distEvt.origin();
124+
125+
// and broadcast it!
126+
json::Value result;
127+
128+
return socket_rpc::invokeRpc(FilePath(kServerRpcSocketPath), kDistributedEventsEndpoint, event, &result);
129+
}
130+
131+
Error initializeAsync(DistributedEventAsyncHandler eventHandler)
132+
{
133+
s_fireEventAsync = eventHandler;
134+
return Success();
135+
}
136+
137+
Error initialize(DistributedEventSyncHandler eventHandler)
138+
{
139+
s_fireEventSync = eventHandler;
140+
return Success();
141+
}
142+
143+
} // distributed_events namespace
144+
} // core namespace
145+
} // rstudio namespace

src/cpp/core/SocketRpc.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* SocketRpc.cpp
3+
*
4+
* Copyright (C) 2017 by RStudio, Inc.
5+
*
6+
* Unless you have received this program directly from RStudio pursuant
7+
* to the terms of a commercial license agreement with RStudio, then
8+
* this program is licensed to you under the terms of version 3 of the
9+
* GNU Affero General Public License. This program is distributed WITHOUT
10+
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11+
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12+
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13+
*
14+
*/
15+
16+
#include <core/Error.hpp>
17+
#include <core/json/Json.hpp>
18+
#include <core/json/JsonRpc.hpp>
19+
#include <core/http/LocalStreamBlockingClient.hpp>
20+
#include <core/SafeConvert.hpp>
21+
#include <core/SocketRpc.hpp>
22+
#include <core/system/Environment.hpp>
23+
24+
namespace rstudio {
25+
namespace core {
26+
namespace socket_rpc {
27+
28+
namespace {
29+
30+
std::string s_sessionSharedSecret;
31+
32+
} // anonymous namespace
33+
34+
35+
Error invokeRpc(const FilePath& socketPath,
36+
const std::string& endpoint,
37+
const json::Object& request,
38+
json::Value *pResult)
39+
{
40+
// serialize the payload
41+
std::ostringstream oss;
42+
core::json::write(request, oss);
43+
44+
// form the request
45+
core::http::Request req;
46+
req.setMethod("POST");
47+
req.setUri(endpoint);
48+
req.setHeader("Connection", "close");
49+
req.setHeader(kServerRpcSecretHeader, s_sessionSharedSecret);
50+
req.setBody(oss.str());
51+
52+
core::http::Response resp;
53+
core::http::sendRequest(socketPath, req, &resp);
54+
55+
if (resp.statusCode() != core::http::status::Ok)
56+
{
57+
LOG_WARNING_MESSAGE("Server RPC failed: " + endpoint +
58+
safe_convert::numberToString(resp.statusCode()) +
59+
"\n" + resp.statusMessage());
60+
return Error(json::errc::ExecutionError, ERROR_LOCATION);
61+
}
62+
else if (resp.body().empty())
63+
{
64+
// empty value from server doesn't imply failure, just that there's
65+
// nothing for us to read
66+
*pResult = json::Value();
67+
return Success();
68+
}
69+
else if (!json::parse(resp.body(), pResult))
70+
{
71+
LOG_WARNING_MESSAGE("Received unparseable result from rserver RPC:\n" +
72+
endpoint + "\n" +
73+
resp.body());
74+
return Error(json::errc::ParseError, ERROR_LOCATION);
75+
}
76+
77+
return Success();
78+
}
79+
80+
Error initialize()
81+
{
82+
// extract shared secret
83+
s_sessionSharedSecret = core::system::getenv(kServerRpcSecretEnvVar);
84+
core::system::unsetenv(kServerRpcSecretEnvVar);
85+
86+
return Success();
87+
}
88+
89+
} // namespace socket_rpc
90+
} // namespace core
91+
} // namespace rstudio
92+
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* DistributedEvents.hpp
3+
*
4+
* Copyright (C) 2017 by RStudio, Inc.
5+
*
6+
* Unless you have received this program directly from RStudio pursuant
7+
* to the terms of a commercial license agreement with RStudio, then
8+
* this program is licensed to you under the terms of version 3 of the
9+
* GNU Affero General Public License. This program is distributed WITHOUT
10+
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11+
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12+
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13+
*
14+
*/
15+
16+
#ifndef DISTRIBUTED_EVENTS_HPP
17+
#define DISTRIBUTED_EVENTS_HPP
18+
19+
#include <core/Exec.hpp>
20+
#include <core/json/Json.hpp>
21+
#include <core/http/AsyncConnection.hpp>
22+
#include <core/http/Request.hpp>
23+
#include <core/http/Response.hpp>
24+
25+
#define kDistributedEventsEndpoint "/distributed_events"
26+
#define kDistEvtSecureCookie "event_secure_cookie"
27+
28+
#define kDistEvtTargetType "target_type"
29+
#define kDistEvtTarget "target"
30+
#define kDistEvtEventType "event_type"
31+
#define kDistEvtEventData "event_data"
32+
#define kDistEvtOrigin "origin_session"
33+
34+
#define kDistEvtTargetProject "project"
35+
#define kDistEvtTargetSession "session"
36+
#define kDistEvtTargetWorkspaces "workspaces"
37+
38+
namespace rstudio {
39+
namespace core {
40+
41+
class Error;
42+
43+
enum DistEvtType
44+
{
45+
DistEvtUserJoined,
46+
DistEvtUserLeft,
47+
DistEvtUserChanged,
48+
DistEvtFollowStarted,
49+
DistEvtFollowEnded,
50+
DistEvtActiveFileChanged,
51+
DistEvtActiveFileMatched,
52+
DistEvtCollabStartRequested,
53+
DistEvtCollabStarted,
54+
DistEvtCollabEnded,
55+
DistEvtProjectACLChanged,
56+
DistEvtFileSaved,
57+
DistEvtNotebookChunkOutput,
58+
DistEvtNotebookConsoleOutput,
59+
DistEvtShutdownSessions,
60+
DistEvtKillSessions
61+
};
62+
63+
class DistributedEvent
64+
{
65+
public:
66+
DistributedEvent(DistEvtType type, const core::json::Object& data):
67+
type_(type),
68+
data_(data)
69+
{
70+
}
71+
72+
DistributedEvent(DistEvtType type, const core::json::Object& data,
73+
const std::string& origin):
74+
type_(type),
75+
data_(data),
76+
origin_(origin)
77+
{
78+
}
79+
80+
DistEvtType type() const
81+
{
82+
return type_;
83+
}
84+
85+
const core::json::Object& data() const
86+
{
87+
return data_;
88+
}
89+
90+
std::string origin() const
91+
{
92+
return origin_;
93+
}
94+
95+
private:
96+
DistEvtType type_;
97+
core::json::Object data_;
98+
std::string origin_;
99+
};
100+
101+
typedef boost::function<void (const DistributedEvent&, boost::shared_ptr<http::AsyncConnection>)> DistributedEventAsyncHandler;
102+
typedef boost::function<void (const DistributedEvent&)> DistributedEventSyncHandler;
103+
104+
namespace distributed_events {
105+
106+
// emit (broadcast) a distributed event
107+
Error emitDistributedEvent(const std::string& targetType,
108+
const std::string& target,
109+
const DistributedEvent& distEvt);
110+
111+
// receives a distributed session event from the server and broadcasts it
112+
// asynchronous mode
113+
Error fireDistributedEventAsync(boost::shared_ptr<http::AsyncConnection> pConnection);
114+
115+
// receives a distributed session event from the server and broadcasts it
116+
// synchronous mode
117+
Error fireDistributedEvent(const http::Request& request,
118+
http::Response* pResponse);
119+
120+
// initialize in asynchronous mode
121+
// pair this with calls to fireDistributedEventAsync
122+
Error initializeAsync(DistributedEventAsyncHandler eventHandler);
123+
124+
125+
// initialize in synchronous mode
126+
// pair this with calls to fireDistributedEvent
127+
Error initialize(DistributedEventSyncHandler eventHandler);
128+
129+
} // namespace distributed_events
130+
} // namespace core
131+
} // namespace rstudio
132+
133+
#endif // DISTRIBUTED_EVENTS_HPP
134+
135+

0 commit comments

Comments
 (0)