Ejemplo n.º 1
0
void listen_channels(void){
    struct atc_conn *childConn;
    int result;
	while (1) {
        if (cur_clients + 1 < MAX_CLIENTS){
            childConn = &(nodes[cur_clients + 1].conn);
            result = atc_accept(&serverConn, childConn);
            if (result == -1) {
                puts("Could not accept connection.");
                return;
            }
            fork_client(childConn); 
        }
	}
    return;
}
Ejemplo n.º 2
0
static void
handle_new_connection(int newfd, int epfd)
{
    struct epoll_event ev;
    struct client_data *client;
    struct sockaddr_storage addr;
    socklen_t addrlen = sizeof (addr);
    char authbuf[AUTHBUFSIZE];
    int pos, is_reg, reconnect_id, authlen, userid;
    static int connection_id = 1;

    if (fd_to_client_max > newfd &&
        fd_to_client[newfd] == &new_connection_dummy) {
        epoll_ctl(epfd, EPOLL_CTL_DEL, newfd, &ev);
        fd_to_client[newfd] = NULL;
    }

    /* it should be possible to read immediately due to the "defer" sockopt */
    authlen = read(newfd, authbuf, AUTHBUFSIZE - 1);
    if (authlen <= 0) {
        close(newfd);
        return;
    }

    getpeername(newfd, (struct sockaddr *)&addr, &addrlen);
    log_msg("New connection from %s.", addr2str(&addr));

    authbuf[authlen] = '\0';    /* make it safe to use as a string */

    /* did we receive too much data? */
    if (authlen >= AUTH_MAXLEN) {
        log_msg("Auth buffer overrun attempt from %s? Peer disconnected.",
                addr2str(&addr));
        close(newfd);
        return;
    }

    /* check the end of the received auth data: a JSON object always ends with
       '}' */
    pos = authlen - 1;
    while (pos > 0 && isspace(authbuf[pos]))
        pos--;

    if (authbuf[pos] != '}') {  /* not the end of JSON auth data */
        log_msg("authentication for %s failed due to incomplete JSON",
                addr2str(&addr));
        return;
    }

    /* 
     * ready to authenticate the user here
     */
    userid = auth_user(authbuf, addr2str(&addr), &is_reg, &reconnect_id);
    if (userid <= 0) {
        if (!userid)
            auth_send_result(newfd, AUTH_FAILED_UNKNOWN_USER, is_reg, 0);
        else
            auth_send_result(newfd, AUTH_FAILED_BAD_PASSWORD, is_reg, 0);
        log_msg("authentication failed for %s", addr2str(&addr));
        close(newfd);
        return;
    }

    /* user ok, we'll keep this socket */
    ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET;
    ev.data.ptr = NULL;
    ev.data.fd = newfd;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, newfd, &ev) == -1) {
        log_msg("Error in epoll_ctl for %s: %s", addr2str(&addr),
                strerror(errno));
        close(newfd);
        return;
    }

    /* is the client re-establishing a connection to an existing, disconnected
       game? */
    for (client = disconnected_list_head.next; client; client = client->next)
        if (client->userid == userid &&
            (!reconnect_id || reconnect_id == client->connid))
            break;
    if (reconnect_id && !client) {
        /* now search through the active connections. The client might have a
           new IP address, which would leave the socket open and seemingly
           valid. */
        for (client = connected_list_head.next; client; client = client->next)
            if (client->userid == userid && reconnect_id == client->connid)
                break;
    }

    if (client) {
        /* there is a running, disconnected game process for this user */
        auth_send_result(newfd, AUTH_SUCCESS_RECONNECT, is_reg, client->connid);
        client->sock = newfd;
        map_fd_to_client(client->sock, client);
        client->state = CLIENT_CONNECTED;
        unlink_client_data(client);
        link_client_data(client, &connected_list_head);
        write(client->pipe_out, "\033", 1);     /* signal to reset the read
                                                   buffer */

        log_msg("Connection to game at pid %d reestablished for user %d",
                client->pid, client->userid);
        return;
    } else {
        client = alloc_client_data(&connected_list_head);
        client->state = CLIENT_CONNECTED;
        client->sock = newfd;
        map_fd_to_client(newfd, client);
        client->connid = connection_id++;
        client->userid = userid;
        /* there is no process yet */
        if (fork_client(client, epfd))
            auth_send_result(newfd, AUTH_SUCCESS_NEW, is_reg, client->connid);
        /* else: client communication is shutdown if fork_client errors out */
    }

    log_msg("There are now %d clients on the server", client_count);
}