Beispiel #1
0
char * shmon_callback(shm_packet_t * packet) {
	shmon_packet_t * shmon_packet = (shmon_packet_t*)packet->dat;
	switch(shmon_packet->cmd) {
	case SHMON_CTRL_GRAB_PID: {
		/* Allocate shell and return its pid */
		/* Read the user from shared memory */
		char * user = shmon_packet->username;
		/* See if he is already logged in (through the hashmap) */
		if(hashmap_contains(multishell_sessions, user)) {
			/* return the user's pid instead of the new one (if he's logged in) */
			return respond_to_client((int)hashmap_get(multishell_sessions, user));
		} else {
			/* the user is not logged in, spawn new shell */
			spawn_shell(shells_forked, user);
			return respond_to_client(get_pid_from_hash(shells_forked++));
		}
		break;
	}
	case SHMON_CTRL_ADD_USR: {
		/* Add a user to the hashmap */
		/* Read the user from shared memory */
		char * user = shmon_packet->username;
		int pid = atoi(shmon_packet->cmd_dat);
		hashmap_set(multishell_sessions, user, (void*)pid);
		break;
	}
	case SHMON_CTRL_GET_USR: {
		/* Get a user from the hashmap */
		/* Grab process pid from user IF he exists */
		/* Read the user from shared memory */
		char * user = shmon_packet->username;
		if(hashmap_contains(multishell_sessions, user))
			return respond_to_client((int)hashmap_get(multishell_sessions, user));
		else
			return respond_to_client(-1);
		break;
	}
	case SHMON_CTRL_REDIR: {
		/* Sends packet to the destination process, causing that process to 'wake up'. */
		char packet_dest[SHM_MAX_ID_SIZE];
		sprintf(packet_dest, SHMON_CLIENT_LOGIN_FORMAT, atoi(shmon_packet->cmd_dat));
		char shm_msg[16] = SHMON_MSG_PROC_WAKE;

		shm_packet_t * pack = create_packet(shmon_server, packet_dest, SHM_DEV_CLIENT, shm_msg, strlen(shm_msg));
		shman_send_to_network_clear(shmon_server, pack, 0);

		free(pack);
		break;
	}
	}

	char * ret = malloc(SHM_MAX_PACKET_DAT_SIZE);
	ret[0] = 1; /* just tells it is finished really. The client won't be expecting data to return, so it's not important what number we put here */
	return ret;
}
Beispiel #2
0
void *serve_loop(void *listenFD)
{
	Request req = {0};
	int connectionFD;

	while (1)
	{
		pthread_mutex_lock(&lock);

		if ((connectionFD = accept_connection((long) listenFD)) == -1)
		{
			pthread_mutex_unlock(&lock);
			continue;
		}

		pthread_mutex_unlock(&lock);

		if (client_request(connectionFD, &req) != 3)
			goto FREE;

		respond_to_client(connectionFD, &req);

FREE:
		close(connectionFD);

		free(req.method);
		req.method = NULL;
		free(req.resource);
		req.resource = NULL;
		free(req.protocol);
		req.protocol = NULL;
	}
}
/*
 *
 *  Function: main()
 *
 */
int main(int argc, char *argv[])
{
	char *program_name = argv[0];
	int optc;		/* option */
	sa_family_t family;	/* protocol family */
	char *portnum = NULL;	/* port number */
	int sock_fd;		/* socket binded open ports */
	int background = 0;	/* work in the background if non-zero */
	fd_set read_fds;	/* list of file descriptor for reading */
	int max_read_fd = 0;	/* maximum number in the read fds */
	FILE *info_fp = stdout;	/* FILE pointer to a information file */
	int on;			/* on/off at an socket option */
	int err;		/* return value of getaddrinfo */
	struct addrinfo hints;	/* hints for getaddrinfo() */
	struct addrinfo *res;	/* pointer to addrinfo */

	debug = 0;
	family = PF_UNSPEC;

	/* Retrieve the options */
	while ((optc = getopt(argc, argv, "f:p:bo:dh")) != EOF) {
		switch (optc) {
		case 'f':
			if (strncmp(optarg, "4", 1) == 0)
				family = PF_INET;	/* IPv4 */
			else if (strncmp(optarg, "6", 1) == 0)
				family = PF_INET6;	/* IPv6 */
			else {
				fprintf(stderr,
					"protocol family should be 4 or 6.\n");
				usage(program_name, EXIT_FAILURE);
			}
			break;

		case 'p':
			{
				unsigned long int num;
				num = strtoul(optarg, NULL, 0);
				if (num < PORTNUMMIN || PORTNUMMAX < num) {
					fprintf(stderr,
						"The range of port is from %u to %u\n",
						PORTNUMMIN, PORTNUMMAX);
					usage(program_name, EXIT_FAILURE);
				}
				portnum = strdup(optarg);
			}
			break;

		case 'b':
			background = 1;
			break;

		case 'o':
			if ((info_fp = fopen(optarg, "w")) == NULL) {
				fprintf(stderr, "Cannot open %s\n", optarg);
				exit(EXIT_FAILURE);
			}
			break;

		case 'd':
			debug = 1;
			break;

		case 'h':
			usage(program_name, EXIT_SUCCESS);
			break;

		default:
			usage(program_name, EXIT_FAILURE);
		}
	}

	/* Check the family is spefied. */
	if (family == PF_UNSPEC) {
		fprintf(stderr, "protocol family should be specified.\n");
		usage(program_name, EXIT_FAILURE);
	}

	/* At first, SIGHUP is ignored. */
	handler.sa_handler = SIG_IGN;
	if (sigfillset(&handler.sa_mask) < 0)
		fatal_error("sigfillset()");
	handler.sa_flags = 0;

	if (sigaction(SIGHUP, &handler, NULL) < 0)
		fatal_error("sigaction()");

	/* Set the hints to addrinfo() */
	memset(&hints, '\0', sizeof(struct addrinfo));
	hints.ai_family = family;
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_protocol = IPPROTO_UDP;
	hints.ai_flags = AI_PASSIVE;

	/* Translate the network and service information of the server */
	err = getaddrinfo(NULL, portnum, &hints, &res);
	if (err) {
		fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(err));
		exit(EXIT_FAILURE);
	}
	if (res->ai_next) {
		fprintf(stderr, "getaddrinfo(): multiple address is found.");
		exit(EXIT_FAILURE);
	}

	/* Create a socket for listening. */
	sock_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock_fd < 0)
		fatal_error("socket()");

#ifdef IPV6_V6ONLY
	/* Don't accept IPv4 mapped address if the protocol family is IPv6 */
	if (res->ai_family == PF_INET6) {
		on = 1;
		if (setsockopt
		    (sock_fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)))
			fatal_error("setsockopt()");
	}
#endif

	/* Enable to reuse the socket */
	on = 1;
	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)))
		fatal_error("setsockopt()");

	/* Bind to the local address */
	if (bind(sock_fd, res->ai_addr, res->ai_addrlen) < 0)
		fatal_error("bind()");

	freeaddrinfo(res);

	/* If -b option is specified, work as a daemon */
	if (background)
		if (daemon(0, 0) < 0)
			fatal_error("daemon()");

	/* Output any server information to the information file */
	fprintf(info_fp, "PID: %u\n", getpid());
	fflush(info_fp);
	if (info_fp != stdout)
		if (fclose(info_fp))
			fatal_error("fclose()");

	/* Catch SIGHUP */
	handler.sa_handler = set_signal_flag;
	if (sigaction(SIGHUP, &handler, NULL) < 0)
		fatal_error("sigaction()");

	/* Loop to wait a client access */
	FD_ZERO(&read_fds);
	FD_SET(sock_fd, &read_fds);
	max_read_fd = sock_fd;
	for (;;) {
		int select_ret;	/* return value of select() */
		fd_set active_fds;	/* list of the active file descriptor */
		struct timeval select_timeout;	/* timeout for select() */

		/* When catch SIGHUP, exit the loop */
		if (catch_sighup)
			break;

		active_fds = read_fds;
		select_timeout.tv_sec = 0;	/* 0.5 sec */
		select_timeout.tv_usec = 500000;

		select_ret = select(max_read_fd + 1, &active_fds,
				    NULL, NULL, &select_timeout);
		if (select_ret < 0) {
			if (catch_sighup)
				break;
			else
				fatal_error("select()");
		} else if (select_ret == 0) {
			continue;
		} else {
			if (FD_ISSET(sock_fd, &active_fds))
				respond_to_client(sock_fd);
		}
	}

	/* Close the sockets */
	if (close(sock_fd))
		fatal_error("close()");

	exit(EXIT_SUCCESS);
}
Beispiel #4
0
void serve_clients(struct server *s, struct frame_buffers *fbs, double timeout) {
	fd_set read_set, write_set;
	int select_result, sock, client_sock, highest_sock_num = max(s->sock4, s->sock6);
    struct sockaddr_storage client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    struct client *c;
    struct timeval timeout_tv;
    double now;

    while (timeout > 0) {
        FD_ZERO(&read_set);
        FD_ZERO(&write_set);

        if (s->sock4 >= 0) {
            FD_SET(s->sock4, &read_set);
        }

        if (s->sock6 >= 0) {
            FD_SET(s->sock6, &read_set);
        }

        for (sock = 0; sock < FD_SETSIZE; sock++) {
            c = s->clients[sock];
            if (c != NULL) {
                FD_SET(c->sock, &read_set);
                FD_SET(c->sock, &write_set);
                highest_sock_num = max(highest_sock_num, c->sock);
            }
        }

        double_to_timeval(timeout, &timeout_tv);
        now = gettime();
        if ((select_result = select(highest_sock_num + 1, &read_set, &write_set, NULL, &timeout_tv)) < 0) {
            serrchk("select() failed");
        }

        if (!select_result) {
            break;
        }

        for (sock = 0; sock <= highest_sock_num; sock++) {

            // Look over read_set
            if (FD_ISSET(sock, &read_set)) {
                if (sock == s->sock4 || sock == s->sock6) {
                    // Accept client
                    if ((client_sock = accept(sock, (struct sockaddr *) &client_addr, &client_addr_len)) < 0) {
                        serrchk("accept() failed");
                    }
                    
                    add_client(s, client_sock, &client_addr, fbs);
                    continue;
                }
                else {
                    c = s->clients[sock];
                    if (c != NULL) {
                        read_request(s, c, fbs);
                    }
                }
            }

            // Look over write set
            if (FD_ISSET(sock, &write_set)) {
                c = s->clients[sock];
                if (c != NULL) {
                    respond_to_client(s, c);
                }
            }

            // Prune clinets that are not communicating
            if ((c = s->clients[sock]) != NULL) {
                if (now - c->last_communication > KEEP_ALIVE_TIMEOUT) {
                    remove_client(s, c);
                }
            }

        }

        timeout -= gettime() - now;
    }
}