mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-08 22:59:29 -04:00
Fix can't connect to on Windows 98
This commit is contained in:
parent
9650b5bf2a
commit
1d82be4654
@ -22,6 +22,9 @@ using System.Windows.Forms;
|
||||
|
||||
namespace MCGalaxy.Gui
|
||||
{
|
||||
// NET 2.0 doesn't have Action delegate defined
|
||||
public delegate void UIAction();
|
||||
|
||||
/// <summary> Shortcuts for MessageBox.Show </summary>
|
||||
public static class Popup
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ namespace MCGalaxy.Gui
|
||||
propsZG.SelectedObject = zsSettings;
|
||||
}
|
||||
|
||||
public void RunOnUI_Async(Action act) { BeginInvoke(act); }
|
||||
public void RunOnUI_Async(UIAction act) { BeginInvoke(act); }
|
||||
|
||||
void PropertyWindow_Load(object sender, EventArgs e) {
|
||||
// try to use same icon as main window
|
||||
|
@ -28,8 +28,10 @@ using MCGalaxy.Generator;
|
||||
using MCGalaxy.Gui.Popups;
|
||||
using MCGalaxy.Tasks;
|
||||
|
||||
namespace MCGalaxy.Gui {
|
||||
public partial class Window : Form {
|
||||
namespace MCGalaxy.Gui
|
||||
{
|
||||
public partial class Window : Form
|
||||
{
|
||||
// for cross thread use
|
||||
delegate void StringCallback(string s);
|
||||
delegate void PlayerListCallback(List<Player> players);
|
||||
@ -237,7 +239,7 @@ Trying to mix two versions is unsupported - you may experience issues";
|
||||
RunOnUI_Async(() => main_btnProps.Enabled = true);
|
||||
}
|
||||
|
||||
public void RunOnUI_Async(Action act) { BeginInvoke(act); }
|
||||
public void RunOnUI_Async(UIAction act) { BeginInvoke(act); }
|
||||
|
||||
void Player_PlayerConnect(Player p) {
|
||||
RunOnUI_Async(() => {
|
||||
|
@ -115,7 +115,7 @@ namespace MCGalaxy.Network
|
||||
static void AcceptCallback(IAsyncResult result) {
|
||||
if (Server.shuttingDown) return;
|
||||
TcpListen listen = (TcpListen)result.AsyncState;
|
||||
TcpSocket s = null;
|
||||
INetSocket s = null;
|
||||
|
||||
try {
|
||||
Socket raw = listen.socket.EndAccept(result);
|
||||
@ -126,7 +126,13 @@ namespace MCGalaxy.Network
|
||||
// intentionally non-clean connection close
|
||||
try { raw.Close(); } catch { }
|
||||
} else {
|
||||
#if NET_20
|
||||
// TODO better non-hardcoded detection? move to OperatingSystem?
|
||||
s = Environment.OSVersion.Platform == PlatformID.Win32Windows ? (INetSocket)(new TcpLegacySocket(raw)) : (INetSocket)(new TcpSocket(raw));
|
||||
#else
|
||||
s = new TcpSocket(raw);
|
||||
#endif
|
||||
|
||||
if (announce) Logger.Log(LogType.UserActivity, s.IP + " connected to the server.");
|
||||
s.Init();
|
||||
}
|
||||
@ -139,7 +145,7 @@ namespace MCGalaxy.Network
|
||||
|
||||
public override void Close() {
|
||||
try {
|
||||
Listening = false;
|
||||
Listening = false;
|
||||
if (socket != null) socket.Close();
|
||||
} catch (Exception ex) {
|
||||
Logger.LogError(ex);
|
||||
|
@ -327,4 +327,135 @@ namespace MCGalaxy.Network
|
||||
return IPAddress.IsLoopback(ip) || ip.Equals(ccnetIP);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO avoid copying so much of TcpSocket
|
||||
#if NET_20
|
||||
/// <summary> Backwards compatible socket for older Windows versions where Recv/SendAsync doesn't work </summary>
|
||||
public sealed class TcpLegacySocket : INetSocket
|
||||
{
|
||||
readonly Socket socket;
|
||||
byte[] recvBuffer = new byte[256];
|
||||
|
||||
byte[] sendBuffer = new byte[4096];
|
||||
readonly object sendLock = new object();
|
||||
readonly Queue<byte[]> sendQueue = new Queue<byte[]>(64);
|
||||
volatile bool sendInProgress;
|
||||
|
||||
public TcpLegacySocket(Socket s) { socket = s; }
|
||||
|
||||
public override void Init() {
|
||||
ReceiveNextAsync();
|
||||
}
|
||||
|
||||
public override IPAddress IP {
|
||||
get { return SocketUtil.GetIP(socket); }
|
||||
}
|
||||
public override bool LowLatency { set { socket.NoDelay = value; } }
|
||||
|
||||
|
||||
static AsyncCallback recvCallback = RecvCallback;
|
||||
void ReceiveNextAsync() {
|
||||
socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 0, recvCallback, this);
|
||||
}
|
||||
|
||||
static void RecvCallback(IAsyncResult result) {
|
||||
TcpLegacySocket s = (TcpLegacySocket)result.AsyncState;
|
||||
if (s.Disconnected) return;
|
||||
|
||||
try {
|
||||
// If received 0, means socket was closed
|
||||
int recvLen = s.socket.EndReceive(result);
|
||||
if (recvLen == 0) { s.Disconnect(); return; }
|
||||
|
||||
s.HandleReceived(s.recvBuffer, recvLen);
|
||||
if (!s.Disconnected) s.ReceiveNextAsync();
|
||||
} catch (SocketException) {
|
||||
s.Disconnect();
|
||||
} catch (ObjectDisposedException) {
|
||||
// Socket was closed by another thread, mark as disconnected
|
||||
} catch (Exception ex) {
|
||||
Logger.LogError(ex);
|
||||
s.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static AsyncCallback sendCallback = SendCallback;
|
||||
public override void Send(byte[] buffer, SendFlags flags) {
|
||||
if (Disconnected || !socket.Connected) return;
|
||||
|
||||
// TODO: Low priority sending support
|
||||
try {
|
||||
if ((flags & SendFlags.Synchronous) != 0) {
|
||||
socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
|
||||
return;
|
||||
}
|
||||
|
||||
lock (sendLock) {
|
||||
if (sendInProgress) {
|
||||
sendQueue.Enqueue(buffer);
|
||||
} else {
|
||||
TrySendAsync(buffer);
|
||||
}
|
||||
}
|
||||
} catch (SocketException) {
|
||||
Disconnect();
|
||||
} catch (ObjectDisposedException) {
|
||||
// Socket was already closed by another thread
|
||||
}
|
||||
}
|
||||
|
||||
void TrySendAsync(byte[] buffer) {
|
||||
// BlockCopy has some overhead, not worth it for very small data
|
||||
if (buffer.Length <= 16) {
|
||||
for (int i = 0; i < buffer.Length; i++) {
|
||||
sendBuffer[i] = buffer[i];
|
||||
}
|
||||
} else {
|
||||
Buffer.BlockCopy(buffer, 0, sendBuffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
sendInProgress = true;
|
||||
socket.BeginSend(sendBuffer, 0, buffer.Length, 0, sendCallback, this);
|
||||
}
|
||||
|
||||
static void SendCallback(IAsyncResult result) {
|
||||
TcpLegacySocket s = (TcpLegacySocket)result.AsyncState;
|
||||
try {
|
||||
lock (s.sendLock) {
|
||||
s.socket.EndSend(result);
|
||||
s.sendInProgress = false;
|
||||
|
||||
if (s.sendQueue.Count > 0) {
|
||||
s.TrySendAsync(s.sendQueue.Dequeue());
|
||||
if (s.Disconnected) s.sendQueue.Clear();
|
||||
}
|
||||
}
|
||||
} catch (SocketException) {
|
||||
s.Disconnect();
|
||||
} catch (ObjectDisposedException) {
|
||||
// Socket was already closed by another thread
|
||||
} catch (Exception ex) {
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Close while also notifying higher level (i.e. show 'X disconnected' in chat)
|
||||
void Disconnect() {
|
||||
if (protocol != null) protocol.Disconnect();
|
||||
Close();
|
||||
}
|
||||
|
||||
public override void Close() {
|
||||
Disconnected = true;
|
||||
pending.Remove(this);
|
||||
|
||||
// swallow errors as connection is being closed anyways
|
||||
try { socket.Shutdown(SocketShutdown.Both); } catch { }
|
||||
try { socket.Close(); } catch { }
|
||||
|
||||
lock (sendLock) { sendQueue.Clear(); }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ namespace MCGalaxy.Scripting
|
||||
|
||||
// only used for resolving plugin DLLs depending on other plugin DLLs
|
||||
static Assembly ResolvePluginAssembly(object sender, ResolveEventArgs args) {
|
||||
#if !NET_20
|
||||
if (args.RequestingAssembly == null) return null;
|
||||
if (!IsPluginDLL(args.RequestingAssembly)) return null;
|
||||
|
||||
@ -57,6 +58,7 @@ namespace MCGalaxy.Scripting
|
||||
|
||||
Logger.Log(LogType.Warning, "Custom command/plugin [{0}] tried to load [{1}], but it could not be found",
|
||||
args.RequestingAssembly.FullName, args.Name);
|
||||
#endif
|
||||
return null;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user