/** * Tencent is pleased to support the open source community by making Tars available. * * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-3-Clause * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ #ifndef _WUP_H_ #define _WUP_H_ #include #include #include #include //支持iphone #ifdef __APPLE__ #include "RequestF.h" #elif defined ANDROID // android #include "RequestF.h" #else #include "tup/RequestF.h" #endif // #ifdef __GNUC__ // # if __GNUC__ >3 || __GNUC_MINOR__ > 3 // # include // # endif // #endif using namespace std; using namespace tars; namespace tup { //存放tars返回值的key const string STATUS_RESULT_CODE = "STATUS_RESULT_CODE"; const string STATUS_RESULT_DESC = "STATUS_RESULT_DESC"; ///////////////////////////////////////////////////////////////////////////////// // 属性封装类 template class Alloc = std::allocator > //template class Alloc = __gnu_cxx::__pool_alloc > class UniAttribute { typedef vector > VECTOR_CHAR_TYPE; typedef map,Alloc< pair > > VECTOR_CHAR_IN_MAP_TYPE; typedef map,Alloc< pair > > WUP_DATA_TYPE; public: /** * 构造函数 */ UniAttribute() { _iVer = 3; } void setVersion(short iVer) { _iVer = iVer; } /** * 添加属性值 * * @param T: 属性类型 * @param name:属性名称 * @param t: 属性值 */ template void put(const string& name, const T& t) { os.reset(); os.write(t, 0); VECTOR_CHAR_TYPE & v = _data[name]; os.swap(v); // v.assign(os.getBuffer(), os.getBuffer() + os.getLength()); } void putUnknown(const string& name, const string& value) { os.reset(); os.writeUnknownV2(value); VECTOR_CHAR_TYPE & v = _data[name]; os.swap(v); // v.assign(os.getBuffer(), os.getBuffer() + os.getLength()); } void getUnknown(const string& name, string& value) { typename VECTOR_CHAR_IN_MAP_TYPE::iterator mit; mit = _data.find(name); if (mit != _data.end() && mit->second.size()>2) { //去掉DataHead::eStructBegin,DataHead::eStructEnd value = string(&mit->second[0]+1, mit->second.size()-2); return; } throw runtime_error(string("UniAttribute not found key:") + name); } /** * 获取属性值,属性不存在则抛出异常 * * @throw runtime_error * @param T: 属性类型 * @param name:属性名称 * @param t: 属性值输出参数 */ template void get(const string& name, T& t) { typename VECTOR_CHAR_IN_MAP_TYPE::iterator mit; mit = _data.find(name); if (mit != _data.end()) { is.reset(); is.setBuffer(mit->second); is.read(t, 0, true); return; } throw runtime_error(string("UniAttribute not found key:") + name); } /** * 获取属性值,属性不存在则抛出异常 * * @throw runtime_error * @param T: 属性类型 * @param name:属性名称 * @return T: 属性值 */ template T get(const string& name) { T t; get(name, t); return t; } /** * 获取属性值,忽略异常,不存在的属性返回缺省值 * * @param T: 属性类型 * @param name:属性名称 * @param t: 属性值输出参数 * @param def: 默认值 */ template void getByDefault(const string& name, T& t, const T& def) { try { get(name, t); } catch (runtime_error& e) { t = def; } } /** * 获取属性值(忽略异常,def为缺省值) * * @param T: 属性类型 * @param name:属性名称 * @param: 默认值 * @return T: 属性值 */ template T getByDefault(const string& name, const T& def) { T t; getByDefault(name, t, def); return t; } /** *清除全部属性值 */ void clear() { _data.clear(); } /** 编码 * * @param buff: 编码结果输出参数 */ void encode(string& buff) { os.reset(); os.write(_data, 0); os.swap(buff); // buff.assign(os.getBuffer(), os.getLength()); } /** 编码 * * @param buff: 编码结果输出参数 */ void encode(vector& buff) { os.reset(); os.write(_data, 0); os.swap(buff); // buff.assign(os.getBuffer(), os.getBuffer() + os.getLength()); } /** 编码 * * @throw runtime_error * @param buff:输出存放编码结果的buffer指针 * @param len: 输入buff长度,输出编码结果长度 */ void encode(char* buff, size_t & len) { os.reset(); os.write(_data, 0); if(len < os.getLength()) throw runtime_error("encode error, buffer length too short"); memcpy(buff, os.getBuffer(), os.getLength()); len = os.getLength(); } /** 解码 * * @throw runtime_error * @param buff:待解码字节流的buffer指针 * @param len: 待解码字节流的长度 */ void decode(const char* buff, size_t len) { is.reset(); is.setBuffer(buff, len); _data.clear(); is.read(_data, 0, true); } /** * 解码 * * @throw runtime_error * @param buff: 待解码的字节流 */ void decode(const vector& buff) { is.reset(); is.setBuffer(buff); _data.clear(); is.read(_data, 0, true); } /** * 获取已有的属性 * * @return const map>>& : 属性map */ const map >& getData() const { return _data; } /** * 判断属性集合是否为空 * * @return bool:属性是否为空 */ bool isEmpty() { return _data.empty(); } /** * 获取属性集合大小 * * @return size_t: 集合大小 */ size_t size() { return _data.size(); } /** * 判断属性是否存在 * * @param key:属性名称 * @return bool:是否存在 */ bool containsKey(const string & key) { return _data.find(key) != _data.end(); } protected: VECTOR_CHAR_IN_MAP_TYPE _data; short _iVer; public: TarsInputStream is; TarsOutputStream os; }; ///////////////////////////////////////////////////////////////////////////////// // 请求、回应包封装类 template class Alloc = std::allocator > struct UniPacket : protected RequestPacket, public UniAttribute { public: /** * 构造函数 */ UniPacket() { iVersion = 3; cPacketType = 0; iMessageType = 0; iRequestId = 0; sServantName = ""; sFuncName = ""; iTimeout = 0; sBuffer.clear(); context.clear(); status.clear(); UniAttribute::_iVer = iVersion; UniAttribute::_data.clear(); UniAttribute::_data.clear(); } /** * 拷贝构造 * @param tup */ UniPacket(const UniPacket &tup) { *this = tup;} void setVersion(short iVer) { UniAttribute::_iVer = iVer; iVersion = iVer; } /** * 由请求包生成回应包基本结构,回填关键的请求信息 * * @return UniPacket: 回应包 */ UniPacket createResponse() { UniPacket respPacket; respPacket.sServantName = sServantName; respPacket.sFuncName = sFuncName; respPacket.iRequestId = iRequestId; return respPacket; } /** * 编码,结果的包头4个字节为整个包的长度,网络字节序 * * @throw runtime_error * @param buff: 编码结果输出参数 */ void encode(string& buff) { encodeBuff(buff); // TarsOutputStream &os = UniAttribute::os; // os.reset(); // doEncode(os); // tars::Int32 iHeaderLen = htonl(sizeof(tars::Int32) + os.getLength()); // buff.assign((const char*)&iHeaderLen, sizeof(tars::Int32)); // buff.append(os.getBuffer(), os.getLength()); } /** * 编码,结果的包头4个字节为整个包的长度,网络字节序 * * @throw runtime_error * @param buff: 编码结果输出参数 */ void encode(vector& buff) { encodeBuff>(buff); // TarsOutputStream & os = UniAttribute::os; // os.reset(); // doEncode(os); // tars::Int32 iHeaderLen = htonl(sizeof(tars::Int32) + os.getLength()); // buff.resize(sizeof(tars::Int32) + os.getLength()); // memcpy(&buff[0], &iHeaderLen, sizeof(tars::Int32)); // memcpy(&buff[sizeof(tars::Int32)], os.getBuffer(), os.getLength()); } /** * 编码,结果的包头4个字节为整个包的长度,网络字节序 * @throw runtime_error * @param buff:存放编码结果的buffer指针 * @param len: 输入buff长度,输出编码结果长度 */ void encode(char* buff, size_t & len) { TarsOutputStream& os = UniAttribute::os; os.reset(); doEncode(os); os.reset(); writeTo(os); tars::Int32 iHeaderLen = htonl(sizeof(tars::Int32) + os.getLength()); if (len < sizeof(tars::Int32) + os.getLength()) throw runtime_error("encode error, buffer length too short"); memcpy(buff, &iHeaderLen, sizeof(tars::Int32)); memcpy(buff + sizeof(tars::Int32), os.getBuffer(), os.getLength()); len = sizeof(tars::Int32) + os.getLength(); // TarsOutputStream &os = UniAttribute::os; // os.reset(); // doEncode(os); // tars::Int32 iHeaderLen = htonl(sizeof(tars::Int32) + os.getLength()); // if(len < sizeof(tars::Int32) + os.getLength()) throw runtime_error("encode error, buffer length too short"); // memcpy(buff, &iHeaderLen, sizeof(tars::Int32)); // memcpy(buff + sizeof(tars::Int32), os.getBuffer(), os.getLength()); // len = sizeof(tars::Int32) + os.getLength(); } /** 解码 * * @throw runtime_error * @param buff:待解码字节流的buffer指针 * @param len: 待解码字节流的长度 */ void decode(const char* buff, size_t len) { if(len < sizeof(tars::Int32)) throw runtime_error("packet length too short, first 4 bytes must be buffer length."); TarsInputStream &is = UniAttribute::is; is.reset(); is.setBuffer(buff + sizeof(tars::Int32), len - sizeof(tars::Int32)); readFrom(is); UniAttribute::_iVer = iVersion; is.reset(); is.setBuffer(sBuffer); UniAttribute::_data.clear(); is.read(UniAttribute::_data, 0, true); } public: /** * 获取消息version * @return tars::Short */ tars::Short getVersion() const { return iVersion; } /** * 获取消息ID * @return tars::Int32 */ tars::Int32 getRequestId() const { return iRequestId; } /** * 设置请求ID * @param value */ void setRequestId(tars::Int32 value) { iRequestId = value; } /** * 获取对象名称 * @return const std::string& */ const std::string& getServantName() const { return sServantName; } /** * 设置对象名称 * @param value */ void setServantName(const std::string& value) { sServantName = value; } /** * 获取方法名 * @return const std::string& */ const std::string& getFuncName() const { return sFuncName; } /** * 设置方法名 * @param value */ void setFuncName(const std::string& value) { sFuncName = value; } protected: template void encodeBuff(T& buff) { TarsOutputStream& os = UniAttribute::os; os.reset(); doEncode(os); os.reset(); tars::Int32 iHeaderLen = 0; // 先预留4个字节长度 os.writeBuf((const char *)&iHeaderLen, sizeof(iHeaderLen)); writeTo(os); os.swap(buff); assert(buff.size() >= 4); iHeaderLen = htonl((int)(buff.size())); memcpy(&buff[0], (const char *)&iHeaderLen, sizeof(iHeaderLen)); } /** * 内部编码 */ void doEncode(TarsOutputStream& os) { //ServantName、FuncName不能为空 if (sServantName.empty()) throw runtime_error("ServantName must not be empty"); if (sFuncName.empty()) throw runtime_error("FuncName must not be empty"); os.reset(); os.write(UniAttribute::_data, 0); os.swap(sBuffer); os.reset(); } // /** // * 内部编码 // */ // void doEncode(TarsOutputStream& os) // { // //ServantName、FuncName不能为空 // if(sServantName.empty()) throw runtime_error("ServantName must not be empty"); // if(sFuncName.empty()) throw runtime_error("FuncName must not be empty"); // os.reset(); // os.write(UniAttribute::_data, 0); // sBuffer.assign(os.getBuffer(), os.getBuffer() + os.getLength()); // os.reset(); // writeTo(os); // } }; ///////////////////////////////////////////////////////////////////////////////// // 调用TARS的服务时使用的类 template class Alloc = std::allocator> struct TarsUniPacket: public UniPacket { public: TarsUniPacket(){}; TarsUniPacket(const UniPacket &tup) : UniPacket(tup) {}; /** * 设置协议版本 * @param value */ void setTarsVersion(tars::Short value) { UniPacket::setVersion(value); } /** * 设置调用类型 * @param value */ void setTarsPacketType(tars::Char value) { this->cPacketType = value; } /** * 设置消息类型 * @param value */ void setTarsMessageType(tars::Int32 value) { this->iMessageType = value; } /** * 设置超时时间 * @param value */ void setTarsTimeout(tars::Int32 value) { this->iTimeout = value; } /** * 设置参数编码内容 * @param value */ void setTarsBuffer(const vector& value) { this->sBuffer = value; } /** * 设置上下文 * @param value */ void setTarsContext(const map& value) { this->context = value; } /** * 设置特殊消息的状态值 * @param value */ void setTarsStatus(const map& value) { this->status = value; } /** * 获取协议版本 * @return tars::Short */ tars::Short getTarsVersion() const { return this->iVersion; } /** * 获取调用类型 * @return tars::Char */ tars::Char getTarsPacketType() const { return this->cPacketType; } /** * 获取消息类型 * @return tars::Int32 */ tars::Int32 getTarsMessageType() const { return this->iMessageType; } /** * 获取超时时间 * @return tars::Int32 */ tars::Int32 getTarsTimeout() const { return this->iTimeout; } /** * 获取参数编码后内容 * @return const vector& */ const vector& getTarsBuffer() const { return this->sBuffer; } /** * 获取上下文信息 * @return const map& */ const map& getTarsContext() const { return this->context; } /** * 获取特殊消息的状态值 * @return const map& */ const map& getTarsStatus() const { return this->status; } /** * 获取调用tars的返回值 * * @retrun tars::Int32 */ tars::Int32 getTarsResultCode() const { map::const_iterator it; if((it = this->status.find(STATUS_RESULT_CODE)) == this->status.end()) { return 0; } else { return atoi(it->second.c_str()); } } /** * 获取调用tars的返回描述 * * @retrun string */ string getTarsResultDesc() const { map::const_iterator it; if((it = this->status.find(STATUS_RESULT_DESC)) == this->status.end()) { return ""; } else { return it->second; } } }; // #ifdef __GNUC__ // # if __GNUC__ >3 || __GNUC_MINOR__ > 3 // typedef UniAttribute UniAttrPoolAlloc; // typedef UniPacket UniPacketPoolAlloc; // typedef TarsUniPacket TarsUniPacketPoolAlloc; // # endif // #endif } //////////////////////////////////////////////////////////////////////////////////////////////// #endif