/************************************************************************** Log player tech messages. **************************************************************************/ void real_tech_log(const char *file, const char *function, int line, enum log_level level, bool notify, const struct player *pplayer, struct advance *padvance, const char *msg, ...) { char buffer[500]; char buffer2[500]; va_list ap; if (!valid_advance(padvance) || advance_by_number(A_NONE) == padvance) { return; } fc_snprintf(buffer, sizeof(buffer), "%s::%s (want %d, dist %d) ", player_name(pplayer), advance_name_by_player(pplayer, advance_number(padvance)), pplayer->ai_common.tech_want[advance_index(padvance)], num_unknown_techs_for_goal(pplayer, advance_number(padvance))); va_start(ap, msg); fc_vsnprintf(buffer2, sizeof(buffer2), msg, ap); va_end(ap); cat_snprintf(buffer, sizeof(buffer), "%s", buffer2); if (notify) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } do_log(file, function, line, FALSE, level, "%s", buffer); }
/************************************************************************** Log city messages, they will appear like this 2: Polish Romenna(5,35) [s1 d106 u11 g1] must have Archers ... **************************************************************************/ void real_city_log(const char *file, const char *function, int line, enum log_level level, bool notify, const struct city *pcity, const char *msg, ...) { char buffer[500]; char buffer2[500]; va_list ap; char aibuf[500] = "\0"; CALL_PLR_AI_FUNC(log_fragment_city, city_owner(pcity), aibuf, sizeof(aibuf), pcity); fc_snprintf(buffer, sizeof(buffer), "%s %s(%d,%d) [s%d] {%s} ", nation_rule_name(nation_of_city(pcity)), city_name(pcity), TILE_XY(pcity->tile), city_size_get(pcity), aibuf); va_start(ap, msg); fc_vsnprintf(buffer2, sizeof(buffer2), msg, ap); va_end(ap); cat_snprintf(buffer, sizeof(buffer), "%s", buffer2); if (notify) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } do_log(file, function, line, FALSE, level, "%s", buffer); }
/************************************************************************** Log player tech messages. **************************************************************************/ void TECH_LOG(int level, const struct player *pplayer, struct advance *padvance, const char *msg, ...) { char buffer[500]; char buffer2[500]; va_list ap; int minlevel = MIN(LOGLEVEL_TECH, level); if (!valid_advance(padvance) || advance_by_number(A_NONE) == padvance) { return; } if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_TECH)) { minlevel = LOG_TEST; } else if (minlevel > fc_log_level) { return; } my_snprintf(buffer, sizeof(buffer), "%s::%s (want %d, dist %d) ", player_name(pplayer), advance_name_by_player(pplayer, advance_number(padvance)), pplayer->ai_data.tech_want[advance_index(padvance)], num_unknown_techs_for_goal(pplayer, advance_number(padvance))); va_start(ap, msg); my_vsnprintf(buffer2, sizeof(buffer2), msg, ap); va_end(ap); cat_snprintf(buffer, sizeof(buffer), "%s", buffer2); if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_TECH)) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } freelog(minlevel, "%s", buffer); }
/************************************************************************** Log city messages, they will appear like this 2: Polish Romenna(5,35) [s1 d106 u11 g1] must have Archers ... **************************************************************************/ void CITY_LOG(int level, const struct city *pcity, const char *msg, ...) { char buffer[500]; char buffer2[500]; va_list ap; int minlevel = MIN(LOGLEVEL_CITY, level); if (pcity->debug) { minlevel = LOG_TEST; } else if (minlevel > fc_log_level) { return; } my_snprintf(buffer, sizeof(buffer), "%s %s(%d,%d) [s%d d%d u%d g%d] ", nation_rule_name(nation_of_city(pcity)), city_name(pcity), TILE_XY(pcity->tile), pcity->size, pcity->ai->danger, pcity->ai->urgency, pcity->ai->grave_danger); va_start(ap, msg); my_vsnprintf(buffer2, sizeof(buffer2), msg, ap); va_end(ap); cat_snprintf(buffer, sizeof(buffer), "%s", buffer2); if (pcity->debug) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } freelog(minlevel, "%s", buffer); }
/************************************************************************** Print results **************************************************************************/ void TIMING_RESULTS(void) { char buf[200]; #ifdef LOG_TIMERS #define AILOG_OUT(text, which) \ fc_snprintf(buf, sizeof(buf), " %s: %g sec turn, %g sec game", text, \ timer_read_seconds(aitimer[which][0]), \ timer_read_seconds(aitimer[which][1])); \ log_test("%s", buf); \ notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buf); log_test(" --- AI timing results ---"); #else /* LOG_TIMERS */ #define AILOG_OUT(text, which) \ fc_snprintf(buf, sizeof(buf), " %s: %g sec turn, %g sec game", text, \ timer_read_seconds(aitimer[which][0]), \ timer_read_seconds(aitimer[which][1])); \ notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buf); #endif /* LOG_TIMERS */ notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, " --- AI timing results ---"); AILOG_OUT("Total AI time", AIT_ALL); AILOG_OUT("Movemap", AIT_MOVEMAP); AILOG_OUT("Units", AIT_UNITS); AILOG_OUT(" - Military", AIT_MILITARY); AILOG_OUT(" - Attack", AIT_ATTACK); AILOG_OUT(" - Defense", AIT_DEFENDERS); AILOG_OUT(" - Ferry", AIT_FERRY); AILOG_OUT(" - Rampage", AIT_RAMPAGE); AILOG_OUT(" - Bodyguard", AIT_BODYGUARD); AILOG_OUT(" - Recover", AIT_RECOVER); AILOG_OUT(" - Caravan", AIT_CARAVAN); AILOG_OUT(" - Hunter", AIT_HUNTER); AILOG_OUT(" - Airlift", AIT_AIRLIFT); AILOG_OUT(" - Diplomat", AIT_DIPLOMAT); AILOG_OUT(" - Air", AIT_AIRUNIT); AILOG_OUT(" - Explore", AIT_EXPLORER); AILOG_OUT("fstk", AIT_FSTK); AILOG_OUT("Settlers", AIT_SETTLERS); AILOG_OUT("Workers", AIT_WORKERS); AILOG_OUT("Government", AIT_GOVERNMENT); AILOG_OUT("Taxes", AIT_TAXES); AILOG_OUT("Cities", AIT_CITIES); AILOG_OUT(" - Buildings", AIT_BUILDINGS); AILOG_OUT(" - Danger", AIT_DANGER); AILOG_OUT(" - Worker want", AIT_CITY_TERRAIN); AILOG_OUT(" - Military want", AIT_CITY_MILITARY); AILOG_OUT(" - Settler want", AIT_CITY_SETTLERS); AILOG_OUT("Citizen arrange", AIT_CITIZEN_ARRANGE); AILOG_OUT("Tech", AIT_TECH); }
/************************************************************************** Log unit messages, they will appear like this 2: Polish Archers[139] (5,35)->(0,0){0,0} stays to defend city where [] is unit id, ()->() are coordinates present and goto, and {,} contains bodyguard and ferryboat ids. **************************************************************************/ void UNIT_LOG(int level, const struct unit *punit, const char *msg, ...) { char buffer[500]; char buffer2[500]; va_list ap; int minlevel = MIN(LOGLEVEL_UNIT, level); int gx, gy; bool messwin = FALSE; /* output to message window */ if (punit->debug) { minlevel = LOG_TEST; } else { /* Are we a virtual unit evaluated in a debug city?. */ if (punit->id == 0) { struct city *pcity = tile_city(punit->tile); if (pcity && pcity->debug) { minlevel = LOG_TEST; messwin = TRUE; } } if (minlevel > fc_log_level) { return; } } if (punit->goto_tile) { gx = punit->goto_tile->x; gy = punit->goto_tile->y; } else { gx = gy = -1; } my_snprintf(buffer, sizeof(buffer), "%s %s[%d] %s (%d,%d)->(%d,%d){%d,%d} ", nation_rule_name(nation_of_unit(punit)), unit_rule_name(punit), punit->id, get_activity_text(punit->activity), TILE_XY(punit->tile), gx, gy, punit->ai.bodyguard, punit->ai.ferryboat); va_start(ap, msg); my_vsnprintf(buffer2, sizeof(buffer2), msg, ap); va_end(ap); cat_snprintf(buffer, sizeof(buffer), "%s", buffer2); if (punit->debug || messwin) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } freelog(minlevel, "%s", buffer); }
/************************************************************************** Receives a password from a client and verifies it. **************************************************************************/ bool handle_authentication_reply(struct connection *pconn, char *password) { char msg[MAX_LEN_MSG]; if (pconn->server.status == AS_REQUESTING_NEW_PASS) { /* check if the new password is acceptable */ if (!is_good_password(password, msg)) { if (pconn->server.auth_tries++ >= MAX_AUTH_TRIES) { reject_new_connection(_("Sorry, too many wrong tries..."), pconn); freelog(LOG_NORMAL, _("%s was rejected: Too many wrong password " "verifies for new user."), pconn->username); return FALSE; } else { dsend_packet_authentication_req(pconn, AUTH_NEWUSER_RETRY, msg); return TRUE; } } /* the new password is good, create a database entry for * this user; we establish the connection in handle_db_lookup */ create_md5sum((unsigned char *)password, strlen(password), pconn->server.password); if (!auth_db_save(pconn)) { notify_conn(pconn->self, NULL, E_CONNECTION, ftc_warning, _("Warning: There was an error in saving to the database. " "Continuing, but your stats will not be saved.")); freelog(LOG_ERROR, "Error writing to database for: %s", pconn->username); } establish_new_connection(pconn); } else if (pconn->server.status == AS_REQUESTING_OLD_PASS) { if (authdb_check_password(pconn, password, strlen(password)) == 1) { establish_new_connection(pconn); } else { pconn->server.status = AS_FAILED; pconn->server.auth_tries++; pconn->server.auth_settime = time(NULL) + auth_fail_wait[pconn->server.auth_tries]; } } else { freelog(LOG_VERBOSE, "%s is sending unrequested auth packets", pconn->username); return FALSE; } return TRUE; }
/************************************************************************** Log message for bodyguards. They will appear like this 2: Polish Mech. Inf.[485] bodyguard (38,22){Riflemen:574@37,23} was ... note that these messages are likely to wrap if long. **************************************************************************/ void BODYGUARD_LOG(int level, const struct unit *punit, const char *msg) { char buffer[500]; int minlevel = MIN(LOGLEVEL_BODYGUARD, level); const struct unit *pcharge; const struct city *pcity; int id = -1; int charge_x = -1; int charge_y = -1; const char *type = "guard"; const char *s = "none"; if (punit->debug) { minlevel = LOG_TEST; } else if (minlevel > fc_log_level) { return; } pcity = game_find_city_by_number(punit->ai.charge); pcharge = game_find_unit_by_number(punit->ai.charge); if (pcharge) { charge_x = pcharge->tile->x; charge_y = pcharge->tile->y; id = pcharge->id; type = "bodyguard"; s = unit_rule_name(pcharge); } else if (pcity) { charge_x = pcity->tile->x; charge_y = pcity->tile->y; id = pcity->id; type = "cityguard"; s = city_name(pcity); } /* else perhaps the charge died */ my_snprintf(buffer, sizeof(buffer), "%s %s[%d] %s (%d,%d){%s:%d@%d,%d} ", nation_rule_name(nation_of_unit(punit)), unit_rule_name(punit), punit->id, type, TILE_XY(punit->tile), s, id, charge_x, charge_y); cat_snprintf(buffer, sizeof(buffer), "%s", msg); if (punit->debug) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } freelog(minlevel, "%s", buffer); }
/************************************************************************** Log unit messages, they will appear like this 2: Polish Archers[139] (5,35)->(0,0){0,0} stays to defend city where [] is unit id, ()->() are coordinates present and goto, and {,} contains bodyguard and ferryboat ids. **************************************************************************/ void real_unit_log(const char *file, const char *function, int line, enum log_level level, bool notify, const struct unit *punit, const char *msg, ...) { char buffer[500]; char buffer2[500]; va_list ap; int gx, gy; char aibuf[500] = "\0"; CALL_PLR_AI_FUNC(log_fragment_unit, unit_owner(punit), aibuf, sizeof(aibuf), punit); if (punit->goto_tile) { index_to_map_pos(&gx, &gy, tile_index(punit->goto_tile)); } else { gx = gy = -1; } fc_snprintf(buffer, sizeof(buffer), "%s %s[%d] %s (%d,%d)->(%d,%d){%s} ", nation_rule_name(nation_of_unit(punit)), unit_rule_name(punit), punit->id, get_activity_text(punit->activity), TILE_XY(unit_tile(punit)), gx, gy, aibuf); va_start(ap, msg); fc_vsnprintf(buffer2, sizeof(buffer2), msg, ap); va_end(ap); cat_snprintf(buffer, sizeof(buffer), "%s", buffer2); if (notify) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } do_log(file, function, line, FALSE, level, "%s", buffer); }
/************************************************************************** Log player messages, they will appear like this where ti is timer, co countdown and lo love for target, who is e. **************************************************************************/ void DIPLO_LOG(int level, const struct player *pplayer, const struct player *aplayer, const char *msg, ...) { char buffer[500]; char buffer2[500]; va_list ap; int minlevel = MIN(LOGLEVEL_PLAYER, level); const struct ai_dip_intel *adip; if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_DIPLOMACY)) { minlevel = LOG_TEST; } else if (minlevel > fc_log_level) { return; } /* Don't use ai_data_get since it can have side effects. */ adip = ai_diplomacy_get(pplayer, aplayer); my_snprintf(buffer, sizeof(buffer), "%s->%s(l%d,c%d,d%d%s): ", player_name(pplayer), player_name(aplayer), pplayer->ai_data.love[player_index(aplayer)], adip->countdown, adip->distance, adip->is_allied_with_enemy ? "?" : (adip->at_war_with_ally ? "!" : "")); va_start(ap, msg); my_vsnprintf(buffer2, sizeof(buffer2), msg, ap); va_end(ap); cat_snprintf(buffer, sizeof(buffer), "%s", buffer2); if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_DIPLOMACY)) { notify_conn(NULL, NULL, E_AI_DEBUG, ftc_log, "%s", buffer); } freelog(minlevel, "%s", buffer); }
/************************************************************************** handle authentication of a user; called by handle_login_request() if authentication is enabled. if the connection is rejected right away, return FALSE, otherwise return TRUE **************************************************************************/ bool authenticate_user(struct connection *pconn, char *username) { char tmpname[MAX_LEN_NAME] = "\0"; /* assign the client a unique guest name/reject if guests aren't allowed */ if (is_guest_name(username)) { if (srvarg.auth_allow_guests) { sz_strlcpy(tmpname, username); get_unique_guest_name(username); if (strncmp(tmpname, username, MAX_LEN_NAME) != 0) { notify_conn(pconn->self, NULL, E_CONNECTION, ftc_warning, _("Warning: the guest name '%s' has been " "taken, renaming to user '%s'."), tmpname, username); } sz_strlcpy(pconn->username, username); establish_new_connection(pconn); } else { reject_new_connection(_("Guests are not allowed on this server. " "Sorry."), pconn); freelog(LOG_NORMAL, _("%s was rejected: Guests not allowed."), username); return FALSE; } } else { /* we are not a guest, we need an extra check as to whether a * connection can be established: the client must authenticate itself */ char buffer[MAX_LEN_MSG]; sz_strlcpy(pconn->username, username); switch(auth_db_load(pconn)) { case AUTH_DB_ERROR: if (srvarg.auth_allow_guests) { sz_strlcpy(tmpname, pconn->username); get_unique_guest_name(tmpname); /* don't pass pconn->username here */ sz_strlcpy(pconn->username, tmpname); freelog(LOG_ERROR, "Error reading database; connection -> guest"); notify_conn(pconn->self, NULL, E_CONNECTION, ftc_warning, _("There was an error reading the user " "database, logging in as guest connection '%s'."), pconn->username); establish_new_connection(pconn); } else { reject_new_connection(_("There was an error reading the user database " "and guest logins are not allowed. Sorry"), pconn); freelog(LOG_NORMAL, _("%s was rejected: Database error and guests not allowed."), pconn->username); return FALSE; } break; case AUTH_DB_SUCCESS: /* we found a user */ my_snprintf(buffer, sizeof(buffer), _("Enter password for %s:"), pconn->username); dsend_packet_authentication_req(pconn, AUTH_LOGIN_FIRST, buffer); pconn->server.auth_settime = time(NULL); pconn->server.status = AS_REQUESTING_OLD_PASS; break; case AUTH_DB_NOT_FOUND: /* we couldn't find the user, he is new */ if (srvarg.auth_allow_newusers) { sz_strlcpy(buffer, _("Enter a new password (and remember it).")); dsend_packet_authentication_req(pconn, AUTH_NEWUSER_FIRST, buffer); pconn->server.auth_settime = time(NULL); pconn->server.status = AS_REQUESTING_NEW_PASS; } else { reject_new_connection(_("This server allows only preregistered " "users. Sorry."), pconn); freelog(LOG_NORMAL, _("%s was rejected: Only preregistered users allowed."), pconn->username); return FALSE; } break; default: assert(0); break; } return TRUE; } return TRUE; }