protected override async void ReadAsync() { int milliseconds = 0; int i = 0; while (true) { milliseconds = 0; try { while (true) { for (i = i; i < Players.Count; i++) { // TODO: Cache these objects to save on garbage collection DataReader reader = new DataReader(((StreamSocket)Players[i].SocketEndpoint).InputStream); if (reader.UnconsumedBufferLength > 0) { byte[] bytes = null; uint messageSize = await reader.LoadAsync(sizeof(uint)); if (messageSize != sizeof(uint)) { Disconnect(); // socket was closed return; } bytes = new byte[messageSize]; reader.ReadBytes(bytes); messageSize = BitConverter.ToUInt32(bytes, 0); await reader.LoadAsync(messageSize); bytes = new byte[messageSize]; // TODO: This may read the first 4 bytes again for the size, make sure it doesn't reader.ReadBytes(bytes); readBuffer.Clone(bytes); NetworkingStream stream = new NetworkingStream().Consume(this, Players[i], readBuffer); DataRead(Players[i], stream); // Write what was read to all the clients Write(new NetworkingStream(stream.ProtocolType).Prepare(this, stream.identifierType, stream.NetworkedBehavior.NetworkedId, stream.Bytes)); } } i = 0; } } catch (Exception e) { ClientDisconnected(i); //Networking.Error(e.Message); } await Task.Delay(ThreadSpeed); } }
/// <summary> /// This method is used on the client to attempt to connect to the server through the NAT hole punch server /// </summary> /// <param name="socket">This is the socket that is being used for the communication with the server</param> /// <param name="port">This is the port number that this client is bound to</param> /// <param name="requestHost">This is the host address of the server that this client is trying to connect to</param> /// <param name="requestPort">This is the host port of the server that this client is trying to connect to</param> /// <param name="proxyHost">This is the NAT hole punch server host address</param> /// <param name="proxyPort">This is the NAT hole punch server port number</param> /// <returns></returns> public static bool RequestNat(NetWorker socket, ushort port, string requestHost, ushort requestPort, string proxyHost, ushort proxyPort = PORT) { #if !NetFX_CORE && !UNITY_WEBGL IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(proxyHost), proxyPort); List <byte> data = new List <byte>(new byte[] { 4, 4, 2 }); data.AddRange(BitConverter.GetBytes(port)); data.AddRange(BitConverter.GetBytes(requestPort)); data.AddRange(Encryptor.Encoding.GetBytes(requestHost)); try { int tryCount = 10; while (((CrossPlatformUDP)socket).ReadClient.Available == 0) { ((CrossPlatformUDP)socket).ReadClient.Send(data.ToArray(), data.Count, endpoint); Thread.Sleep(500); if (--tryCount <= 0) { throw new Exception("Unable to contact proxy host"); } } string endpointStr = ""; BMSByte otherBytes = ((CrossPlatformUDP)socket).ReadClient.Receive(ref endpoint, ref endpointStr); BMSByte found = new BMSByte(); found.Clone(otherBytes); if (found.byteArr[2] == 0) { return(false); } ushort targetPort = System.BitConverter.ToUInt16(found.byteArr, 3); string targetHost = Encryptor.Encoding.GetString(found.byteArr, 5, found.byteArr.Length - 6); IPEndPoint targetEndpoint = new IPEndPoint(IPAddress.Parse(targetHost), targetPort); tryCount = 20; while (((CrossPlatformUDP)socket).ReadClient.Available == 0) { ((CrossPlatformUDP)socket).ReadClient.Send(new byte[] { 4, 4, 0 }, 3, targetEndpoint); Thread.Sleep(500); if (--tryCount <= 0) { throw new Exception("Unable to contact proxy host"); } } #if UNITY_EDITOR Debug.Log("Connected via NAT traversal"); #endif } #if UNITY_EDITOR catch (Exception e) { Debug.LogException(e); } #else catch { } #endif #endif return(true); }