Commit ee01ac19 (v4.3.23) enlarged player member hostaddr from 32 to
46 characters, but missed natstr member nat_hostaddr. player_main()
copies hostaddr to nat_hostaddr. Can overrun the destination, but
fortunately just into nat_hostname.
Impact:
* Can makes praddr() print only a suffix of the address. Used by play
command, for player messages during login and logout, and for
logging.
* Can make player_main()'s test for "same address as last time" fail,
causing extra "Last connection" messages.
* Matching against econfig key privip is not affected.
* Journal event login is not affected.
Deities can customize which commodities can be sold in table item.
Default is to allow anything but civilians and military. However,
this applies only to the commodity market, not to the unit market:
cargo of ships and land units is not restricted.
Make the two markets consistent: permit selling military by default,
forbid selling units carrying unsalable commodities. This outlaws
selling units carrying civilians by default.
Planes flying one-way with crew or cargo spread plague from their old
base to their new base. Planes dropping cargo spread plague from
their base to the drop's target sector.
New function reads and returns target sector/ship. Avoids reading the
target sector unnecessarily. Callers receive the target ship, not
just its number. Next commit will put it to use.
It was renamed to play_lock because it synchronized not just updates
but also shutdown. Since the previous commit, it again only
synchronizes updates. Rename it back.
Also move its initialization next to shutdown_lock's.
shutdwn() sets the EOF indicator, aborts the running command, if any,
forbids sleeping on I/O and wakes up the player thread, for all player
threads in state PS_PLAYING. It takes play_lock to prevent new
commands from running. It then waits up to 3s for player threads to
terminate, by polling player_next(), to let output buffers drain.
Issues:
1. Polling is lame.
2. New player threads can still enter state PS_PLAYING. They'll block
as soon as they try to run a command. Somehwat unclean.
3. We can exit before all player threads left state PS_PLAYING, losing
a treasury update, play time update, and log entries. Could happen
when player threads blocked on output until commit 90b3abc5 fixed
that; its commit message describes the bug's impact in more detail.
Since then, the bug shouldn't bite in practice, because player
threads should leave state PS_PLAYING quickly.
Fix by introducing shutdown_lock: player threads in state PS_PLAYING
hold it shared, shutdwn() takes it exclusive, instead of play_lock.
Takes care of the issues as follows:
3. shutdwn() waits until all player threads left state PS_PLAYING, no
matter how long it takes them.
2. New player threads block before entering state PS_PLAYING.
1. shutdwn() still polls up to 3s for player threads to terminate.
Still lame. Left for another day.
max_idle applies in state PS_PLAYING, login_grace_time before (login,
state PS_INIT) and after (logout, state PS_SHUTDOWN).
Cut login_grace_time to two minutes, from max_idle's 15. Two minutes
is plenty to complete login and logout. Makes swamping the server
with connections slightly harder, as they get dropped faster. While
that makes sense all by itself, the real aim is making increasing
max_idle safe. The next commit will complete that job.
Idle timeout used to expire max_idle minutes after the last
player->curup update. When we got rid of the idle thread in commit
08b94556 (v4.3.20), this got changed to "wait no more than max_idle
minutes for input". Time spent computing and time spent blocked on
output no longer counts. In particular, a connection can block
indefinitely on output since then. Let's fix that.
Start with basing the input timeout on player->curup again. The
missing output timeout will be added shortly.
Aside: since status() updates player->curup, the idle timer gets reset
when the update aborts a command. Left for another day.
Commit 08b94556 (v4.3.20) added io_open() parameter input_timeout. It
applies to io_input() and, since commit 904822e3, to io_close(). Add
timeout parameters to these functions instead.
Create new command capability NONVIS. Give it to players in any state
except visitors (and STAT_UNUSED, but those must not exist). This
makes it possible to have commands available to anyone but visitors.
Command change fails when the player is a visitor. Simply make it
unavailable instead, by requiring NONVIS.
Make read unavailable to visitors, because it's useless: visitors
can't receive telegrams (typed_wu() fails).
Make census, commodity and sinfra unavailable to visitors. Visitors
don't normally have sectors.
Make map and nmap unavailable to visitors. Visitors don't have sectors,
so their maps are always empty.
Make them unavailable to new players (between add and newcap) and
players in sanctuary, too. This is consistent with all the other
commands to examine the environment. It also prevents people from
trying multiple unbroken countries in a blitz to find the one with the
nicest vicinity.
Make resource available to new players, for consistency with census
and commodity.
Make country, echo and financial available to anyone.
A player may execute a command when his player->nstat has all the bits
in the command's c_permit.
Normal player commands require bit(2). Command break requires bit(1),
and execute requires bit(5). Deity commands require both bit(2) and
bit(3). Works, because deities always have both bits set in nstat, as
they may execute normal player commands, too. But it's a bit
confusing. Change them to only require their own bit(3).
A player may execute a command when his player->nstat has all the bits
in the command's c_permit.
All commands require bit(0). All players always have it. Silly; get
rid of it.
Timeout during execute gets handled just like an EOF cookie: end the
batch file, resume reading normal commands. That's wrong, we need to
close the connection.
A real EOF is recorded in the player's connection's EOF indicator.
Let's use that for all "connection needs to be closed" conditions, so
they all work the same. Create io_set_eof() to provide access.
Make recvclient() set the player connection's EOF indicator on
timeout. This makes the timeout "stick". Record receipt of an EOF
cookie in new struct player member got_ctld. Also abort the command,
as before. This leaves further interpretation of the EOF cookie to
the command loops.
Make player_main() set the player connection's EOF indicator on
got_ctld. Player connection gets closed on on EOF cookie, as before.
Change execute() to break the batch command loop when got_ctld is set,
then reset it. Ends the batch file on EOF cookie, as before.
Change status() back to checking EOF and error indicators (partial
revert of commit 9c5854c8, v4.3.16), and drop struct player member
eof.
Adjacent telegrams are squashed together if type and sender are the
same, and the timestamp is "close enough". This is done in two
places: rea() and typed_wu(). They're inconsistent: typed_wu()
ignores the timestamp for production reports since Empire 2, but rea()
doesn't.
Record typed_wu()'s decision in new telstr member tel_cont. Use it in
rea().
When units somehow get stuck on a dead carrier, a new build reusing
the dead carrier's UID picks up its cargo. The cargo gets teleported
to its new carrier when the carrier moves.
Oops when a ship, plane or land unit is created with cargo. To
recover, destroy the cargo.
Commit e3cf1e32 (v4.3.27) created make_stale_if_command_arg() to
permit catching more potential yields on input. Unfortunately, the
implementation of navigate and march sub-commands 'r', 'l' and 's'
breaks it.
do_unit_move() reads units into a unit list at the beginning and at
each stop. It writes them back when they move or sweep. If a unit
changed in the file in between, the changes would get wiped out.
Therefore, do_unit_move() must not yield between stops.
do_unit_move() parses sub-commands into player->argp[], then supplies
defaults for missing arguments, so that code using them (radar(),
do_look(), sona(), mine(), landmine()) won't prompt for missing
arguments. Unclean and brittle. See also commit 28cc236e and commit
45106ab9.
Unfortunately, make_stale_if_command_arg() doesn't recognize the
difference between these defaulted arguments and parsed arguments, so
it makes objects stale, even though the defaulted arguments can't be
missing. If a move or sweep follows, it triggers a false positive
generation oops.
To fix, test "points into argument buffer" (only true for parsed
arguments) instead of "is in player->argp[]". Requires making the
argument buffer accessible: new struct player member argbuf[]. Use it
for parsing commands, in command(), execute(), do_unit_move(). Don't
use it in emp_config(), player_login(), move_ground(), because these
parse something else.
pln_zap_transient_flags() fixes up planes stuck in the air (commit
7ca4f412, v4.3.12). Since commit 4e9e58bf (v4.3.14), it writes back
the fixed planes. This is wrong for empdump.
empdump should touch data only on successful import. When it fails
because ef_verify() fails, and any planes are found stuck in the air,
the plane file gets rewritten.
Make parameter ef_verify() take parameter may_put to let empdump
suppress the plane write-back. The plane file still get written out
on successful import, along with the other imported game state.
verify_row() refrains from rejecting zero uids, because some tables
may contain blank entries, with zero uid.
Change it to check only header sanity for entries that are not in use.
This filters out all legitimately blank entries. Tighten up the uid
check.
For computing "in use", factor empobj_in_use() out of xdvisible().
Note that xdvisible()'s case EF_COUNTRY doesn't bother to check
nat_stat, because that's implied by what it does check. It's not
implied in empobj_in_use(), so add it there.
Spy units are now enabled when a land unit type with capability spy
exists. To disable them, deities have to customize table land-chr.
Before, spy units types were ignored when option LANDSPIES was
disabled. Except for xdump land-chr, which happily dumped unusable
spy unit types.
Trade ships are now enabled when a ship type with capability trade
exists. No such type exists by default; to enable trade ships,
deities have to customize table ship-chr.
Before, trade ship types were ignored when option TRADESHIPS was
disabled. Except for xdump ship-chr, which happily dumped unusable
trade ship types.