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.

178 lines
5.1KB

  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. #define MAX_HOST_NAME 512
  31. /** open a socket listening on TCP port /port/. Returns -1 in case of error. */
  32. int
  33. Server::listen_on_port ( int port )
  34. {
  35. int s;
  36. char name[ MAX_HOST_NAME + 1 ];
  37. struct sockaddr_in sa;
  38. struct hostent *hp;
  39. memset( &sa, 0, sizeof( sa ) );
  40. gethostname( name, MAX_HOST_NAME );
  41. hp = gethostbyname( name );
  42. sa.sin_family = hp->h_addrtype;
  43. sa.sin_port = htons( port );
  44. sa.sin_addr.s_addr = INADDR_ANY;
  45. if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
  46. {
  47. printf( "Could not create command socket!" );
  48. return -1;
  49. }
  50. int yes = 1;
  51. if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char * )&yes, sizeof( int ) ) < 0 )
  52. {
  53. close( s );
  54. return -1;
  55. }
  56. if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
  57. {
  58. printf( "bind: %s", strerror( errno ) );
  59. close( s );
  60. return -1;
  61. }
  62. listen( s, 1 );
  63. return s;
  64. }
  65. Server::Server ( int port )
  66. {
  67. _port = port;
  68. }
  69. void
  70. Server::run ( void )
  71. {
  72. int server; /* server socket */
  73. if ( ( server = listen_on_port( _port ) ) < 0 )
  74. /* error */;
  75. fd_set master;
  76. fd_set read_fds;
  77. int maxfd;
  78. FD_ZERO( &master );
  79. FD_ZERO( &read_fds );
  80. FD_SET( server, &master );
  81. maxfd = server;
  82. for ( ;; )
  83. {
  84. read_fds = master;
  85. if ( select( maxfd + 1, &read_fds, NULL, NULL, NULL ) == -1 )
  86. {
  87. perror( "select()" );
  88. /* error */
  89. }
  90. /* service connections */
  91. /* FIXME: there's a better way to do this than cover *all* fds. */
  92. for ( int i = 2; i < maxfd + 1; ++i )
  93. {
  94. if ( FD_ISSET( i, &read_fds ) )
  95. {
  96. if ( i == server )
  97. {
  98. struct sockaddr_in ca;
  99. socklen_t al = sizeof( ca );
  100. int c;
  101. if ( ( c = accept( server, (struct sockaddr *)&ca, &al ) ) < 0 )
  102. perror( "accept()" );
  103. FD_SET( c, &master );
  104. if ( c > maxfd )
  105. maxfd = c;
  106. handle_new( c );
  107. // printf( "New connection from %s on socket %d\n", inet_ntoa( ca.sin_addr ), c );
  108. }
  109. else
  110. {
  111. char buf[ BUFSIZ ];
  112. int l;
  113. if ( ( l = recv( i, buf, sizeof( buf ), 0 ) ) <= 0 )
  114. {
  115. if ( l == 0 )
  116. {
  117. handle_hang_up( i );
  118. }
  119. else
  120. perror( "recv()" );
  121. close( i );
  122. FD_CLR( i, &master );
  123. }
  124. else
  125. {
  126. /* echo to others */
  127. for ( int j = maxfd; j-- ; )
  128. {
  129. if ( ! FD_ISSET( j, &master ) )
  130. continue;
  131. if ( j != server && j != i )
  132. {
  133. if ( send( j, buf, l, 0 ) < 0 )
  134. perror( "send()" );
  135. }
  136. }
  137. buf[ l ] = '\0';
  138. handle_request( buf, l );
  139. }
  140. }
  141. }
  142. }
  143. }
  144. }