Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

558 строки
14 KiB

  1. /*
  2. * cacaserver Colour ASCII-Art library
  3. * Copyright (c) 2006 Jean-Yves Lamoureux <jylam@lnxscene.org>
  4. * 2006 Sam Hocevar <sam@zoy.org>
  5. * All Rights Reserved
  6. *
  7. * $Id$
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the Do What The Fuck You Want To
  11. * Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. #include "config.h"
  15. #include "common.h"
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #if defined(HAVE_ARPA_INET_H)
  20. # include <arpa/inet.h>
  21. #elif defined(HAVE_NETINET_IN_H)
  22. # include <netinet/in.h>
  23. #elif defined(HAVE_WINSOCK2_H)
  24. # include <winsock2.h>
  25. # include <ws2tcpip.h>
  26. #endif
  27. #if defined(HAVE_UNISTD_H)
  28. # include <unistd.h>
  29. #endif
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <fcntl.h>
  33. #include <signal.h>
  34. #include <errno.h>
  35. #include <stdarg.h>
  36. #include "cucul.h"
  37. #define BACKLOG 1337 /* Number of pending connections */
  38. #define INBUFFER 32 /* Size of per-client input buffer */
  39. #define OUTBUFFER 300000 /* Size of per-client output buffer */
  40. /* Following vars are static */
  41. #define INIT_PREFIX \
  42. "\xff\xfb\x01" /* WILL ECHO */ \
  43. "\xff\xfb\x03" /* WILL SUPPRESS GO AHEAD */ \
  44. "\xff\xfd\x31" /* DO NAWS */ \
  45. "\xff\x1f\xfa____" /* SB NAWS */ \
  46. "\xff\xf0" /* SE */ \
  47. "\x1b]2;caca for the network\x07" /* Change window title */ \
  48. "\x1b[H\x1b[J" /* Clear screen */
  49. /*"\x1b[?25l"*/ /* Hide cursor */
  50. #define ANSI_PREFIX \
  51. "\x1b[1;1H" /* move(0,0) */ \
  52. "\x1b[1;1H" /* move(0,0) again */
  53. #define ANSI_RESET \
  54. " " /* Garbage */ \
  55. "\x1b[?1049h" /* Clear screen */ \
  56. "\x1b[?1049h" /* Clear screen again */
  57. static char const telnet_commands[16][5] =
  58. {
  59. "SE ", "NOP ", "DM ", "BRK ", "IP ", "AO ", "AYT ", "EC ",
  60. "EL ", "GA ", "SB ", "WILL", "WONT", "DO ", "DONT", "IAC "
  61. };
  62. static char const telnet_options[37][5] =
  63. {
  64. "????", "ECHO", "????", "SUGH", "????", "STTS", "TIMK", "????",
  65. "????", "????", "????", "????", "????", "????", "????", "????",
  66. "????", "????", "????", "????", "????", "????", "????", "????",
  67. "TTYP", "????", "????", "????", "????", "????", "????", "NAWS",
  68. "TRSP", "RMFC", "LIMO", "????", "EVAR"
  69. };
  70. #define COMMAND_NAME(x) (x>=240)?telnet_commands[x-240]:"????"
  71. #define OPTION_NAME(x) (x<=36)?telnet_options[x]:"????"
  72. struct client
  73. {
  74. int fd;
  75. int ready;
  76. uint8_t inbuf[INBUFFER];
  77. int inbytes;
  78. uint8_t outbuf[OUTBUFFER];
  79. int start, stop;
  80. };
  81. struct server
  82. {
  83. unsigned int width, height;
  84. unsigned int port;
  85. int sockfd;
  86. struct sockaddr_in my_addr;
  87. socklen_t sin_size;
  88. /* Input buffer */
  89. uint8_t *input;
  90. unsigned int read;
  91. char prefix[sizeof(INIT_PREFIX)];
  92. cucul_canvas_t *canvas;
  93. void *buffer;
  94. unsigned long int buflen;
  95. int client_count;
  96. struct client *clients;
  97. RETSIGTYPE (*sigpipe_handler)(int);
  98. };
  99. static void manage_connections(struct server *server);
  100. static int send_data(struct server *server, struct client *c);
  101. ssize_t nonblock_write(int fd, void *buf, size_t len);
  102. int main(void)
  103. {
  104. int i, yes = 1, flags;
  105. struct server *server;
  106. char *tmp;
  107. #ifdef HAVE_WINDOWS_H
  108. WORD winsockVersion;
  109. WSADATA wsaData;
  110. winsockVersion = MAKEWORD(1, 1);
  111. WSAStartup(winsockVersion, &wsaData);
  112. #endif
  113. server = malloc(sizeof(struct server));
  114. server->input = malloc(12);
  115. server->read = 0;
  116. server->client_count = 0;
  117. server->clients = NULL;
  118. server->port = 0xCACA; /* 51914 */
  119. /* FIXME, handle >255 sizes */
  120. memcpy(server->prefix, INIT_PREFIX, sizeof(INIT_PREFIX));
  121. tmp = strstr(server->prefix, "____");
  122. tmp[0] = (unsigned char) (server->width & 0xff00) >> 8;
  123. tmp[1] = (unsigned char) server->width & 0xff;
  124. tmp[2] = (unsigned char) (server->height & 0xff00) >> 8;
  125. tmp[3] = (unsigned char) server->height & 0xff;
  126. if((server->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
  127. {
  128. perror("socket");
  129. return -1;
  130. }
  131. if(setsockopt(server->sockfd, SOL_SOCKET,
  132. SO_REUSEADDR, &yes, sizeof(int)) == -1)
  133. {
  134. perror("setsockopt SO_REUSEADDR");
  135. return -1;
  136. }
  137. server->my_addr.sin_family = AF_INET;
  138. server-> my_addr.sin_port = htons(server->port);
  139. server->my_addr.sin_addr.s_addr = INADDR_ANY;
  140. memset(&(server->my_addr.sin_zero), '\0', 8);
  141. if(bind(server->sockfd, (struct sockaddr *)&server->my_addr,
  142. sizeof(struct sockaddr)) == -1)
  143. {
  144. perror("bind");
  145. return -1;
  146. }
  147. /* Non blocking socket */
  148. flags = fcntl(server->sockfd, F_GETFL, 0);
  149. fcntl(server->sockfd, F_SETFL, flags | O_NONBLOCK);
  150. if(listen(server->sockfd, BACKLOG) == -1)
  151. {
  152. perror("listen");
  153. return -1;
  154. }
  155. server->canvas = cucul_create_canvas(0, 0);
  156. server->buffer = NULL;
  157. /* Ignore SIGPIPE */
  158. server->sigpipe_handler = signal(SIGPIPE, SIG_IGN);
  159. fprintf(stderr, "initialised network, listening on port %i\n",
  160. server->port);
  161. /* Main loop */
  162. for(;;)
  163. {
  164. restart:
  165. /* Manage new connections as this function will be called sometimes
  166. * more often than display */
  167. manage_connections(server);
  168. /* Read data from stdin */
  169. if(server->read < 12)
  170. {
  171. read(0, server->input + server->read, 12 - server->read);
  172. server->read = 12;
  173. }
  174. while(cucul_import_memory(server->canvas, server->input,
  175. server->read, "caca") < 0)
  176. {
  177. memmove(server->input, server->input + 1, server->read - 1);
  178. read(0, server->input + server->read - 1, 1);
  179. }
  180. for(;;)
  181. {
  182. long int needed;
  183. ssize_t wanted;
  184. needed = cucul_import_memory(server->canvas, server->input,
  185. server->read, "caca");
  186. if(needed < 0)
  187. goto restart;
  188. if(needed > 0)
  189. {
  190. server->read -= needed;
  191. memmove(server->input, server->input + needed, server->read);
  192. break;
  193. }
  194. server->input = realloc(server->input, server->read + 128);
  195. wanted = read(0, server->input + server->read, 128);
  196. if(wanted < 0)
  197. goto restart;
  198. server->read += wanted;
  199. }
  200. /* Free the previous export buffer, if any */
  201. if(server->buffer)
  202. {
  203. free(server->buffer);
  204. server->buffer = NULL;
  205. }
  206. /* Get ANSI representation of the image and skip the end-of buffer
  207. * linefeed ("\r\n", 2 byte) */
  208. server->buffer = cucul_export_memory(server->canvas, "utf8cr",
  209. &server->buflen);
  210. server->buflen -= 2;
  211. for(i = 0; i < server->client_count; i++)
  212. {
  213. if(server->clients[i].fd == -1)
  214. continue;
  215. if(send_data(server, &server->clients[i]))
  216. {
  217. fprintf(stderr, "[%i] dropped connection\n",
  218. server->clients[i].fd);
  219. close(server->clients[i].fd);
  220. server->clients[i].fd = -1;
  221. }
  222. }
  223. }
  224. /* Kill all remaining clients */
  225. for(i = 0; i < server->client_count; i++)
  226. {
  227. if(server->clients[i].fd == -1)
  228. continue;
  229. close(server->clients[i].fd);
  230. server->clients[i].fd = -1;
  231. }
  232. if(server->buffer)
  233. free(server->buffer);
  234. cucul_free_canvas(server->canvas);
  235. /* Restore SIGPIPE handler */
  236. signal(SIGPIPE, server->sigpipe_handler);
  237. free(server);
  238. #ifdef HAVE_WINDOWS_H
  239. WSACleanup();
  240. #endif
  241. return 0;
  242. }
  243. /*
  244. * XXX: The following functions are local
  245. */
  246. static void manage_connections(struct server *server)
  247. {
  248. int fd, flags;
  249. struct sockaddr_in remote_addr;
  250. socklen_t len = sizeof(struct sockaddr_in);
  251. fd = accept(server->sockfd, (struct sockaddr *)&remote_addr, &len);
  252. if(fd == -1)
  253. return;
  254. fprintf(stderr, "[%i] connected from %s\n",
  255. fd, inet_ntoa(remote_addr.sin_addr));
  256. /* Non blocking socket */
  257. flags = fcntl(fd, F_SETFL, 0);
  258. fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  259. if(server->clients == NULL)
  260. {
  261. server->clients = malloc(sizeof(struct client));
  262. if(server->clients == NULL)
  263. return;
  264. }
  265. else
  266. {
  267. server->clients = realloc(server->clients,
  268. (server->client_count+1) * sizeof(struct client));
  269. }
  270. server->clients[server->client_count].fd = fd;
  271. server->clients[server->client_count].ready = 0;
  272. server->clients[server->client_count].inbytes = 0;
  273. server->clients[server->client_count].start = 0;
  274. server->clients[server->client_count].stop = 0;
  275. /* If we already have data to send, send it to the new client */
  276. if(send_data(server, &server->clients[server->client_count]))
  277. {
  278. fprintf(stderr, "[%i] dropped connection\n", fd);
  279. close(fd);
  280. server->clients[server->client_count].fd = -1;
  281. return;
  282. }
  283. server->client_count++;
  284. }
  285. static int send_data(struct server *server, struct client *c)
  286. {
  287. ssize_t ret;
  288. /* Not for us */
  289. if(c->fd < 0)
  290. return -1;
  291. /* Listen to incoming data */
  292. for(;;)
  293. {
  294. ret = read(c->fd, c->inbuf + c->inbytes, 1);
  295. if(ret <= 0)
  296. break;
  297. c->inbytes++;
  298. /* Check for telnet sequences */
  299. if(c->inbuf[0] == 0xff)
  300. {
  301. if(c->inbytes == 1)
  302. {
  303. ;
  304. }
  305. else if(c->inbuf[1] == 0xfd || c->inbuf[1] == 0xfc)
  306. {
  307. if(c->inbytes == 3)
  308. {
  309. fprintf(stderr, "[%i] said: %.02x %.02x %.02x (%s %s %s)\n",
  310. c->fd, c->inbuf[0], c->inbuf[1], c->inbuf[2],
  311. COMMAND_NAME(c->inbuf[0]), COMMAND_NAME(c->inbuf[1]), OPTION_NAME(c->inbuf[2]));
  312. /* Just ignore, lol */
  313. c->inbytes = 0;
  314. }
  315. }
  316. else
  317. c->inbytes = 0;
  318. }
  319. else if(c->inbytes == 1)
  320. {
  321. if(c->inbuf[0] == 0x03)
  322. {
  323. fprintf(stderr, "[%i] pressed C-c\n", c->fd);
  324. return -1; /* User requested to quit */
  325. }
  326. c->inbytes = 0;
  327. }
  328. }
  329. /* Send the telnet initialisation commands */
  330. if(!c->ready)
  331. {
  332. ret = nonblock_write(c->fd, server->prefix, sizeof(INIT_PREFIX));
  333. if(ret == -1)
  334. return (errno == EAGAIN) ? 0 : -1;
  335. if(ret < (ssize_t)sizeof(INIT_PREFIX))
  336. return 0;
  337. c->ready = 1;
  338. }
  339. /* No error, there's just nothing to send yet */
  340. if(!server->buffer)
  341. return 0;
  342. /* If we have backlog, send the backlog */
  343. if(c->stop)
  344. {
  345. ret = nonblock_write(c->fd, c->outbuf + c->start, c->stop - c->start);
  346. if(ret == -1)
  347. {
  348. if(errno == EAGAIN)
  349. ret = 0;
  350. else
  351. {
  352. fprintf(stderr, "[%i] failed (%s)\n",
  353. c->fd, strerror(errno));
  354. return -1;
  355. }
  356. }
  357. if(ret == c->stop - c->start)
  358. {
  359. /* We got rid of the backlog! */
  360. c->start = c->stop = 0;
  361. }
  362. else
  363. {
  364. c->start += ret;
  365. if(c->stop - c->start + strlen(ANSI_PREFIX) + server->buflen
  366. > OUTBUFFER)
  367. {
  368. /* Overflow! Empty buffer and start again */
  369. memcpy(c->outbuf, ANSI_RESET, strlen(ANSI_RESET));
  370. c->start = 0;
  371. c->stop = strlen(ANSI_RESET);
  372. return 0;
  373. }
  374. /* Need to move? */
  375. if(c->stop + strlen(ANSI_PREFIX) + server->buflen > OUTBUFFER)
  376. {
  377. memmove(c->outbuf, c->outbuf + c->start, c->stop - c->start);
  378. c->stop -= c->start;
  379. c->start = 0;
  380. }
  381. memcpy(c->outbuf + c->stop, ANSI_PREFIX, strlen(ANSI_PREFIX));
  382. c->stop += strlen(ANSI_PREFIX);
  383. memcpy(c->outbuf + c->stop, server->buffer, server->buflen);
  384. c->stop += server->buflen;
  385. return 0;
  386. }
  387. }
  388. /* We no longer have backlog, send our new data */
  389. /* Send ANSI prefix */
  390. ret = nonblock_write(c->fd, ANSI_PREFIX, strlen(ANSI_PREFIX));
  391. if(ret == -1)
  392. {
  393. if(errno == EAGAIN)
  394. ret = 0;
  395. else
  396. {
  397. fprintf(stderr, "[%i] failed (%s)\n", c->fd, strerror(errno));
  398. return -1;
  399. }
  400. }
  401. if(ret < (ssize_t)strlen(ANSI_PREFIX))
  402. {
  403. if(strlen(ANSI_PREFIX) + server->buflen > OUTBUFFER)
  404. {
  405. /* Overflow! Empty buffer and start again */
  406. memcpy(c->outbuf, ANSI_RESET, strlen(ANSI_RESET));
  407. c->start = 0;
  408. c->stop = strlen(ANSI_RESET);
  409. return 0;
  410. }
  411. memcpy(c->outbuf, ANSI_PREFIX, strlen(ANSI_PREFIX) - ret);
  412. c->stop = strlen(ANSI_PREFIX) - ret;
  413. memcpy(c->outbuf + c->stop, server->buffer, server->buflen);
  414. c->stop += server->buflen;
  415. return 0;
  416. }
  417. /* Send actual data */
  418. ret = nonblock_write(c->fd, server->buffer, server->buflen);
  419. if(ret == -1)
  420. {
  421. if(errno == EAGAIN)
  422. ret = 0;
  423. else
  424. {
  425. fprintf(stderr, "[%i] failed (%s)\n", c->fd, strerror(errno));
  426. return -1;
  427. }
  428. }
  429. if(ret < (int)server->buflen)
  430. {
  431. if(server->buflen > OUTBUFFER)
  432. {
  433. /* Overflow! Empty buffer and start again */
  434. memcpy(c->outbuf, ANSI_RESET, strlen(ANSI_RESET));
  435. c->start = 0;
  436. c->stop = strlen(ANSI_RESET);
  437. return 0;
  438. }
  439. memcpy(c->outbuf, server->buffer, server->buflen - ret);
  440. c->stop = server->buflen - ret;
  441. return 0;
  442. }
  443. return 0;
  444. }
  445. ssize_t nonblock_write(int fd, void *buf, size_t len)
  446. {
  447. size_t total = 0;
  448. ssize_t ret;
  449. while(total < len)
  450. {
  451. do
  452. {
  453. ret = write(fd, buf, len);
  454. }
  455. while(ret < 0 && errno == EINTR);
  456. if(ret < 0)
  457. return ret;
  458. else if(ret == 0)
  459. return total;
  460. total += len;
  461. buf = (void *)((uintptr_t)buf + len);
  462. }
  463. return total;
  464. }