SupernodeHunter_admin.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "admin/Admin.h"
  16. #include "benc/List.h"
  17. #include "crypto/Key.h"
  18. #include "subnode/SupernodeHunter.h"
  19. #include "subnode/SupernodeHunter_admin.h"
  20. #include "util/Identity.h"
  21. struct Context {
  22. struct Admin* admin;
  23. struct Allocator* alloc;
  24. struct SupernodeHunter* snh;
  25. Identity
  26. };
  27. static struct Address* getAddr(Dict* args, struct Allocator* alloc)
  28. {
  29. struct Address addr;
  30. Bits_memset(&addr, 0, Address_SIZE);
  31. if (Key_parse(Dict_getStringC(args, "key"), addr.key, addr.ip6.bytes)) { return NULL; }
  32. return Address_clone(&addr, alloc);
  33. }
  34. static void sendError(struct Context* ctx, String* txid, struct Allocator* requestAlloc, char* err)
  35. {
  36. Dict* out = Dict_new(requestAlloc);
  37. Dict_putStringCC(out, "error", err, requestAlloc);
  38. Admin_sendMessage(out, txid, ctx->admin);
  39. }
  40. static void addSnode(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  41. {
  42. struct Context* ctx = Identity_check((struct Context*) vcontext);
  43. struct Address* addr = getAddr(args, requestAlloc);
  44. if (!addr) {
  45. sendError(ctx, txid, requestAlloc, "parse_error");
  46. return;
  47. }
  48. int ret = SupernodeHunter_addSnode(ctx->snh, addr);
  49. char* err;
  50. switch (ret) {
  51. case SupernodeHunter_addSnode_EXISTS: {
  52. err = "SupernodeHunter_addSnode_EXISTS";
  53. break;
  54. }
  55. case 0: {
  56. err = "none";
  57. break;
  58. }
  59. default: {
  60. err = "UNKNOWN";
  61. }
  62. }
  63. sendError(ctx, txid, requestAlloc, err);
  64. }
  65. static void removeSnode(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  66. {
  67. struct Context* ctx = Identity_check((struct Context*) vcontext);
  68. struct Address* addr = getAddr(args, requestAlloc);
  69. if (!addr) {
  70. sendError(ctx, txid, requestAlloc, "parse_error");
  71. return;
  72. }
  73. int ret = SupernodeHunter_removeSnode(ctx->snh, addr);
  74. char* err;
  75. switch (ret) {
  76. case SupernodeHunter_removeSnode_NONEXISTANT: {
  77. err = "SupernodeHunter_removeSnode_NONEXISTANT";
  78. break;
  79. }
  80. case 0: {
  81. err = "none";
  82. break;
  83. }
  84. default: {
  85. err = "UNKNOWN";
  86. }
  87. }
  88. sendError(ctx, txid, requestAlloc, err);
  89. }
  90. #define NODES_PER_PAGE 8
  91. static void listSnodes(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  92. {
  93. struct Context* ctx = Identity_check((struct Context*) vcontext);
  94. int page = 0;
  95. int64_t* pageP = Dict_getIntC(args, "page");
  96. if (pageP && *pageP > 0) { page = *pageP; }
  97. struct Address** snodes;
  98. int count = SupernodeHunter_listSnodes(ctx->snh, &snodes, requestAlloc);
  99. List* snodeList = List_new(requestAlloc);
  100. for (int i = page * NODES_PER_PAGE, j = 0; i < count && j < NODES_PER_PAGE; i++, j++) {
  101. List_addString(snodeList, Key_stringify(snodes[i]->key, requestAlloc), requestAlloc);
  102. }
  103. Dict* out = Dict_new(requestAlloc);
  104. Dict_putListC(out, "snodes", snodeList, requestAlloc);
  105. Dict_putStringCC(out, "error", "none", requestAlloc);
  106. Admin_sendMessage(out, txid, ctx->admin);
  107. }
  108. static void status(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  109. {
  110. struct Context* ctx = Identity_check((struct Context*) vcontext);
  111. char* activeSnode = "NONE";
  112. Dict* out = Dict_new(requestAlloc);
  113. if (ctx->snh->snodeIsReachable) {
  114. String* as = Address_toStringKey(&ctx->snh->snodeAddr, requestAlloc);
  115. activeSnode = as->bytes;
  116. }
  117. Dict_putIntC(out, "usingAuthorizedSnode", ctx->snh->snodeIsReachable > 1, requestAlloc);
  118. Dict_putStringCC(out, "activeSnode", activeSnode, requestAlloc);
  119. Dict_putStringCC(out, "error", "none", requestAlloc);
  120. Admin_sendMessage(out, txid, ctx->admin);
  121. }
  122. void SupernodeHunter_admin_register(struct SupernodeHunter* snh,
  123. struct Admin* admin,
  124. struct Allocator* alloc)
  125. {
  126. struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
  127. .admin = admin,
  128. .alloc = alloc,
  129. .snh = snh
  130. }));
  131. Identity_set(ctx);
  132. Admin_registerFunction("SupernodeHunter_addSnode", addSnode, ctx, true,
  133. ((struct Admin_FunctionArg[]) {
  134. { .name = "key", .required = true, .type = "String" }
  135. }), admin);
  136. Admin_registerFunction("SupernodeHunter_listSnodes", listSnodes, ctx, false,
  137. ((struct Admin_FunctionArg[]) {
  138. { .name = "page", .required = false, .type = "Int" }
  139. }), admin);
  140. Admin_registerFunction("SupernodeHunter_removeSnode", removeSnode, ctx, true,
  141. ((struct Admin_FunctionArg[]) {
  142. { .name = "key", .required = true, .type = "String" }
  143. }), admin);
  144. Admin_registerFunction("SupernodeHunter_status", status, ctx, false, NULL, admin);
  145. }