Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

driver_network.c 13 KiB

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