using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace SharpQuake
{
	internal class net_datagram : INetDriver
	{
		public static net_datagram Instance
		{
			get
			{
				return net_datagram._Singletone;
			}
		}

		private static string StrAddr(EndPoint ep)
		{
			return ep.ToString();
		}

		private void Stats_f()
		{
			if (cmd.Argc == 1)
			{
				Con.Print("unreliable messages sent   = %i\n", new object[]
				{
					net.UnreliableMessagesSent
				});
				Con.Print("unreliable messages recv   = %i\n", new object[]
				{
					net.UnreliableMessagesReceived
				});
				Con.Print("reliable messages sent     = %i\n", new object[]
				{
					net.MessagesSent
				});
				Con.Print("reliable messages received = %i\n", new object[]
				{
					net.MessagesReceived
				});
				Con.Print("packetsSent                = %i\n", new object[]
				{
					this.packetsSent
				});
				Con.Print("packetsReSent              = %i\n", new object[]
				{
					this.packetsReSent
				});
				Con.Print("packetsReceived            = %i\n", new object[]
				{
					this.packetsReceived
				});
				Con.Print("receivedDuplicateCount     = %i\n", new object[]
				{
					this.receivedDuplicateCount
				});
				Con.Print("shortPacketCount           = %i\n", new object[]
				{
					this.shortPacketCount
				});
				Con.Print("droppedDatagrams           = %i\n", new object[]
				{
					this.droppedDatagrams
				});
				return;
			}
			if (cmd.Argv(1) == "*")
			{
				foreach (qsocket_t s in net.ActiveSockets)
				{
					this.PrintStats(s);
				}
				using (IEnumerator<qsocket_t> enumerator = net.FreeSockets.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						qsocket_t s2 = enumerator.Current;
						this.PrintStats(s2);
					}
					return;
				}
			}
			qsocket_t qsocket_t = null;
			string b = cmd.Argv(1);
			foreach (qsocket_t qsocket_t2 in net.ActiveSockets)
			{
				if (common.SameText(qsocket_t2.address, b))
				{
					qsocket_t = qsocket_t2;
					break;
				}
			}
			if (qsocket_t == null)
			{
				foreach (qsocket_t qsocket_t3 in net.FreeSockets)
				{
					if (common.SameText(qsocket_t3.address, b))
					{
						qsocket_t = qsocket_t3;
						break;
					}
				}
			}
			if (qsocket_t == null)
			{
				return;
			}
			this.PrintStats(qsocket_t);
		}

		private void PrintStats(qsocket_t s)
		{
			Con.Print("canSend = {0:4}   \n", new object[]
			{
				s.canSend
			});
			Con.Print("sendSeq = {0:4}   ", new object[]
			{
				s.sendSequence
			});
			Con.Print("recvSeq = {0:4}   \n", new object[]
			{
				s.receiveSequence
			});
			Con.Print("\n", Array.Empty<object>());
		}

		private net_datagram()
		{
			this._PacketBuffer = new byte[1032];
		}

		public string Name
		{
			get
			{
				return "Datagram";
			}
		}

		public bool IsInitialized
		{
			get
			{
				return this._IsInitialized;
			}
		}

		public void Init()
		{
			this._DriverLevel = Array.IndexOf<INetDriver>(net.Drivers, this);
			cmd.Add("net_stats", new xcommand_t(this.Stats_f));
			if (common.HasParam("-nolan"))
			{
				return;
			}
			INetLanDriver[] lanDrivers = net.LanDrivers;
			for (int i = 0; i < lanDrivers.Length; i++)
			{
				lanDrivers[i].Init();
			}
			this._IsInitialized = true;
		}

		public void Listen(bool state)
		{
			foreach (INetLanDriver netLanDriver in net.LanDrivers)
			{
				if (netLanDriver.IsInitialized)
				{
					netLanDriver.Listen(state);
				}
			}
		}

		public void SearchForHosts(bool xmit)
		{
			net.LanDriverLevel = 0;
			while (net.LanDriverLevel < net.LanDrivers.Length && net.HostCacheCount != 8)
			{
				if (net.LanDrivers[net.LanDriverLevel].IsInitialized)
				{
					this.InternalSearchForHosts(xmit);
				}
				net.LanDriverLevel++;
			}
		}

		public qsocket_t Connect(string host)
		{
			qsocket_t qsocket_t = null;
			net.LanDriverLevel = 0;
			while (net.LanDriverLevel < net.LanDrivers.Length)
			{
				if (net.LanDrivers[net.LanDriverLevel].IsInitialized)
				{
					qsocket_t = this.InternalConnect(host);
					if (qsocket_t != null)
					{
						break;
					}
				}
				net.LanDriverLevel++;
			}
			return qsocket_t;
		}

		public qsocket_t CheckNewConnections()
		{
			qsocket_t qsocket_t = null;
			net.LanDriverLevel = 0;
			while (net.LanDriverLevel < net.LanDrivers.Length)
			{
				if (net.LanDriver.IsInitialized)
				{
					qsocket_t = this.InternalCheckNewConnections();
					if (qsocket_t != null)
					{
						break;
					}
				}
				net.LanDriverLevel++;
			}
			return qsocket_t;
		}

		public qsocket_t InternalCheckNewConnections()
		{
			Socket socket = net.LanDriver.CheckNewConnections();
			if (socket == null)
			{
				return null;
			}
			EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
			net.Message.FillFrom(socket, ref endPoint);
			if (net.Message.Length < 4)
			{
				return null;
			}
			net.Reader.Reset();
			int num = common.BigLong(net.Reader.ReadLong());
			if (num == -1)
			{
				return null;
			}
			if ((num & -65536) != -2147483648)
			{
				return null;
			}
			if ((num & 65535) != net.Message.Length)
			{
				return null;
			}
			int num2 = net.Reader.ReadByte();
			if (num2 == 2)
			{
				if (net.Reader.ReadString() != "QUAKE")
				{
					return null;
				}
				net.Message.Clear();
				net.Message.WriteLong(0);
				net.Message.WriteByte(131);
				EndPoint localEndPoint = socket.LocalEndPoint;
				net.Message.WriteString(localEndPoint.ToString());
				net.Message.WriteString(net.HostName);
				net.Message.WriteString(server.sv.name);
				net.Message.WriteByte(net.ActiveConnections);
				net.Message.WriteByte(server.svs.maxclients);
				net.Message.WriteByte(3);
				common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
				net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, endPoint);
				net.Message.Clear();
				return null;
			}
			else if (num2 == 3)
			{
				int num3 = net.Reader.ReadByte();
				int num4 = -1;
				client_t client_t = null;
				int i;
				for (i = 0; i < server.svs.maxclients; i++)
				{
					client_t = server.svs.clients[i];
					if (client_t.active)
					{
						num4++;
						if (num4 == num3)
						{
							break;
						}
					}
				}
				if (i == server.svs.maxclients)
				{
					return null;
				}
				net.Message.Clear();
				net.Message.WriteLong(0);
				net.Message.WriteByte(132);
				net.Message.WriteByte(num3);
				net.Message.WriteString(client_t.name);
				net.Message.WriteLong(client_t.colors);
				net.Message.WriteLong((int)client_t.edict.v.frags);
				net.Message.WriteLong((int)(net.Time - client_t.netconnection.connecttime));
				net.Message.WriteString(client_t.netconnection.address);
				common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
				net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, endPoint);
				net.Message.Clear();
				return null;
			}
			else
			{
				if (num2 == 4)
				{
					string text = net.Reader.ReadString();
					cvar cvar;
					if (!string.IsNullOrEmpty(text))
					{
						cvar = cvar.Find(text);
						if (cvar == null)
						{
							return null;
						}
						cvar = cvar.Next;
					}
					else
					{
						cvar = cvar.First;
					}
					while (cvar != null && !cvar.IsServer)
					{
						cvar = cvar.Next;
					}
					net.Message.Clear();
					net.Message.WriteLong(0);
					net.Message.WriteByte(133);
					if (cvar != null)
					{
						net.Message.WriteString(cvar.Name);
						net.Message.WriteString(cvar.String);
					}
					common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
					net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, endPoint);
					net.Message.Clear();
					return null;
				}
				if (num2 != 1)
				{
					return null;
				}
				if (net.Reader.ReadString() != "QUAKE")
				{
					return null;
				}
				if (net.Reader.ReadByte() != 3)
				{
					net.Message.Clear();
					net.Message.WriteLong(0);
					net.Message.WriteByte(130);
					net.Message.WriteString("Incompatible version.\n");
					common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
					net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, endPoint);
					net.Message.Clear();
					return null;
				}
				foreach (qsocket_t qsocket_t in net.ActiveSockets)
				{
					if (qsocket_t.driver == net.DriverLevel)
					{
						int num5 = net.LanDriver.AddrCompare(endPoint, qsocket_t.addr);
						if (num5 >= 0)
						{
							if (num5 == 0 && net.Time - qsocket_t.connecttime < 2.0)
							{
								net.Message.Clear();
								net.Message.WriteLong(0);
								net.Message.WriteByte(129);
								EndPoint localEndPoint2 = qsocket_t.socket.LocalEndPoint;
								net.Message.WriteLong(net.LanDriver.GetSocketPort(localEndPoint2));
								common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
								net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, endPoint);
								net.Message.Clear();
								return null;
							}
							net.Close(qsocket_t);
							return null;
						}
					}
				}
				qsocket_t qsocket_t2 = net.NewSocket();
				if (qsocket_t2 == null)
				{
					net.Message.Clear();
					net.Message.WriteLong(0);
					net.Message.WriteByte(130);
					net.Message.WriteString("Server is full.\n");
					common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
					net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, endPoint);
					net.Message.Clear();
					return null;
				}
				Socket socket2 = net.LanDriver.OpenSocket(0);
				if (socket2 == null)
				{
					net.FreeSocket(qsocket_t2);
					return null;
				}
				if (net.LanDriver.Connect(socket2, endPoint) == -1)
				{
					net.LanDriver.CloseSocket(socket2);
					net.FreeSocket(qsocket_t2);
					return null;
				}
				qsocket_t2.socket = socket2;
				qsocket_t2.landriver = net.LanDriverLevel;
				qsocket_t2.addr = endPoint;
				qsocket_t2.address = endPoint.ToString();
				net.Message.Clear();
				net.Message.WriteLong(0);
				net.Message.WriteByte(129);
				EndPoint localEndPoint3 = socket2.LocalEndPoint;
				net.Message.WriteLong(net.LanDriver.GetSocketPort(localEndPoint3));
				common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
				net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, endPoint);
				net.Message.Clear();
				return qsocket_t2;
			}
		}

		public int GetMessage(qsocket_t sock)
		{
			if (!sock.canSend && net.Time - sock.lastSendTime > 1.0)
			{
				this.ReSendMessage(sock);
			}
			int result = 0;
			EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
			int num;
			uint num3;
			for (;;)
			{
				num = sock.Read(this._PacketBuffer, 1032, ref endPoint);
				if (num == 0)
				{
					goto IL_337;
				}
				if (num == -1)
				{
					break;
				}
				if (sock.LanDriver.AddrCompare(endPoint, sock.addr) == 0)
				{
					if (num < 8)
					{
						this.shortPacketCount++;
					}
					else
					{
						net_datagram.PacketHeader packetHeader = sys.BytesToStructure<net_datagram.PacketHeader>(this._PacketBuffer, 0);
						num = common.BigLong(packetHeader.length);
						int num2 = num & -65536;
						num &= 65535;
						if ((num2 & -2147483648) == 0)
						{
							num3 = (uint)common.BigLong(packetHeader.sequence);
							this.packetsReceived++;
							if ((num2 & 1048576) != 0)
							{
								goto Block_8;
							}
							if ((num2 & 131072) != 0)
							{
								if (num3 != sock.sendSequence - 1u)
								{
									Con.DPrint("Stale ACK received\n", Array.Empty<object>());
								}
								else if (num3 == sock.ackSequence)
								{
									sock.ackSequence += 1u;
									if (sock.ackSequence != sock.sendSequence)
									{
										Con.DPrint("ack sequencing error\n", Array.Empty<object>());
									}
									sock.sendMessageLength -= 1024;
									if (sock.sendMessageLength > 0)
									{
										Buffer.BlockCopy(sock.sendMessage, 1024, sock.sendMessage, 0, sock.sendMessageLength);
										sock.sendNext = true;
									}
									else
									{
										sock.sendMessageLength = 0;
										sock.canSend = true;
									}
								}
								else
								{
									Con.DPrint("Duplicate ACK received\n", Array.Empty<object>());
								}
							}
							else if ((num2 & 65536) != 0)
							{
								packetHeader.length = common.BigLong(131080);
								packetHeader.sequence = common.BigLong((int)num3);
								sys.StructureToBytes<net_datagram.PacketHeader>(ref packetHeader, this._PacketBuffer, 0);
								sock.Write(this._PacketBuffer, 8, endPoint);
								if (num3 != sock.receiveSequence)
								{
									this.receivedDuplicateCount++;
								}
								else
								{
									sock.receiveSequence += 1u;
									num -= 8;
									if ((num2 & 524288) != 0)
									{
										goto Block_18;
									}
									Buffer.BlockCopy(this._PacketBuffer, net_datagram.PacketHeader.SizeInBytes, sock.receiveMessage, sock.receiveMessageLength, num);
									sock.receiveMessageLength += num;
								}
							}
						}
					}
				}
			}
			Con.Print("Read error\n", Array.Empty<object>());
			return -1;
			Block_8:
			if (num3 < sock.unreliableReceiveSequence)
			{
				Con.DPrint("Got a stale datagram\n", Array.Empty<object>());
				result = 0;
				goto IL_337;
			}
			if (num3 != sock.unreliableReceiveSequence)
			{
				int num4 = (int)(num3 - sock.unreliableReceiveSequence);
				this.droppedDatagrams += num4;
				Con.DPrint("Dropped {0} datagram(s)\n", new object[]
				{
					num4
				});
			}
			sock.unreliableReceiveSequence = num3 + 1u;
			num -= 8;
			net.Message.FillFrom(this._PacketBuffer, net_datagram.PacketHeader.SizeInBytes, num);
			result = 2;
			goto IL_337;
			Block_18:
			net.Message.Clear();
			net.Message.FillFrom(sock.receiveMessage, 0, sock.receiveMessageLength);
			net.Message.AppendFrom(this._PacketBuffer, net_datagram.PacketHeader.SizeInBytes, num);
			sock.receiveMessageLength = 0;
			result = 1;
			IL_337:
			if (sock.sendNext)
			{
				this.SendMessageNext(sock);
			}
			return result;
		}

		public int SendMessage(qsocket_t sock, MsgWriter data)
		{
			Buffer.BlockCopy(data.Data, 0, sock.sendMessage, 0, data.Length);
			sock.sendMessageLength = data.Length;
			int num;
			int num2;
			if (data.Length <= 1024)
			{
				num = data.Length;
				num2 = 524288;
			}
			else
			{
				num = 1024;
				num2 = 0;
			}
			int num3 = 8 + num;
			net_datagram.PacketHeader packetHeader;
			packetHeader.length = common.BigLong(num3 | 65536 | num2);
			uint sendSequence = sock.sendSequence;
			sock.sendSequence = sendSequence + 1u;
			packetHeader.sequence = common.BigLong((int)sendSequence);
			sys.StructureToBytes<net_datagram.PacketHeader>(ref packetHeader, this._PacketBuffer, 0);
			Buffer.BlockCopy(data.Data, 0, this._PacketBuffer, net_datagram.PacketHeader.SizeInBytes, num);
			sock.canSend = false;
			if (sock.Write(this._PacketBuffer, num3, sock.addr) == -1)
			{
				return -1;
			}
			sock.lastSendTime = net.Time;
			this.packetsSent++;
			return 1;
		}

		public int SendUnreliableMessage(qsocket_t sock, MsgWriter data)
		{
			int num = 8 + data.Length;
			net_datagram.PacketHeader packetHeader;
			packetHeader.length = common.BigLong(num | 1048576);
			uint unreliableSendSequence = sock.unreliableSendSequence;
			sock.unreliableSendSequence = unreliableSendSequence + 1u;
			packetHeader.sequence = common.BigLong((int)unreliableSendSequence);
			sys.StructureToBytes<net_datagram.PacketHeader>(ref packetHeader, this._PacketBuffer, 0);
			Buffer.BlockCopy(data.Data, 0, this._PacketBuffer, net_datagram.PacketHeader.SizeInBytes, data.Length);
			if (sock.Write(this._PacketBuffer, num, sock.addr) == -1)
			{
				return -1;
			}
			this.packetsSent++;
			return 1;
		}

		public bool CanSendMessage(qsocket_t sock)
		{
			if (sock.sendNext)
			{
				this.SendMessageNext(sock);
			}
			return sock.canSend;
		}

		public bool CanSendUnreliableMessage(qsocket_t sock)
		{
			return true;
		}

		public void Close(qsocket_t sock)
		{
			sock.LanDriver.CloseSocket(sock.socket);
		}

		public void Shutdown()
		{
			foreach (INetLanDriver netLanDriver in net.LanDrivers)
			{
				if (netLanDriver.IsInitialized)
				{
					netLanDriver.Shutdown();
				}
			}
			this._IsInitialized = false;
		}

		private void InternalSearchForHosts(bool xmit)
		{
			EndPoint localEndPoint = net.LanDriver.ControlSocket.LocalEndPoint;
			if (xmit)
			{
				net.Message.Clear();
				net.Message.WriteLong(0);
				net.Message.WriteByte(2);
				net.Message.WriteString("QUAKE");
				net.Message.WriteByte(3);
				common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
				net.LanDriver.Broadcast(net.LanDriver.ControlSocket, net.Message.Data, net.Message.Length);
				net.Message.Clear();
			}
			EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
			for (;;)
			{
				net.Message.FillFrom(net.LanDriver.ControlSocket, ref endPoint);
				if (net.Message.IsEmpty)
				{
					break;
				}
				if (net.Message.Length >= 4 && net.LanDriver.AddrCompare(endPoint, localEndPoint) < 0 && net.HostCacheCount != 8)
				{
					net.Reader.Reset();
					int num = common.BigLong(net.Reader.ReadLong());
					if (num != -1 && (num & -65536) == -2147483648 && (num & 65535) == net.Message.Length && net.Reader.ReadByte() == 131)
					{
						EndPoint endPoint2 = endPoint;
						endPoint = net.LanDriver.GetAddrFromName(net.Reader.ReadString());
						int num2 = 0;
						while (num2 < net.HostCacheCount && net.LanDriver.AddrCompare(endPoint, net.HostCache[num2].addr) != 0)
						{
							num2++;
						}
						if (num2 >= net.HostCacheCount)
						{
							net.HostCacheCount++;
							hostcache_t hostcache_t = net.HostCache[num2];
							hostcache_t.name = net.Reader.ReadString();
							hostcache_t.map = net.Reader.ReadString();
							hostcache_t.users = net.Reader.ReadByte();
							hostcache_t.maxusers = net.Reader.ReadByte();
							if (net.Reader.ReadByte() != 3)
							{
								hostcache_t.cname = hostcache_t.name;
								hostcache_t.name = "*" + hostcache_t.name;
							}
							string[] array = endPoint.ToString().Split(new char[]
							{
								':'
							});
							IPAddress address;
							IPAddress.TryParse(array[0].ToString(), out address);
							int port;
							int.TryParse(array[1].ToString(), out port);
							hostcache_t.addr = new IPEndPoint(address, port);
							hostcache_t.driver = net.DriverLevel;
							hostcache_t.ldriver = net.LanDriverLevel;
							hostcache_t.cname = endPoint2.ToString();
							for (int i = 0; i < net.HostCacheCount; i++)
							{
								if (i != num2)
								{
									hostcache_t hostcache_t2 = net.HostCache[i];
									if (hostcache_t.name == hostcache_t2.name)
									{
										i = hostcache_t.name.Length;
										if (i < 15 && hostcache_t.name[i - 1] > '8')
										{
											hostcache_t.name = hostcache_t.name.Substring(0, i) + "0";
										}
										else
										{
											hostcache_t.name = hostcache_t.name.Substring(0, i - 1) + (hostcache_t.name[i - 1] + '\u0001').ToString();
										}
										i = 0;
									}
								}
							}
						}
					}
				}
			}
		}

		private qsocket_t InternalConnect(string host)
		{
			EndPoint addrFromName = net.LanDriver.GetAddrFromName(host);
			if (addrFromName == null)
			{
				return null;
			}
			Socket socket = net.LanDriver.OpenSocket(0);
			if (socket == null)
			{
				return null;
			}
			qsocket_t qsocket_t = net.NewSocket();
			if (qsocket_t != null)
			{
				qsocket_t.socket = socket;
				qsocket_t.landriver = net.LanDriverLevel;
				if (net.LanDriver.Connect(socket, addrFromName) != -1)
				{
					Con.Print("Connecting to " + addrFromName + "\n", Array.Empty<object>());
					Con.Print("trying...\n", Array.Empty<object>());
					Scr.UpdateScreen();
					double num = net.Time;
					int num2 = 0;
					for (int i = 0; i < 3; i++)
					{
						net.Message.Clear();
						net.Message.WriteLong(0);
						net.Message.WriteByte(1);
						net.Message.WriteString("QUAKE");
						net.Message.WriteByte(3);
						common.WriteInt(net.Message.Data, 0, common.BigLong(int.MinValue | (net.Message.Length & 65535)));
						net.LanDriver.Write(socket, net.Message.Data, net.Message.Length, addrFromName);
						net.Message.Clear();
						EndPoint addr = new IPEndPoint(IPAddress.Any, 0);
						do
						{
							num2 = net.Message.FillFrom(socket, ref addr);
							if (num2 > 0)
							{
								if (qsocket_t.LanDriver.AddrCompare(addr, addrFromName) != 0)
								{
									num2 = 0;
								}
								else if (num2 < 4)
								{
									num2 = 0;
								}
								else
								{
									net.Reader.Reset();
									int num3 = common.BigLong(net.Reader.ReadLong());
									if (num3 == -1)
									{
										num2 = 0;
									}
									else if ((num3 & -65536) != -2147483648)
									{
										num2 = 0;
									}
									else if ((num3 & 65535) != num2)
									{
										num2 = 0;
									}
								}
							}
						}
						while (num2 == 0 && net.SetNetTime() - num < 2.5);
						if (num2 > 0)
						{
							break;
						}
						Con.Print("still trying...\n", Array.Empty<object>());
						Scr.UpdateScreen();
						num = net.SetNetTime();
					}
					string text = string.Empty;
					if (num2 == 0)
					{
						text = "No Response";
						Con.Print("{0}\n", new object[]
						{
							text
						});
						menu.ReturnReason = text;
					}
					else if (num2 == -1)
					{
						text = "Network Error";
						Con.Print("{0}\n", new object[]
						{
							text
						});
						menu.ReturnReason = text;
					}
					else
					{
						num2 = net.Reader.ReadByte();
						if (num2 == 130)
						{
							text = net.Reader.ReadString();
							Con.Print(text, Array.Empty<object>());
							menu.ReturnReason = text;
						}
						else if (num2 == 129)
						{
							IPEndPoint ipendPoint = (IPEndPoint)addrFromName;
							qsocket_t.addr = new IPEndPoint(ipendPoint.Address, ipendPoint.Port);
							net.LanDriver.SetSocketPort(qsocket_t.addr, net.Reader.ReadLong());
							qsocket_t.address = net.LanDriver.GetNameFromAddr(addrFromName);
							Con.Print("Connection accepted\n", Array.Empty<object>());
							qsocket_t.lastMessageTime = net.SetNetTime();
							if (net.LanDriver.Connect(socket, qsocket_t.addr) != -1)
							{
								menu.ReturnOnError = false;
								return qsocket_t;
							}
							text = "Connect to Game failed";
							Con.Print("{0}\n", new object[]
							{
								text
							});
							menu.ReturnReason = text;
						}
						else
						{
							text = "Bad Response";
							Con.Print("{0}\n", new object[]
							{
								text
							});
							menu.ReturnReason = text;
						}
					}
				}
				net.FreeSocket(qsocket_t);
			}
			net.LanDriver.CloseSocket(socket);
			if (menu.ReturnOnError && menu.ReturnMenu != null)
			{
				menu.ReturnMenu.Show();
				menu.ReturnOnError = false;
			}
			return null;
		}

		private int SendMessageNext(qsocket_t sock)
		{
			int num;
			int num2;
			if (sock.sendMessageLength <= 1024)
			{
				num = sock.sendMessageLength;
				num2 = 524288;
			}
			else
			{
				num = 1024;
				num2 = 0;
			}
			int num3 = 8 + num;
			net_datagram.PacketHeader packetHeader;
			packetHeader.length = common.BigLong(num3 | (65536 | num2));
			uint sendSequence = sock.sendSequence;
			sock.sendSequence = sendSequence + 1u;
			packetHeader.sequence = common.BigLong((int)sendSequence);
			sys.StructureToBytes<net_datagram.PacketHeader>(ref packetHeader, this._PacketBuffer, 0);
			Buffer.BlockCopy(sock.sendMessage, 0, this._PacketBuffer, net_datagram.PacketHeader.SizeInBytes, num);
			sock.sendNext = false;
			if (sock.Write(this._PacketBuffer, num3, sock.addr) == -1)
			{
				return -1;
			}
			sock.lastSendTime = net.Time;
			this.packetsSent++;
			return 1;
		}

		private int ReSendMessage(qsocket_t sock)
		{
			int num;
			int num2;
			if (sock.sendMessageLength <= 1024)
			{
				num = sock.sendMessageLength;
				num2 = 524288;
			}
			else
			{
				num = 1024;
				num2 = 0;
			}
			int num3 = 8 + num;
			net_datagram.PacketHeader packetHeader;
			packetHeader.length = common.BigLong(num3 | (65536 | num2));
			packetHeader.sequence = common.BigLong((int)(sock.sendSequence - 1u));
			sys.StructureToBytes<net_datagram.PacketHeader>(ref packetHeader, this._PacketBuffer, 0);
			Buffer.BlockCopy(sock.sendMessage, 0, this._PacketBuffer, net_datagram.PacketHeader.SizeInBytes, num);
			sock.sendNext = false;
			if (sock.Write(this._PacketBuffer, num3, sock.addr) == -1)
			{
				return -1;
			}
			sock.lastSendTime = net.Time;
			this.packetsReSent++;
			return 1;
		}

		private static net_datagram _Singletone = new net_datagram();

		private int _DriverLevel;

		private bool _IsInitialized;

		private byte[] _PacketBuffer;

		private int packetsSent;

		private int packetsReSent;

		private int packetsReceived;

		private int receivedDuplicateCount;

		private int shortPacketCount;

		private int droppedDatagrams;

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		private struct PacketHeader
		{
			public int length;

			public int sequence;

			public static int SizeInBytes = Marshal.SizeOf(typeof(net_datagram.PacketHeader));
		}
	}
}
