Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions WorldServer/District/Listener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,25 +121,30 @@ private void handleDistrict(object client)
}
try
{
// Issue #10: the old teardown iterated DistrictsTcp in insertion
// order, broke after the FIRST entry, and removed the code of
// whichever district registered first — not the dying one. With
// multiple districts the dead entry stayed listed and its
// re-registering replacement was rejected until a world restart.
lock (DistrictsTcp)
{
foreach (KeyValuePair<TcpClient, uint> dtcp in DistrictsTcp)
uint code;
if (DistrictsTcp.TryGetValue(tcpClient, out code))
{
lock (Districts)
{
foreach (KeyValuePair<uint, District> dis in Districts)
District dis;
if (Districts.TryGetValue(code, out dis))
{
if (dis.Key == dtcp.Value)
{
Log.Error("Listener", dis.Value.ToString() + " disconnected!");
break;
}
Log.Error("Listener", dis.ToString() + " disconnected!");
}
Districts.Remove(dtcp.Value);
break;
// Remove exactly this connection's registration.
// Idempotent: harmless when a re-registration already
// replaced the entry after the old socket died.
Districts.Remove(code);
}
DistrictsTcp.Remove(tcpClient);
}
DistrictsTcp.Remove(tcpClient);
}
tcpClient.Close();
}
Expand Down
17 changes: 15 additions & 2 deletions WorldServer/District/RegisterDistrict.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,28 @@ public static void Register(District district, TcpClient tcpClient, int type, by
{
if (dist.Value.IP == ip && Program.districtsListener.Districts.ContainsKey(code))
{
district.tcp.Client.Send(new byte[] { 0x30, 0x31 });
// Same-IP re-registration: replace the stale
// entry and reply with a SINGLE success byte-pair
// (0x33), identical to a fresh registration. The
// old 0x31 prelude made the reply TWO 2-byte
// messages for one registration; the
// DistrictServer's one-reply parser could not
// frame it (the trailing 0x33 leaked into its
// control-record stream and killed the
// connection loop).
Program.districtsListener.Districts.Remove(code);
break;
}
else if (dist.Value.IP != ip && Program.districtsListener.Districts.ContainsKey(code))
{
Log.Error("RegisterDistrict", "Fail try of district registration that already exists!");
district.tcp.Client.Send(new byte[] { 0x30, 0x32 });
break;
// Reject cleanly: do NOT fall through to the
// register+0x33 below. The old fall-through added
// the rejected district anyway and crashed on the
// duplicate key, leaving the socket open.
district.tcp.Client.Disconnect(true);
return;
}
}
Program.districtsListener.Districts.Add(code, district);
Expand Down