/// <summary>Create a link</summary> /// <param name="address">Address</param> /// <param name="approval">Approval</param> public Link Link(string address, Content approval) { if (string.IsNullOrEmpty(address)) { throw new ArgumentException("An IPv4 network address was expected"); } if (approval != null && approval.Protocol != Content.RELIABLE) { throw new NetworkException("A reliable content was expected"); } // Content APPROVAL if (approval == null) { approval = Content.Reliable(); } approval.SetHeader(Content.APPROVAL); // Create a link var link = new Link(address, approval, this); // Register a link LinksByEndPoint.Setter(link, link); return(link); }
/// <summary>ICHANNEL Outlet</summary> /// <param name="content">Content</param> void IChannel.Outlet(Content content) { if ((content.Protocol & Content.IDENTIFIABLE) == 0) { return; } // MTU minis 20 bytes of UDP IPv4 header var mtu = Network.Settings.MTU - 20; // Sets the sequence content.Sequence = Sequence; // Fragments in parts compatible with MTU if (content.LengthBytes > mtu) { // Fragments var fragments = content.Fragmenter(mtu); for (int i = 0; i < fragments.Length; i++) { // Set the current timestamp and packing // Add 10 milliseconds to save connection fragments[i].Timestamp = content.Timestamp + ((uint)i * 10); fragments[i].Packing(); // Attempts Attempts.Setter(fragments[i].Identifier, 0); // Add to the package table Contents.Setter(fragments[i].Identifier, fragments[i]); // Send immediately var size = (uint)Network.Outlet(fragments[i], Link); // Statistics Network.Statistics.PacketSent(size, true); Link.Statistics.PacketSent(size, true); } } // Simple reliable else { // Copy content var contentOrig = content; content = Content.New(0); content.Copy(contentOrig); // Packing content.Packing(); // Attempts Attempts.Setter(content.Identifier, 0); // Add to the package table Contents.Setter(content.Identifier, content); // Send immediately var size = (uint)Network.Outlet(content, Link); // Statistics Network.Statistics.PacketSent(size, true); Link.Statistics.PacketSent(size, true); } // Next sequence NextSequence(); }
/// <summary>Do FRAGMENT</summary> /// <returns>True if FRAGMENT</returns> /// <param name="content">Content</param> private bool DoFragment(Content content) { if (content.Protocol != Content.FRAGMENT) { return(false); } // Size of the content is within the expected if (content.LengthBits >= Content.RELIABLE_HEADER) { // Content not delivered if (!Acks.Contains(content.Sequence)) { // Merge the received fragment if (Cached.Contains(content.Sequence)) { // Cached content var cachedContent = Cached[content.Sequence]; // Is within expected sequence if (content.Fragment == (cachedContent.Fragment + 1)) { // Make response MakeResponse(content); // Defragmenter cachedContent.Defragmenter(content); // Update timestamp cachedContent.Timestamp = content.Timestamp; // Content is complete if (content.Fragment == cachedContent.Fragments) { Acks.Setter(content.Sequence, content.Timestamp); } } } else { // Stores the first content of the stream if (content.Fragment == 1) { // Add content Cached.Setter(content.Sequence, content); // Make response MakeResponse(content); return(true); } } } // already delivered else { MakeResponse(content); } } return(true); }