AdminTestFramework.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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 <http://www.gnu.org/licenses/>.
  14. */
  15. #include "admin/Admin.h"
  16. #include "admin/AdminClient.h"
  17. #include "admin/angel/AngelInit.h"
  18. #include "admin/angel/InterfaceWaiter.h"
  19. #include "admin/testframework/AdminTestFramework.h"
  20. #include "benc/String.h"
  21. #include "benc/Int.h"
  22. #include "benc/serialization/BencSerializer.h"
  23. #include "benc/serialization/standard/StandardBencSerializer.h"
  24. #include "crypto/random/Random.h"
  25. #include "memory/Allocator.h"
  26. #include "memory/MallocAllocator.h"
  27. #include "memory/BufferAllocator.h"
  28. #include "interface/FramingInterface.h"
  29. #include "interface/addressable/UDPAddrInterface.h"
  30. #include "io/ArrayReader.h"
  31. #include "io/ArrayWriter.h"
  32. #include "io/FileWriter.h"
  33. #include "io/Writer.h"
  34. #include "util/events/EventBase.h"
  35. #include "util/events/Pipe.h"
  36. #include "util/events/Process.h"
  37. #include "util/Assert.h"
  38. #include "util/log/Log.h"
  39. #include "util/log/WriterLog.h"
  40. #define string_strlen
  41. #define string_strchr
  42. #define string_strcmp
  43. #include "util/platform/libc/string.h"
  44. #include <unistd.h>
  45. #include <stdlib.h>
  46. static void spawnAngel(char* asClientPipeName, struct EventBase* base, struct Allocator* alloc)
  47. {
  48. char* args[] = { "angel", asClientPipeName, NULL };
  49. uint8_t allocBuff[1024];
  50. struct Allocator* tempAlloc = BufferAllocator_new(allocBuff, 1024);
  51. char* path = Process_getPath(tempAlloc);
  52. Assert_true(path);
  53. Process_spawn(path, args, base, alloc);
  54. }
  55. /** @return a string representing the address and port to connect to. */
  56. static void initAngel(struct Pipe* asClientPipe,
  57. struct Interface* asCoreIface,
  58. char* asCorePipeName,
  59. struct EventBase* eventBase,
  60. struct Log* logger,
  61. struct Allocator* alloc,
  62. struct Random* rand)
  63. {
  64. Dict admin = Dict_CONST(
  65. String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST(
  66. String_CONST("corePipeName"), String_OBJ(String_CONST(asCorePipeName)), Dict_CONST(
  67. String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL
  68. )));
  69. Dict message = Dict_CONST(
  70. String_CONST("admin"), Dict_OBJ(&admin), NULL
  71. );
  72. struct Allocator* tempAlloc = Allocator_child(alloc);
  73. #define BUFFER_SZ 1023
  74. uint8_t buff[BUFFER_SZ + 1] = {0};
  75. struct Writer* w = ArrayWriter_new(buff, BUFFER_SZ, tempAlloc);
  76. StandardBencSerializer_get()->serializeDictionary(w, &message);
  77. struct Message* toAngel = Allocator_malloc(tempAlloc, sizeof(struct Message) + w->bytesWritten);
  78. toAngel->bytes = (uint8_t*) (&toAngel[1]);
  79. toAngel->length = toAngel->capacity = w->bytesWritten;
  80. toAngel->padding = 0;
  81. toAngel->alloc = tempAlloc;
  82. Bits_memcpy(toAngel->bytes, buff, toAngel->length);
  83. Log_info(logger, "Writing intial configuration to angel on [%s] config: [%s]",
  84. asClientPipe->name, buff);
  85. Interface_sendMessage(&asClientPipe->iface, toAngel);
  86. // This is client->angel->core data, we can throw this away.
  87. struct Message* angelToCore =
  88. InterfaceWaiter_waitForData(asCoreIface, eventBase, tempAlloc, NULL);
  89. // unterminated string
  90. Log_info(logger, "Init message from angel to core: [%s]", angelToCore->bytes);
  91. // Send response on behalf of core.
  92. char* coreToAngelResponse = " PADDING "
  93. "d"
  94. "5:error" "4:none"
  95. "e";
  96. struct Message* m = &(struct Message) {
  97. .bytes = (uint8_t*) coreToAngelResponse,
  98. .length = strlen(coreToAngelResponse),
  99. .padding = 0,
  100. .capacity = strlen(coreToAngelResponse)
  101. };
  102. Message_shift(m, -24);
  103. m = Message_clone(m, tempAlloc);
  104. Interface_sendMessage(asCoreIface, m);
  105. // This is angel->client data, it will tell us which port was bound.
  106. struct Message* angelToClient =
  107. InterfaceWaiter_waitForData(&asClientPipe->iface, eventBase, tempAlloc, NULL);
  108. printf("Response from angel to client: [%s]\n", angelToClient->bytes);
  109. Allocator_free(tempAlloc);
  110. return;
  111. }
  112. /**
  113. * This spawns itself as the Angel process which spawns itself again as the core process.
  114. * The "core process" pipes all of its inputs back to the originating process
  115. */
  116. struct AdminTestFramework* AdminTestFramework_setUp(int argc, char** argv)
  117. {
  118. if (argc > 1 && !strcmp("angel", argv[1])) {
  119. exit(AngelInit_main(argc, argv));
  120. }
  121. struct Allocator* alloc = MallocAllocator_new(1<<20);
  122. struct Writer* logwriter = FileWriter_new(stdout, alloc);
  123. Assert_always(logwriter);
  124. struct Log* logger = WriterLog_new(logwriter, alloc);
  125. struct EventBase* eventBase = EventBase_new(alloc);
  126. struct Random* rand = Random_new(alloc, logger, NULL);
  127. char asClientPipeName[32] = {0};
  128. Random_base32(rand, (uint8_t*)asClientPipeName, 31);
  129. struct Pipe* asClientPipe = Pipe_named(asClientPipeName, eventBase, NULL, alloc);
  130. asClientPipe->logger = logger;
  131. char asCorePipeName[32] = {0};
  132. Random_base32(rand, (uint8_t*)asCorePipeName, 31);
  133. struct Pipe* asCorePipe = Pipe_named(asCorePipeName, eventBase, NULL, alloc);
  134. asCorePipe->logger = logger;
  135. struct Interface* asCoreIface = FramingInterface_new(65535, &asCorePipe->iface, alloc);
  136. spawnAngel(asClientPipeName, eventBase, alloc);
  137. Log_info(logger, "Initializing Angel");
  138. initAngel(asClientPipe, asCoreIface, (char*)asCorePipe->name, eventBase, logger, alloc, rand);
  139. struct Sockaddr_storage addr;
  140. Assert_true(!Sockaddr_parse("127.0.0.1", &addr));
  141. Log_info(logger, "Binding UDP admin socket");
  142. struct AddrInterface* udpAdmin =
  143. UDPAddrInterface_new(eventBase, &addr.addr, alloc, NULL, logger);
  144. String* password = String_new("abcd", alloc);
  145. struct Admin* admin = Admin_new(udpAdmin, alloc, logger, eventBase, password);
  146. // Now setup the client.
  147. struct AdminClient* client =
  148. AdminClient_new(udpAdmin->addr, password, eventBase, logger, alloc);
  149. Assert_always(client);
  150. return Allocator_clone(alloc, (&(struct AdminTestFramework) {
  151. .admin = admin,
  152. .client = client,
  153. .alloc = alloc,
  154. .eventBase = eventBase,
  155. .logger = logger,
  156. .addr = Sockaddr_clone(udpAdmin->addr, alloc),
  157. .angelInterface = asCoreIface
  158. }));
  159. }
  160. void AdminTestFramework_tearDown(struct AdminTestFramework* framework)
  161. {
  162. char buff[128] = " PADDING "
  163. "d"
  164. "1:q" "10:Angel_exit"
  165. "e";
  166. char* start = strchr(buff, 'd');
  167. struct Message m = {
  168. .bytes = (uint8_t*) start,
  169. .length = strlen(start),
  170. .padding = start - buff
  171. };
  172. struct Message* mp = Message_clone(&m, framework->alloc);
  173. Interface_sendMessage(framework->angelInterface, mp);
  174. Allocator_free(framework->alloc);
  175. }