main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. // Main loop part of HaxServ
  2. //
  3. // Written by: Test_User <hax@andrewyu.org>
  4. //
  5. // This is free and unencumbered software released into the public
  6. // domain.
  7. //
  8. // Anyone is free to copy, modify, publish, use, compile, sell, or
  9. // distribute this software, either in source code form or as a compiled
  10. // binary, for any purpose, commercial or non-commercial, and by any
  11. // means.
  12. //
  13. // In jurisdictions that recognize copyright laws, the author or authors
  14. // of this software dedicate any and all copyright interest in the
  15. // software to the public domain. We make this dedication for the benefit
  16. // of the public at large and to the detriment of our heirs and
  17. // successors. We intend this dedication to be an overt act of
  18. // relinquishment in perpetuity of all present and future rights to this
  19. // software under copyright law.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  24. // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  25. // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  26. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  27. // OTHER DEALINGS IN THE SOFTWARE.
  28. #include <gnutls/gnutls.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <pthread.h>
  33. #include "network.h"
  34. #include "config.h"
  35. #include "types.h"
  36. #include "tls.h"
  37. #include "types.h"
  38. void *client_loop(void *ign) {
  39. pthread_mutex_lock(&send_lock);
  40. while (1) {
  41. struct string full_msg = {.data = malloc(0), .len = 0};
  42. pthread_mutex_unlock(&send_lock);
  43. client_fd = accept(client_listen_fd, NULL, NULL);
  44. pthread_mutex_lock(&send_lock);
  45. listen(client_listen_fd, 0);
  46. client_connected = 0;
  47. while (1) {
  48. char data[512];
  49. pthread_mutex_unlock(&send_lock); // TODO: proper locking, this works for now but is certainly inefficient
  50. uint64_t new_len;
  51. {
  52. ssize_t len = read(client_fd, data, 512);
  53. if (len < 0)
  54. new_len = 0;
  55. else
  56. new_len = (size_t)len;
  57. }
  58. pthread_mutex_lock(&send_lock);
  59. if (new_len == 0) {
  60. goto disconnect_client;
  61. }
  62. uint8_t found = 0;
  63. uint64_t msg_len;
  64. for (uint64_t i = 0; i < new_len; i++) {
  65. if (data[i] == '\n') {
  66. found = 1;
  67. msg_len = i + full_msg.len;
  68. break;
  69. }
  70. }
  71. void *tmp = realloc(full_msg.data, full_msg.len+new_len);
  72. if (tmp == 0 && full_msg.len+new_len != 0) {
  73. WRITES(2, STRING("OOM... disconnect client.\n"));
  74. goto disconnect_client;
  75. }
  76. full_msg.data = tmp;
  77. memcpy(full_msg.data+full_msg.len, data, new_len);
  78. full_msg.len += new_len;
  79. if (!found)
  80. continue;
  81. while (1) {
  82. if (full_msg.data[msg_len - 1] == '\r')
  83. msg_len--;
  84. uint64_t offset = 0;
  85. while (offset < msg_len && full_msg.data[offset] == ' ')
  86. offset++;
  87. if (offset == msg_len) {
  88. puts("Protocol violation: No command.");
  89. goto disconnect_client;
  90. }
  91. struct string command;
  92. command.data = full_msg.data+offset;
  93. found = 0;
  94. for (uint64_t i = offset; i < msg_len; i++) {
  95. if (full_msg.data[i] == ' ') {
  96. found = 1;
  97. command.len = i - offset;
  98. offset = i;
  99. break;
  100. }
  101. }
  102. if (!found) {
  103. command.len = msg_len - offset;
  104. offset = msg_len;
  105. }
  106. while (offset < msg_len && full_msg.data[offset] == ' ')
  107. offset++;
  108. uint64_t argc = 0;
  109. uint64_t old_offset = offset;
  110. if (offset < msg_len) {
  111. while (offset < msg_len) {
  112. if (full_msg.data[offset] == ':') {
  113. argc++;
  114. break;
  115. }
  116. while (offset < msg_len && full_msg.data[offset] != ' ')
  117. offset++;
  118. argc++;
  119. while (offset < msg_len && full_msg.data[offset] == ' ')
  120. offset++;
  121. }
  122. }
  123. offset = old_offset;
  124. struct string argv[argc];
  125. if (offset < msg_len) {
  126. uint64_t i = 0;
  127. while (offset < msg_len) {
  128. if (full_msg.data[offset] == ':') {
  129. argv[i].data = full_msg.data+offset+1;
  130. argv[i].len = msg_len - offset - 1;
  131. break;
  132. }
  133. argv[i].data = full_msg.data+offset;
  134. uint64_t start = offset;
  135. while (offset < msg_len && full_msg.data[offset] != ' ')
  136. offset++;
  137. argv[i].len = offset - start;
  138. while (offset < msg_len && full_msg.data[offset] == ' ')
  139. offset++;
  140. i++;
  141. }
  142. }
  143. int (*func)(uint64_t argc, struct string *argv) = get_table_index(client_network_commands, command);
  144. #if LOGALL
  145. #if COLORIZE
  146. WRITES(1, STRING("\x1b[34m[Client->Us] \x1b[33m"));
  147. #else
  148. WRITES(1, STRING("[Client->Us] "));
  149. #endif
  150. #if COLORIZE
  151. write(1, full_msg.data, msg_len);
  152. WRITES(1, STRING("\x1b[0m\n"));
  153. #else
  154. write(1, full_msg.data, msg_len+(full_msg.data[msg_len] == '\r' ? 2 : 1)); // +2 or 1: \r\n or \n
  155. #endif
  156. #endif
  157. if (func == 0) {
  158. #if !LOGALL
  159. WRITES(2, STRING("[Client] "));
  160. write(2, full_msg.data, msg_len+(full_msg.data[msg_len] == '\r' ? 2 : 1));
  161. #endif
  162. WRITES(2, STRING("WARNING: Command is unknown, ignoring...\n"));
  163. WRITES(2, STRING("\n"));
  164. } else {
  165. #if LOGALL
  166. WRITES(1, STRING("\n"));
  167. #endif
  168. int err = func(argc, argv);
  169. if (err) {
  170. WRITES(1, STRING("Disconnecting client by result of the network command handler...\n"));
  171. goto disconnect_client;
  172. }
  173. }
  174. if (full_msg.data[msg_len] == '\r')
  175. msg_len++;
  176. memmove(full_msg.data, full_msg.data+msg_len+1, full_msg.len - msg_len - 1);
  177. full_msg.len -= msg_len+1;
  178. found = 0;
  179. for (uint64_t i = 0; i < full_msg.len; i++) {
  180. if (full_msg.data[i] == '\n') {
  181. found = 1;
  182. msg_len = i;
  183. break;
  184. }
  185. }
  186. if (found == 0) {
  187. void *tmp = realloc(full_msg.data, full_msg.len);
  188. if (tmp == 0 && full_msg.len != 0) {
  189. puts("AAAAAAAAA (OOM shrinking allocated data?)");
  190. goto disconnect_client;
  191. }
  192. full_msg.data = tmp;
  193. break;
  194. }
  195. }
  196. }
  197. disconnect_client:
  198. if (client_connected) {
  199. SEND(STRING(":1HC000001 QUIT :Ping timeout: -240 seconds\n"));
  200. client_connected = 0;
  201. remove_user(STRING("1HC000001"), STRING("Ping timeout: -240 seconds\n"));
  202. }
  203. close(client_fd);
  204. client_fd = -1;
  205. free(full_msg.data);
  206. listen(client_listen_fd, 1);
  207. }
  208. }
  209. pthread_t client_thread_id;
  210. int main(void) {
  211. if (initservernetwork() != 0)
  212. return 1;
  213. if (initclientnetwork() != 0)
  214. return 1;
  215. pthread_create(&client_thread_id, NULL, client_loop, NULL);
  216. pthread_mutex_lock(&send_lock);
  217. struct string full_msg = {malloc(0), 0};
  218. while (1) {
  219. char data[512];
  220. char timeout;
  221. uint64_t new_len;
  222. char last_timeout = 0;
  223. while (1) {
  224. pthread_mutex_unlock(&send_lock);
  225. new_len = RECV(data, sizeof(data), &timeout);
  226. pthread_mutex_lock(&send_lock);
  227. if (!timeout)
  228. break;
  229. if (last_timeout) {
  230. break;
  231. } else {
  232. SEND(STRING(":1HC PING 1HC 100\n")); // TODO: Fix this as well
  233. last_timeout = 1;
  234. }
  235. }
  236. if (new_len == 0) {
  237. WRITES(1, STRING("Disconnected.\n"));
  238. return 0;
  239. }
  240. uint8_t found = 0;
  241. uint64_t msg_len;
  242. for (uint64_t i = 0; i < new_len; i++) {
  243. if (data[i] == '\n') {
  244. found = 1;
  245. msg_len = i + full_msg.len;
  246. break;
  247. }
  248. }
  249. void *tmp = realloc(full_msg.data, full_msg.len+new_len);
  250. if (tmp == 0 && full_msg.len+new_len != 0) {
  251. WRITES(2, STRING("OOM... currently just exiting bc there's no automatic reconnect in here yet, and the only sane solution to this is resyncing.\n"));
  252. return 1;
  253. }
  254. full_msg.data = tmp;
  255. memcpy(full_msg.data+full_msg.len, data, new_len);
  256. full_msg.len += new_len;
  257. if (!found)
  258. continue;
  259. while (1) {
  260. uint64_t offset = 0;
  261. while (offset < msg_len && full_msg.data[offset] == ' ')
  262. offset++;
  263. if (msg_len == offset) {
  264. WRITES(2, STRING("Protocol violation: Empty message.\n"));
  265. return 2;
  266. }
  267. struct string source;
  268. if (full_msg.data[offset] == ':') {
  269. source.data = full_msg.data + 1 + offset;
  270. found = 0;
  271. for (uint64_t i = offset + 1; i < msg_len; i++) {
  272. if (full_msg.data[i] == ' ') {
  273. found = 1;
  274. source.len = i - offset - 1;
  275. offset = i + 1;
  276. break;
  277. }
  278. }
  279. if (!found || source.len + 1 == msg_len) {
  280. WRITES(2, STRING("Protocol violation: Sender but no command."));
  281. return 2;
  282. }
  283. } else {
  284. source = (struct string){0};
  285. }
  286. while (offset < msg_len && full_msg.data[offset] == ' ')
  287. offset++;
  288. if (offset == msg_len) {
  289. WRITES(2, STRING("Protocol violation: No command."));
  290. return 2;
  291. }
  292. struct string command;
  293. command.data = full_msg.data+offset;
  294. found = 0;
  295. for (uint64_t i = offset; i < msg_len; i++) {
  296. if (full_msg.data[i] == ' ') {
  297. found = 1;
  298. command.len = i - offset;
  299. offset = i;
  300. break;
  301. }
  302. }
  303. if (!found) {
  304. command.len = msg_len - offset;
  305. offset = msg_len;
  306. }
  307. while (offset < msg_len && full_msg.data[offset] == ' ')
  308. offset++;
  309. uint64_t argc = 0;
  310. uint64_t old_offset = offset;
  311. if (offset < msg_len) {
  312. while (offset < msg_len) {
  313. if (full_msg.data[offset] == ':') {
  314. argc++;
  315. break;
  316. }
  317. while (offset < msg_len && full_msg.data[offset] != ' ')
  318. offset++;
  319. argc++;
  320. while (offset < msg_len && full_msg.data[offset] == ' ')
  321. offset++;
  322. }
  323. }
  324. offset = old_offset;
  325. struct string argv[argc];
  326. if (offset < msg_len) {
  327. uint64_t i = 0;
  328. while (offset < msg_len) {
  329. if (full_msg.data[offset] == ':') {
  330. argv[i].data = full_msg.data+offset+1;
  331. argv[i].len = msg_len - offset - 1;
  332. break;
  333. }
  334. argv[i].data = full_msg.data+offset;
  335. uint64_t start = offset;
  336. while (offset < msg_len && full_msg.data[offset] != ' ')
  337. offset++;
  338. argv[i].len = offset - start;
  339. while (offset < msg_len && full_msg.data[offset] == ' ')
  340. offset++;
  341. i++;
  342. }
  343. }
  344. int (*func)(struct string source, uint64_t argc, struct string *argv) = get_table_index(server_network_commands, command);
  345. #if LOGALL
  346. #if COLORIZE
  347. WRITES(1, STRING("\x1b[35m[Server->Us] \x1b[36m"));
  348. #else
  349. WRITES(1, STRING("[Server->Us] "));
  350. #endif
  351. #if COLORIZE
  352. write(1, full_msg.data, msg_len);
  353. WRITES(1, STRING("\x1b[0m\n"));
  354. #else
  355. write(1, full_msg.data, msg_len+1); // +1: \n
  356. #endif
  357. #endif
  358. if (func == 0) {
  359. #if !LOGALL
  360. WRITES(2, STRING("[Server] "));
  361. write(2, full_msg.data, msg_len+1); // +1: \n
  362. #endif
  363. WRITES(2, STRING("WARNING: Command is unknown, ignoring...\n"));
  364. WRITES(2, STRING("\n"));
  365. } else {
  366. #if LOGALL
  367. WRITES(1, STRING("\n"));
  368. #endif
  369. int err = func(source, argc, argv);
  370. if (err) {
  371. #if !LOGALL
  372. WRITES(2, STRING("Message was: [Server] "));
  373. write(2, full_msg.data, msg_len+1);
  374. #endif
  375. WRITES(1, STRING("Disconnecting by result of the network command handler...\n"));
  376. return 0;
  377. }
  378. }
  379. memmove(full_msg.data, full_msg.data+msg_len+1, full_msg.len - msg_len - 1);
  380. full_msg.len -= msg_len+1;
  381. found = 0;
  382. for (uint64_t i = 0; i < full_msg.len; i++) {
  383. if (full_msg.data[i] == '\n') {
  384. found = 1;
  385. msg_len = i;
  386. break;
  387. }
  388. }
  389. if (found == 0) {
  390. void *tmp = realloc(full_msg.data, full_msg.len);
  391. if (tmp == 0 && full_msg.len != 0) {
  392. puts("AAAAAAAAA (OOM shrinking allocated data?)");
  393. return 1;
  394. }
  395. full_msg.data = tmp;
  396. break;
  397. }
  398. }
  399. }
  400. return 0;
  401. }