diff --git a/TShockAPI/Net/DisconnectMsg.cs b/TShockAPI/Net/DisconnectMsg.cs
new file mode 100644
index 00000000..e838280e
--- /dev/null
+++ b/TShockAPI/Net/DisconnectMsg.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Microsoft.Xna.Framework;
+using TerrariaAPI;
+using XNAHelpers;
+
+namespace TShockAPI.Net
+{
+ class DisconnectMsg : BaseMsg
+ {
+ public override PacketTypes ID
+ {
+ get
+ {
+ return PacketTypes.Disconnect;
+ }
+ }
+ public string Reason {get;set;}
+ public override void Pack(Stream stream)
+ {
+ stream.WriteBytes(Encoding.ASCII.GetBytes(Reason));
+ }
+ }
+}
diff --git a/TShockAPI/PacketBufferer.cs b/TShockAPI/PacketBufferer.cs
index 4778e9dd..cd19f6ed 100644
--- a/TShockAPI/PacketBufferer.cs
+++ b/TShockAPI/PacketBufferer.cs
@@ -110,22 +110,18 @@ namespace TShockAPI
if (socket == null || !socket.active)
return false;
- if (!socket.tcpClient.Client.Poll(0, SelectMode.SelectWrite))
+ if (buffers[socket.whoAmI].Count < 1)
return false;
byte[] buff = buffers[socket.whoAmI].GetBytes(BytesPerUpdate);
if (buff == null)
return false;
-
- socket.tcpClient.Client.Send(buff);
- return true;
- }
- catch (ObjectDisposedException)
- {
- }
- catch (SocketException)
- {
+ if (SendBytes(socket, buff))
+ {
+ buffers[socket.whoAmI].Pop(buff.Length);
+ return true;
+ }
}
catch (Exception e)
{
@@ -140,12 +136,16 @@ namespace TShockAPI
buffers[socket.whoAmI] = new PacketBuffer();
}
- public void SendBytes(ServerSock socket, byte[] buffer)
+ public bool SendBytes(ServerSock socket, byte[] buffer)
{
- SendBytes(socket, buffer, 0, buffer.Length);
+ return SendBytes(socket, buffer, 0, buffer.Length);
+ }
+ public void BufferBytes(ServerSock socket, byte[] buffer)
+ {
+ BufferBytes(socket, buffer, 0, buffer.Length);
}
- public void SendBytes(ServerSock socket, byte[] buffer, int offset, int count)
+ public void BufferBytes(ServerSock socket, byte[] buffer, int offset, int count)
{
lock (buffers[socket.whoAmI])
{
@@ -164,10 +164,29 @@ namespace TShockAPI
}
}
+ public bool SendBytes(ServerSock socket, byte[] buffer, int offset, int count)
+ {
+ try
+ {
+ if (socket.tcpClient.Client != null && socket.tcpClient.Client.Poll(0, SelectMode.SelectWrite))
+ {
+ socket.tcpClient.Client.Send(buffer, offset, count, SocketFlags.None);
+ return true;
+ }
+ }
+ catch (ObjectDisposedException)
+ {
+ }
+ catch (SocketException)
+ {
+ }
+ return false;
+ }
+
void ServerHooks_SendBytes(ServerSock socket, byte[] buffer, int offset, int count, HandledEventArgs e)
{
e.Handled = true;
- SendBytes(socket, buffer, offset, count);
+ BufferBytes(socket, buffer, offset, count);
}
#if DEBUG_NET
static int Compress(byte[] buffer, int offset, int count)
@@ -195,9 +214,16 @@ namespace TShockAPI
var ret = new byte[Math.Min(max, this.Count)];
this.CopyTo(0, ret, 0, ret.Length);
- this.RemoveRange(0, ret.Length);
return ret;
}
}
+
+ public void Pop(int count)
+ {
+ lock (this)
+ {
+ this.RemoveRange(0, count);
+ }
+ }
}
}
diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs
index b57720cb..529c736f 100644
--- a/TShockAPI/Properties/AssemblyInfo.cs
+++ b/TShockAPI/Properties/AssemblyInfo.cs
@@ -36,5 +36,5 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("3.2.7.0817")]
-[assembly: AssemblyFileVersion("3.2.7.0817")]
+[assembly: AssemblyVersion("3.2.8.0818")]
+[assembly: AssemblyFileVersion("3.2.8.0818")]
diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs
index a59fbc57..e63b65bb 100644
--- a/TShockAPI/TSPlayer.cs
+++ b/TShockAPI/TSPlayer.cs
@@ -156,7 +156,6 @@ namespace TShockAPI
public virtual void Disconnect(string reason)
{
SendData(PacketTypes.Disconnect, reason);
- Flush();
}
public virtual void Flush()
diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs
index 397a7ab7..9e0e258b 100644
--- a/TShockAPI/TShock.cs
+++ b/TShockAPI/TShock.cs
@@ -40,6 +40,7 @@ using Terraria;
using TerrariaAPI;
using TerrariaAPI.Hooks;
using TShockAPI.DB;
+using TShockAPI.Net;
namespace TShockAPI
{
@@ -179,6 +180,7 @@ namespace TShockAPI
ServerHooks.Chat += OnChat;
ServerHooks.Command += ServerHooks_OnCommand;
NetHooks.GetData += OnGetData;
+ NetHooks.SendData += NetHooks_SendData;
NetHooks.GreetPlayer += OnGreetPlayer;
NpcHooks.StrikeNpc += NpcHooks_OnStrikeNpc;
@@ -212,6 +214,7 @@ namespace TShockAPI
ServerHooks.Chat -= OnChat;
ServerHooks.Command -= ServerHooks_OnCommand;
NetHooks.GetData -= OnGetData;
+ NetHooks.SendData -= NetHooks_SendData;
NetHooks.GreetPlayer -= OnGreetPlayer;
NpcHooks.StrikeNpc -= NpcHooks_OnStrikeNpc;
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
@@ -556,6 +559,9 @@ namespace TShockAPI
return;
PacketTypes type = e.MsgID;
+
+ Debug.WriteLine("Recv: {0:X}: {2} ({1:XX})", e.Msg.whoAmI, (byte)type, type);
+
var player = Players[e.Msg.whoAmI];
if (player == null)
{
@@ -569,7 +575,7 @@ namespace TShockAPI
return;
}
- //Debug.WriteLine("Recv: {0:X} ({2}): {3} ({1:XX})", player.Index, (byte)type, player.TPlayer.dead ? "dead " : "alive", type);
+
// Stop accepting updates from player as this player is going to be kicked/banned during OnUpdate (different thread so can produce race conditions)
if ((Config.BanKillTileAbusers || Config.KickKillTileAbusers) &&
@@ -656,10 +662,20 @@ namespace TShockAPI
{
if (PacketBuffer != null)
{
- PacketBuffer.SendBytes(client, bytes);
+ PacketBuffer.BufferBytes(client, bytes);
return true;
}
+ return SendBytesBufferless(client,bytes);
+ }
+ ///
+ /// Send bytes to a client ignoring the packet buffer
+ ///
+ /// socket to send to
+ /// bytes to send
+ /// False on exception
+ public static bool SendBytesBufferless(ServerSock client, byte[] bytes)
+ {
try
{
if (client.tcpClient.Connected)
@@ -668,11 +684,44 @@ namespace TShockAPI
}
catch (Exception ex)
{
+ Log.Warn("This is a normal exception");
Log.Warn(ex.ToString());
}
return false;
}
+ void NetHooks_SendData(SendDataEventArgs e)
+ {
+ if (e.MsgID == PacketTypes.Disconnect)
+ {
+ Action senddisconnect = (sock, str) =>
+ {
+ if (sock == null || !sock.active)
+ return;
+ using (var ms = new MemoryStream())
+ {
+ new DisconnectMsg {Reason = str}.PackFull(ms);
+ SendBytesBufferless(sock, ms.ToArray());
+ }
+ };
+
+ if (e.remoteClient != -1)
+ {
+ senddisconnect(Netplay.serverSock[e.remoteClient], e.text);
+ }
+ else
+ {
+ for (int i = 0; i < Netplay.serverSock.Length; i++)
+ {
+ if (e.ignoreClient != -1 && e.ignoreClient == i)
+ continue;
+
+ senddisconnect(Netplay.serverSock[i], e.text);
+ }
+ }
+ }
+ }
+
private void OnSaveWorld(bool resettime, HandledEventArgs e)
{
Tools.Broadcast("Saving world. Momentary lag might result from this.", Color.Red);
diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj
index 08f1fb60..9f680956 100644
--- a/TShockAPI/TShockAPI.csproj
+++ b/TShockAPI/TShockAPI.csproj
@@ -112,6 +112,7 @@
+
@@ -180,7 +181,7 @@
-
+