Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

271 wiersze
6.2 KiB

  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. #if defined(HAVE_UNISTD_H)
  28. # include <unistd.h>
  29. #endif
  30. #include <stdarg.h>
  31. #include "caca.h"
  32. #include "caca_internals.h"
  33. #include "cucul.h"
  34. #include "cucul_internals.h"
  35. static void manage_connections(caca_t *kk);
  36. static int send_data(caca_t *kk, int fd);
  37. struct driver_private
  38. {
  39. unsigned int width, height;
  40. unsigned int port;
  41. int sockfd;
  42. struct sockaddr_in my_addr;
  43. struct sockaddr_in remote_addr;
  44. socklen_t sin_size;
  45. int clilen;
  46. char *buffer;
  47. int size;
  48. int client_count;
  49. int *fd_list;
  50. };
  51. #define BACKLOG 1337 /* Number of pending connections */
  52. /* Following vars are static */
  53. static char codes[] = {0xff, 0xfb, 0x01, // WILL ECHO
  54. 0xff, 0xfb, 0x03, // WILL SUPPRESS GO AHEAD
  55. 0xff, 253, 31, // DO NAWS
  56. 0xff, 254, 31, // DON'T NAWS
  57. 0xff, 31, 250, 0, 30, 0, 0xFF, // to be replaced
  58. 0xff, 240};
  59. static int network_init_graphics(caca_t *kk)
  60. {
  61. int yes=1;
  62. printf("Initing network stack.\n");
  63. kk->drv.p = malloc(sizeof(struct driver_private));
  64. if(kk->drv.p == NULL)
  65. return -1;
  66. kk->drv.p->width = 80;
  67. kk->drv.p->height = 24;
  68. kk->drv.p->port = 7575; // 75 75 decimal ASCII -> KK // FIXME, sadly
  69. kk->drv.p->client_count = 0;
  70. kk->drv.p->fd_list = NULL;
  71. _cucul_set_size(kk->qq, kk->drv.p->width, kk->drv.p->height);
  72. printf("socket\n");
  73. if ((kk->drv.p->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
  74. perror("socket");
  75. return -1;
  76. }
  77. printf("setsockopt\n");
  78. if (setsockopt(kk->drv.p->sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
  79. perror("setsockopt");
  80. return -1;
  81. }
  82. kk->drv.p->my_addr.sin_family = AF_INET;
  83. kk->drv.p-> my_addr.sin_port = htons(kk->drv.p->port);
  84. kk->drv.p->my_addr.sin_addr.s_addr = INADDR_ANY;
  85. memset(&(kk->drv.p->my_addr.sin_zero), '\0', 8);
  86. printf("bind\n");
  87. if (bind(kk->drv.p->sockfd, (struct sockaddr *)&kk->drv.p->my_addr, sizeof(struct sockaddr))
  88. == -1) {
  89. perror("bind");
  90. return -1;
  91. }
  92. /* Non blocking socket */
  93. fcntl(kk->drv.p->sockfd, F_SETFL, O_NONBLOCK);
  94. printf("listen\n");
  95. if (listen(kk->drv.p->sockfd, BACKLOG) == -1) {
  96. perror("listen");
  97. return -1;
  98. }
  99. printf("network ok.\n");
  100. kk->drv.p->buffer = NULL;
  101. return 0;
  102. }
  103. static int network_end_graphics(caca_t *kk)
  104. {
  105. int i;
  106. for(i = 0; i < kk->drv.p->client_count; i++) {
  107. close(kk->drv.p->fd_list[i]);
  108. }
  109. return 0;
  110. }
  111. static int network_set_window_title(caca_t *kk, char const *title)
  112. {
  113. /* Not handled (yet)*/
  114. return 0;
  115. }
  116. static unsigned int network_get_window_width(caca_t *kk)
  117. {
  118. return kk->drv.p->width * 6;
  119. }
  120. static unsigned int network_get_window_height(caca_t *kk)
  121. {
  122. return kk->drv.p->height * 10;
  123. }
  124. static void network_display(caca_t *kk)
  125. {
  126. int i;
  127. kk->drv.p->buffer = cucul_get_ansi(kk->qq, 0, &kk->drv.p->size);;
  128. for(i = 0; i < kk->drv.p->client_count; i++)
  129. {
  130. if(send_data(kk, kk->drv.p->fd_list[i]))
  131. kk->drv.p->fd_list[i] = -1;
  132. }
  133. manage_connections(kk);
  134. }
  135. static void network_handle_resize(caca_t *kk)
  136. {
  137. /* Not handled */
  138. }
  139. static unsigned int network_get_event(caca_t *kk)
  140. {
  141. manage_connections(kk);
  142. /* Not handled */
  143. return 0;
  144. }
  145. /*
  146. * XXX: The following functions are local
  147. */
  148. static void manage_connections(caca_t *kk)
  149. {
  150. int fd;
  151. kk->drv.p->clilen = sizeof(kk->drv.p->remote_addr);
  152. fd = accept(kk->drv.p->sockfd, (struct sockaddr *) &kk->drv.p->remote_addr, &kk->drv.p->clilen);
  153. if(fd != -1)
  154. {
  155. if(kk->drv.p->fd_list == NULL)
  156. {
  157. kk->drv.p->fd_list = malloc(sizeof(int));
  158. if(kk->drv.p->fd_list == NULL)
  159. return;
  160. }
  161. else
  162. {
  163. kk->drv.p->fd_list = realloc(kk->drv.p->fd_list, (kk->drv.p->client_count+1) * sizeof(int));
  164. }
  165. if(send_data(kk, fd) == 0)
  166. {
  167. kk->drv.p->fd_list[kk->drv.p->client_count] = fd;
  168. kk->drv.p->client_count++;
  169. }
  170. }
  171. }
  172. static int send_data(caca_t *kk, int fd)
  173. {
  174. /* No error, there's just nothing to send yet */
  175. if(!kk->drv.p->buffer)
  176. return 0;
  177. if(fd < 0)
  178. return -1;
  179. /* FIXME, handle >255 sizes */
  180. codes[16] = (unsigned char) kk->drv.p->width & 0xff;
  181. codes[18] = (unsigned char) kk->drv.p->height & 0xff;
  182. /* Send basic telnet codes */
  183. if (send(fd, codes,sizeof(codes) , 0) == -1)
  184. return -1;
  185. /* ANSI code for move(0,0)*/
  186. if (send(fd, "\033[1,1H", 6, 0) == -1)
  187. return -1;
  188. if (send(fd, kk->drv.p->buffer, kk->drv.p->size, 0) == -1)
  189. return -1;
  190. return 0;
  191. }
  192. /*
  193. * Driver initialisation
  194. */
  195. void network_init_driver(caca_t *kk)
  196. {
  197. kk->drv.driver = CACA_DRIVER_NETWORK;
  198. kk->drv.init_graphics = network_init_graphics;
  199. kk->drv.end_graphics = network_end_graphics;
  200. kk->drv.set_window_title = network_set_window_title;
  201. kk->drv.get_window_width = network_get_window_width;
  202. kk->drv.get_window_height = network_get_window_height;
  203. kk->drv.display = network_display;
  204. kk->drv.handle_resize = network_handle_resize;
  205. kk->drv.get_event = network_get_event;
  206. }
  207. #endif // USE_NETWORK