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.

184 lines
5.2KB

  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. }
  70. void
  71. Server::run ( void )
  72. {
  73. int server; /* server socket */
  74. if ( ( server = listen_on_port( _port ) ) < 0 )
  75. /* error */;
  76. fd_set master;
  77. fd_set read_fds;
  78. int maxfd;
  79. FD_ZERO( &master );
  80. FD_ZERO( &read_fds );
  81. FD_SET( server, &master );
  82. maxfd = server;
  83. for ( ;; )
  84. {
  85. read_fds = master;
  86. if ( select( maxfd + 1, &read_fds, NULL, NULL, NULL ) == -1 )
  87. {
  88. perror( "select()" );
  89. /* error */
  90. }
  91. /* service connections */
  92. /* FIXME: there's a better way to do this than cover *all* fds. */
  93. for ( int i = 2; i < maxfd + 1; ++i )
  94. {
  95. if ( FD_ISSET( i, &read_fds ) )
  96. {
  97. if ( i == server )
  98. {
  99. struct sockaddr_in ca;
  100. socklen_t al = sizeof( ca );
  101. int c;
  102. if ( ( c = accept( server, (struct sockaddr *)&ca, &al ) ) < 0 )
  103. perror( "accept()" );
  104. FD_SET( c, &master );
  105. if ( c > maxfd )
  106. maxfd = c;
  107. handle_new( c );
  108. // printf( "New connection from %s on socket %d\n", inet_ntoa( ca.sin_addr ), c );
  109. }
  110. else
  111. {
  112. char buf[ BUFSIZ ];
  113. int l;
  114. if ( ( l = recv( i, buf, sizeof( buf ), 0 ) ) <= 0 )
  115. {
  116. if ( l == 0 )
  117. {
  118. handle_hang_up( i );
  119. }
  120. else
  121. perror( "recv()" );
  122. close( i );
  123. FD_CLR( i, &master );
  124. }
  125. else
  126. {
  127. if ( echos() )
  128. /* echo to others */
  129. for ( int j = maxfd; j-- ; )
  130. {
  131. if ( ! FD_ISSET( j, &master ) )
  132. continue;
  133. if ( j != server && j != i )
  134. {
  135. if ( send( j, buf, l, 0 ) < 0 )
  136. perror( "send()" );
  137. }
  138. }
  139. buf[ l ] = '\0';
  140. handle_request( i, buf, l );
  141. }
  142. }
  143. }
  144. }
  145. }
  146. }