srpc_proxy_controller.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. Copyright (c) 2022 Sogou, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string>
  16. #include <string.h>
  17. #include <sys/stat.h>
  18. #include <sys/types.h>
  19. #include <dirent.h>
  20. #include <fcntl.h>
  21. #include <unordered_map>
  22. #include "srpc_controller.h"
  23. static std::string default_server_port(uint8_t type)
  24. {
  25. if (type == PROTOCOL_TYPE_HTTP)
  26. return "8080";
  27. if (type == PROTOCOL_TYPE_REDIS)
  28. return "6379";
  29. if (type == PROTOCOL_TYPE_MYSQL)
  30. return "3306";
  31. // Add other protocol here
  32. return "1412";
  33. }
  34. static std::string default_proxy_port(uint8_t type)
  35. {
  36. if (type == PROTOCOL_TYPE_HTTP)
  37. return "8888";
  38. if (type == PROTOCOL_TYPE_REDIS)
  39. return "6378";
  40. if (type == PROTOCOL_TYPE_MYSQL)
  41. return "3305";
  42. // Add other protocol here
  43. return "1411";
  44. }
  45. static std::string proxy_process_request_codes(uint8_t server_type,
  46. uint8_t client_type)
  47. {
  48. if (server_type == client_type)
  49. return std::string(R"(
  50. *client_task->get_req() = std::move(*req);
  51. )");
  52. else
  53. return std::string(R"( {
  54. // TODO: fill the client request to server request
  55. }
  56. )");
  57. }
  58. static std::string proxy_callback_response_codes(uint8_t server_type,
  59. uint8_t client_type)
  60. {
  61. if (server_type != client_type)
  62. return std::string(R"(
  63. {
  64. // TODO: fill the server response to client response
  65. }
  66. )");
  67. if (server_type == PROTOCOL_TYPE_HTTP)
  68. return std::string(R"(
  69. {
  70. const void *body;
  71. size_t len;
  72. resp->get_parsed_body(&body, &len);
  73. resp->append_output_body_nocopy(body, len);
  74. *proxy_resp = std::move(*resp);
  75. }
  76. else
  77. {
  78. proxy_resp->set_status_code("404");
  79. proxy_resp->append_output_body_nocopy(
  80. "<html>404 Not Found.</html>", 27);
  81. }
  82. )");
  83. return std::string(R"(
  84. *proxy_resp = std::move(*resp);
  85. )");
  86. }
  87. static std::string proxy_redirect_codes(uint8_t type)
  88. {
  89. if (type == PROTOCOL_TYPE_HTTP)
  90. return std::string(R"(
  91. config.redirect_max(),)");
  92. return std::string("");
  93. }
  94. static bool proxy_basic_transform(const std::string& format, FILE *out,
  95. const struct srpc_config *config)
  96. {
  97. const char *server_type = config->proxy_server_type_string();
  98. const char *client_type = config->proxy_client_type_string();
  99. std::string server_lower = server_type;
  100. std::transform(server_lower.begin(), server_lower.end(),
  101. server_lower.begin(), ::tolower);
  102. std::string server_port = default_server_port(config->proxy_server_type);
  103. std::string proxy_port = default_proxy_port(config->proxy_client_type);
  104. size_t len = fprintf(out, format.c_str(), client_type, server_type,
  105. server_type, client_type, client_type,
  106. proxy_callback_response_codes(config->proxy_server_type,
  107. config->proxy_client_type).c_str(),
  108. // process
  109. client_type, client_type, server_lower.c_str(),
  110. server_type, server_lower.c_str(),
  111. proxy_redirect_codes(config->proxy_server_type).c_str(),
  112. proxy_process_request_codes(config->proxy_server_type,
  113. config->proxy_client_type).c_str(),
  114. // main
  115. client_type, server_type, client_type);
  116. return len > 0;
  117. }
  118. static bool proxy_config_transform(const std::string& format, FILE *out,
  119. const struct srpc_config *config)
  120. {
  121. std::string server_port = default_server_port(config->proxy_server_type);
  122. std::string proxy_port = default_proxy_port(config->proxy_client_type);
  123. size_t len = fprintf(out, format.c_str(),
  124. proxy_port.c_str(), server_port.c_str());
  125. return len > 0;
  126. }
  127. static bool proxy_rpc_proxy_transform(const std::string& format, FILE *out,
  128. const struct srpc_config *config)
  129. {
  130. const char *server_type = config->proxy_server_type_string();
  131. const char *client_type = config->proxy_client_type_string();
  132. size_t len = fprintf(out, format.c_str(),
  133. config->project_name, // not support specified idl file
  134. config->project_name, config->project_name,
  135. config->project_name, server_type,
  136. // main
  137. client_type, config->project_name,
  138. client_type, server_type);
  139. return len > 0;
  140. }
  141. ProxyController::ProxyController()
  142. {
  143. this->config.type = COMMAND_PROXY;
  144. this->config.proxy_client_type = PROTOCOL_TYPE_HTTP;
  145. this->config.proxy_server_type = PROTOCOL_TYPE_HTTP;
  146. struct file_info info;
  147. info = { "proxy/proxy.conf", "proxy.conf", proxy_config_transform };
  148. this->default_files.push_back(info);
  149. info = { "basic/server.conf", "server.conf", basic_server_config_transform };
  150. this->default_files.push_back(info);
  151. info = { "basic/client.conf", "client.conf", basic_client_config_transform };
  152. this->default_files.push_back(info);
  153. info = { "common/GNUmakefile", "GNUmakefile", nullptr };
  154. this->default_files.push_back(info);
  155. info = { "config/Json.h", "config/Json.h", nullptr };
  156. this->default_files.push_back(info);
  157. info = { "config/Json.cc", "config/Json.cc", nullptr };
  158. this->default_files.push_back(info);
  159. }
  160. void ProxyController::print_usage(const char *name) const
  161. {
  162. printf(COLOR_PINK"Usage:\n"
  163. COLOR_INFO" %s " COLOR_BLUE "proxy "
  164. COLOR_INFO "<PROJECT_NAME>" COLOR_FLAG " [FLAGS]\n\n"
  165. COLOR_PINK"Example:\n"
  166. COLOR_PURPLE" %s proxy my_proxy_project\n\n"
  167. COLOR_PINK"Available Flags:\n"
  168. COLOR_FLAG" -c :"
  169. COLOR_WHITE" client type for proxy [ Http | Redis | SRPC | SRPCHttp"
  170. " | BRPC | Thrift | ThriftHttp | TRPC | TRPCHttp ] (default: Http)\n"
  171. COLOR_FLAG" -s :"
  172. COLOR_WHITE" server type for proxy [ Http | Redis | SRPC | SRPCHttp"
  173. " | BRPC | Thrift | ThriftHttp | TRPC | TRPCHttp ] (default: Http)\n"
  174. COLOR_FLAG" -o :"
  175. COLOR_WHITE" project output path (default: CURRENT_PATH)\n"
  176. COLOR_FLAG" -d :"
  177. COLOR_WHITE" path of dependencies (default: COMPILE_PATH)\n"
  178. COLOR_OFF, name, name);
  179. }
  180. void ProxyController::print_success_info() const
  181. {
  182. printf(COLOR_GREEN"Success:\n make project path "
  183. COLOR_BLUE" %s " COLOR_GREEN " done.\n\n" COLOR_OFF,
  184. this->config.output_path);
  185. printf(COLOR_PINK"Commands:\n"
  186. COLOR_BLUE " cd %s\n make -j\n\n" COLOR_OFF,
  187. this->config.output_path);
  188. printf(COLOR_PINK"Execute:\n"
  189. COLOR_GREEN" ./server\n ./proxy\n ./client\n\n" COLOR_OFF);
  190. }
  191. bool ProxyController::copy_files()
  192. {
  193. struct file_info info;
  194. if (check_proxy_type(this->config.proxy_client_type) == PROXY_BASIC_TYPE &&
  195. check_proxy_type(this->config.proxy_server_type) == PROXY_BASIC_TYPE)
  196. {
  197. info = { "common/CMakeLists.txt", "CMakeLists.txt", common_cmake_transform };
  198. this->default_files.push_back(info);
  199. info = { "common/util.h", "config/util.h", nullptr };
  200. this->default_files.push_back(info);
  201. info = { "proxy/proxy_main.cc", "proxy_main.cc", proxy_basic_transform };
  202. this->default_files.push_back(info);
  203. info = { "basic/client_main.cc", "client_main.cc", basic_client_transform };
  204. this->default_files.push_back(info);
  205. info = { "basic/server_main.cc", "server_main.cc", basic_server_transform };
  206. this->default_files.push_back(info);
  207. info = { "config/config_simple.h", "config/config.h", nullptr };
  208. this->default_files.push_back(info);
  209. info = { "config/config_simple.cc", "config/config.cc", nullptr };
  210. this->default_files.push_back(info);
  211. }
  212. else
  213. {
  214. std::string proxy_main = "proxy/proxy_main_";
  215. if (this->config.idl_type == IDL_TYPE_PROTOBUF)
  216. proxy_main += "proto.cc";
  217. else
  218. proxy_main += "thrift.cc";
  219. info = { std::move(proxy_main), "proxy_main.cc", proxy_rpc_proxy_transform };
  220. this->default_files.push_back(info);
  221. info = { "rpc/CMakeLists.txt", "CMakeLists.txt", rpc_cmake_transform };
  222. this->default_files.push_back(info);
  223. info = { "config/config_full.h", "config/config.h", nullptr };
  224. this->default_files.push_back(info);
  225. info = { "config/config_full.cc", "config/config.cc", nullptr };
  226. this->default_files.push_back(info);
  227. if (this->config.specified_idl_file == NULL)
  228. this->fill_rpc_default_files();
  229. else
  230. return false; // TODO: NOT supported yet
  231. }
  232. return CommandController::copy_files();
  233. }
  234. static uint8_t proxy_string_to_type(const char *type)
  235. {
  236. if (strcasecmp(type, "http") == 0)
  237. return PROTOCOL_TYPE_HTTP;
  238. else if (strcasecmp(type, "redis") == 0)
  239. return PROTOCOL_TYPE_REDIS;
  240. else if (strcasecmp(type, "mysql") == 0)
  241. return PROTOCOL_TYPE_MYSQL;
  242. else if (strcasecmp(type, "kafka") == 0)
  243. return PROTOCOL_TYPE_KAFKA;
  244. else if (strcasecmp(type, "SRPC") == 0)
  245. return PROTOCOL_TYPE_SRPC;
  246. else if (strcasecmp(type, "SRPCHttp") == 0)
  247. return PROTOCOL_TYPE_SRPC_HTTP;
  248. else if (strcasecmp(type, "BRPC") == 0)
  249. return PROTOCOL_TYPE_BRPC;
  250. else if (strcasecmp(type, "TRPC") == 0)
  251. return PROTOCOL_TYPE_TRPC;
  252. else if (strcasecmp(type, "TRPCHttp") == 0)
  253. return PROTOCOL_TYPE_TRPC_HTTP;
  254. else if (strcasecmp(type, "Thrift") == 0)
  255. return PROTOCOL_TYPE_THRIFT;
  256. else if (strcasecmp(type, "ThriftHTTP") == 0)
  257. return PROTOCOL_TYPE_THRIFT_HTTP;
  258. return PROTOCOL_TYPE_MAX;
  259. }
  260. static bool proxy_get_opt(int argc, const char **argv, struct srpc_config *config)
  261. {
  262. int c;
  263. while ((c = getopt(argc, (char * const *)argv, "o:c:s:d:")) >= 0)
  264. {
  265. switch (c)
  266. {
  267. case 'o':
  268. if (sscanf(optarg, "%s", config->output_path) != 1)
  269. return false;
  270. break;
  271. case 'c':
  272. config->proxy_client_type = proxy_string_to_type(optarg);
  273. break;
  274. case 's':
  275. config->proxy_server_type = proxy_string_to_type(optarg);
  276. break;
  277. case 'd':
  278. config->specified_depend_path = true;
  279. memset(config->depend_path, 0, MAXPATHLEN);
  280. if (sscanf(optarg, "%s", config->depend_path) != 1)
  281. return false;
  282. break;
  283. default:
  284. printf(COLOR_RED"Error:\n Unknown args : "
  285. COLOR_BLUE"%s\n\n" COLOR_OFF, argv[optind - 1]);
  286. return false;
  287. }
  288. }
  289. return true;
  290. }
  291. bool ProxyController::get_opt(int argc, const char **argv)
  292. {
  293. optind = 2;
  294. getcwd(this->config.output_path, MAXPATHLEN);
  295. if (proxy_get_opt(argc, argv, &this->config) == false)
  296. return false;
  297. if (optind == argc)
  298. {
  299. printf(COLOR_RED "Missing: PROJECT_NAME\n\n" COLOR_OFF);
  300. return false;
  301. }
  302. this->config.project_name = argv[optind];
  303. optind++;
  304. if (proxy_get_opt(argc, argv, &this->config) == false)
  305. return false;
  306. if (this->config.project_name == NULL)
  307. {
  308. printf(COLOR_RED "Missing: PROJECT_NAME\n\n" COLOR_OFF);
  309. return false;
  310. }
  311. this->config.service_name = this->config.project_name;
  312. return true;
  313. }
  314. bool ProxyController::check_args()
  315. {
  316. int server_type = check_proxy_type(this->config.proxy_server_type);
  317. int client_type = check_proxy_type(this->config.proxy_client_type);
  318. if (CommandController::check_args() == false)
  319. return false;
  320. if (client_type < 0 || server_type < 0)
  321. {
  322. printf(COLOR_RED"Error:\n Invalid type :"
  323. COLOR_BLUE" %s" COLOR_RED ", " COLOR_BLUE "%s\n\n" COLOR_OFF,
  324. this->config.proxy_server_type_string(),
  325. this->config.proxy_client_type_string());
  326. return false;
  327. }
  328. if ((client_type == PROXY_BASIC_TYPE && server_type > PROXY_BASIC_TYPE) ||
  329. (server_type == PROXY_BASIC_TYPE && client_type > PROXY_BASIC_TYPE) ||
  330. // TODO: temperarily only support workflow to workflow, rpc to rpc
  331. (client_type == PROXY_PROTOBUF_TYPE && server_type == PROXY_THRIFT_TYPE) ||
  332. (server_type == PROXY_PROTOBUF_TYPE && client_type == PROXY_THRIFT_TYPE))
  333. // TODO: temperarily NOT support protobuf with thrift
  334. {
  335. printf(COLOR_RED"Error:\n Temperarily not support "
  336. COLOR_BLUE"%s" COLOR_RED " and " COLOR_BLUE "%s"
  337. COLOR_RED" together\n\n" COLOR_OFF,
  338. this->config.proxy_server_type_string(),
  339. this->config.proxy_client_type_string());
  340. return false;
  341. }
  342. if (client_type == PROXY_PROTOBUF_TYPE)
  343. {
  344. this->config.idl_type = IDL_TYPE_PROTOBUF;
  345. }
  346. else if (client_type == PROXY_THRIFT_TYPE)
  347. {
  348. // this->config.idl_type = IDL_TYPE_THRIFT;
  349. printf(COLOR_RED"Error:\n Temperarily not support IDL thrift.\n\n" COLOR_OFF);
  350. return false;
  351. }
  352. return true;
  353. }