1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 #ifndef _THRIFT_TDISPATCHPROCESSOR_H_ 20 #define _THRIFT_TDISPATCHPROCESSOR_H_ 1 21 22 #include <thrift/TProcessor.h> 23 24 namespace apache { 25 namespace thrift { 26 27 /** 28 * TDispatchProcessor is a helper class to parse the message header then call 29 * another function to dispatch based on the function name. 30 * 31 * Subclasses must implement dispatchCall() to dispatch on the function name. 32 */ 33 template <class Protocol_> 34 class TDispatchProcessorT : public TProcessor { 35 public: process(std::shared_ptr<protocol::TProtocol> in,std::shared_ptr<protocol::TProtocol> out,void * connectionContext)36 bool process(std::shared_ptr<protocol::TProtocol> in, 37 std::shared_ptr<protocol::TProtocol> out, 38 void* connectionContext) override { 39 protocol::TProtocol* inRaw = in.get(); 40 protocol::TProtocol* outRaw = out.get(); 41 42 // Try to dynamic cast to the template protocol type 43 auto* specificIn = dynamic_cast<Protocol_*>(inRaw); 44 auto* specificOut = dynamic_cast<Protocol_*>(outRaw); 45 if (specificIn && specificOut) { 46 return processFast(specificIn, specificOut, connectionContext); 47 } 48 49 // Log the fact that we have to use the slow path 50 T_GENERIC_PROTOCOL(this, inRaw, specificIn); 51 T_GENERIC_PROTOCOL(this, outRaw, specificOut); 52 53 std::string fname; 54 protocol::TMessageType mtype; 55 int32_t seqid; 56 inRaw->readMessageBegin(fname, mtype, seqid); 57 58 // If this doesn't look like a valid call, log an error and return false so 59 // that the server will close the connection. 60 // 61 // (The old generated processor code used to try to skip a T_STRUCT and 62 // continue. However, that seems unsafe.) 63 if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { 64 GlobalOutput.printf("received invalid message type %d from client", mtype); 65 return false; 66 } 67 68 return this->dispatchCall(inRaw, outRaw, fname, seqid, connectionContext); 69 } 70 71 protected: processFast(Protocol_ * in,Protocol_ * out,void * connectionContext)72 bool processFast(Protocol_* in, Protocol_* out, void* connectionContext) { 73 std::string fname; 74 protocol::TMessageType mtype; 75 int32_t seqid; 76 in->readMessageBegin(fname, mtype, seqid); 77 78 if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { 79 GlobalOutput.printf("received invalid message type %d from client", mtype); 80 return false; 81 } 82 83 return this->dispatchCallTemplated(in, out, fname, seqid, connectionContext); 84 } 85 86 /** 87 * dispatchCall() methods must be implemented by subclasses 88 */ 89 virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in, 90 apache::thrift::protocol::TProtocol* out, 91 const std::string& fname, 92 int32_t seqid, 93 void* callContext) = 0; 94 95 virtual bool dispatchCallTemplated(Protocol_* in, 96 Protocol_* out, 97 const std::string& fname, 98 int32_t seqid, 99 void* callContext) = 0; 100 }; 101 102 /** 103 * Non-templatized version of TDispatchProcessor, that doesn't bother trying to 104 * perform a dynamic_cast. 105 */ 106 class TDispatchProcessor : public TProcessor { 107 public: process(std::shared_ptr<protocol::TProtocol> in,std::shared_ptr<protocol::TProtocol> out,void * connectionContext)108 bool process(std::shared_ptr<protocol::TProtocol> in, 109 std::shared_ptr<protocol::TProtocol> out, 110 void* connectionContext) override { 111 std::string fname; 112 protocol::TMessageType mtype; 113 int32_t seqid; 114 in->readMessageBegin(fname, mtype, seqid); 115 116 if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { 117 GlobalOutput.printf("received invalid message type %d from client", mtype); 118 return false; 119 } 120 121 return dispatchCall(in.get(), out.get(), fname, seqid, connectionContext); 122 } 123 124 protected: 125 virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in, 126 apache::thrift::protocol::TProtocol* out, 127 const std::string& fname, 128 int32_t seqid, 129 void* callContext) = 0; 130 }; 131 132 // Specialize TDispatchProcessorT for TProtocol and TDummyProtocol just to use 133 // the generic TDispatchProcessor. 134 template <> 135 class TDispatchProcessorT<protocol::TDummyProtocol> : public TDispatchProcessor {}; 136 template <> 137 class TDispatchProcessorT<protocol::TProtocol> : public TDispatchProcessor {}; 138 } 139 } // apache::thrift 140 141 #endif // _THRIFT_TDISPATCHPROCESSOR_H_ 142