コード例 #1
0
ファイル: c_tinyserve.c プロジェクト: kjseefried/SparForte
int manageConnections( SocketData *socket_data ) {
    int client_socket;
    struct sockaddr_in adr_clnt;
    struct timeval socket_timeout;
    int res;
    int c;

    socket_error = 0;
    prepare_for_select( socket_data );
    socket_timeout.tv_sec  = socket_data->timeout_secs;
    socket_timeout.tv_usec = socket_data->timeout_usecs;
    res = select( socket_data->max_fd, &socket_data->rd_set, NULL, NULL, &socket_timeout );
    if ( res < 0 ) {
       socket_error = errno;
       if ( socket_error == EINTR ) {
          client_socket = 0;
       } else {
          printf( "Select failed: %d\n", errno );
          client_socket = -1;
       }
    } else if ( res == 0 ) {
      // zero is a timeout
      client_socket = 0;
    } else if ( FD_ISSET( socket_data->socket_listener, &socket_data->rd_set ) ) {
      // New client connecting - what priority should this be?

retry:
     client_socket = accept( socket_data->socket_listener, (struct sockaddr *)&adr_clnt, &socket_data->len_inet );
     if ( client_socket < 0 ) {
       socket_error = errno;
       if ( socket_error == EINTR ) {
          goto retry;
       } else if ( socket_error == EAGAIN ) {
          // EAGAIN only occurs on non-blocking sockets to indicate no data yet
          socket_error = 0;
       } else {
          printf( "Accept failed: %d\n", errno );
          client_socket = -1;
       }
    } else if ( client_socket > FD_SETSIZE )  {
       printf( "Socket closed: at capacity - FD_SETSIZE exceeded\n" );
       close( client_socket );
       client_socket = -1;
    } else {
        if ( client_socket + 1 > socket_data->max_fd ) {
           socket_data->max_fd = client_socket + 1;
       }
       FD_SET( client_socket, &socket_data->so_set );
       // client_socket = 0; // nothing to do
    }
 } else {
    //printf( "Existing socket\n" );
    // existing client with new data
    // not very efficient here since accept may report multiple
    // clients but I'm only servicing one at a time.
    client_socket = 0;
    for ( c = 0 ; c < socket_data->max_fd ; ++c ) {
        if ( c == socket_data->socket_listener ) // should never occur
           continue;     // but ignore listener
        if ( FD_ISSET( c, &socket_data->rd_set ) )  {
           client_socket = c;
           break;
        }
    }
  }

  return client_socket;

} // get_client_connection
コード例 #2
0
ファイル: svrside.c プロジェクト: IIJ-NetBSD/netbsd-src
int
main(int argc, char **argv)
{
	TSS_RESULT result;
	int newsd, c, rv, option_index = 0;
	int i;
	socklen_t client_len;
	char *hostname = NULL;
	fd_set rdfd_set;
	int num_fds = 0;
	int nfds = 0;
	int stor_errno;
	sigset_t sigmask, termmask, oldsigmask;
	struct sockaddr_storage client_addr;
	struct srv_sock_info socks_info[MAX_IP_PROTO];
	struct passwd *pwd;
	struct option long_options[] = {
		{"help", 0, NULL, 'h'},
		{"foreground", 0, NULL, 'f'},
		{"config", 1, NULL, 'c'},
		{0, 0, 0, 0}
	};

	unsetenv("TCSD_USE_TCP_DEVICE");
	while ((c = getopt_long(argc, argv, "fhec:", long_options, &option_index)) != -1) {
		switch (c) {
			case 'f':
				setenv("TCSD_FOREGROUND", "1", 1);
				break;
			case 'c':
				tcsd_config_file = optarg;
				break;
			case 'e':
				setenv("TCSD_USE_TCP_DEVICE", "1", 1);
				break;
			case 'h':
				/* fall through */
			default:
				usage();
				return -1;
				break;
		}
	}

	if (!tcsd_config_file)
		tcsd_config_file = TCSD_DEFAULT_CONFIG_FILE;

	if ((result = tcsd_startup()))
		return (int)result;

#ifdef NOUSERCHECK
    LogWarn("will not switch user or check for file permissions. "
            "(Compiled with --disable-usercheck)");
#else
#ifndef SOLARIS
	pwd = getpwnam(TSS_USER_NAME);
	if (pwd == NULL) {
		if (errno == 0) {
			LogError("User \"%s\" not found, please add this user"
					" manually.", TSS_USER_NAME);
		} else {
			LogError("getpwnam(%s): %s", TSS_USER_NAME, strerror(errno));
		}
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}
	setuid(pwd->pw_uid);
#endif
#endif

	if (setup_server_sockets(socks_info) == -1) {
		LogError("Could not create sockets to listen to connections. Aborting...");
		return -1;
	}

	if (getenv("TCSD_FOREGROUND") == NULL) {
		if (daemon(0, 0) == -1) {
			perror("daemon");
			tcsd_shutdown(socks_info);
			return -1;
		}
	}

	LogInfo("%s: TCSD up and running.", PACKAGE_STRING);

	sigemptyset(&sigmask);
	sigaddset(&sigmask, SIGTERM);
	sigaddset(&sigmask, SIGHUP);

	sigemptyset(&termmask);
	sigaddset(&termmask, SIGTERM);

	do {
		prepare_for_select(socks_info, &num_fds, &rdfd_set, &nfds);
		// Sanity check
		if (num_fds == 0) {
			LogError("No server sockets available to listen connections. Aborting...");
			return -1;
		}

		// Block TERM and HUP signals to prevent race condition
		if (sigprocmask(SIG_BLOCK, &sigmask, &oldsigmask) == -1) {
			LogError("Error setting interrupt mask before accept");
		}

		// TERM and HUP are blocked here, so its safe to test flags.
		if (hup) {
			// Config reading can be slow, so unmask SIGTERM.
			if (sigprocmask(SIG_UNBLOCK, &termmask, NULL) == -1) {
				LogError("Error unblocking SIGTERM before config reload");
			}
			if (reload_config() != TSS_SUCCESS)
				LogError("Failed reloading config");
			if (sigprocmask(SIG_BLOCK, &termmask, NULL) == -1) {
				LogError("Error blocking SIGTERM after config reload");
			}
		}
		if (term)
			break;

		// Select IPv4 and IPv6 socket descriptors with appropriate sigmask.
		LogDebug("Waiting for connections");
		rv = pselect(nfds+1, &rdfd_set, NULL, NULL, NULL, &oldsigmask);
		stor_errno = errno; // original mask must be set ASAP, so store errno.
		if (sigprocmask(SIG_SETMASK, &oldsigmask, NULL) == -1) {
			LogError("Error reseting signal mask to the original configuration.");
		}
		if (rv == -1) {
			if (stor_errno != EINTR) {
				LogError("Error monitoring server socket descriptors.");
				return -1;
			}
			continue;
		}

		for (i=0; i < num_fds; i++) { // accept connections from all IP versions (with valid sd)
			if (!FD_ISSET(socks_info[i].sd, &rdfd_set)) {
				continue;
			}
			client_len = socks_info[i].addr_len;
			newsd = accept(socks_info[i].sd, (struct sockaddr *) &client_addr, &client_len);
			if (newsd < 0) {
				if (errno != EINTR)
					LogError("Failed accept: %s", strerror(errno));
				continue;
			}
			LogDebug("accepted socket %i", newsd);

			hostname = fetch_hostname(&client_addr, client_len);
			if (hostname == NULL)
				hostname=INVALID_ADDR_STR;

			tcsd_thread_create(newsd, hostname);
			hostname = NULL;
		} // for (i=0; i < MAX_IP_PROTO; i++)
	} while (term ==0);

	/* To close correctly, we must receive a SIGTERM */
	tcsd_shutdown(socks_info);
	return 0;
}