You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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