bool PerformOp(Connection &con, string client, string file, vector<string> slaves) { if (slaves.empty()) { return false; } // Send message to master slave(first) to prepare for client operation Message slave_prep(kSlavePrepareOp, SAFE_MESS); slave_prep.SetContent(SlaveOp{file, client, "", slaves}); if (!con.SendMessage(slave_prep, slaves.front())) { cout << "Failed to prepare slaves for operation." << endl; return false; } // Wait slave to confirm operation and to inform the handler bool confirmed = false; string op_handler; Message tmp(0,0); if (con.GetMessage(kSlaveConfirmOp, kCreateTimeout, tmp)) { SlaveOp cop; tmp.GetContent(cop); confirmed = cop.client == client && cop.file_name == file; op_handler = tmp.sender(); } // Slaves are not responding to prepare op if (!confirmed) { cout << "Storage slaves did not respond." << endl; return false; } Message client_prep(kClientPrepareOp, SAFE_MESS); client_prep.SetContent(ClientOp{file, op_handler}); if (!con.SendMessage(client_prep, client)) { cout << "Failed to prepare client for operation." << endl; return false; } // Wait slave to confirm operation and to inform the handler confirmed = false; if (con.GetMessage(kFileOpResult, kCreateTimeout, tmp)) { ResultFileOp result; tmp.GetContent(result); confirmed = result.ok; } // Slave did not confirm if (!confirmed) { cout << "Storage slaves did not confirm operation." << endl; } return confirmed; }
void DOTHeal::HandleGetLc(StringHash eventType, VariantMap& eventData) { Node* sceneNode = (Node*)(eventData[GetLc::P_NODE].GetPtr()); if (sceneNode == node_) { if (!targets_.Size()) { return; } Connection* conn = (Connection*)(eventData[GetLc::P_CONNECTION].GetPtr()); lc_->GetLagTime(conn); for (int x = 0; x < targets_.Size(); x++) { float timeRamp = targets_[x]->elapsedTime_ + lc_->lagTime_; lc_->msg_.Clear(); lc_->msg_.WriteInt(lc_->clientID_); lc_->msg_.WriteString("DOTHeal"); lc_->msg_.WriteInt(targets_[x]->clientID_); lc_->msg_.WriteFloat(timeRamp); conn->SendMessage(MSG_LCMSG, true, true, lc_->msg_); } } }
void Server::HandleClientConnect(StringHash eventType, VariantMap& eventData) { //LOGERRORF("client connected to server"); using namespace NetworkMessage; Connection* sender = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr()); ClientData* newClient = new ClientData(clientIDCount_, sender, false); //Synchronize client data. for (int x = 0; x < clientData_.Size(); x++) { //Send the new client an old clients data msg_.Clear(); msg_.WriteInt(clientData_[x]->clientID_); msg_.WriteBool(false); sender->SendMessage(MSG_NEWCLIENT, true, true, msg_); //Send the old client the new clients data. msg_.Clear(); msg_.WriteInt(clientIDCount_); msg_.WriteBool(false); clientData_[x]->connection_->SendMessage(MSG_NEWCLIENT, true, true, msg_); } //Send the new client its data. clientData_.Push(newClient); msg_.Clear(); msg_.WriteInt(clientIDCount_); msg_.WriteBool(true); sender->SendMessage(MSG_NEWCLIENT, true, true, msg_); //Send the new client the gamemode to load. msg_.Clear(); msg_.WriteString(gamemodeName_.CString()); sender->SendMessage(MSG_LOADGAMEMODE, true, true, msg_); clientIDCount_++; }
bool HandleCreate(const Message &msg, Connection &con) { bool succeeded = false; CreateFileOp op; auto client = msg.sender(); try { msg.GetContent(op); cout << msg.sender() << " requested createop with args: " << op.file_name << " and " << op.redundancy << endl; if (!gFileMap.LockFile(op.file_name)) { cout << "Failed to lock entry. File was locked in the meantime." << endl; goto finish; } // get slaves associated with the file vector<string> slaves = GetFileSlaves(op.file_name); if (!slaves.empty()) { cout << "Create request failed. File does exist." << endl; } else { gSlavesLock.lock(); for (auto &entry : gSlaves) { slaves.push_back(entry.first); if (slaves.size() == op.redundancy) break; } gSlavesLock.unlock(); if (slaves.size() == op.redundancy) { succeeded = PerformOp(con, client, op.file_name, slaves); } } if (succeeded) { // insert the file on slaves gSlavesLock.lock(); for (auto & slave : gSlaves) { if (find(begin(slaves), end(slaves), slave.first) != end(slaves)) { slave.second.push_back(op.file_name); } } gSlavesLock.unlock(); SortSlaves(); } } catch (...) { cout << "Invalid create request from " << msg.sender() << endl; } gFileMap.UnlockFile(op.file_name); finish: Message res_msg(kFileOpResult, SAFE_MESS); ResultFileOp res{op.file_name, succeeded}; res_msg.SetContent(res); if (!con.SendMessage(res_msg, client)) { cout << "Failed to inform client of op result." << endl; } return succeeded; }
bool HandleRemove(const Message &msg, Connection &con) { bool succeeded = false; bool locked = false; RemoveFileOp op; auto client = msg.sender(); vector<string> slaves; try { msg.GetContent(op); cout << msg.sender() << " requested removeop with arg: " << op.file_name << endl; if (!(locked = gFileMap.LockFile(op.file_name))) { cout << "Failed to lock entry. File was locked in the meantime." << endl; goto finish; } // get slaves associated with the file slaves = GetFileSlaves(op.file_name); if (slaves.empty()) { cout << "Remove request failed. File does not exist." << endl; } else { succeeded = PerformOp(con, client, op.file_name, slaves); } if (succeeded) { // erases the files from slaves gSlavesLock.lock(); for (auto & slave : gSlaves) { if (find(begin(slaves), end(slaves), slave.first) != end(slaves)) { auto &files = slave.second; files.erase(remove(begin(files), end(files), op.file_name), end(files)); } } gSlavesLock.unlock(); SortSlaves(); } } catch (...) { cout << "Invalid create request from " << msg.sender() << endl; } if (locked) { gFileMap.UnlockFile(op.file_name); } finish: Message res_msg(kFileOpResult, SAFE_MESS); ResultFileOp res{op.file_name, succeeded}; res_msg.SetContent(res); if (!con.SendMessage(res_msg, client)) { cout << "Failed to inform client of op result." << endl; } return succeeded; }
void Silence::HandleGetLc(StringHash eventType, VariantMap& eventData) { Node* clientNode = (Node*)(eventData[GetLc::P_NODE].GetPtr()); if (clientNode == node_) { Connection* conn = (Connection*)(eventData[GetLc::P_CONNECTION].GetPtr()); msg_.Clear(); msg_.WriteInt(clientID_); msg_.WriteString("Silence"); msg_.WriteBool(silence_); conn->SendMessage(MSG_LCMSG, true, true, msg_); } }
void Chat::HandleSend(StringHash eventType, VariantMap& eventData) { String text = textEdit_->GetText(); if (text.Empty()) return; // Do not send an empty message Network* network = GetSubsystem<Network>(); Connection* serverConnection = network->GetServerConnection(); if (serverConnection) { // A VectorBuffer object is convenient for constructing a message to send VectorBuffer msg; msg.WriteString(text); // Send the chat message as in-order and reliable serverConnection->SendMessage(MSG_CHAT, true, true, msg); // Empty the text edit after sending textEdit_->SetText(String::EMPTY); } }
bool HandleRead(const Message &msg, Connection &con) { bool succeeded = false; bool locked = false; ReadFileOp op; auto client = msg.sender(); vector<string> slaves; try { msg.GetContent(op); cout << msg.sender() << " requested readop with arg: " << op.file_name << endl; if (!(locked = gFileMap.LockFile(op.file_name))) { cout << "Failed to lock entry. File was locked in the meantime." << endl; goto finish; } // get slaves associated with the file slaves = GetFileSlaves(op.file_name); if (slaves.empty()) { cout << "Read request failed. File does not exist." << endl; } else { slaves.resize(1); succeeded = PerformOp(con, client, op.file_name, slaves); } } catch (...) { cout << "Invalid read request from " << msg.sender() << endl; } if (locked) { gFileMap.UnlockFile(op.file_name); } finish: Message res_msg(kFileOpResult, SAFE_MESS); ResultFileOp res{op.file_name, succeeded}; res_msg.SetContent(res); if (!con.SendMessage(res_msg, client)) { cout << "Failed to inform client of op result." << endl; } return succeeded; }
void GameEconomicServerClientConsole::SendMessage(String Message) { /// If sending message is empty if (Message.Empty()) { return; // Do not send an empty message } /// Get connection Network* network = GetSubsystem<Network>(); Connection* serverConnection = network->GetServerConnection(); /// Send message only if serverconnection and connection is true if (serverConnection&&serverconnection) { // A VectorBuffer object is convenient for constructing a message to send VectorBuffer msg; msg.WriteString(Message); // Send the chat message as in-order and reliable serverConnection->SendMessage(NetMessageAdminClientSend, true, true, msg); } return; }
/** Accepts an outgoing message and sends it through the best * connection it currently has. Note that this WILL NOT create a * connection if one does not exist (for direct messages). Instead * it will convert the message to be a routable message and send it * on a random connection. * * \param msg The RAIN::Message object to be sent */ void RAIN::ConnectionPool::DispatchMessage(RAIN::Message *msg) { wxLogVerbose("ConnectionPool::DispatchMessage"); if (msg->status != MSG_STATUS_OUTGOING) return; BENC_SAFE_CAST(msg->headers["Destination"], msgdest, String); BENC_SAFE_CAST(msg->headers["Event"], msgevent, String); wxLogVerbose("ConnectionPool::DispatchMessage with msg for %s - %s", msgdest->getString().c_str(), msgevent->getString().c_str()); if (msgdest->getString().Cmp("Broadcast") == 0) { this->app->router->ImportBroadcast(msg); BEnc::Value *via = msg->headers["Via"]; BEnc::Dictionary *myval = NULL; wxString myhash = globalCredentialManager->GetMyPeerID()->hash; wxArrayString alreadyto; // we flatten the via to a list of peers already sent-to std::vector<BEnc::Value *> children; children.push_back(via); while (children.size() > 0) { BENC_SAFE_CAST(children.at(0), v, Dictionary); children.erase(children.begin()); // via is always a dict of dicts std::map<wxString, RAIN::BEnc::Value*, BEnc::Cmp>::iterator it = v->hash.begin(); while (it != v->hash.end()) { BENC_SAFE_CAST(it->second, h, Dictionary); alreadyto.Add(it->first); if (RAIN::SafeStringsEq(it->first, myhash)) { myval = h; } if (h->hash.size() > 0) { children.push_back(h); } it++; } } if (myval == NULL) { /* this is an error, because it means we got a message * without the sender modifying the message to indicate * we were sent it */ wxLogVerbose("Warning: Message received without our hash in Via"); return; } std::vector <RAIN::Connection *> local_sendto; int i = 0, n = 0; wxLogVerbose("Rebroadcasting message already sent to %d peers", alreadyto.GetCount()); // TODO: optimise this search /* now we search through our connected peers to determine if we can * further distribute this message to peers who haven't yet seen it */ for (i = 0; i < this->pool.size(); i++) { if (!this->pool.at(i)->isConnected) continue; wxString fp_hash = this->pool.at(i)->pid->hash; bool sendToThisPeer = true; /* has this message been seen by this peer? */ for (n = 0; n < alreadyto.GetCount(); n++) { if (RAIN::SafeStringsEq(fp_hash, alreadyto[n])) { /* yes, so don't resend */ sendToThisPeer = false; break; } } if (sendToThisPeer) { local_sendto.push_back(this->pool.at(i)); } } if (local_sendto.size() == 0) { wxLogVerbose("we cannot further distribute this broadcast"); /* we have nothing to do */ return; } /* prepare the message */ for (i = 0; i < local_sendto.size(); i++) { RAIN::Connection *c = local_sendto.at(i); /* myval is a pointer into msg's via hash at the node containing our hash */ myval->hash[c->pid->hash] = new BEnc::Dictionary(); } /* now send it */ for (i = 0; i < local_sendto.size(); i++) { wxLogVerbose("dispatching to %d (%s)", i, local_sendto.at(i)->pid->address.c_str()); local_sendto.at(i)->SendMessage(msg); } } else if (msgdest->getString().Cmp("Peer") == 0) { BENC_SAFE_CAST(msg->headers["To"], msgto, String); if (!msgto) return; wxString to = msgto->getString(); wxLogVerbose(" peer routing - to %s - searching local connections", CryptoHelper::HashToHex(to, true).c_str()); for (int i = 0; i < this->pool.size(); i++) { if (this->pool.at(i) && this->pool.at(i)->isConnected) { if (RAIN::SafeStringsEq(this->pool.at(i)->pid->hash, to)) { wxLogVerbose(" found connection"); this->pool.at(i)->SendMessage(msg); return; } } } /* we're still here :( * this implies we're not connected to the recipient of this message * so we need to route it */ if (!msg->headers.count("Route-Preload")) { /* we need to consult our routing manager to see if we know * of a route to this host */ RoutePath *rp; if (rp = this->app->router->GetBestRoute(to)) { rp->PreloadMessage(msg); } else { wxLogVerbose("Warning: route to %s unknown", CryptoHelper::HashToHex(to, true).c_str()); msgdest->str = "Broadcast"; this->DispatchMessage(msg); return; } } /* walk the route-preload looking for our hash */ wxString myHash = globalCredentialManager->GetMyPeerID()->hash; wxString target = ""; BENC_SAFE_CAST(msg->headers["Route-Preload"], preload, List); for (size_t i = 0; i < preload->getListSize(); i++) { BENC_SAFE_CAST(preload->getListItem(i), listitem, String); if (RAIN::SafeStringsEq(listitem->getString(), myHash)) { if (i + 1 == preload->getListSize()) { /* our target is actually To because we're last in the routelist */ target = to; } else { BENC_SAFE_CAST(preload->getListItem(i + 1), nextlistitem, String); target = nextlistitem->getString(); } break; } } if (target == "") { /* this should never happen - we got a message preloaded with a route * not including us, or the message is to nowhere! */ return; } else { for (size_t i = 0; i < this->pool.size(); i++) { if (this->pool.at(i) && this->pool.at(i)->isConnected) { if (RAIN::SafeStringsEq(this->pool.at(i)->pid->hash, to)) { if (msg->headers.count("Via")) { BENC_SAFE_CAST(msg->headers["Via"], msgvia, List); msgvia->pushList(new BEnc::String(myHash)); } else { BEnc::List *msgvia = new BEnc::List(); msgvia->pushList(new BEnc::String(myHash)); msg->headers["Via"] = msgvia; } this->pool.at(i)->SendMessage(msg); return; } } } /* we got a message with an old/invalid route - default to broadcast */ msgdest->str = "Broadcast"; this->DispatchMessage(msg); return; } } else if (msgdest->getString().Cmp("Random") == 0) { if (!this->AnyConnections()) { wxLogVerbose("Warning: Tried to send message to random peer with no connections - ignored"); return; } Connection *c = NULL; while (c == NULL) { size_t i = (size_t) this->pool.size() * (float) rand() / (float) RAND_MAX; wxLogVerbose("ConnectionPool: chose connection %d/%d for random dest", i, pool.size()); if (i < this->pool.size()) c = this->pool.at(i); if (!c->isConnected) c = NULL; } wxLogVerbose("Sending random message to connection %08x (%s)", c, c->pid->address.c_str()); msgdest->str = "Peer"; msg->headers["To"] = new BEnc::String(c->pid->hash); c->SendMessage(msg); } }
void PvPGM::ServerHandleNetworkMessage(StringHash eventType, VariantMap& eventData) { using namespace NetworkMessage; int msgID = eventData[P_MESSAGEID].GetInt(); Connection* sender = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr()); if (msgID == MSG_GAMEMODELOADED) { ServerSynchronizeScene(sender); } else if (msgID == MSG_GAMEMODEMSG) { const PODVector<unsigned char>& data = eventData[P_DATA].GetBuffer(); MemoryBuffer msg(data); int messageID = msg.ReadInt(); if (messageID == MSG_SCENELOADED_) { PlayerSB* player; //Create player on server. for (int x = 0; x < server_->clientData_.Size(); x++) { if (server_->clientData_[x]->connection_ == sender) { int index = Random( 0, spawnPoints_.Size() ); victoria_ = spawnPoints_[index]->GetPosition(); quarterOnion_ = spawnPoints_[index]->GetRotation(); player = NewPlayer(server_->clientData_[x], "Witch3", victoria_, quarterOnion_);//Witch3 is the default model. break; } } for (int x = 0; x < players_.Size(); x++) { //Send client the existing players. msg_.Clear(); msg_.WriteInt(MSG_NEWPLAYER_); msg_.WriteInt(players_[x]->clientData_->clientID_); msg_.WriteString(players_[x]->modelFilename_); msg_.WriteVector3(players_[x]->player_->GetPosition()); msg_.WriteQuaternion(players_[x]->player_->GetRotation()); sender->SendMessage(MSG_GAMEMODEMSG, true, true, msg_); if (sender != players_[x]->clientData_->connection_) { ((GameMechanic*)(players_[x]))->receiver_ = sender; ((GameMechanic*)(players_[x]))->clientID_ = players_[x]->clientData_->clientID_; players_[x]->ServerSync(); //Send the existing players the client. msg_.Clear(); msg_.WriteInt(MSG_NEWPLAYER_); msg_.WriteInt(player->clientData_->clientID_); msg_.WriteString(player->modelFilename_); msg_.WriteVector3(player->player_->GetPosition()); msg_.WriteQuaternion(player->player_->GetRotation()); players_[x]->clientData_->connection_->SendMessage(MSG_GAMEMODEMSG, true, true, msg_); } } } else if (messageID == MSG_RequestMechanicExecute_) { for (int x = 0; x < players_.Size(); x++) { if (players_[x]->clientData_->connection_ == sender) { float lagTime = ServerGetSenderLagTime(sender); lagTime += ServerGetSenderLagTime(sender); ((GameMechanic*)(players_[x]))->message_ = &msg; ((GameMechanic*)(players_[x]))->clientID_ = players_[x]->clientData_->clientID_; ((GameMechanic*)(players_[x]))->lagTime_ = lagTime; players_[x]->RequestMechanicExecute(); break; } } } } }