AppProtocol.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #include "util/tc_epoll_server.h"
  17. #include "servant/AppProtocol.h"
  18. #include "tup/Tars.h"
  19. #include <iostream>
  20. #if TARS_HTTP2
  21. #include "util/tc_nghttp2.h"
  22. #include "util/tc_http2clientmgr.h"
  23. #define MAKE_NV(NAME, VALUE, VALUELEN) \
  24. { \
  25. (uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
  26. NGHTTP2_NV_FLAG_NONE \
  27. }
  28. #define MAKE_NV2(NAME, VALUE) \
  29. { \
  30. (uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
  31. NGHTTP2_NV_FLAG_NONE \
  32. }
  33. #define MAKE_STRING_NV(NAME, VALUE) {(uint8_t*)(NAME.data()), (uint8_t*)(VALUE.data()), NAME.size(), VALUE.size(), NGHTTP2_NV_FLAG_NONE};
  34. #endif
  35. namespace tars
  36. {
  37. //TARSServer的协议解析器
  38. int AppProtocol::parseAdmin(string &in, string &out)
  39. {
  40. return parse(in, out);
  41. }
  42. void ProxyProtocol::tarsRequest(const RequestPacket& request, string& buff)
  43. {
  44. TarsOutputStream<BufferWriter> os;
  45. request.writeTo(os);
  46. tars::Int32 iHeaderLen = htonl(sizeof(tars::Int32) + os.getLength());
  47. buff.clear();
  48. buff.reserve(sizeof(tars::Int32) + os.getLength());
  49. buff.append((const char*)&iHeaderLen, sizeof(tars::Int32));
  50. buff.append(os.getBuffer(), os.getLength());
  51. }
  52. ////////////////////////////////////////////////////////////////////////////////////
  53. #if TARS_HTTP2
  54. // nghttp2读取请求包体,准备发送
  55. static ssize_t reqbody_read_callback(nghttp2_session *session, int32_t stream_id,
  56. uint8_t *buf, size_t length,
  57. uint32_t *data_flags,
  58. nghttp2_data_source *source,
  59. void *user_data)
  60. {
  61. std::vector<char>* body = (std::vector<char>* )source->ptr;
  62. if (body->empty())
  63. {
  64. *data_flags |= NGHTTP2_DATA_FLAG_EOF;
  65. return 0;
  66. }
  67. ssize_t len = length > body->size() ? body->size() : length;
  68. std::memcpy(buf, &(*body)[0], len);
  69. vector<char>::iterator end = body->begin();
  70. std::advance(end, len);
  71. body->erase(body->begin(), end);
  72. return len;
  73. }
  74. size_t http1Response(const char* recvBuffer, size_t length, std::list<tars::ResponsePacket>& done)
  75. {
  76. tars::TC_HttpResponse httpRsp;
  77. bool ok = httpRsp.decode(std::string(recvBuffer, length));
  78. if(!ok)
  79. return 0;
  80. ResponsePacket rsp;
  81. rsp.status["status"] = httpRsp.getResponseHeaderLine();
  82. for (const auto& kv : httpRsp.getHeaders())
  83. {
  84. // 响应的头部
  85. rsp.status[kv.first] = kv.second;
  86. }
  87. std::string content(httpRsp.getContent());
  88. rsp.sBuffer.assign(content.begin(), content.end());
  89. done.push_back(rsp);
  90. return httpRsp.getHeadLength() + httpRsp.getContentLength();
  91. }
  92. std::string encodeHttp2(RequestPacket& request, TC_NgHttp2* session)
  93. {
  94. std::vector<nghttp2_nv> nva;
  95. const std::string method(":method");
  96. nghttp2_nv nv1 = MAKE_STRING_NV(method, request.sFuncName);
  97. if (!request.sFuncName.empty())
  98. nva.push_back(nv1);
  99. const std::string path(":path");
  100. nghttp2_nv nv2 = MAKE_STRING_NV(path, request.sServantName);
  101. if (!request.sServantName.empty())
  102. nva.push_back(nv2);
  103. for (std::map<std::string, std::string>::const_iterator
  104. it(request.context.begin());
  105. it != request.context.end();
  106. ++ it)
  107. {
  108. nghttp2_nv nv = MAKE_STRING_NV(it->first, it->second);
  109. nva.push_back(nv);
  110. }
  111. nghttp2_data_provider* pData = NULL;
  112. nghttp2_data_provider data;
  113. if (!request.sBuffer.empty())
  114. {
  115. pData = &data;
  116. data.source.ptr = (void*)&request.sBuffer;
  117. data.read_callback = reqbody_read_callback;
  118. }
  119. int32_t sid = nghttp2_submit_request(session->session(),
  120. NULL,
  121. &nva[0],
  122. nva.size(),
  123. pData,
  124. NULL);
  125. if (sid < 0)
  126. {
  127. cerr << "Fatal error: nghttp2_submit_request return " << sid << endl;
  128. return "";
  129. }
  130. request.iRequestId = sid;
  131. nghttp2_session_send(session->session());
  132. // 交给tars发送
  133. std::string out;
  134. out.swap(session->sendBuffer());
  135. return out;
  136. }
  137. // ENCODE function, called by network thread
  138. void http2Request(const RequestPacket& request, std::string& out)
  139. {
  140. TC_NgHttp2* session = Http2ClientSessionManager::getInstance()->getSession(request.iRequestId);
  141. if (session->getState() == TC_NgHttp2::None)
  142. {
  143. session->Init();
  144. session->settings();
  145. }
  146. assert (session->getState() == TC_NgHttp2::Http2);
  147. out = encodeHttp2(const_cast<RequestPacket&>(request), session);
  148. }
  149. size_t http2Response(const char* recvBuffer, size_t length, list<ResponsePacket>& done, void* userptr)
  150. {
  151. const int sessionId = *(int*)&userptr;
  152. TC_NgHttp2* session = Http2ClientSessionManager::getInstance()->getSession(sessionId);
  153. assert (session->getState() == TC_NgHttp2::Http2);
  154. int readlen = nghttp2_session_mem_recv(session->session(),
  155. (const uint8_t*)recvBuffer,
  156. length);
  157. if (readlen < 0)
  158. {
  159. throw std::runtime_error("nghttp2_session_mem_recv return error");
  160. return 0;
  161. }
  162. std::map<int, Http2Response>::const_iterator it(session->_doneResponses.begin());
  163. for (; it != session->_doneResponses.end(); ++ it)
  164. {
  165. ResponsePacket rsp;
  166. rsp.iRequestId = it->second.streamId;
  167. rsp.status = it->second.headers;
  168. rsp.sBuffer.assign(it->second.body.begin(), it->second.body.end());
  169. done.push_back(rsp);
  170. }
  171. session->_doneResponses.clear();
  172. return readlen;
  173. }
  174. #endif
  175. }