/// <summary> /// Checks package for completed transfer /// </summary> /// <param name="package">Specified package</param> private bool CheckIsPackageSent(Package package) { if (package.Sent == package.SizeTotal() || // Sended from some node package.To == package.FromNow) // Reached next node { if (package.ImInfoAndICanBeDeleted || package.IsService) DeletePackage(package); // If need further send if (!package.ReceiverHasOverflowedBuffer && package.Sent == package.SizeTotal()) { var packageOtherSide = Nodes[package.ToNow].Buffer[package.ReceiverBufIdx]; if (!package.IsService) { Nodes[package.ToNow].Buffer.Add(new Package { IsService = true, ApprovesPackage = true, ApproveFrom = package.FromNow, //ApproveTo = package.ToNow, From = package.ToNow, To = package.FromNow, FromNow = package.ToNow, AlreadySentOnThisTick = true, Sent = 0, MyBufIdx = Nodes[package.ToNow].Buffer.Count, IsDatagram = true, ApproveBufferIdxWhoWait = package.MyBufIdx, }); if (package.IsDatagram) ServiceDg++; else ServiceVc++; // For statistics if (package.Sent == package.SizeTotal()) if (package.IsDatagram) DatagramsReceived++; else VirtualReceived++; // For global history if (packageOtherSide.FromNow == packageOtherSide.To) { var completedPacks = Nodes[packageOtherSide.FromNow].Buffer.Count(pack => pack.Id == packageOtherSide.Id); if (completedPacks == packageOtherSide.Parts && !CompletedMessages.Contains(packageOtherSide.Id)) { CompletedMessages.Add(packageOtherSide.Id); _messages[packageOtherSide.Id].MessageCompletedOn = TickNumber; } } packageOtherSide.Received = -1; packageOtherSide.Sent = 0; packageOtherSide.CreatedOn = TickNumber; // If other size package reached final destiny if (package.To == package.ToNow) DeletePackage(packageOtherSide); } else { if (package.ApprovesPackage) DeletePackage(packageOtherSide); } } if (package.ApprovesPackage && package.To == package.ToNow) { var packageInfo = Nodes[package.ApproveFrom].Buffer[package.ApproveBufferIdxWhoWait]; packageInfo.ImInfoAndICanBeDeleted = true; DeletePackage(packageInfo); } return true; } return false; }
/// <summary> /// Checks how many bytes can be sent from package throughselected connection /// </summary> /// <param name="package">Specified package</param> /// <returns></returns> private int HowManySend(Package package) { var connSendThrough = Connections[package.SendThroughConnection]; int willSend; // Sending through full duplex if (connSendThrough.IsFullDuplex) { willSend = connSendThrough.TransferRate / 2; if (connSendThrough.SendingFromNode == package.FromNow) willSend -= connSendThrough.FilledFromNode; else willSend -= connSendThrough.FilledToNode; } else // Sending through half duplex { willSend = connSendThrough.TransferRate; if (connSendThrough.SendingFromNode == package.FromNow) willSend -= connSendThrough.FilledFromNode; else willSend -= connSendThrough.FilledToNode; } // "Send" if (package.SizeTotal() < package.Sent + willSend) willSend = package.SizeTotal() - package.Sent; package.Sent += willSend; // Set connection fill if (connSendThrough.IsFullDuplex) if (connSendThrough.SendingFromNode == package.FromNow) connSendThrough.FilledFromNode += willSend; else connSendThrough.FilledToNode += willSend; else // Sending through half duplex if (connSendThrough.SendingFromNode == package.FromNow) connSendThrough.FilledFromNode += willSend; else connSendThrough.FilledToNode += willSend; return willSend; }
/// <summary> /// Sends message (from template in parameter) /// </summary> /// <param name="package">Package with initial data</param> public void SendPackage(Package package) { // Divide to packages var packages = new List<Package>(); _messages.Add(new Package { Id = FreeId, MessageCreatedOn = TickNumber }); if (package.SizeTotal() <= SizeMaxPackage) // If message is in size like one package { package.FromNow = package.From; package.Id = FreeId; package.MyBufIdx = Nodes[package.From].Buffer.Count; package.Sent = 0; package.PartIdx = 0; package.TickGeneratedOn = TickNumber; // For statistics package.CreatedOn = TickNumber; // For statistics packages.Add(package); SendedMessagePart = 1; // For external world if (package.IsDatagram) DatagramsSent++; else VirtualSent++; } else // If bigger { // Divide message to packages var sizeMaxInf = SizeMaxPackage - Package.SizeHeader; var packagesNumber = Convert.ToInt32(Math.Ceiling(package.SizeInformation / (double)sizeMaxInf)); if (package.IsDatagram) DatagramsSent += packagesNumber; else VirtualSent += packagesNumber; SendedMessagePart = packagesNumber; // For external world var firstBufIdx = Nodes[package.From].Buffer.Count; for (var i = 0; i < packagesNumber - 1; i++) // Several the same packages packages.Add(new Package { To = package.To, FromNow = package.From, From = package.From, IsDatagram = package.IsDatagram, Id = FreeId, PartIdx = i, SizeInformation = sizeMaxInf, MyBufIdx = firstBufIdx + i, Sent = 0, Parts = packagesNumber, TickGeneratedOn = TickNumber, // For statistics CreatedOn = TickNumber // For statistics }); // Last package can be lesser in size var sizeLastInf = package.SizeInformation % sizeMaxInf; packages.Add(new Package { To = package.To, FromNow = package.From, From = package.From, IsDatagram = package.IsDatagram, Id = FreeId, PartIdx = packagesNumber - 1, SizeInformation = sizeLastInf, MyBufIdx = firstBufIdx + packagesNumber - 1, Sent = 0, Parts = packagesNumber, TickGeneratedOn = TickNumber, // For statistics CreatedOn = TickNumber // For statistics }); } // Add packages while it isn't filled foreach (var pack in packages.TakeWhile(pack => BufferSize > Nodes[package.From].Buffer.Count)) Nodes[package.From].Buffer.Add(pack); // Add new packages to buffer //Nodes[package.From].Buffer.AddRange(packages); FreeId++; }