/** * Handle a connection attempt from a player : * - check the crc * - check server/user password (TODO) * - check if the player is already connected (TODO) * - initialize the player, add it to the pool * - notify the player if he has been accepted (or not TODO) * - notify the other players (TODO) * - move the player to the default channel (TODO) * * @param data the connection packet * @param len the length of the connection packet * @param cli_addr the adress of the client * @param cli_len the length of cli_addr */ void handle_player_connect(char *data, unsigned int len, struct sockaddr_in *cli_addr, unsigned int cli_len, struct server *s) { struct player *pl, *tmp_pl; char password[30]; char login[30]; struct registration *r; size_t iter; /* Check crc */ if (!packet_check_crc(data, len, 16)) return; /* Check if the IP is banned */ if (get_ban_by_ip(s, cli_addr->sin_addr) != NULL) { server_refuse_connection_ban(cli_addr, cli_len, s); logger(LOG_INFO, "PLAYER BANNED TRIED TO CONNECT"); return; } /* If registered, check if player exists, else check server password */ bzero(password, 30 * sizeof(char)); strncpy(password, data + 121, MIN(29, data[120])); bzero(login, 30 * sizeof(char)); strncpy(login, data + 91, MIN(29, data[90])); pl = new_player_from_data(data, len, cli_addr, cli_len); if (data[90] == 0) { /* no login = anonymous mode */ /* check password against server password */ if (strcmp(password, s->password) != 0) { destroy_player(pl); return; /* wrong server password */ } pl->global_flags = GLOBAL_FLAG_UNREGISTERED; } else { r = get_registration(s, login, password); if (r == NULL) { logger(LOG_INFO, "Invalid credentials for a registered player"); destroy_player(pl); return; /* nobody found with those credentials */ } pl->global_flags |= r->global_flags; pl->global_flags |= GLOBAL_FLAG_REGISTERED; pl->reg = r; } /* Add player to the pool */ add_player(s, pl); /* Send a message to the client indicating he has been accepted */ /* Send server information to the player (0xf4be0400) */ server_accept_connection(pl); /* Send a message to all players saying that a new player arrived (0xf0be6400) */ s_notify_new_player(pl); /* Send the new player the list of all the Voice Requests */ ar_each(struct player *, tmp_pl, iter, s->players) if (pl->player_attributes & PL_ATTR_REQUEST_VOICE) s_notify_player_requested_voice(tmp_pl, pl); ar_end_each; }
/** * Handle a keepalive sent by the client * - check the crc * - send a keepalive back to the client * * @param data the connection packet * @param len the length of the connection packet * @param cli_addr the adress of the client * @param cli_len the length of cli_addr */ void handle_player_keepalive(char *data, unsigned int len, struct server *s) { struct player *pl; char *ptr = data; uint32_t pub_id, priv_id, ka_id; /* Check crc */ if(!packet_check_crc(data, len, 16)) return; /* Retrieve the player */ ptr += 4; priv_id = ru32(&ptr); pub_id = ru32(&ptr); ka_id = ru32(&ptr); /* Get the counter */ pl = get_player_by_ids(s, pub_id, priv_id); if (pl == NULL) { logger(LOG_WARN, "handle_player_keepalive : pl == NULL. Why????"); return; } /* Send the keepalive response */ s_resp_keepalive(pl, ka_id); /* Update the last_ping field */ gettimeofday(&pl->last_ping, NULL); }
/** * Check the crc of a packet at the default offset * Most packets have the checksum at start+24 bytes, * but some have it at start+16 bytes. * * @param data the packet * @param len the length of the packet */ int packet_check_crc_d(char *data, size_t len) { return packet_check_crc(data, len, 20); }