public void Send(IPEndPoint endPoint, byte[] buffer, int offset, int length, bool reliable) { var seqState = GetSeqStateOnSend(endPoint); if (seqState.DisconnectRequestSent) { return; } // Don't send until connected if (seqState.SessionId == PacketHeader.EmptySessionId) { return; } // Reliable packets should wait for ack before going to pool var putBufferToPool = !reliable; if (length > MaxPayload - seqState.AckLoad) { ushort fragId = seqState.NextFragId(); // Cut packet var fragmentCount = (length + seqState.FullAckLoad + MaxPayload - 1) / MaxPayload; var tailSize = length; var fragmentOffset = 0; for (int i = 0; i < fragmentCount; ++i) { var fragmentSize = Math.Min(MaxPayload - seqState.AckLoad, tailSize); tailSize -= fragmentSize; var fullBuffer = WrapFragment(seqState, buffer, fragmentOffset, fragmentSize, fragId, (ushort)i, (ushort)fragmentCount, reliable); // It should be done after using fragmentOffset to cut fragment fragmentOffset += fragmentSize; try { SubSock.Send(endPoint, fullBuffer.Array, fullBuffer.Offset, fullBuffer.Count, putBufferToPool); } catch (SocketException) { Close(endPoint, seqState); break; } } } else { var fullBuffer = Wrap(seqState, buffer, offset, length, reliable); try { SubSock.Send(endPoint, fullBuffer.Array, fullBuffer.Offset, fullBuffer.Count, putBufferToPool); } catch (SocketException) { Close(endPoint, seqState); } } }
public void Tick(IPEndPoint endPoint, SockBase sock, int now, int ackTimeout, int fragmentTimeout) { var notAckedCount = _notAcked.Count; for (int i = 0; i < notAckedCount; ++i) { var packet = _notAcked[i]; if (now - packet.SendTicks > ackTimeout) { sock.Send(endPoint, packet.Buffer, packet.Offset, packet.Length, false); packet.SendTicks = now; _notAcked[i] = packet; } } var packetsCount = _frags.Count; for (int i = packetsCount - 1; i >= 0; --i) { var frag = _frags[i]; if (SmartSock.TimeDelta(frag.LastActive, now) > fragmentTimeout) { _frags.RemoveAt(i); _fragPacketsPool.Put(frag); } } while (_ackQueue.Count > 0) { var header = _headersPool.Get(); AddAcks(header); header.SetSessionId(SessionId); header.Length = (ushort)header.HeaderLength; var buffer = _buffersPool.Get(header.Length); header.WriteTo(buffer, 0); sock.Send(endPoint, buffer, 0, header.Length, true); _headersPool.Put(header); } }