SupernodeHunter_admin.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. #include "benc/Dict.h"
  22. struct Context {
  23. struct Admin* admin;
  24. struct Allocator* alloc;
  25. struct SupernodeHunter* snh;
  26. Identity
  27. };
  28. static struct Address* getAddr(Dict* args, struct Allocator* alloc)
  29. {
  30. struct Address addr = {0};
  31. Bits_memset(&addr, 0, Address_SIZE);
  32. if (Key_parse(Dict_getStringC(args, "key"), addr.key, addr.ip6.bytes)) { return NULL; }
  33. return Address_clone(&addr, alloc);
  34. }
  35. static void sendError(struct Context* ctx, String* txid, struct Allocator* requestAlloc, char* err)
  36. {
  37. Dict* out = Dict_new(requestAlloc);
  38. Dict_putStringCC(out, "error", err, requestAlloc);
  39. Admin_sendMessage(out, txid, ctx->admin);
  40. }
  41. static void addSnode(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  42. {
  43. struct Context* ctx = Identity_check((struct Context*) vcontext);
  44. struct Address* addr = getAddr(args, requestAlloc);
  45. if (!addr) {
  46. sendError(ctx, txid, requestAlloc, "parse_error");
  47. return;
  48. }
  49. int ret = SupernodeHunter_addSnode(ctx->snh, addr);
  50. char* err;
  51. switch (ret) {
  52. case SupernodeHunter_addSnode_EXISTS: {
  53. err = "SupernodeHunter_addSnode_EXISTS";
  54. break;
  55. }
  56. case 0: {
  57. err = "none";
  58. break;
  59. }
  60. default: {
  61. err = "UNKNOWN";
  62. }
  63. }
  64. sendError(ctx, txid, requestAlloc, err);
  65. }
  66. static void removeSnode(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  67. {
  68. struct Context* ctx = Identity_check((struct Context*) vcontext);
  69. struct Address* addr = getAddr(args, requestAlloc);
  70. if (!addr) {
  71. sendError(ctx, txid, requestAlloc, "parse_error");
  72. return;
  73. }
  74. int ret = SupernodeHunter_removeSnode(ctx->snh, addr);
  75. char* err;
  76. switch (ret) {
  77. case SupernodeHunter_removeSnode_NONEXISTANT: {
  78. err = "SupernodeHunter_removeSnode_NONEXISTANT";
  79. break;
  80. }
  81. case 0: {
  82. err = "none";
  83. break;
  84. }
  85. default: {
  86. err = "UNKNOWN";
  87. }
  88. }
  89. sendError(ctx, txid, requestAlloc, err);
  90. }
  91. #define NODES_PER_PAGE 8
  92. static void listSnodes(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  93. {
  94. struct Context* ctx = Identity_check((struct Context*) vcontext);
  95. int page = 0;
  96. int64_t* pageP = Dict_getIntC(args, "page");
  97. if (pageP && *pageP > 0) { page = *pageP; }
  98. struct Address** snodes;
  99. int count = SupernodeHunter_listSnodes(ctx->snh, &snodes, requestAlloc);
  100. List* snodeList = List_new(requestAlloc);
  101. for (int i = page * NODES_PER_PAGE, j = 0; i < count && j < NODES_PER_PAGE; i++, j++) {
  102. List_addString(snodeList, Key_stringify(snodes[i]->key, requestAlloc), requestAlloc);
  103. }
  104. Dict* out = Dict_new(requestAlloc);
  105. Dict_putListC(out, "snodes", snodeList, requestAlloc);
  106. Dict_putStringCC(out, "error", "none", requestAlloc);
  107. Admin_sendMessage(out, txid, ctx->admin);
  108. }
  109. static void status(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
  110. {
  111. struct Context* ctx = Identity_check((struct Context*) vcontext);
  112. char* activeSnode = "NONE";
  113. Dict* out = Dict_new(requestAlloc);
  114. if (ctx->snh->snodeIsReachable) {
  115. String* as = Address_toStringKey(&ctx->snh->snodeAddr, requestAlloc);
  116. activeSnode = as->bytes;
  117. }
  118. Dict_putIntC(out, "usingAuthorizedSnode", ctx->snh->snodeIsReachable > 1, requestAlloc);
  119. Dict_putStringCC(out, "activeSnode", activeSnode, requestAlloc);
  120. Dict_putStringCC(out, "error", "none", requestAlloc);
  121. Admin_sendMessage(out, txid, ctx->admin);
  122. }
  123. void SupernodeHunter_admin_register(struct SupernodeHunter* snh,
  124. struct Admin* admin,
  125. struct Allocator* alloc)
  126. {
  127. struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
  128. .admin = admin,
  129. .alloc = alloc,
  130. .snh = snh
  131. }));
  132. Identity_set(ctx);
  133. Admin_registerFunction("SupernodeHunter_addSnode", addSnode, ctx, true,
  134. ((struct Admin_FunctionArg[]) {
  135. { .name = "key", .required = true, .type = "String" }
  136. }), admin);
  137. Admin_registerFunction("SupernodeHunter_listSnodes", listSnodes, ctx, false,
  138. ((struct Admin_FunctionArg[]) {
  139. { .name = "page", .required = false, .type = "Int" }
  140. }), admin);
  141. Admin_registerFunction("SupernodeHunter_removeSnode", removeSnode, ctx, true,
  142. ((struct Admin_FunctionArg[]) {
  143. { .name = "key", .required = true, .type = "String" }
  144. }), admin);
  145. Admin_registerFunction("SupernodeHunter_status", status, ctx, false, NULL, admin);
  146. }