Moontalk server and client (provided by many parties)
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

253 líneas
8.6KB

  1. /* moontalk-imgui.cpp - Dear ImGui frontend
  2. * written by an Anon. https://boards.4chan.org/g/thread/98813374#p98826333
  3. */
  4. #include <imgui.h>
  5. #include <imgui_stdlib.h>
  6. #include <imgui_impl_sdl2.h>
  7. #include <imgui_impl_sdlrenderer2.h>
  8. #include <SDL.h>
  9. #include <arpa/inet.h>
  10. #include <netdb.h>
  11. #include <netinet/in.h>
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <err.h>
  15. #include <stdio.h>
  16. #include <unistd.h>
  17. #include <vector>
  18. #include <string>
  19. #include <thread>
  20. #include <mutex>
  21. #include <queue>
  22. #define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
  23. #define PORT "50000"
  24. static int moontalk_fd = -1;
  25. static std::mutex inqueue_lock;
  26. static std::queue<std::string> inqueue;
  27. static std::vector<std::string> moontalk_lines;
  28. int tcp_connect(const char* addr, const char *port)
  29. {
  30. struct addrinfo hints;
  31. memset(&hints, 0, sizeof(struct addrinfo));
  32. hints.ai_family = AF_UNSPEC;
  33. hints.ai_socktype = SOCK_STREAM;
  34. struct addrinfo* res;
  35. int status = getaddrinfo(addr, port, &hints, &res);
  36. if (status != 0)
  37. errx(1, "getaddrinfo: %s", gai_strerror(status));
  38. int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  39. if (fd < 0)
  40. err(1, "socket");
  41. if (connect(fd, res->ai_addr, res->ai_addrlen))
  42. err(1, "socket");
  43. freeaddrinfo(res);
  44. return fd;
  45. }
  46. void moontalk_send(const std::string& line)
  47. {
  48. char timebuf[256];
  49. time_t t = time(NULL);;
  50. struct tm * tm;
  51. tm = gmtime(&t);
  52. strftime(timebuf, sizeof(timebuf), "<%Y/%m/%d %H:%M:%S ", tm);
  53. std::string out;
  54. out += timebuf;
  55. out += line;
  56. if (line.at(line.size()-1) != '\n') out.push_back('\n');
  57. send(moontalk_fd, out.data(), out.size(), 0);
  58. printf("send %s", out.c_str());
  59. }
  60. void read_loop()
  61. {
  62. char buffer[4096];
  63. size_t pos = 0;
  64. for (;;) {
  65. ssize_t r = read(moontalk_fd, buffer + pos, sizeof(buffer) - pos);
  66. if (r < 0) {
  67. if (r == EINTR)
  68. continue;
  69. err(1, "read");
  70. }
  71. pos += r;
  72. // scan lines and push them to inqueue
  73. size_t start = 0;
  74. size_t end = 0;
  75. while (end < pos) {
  76. if (buffer[end] == '\n') {
  77. std::string line = {buffer + start, buffer + end+1};
  78. inqueue_lock.lock();
  79. inqueue.push(std::move(line));
  80. inqueue_lock.unlock();
  81. start = end+1;
  82. end = end+1;
  83. } else {
  84. end++;
  85. }
  86. }
  87. if (start != 0) {
  88. memmove(buffer, buffer+start, pos-start);
  89. pos -= start;
  90. }
  91. }
  92. }
  93. void ui()
  94. {
  95. static std::string input;
  96. if (ImGui::Begin("Chat")) {
  97. for (auto& line : moontalk_lines) {
  98. ImGui::TextUnformatted(line.c_str());
  99. }
  100. ImGui::End();
  101. }
  102. if (ImGui::Begin("Input")) {
  103. ImGui::InputText("Input", &input);
  104. if (ImGui::Button("Send")) {
  105. moontalk_send(input);
  106. input.clear();
  107. }
  108. // TODO or make it separate window and handle the layout on docking layer
  109. ImGui::End();
  110. }
  111. }
  112. int main(int argc, char *argv[])
  113. {
  114. if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
  115. err(1, "SDL_Init: %s", SDL_GetError());
  116. // From 2.0.18: Enable native IME.
  117. #ifdef SDL_HINT_IME_SHOW_UI
  118. SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
  119. #endif
  120. SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
  121. SDL_Window* window = SDL_CreateWindow("moontalk", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
  122. if (!window)
  123. err(1, "SDL_CreateWindow: %s", SDL_GetError());
  124. SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
  125. if (renderer == nullptr)
  126. err(1, "SDL_CreateRenderer: %s", SDL_GetError());
  127. // Setup Dear ImGui context
  128. IMGUI_CHECKVERSION();
  129. ImGui::CreateContext();
  130. ImGuiIO& io = ImGui::GetIO(); (void)io;
  131. io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
  132. io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
  133. io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
  134. // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
  135. //io.ConfigViewportsNoAutoMerge = true;
  136. //io.ConfigViewportsNoTaskBarIcon = true;
  137. // Setup Dear ImGui style
  138. ImGui::StyleColorsDark();
  139. //ImGui::StyleColorsLight();
  140. // Setup Platform/Renderer backends
  141. ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
  142. ImGui_ImplSDLRenderer2_Init(renderer);
  143. // Load Fonts
  144. // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
  145. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
  146. // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
  147. // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
  148. // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
  149. // - Read 'docs/FONTS.md' for more instructions and details.
  150. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
  151. //io.Fonts->AddFontDefault();
  152. //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
  153. //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
  154. //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
  155. //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
  156. //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
  157. //IM_ASSERT(font != nullptr);
  158. // setup
  159. fprintf(stderr, "Connecting...\n");
  160. moontalk_fd = tcp_connect(SERV, PORT);
  161. fprintf(stderr, "Connected\n");
  162. std::thread t(read_loop);
  163. bool done = false;
  164. while (!done) {
  165. // Poll and handle events (inputs, window resize, etc.)
  166. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
  167. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
  168. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
  169. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
  170. SDL_Event event;
  171. while (SDL_PollEvent(&event)) {
  172. ImGui_ImplSDL2_ProcessEvent(&event);
  173. if (event.type == SDL_QUIT)
  174. done = true;
  175. if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
  176. done = true;
  177. }
  178. inqueue_lock.lock();
  179. if (!inqueue.empty()) {
  180. std::string line = std::move(inqueue.front());
  181. inqueue.pop();
  182. moontalk_lines.push_back(std::move(line));
  183. }
  184. inqueue_lock.unlock();
  185. // Start the Dear ImGui frame
  186. ImGui_ImplSDLRenderer2_NewFrame();
  187. ImGui_ImplSDL2_NewFrame();
  188. ImGui::NewFrame();
  189. ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
  190. ui();
  191. // Rendering
  192. ImGui::Render();
  193. SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
  194. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 1);
  195. SDL_RenderClear(renderer);
  196. ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData());
  197. SDL_RenderPresent(renderer);
  198. }
  199. // Cleanup
  200. ImGui_ImplSDLRenderer2_Shutdown();
  201. ImGui_ImplSDL2_Shutdown();
  202. ImGui::DestroyContext();
  203. SDL_DestroyRenderer(renderer);
  204. SDL_DestroyWindow(window);
  205. SDL_Quit();
  206. close(moontalk_fd);
  207. return 0;
  208. }