1    	// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2    	// vim: ts=8 sw=2 smarttab
3    	/*
4    	 * Ceph - scalable distributed file system
5    	 *
6    	 * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
7    	 *
8    	 * This is free software; you can redistribute it and/or
9    	 * modify it under the terms of the GNU Lesser General Public
10   	 * License version 2.1, as published by the Free Software 
11   	 * Foundation.  See file COPYING.
12   	 * 
13   	 * Client requests often need to get forwarded from some monitor
14   	 * to the leader. This class encapsulates the original message
15   	 * along with the client's caps so the leader can do proper permissions
16   	 * checking.
17   	 */
18   	
19   	#ifndef CEPH_MFORWARD_H
20   	#define CEPH_MFORWARD_H
21   	
22   	#include "msg/Message.h"
23   	#include "mon/MonCap.h"
24   	#include "include/encoding.h"
25   	#include "include/stringify.h"
26   	
27   	class MForward : public Message {
28   	public:
29   	  uint64_t tid;
30   	  uint8_t client_type;
31   	  entity_addrvec_t client_addrs;
32   	  entity_addr_t client_socket_addr;
33   	  MonCap client_caps;
34   	  uint64_t con_features;
35   	  EntityName entity_name;
36   	  PaxosServiceMessage *msg;   // incoming or outgoing message
37   	
38   	  string msg_desc;  // for operator<< only
39   	  
40   	  static constexpr int HEAD_VERSION = 4;
41   	  static constexpr int COMPAT_VERSION = 4;
42   	
43   	  MForward() : Message{MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION},
44   	               tid(0), con_features(0), msg(NULL) {}
45   	  MForward(uint64_t t, PaxosServiceMessage *m, uint64_t feat,
46   	           const MonCap& caps) :
47   	    Message{MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION},
48   	    tid(t), client_caps(caps), msg(NULL) {
49   	    client_type = m->get_source().type();
50   	    client_addrs = m->get_source_addrs();
51   	    if (auto con = m->get_connection()) {
52   	      client_socket_addr = con->get_peer_socket_addr();
53   	    }
54   	    con_features = feat;
55   	    msg = (PaxosServiceMessage*)m->get();
56   	  }
57   	private:
(1) Event exn_spec_violation: An exception of type "std::length_error" is thrown but the throw list "throw()" doesn't allow it to be thrown. This will cause a call to unexpected() which usually calls terminate().
Also see events: [fun_call_w_exception]
58   	  ~MForward() override {
59   	    if (msg) {
60   	      // message was unclaimed
(2) Event fun_call_w_exception: Called function throws an exception of type "std::length_error". [details]
Also see events: [exn_spec_violation]
61   	      msg->put();
62   	      msg = NULL;
63   	    }
64   	  }
65   	
66   	public:
67   	  void encode_payload(uint64_t features) override {
68   	    using ceph::encode;
69   	    if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) {
70   	      header.version = 3;
71   	      header.compat_version = 3;
72   	      encode(tid, payload);
73   	      entity_inst_t client;
74   	      client.name = entity_name_t(client_type, -1);
75   	      client.addr = client_addrs.legacy_addr();
76   	      encode(client, payload, features);
77   	      encode(client_caps, payload, features);
78   	      // Encode client message with intersection of target and source
79   	      // features.  This could matter if the semantics of the encoded
80   	      // message are changed when reencoding with more features than the
81   	      // client had originally.  That should never happen, but we may as
82   	      // well be defensive here.
83   	      if (con_features != features) {
84   		msg->clear_payload();
85   	      }
86   	      encode_message(msg, features & con_features, payload);
87   	      encode(con_features, payload);
88   	      encode(entity_name, payload);
89   	      return;
90   	    }
91   	    header.version = HEAD_VERSION;
92   	    header.compat_version = COMPAT_VERSION;
93   	    encode(tid, payload);
94   	    encode(client_type, payload, features);
95   	    encode(client_addrs, payload, features);
96   	    encode(client_socket_addr, payload, features);
97   	    encode(client_caps, payload, features);
98   	    // Encode client message with intersection of target and source
99   	    // features.  This could matter if the semantics of the encoded
100  	    // message are changed when reencoding with more features than the
101  	    // client had originally.  That should never happen, but we may as
102  	    // well be defensive here.
103  	    if (con_features != features) {
104  	      msg->clear_payload();
105  	    }
106  	    encode_message(msg, features & con_features, payload);
107  	    encode(con_features, payload);
108  	    encode(entity_name, payload);
109  	  }
110  	
111  	  void decode_payload() override {
112  	    auto p = payload.cbegin();
113  	    decode(tid, p);
114  	    if (header.version < 4) {
115  	      entity_inst_t client;
116  	      decode(client, p);
117  	      client_type = client.name.type();
118  	      client_addrs = entity_addrvec_t(client.addr);
119  	      client_socket_addr = client.addr;
120  	    } else {
121  	      decode(client_type, p);
122  	      decode(client_addrs, p);
123  	      decode(client_socket_addr, p);
124  	    }
125  	    decode(client_caps, p);
126  	    msg = (PaxosServiceMessage *)decode_message(NULL, 0, p);
127  	    decode(con_features, p);
128  	    decode(entity_name, p);
129  	  }
130  	
131  	  PaxosServiceMessage *claim_message() {
132  	    // let whoever is claiming the message deal with putting it.
133  	    ceph_assert(msg);
134  	    msg_desc = stringify(*msg);
135  	    PaxosServiceMessage *m = msg;
136  	    msg = NULL;
137  	    return m;
138  	  }
139  	
140  	  std::string_view get_type_name() const override { return "forward"; }
141  	  void print(ostream& o) const override {
142  	    o << "forward(";
143  	    if (msg) {
144  	      o << *msg;
145  	    } else {
146  	      o << msg_desc;
147  	    }
148  	    o << " caps " << client_caps
149  	      << " tid " << tid
150  	      << " con_features " << con_features << ")";
151  	  }
152  	private:
153  	  template<class T, typename... Args>
154  	  friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);
155  	};
156  	  
157  	#endif
158