1
0

jsonrpc_server.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 "jsonrpc.h"
  13. #include "cJSON.h"
  14. #include "router.h"
  15. #include "handler.h"
  16. // hloop_create_tcp_server -> on_accept -> hio_read -> on_recv -> hio_write
  17. static int verbose = 0;
  18. static unpack_setting_t jsonrpc_unpack_setting;
  19. jsonrpc_router router[] = {
  20. {"add", calc_add},
  21. {"sub", calc_sub},
  22. {"mul", calc_mul},
  23. {"div", calc_div},
  24. };
  25. #define JSONRPC_ROUTER_NUM (sizeof(router)/sizeof(router[0]))
  26. static void on_close(hio_t* io) {
  27. printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
  28. }
  29. static void on_recv(hio_t* io, void* readbuf, int readbytes) {
  30. // printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
  31. if (verbose) {
  32. char localaddrstr[SOCKADDR_STRLEN] = {0};
  33. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  34. printf("[%s] <=> [%s]\n",
  35. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  36. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  37. }
  38. // unpack -> cJSON_Parse -> router -> cJSON_Print -> pack -> hio_write
  39. // unpack
  40. jsonrpc_message msg;
  41. memset(&msg, 0, sizeof(msg));
  42. int packlen = jsonrpc_unpack(&msg, readbuf, readbytes);
  43. if (packlen < 0) {
  44. printf("jsonrpc_unpack failed!\n");
  45. return;
  46. }
  47. assert(packlen == readbytes);
  48. // cJSON_Parse
  49. printf("> %.*s\n", msg.head.length, msg.body);
  50. cJSON* jreq = cJSON_ParseWithLength(msg.body, msg.head.length);
  51. cJSON* jres = cJSON_CreateObject();
  52. cJSON* jid = cJSON_GetObjectItem(jreq, "id");
  53. cJSON* jmethod = cJSON_GetObjectItem(jreq, "method");
  54. if (cJSON_IsNumber(jid)) {
  55. long id = cJSON_GetNumberValue(jid);
  56. cJSON_AddItemToObject(jres, "id", cJSON_CreateNumber(id));
  57. }
  58. if (cJSON_IsString(jmethod)) {
  59. // router
  60. char* method = cJSON_GetStringValue(jmethod);
  61. bool found = false;
  62. for (int i = 0; i < JSONRPC_ROUTER_NUM; ++i) {
  63. if (strcmp(method, router[i].method) == 0) {
  64. found = true;
  65. router[i].handler(jreq, jres);
  66. break;
  67. }
  68. }
  69. if (!found) {
  70. not_found(jreq, jres);
  71. }
  72. } else {
  73. bad_request(jreq, jres);
  74. }
  75. // cJSON_Print
  76. memset(&msg, 0, sizeof(msg));
  77. msg.body = cJSON_PrintUnformatted(jres);
  78. msg.head.length = strlen(msg.body);
  79. printf("< %.*s\n", msg.head.length, msg.body);
  80. // pack
  81. packlen = jsonrpc_package_length(&msg.head);
  82. unsigned char* writebuf = NULL;
  83. HV_ALLOC(writebuf, packlen);
  84. packlen = jsonrpc_pack(&msg, writebuf, packlen);
  85. if (packlen > 0) {
  86. hio_write(io, writebuf, packlen);
  87. }
  88. cJSON_Delete(jreq);
  89. cJSON_Delete(jres);
  90. cJSON_free((void*)msg.body);
  91. HV_FREE(writebuf);
  92. }
  93. static void on_accept(hio_t* io) {
  94. printf("on_accept connfd=%d\n", hio_fd(io));
  95. if (verbose) {
  96. char localaddrstr[SOCKADDR_STRLEN] = {0};
  97. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  98. printf("accept connfd=%d [%s] <= [%s]\n", hio_fd(io),
  99. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  100. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  101. }
  102. hio_setcb_close(io, on_close);
  103. hio_setcb_read(io, on_recv);
  104. hio_set_unpack(io, &jsonrpc_unpack_setting);
  105. hio_read(io);
  106. }
  107. int main(int argc, char** argv) {
  108. if (argc < 2) {
  109. printf("Usage: %s port\n", argv[0]);
  110. return -10;
  111. }
  112. int port = atoi(argv[1]);
  113. // init jsonrpc_unpack_setting
  114. memset(&jsonrpc_unpack_setting, 0, sizeof(unpack_setting_t));
  115. jsonrpc_unpack_setting.mode = UNPACK_BY_LENGTH_FIELD;
  116. jsonrpc_unpack_setting.package_max_length = DEFAULT_PACKAGE_MAX_LENGTH;
  117. jsonrpc_unpack_setting.body_offset = JSONRPC_HEAD_LENGTH;
  118. jsonrpc_unpack_setting.length_field_offset = 1;
  119. jsonrpc_unpack_setting.length_field_bytes = 4;
  120. jsonrpc_unpack_setting.length_field_coding = ENCODE_BY_BIG_ENDIAN;
  121. hloop_t* loop = hloop_new(0);
  122. hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", port, on_accept);
  123. if (listenio == NULL) {
  124. return -20;
  125. }
  126. printf("listenfd=%d\n", hio_fd(listenio));
  127. hloop_run(loop);
  128. hloop_free(&loop);
  129. return 0;
  130. }