Fix racy detection of ally rejecting flashes

sendmessage() checked NF_FLASH on two places: when deciding whether to
send the message, and later when telling the player why it didn't send
a flash.  This can race with the toggle command as follows: if a flash
could not be sent because the recipient's NF_FLASH was off, and the
recipient toggled it on before the flag was checked again, the flash
command claimed the sender wasn't logged on.
This commit is contained in:
Markus Armbruster 2011-02-05 11:09:37 +01:00
parent 53a4fc6e26
commit fc633a4f1f

View file

@ -119,7 +119,7 @@ sendmessage(struct natstr *us, struct natstr *to, char *message, int verbose)
struct player *other; struct player *other;
struct tm *tm; struct tm *tm;
time_t now; time_t now;
int sent = 0; int sent = 0, rejected = 0;
struct natstr *wto; struct natstr *wto;
time(&now); time(&now);
@ -127,16 +127,18 @@ sendmessage(struct natstr *us, struct natstr *to, char *message, int verbose)
for (other = player_next(NULL); other; other = player_next(other)) { for (other = player_next(NULL); other; other = player_next(other)) {
if (other->state != PS_PLAYING) if (other->state != PS_PLAYING)
continue; continue;
if (player == other)
continue;
if (to && other->cnum != to->nat_cnum) if (to && other->cnum != to->nat_cnum)
continue; continue;
if (!(wto = getnatp(other->cnum))) if (!(wto = getnatp(other->cnum)))
continue; continue;
if (!to && !player->god && getrel(wto, player->cnum) != ALLIED) if (!to && !player->god && getrel(wto, player->cnum) != ALLIED)
continue; continue;
if (!player->god && !(wto->nat_flags & NF_FLASH)) if (!player->god && !(wto->nat_flags & NF_FLASH)) {
continue; rejected++;
if (player == other)
continue; continue;
}
if (verbose) if (verbose)
if (to) if (to)
pr_flash(other, "FLASH from %s (#%d) @ %02d:%02d%s\n", pr_flash(other, "FLASH from %s (#%d) @ %02d:%02d%s\n",
@ -162,14 +164,13 @@ sendmessage(struct natstr *us, struct natstr *to, char *message, int verbose)
else else
pr("No-one is logged in\n"); pr("No-one is logged in\n");
} }
if (to && !player->god) { if (to && !player->god && getrel(to, player->cnum) == ALLIED) {
/* If they are allied with us, we would normally see that /* If they are allied with us, we would normally see that
* they are logged in anyway, so just tell us */ * they are logged in anyway, so just tell us */
if ((getrel(to, player->cnum) == ALLIED) && !sent) { if (rejected)
if (to->nat_flags & NF_FLASH)
pr("%s is not logged on\n", to->nat_cnam);
else
pr("%s is not accepting flashes\n", to->nat_cnam); pr("%s is not accepting flashes\n", to->nat_cnam);
else if (!sent) {
pr("%s is not logged on\n", to->nat_cnam);
} }
} }
return 0; return 0;