PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lirc_srv.c

http://bdremote-ng.googlecode.com/
C | 257 lines | 170 code | 43 blank | 44 comment | 21 complexity | 257cd6a1ff0ee5b398e85da473dbef19 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * bdremoteng - helper daemon for Sony(R) BD Remote Control
  3. * Based on bdremoted, written by Anton Starikov <antst@mail.ru>.
  4. *
  5. * Copyright (C) 2009 Michael Wojciechowski <wojci@wojci.dk>
  6. *
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. /** \ingroup LIRC */
  24. /*@{*/
  25. /*! \file lirc_srv.c
  26. \brief Implements a LIRC server.
  27. This file implements a LIRC server. This means listening for a
  28. socket for connections from LIRC and accepting new clients. Added
  29. client are broadcast keypresses in other part of this application -
  30. see lirc_thr.c.
  31. The lirc_server() function is the one to examine in order to
  32. understand how this module works.
  33. */
  34. #include "lirc_srv.h"
  35. #include <globaldefs.h>
  36. #define _GNU_SOURCE
  37. #include <stdio.h>
  38. #include <errno.h>
  39. #include <fcntl.h>
  40. #include <unistd.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <syslog.h>
  44. #include <signal.h>
  45. #include <getopt.h>
  46. #ifndef __USE_GNU
  47. /* Define this to avoid a warning about implicit definition of
  48. ppoll.*/
  49. # define __USE_GNU
  50. #endif
  51. #include <sys/poll.h>
  52. #include <sys/ioctl.h>
  53. #include <sys/socket.h>
  54. /* #include <poll.h> */
  55. #include <netinet/in.h>
  56. #include <assert.h>
  57. static const unsigned int moduleMask = MODULEMASK_LIRC_SOCK;
  58. /** Indicates that a TERM signal was received which interrupted IO. */
  59. volatile sig_atomic_t __io_canceled = 0;
  60. void add_client(lirc_data* _lircdata);
  61. int create_listener(configuration* _config, lirc_data* _lircdata);
  62. void initLircData(lirc_data* _ld, const configuration* _config)
  63. {
  64. assert(_config != NULL);
  65. assert(
  66. pthread_mutex_init (&_ld->dataMutex, NULL) == 0
  67. );
  68. #if BDREMOTE_DEBUG
  69. _ld->magic0 = 0x15;
  70. #endif /* BDREMOTE_DEBUG */
  71. _ld->config = _config;
  72. _ld->sockinet = -1;
  73. _ld->charge_percent = 100;
  74. _ld->charge_percent_set = 0;
  75. pthread_mutex_lock (&_ld->dataMutex);
  76. memset(&_ld->clis[0], 0, MAX_CLIENTS);
  77. _ld->clin = 0;
  78. pthread_mutex_unlock (&_ld->dataMutex);
  79. assert(queueInit(&_ld->qu) == Q_OK);
  80. }
  81. void destroyLircData(lirc_data* _ld)
  82. {
  83. queueDeinit(&_ld->qu);
  84. _ld->config = NULL;
  85. assert(_ld->clin == 0);
  86. assert(_ld->sockinet == BDREMOTE_FAIL);
  87. pthread_mutex_destroy (&_ld->dataMutex);
  88. }
  89. int lirc_server(configuration* _config, lirc_data* _lircdata)
  90. {
  91. struct pollfd p;
  92. sigset_t sigs;
  93. int i = 0;
  94. if (create_listener(_config, _lircdata) == BDREMOTE_FAIL)
  95. {
  96. return BDREMOTE_FAIL;
  97. }
  98. sigfillset(&sigs);
  99. sigdelset(&sigs, SIGCHLD);
  100. sigdelset(&sigs, SIGPIPE);
  101. sigdelset(&sigs, SIGTERM);
  102. sigdelset(&sigs, SIGINT);
  103. sigdelset(&sigs, SIGHUP);
  104. p.fd = _lircdata->sockinet;
  105. p.events = POLLIN | POLLERR | POLLHUP;
  106. while (!__io_canceled)
  107. {
  108. p.revents = 0;
  109. if (ppoll(&p, 1, NULL, &sigs) < 1)
  110. {
  111. continue;
  112. }
  113. if (p.events & POLLIN)
  114. {
  115. BDREMOTE_DBG(_config->debug, "new client accepted.");
  116. add_client(_lircdata);
  117. }
  118. }
  119. pthread_mutex_lock (&_lircdata->dataMutex);
  120. /* Close all client sockets. */
  121. for(i=0;i<_lircdata->clin;i++)
  122. {
  123. shutdown(_lircdata->clis[i],2);
  124. close(_lircdata->clis[i]);
  125. }
  126. _lircdata->clin = 0;
  127. pthread_mutex_unlock (&_lircdata->dataMutex);
  128. shutdown(_lircdata->sockinet,2);
  129. close(_lircdata->sockinet);
  130. _lircdata->sockinet = BDREMOTE_FAIL;
  131. return BDREMOTE_OK;
  132. }
  133. int create_listener(configuration* _config, lirc_data* _lircdata)
  134. {
  135. int enable=1;
  136. unsigned short int port=_config->listen_port;
  137. struct sockaddr_in serv_addr_in;
  138. /* create socket*/
  139. _lircdata->sockinet=socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
  140. if (_lircdata->sockinet==-1)
  141. {
  142. perror("socket");
  143. BDREMOTE_DBG(_config->debug, "Could not create TCP/IP socket.");
  144. return BDREMOTE_FAIL;
  145. }
  146. (void) setsockopt(_lircdata->sockinet,SOL_SOCKET,SO_REUSEADDR,&enable,sizeof(enable));
  147. serv_addr_in.sin_family = AF_INET;
  148. serv_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
  149. serv_addr_in.sin_port = htons(port);
  150. if (bind(_lircdata->sockinet,(struct sockaddr *) &serv_addr_in,
  151. sizeof(serv_addr_in))==-1)
  152. {
  153. BDREMOTE_DBG(_config->debug, "Could not assign address to socket\n");
  154. perror("bind");
  155. close(_lircdata->sockinet);
  156. return BDREMOTE_FAIL;
  157. }
  158. listen(_lircdata->sockinet,3);
  159. nolinger(_lircdata->sockinet);
  160. return BDREMOTE_OK;
  161. }
  162. void add_client(lirc_data* _lircdata)
  163. {
  164. struct sockaddr client_addr;
  165. socklen_t clilen = sizeof(client_addr);
  166. int flags = 0;
  167. int fd = accept(_lircdata->sockinet,(struct sockaddr *)&client_addr, &clilen);
  168. if (fd==-1)
  169. {
  170. BDREMOTE_DBG(_lircdata->config->debug,
  171. "accept() failed for new client.");
  172. perror("accept");
  173. };
  174. if(fd>=FD_SETSIZE || _lircdata->clin>=MAX_CLIENTS)
  175. {
  176. BDREMOTE_DBG(_lircdata->config->debug,
  177. "Connection rejected.");
  178. shutdown(fd,2);
  179. close(fd);
  180. return;
  181. }
  182. nolinger(fd);
  183. flags=fcntl(fd, F_GETFL, 0);
  184. if(flags!=-1)
  185. {
  186. fcntl(fd,F_SETFL,flags|O_NONBLOCK);
  187. }
  188. pthread_mutex_lock (&_lircdata->dataMutex);
  189. _lircdata->clis[_lircdata->clin++]=fd;
  190. pthread_mutex_unlock (&_lircdata->dataMutex);
  191. }
  192. /* Only called from LIRC thread, mutex already locked. */
  193. void remove_client(lirc_data* _lircdata, int fd)
  194. {
  195. int i;
  196. for(i=0;i<_lircdata->clin;i++)
  197. {
  198. if(_lircdata->clis[i] == fd)
  199. {
  200. shutdown(_lircdata->clis[i],2);
  201. close(_lircdata->clis[i]);
  202. _lircdata->clin--;
  203. for(;i<_lircdata->clin;i++)
  204. {
  205. _lircdata->clis[i]=_lircdata->clis[i+1];
  206. }
  207. return;
  208. }
  209. }
  210. }
  211. /*@}*/