private void SendMerged() { if (_mergeCount == 0) { return; } int bytesSent; if (_mergeCount > 1) { NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount); bytesSent = NetManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, EndPoint); } else { //Send without length information and merging bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, EndPoint); } #if STATS_ENABLED Statistics.PacketsSent++; Statistics.BytesSent += (ulong)bytesSent; #endif _mergePos = 0; _mergeCount = 0; }
//We got punch and can connect private void OnNatPunch(NatPunchPacket req, IPEndPoint senderEndPoint) { //Read info NetDebug.Write(NetLogLevel.Trace, "[NAT] punch received from {0} - additional info: {1}", senderEndPoint, req.Token); //Release punch success to client; enabling him to Connect() to Sender if token is ok if (UnsyncedEvents) { _natPunchListener.OnNatIntroductionSuccess( senderEndPoint, req.IsExternal ? NatAddressType.External : NatAddressType.Internal, req.Token ); } else { _successEvents.Enqueue(new SuccessEventData { TargetEndPoint = senderEndPoint, Type = req.IsExternal ? NatAddressType.External : NatAddressType.Internal, Token = req.Token }); } }
private void ReceiveLogic(object state) { var socket = (Socket)state; EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0); var receiveBuffer = new byte[NetConstants.MaxPacketSize]; while (IsActive()) { int result; //Reading data try { if (socket.Available == 0 && !socket.Poll(ReceivePollingTime, SelectMode.SelectRead)) { continue; } result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref bufferEndPoint); } catch (SocketException ex) { switch (ex.SocketErrorCode) { #if UNITY_IOS && !UNITY_EDITOR case SocketError.NotConnected: #endif case SocketError.Interrupted: case SocketError.NotSocket: return; case SocketError.ConnectionReset: case SocketError.MessageSize: case SocketError.TimedOut: NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); break; default: NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint); break; } continue; } catch (ObjectDisposedException) { return; } //All ok! NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result); _listener.OnMessageReceived(receiveBuffer, result, 0, (IPEndPoint)bufferEndPoint); } }
private bool ProcessError(SocketException ex, EndPoint bufferEndPoint) { switch (ex.SocketErrorCode) { #if UNITY_IOS && !UNITY_EDITOR case SocketError.NotConnected: #endif case SocketError.Interrupted: case SocketError.NotSocket: return(true); case SocketError.ConnectionReset: case SocketError.MessageSize: case SocketError.TimedOut: NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); break; default: NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint); break; } return(false); }
private bool ManualReceive(Socket socket, EndPoint bufferEndPoint, byte[] receiveBuffer) { int result; //Reading data try { int available = socket.Available; if (available == 0) { return(false); } while (available > 0) { result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref bufferEndPoint); NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result); _listener.OnMessageReceived(receiveBuffer, result, 0, (IPEndPoint)bufferEndPoint); available -= result; } } catch (SocketException ex) { return(ProcessError(ex, bufferEndPoint)); } catch (ObjectDisposedException) { return(true); } return(false); }
private void SendMerged() { if (_mergeCount == 0) { return; } int bytesSent; if (_mergeCount > 1) { NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount); bytesSent = NetManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, EndPoint); } else { //Send without length information and merging bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, EndPoint); } if (NetManager.EnableStatistics) { Statistics.IncrementPacketsSent(); Statistics.AddBytesSent(bytesSent); } _mergePos = 0; _mergeCount = 0; }
private bool ManualReceive(Socket socket, EndPoint bufferEndPoint, byte[] receiveBuffer) { int result; //Reading data try { int available = socket.Available; if (available == 0) { return(false); } while (available > 0) { var packet = _listener.NetPacketPool.GetPacket(NetConstants.MaxPacketSize); packet.Size = socket.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, ref bufferEndPoint); NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result); _listener.OnMessageReceived(packet, 0, (IPEndPoint)bufferEndPoint); available -= packet.Size; } } catch (SocketException ex) { return(ProcessError(ex, bufferEndPoint)); } catch (ObjectDisposedException) { return(true); } return(false); }
internal void SendUserData(NetPacket packet) { packet.ConnectionNumber = _connectNum; int mergedPacketSize = NetConstants.HeaderSize + packet.Size + 2; const int sizeTreshold = 20; if (mergedPacketSize + sizeTreshold >= _mtu) { NetDebug.Write(NetLogLevel.Trace, "[P]SendingPacket: " + packet.Property); int bytesSent = NetManager.SendRaw(packet, EndPoint); #if STATS_ENABLED Statistics.PacketsSent++; Statistics.BytesSent += (ulong)bytesSent; #endif return; } if (_mergePos + mergedPacketSize > _mtu) { SendMerged(); } FastBitConverter.GetBytes(_mergeData.RawData, _mergePos + NetConstants.HeaderSize, (ushort)packet.Size); Buffer.BlockCopy(packet.RawData, 0, _mergeData.RawData, _mergePos + NetConstants.HeaderSize + 2, packet.Size); _mergePos += packet.Size + 2; _mergeCount++; //DebugWriteForce("Merged: " + _mergePos + "/" + (_mtu - 2) + ", count: " + _mergeCount); }
private void ReceiveLogic(object state) { Socket socket = (Socket)state; EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0); byte[] receiveBuffer = new byte[NetConstants.MaxPacketSize]; //Console.WriteLine("Socket family: " + socket.AddressFamily); //Console.WriteLine("IPEndpoint: " + bufferEndPoint); // Create socket event args var e = new SocketAsyncEventArgs(); e.Completed += (sender, args) => OnReceive(socket, args, receiveBuffer, bufferEndPoint); e.RemoteEndPoint = bufferEndPoint; e.SetBuffer(receiveBuffer, 0, NetConstants.MaxPacketSize); // Read initial data bool willRaiseEvent = false; try { willRaiseEvent = _udpSocketv4.ReceiveFromAsync(e); } // According to msdn this call CAN raise an exception, so let's catch it just in case catch (SocketException ex) { switch (ex.SocketErrorCode) { case SocketError.Interrupted: return; case SocketError.ConnectionReset: case SocketError.MessageSize: case SocketError.TimedOut: NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); break; default: NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)e.RemoteEndPoint); break; } } // If error, call OnReceive if (!willRaiseEvent) { OnReceive(socket, e, receiveBuffer, bufferEndPoint); } }
//"Accept" incoming constructor internal void Accept(long connectId, byte connectNum) { _connectTime = connectId; _connectionState = ConnectionState.Connected; ConnectionNum = connectNum; //Make initial packet _connectAcceptPacket = NetConnectAcceptPacket.Make(_connectTime, connectNum, false); //Send NetManager.SendRaw(_connectAcceptPacket, EndPoint); NetDebug.Write(NetLogLevel.Trace, "[CC] ConnectId: {0}", _connectTime); }
//"Accept" incoming constructor internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, long connectId, byte connectNum) : this(netManager, remoteEndPoint, id) { _connectTime = connectId; _connectionState = ConnectionState.Connected; ConnectionNum = connectNum; //Make initial packet _connectAcceptPacket = NetConnectAcceptPacket.Make(_connectTime, connectNum, false); //Send NetManager.SendRaw(_connectAcceptPacket, EndPoint); NetDebug.Write(NetLogLevel.Trace, "[CC] ConnectId: {0}", _connectTime); }
protected override bool SendNextPackets() { if (_mustSendAcks) { _mustSendAcks = false; NetDebug.Write("[RR]SendAcks"); lock (_outgoingAcks) Peer.SendUserData(_outgoingAcks); } long currentTime = DateTime.UtcNow.Ticks; bool hasPendingPackets = false; lock (_pendingPackets) { //get packets from queue while (!OutgoingQueue.IsEmpty) { int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart); if (relate >= _windowSize) { break; } if (!OutgoingQueue.TryDequeue(out var netPacket)) { break; } netPacket.Sequence = (ushort)_localSeqence; netPacket.ChannelId = _id; _pendingPackets[_localSeqence % _windowSize].Init(netPacket); _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence; } //send for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence) { // Please note: TrySend is invoked on a mutable struct, it's important to not extract it into a variable here bool hasPacket; _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer, out hasPacket); if (hasPacket) { hasPendingPackets = true; } } } return(hasPendingPackets || _mustSendAcks || OutgoingQueue.Count > 0); }
//"Connect to" constructor internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, byte connectNum, NetDataWriter connectData) : this(netManager, remoteEndPoint, id) { _connectTime = DateTime.UtcNow.Ticks; _connectionState = ConnectionState.Outgoing; ConnectionNum = connectNum; //Make initial packet _connectRequestPacket = NetConnectRequestPacket.Make(connectData, _connectTime); _connectRequestPacket.ConnectionNumber = connectNum; //Send request NetManager.SendRaw(_connectRequestPacket, EndPoint); NetDebug.Write(NetLogLevel.Trace, "[CC] ConnectId: {0}, ConnectNum: {1}", _connectTime, connectNum); }
private void ReceiveLogicAsync(IAsyncResult ar) { Socket _udpSocket = (Socket)ar.AsyncState; EndPoint bufferEndPoint = new IPEndPoint(_udpSocket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0); try { int result = _udpSocket.EndReceiveFrom(ar, ref bufferEndPoint); //clone receive array byte[] buffer = new byte[result]; Array.Copy(_receiveBufferv4, buffer, result); //call BeginReceiveFrom before _listener.OnMessageReceived _udpSocket.BeginReceiveFrom(_receiveBufferv4, 0, _receiveBufferv4.Length, SocketFlags.None, ref bufferEndPoint, ReceiveLogicAsync, _udpSocket); _listener.OnMessageReceived(buffer, result, 0, (IPEndPoint)bufferEndPoint); } catch (SocketException ex) { switch (ex.SocketErrorCode) { case SocketError.Interrupted: return; case SocketError.ConnectionReset: case SocketError.MessageSize: case SocketError.TimedOut: NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); break; case SocketError.NotConnected: NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); break; default: NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint); break; } } catch (ObjectDisposedException) { return; } }
private void ProcessMtuPacket(NetPacket packet) { //header + int if (packet.Size < NetConstants.PossibleMtu[0]) { return; } //first stage check (mtu check and mtu ok) int receivedMtu = BitConverter.ToInt32(packet.RawData, 1); int endMtuCheck = BitConverter.ToInt32(packet.RawData, packet.Size - 4); if (receivedMtu != packet.Size || receivedMtu != endMtuCheck || receivedMtu > NetConstants.MaxPacketSize) { NetDebug.WriteError("[MTU] Broken packet. RMTU {0}, EMTU {1}, PSIZE {2}", receivedMtu, endMtuCheck, packet.Size); return; } if (packet.Property == PacketProperty.MtuCheck) { _mtuCheckAttempts = 0; NetDebug.Write("[MTU] check. send back: " + receivedMtu); packet.Property = PacketProperty.MtuOk; NetManager.SendRawAndRecycle(packet, EndPoint); } else if (receivedMtu > _mtu && !_finishMtu) //MtuOk { //invalid packet if (receivedMtu != NetConstants.PossibleMtu[_mtuIdx + 1]) { return; } lock (_mtuMutex) { _mtuIdx++; _mtu = receivedMtu; } //if maxed - finish. if (_mtuIdx == NetConstants.PossibleMtu.Length - 1) { _finishMtu = true; } NetDebug.Write("[MTU] ok. Increase to: " + _mtu); } }
internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) { lock (_shutdownLock) { //trying to shutdown already disconnected if (_connectionState == ConnectionState.Disconnected || _connectionState == ConnectionState.ShutdownRequested) { return(ShutdownResult.None); } var result = _connectionState == ConnectionState.Connected ? ShutdownResult.WasConnected : ShutdownResult.Success; //don't send anything if (force) { _connectionState = ConnectionState.Disconnected; return(result); } //reset time for reconnect protection Interlocked.Exchange(ref _timeSinceLastPacket, 0); //send shutdown packet _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length) { ConnectionNumber = _connectNum }; FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime); if (_shutdownPacket.Size >= _mtu) { //Drop additional data NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!"); } else if (data != null && length > 0) { Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length); } _connectionState = ConnectionState.ShutdownRequested; NetDebug.Write("[Peer] Send disconnect"); NetManager.SendRaw(_shutdownPacket, EndPoint); return(result); } }
public override void SendNextPackets() { if (_mustSendAcks) { _mustSendAcks = false; NetDebug.Write("[RR]SendAcks"); lock (_outgoingAcks) { Peer.SendUserData(_outgoingAcks); } } var currentTime = DateTime.UtcNow.Ticks; lock (_pendingPackets) { //get packets from queue lock (OutgoingQueue) { while (OutgoingQueue.Count > 0) { var relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart); if (relate >= _windowSize) { break; } var netPacket = OutgoingQueue.Dequeue(); netPacket.Sequence = (ushort)_localSeqence; netPacket.ChannelId = _id; _pendingPackets[_localSeqence % _windowSize].Init(netPacket); _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence; } } //send for (var pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence) { _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer); } } }
public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint, ref SocketError errorCode) { if (!IsActive()) { return(0); } try { var socket = _udpSocketv4; if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support) { socket = _udpSocketv6; } //Console.WriteLine("{0}, {1}, {2}, {3}, {4}", data, offset, size, SocketFlags.None, remoteEndPoint); int result = socket.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint); NetDebug.Write(NetLogLevel.Trace, "[S]Send packet to {0}, result: {1}", remoteEndPoint, result); return(result); } catch (SocketException ex) { switch (ex.SocketErrorCode) { case SocketError.NoBufferSpaceAvailable: case SocketError.Interrupted: return(0); case SocketError.MessageSize: //do nothing break; default: NetDebug.WriteError("[S]" + ex); break; } errorCode = ex.SocketErrorCode; return(-1); } catch (Exception ex) { NetDebug.WriteError("[S]" + ex); return(-1); } }
public void TrySend(long currentTime, NetPeer peer) { if (_packet == null) { return; } if (_isSent) //check send time { double resendDelay = peer.ResendDelay * TimeSpan.TicksPerMillisecond; double packetHoldTime = currentTime - _timeStamp; if (packetHoldTime < resendDelay) { return; } NetDebug.Write("[RC]Resend: {0} > {1}", (int)packetHoldTime, resendDelay); } _timeStamp = currentTime; _isSent = true; peer.SendUserData(_packet); }
public override void SendNextPackets() { //check sending acks if (_mustSendAcks) { _mustSendAcks = false; NetDebug.Write("[RR]SendAcks"); Monitor.Enter(_outgoingAcks); Peer.SendUserData(_outgoingAcks); Monitor.Exit(_outgoingAcks); } long currentTime = DateTime.UtcNow.Ticks; Monitor.Enter(_pendingPackets); //get packets from queue Monitor.Enter(OutgoingQueue); while (OutgoingQueue.Count > 0) { int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart); if (relate < _windowSize) { var netPacket = OutgoingQueue.Dequeue(); netPacket.Sequence = (ushort)_localSeqence; netPacket.ChannelId = _id; _pendingPackets[_localSeqence % _windowSize].Init(netPacket); _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence; } else //Queue filled { break; } } Monitor.Exit(OutgoingQueue); //send for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence) { _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer); } Monitor.Exit(_pendingPackets); }
internal bool ProcessConnectAccept(NetConnectAcceptPacket packet) { if (_connectionState != ConnectionState.Outgoing) { return(false); } //check connection id if (packet.ConnectionId != _connectTime) { NetDebug.Write(NetLogLevel.Trace, "[NC] Invalid connectId: {0}", _connectTime); return(false); } //check connect num ConnectionNum = packet.ConnectionNumber; NetDebug.Write(NetLogLevel.Trace, "[NC] Received connection accept"); _timeSinceLastPacket = 0; _connectionState = ConnectionState.Connected; return(true); }
/// <summary> /// Flush all queued packets /// </summary> public void Flush() { if (_connectionState != ConnectionState.Connected) { return; } lock (_flushLock) { _reliableOrderedChannel.SendNextPackets(); _reliableUnorderedChannel.SendNextPackets(); _reliableSequencedChannel.SendNextPackets(); _sequencedChannel.SendNextPackets(); _unreliableChannel.SendNextPackets(); //If merging enabled if (_mergePos > 0) { if (_mergeCount > 1) { NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount); _netManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, _remoteEndPoint); #if STATS_ENABLED Statistics.PacketsSent++; Statistics.BytesSent += (ulong)(NetConstants.HeaderSize + _mergePos); #endif } else { //Send without length information and merging _netManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, _remoteEndPoint); #if STATS_ENABLED Statistics.PacketsSent++; Statistics.BytesSent += (ulong)(_mergePos - 2); #endif } _mergePos = 0; _mergeCount = 0; } } }
internal bool Shutdown(byte[] data, int start, int length, bool force) { lock (this) { //trying to shutdown already disconnected if (_connectionState == ConnectionState.Disconnected || _connectionState == ConnectionState.ShutdownRequested) { return(false); } //don't send anything if (force) { _connectionState = ConnectionState.Disconnected; return(true); } //reset time for reconnect protection _timeSinceLastPacket = 0; //send shutdown packet _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length); _shutdownPacket.ConnectionNumber = _connectNum; FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime); if (_shutdownPacket.Size >= _mtu) { //Drop additional data NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!"); } else if (data != null && length > 0) { Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length); } _connectionState = ConnectionState.ShutdownRequested; NetDebug.Write("[Peer] Send disconnect"); _netManager.SendRaw(_shutdownPacket, _remoteEndPoint); return(true); } }
private void ReceiveLogic(object state) { Socket socket = (Socket)state; EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0); byte[] receiveBuffer = new byte[NetConstants.MaxPacketSize]; while (IsActive()) { int result; //Reading data try { if (socket.Available == 0 && !socket.Poll(ReceivePollingTime, SelectMode.SelectRead)) { continue; } result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref bufferEndPoint); } catch (SocketException ex) { if (ProcessError(ex, bufferEndPoint)) { return; } continue; } catch (ObjectDisposedException) { return; } //All ok! NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result); _listener.OnMessageReceived(receiveBuffer, result, 0, (IPEndPoint)bufferEndPoint); } }
//We got introduce and must punch private void OnNatIntroductionResponse(NatIntroduceResponsePacket req) { NetDebug.Write(NetLogLevel.Trace, "[NAT] introduction received"); // send internal punch var punchPacket = new NatPunchPacket { Token = req.Token }; Send(punchPacket, req.Internal); NetDebug.Write(NetLogLevel.Trace, "[NAT] internal punch sent to " + req.Internal); // hack for some routers _socket.Ttl = 2; _socket.SendRaw(new[] { (byte)PacketProperty.Empty }, 0, 1, req.External); // send external punch _socket.Ttl = NetConstants.SocketTTL; punchPacket.IsExternal = true; Send(punchPacket, req.External); NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + req.External); }
internal void SendUserData(NetPacket packet) { packet.ConnectionNumber = _connectNum; //2 - merge byte + minimal packet size + datalen(ushort) if (_netManager.MergeEnabled && _mergePos + packet.Size + NetConstants.HeaderSize * 2 + 2 < _mtu) { FastBitConverter.GetBytes(_mergeData.RawData, _mergePos + NetConstants.HeaderSize, (ushort)packet.Size); Buffer.BlockCopy(packet.RawData, 0, _mergeData.RawData, _mergePos + NetConstants.HeaderSize + 2, packet.Size); _mergePos += packet.Size + 2; _mergeCount++; //DebugWriteForce("Merged: " + _mergePos + "/" + (_mtu - 2) + ", count: " + _mergeCount); return; } NetDebug.Write(NetLogLevel.Trace, "[P]SendingPacket: " + packet.Property); _netManager.SendRaw(packet, _remoteEndPoint); #if STATS_ENABLED Statistics.PacketsSent++; Statistics.BytesSent += (ulong)packet.Size; #endif }
private void HandleNatIntroduction(NetDataReader dr) { // read intro byte hostByte = dr.GetByte(); IPEndPoint remoteInternal = dr.GetNetEndPoint(); IPEndPoint remoteExternal = dr.GetNetEndPoint(); string token = dr.GetString(MaxTokenLength); NetDebug.Write(NetLogLevel.Trace, "[NAT] introduction received; we are designated " + (hostByte == HostByte ? "host" : "client")); NetDataWriter writer = new NetDataWriter(); // send internal punch writer.Put((byte)PacketProperty.NatPunchMessage); writer.Put(hostByte); writer.Put(token); SocketError errorCode = 0; _socket.SendTo(writer.Data, 0, writer.Length, remoteInternal, ref errorCode); NetDebug.Write(NetLogLevel.Trace, "[NAT] internal punch sent to " + remoteInternal); // send external punch writer.Reset(); writer.Put((byte)PacketProperty.NatPunchMessage); writer.Put(hostByte); writer.Put(token); if (hostByte == HostByte) { _socket.Ttl = 2; _socket.SendTo(writer.Data, 0, writer.Length, remoteExternal, ref errorCode); _socket.Ttl = NetConstants.SocketTTL; } else { _socket.SendTo(writer.Data, 0, writer.Length, remoteExternal, ref errorCode); } NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + remoteExternal); }
private void HandleNatPunch(IPEndPoint senderEndPoint, NetDataReader dr) { byte fromHostByte = dr.GetByte(); if (fromHostByte != HostByte && fromHostByte != ClientByte) { //garbage return; } //Read info string additionalInfo = dr.GetString(MaxTokenLength); NetDebug.Write(NetLogLevel.Trace, "[NAT] punch received from {0} - additional info: {1}", senderEndPoint, additionalInfo); //Release punch success to client; enabling him to Connect() to msg.Sender if token is ok lock (_successEvents) { _successEvents.Enqueue(new SuccessEventData { TargetEndPoint = senderEndPoint, Token = additionalInfo }); } }
//Returns true if there is a pending packet inside public bool TrySend(DateTime currentTime, NetPeer peer) { if (_packet == null) { return(false); } if (_isSent) //check send time { TimeSpan resendDelay = peer.ResendDelay; TimeSpan packetHoldTime = currentTime - _timeStamp; if (packetHoldTime < resendDelay) { return(true); } NetDebug.Write("[RC]Resend: {0} > {1}", packetHoldTime, resendDelay); } _timeStamp = currentTime; _isSent = true; peer.SendUserData(_packet); return(true); }
private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress, IPv6Mode ipv6Mode) { //Setup socket socket.ReceiveTimeout = 500; socket.SendTimeout = 500; socket.ReceiveBufferSize = NetConstants.SocketBufferSize; socket.SendBufferSize = NetConstants.SocketBufferSize; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { socket.IOControl(SioUdpConnreset, new byte[] { 0 }, null); } catch { //ignored } } try { socket.ExclusiveAddressUse = !reuseAddress; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress); } catch { //Unity with IL2CPP throws an exception here, it doesn't matter in most cases so just ignore it } if (ep.AddressFamily == AddressFamily.InterNetwork || ipv6Mode == IPv6Mode.DualMode) { Ttl = NetConstants.SocketTTL; try { socket.EnableBroadcast = true; } catch (SocketException e) { NetDebug.WriteError($"[B]Broadcast error: {e.SocketErrorCode}"); } if (ipv6Mode == IPv6Mode.DualMode) { try { socket.DualMode = true; } catch (Exception e) { NetDebug.WriteError($"[B]Bind exception (dualmode setting): {e}"); } } else if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { socket.DontFragment = true; } catch (SocketException e) { NetDebug.WriteError($"[B]DontFragment error: {e.SocketErrorCode}"); } } } //Bind try { socket.Bind(ep); NetDebug.Write(NetLogLevel.Trace, $"[B]Successfully binded to port: {((IPEndPoint)socket.LocalEndPoint).Port}, AF: {socket.AddressFamily}"); //join multicast if (ep.AddressFamily == AddressFamily.InterNetworkV6) { try { #if !UNITY_2018_3_OR_NEWER socket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(MulticastAddressV6)); #endif } catch (Exception) { // Unity3d throws exception - ignored } } } catch (SocketException bindException) { switch (bindException.SocketErrorCode) { //IPv6 bind fix case SocketError.AddressAlreadyInUse: if (socket.AddressFamily == AddressFamily.InterNetworkV6 && ipv6Mode != IPv6Mode.DualMode) { try { //Set IPv6Only socket.DualMode = false; socket.Bind(ep); } catch (SocketException ex) { //because its fixed in 2018_3 NetDebug.WriteError($"[B]Bind exception: {ex}, errorCode: {ex.SocketErrorCode}"); return(false); } return(true); } break; //hack for iOS (Unity3D) case SocketError.AddressFamilyNotSupported: return(true); } NetDebug.WriteError($"[B]Bind exception: {bindException}, errorCode: {bindException.SocketErrorCode}"); return(false); } return(true); }