/// <summary> /// Creates a peer address from a continuous byte array. This is useful if you don't know the size beforehand. /// The new offset can be accessed through the Offset property. /// </summary> /// <param name="me">The serialized array.</param> /// <param name="initialOffset">The offset where to start.</param> public PeerAddress(sbyte[] me, int initialOffset) { // get the peer ID, this is independent of the type long offset = initialOffset; // get the options int options = me[offset++] & Utils.Utils.MaskFf; IsIPv6 = (options & Net6) > 0; // TODO static methods could be used instead IsFirewalledUdp = (options & FirewallUdp) > 0; IsFirewalledTcp = (options & FirewallTcp) > 0; IsRelayed = (options & Relayed) > 0; // get the relays int relays = me[offset++] & Utils.Utils.MaskFf; // first 3 bits are the size RelaySize = (relays >> TypeBitSize) & Mask07; // last 5 bits indicate if IPv6 or IPv4 var b = (byte)(relays & Mask1F); // TODO check if works (2x) _relayType = new BitArray(b); // get the ID var tmp = new sbyte[Number160.ByteArraySize]; Array.Copy(me, offset, tmp, 0, Number160.ByteArraySize); PeerId = new Number160(tmp); offset += Number160.ByteArraySize; PeerSocketAddress = PeerSocketAddress.Create(me, IsIPv4, offset); offset = PeerSocketAddress.Offset; if (RelaySize > 0) { PeerSocketAddresses = new List <PeerSocketAddress>(RelaySize); for (int i = 0; i < RelaySize; i++) { var psa = PeerSocketAddress.Create(me, !_relayType.Get(i), offset); PeerSocketAddresses.Add(psa); offset = psa.Offset; } } else { PeerSocketAddresses = EmptyPeerSocketAddresses; } Size = offset - initialOffset; Offset = offset; _hashCode = PeerId.GetHashCode(); }
/// <summary> /// Creates a peer address from a byte buffer. /// </summary> /// <param name="buffer">The channel buffer to read from.</param> public PeerAddress(AlternativeCompositeByteBuf buffer) { long readerIndex = buffer.ReaderIndex; // get the type int options = buffer.ReadByte(); IsIPv6 = (options & Net6) > 0; IsFirewalledUdp = (options & FirewallUdp) > 0; IsFirewalledTcp = (options & FirewallTcp) > 0; IsRelayed = (options & Relayed) > 0; // get the relays int relays = buffer.ReadByte(); RelaySize = (relays >> TypeBitSize) & Mask07; var b = (byte)(relays & Mask1F); // TODO check if works (2x) _relayType = new BitArray(b); // get the ID var me = new sbyte[Number160.ByteArraySize]; buffer.ReadBytes(me); PeerId = new Number160(me); PeerSocketAddress = PeerSocketAddress.Create(buffer, IsIPv4); if (RelaySize > 0) { PeerSocketAddresses = new List <PeerSocketAddress>(RelaySize); for (int i = 0; i < RelaySize; i++) { PeerSocketAddresses.Add(PeerSocketAddress.Create(buffer, !_relayType.Get(i))); } } else { PeerSocketAddresses = EmptyPeerSocketAddresses; } Size = buffer.ReaderIndex - readerIndex; Offset = -1; // not used here _hashCode = PeerId.GetHashCode(); }
/// <summary> /// Creates a peer address if all the values are known. /// </summary> /// <param name="id">The ID of the peer.</param> /// <param name="peerSocketAddress">The peer socket address including both ports UDP and TCP.</param> /// <param name="isFirewalledTcp">Indicates if the peer is not reachable via UDP.</param> /// <param name="isFirewalledUdp">Indicates if the peer is not reachable via TCP.</param> /// <param name="isRelayed">Indicates if the peer is used as a relay.</param> /// <param name="peerSocketAddresses">The relay peers.</param> public PeerAddress(Number160 id, PeerSocketAddress peerSocketAddress, bool isFirewalledTcp, bool isFirewalledUdp, bool isRelayed, ICollection <PeerSocketAddress> peerSocketAddresses) { PeerId = id; int size = Number160.ByteArraySize; PeerSocketAddress = peerSocketAddress; _hashCode = id.GetHashCode(); IsIPv6 = peerSocketAddress.InetAddress.IsIPv6(); IsFirewalledUdp = isFirewalledUdp; IsFirewalledTcp = isFirewalledTcp; IsRelayed = isRelayed; // header + TCP port + UDP port size += HeaderSize + PortsSize + (IsIPv6 ? Utils.Utils.IPv6Bytes : Utils.Utils.IPv4Bytes); if (PeerSocketAddresses == null) { PeerSocketAddresses = EmptyPeerSocketAddresses; _relayType = EmptyRelayType; RelaySize = 0; } else { RelaySize = PeerSocketAddresses.Count; if (RelaySize > TypeBitSize) { throw new ArgumentException(String.Format("Can only store up to {0} relay peers. Tried to store {1} relay peers.", TypeBitSize, RelaySize)); } PeerSocketAddresses = peerSocketAddresses; _relayType = new BitArray(RelaySize); } int index = 0; foreach (var psa in peerSocketAddresses) { bool isIPv6 = psa.InetAddress.IsIPv6(); _relayType.Set(index, isIPv6); size += psa.Size(); index++; } Size = size; Offset = -1; // not used here }
/// <summary> /// Serializes to an existing array. /// </summary> /// <param name="me">The array where the result should be stored.</param> /// <param name="offset">The offset where to start to save the result in the byte array.</param> /// <returns>The new offset.</returns> public int ToByteArray(sbyte[] me, int offset) { // save the peer ID int newOffset = offset; me[newOffset++] = Options; me[newOffset++] = Relays; newOffset = PeerId.ToByteArray(me, newOffset); // we store both the addresses of the peer and the relays // currently, this is not needed as we don't consider asymmetric relays newOffset = PeerSocketAddress.ToByteArray(me, newOffset); foreach (var psa in PeerSocketAddresses) { newOffset = psa.ToByteArray(me, newOffset); } return(newOffset); }
public PeerAddress ChangePeerSocketAddress(PeerSocketAddress peerSocketAddress) { return(new PeerAddress(PeerId, peerSocketAddress, IsFirewalledTcp, IsFirewalledUdp, IsRelayed, PeerSocketAddresses)); }