Assists music production by grouping standalone programs into sessions. Community version of "Non Session Manager".
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.

186 lines
5.3KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2008 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. #include "Server.H"
  19. #include <netdb.h>
  20. #include <netinet/in.h>
  21. #include <unistd.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <errno.h>
  26. #include <sys/socket.h>
  27. #include <sys/types.h>
  28. #include <sys/select.h>
  29. /* Generic TCP server class */
  30. /* */
  31. #define MAX_HOST_NAME 512
  32. /** open a socket listening on TCP port /port/. Returns -1 in case of error. */
  33. int
  34. Server::listen_on_port ( int port )
  35. {
  36. int s;
  37. char name[ MAX_HOST_NAME + 1 ];
  38. struct sockaddr_in sa;
  39. struct hostent *hp;
  40. memset( &sa, 0, sizeof( sa ) );
  41. gethostname( name, MAX_HOST_NAME );
  42. hp = gethostbyname( name );
  43. sa.sin_family = hp->h_addrtype;
  44. sa.sin_port = htons( port );
  45. sa.sin_addr.s_addr = INADDR_ANY;
  46. if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
  47. {
  48. printf( "Could not create command socket!" );
  49. return -1;
  50. }
  51. int yes = 1;
  52. if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char * )&yes, sizeof( int ) ) < 0 )
  53. {
  54. close( s );
  55. return -1;
  56. }
  57. if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
  58. {
  59. printf( "bind: %s", strerror( errno ) );
  60. close( s );
  61. return -1;
  62. }
  63. listen( s, 1 );
  64. return s;
  65. }
  66. Server::Server ( int port )
  67. {
  68. _port = port;
  69. _echo = false;
  70. _fork = false;
  71. }
  72. void
  73. Server::run ( void )
  74. {
  75. int server; /* server socket */
  76. if ( ( server = listen_on_port( _port ) ) < 0 )
  77. /* error */;
  78. fd_set master;
  79. fd_set read_fds;
  80. int maxfd;
  81. FD_ZERO( &master );
  82. FD_ZERO( &read_fds );
  83. FD_SET( server, &master );
  84. maxfd = server;
  85. for ( ;; )
  86. {
  87. read_fds = master;
  88. if ( select( maxfd + 1, &read_fds, NULL, NULL, NULL ) == -1 )
  89. {
  90. perror( "select()" );
  91. /* error */
  92. }
  93. /* service connections */
  94. /* FIXME: there's a better way to do this than cover *all* fds. */
  95. for ( int i = 2; i < maxfd + 1; ++i )
  96. {
  97. if ( FD_ISSET( i, &read_fds ) )
  98. {
  99. if ( i == server )
  100. {
  101. struct sockaddr_in ca;
  102. socklen_t al = sizeof( ca );
  103. int c;
  104. if ( ( c = accept( server, (struct sockaddr *)&ca, &al ) ) < 0 )
  105. perror( "accept()" );
  106. FD_SET( c, &master );
  107. if ( c > maxfd )
  108. maxfd = c;
  109. handle_new( c );
  110. // printf( "New connection from %s on socket %d\n", inet_ntoa( ca.sin_addr ), c );
  111. }
  112. else
  113. {
  114. char buf[ BUFSIZ ];
  115. int l;
  116. if ( ( l = recv( i, buf, sizeof( buf ), 0 ) ) <= 0 )
  117. {
  118. if ( l == 0 )
  119. {
  120. handle_hang_up( i );
  121. }
  122. else
  123. perror( "recv()" );
  124. close( i );
  125. FD_CLR( i, &master );
  126. }
  127. else
  128. {
  129. if ( echo() )
  130. /* echo to others */
  131. for ( int j = maxfd; j-- ; )
  132. {
  133. if ( ! FD_ISSET( j, &master ) )
  134. continue;
  135. if ( j != server && j != i )
  136. {
  137. if ( send( j, buf, l, 0 ) < 0 )
  138. perror( "send()" );
  139. }
  140. }
  141. buf[ l ] = '\0';
  142. handle_request( i, buf, l );
  143. }
  144. }
  145. }
  146. }
  147. }
  148. }