UpperDistributor_admin.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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 "benc/Dict.h"
  16. #include "benc/String.h"
  17. #include "benc/List.h"
  18. #include "admin/Admin.h"
  19. #include "memory/Allocator.h"
  20. #include "net/UpperDistributor.h"
  21. #include "net/UpperDistributor_admin.h"
  22. struct Context
  23. {
  24. struct Admin* admin;
  25. struct Allocator* alloc;
  26. struct UpperDistributor* ud;
  27. Identity
  28. };
  29. static void sendError(struct Context* ctx, String* txid, struct Allocator* requestAlloc, char* err)
  30. {
  31. Dict* out = Dict_new(requestAlloc);
  32. Dict_putStringCC(out, "error", err, requestAlloc);
  33. Admin_sendMessage(out, txid, ctx->admin);
  34. }
  35. static void unregisterHandler(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  36. {
  37. struct Context* ctx = Identity_check((struct Context*) vctx);
  38. int64_t* udpPort = Dict_getIntC(args, "udpPort");
  39. char* err;
  40. if (*udpPort < 1 && *udpPort > 65536) {
  41. err = "invalid_udpPort";
  42. } else {
  43. int ret = UpperDistributor_unregisterHandler(ctx->ud, (int) *udpPort);
  44. if (!ret) {
  45. err = "none";
  46. } else if (ret == UpperDistributor_unregisterHandler_NONEXISTANT) {
  47. err = "UpperDistributor_unregisterHandler_NONEXISTANT";
  48. } else {
  49. err = "UNKNOWN";
  50. }
  51. }
  52. sendError(ctx, txid, requestAlloc, err);
  53. }
  54. #define HANDLERS_PER_PAGE 8
  55. static void listHandlers(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  56. {
  57. struct Context* ctx = Identity_check((struct Context*) vctx);
  58. int page = 0;
  59. int64_t* pageP = Dict_getIntC(args, "page");
  60. if (pageP && *pageP > 0) { page = *pageP; }
  61. struct UpperDistributor_Handler* handlers;
  62. int count = UpperDistributor_listHandlers(ctx->ud, &handlers, requestAlloc);
  63. List* handlerList = List_new(requestAlloc);
  64. for (int i = page * HANDLERS_PER_PAGE, j = 0; i < count && j < HANDLERS_PER_PAGE; i++, j++) {
  65. Dict* d = Dict_new(requestAlloc);
  66. Dict_putIntC(d, "udpPort", handlers[i].udpPort, requestAlloc);
  67. Dict_putIntC(d, "type", handlers[i].type, requestAlloc);
  68. List_addDict(handlerList, d, requestAlloc);
  69. }
  70. Dict* out = Dict_new(requestAlloc);
  71. Dict_putListC(out, "handlers", handlerList, requestAlloc);
  72. Dict_putStringCC(out, "error", "none", requestAlloc);
  73. Admin_sendMessage(out, txid, ctx->admin);
  74. }
  75. static void registerHandler(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  76. {
  77. struct Context* ctx = Identity_check((struct Context*) vctx);
  78. int64_t* udpPort = Dict_getIntC(args, "udpPort");
  79. if (*udpPort < 1 || *udpPort > 65535) {
  80. sendError(ctx, txid, requestAlloc, "invalid_udpPort");
  81. return;
  82. }
  83. int64_t* contentTypeP = Dict_getIntC(args, "contentType");
  84. if (*contentTypeP < 0 || *contentTypeP > ContentType_MAX) {
  85. sendError(ctx, txid, requestAlloc, "invalid_contentType");
  86. return;
  87. }
  88. enum ContentType ct = (enum ContentType) *contentTypeP;
  89. int ret = UpperDistributor_registerHandler(ctx->ud, ct, (int) *udpPort);
  90. if (ret < 0) {
  91. char* err = "UNKNOWN";
  92. if (ret == UpperDistributor_registerHandler_PORT_REGISTERED) {
  93. err = "UpperDistributor_registerHandler_PORT_REGISTERED";
  94. }
  95. sendError(ctx, txid, requestAlloc, err);
  96. return;
  97. }
  98. sendError(ctx, txid, requestAlloc, "none");
  99. }
  100. void UpperDistributor_admin_register(struct UpperDistributor* ud,
  101. struct Admin* admin,
  102. struct Allocator* alloc)
  103. {
  104. struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
  105. .admin = admin,
  106. .alloc = alloc,
  107. .ud = ud
  108. }));
  109. Identity_set(ctx);
  110. Admin_registerFunction("UpperDistributor_unregisterHandler", unregisterHandler, ctx, true,
  111. ((struct Admin_FunctionArg[]) {
  112. { .name = "udpPort", .required = true, .type = "Int" }
  113. }), admin);
  114. Admin_registerFunction("UpperDistributor_listHandlers", listHandlers, ctx, true,
  115. ((struct Admin_FunctionArg[]) {
  116. { .name = "page", .required = false, .type = "Int" }
  117. }), admin);
  118. Admin_registerFunction("UpperDistributor_registerHandler", registerHandler, ctx, true,
  119. ((struct Admin_FunctionArg[]) {
  120. { .name = "contentType", .required = true, .type = "Int" },
  121. { .name = "udpPort", .required = true, .type = "Int" },
  122. }), admin);
  123. }