socket_harness.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * socket_harness.c
  5. *
  6. * Written by Steve Underwood <steveu@coppice.org>
  7. *
  8. * Copyright (C) 2007 Steve Underwood
  9. *
  10. * All rights reserved.
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License version 2, as
  14. * published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24. */
  25. /*! \page bitstream_tests_page Bitstream tests
  26. \section bitstream_tests_page_sec_1 What does it do?
  27. \section bitstream_tests_page_sec_2 How is it used?
  28. */
  29. #if defined(HAVE_CONFIG_H)
  30. #include "config.h"
  31. #endif
  32. #define _GNU_SOURCE
  33. #include <inttypes.h>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <fcntl.h>
  37. #include <string.h>
  38. #include <assert.h>
  39. #include <unistd.h>
  40. #include <signal.h>
  41. #include <termios.h>
  42. #include <fcntl.h>
  43. #include <errno.h>
  44. #include <sys/ioctl.h>
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #include <netinet/in.h>
  48. #include <sys/socket.h>
  49. #include <sys/un.h>
  50. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  51. #include "spandsp.h"
  52. #include "pseudo_terminals.h"
  53. #include "socket_harness.h"
  54. //#define SIMULATE_RING 1
  55. #define CLOSE_COUNT_MAX 100
  56. /* static data */
  57. static int16_t inbuf[4096];
  58. static int16_t outbuf[4096];
  59. static volatile sig_atomic_t keep_running = true;
  60. static void log_signal(int signum)
  61. {
  62. fprintf(stderr, "Signal %d: mark termination.\n", signum);
  63. keep_running = false;
  64. exit(2);
  65. }
  66. /*- End of function --------------------------------------------------------*/
  67. int socket_harness_run(socket_harness_state_t *s)
  68. {
  69. struct timeval tmo;
  70. fd_set rset;
  71. fd_set eset;
  72. struct termios termios;
  73. int max_fd;
  74. int count;
  75. int samples;
  76. int tx_samples;
  77. int ret;
  78. while (keep_running)
  79. {
  80. //if (s->modem->event)
  81. // modem_event(s->modem);
  82. #if defined(SIMULATE_RING)
  83. tmo.tv_sec = 0;
  84. tmo.tv_usec= 1000000/RING_HZ;
  85. #else
  86. tmo.tv_sec = 1;
  87. tmo.tv_usec= 0;
  88. #endif
  89. max_fd = 0;
  90. FD_ZERO(&rset);
  91. FD_ZERO(&eset);
  92. FD_SET(s->audio_fd, &rset);
  93. FD_SET(s->audio_fd, &eset);
  94. FD_SET(s->pty_fd, &rset);
  95. FD_SET(s->pty_fd, &eset);
  96. if (s->audio_fd > max_fd)
  97. max_fd = s->audio_fd;
  98. if (s->pty_fd > max_fd)
  99. max_fd = s->pty_fd;
  100. if (s->pty_closed && s->close_count)
  101. {
  102. if (!s->started || s->close_count++ > CLOSE_COUNT_MAX)
  103. s->close_count = 0;
  104. }
  105. else if (s->terminal_free_space_callback(s->user_data))
  106. {
  107. FD_SET(s->pty_fd, &rset);
  108. if (s->pty_fd > max_fd)
  109. max_fd = s->pty_fd;
  110. }
  111. if ((ret = select(max_fd + 1, &rset, NULL, &eset, &tmo)) < 0)
  112. {
  113. if (errno == EINTR)
  114. continue;
  115. fprintf(stderr, "Error: select: %s\n", strerror(errno));
  116. return ret;
  117. }
  118. if (ret == 0)
  119. {
  120. /* Timeout */
  121. #if defined(SIMULATE_RING)
  122. if (!modem->modem->started)
  123. {
  124. rcount++;
  125. if (rcount <= RING_ON)
  126. modem_ring(modem->modem);
  127. else if (rcount > RING_OFF)
  128. rcount = 0;
  129. }
  130. #endif
  131. continue;
  132. }
  133. if (FD_ISSET(s->audio_fd, &rset))
  134. {
  135. if ((count = read(s->audio_fd, inbuf, sizeof(inbuf)/2)) < 0)
  136. {
  137. if (errno != EAGAIN)
  138. {
  139. fprintf(stderr, "Error: audio read: %s\n", strerror(errno));
  140. return -1;
  141. }
  142. count = 0;
  143. }
  144. if (count == 0)
  145. {
  146. fprintf(stderr, "Audio socket closed\n");
  147. return 0;
  148. }
  149. samples = count/2;
  150. usleep(125*samples);
  151. s->rx_callback(s->user_data, inbuf, samples);
  152. tx_samples = s->tx_callback(s->user_data, outbuf, samples);
  153. if (tx_samples < samples)
  154. memset(&outbuf[tx_samples], 0, (samples - tx_samples)*2);
  155. if ((count = write(s->audio_fd, outbuf, samples*2)) < 0)
  156. {
  157. if (errno != EAGAIN)
  158. {
  159. fprintf(stderr, "Error: audio write: %s\n", strerror(errno));
  160. return -1;
  161. }
  162. /* TODO: */
  163. }
  164. if (count != samples*2)
  165. fprintf(stderr, "audio write = %d\n", count);
  166. }
  167. if (FD_ISSET(s->pty_fd, &rset))
  168. {
  169. /* Check termios */
  170. tcgetattr(s->pty_fd, &termios);
  171. if (memcmp(&termios, &s->termios, sizeof(termios)))
  172. s->termios_callback(s->user_data, &termios);
  173. /* Read data */
  174. if ((count = s->terminal_free_space_callback(s->user_data)))
  175. {
  176. if (count > sizeof(inbuf))
  177. count = sizeof(inbuf);
  178. if ((count = read(s->pty_fd, inbuf, count)) < 0)
  179. {
  180. if (errno == EAGAIN)
  181. {
  182. fprintf(stderr, "pty read, errno = EAGAIN\n");
  183. }
  184. else
  185. {
  186. if (errno == EIO)
  187. {
  188. if (!s->pty_closed)
  189. {
  190. fprintf(stderr, "pty closed.\n");
  191. s->pty_closed = 1;
  192. if ((termios.c_cflag & HUPCL))
  193. s->hangup_callback(s->user_data, 0);
  194. }
  195. s->close_count = 1;
  196. }
  197. else
  198. {
  199. fprintf(stderr, "Error: pty read: %s\n", strerror(errno));
  200. return -1;
  201. }
  202. }
  203. }
  204. else
  205. {
  206. if (count == 0)
  207. fprintf(stderr, "pty read = 0\n");
  208. s->pty_closed = false;
  209. s->terminal_callback(s->user_data, (uint8_t *) inbuf, count);
  210. }
  211. }
  212. }
  213. }
  214. return 0;
  215. }
  216. /*- End of function --------------------------------------------------------*/
  217. socket_harness_state_t *socket_harness_init(socket_harness_state_t *s,
  218. const char *socket_name,
  219. const char *tag,
  220. int caller,
  221. put_msg_func_t terminal_callback,
  222. termio_update_func_t termios_callback,
  223. modem_status_func_t hangup_callback,
  224. put_msg_free_space_func_t terminal_free_space_callback,
  225. span_rx_handler_t rx_callback,
  226. span_rx_fillin_handler_t rx_fillin_callback,
  227. span_tx_handler_t tx_callback,
  228. void *user_data)
  229. {
  230. int sockfd;
  231. int listensockfd;
  232. struct sockaddr_un serv_addr;
  233. struct sockaddr_un cli_addr;
  234. socklen_t servlen;
  235. socklen_t clilen;
  236. if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  237. {
  238. fprintf(stderr, "Socket failed - errno = %d\n", errno);
  239. return NULL;
  240. }
  241. if (s == NULL)
  242. {
  243. if ((s = (socket_harness_state_t *) malloc(sizeof(*s))) == NULL)
  244. return NULL;
  245. }
  246. memset(s, 0, sizeof(*s));
  247. signal(SIGINT, log_signal);
  248. signal(SIGTERM, log_signal);
  249. s->terminal_callback = terminal_callback;
  250. s->termios_callback = termios_callback;
  251. s->hangup_callback = hangup_callback;
  252. s->terminal_free_space_callback = terminal_free_space_callback;
  253. s->rx_callback = rx_callback;
  254. s->rx_fillin_callback = rx_fillin_callback;
  255. s->tx_callback = tx_callback;
  256. s->user_data = user_data;
  257. memset((char *) &serv_addr, 0, sizeof(serv_addr));
  258. serv_addr.sun_family = AF_UNIX;
  259. /* This is a generic Unix domain socket. */
  260. strcpy(serv_addr.sun_path, socket_name);
  261. printf("Creating socket '%s'\n", serv_addr.sun_path);
  262. servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family) + 1;
  263. if (caller)
  264. {
  265. fprintf(stderr, "Connecting to '%s'\n", serv_addr.sun_path);
  266. if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
  267. {
  268. fprintf(stderr, "Connect failed - errno = %d\n", errno);
  269. exit(2);
  270. }
  271. fprintf(stderr, "Connected to '%s'\n", serv_addr.sun_path);
  272. }
  273. else
  274. {
  275. fprintf(stderr, "Listening to '%s'\n", serv_addr.sun_path);
  276. listensockfd = sockfd;
  277. /* The file may or may not exist. Just try to delete it anyway. */
  278. unlink(serv_addr.sun_path);
  279. if (bind(listensockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
  280. {
  281. fprintf(stderr, "Bind failed - errno = %d\n", errno);
  282. exit(2);
  283. }
  284. listen(listensockfd, 5);
  285. clilen = sizeof(cli_addr);
  286. if ((sockfd = accept(listensockfd, (struct sockaddr *) &cli_addr, &clilen)) < 0)
  287. {
  288. fprintf(stderr, "Accept failed - errno = %d", errno);
  289. exit(2);
  290. }
  291. fprintf(stderr, "Accepted on '%s'\n", serv_addr.sun_path);
  292. }
  293. if (pseudo_terminal_create(&s->modem))
  294. {
  295. fprintf(stderr, "Failed to create pseudo TTY\n");
  296. exit(2);
  297. }
  298. s->audio_fd = sockfd;
  299. s->pty_fd = s->modem.master;
  300. return s;
  301. }
  302. /*- End of function --------------------------------------------------------*/
  303. int socket_harness_release(socket_harness_state_t *s)
  304. {
  305. return 0;
  306. }
  307. /*- End of function --------------------------------------------------------*/
  308. int socket_harness_free(socket_harness_state_t *s)
  309. {
  310. free(s);
  311. return 0;
  312. }
  313. /*- End of function --------------------------------------------------------*/
  314. /*- End of file ------------------------------------------------------------*/