jsonrpc_server.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * json rpc server
  3. *
  4. * @build make jsonrpc
  5. * @server bin/jsonrpc_server 1234
  6. * @client bin/jsonrpc_client 127.0.0.1 1234 add 1 2
  7. *
  8. */
  9. #include "hloop.h"
  10. #include "hbase.h"
  11. #include "hsocket.h"
  12. #include "cJSON.h"
  13. #include "router.h"
  14. #include "handler.h"
  15. // hloop_create_tcp_server -> on_accept -> hio_read -> on_recv -> hio_write
  16. static int verbose = 0;
  17. static unpack_setting_t jsonrpc_unpack_setting;
  18. jsonrpc_router router[] = {
  19. {"add", calc_add},
  20. {"sub", calc_sub},
  21. {"mul", calc_mul},
  22. {"div", calc_div},
  23. };
  24. #define JSONRPC_ROUTER_NUM (sizeof(router)/sizeof(router[0]))
  25. static void on_close(hio_t* io) {
  26. printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
  27. }
  28. static void on_recv(hio_t* io, void* readbuf, int readbytes) {
  29. // printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
  30. if (verbose) {
  31. char localaddrstr[SOCKADDR_STRLEN] = {0};
  32. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  33. printf("[%s] <=> [%s]\n",
  34. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  35. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  36. }
  37. // cJSON_Parse -> router -> cJSON_Print -> hio_write
  38. char* req_str = (char*)readbuf;
  39. printf("> %s\n", req_str);
  40. cJSON* jreq = cJSON_Parse(req_str);
  41. cJSON* jres = cJSON_CreateObject();
  42. cJSON* jid = cJSON_GetObjectItem(jreq, "id");
  43. cJSON* jmethod = cJSON_GetObjectItem(jreq, "method");
  44. if (cJSON_IsNumber(jid)) {
  45. long id = cJSON_GetNumberValue(jid);
  46. cJSON_AddItemToObject(jres, "id", cJSON_CreateNumber(id));
  47. }
  48. if (cJSON_IsString(jmethod)) {
  49. // router
  50. char* method = cJSON_GetStringValue(jmethod);
  51. bool found = false;
  52. for (int i = 0; i < JSONRPC_ROUTER_NUM; ++i) {
  53. if (strcmp(method, router[i].method) == 0) {
  54. found = true;
  55. router[i].handler(jreq, jres);
  56. break;
  57. }
  58. }
  59. if (!found) {
  60. not_found(jreq, jres);
  61. }
  62. } else {
  63. bad_request(jreq, jres);
  64. }
  65. char* resp_str = cJSON_PrintUnformatted(jres);
  66. printf("< %s\n", resp_str);
  67. // NOTE: +1 for \0
  68. hio_write(io, resp_str, strlen(resp_str) + 1);
  69. cJSON_Delete(jreq);
  70. cJSON_Delete(jres);
  71. cJSON_free(resp_str);
  72. }
  73. static void on_accept(hio_t* io) {
  74. printf("on_accept connfd=%d\n", hio_fd(io));
  75. if (verbose) {
  76. char localaddrstr[SOCKADDR_STRLEN] = {0};
  77. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  78. printf("accept connfd=%d [%s] <= [%s]\n", hio_fd(io),
  79. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  80. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  81. }
  82. hio_setcb_close(io, on_close);
  83. hio_setcb_read(io, on_recv);
  84. hio_set_unpack(io, &jsonrpc_unpack_setting);
  85. hio_read(io);
  86. }
  87. int main(int argc, char** argv) {
  88. if (argc < 2) {
  89. printf("Usage: %s port\n", argv[0]);
  90. return -10;
  91. }
  92. int port = atoi(argv[1]);
  93. // init jsonrpc_unpack_setting
  94. memset(&jsonrpc_unpack_setting, 0, sizeof(unpack_setting_t));
  95. jsonrpc_unpack_setting.mode = UNPACK_BY_DELIMITER;
  96. jsonrpc_unpack_setting.package_max_length = DEFAULT_PACKAGE_MAX_LENGTH;
  97. jsonrpc_unpack_setting.delimiter[0] = '\0';
  98. jsonrpc_unpack_setting.delimiter_bytes = 1;
  99. hloop_t* loop = hloop_new(0);
  100. hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", port, on_accept);
  101. if (listenio == NULL) {
  102. return -20;
  103. }
  104. printf("listenfd=%d\n", hio_fd(listenio));
  105. hloop_run(loop);
  106. hloop_free(&loop);
  107. return 0;
  108. }