History

Add support for sending requests to entity script server

Ryan Huffman committed 9 years ago

Commit 8137c591 parent 340eeb96 files · +261 −3Browse files

Showing the changes to libraries/networking/src/EntityScriptClient.cpp (1 of 6 files). Show all

Unified · Split

libraries/networking/src/EntityScriptClient.cpp+153−0
@@ -0,0 +1,153 @@
1+#include "EntityScriptClient.h"
2+#include "NodeList.h"
3+#include "NetworkLogging.h"
4+
5+#include <QThread>
6+
7+MessageID EntityScriptClient::_currentID = 0;
8+
9+GetScriptStatusRequest::GetScriptStatusRequest(QUuid entityID) : _entityID(entityID) {
10+}
11+
12+GetScriptStatusRequest::~GetScriptStatusRequest() {
13+
14+}
15+
16+void GetScriptStatusRequest::start() {
17+ auto client = DependencyManager::get<EntityScriptClient>();
18+ qDebug() << "Sending script status request";
19+ client->getEntityServerScriptStatus(_entityID, [this](bool responseReceived) {
20+ qDebug() << "Received script status request";
21+ emit finished(this);
22+ });
23+}
24+
25+EntityScriptClient::EntityScriptClient() {
26+ setCustomDeleter([](Dependency* dependency){
27+ static_cast<EntityScriptClient*>(dependency)->deleteLater();
28+ });
29+
30+ auto nodeList = DependencyManager::get<NodeList>();
31+ auto& packetReceiver = nodeList->getPacketReceiver();
32+
33+ packetReceiver.registerListener(PacketType::EntityScriptGetStatusReply, this, "handleGetScriptStatusReply");
34+
35+ connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptClient::handleNodeKilled);
36+ connect(nodeList.data(), &LimitedNodeList::clientConnectionToNodeReset,
37+ this, &EntityScriptClient::handleNodeClientConnectionReset);
38+}
39+
40+GetScriptStatusRequest* EntityScriptClient::createScriptStatusRequest(QUuid entityID) {
41+ auto request = new GetScriptStatusRequest(entityID);
42+
43+ request->moveToThread(thread());
44+
45+ return request;
46+}
47+
48+bool EntityScriptClient::reloadServerScript(QUuid entityID) {
49+ // Send packet to entity script server
50+ auto nodeList = DependencyManager::get<NodeList>();
51+ SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer);
52+
53+ if (entityScriptServer) {
54+ auto id = entityID.toRfc4122();
55+ auto payloadSize = id.size();
56+ auto packet = NLPacket::create(PacketType::ReloadEntityServerScript, payloadSize, true);
57+
58+ packet->write(id);
59+
60+ if (nodeList->sendPacket(std::move(packet), *entityScriptServer) != -1) {
61+ return true;
62+ }
63+ }
64+
65+ return false;
66+}
67+
68+MessageID EntityScriptClient::getEntityServerScriptStatus(QUuid entityID, GetScriptStatusCallback callback) {
69+ auto nodeList = DependencyManager::get<NodeList>();
70+ SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer);
71+
72+ if (entityScriptServer) {
73+ auto packetList = NLPacketList::create(PacketType::EntityScriptGetStatus, QByteArray(), true, true);
74+
75+ auto messageID = ++_currentID;
76+ packetList->writePrimitive(messageID);
77+
78+ packetList->write(entityID.toRfc4122());
79+
80+ if (nodeList->sendPacketList(std::move(packetList), *entityScriptServer) != -1) {
81+ _pendingEntityScriptStatusRequests[entityScriptServer][messageID] = callback;
82+
83+ return messageID;
84+ }
85+ }
86+
87+ callback(false);
88+ return INVALID_MESSAGE_ID;
89+}
90+
91+void EntityScriptClient::handleGetScriptStatusReply(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
92+ Q_ASSERT(QThread::currentThread() == thread());
93+
94+ MessageID messageID;
95+ message->readPrimitive(&messageID);
96+
97+ auto status = message->readString();
98+
99+ // Check if we have any pending requests for this node
100+ auto messageMapIt = _pendingEntityScriptStatusRequests.find(senderNode);
101+ if (messageMapIt != _pendingEntityScriptStatusRequests.end()) {
102+
103+ // Found the node, get the MessageID -> Callback map
104+ auto& messageCallbackMap = messageMapIt->second;
105+
106+ // Check if we have this pending request
107+ auto requestIt = messageCallbackMap.find(messageID);
108+ if (requestIt != messageCallbackMap.end()) {
109+ auto callback = requestIt->second;
110+ callback(true);
111+ messageCallbackMap.erase(requestIt);
112+ }
113+
114+ // Although the messageCallbackMap may now be empty, we won't delete the node until we have disconnected from
115+ // it to avoid constantly creating/deleting the map on subsequent requests.
116+ }
117+}
118+
119+void EntityScriptClient::handleNodeKilled(SharedNodePointer node) {
120+ Q_ASSERT(QThread::currentThread() == thread());
121+
122+ if (node->getType() != NodeType::EntityScriptServer) {
123+ return;
124+ }
125+
126+ forceFailureOfPendingRequests(node);
127+}
128+
129+void EntityScriptClient::handleNodeClientConnectionReset(SharedNodePointer node) {
130+ // a client connection to a Node was reset
131+ // if it was an EntityScriptServer we need to cause anything pending to fail so it is re-attempted
132+
133+ if (node->getType() != NodeType::EntityScriptServer) {
134+ return;
135+ }
136+
137+ //qCDebug(entity_script_client) << "EntityScriptClient detected client connection reset handshake with Asset Server - failing any pending requests";
138+
139+ forceFailureOfPendingRequests(node);
140+}
141+
142+void EntityScriptClient::forceFailureOfPendingRequests(SharedNodePointer node) {
143+
144+ {
145+ auto messageMapIt = _pendingEntityScriptStatusRequests.find(node);
146+ if (messageMapIt != _pendingEntityScriptStatusRequests.end()) {
147+ for (const auto& value : messageMapIt->second) {
148+ value.second(false);
149+ }
150+ messageMapIt->second.clear();
151+ }
152+ }
153+}