summaryrefslogtreecommitdiffstats
path: root/src/messages/MForward.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/messages/MForward.h158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/messages/MForward.h b/src/messages/MForward.h
new file mode 100644
index 000000000..f47de8fc2
--- /dev/null
+++ b/src/messages/MForward.h
@@ -0,0 +1,158 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ * Client requests often need to get forwarded from some monitor
+ * to the leader. This class encapsulates the original message
+ * along with the client's caps so the leader can do proper permissions
+ * checking.
+ */
+
+#ifndef CEPH_MFORWARD_H
+#define CEPH_MFORWARD_H
+
+#include "msg/Message.h"
+#include "mon/MonCap.h"
+#include "include/encoding.h"
+#include "include/stringify.h"
+
+class MForward final : public Message {
+public:
+ uint64_t tid;
+ uint8_t client_type;
+ entity_addrvec_t client_addrs;
+ entity_addr_t client_socket_addr;
+ MonCap client_caps;
+ uint64_t con_features;
+ EntityName entity_name;
+ PaxosServiceMessage *msg; // incoming or outgoing message
+
+ std::string msg_desc; // for operator<< only
+
+ static constexpr int HEAD_VERSION = 4;
+ static constexpr int COMPAT_VERSION = 4;
+
+ MForward() : Message{MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION},
+ tid(0), con_features(0), msg(NULL) {}
+ MForward(uint64_t t, PaxosServiceMessage *m, uint64_t feat,
+ const MonCap& caps) :
+ Message{MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION},
+ tid(t), client_caps(caps), msg(NULL) {
+ client_type = m->get_source().type();
+ client_addrs = m->get_source_addrs();
+ if (auto con = m->get_connection()) {
+ client_socket_addr = con->get_peer_socket_addr();
+ }
+ con_features = feat;
+ msg = (PaxosServiceMessage*)m->get();
+ }
+private:
+ ~MForward() final {
+ if (msg) {
+ // message was unclaimed
+ msg->put();
+ msg = NULL;
+ }
+ }
+
+public:
+ void encode_payload(uint64_t features) override {
+ using ceph::encode;
+ if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) {
+ header.version = 3;
+ header.compat_version = 3;
+ encode(tid, payload);
+ entity_inst_t client;
+ client.name = entity_name_t(client_type, -1);
+ client.addr = client_addrs.legacy_addr();
+ encode(client, payload, features);
+ encode(client_caps, payload, features);
+ // Encode client message with intersection of target and source
+ // features. This could matter if the semantics of the encoded
+ // message are changed when reencoding with more features than the
+ // client had originally. That should never happen, but we may as
+ // well be defensive here.
+ if (con_features != features) {
+ msg->clear_payload();
+ }
+ encode_message(msg, features & con_features, payload);
+ encode(con_features, payload);
+ encode(entity_name, payload);
+ return;
+ }
+ header.version = HEAD_VERSION;
+ header.compat_version = COMPAT_VERSION;
+ encode(tid, payload);
+ encode(client_type, payload, features);
+ encode(client_addrs, payload, features);
+ encode(client_socket_addr, payload, features);
+ encode(client_caps, payload, features);
+ // Encode client message with intersection of target and source
+ // features. This could matter if the semantics of the encoded
+ // message are changed when reencoding with more features than the
+ // client had originally. That should never happen, but we may as
+ // well be defensive here.
+ if (con_features != features) {
+ msg->clear_payload();
+ }
+ encode_message(msg, features & con_features, payload);
+ encode(con_features, payload);
+ encode(entity_name, payload);
+ }
+
+ void decode_payload() override {
+ using ceph::decode;
+ auto p = payload.cbegin();
+ decode(tid, p);
+ if (header.version < 4) {
+ entity_inst_t client;
+ decode(client, p);
+ client_type = client.name.type();
+ client_addrs = entity_addrvec_t(client.addr);
+ client_socket_addr = client.addr;
+ } else {
+ decode(client_type, p);
+ decode(client_addrs, p);
+ decode(client_socket_addr, p);
+ }
+ decode(client_caps, p);
+ msg = (PaxosServiceMessage *)decode_message(NULL, 0, p);
+ decode(con_features, p);
+ decode(entity_name, p);
+ }
+
+ PaxosServiceMessage *claim_message() {
+ // let whoever is claiming the message deal with putting it.
+ ceph_assert(msg);
+ msg_desc = stringify(*msg);
+ PaxosServiceMessage *m = msg;
+ msg = NULL;
+ return m;
+ }
+
+ std::string_view get_type_name() const override { return "forward"; }
+ void print(std::ostream& o) const override {
+ o << "forward(";
+ if (msg) {
+ o << *msg;
+ } else {
+ o << msg_desc;
+ }
+ o << " caps " << client_caps
+ << " tid " << tid
+ << " con_features " << con_features << ")";
+ }
+private:
+ template<class T, typename... Args>
+ friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);
+};
+
+#endif