NetPeer.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. #if DEBUG && !UNITY_WP_8_1 && !UNITY_WSA_8_1
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using FlyingWormConsole3.LiteNetLib.Utils;
  6. namespace FlyingWormConsole3.LiteNetLib
  7. {
  8. public enum ConnectionState
  9. {
  10. InProgress,
  11. Connected,
  12. Disconnected
  13. }
  14. public sealed class NetPeer
  15. {
  16. //Flow control
  17. private int _currentFlowMode;
  18. private int _sendedPacketsCount;
  19. private int _flowTimer;
  20. //Ping and RTT
  21. private int _ping;
  22. private int _rtt;
  23. private int _avgRtt;
  24. private int _rttCount;
  25. private int _goodRttCount;
  26. private ushort _pingSequence;
  27. private ushort _remotePingSequence;
  28. private double _resendDelay = 27.0;
  29. private int _pingSendTimer;
  30. private const int RttResetDelay = 1000;
  31. private int _rttResetTimer;
  32. private DateTime _pingTimeStart;
  33. private int _timeSinceLastPacket;
  34. //Common
  35. private readonly NetEndPoint _remoteEndPoint;
  36. private readonly NetManager _peerListener;
  37. private readonly NetPacketPool _packetPool;
  38. private readonly object _flushLock = new object();
  39. //Channels
  40. private readonly ReliableChannel _reliableOrderedChannel;
  41. private readonly ReliableChannel _reliableUnorderedChannel;
  42. private readonly SequencedChannel _sequencedChannel;
  43. private readonly SimpleChannel _simpleChannel;
  44. private int _windowSize = NetConstants.DefaultWindowSize;
  45. //MTU
  46. private int _mtu = NetConstants.PossibleMtu[0];
  47. private int _mtuIdx;
  48. private bool _finishMtu;
  49. private int _mtuCheckTimer;
  50. private int _mtuCheckAttempts;
  51. private const int MtuCheckDelay = 1000;
  52. private const int MaxMtuCheckAttempts = 4;
  53. private readonly object _mtuMutex = new object();
  54. //Fragment
  55. private class IncomingFragments
  56. {
  57. public NetPacket[] Fragments;
  58. public int ReceivedCount;
  59. public int TotalSize;
  60. }
  61. private ushort _fragmentId;
  62. private readonly Dictionary<ushort, IncomingFragments> _holdedFragments;
  63. //Merging
  64. private readonly NetPacket _mergeData;
  65. private int _mergePos;
  66. private int _mergeCount;
  67. //Connection
  68. private int _connectAttempts;
  69. private int _connectTimer;
  70. private long _connectId;
  71. private ConnectionState _connectionState;
  72. public ConnectionState ConnectionState
  73. {
  74. get { return _connectionState; }
  75. }
  76. public long ConnectId
  77. {
  78. get { return _connectId; }
  79. }
  80. public NetEndPoint EndPoint
  81. {
  82. get { return _remoteEndPoint; }
  83. }
  84. public int Ping
  85. {
  86. get { return _ping; }
  87. }
  88. public int CurrentFlowMode
  89. {
  90. get { return _currentFlowMode; }
  91. }
  92. public int Mtu
  93. {
  94. get { return _mtu; }
  95. }
  96. public int TimeSinceLastPacket
  97. {
  98. get { return _timeSinceLastPacket; }
  99. }
  100. public NetManager NetManager
  101. {
  102. get { return _peerListener; }
  103. }
  104. public int PacketsCountInReliableQueue
  105. {
  106. get { return _reliableUnorderedChannel.PacketsInQueue; }
  107. }
  108. public int PacketsCountInReliableOrderedQueue
  109. {
  110. get { return _reliableOrderedChannel.PacketsInQueue; }
  111. }
  112. internal double ResendDelay
  113. {
  114. get { return _resendDelay; }
  115. }
  116. /// <summary>
  117. /// Application defined object containing data about the connection
  118. /// </summary>
  119. public object Tag;
  120. internal NetPeer(NetManager peerListener, NetEndPoint remoteEndPoint, long connectId)
  121. {
  122. _packetPool = peerListener.PacketPool;
  123. _peerListener = peerListener;
  124. _remoteEndPoint = remoteEndPoint;
  125. _avgRtt = 0;
  126. _rtt = 0;
  127. _pingSendTimer = 0;
  128. _reliableOrderedChannel = new ReliableChannel(this, true, _windowSize);
  129. _reliableUnorderedChannel = new ReliableChannel(this, false, _windowSize);
  130. _sequencedChannel = new SequencedChannel(this);
  131. _simpleChannel = new SimpleChannel(this);
  132. _holdedFragments = new Dictionary<ushort, IncomingFragments>();
  133. _mergeData = _packetPool.Get(PacketProperty.Merged, NetConstants.MaxPacketSize);
  134. //if ID != 0 then we already connected
  135. _connectAttempts = 0;
  136. if (connectId == 0)
  137. {
  138. _connectId = DateTime.UtcNow.Ticks;
  139. SendConnectRequest();
  140. }
  141. else
  142. {
  143. _connectId = connectId;
  144. _connectionState = ConnectionState.Connected;
  145. SendConnectAccept();
  146. }
  147. NetUtils.DebugWrite(ConsoleColor.Cyan, "[CC] ConnectId: {0}", _connectId);
  148. }
  149. private void SendConnectRequest()
  150. {
  151. //Get connect key bytes
  152. byte[] keyData = Encoding.UTF8.GetBytes(_peerListener.ConnectKey);
  153. //Make initial packet
  154. var connectPacket = _packetPool.Get(PacketProperty.ConnectRequest, 12 + keyData.Length);
  155. //Add data
  156. FastBitConverter.GetBytes(connectPacket.RawData, 1, NetConstants.ProtocolId);
  157. FastBitConverter.GetBytes(connectPacket.RawData, 5, _connectId);
  158. Buffer.BlockCopy(keyData, 0, connectPacket.RawData, 13, keyData.Length);
  159. //Send raw
  160. _peerListener.SendRawAndRecycle(connectPacket, _remoteEndPoint);
  161. }
  162. private void SendConnectAccept()
  163. {
  164. //Reset connection timer
  165. _timeSinceLastPacket = 0;
  166. //Make initial packet
  167. var connectPacket = _packetPool.Get(PacketProperty.ConnectAccept, 8);
  168. //Add data
  169. FastBitConverter.GetBytes(connectPacket.RawData, 1, _connectId);
  170. //Send raw
  171. _peerListener.SendRawAndRecycle(connectPacket, _remoteEndPoint);
  172. }
  173. internal bool ProcessConnectAccept(NetPacket packet)
  174. {
  175. if (_connectionState != ConnectionState.InProgress)
  176. return false;
  177. //check connection id
  178. if (BitConverter.ToInt64(packet.RawData, 1) != _connectId)
  179. {
  180. return false;
  181. }
  182. NetUtils.DebugWrite(ConsoleColor.Cyan, "[NC] Received connection accept");
  183. _timeSinceLastPacket = 0;
  184. _connectionState = ConnectionState.Connected;
  185. return true;
  186. }
  187. private static PacketProperty SendOptionsToProperty(SendOptions options)
  188. {
  189. switch (options)
  190. {
  191. case SendOptions.ReliableUnordered:
  192. return PacketProperty.Reliable;
  193. case SendOptions.Sequenced:
  194. return PacketProperty.Sequenced;
  195. case SendOptions.ReliableOrdered:
  196. return PacketProperty.ReliableOrdered;
  197. default:
  198. return PacketProperty.Unreliable;
  199. }
  200. }
  201. public int GetMaxSinglePacketSize(SendOptions options)
  202. {
  203. return _mtu - NetPacket.GetHeaderSize(SendOptionsToProperty(options));
  204. }
  205. public void Send(byte[] data, SendOptions options)
  206. {
  207. Send(data, 0, data.Length, options);
  208. }
  209. public void Send(NetDataWriter dataWriter, SendOptions options)
  210. {
  211. Send(dataWriter.Data, 0, dataWriter.Length, options);
  212. }
  213. public void Send(byte[] data, int start, int length, SendOptions options)
  214. {
  215. //Prepare
  216. PacketProperty property = SendOptionsToProperty(options);
  217. int headerSize = NetPacket.GetHeaderSize(property);
  218. //Check fragmentation
  219. if (length + headerSize > _mtu)
  220. {
  221. if (options == SendOptions.Sequenced || options == SendOptions.Unreliable)
  222. {
  223. throw new Exception("Unreliable packet size > allowed (" + (_mtu - headerSize) + ")");
  224. }
  225. int packetFullSize = _mtu - headerSize;
  226. int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize;
  227. int fullPacketsCount = length / packetDataSize;
  228. int lastPacketSize = length % packetDataSize;
  229. int totalPackets = fullPacketsCount + (lastPacketSize == 0 ? 0 : 1);
  230. NetUtils.DebugWrite("FragmentSend:\n" +
  231. " MTU: {0}\n" +
  232. " headerSize: {1}\n" +
  233. " packetFullSize: {2}\n" +
  234. " packetDataSize: {3}\n" +
  235. " fullPacketsCount: {4}\n" +
  236. " lastPacketSize: {5}\n" +
  237. " totalPackets: {6}",
  238. _mtu, headerSize, packetFullSize, packetDataSize, fullPacketsCount, lastPacketSize, totalPackets);
  239. if (totalPackets > ushort.MaxValue)
  240. {
  241. throw new Exception("Too many fragments: " + totalPackets + " > " + ushort.MaxValue);
  242. }
  243. int dataOffset = headerSize + NetConstants.FragmentHeaderSize;
  244. for (ushort i = 0; i < fullPacketsCount; i++)
  245. {
  246. NetPacket p = _packetPool.Get(property, packetFullSize);
  247. p.FragmentId = _fragmentId;
  248. p.FragmentPart = i;
  249. p.FragmentsTotal = (ushort)totalPackets;
  250. p.IsFragmented = true;
  251. Buffer.BlockCopy(data, i * packetDataSize, p.RawData, dataOffset, packetDataSize);
  252. SendPacket(p);
  253. }
  254. if (lastPacketSize > 0)
  255. {
  256. NetPacket p = _packetPool.Get(property, lastPacketSize + NetConstants.FragmentHeaderSize);
  257. p.FragmentId = _fragmentId;
  258. p.FragmentPart = (ushort)fullPacketsCount; //last
  259. p.FragmentsTotal = (ushort)totalPackets;
  260. p.IsFragmented = true;
  261. Buffer.BlockCopy(data, fullPacketsCount * packetDataSize, p.RawData, dataOffset, lastPacketSize);
  262. SendPacket(p);
  263. }
  264. _fragmentId++;
  265. return;
  266. }
  267. //Else just send
  268. NetPacket packet = _packetPool.GetWithData(property, data, start, length);
  269. SendPacket(packet);
  270. }
  271. private void CreateAndSend(PacketProperty property, ushort sequence)
  272. {
  273. NetPacket packet = _packetPool.Get(property, 0);
  274. packet.Sequence = sequence;
  275. SendPacket(packet);
  276. }
  277. //from user thread, our thread, or recv?
  278. private void SendPacket(NetPacket packet)
  279. {
  280. NetUtils.DebugWrite("[RS]Packet: " + packet.Property);
  281. switch (packet.Property)
  282. {
  283. case PacketProperty.Reliable:
  284. _reliableUnorderedChannel.AddToQueue(packet);
  285. break;
  286. case PacketProperty.Sequenced:
  287. _sequencedChannel.AddToQueue(packet);
  288. break;
  289. case PacketProperty.ReliableOrdered:
  290. _reliableOrderedChannel.AddToQueue(packet);
  291. break;
  292. case PacketProperty.Unreliable:
  293. _simpleChannel.AddToQueue(packet);
  294. break;
  295. case PacketProperty.MtuCheck:
  296. //Must check result for MTU fix
  297. if (!_peerListener.SendRawAndRecycle(packet, _remoteEndPoint))
  298. {
  299. _finishMtu = true;
  300. }
  301. break;
  302. case PacketProperty.AckReliable:
  303. case PacketProperty.AckReliableOrdered:
  304. case PacketProperty.Ping:
  305. case PacketProperty.Pong:
  306. case PacketProperty.Disconnect:
  307. case PacketProperty.MtuOk:
  308. SendRawData(packet);
  309. _packetPool.Recycle(packet);
  310. break;
  311. default:
  312. throw new Exception("Unknown packet property: " + packet.Property);
  313. }
  314. }
  315. private void UpdateRoundTripTime(int roundTripTime)
  316. {
  317. //Calc average round trip time
  318. _rtt += roundTripTime;
  319. _rttCount++;
  320. _avgRtt = _rtt/_rttCount;
  321. //flowmode 0 = fastest
  322. //flowmode max = lowest
  323. if (_avgRtt < _peerListener.GetStartRtt(_currentFlowMode - 1))
  324. {
  325. if (_currentFlowMode <= 0)
  326. {
  327. //Already maxed
  328. return;
  329. }
  330. _goodRttCount++;
  331. if (_goodRttCount > NetConstants.FlowIncreaseThreshold)
  332. {
  333. _goodRttCount = 0;
  334. _currentFlowMode--;
  335. NetUtils.DebugWrite("[PA]Increased flow speed, RTT: {0}, PPS: {1}", _avgRtt, _peerListener.GetPacketsPerSecond(_currentFlowMode));
  336. }
  337. }
  338. else if(_avgRtt > _peerListener.GetStartRtt(_currentFlowMode))
  339. {
  340. _goodRttCount = 0;
  341. if (_currentFlowMode < _peerListener.GetMaxFlowMode())
  342. {
  343. _currentFlowMode++;
  344. NetUtils.DebugWrite("[PA]Decreased flow speed, RTT: {0}, PPS: {1}", _avgRtt, _peerListener.GetPacketsPerSecond(_currentFlowMode));
  345. }
  346. }
  347. //recalc resend delay
  348. double avgRtt = _avgRtt;
  349. if (avgRtt <= 0.0)
  350. avgRtt = 0.1;
  351. _resendDelay = 25 + (avgRtt * 2.1); // 25 ms + double rtt
  352. }
  353. internal void AddIncomingPacket(NetPacket p)
  354. {
  355. if (p.IsFragmented)
  356. {
  357. NetUtils.DebugWrite("Fragment. Id: {0}, Part: {1}, Total: {2}", p.FragmentId, p.FragmentPart, p.FragmentsTotal);
  358. //Get needed array from dictionary
  359. ushort packetFragId = p.FragmentId;
  360. IncomingFragments incomingFragments;
  361. if (!_holdedFragments.TryGetValue(packetFragId, out incomingFragments))
  362. {
  363. incomingFragments = new IncomingFragments
  364. {
  365. Fragments = new NetPacket[p.FragmentsTotal]
  366. };
  367. _holdedFragments.Add(packetFragId, incomingFragments);
  368. }
  369. //Cache
  370. var fragments = incomingFragments.Fragments;
  371. //Error check
  372. if (p.FragmentPart >= fragments.Length || fragments[p.FragmentPart] != null)
  373. {
  374. _packetPool.Recycle(p);
  375. NetUtils.DebugWriteError("Invalid fragment packet");
  376. return;
  377. }
  378. //Fill array
  379. fragments[p.FragmentPart] = p;
  380. //Increase received fragments count
  381. incomingFragments.ReceivedCount++;
  382. //Increase total size
  383. int dataOffset = p.GetHeaderSize() + NetConstants.FragmentHeaderSize;
  384. incomingFragments.TotalSize += p.Size - dataOffset;
  385. //Check for finish
  386. if (incomingFragments.ReceivedCount != fragments.Length)
  387. {
  388. return;
  389. }
  390. NetUtils.DebugWrite("Received all fragments!");
  391. NetPacket resultingPacket = _packetPool.Get( p.Property, incomingFragments.TotalSize );
  392. int resultingPacketOffset = resultingPacket.GetHeaderSize();
  393. int firstFragmentSize = fragments[0].Size - dataOffset;
  394. for (int i = 0; i < incomingFragments.ReceivedCount; i++)
  395. {
  396. //Create resulting big packet
  397. int fragmentSize = fragments[i].Size - dataOffset;
  398. Buffer.BlockCopy(
  399. fragments[i].RawData,
  400. dataOffset,
  401. resultingPacket.RawData,
  402. resultingPacketOffset + firstFragmentSize * i,
  403. fragmentSize);
  404. //Free memory
  405. _packetPool.Recycle(fragments[i]);
  406. fragments[i] = null;
  407. }
  408. //Send to process
  409. _peerListener.ReceiveFromPeer(resultingPacket, _remoteEndPoint);
  410. //Clear memory
  411. _packetPool.Recycle(resultingPacket);
  412. _holdedFragments.Remove(packetFragId);
  413. }
  414. else //Just simple packet
  415. {
  416. _peerListener.ReceiveFromPeer(p, _remoteEndPoint);
  417. _packetPool.Recycle(p);
  418. }
  419. }
  420. private void ProcessMtuPacket(NetPacket packet)
  421. {
  422. if (packet.Size == 1 ||
  423. packet.RawData[1] >= NetConstants.PossibleMtu.Length)
  424. return;
  425. //MTU auto increase
  426. if (packet.Property == PacketProperty.MtuCheck)
  427. {
  428. if (packet.Size != NetConstants.PossibleMtu[packet.RawData[1]])
  429. {
  430. return;
  431. }
  432. _mtuCheckAttempts = 0;
  433. NetUtils.DebugWrite("MTU check. Resend: " + packet.RawData[1]);
  434. var mtuOkPacket = _packetPool.Get(PacketProperty.MtuOk, 1);
  435. mtuOkPacket.RawData[1] = packet.RawData[1];
  436. SendPacket(mtuOkPacket);
  437. }
  438. else if(packet.RawData[1] > _mtuIdx) //MtuOk
  439. {
  440. lock (_mtuMutex)
  441. {
  442. _mtuIdx = packet.RawData[1];
  443. _mtu = NetConstants.PossibleMtu[_mtuIdx];
  444. }
  445. //if maxed - finish.
  446. if (_mtuIdx == NetConstants.PossibleMtu.Length - 1)
  447. {
  448. _finishMtu = true;
  449. }
  450. NetUtils.DebugWrite("MTU ok. Increase to: " + _mtu);
  451. }
  452. }
  453. //Process incoming packet
  454. internal void ProcessPacket(NetPacket packet)
  455. {
  456. _timeSinceLastPacket = 0;
  457. NetUtils.DebugWrite("[RR]PacketProperty: {0}", packet.Property);
  458. switch (packet.Property)
  459. {
  460. case PacketProperty.ConnectRequest:
  461. //response with connect
  462. long newId = BitConverter.ToInt64(packet.RawData, 1);
  463. if (newId > _connectId)
  464. {
  465. _connectId = newId;
  466. }
  467. NetUtils.DebugWrite("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}", ConnectId, newId, _remoteEndPoint);
  468. SendConnectAccept();
  469. _packetPool.Recycle(packet);
  470. break;
  471. case PacketProperty.Merged:
  472. int pos = NetConstants.HeaderSize;
  473. while (pos < packet.Size)
  474. {
  475. ushort size = BitConverter.ToUInt16(packet.RawData, pos);
  476. pos += 2;
  477. NetPacket mergedPacket = _packetPool.GetAndRead(packet.RawData, pos, size);
  478. if (mergedPacket == null)
  479. {
  480. _packetPool.Recycle(packet);
  481. break;
  482. }
  483. pos += size;
  484. ProcessPacket(mergedPacket);
  485. }
  486. break;
  487. //If we get ping, send pong
  488. case PacketProperty.Ping:
  489. if (NetUtils.RelativeSequenceNumber(packet.Sequence, _remotePingSequence) < 0)
  490. {
  491. _packetPool.Recycle(packet);
  492. break;
  493. }
  494. NetUtils.DebugWrite("[PP]Ping receive, send pong");
  495. _remotePingSequence = packet.Sequence;
  496. _packetPool.Recycle(packet);
  497. //send
  498. CreateAndSend(PacketProperty.Pong, _remotePingSequence);
  499. break;
  500. //If we get pong, calculate ping time and rtt
  501. case PacketProperty.Pong:
  502. if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pingSequence) < 0)
  503. {
  504. _packetPool.Recycle(packet);
  505. break;
  506. }
  507. _pingSequence = packet.Sequence;
  508. int rtt = (int)(DateTime.UtcNow - _pingTimeStart).TotalMilliseconds;
  509. UpdateRoundTripTime(rtt);
  510. NetUtils.DebugWrite("[PP]Ping: {0}", rtt);
  511. _packetPool.Recycle(packet);
  512. break;
  513. //Process ack
  514. case PacketProperty.AckReliable:
  515. _reliableUnorderedChannel.ProcessAck(packet);
  516. _packetPool.Recycle(packet);
  517. break;
  518. case PacketProperty.AckReliableOrdered:
  519. _reliableOrderedChannel.ProcessAck(packet);
  520. _packetPool.Recycle(packet);
  521. break;
  522. //Process in order packets
  523. case PacketProperty.Sequenced:
  524. _sequencedChannel.ProcessPacket(packet);
  525. break;
  526. case PacketProperty.Reliable:
  527. _reliableUnorderedChannel.ProcessPacket(packet);
  528. break;
  529. case PacketProperty.ReliableOrdered:
  530. _reliableOrderedChannel.ProcessPacket(packet);
  531. break;
  532. //Simple packet without acks
  533. case PacketProperty.Unreliable:
  534. AddIncomingPacket(packet);
  535. return;
  536. case PacketProperty.MtuCheck:
  537. case PacketProperty.MtuOk:
  538. ProcessMtuPacket(packet);
  539. break;
  540. default:
  541. NetUtils.DebugWriteError("Error! Unexpected packet type: " + packet.Property);
  542. break;
  543. }
  544. }
  545. private static bool CanMerge(PacketProperty property)
  546. {
  547. switch (property)
  548. {
  549. case PacketProperty.ConnectAccept:
  550. case PacketProperty.ConnectRequest:
  551. case PacketProperty.MtuOk:
  552. case PacketProperty.Pong:
  553. case PacketProperty.Disconnect:
  554. return false;
  555. default:
  556. return true;
  557. }
  558. }
  559. internal void SendRawData(NetPacket packet)
  560. {
  561. //2 - merge byte + minimal packet size + datalen(ushort)
  562. if (_peerListener.MergeEnabled &&
  563. CanMerge(packet.Property) &&
  564. _mergePos + packet.Size + NetConstants.HeaderSize*2 + 2 < _mtu)
  565. {
  566. FastBitConverter.GetBytes(_mergeData.RawData, _mergePos + NetConstants.HeaderSize, (ushort)packet.Size);
  567. Buffer.BlockCopy(packet.RawData, 0, _mergeData.RawData, _mergePos + NetConstants.HeaderSize + 2, packet.Size);
  568. _mergePos += packet.Size + 2;
  569. _mergeCount++;
  570. //DebugWriteForce("Merged: " + _mergePos + "/" + (_mtu - 2) + ", count: " + _mergeCount);
  571. return;
  572. }
  573. NetUtils.DebugWrite(ConsoleColor.DarkYellow, "[P]SendingPacket: " + packet.Property);
  574. _peerListener.SendRaw(packet.RawData, 0, packet.Size, _remoteEndPoint);
  575. }
  576. private void SendQueuedPackets(int currentMaxSend)
  577. {
  578. int currentSended = 0;
  579. while (currentSended < currentMaxSend)
  580. {
  581. //Get one of packets
  582. if (_reliableOrderedChannel.SendNextPacket() ||
  583. _reliableUnorderedChannel.SendNextPacket() ||
  584. _sequencedChannel.SendNextPacket() ||
  585. _simpleChannel.SendNextPacket())
  586. {
  587. currentSended++;
  588. }
  589. else
  590. {
  591. //no outgoing packets
  592. break;
  593. }
  594. }
  595. //Increase counter
  596. _sendedPacketsCount += currentSended;
  597. //If merging enabled
  598. if (_mergePos > 0)
  599. {
  600. if (_mergeCount > 1)
  601. {
  602. NetUtils.DebugWrite("Send merged: " + _mergePos + ", count: " + _mergeCount);
  603. _peerListener.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, _remoteEndPoint);
  604. }
  605. else
  606. {
  607. //Send without length information and merging
  608. _peerListener.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, _remoteEndPoint);
  609. }
  610. _mergePos = 0;
  611. _mergeCount = 0;
  612. }
  613. }
  614. /// <summary>
  615. /// Flush all queued packets
  616. /// </summary>
  617. public void Flush()
  618. {
  619. lock (_flushLock)
  620. {
  621. SendQueuedPackets(int.MaxValue);
  622. }
  623. }
  624. internal void Update(int deltaTime)
  625. {
  626. if (_connectionState == ConnectionState.Disconnected)
  627. {
  628. return;
  629. }
  630. _timeSinceLastPacket += deltaTime;
  631. if (_connectionState == ConnectionState.InProgress)
  632. {
  633. _connectTimer += deltaTime;
  634. if (_connectTimer > _peerListener.ReconnectDelay)
  635. {
  636. _connectTimer = 0;
  637. _connectAttempts++;
  638. if (_connectAttempts > _peerListener.MaxConnectAttempts)
  639. {
  640. _connectionState = ConnectionState.Disconnected;
  641. return;
  642. }
  643. //else send connect again
  644. SendConnectRequest();
  645. }
  646. return;
  647. }
  648. //Get current flow mode
  649. int maxSendPacketsCount = _peerListener.GetPacketsPerSecond(_currentFlowMode);
  650. int currentMaxSend;
  651. if (maxSendPacketsCount > 0)
  652. {
  653. int availableSendPacketsCount = maxSendPacketsCount - _sendedPacketsCount;
  654. currentMaxSend = Math.Min(availableSendPacketsCount, (maxSendPacketsCount*deltaTime)/NetConstants.FlowUpdateTime);
  655. }
  656. else
  657. {
  658. currentMaxSend = int.MaxValue;
  659. }
  660. //DebugWrite("[UPDATE]Delta: {0}ms, MaxSend: {1}", deltaTime, currentMaxSend);
  661. //Pending acks
  662. _reliableOrderedChannel.SendAcks();
  663. _reliableUnorderedChannel.SendAcks();
  664. //ResetFlowTimer
  665. _flowTimer += deltaTime;
  666. if (_flowTimer >= NetConstants.FlowUpdateTime)
  667. {
  668. NetUtils.DebugWrite("[UPDATE]Reset flow timer, _sendedPackets - {0}", _sendedPacketsCount);
  669. _sendedPacketsCount = 0;
  670. _flowTimer = 0;
  671. }
  672. //Send ping
  673. _pingSendTimer += deltaTime;
  674. if (_pingSendTimer >= _peerListener.PingInterval)
  675. {
  676. NetUtils.DebugWrite("[PP] Send ping...");
  677. //reset timer
  678. _pingSendTimer = 0;
  679. //send ping
  680. CreateAndSend(PacketProperty.Ping, _pingSequence);
  681. //reset timer
  682. _pingTimeStart = DateTime.UtcNow;
  683. }
  684. //RTT - round trip time
  685. _rttResetTimer += deltaTime;
  686. if (_rttResetTimer >= RttResetDelay)
  687. {
  688. _rttResetTimer = 0;
  689. //Rtt update
  690. _rtt = _avgRtt;
  691. _ping = _avgRtt;
  692. _peerListener.ConnectionLatencyUpdated(this, _ping);
  693. _rttCount = 1;
  694. }
  695. //MTU - Maximum transmission unit
  696. if (!_finishMtu)
  697. {
  698. _mtuCheckTimer += deltaTime;
  699. if (_mtuCheckTimer >= MtuCheckDelay)
  700. {
  701. _mtuCheckTimer = 0;
  702. _mtuCheckAttempts++;
  703. if (_mtuCheckAttempts >= MaxMtuCheckAttempts)
  704. {
  705. _finishMtu = true;
  706. }
  707. else
  708. {
  709. lock (_mtuMutex)
  710. {
  711. //Send increased packet
  712. if (_mtuIdx < NetConstants.PossibleMtu.Length - 1)
  713. {
  714. int newMtu = NetConstants.PossibleMtu[_mtuIdx + 1] - NetConstants.HeaderSize;
  715. var p = _packetPool.Get(PacketProperty.MtuCheck, newMtu);
  716. p.RawData[1] = (byte)(_mtuIdx + 1);
  717. SendPacket(p);
  718. }
  719. }
  720. }
  721. }
  722. }
  723. //MTU - end
  724. //Pending send
  725. lock (_flushLock)
  726. {
  727. SendQueuedPackets(currentMaxSend);
  728. }
  729. }
  730. //For channels
  731. internal void Recycle(NetPacket packet)
  732. {
  733. _packetPool.Recycle(packet);
  734. }
  735. internal NetPacket GetPacketFromPool(PacketProperty property, int bytesCount)
  736. {
  737. return _packetPool.Get(property, bytesCount);
  738. }
  739. }
  740. }
  741. #endif