예제 #1
0
        private void Heartbeating(object state)
        {
            var ctx = (ChannelHandlerContext)state;

            if (!ctx.Channel.IsOpen)
            {
                return;
            }

            var currentTime = Convenient.CurrentTimeMillis();
            var lastIoTime  = Math.Max(_lastReadTime.Get(), _lastWriteTime.Get());
            var nextDelay   = TimeToHeartBeatMillis - (currentTime - lastIoTime);

            if (_peerConnection != null && nextDelay <= 0)
            {
                Logger.Debug("Sending heart beat to {0}. Channel: {1}.", _peerConnection.RemotePeer, _peerConnection.Channel);
                var builder  = _pingBuilderFactory.Create();
                var taskPing = builder.SetPeerConnection(_peerConnection).Start();
                builder.NotifyAutomaticFutures(taskPing);
            }
            else
            {
                // TODO fix possible NPE
                Logger.Debug("Not sending heart beat to {0}. Channel: {1}.", _peerConnection.RemotePeer, _peerConnection.Channel);
            }
        }
예제 #2
0
        public override async Task DoReceiveMessageAsync()
        {
            // receive bytes
            UdpReceiveResult udpRes;

            try
            {
                udpRes = await _udpClient.ReceiveAsync().WithCancellation(CloseToken);
            }
            catch (OperationCanceledException)
            {
                // the socket has been closed
                return;
            }

            var buf = AlternativeCompositeByteBuf.CompBuffer();

            buf.WriteBytes(udpRes.Buffer.ToSByteArray());

            var localEp = (IPEndPoint)Socket.LocalEndPoint;

            RemoteEndPoint = udpRes.RemoteEndPoint;

            var dgram = new DatagramPacket(buf, localEp, RemoteEndPoint);

            Logger.Debug("Received {0}. {1} : {2}", dgram, Convenient.ToHumanReadable(udpRes.Buffer.Length), Convenient.ToString(udpRes.Buffer));

            // execute inbound pipeline
            if (Session.IsTimedOut)
            {
                return;
            }
            Session.Read(dgram);
            Session.Reset();
        }
예제 #3
0
        public void CheckTimeout()
        {
            var time     = Convenient.CurrentTimeMillis();
            var toRemove = _backend.SubMapTimeout(time);

            foreach (var key in toRemove)
            {
                var rangeLock = Lock(key);
                try
                {
                    _backend.Remove(key, false);
                    _backend.RemoveTimeout(key);
                    // remove responsibility if we don't have any data stored under locationkey
                    var locationKey = key.LocationKey;
                    var lockResp    = LockResponsibility(locationKey);
                    try
                    {
                        if (IsEmpty(locationKey))
                        {
                            _backend.RemoveResponsibility(locationKey);
                        }
                    }
                    finally
                    {
                        lockResp.Unlock();
                    }
                }
                finally
                {
                    rangeLock.Unlock();
                }
            }
        }
예제 #4
0
        /// <summary>
        /// This does not reset the timer!
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public TValue PutIfAbsent(TKey key, TValue value)
        {
            var            newValue = new ExpiringObject(value, Convenient.CurrentTimeMillis(), _timeToLiveSeconds);
            var            segment  = Segment(key);
            ExpiringObject oldValue;

            lock (segment)
            {
                if (!segment.ContainsKey(key))
                {
                    oldValue = segment.Add(key, newValue);
                }
                else
                {
                    oldValue = segment.Get(key);
                    if (oldValue.IsExpired)
                    {
                        segment.Add(key, newValue);
                    }
                    else if (_refreshTimeout)
                    {
                        oldValue = new ExpiringObject(oldValue.Value, Convenient.CurrentTimeMillis(), _timeToLiveSeconds);
                        segment.Add(key, oldValue);
                    }
                }
            }
            if (oldValue == null || oldValue.IsExpired)
            {
                return(null);
            }
            return(oldValue.Value);
        }
예제 #5
0
        /// <summary>
        /// Bootstraps to the given peer addresses. I.e., looking for near nodes.
        /// </summary>
        /// <param name="peerAddresses">The node to which bootstrap should be performed to.</param>
        /// <param name="routingBuilder">All relevant information for the routing process.</param>
        /// <param name="cc">The channel creator.</param>
        /// <returns>A task object that is set to complete if the route has been found.</returns>
        public Task <Pair <TcsRouting, TcsRouting> > Bootstrap(ICollection <PeerAddress> peerAddresses,
                                                               RoutingBuilder routingBuilder, ChannelCreator cc)
        {
            // search close peers
            Logger.Debug("Bootstrap to {0}.", Convenient.ToString(peerAddresses));
            var tcsDone = new TaskCompletionSource <Pair <TcsRouting, TcsRouting> >();

            // first, we find close peers to us
            routingBuilder.IsBootstrap = true;

            var tcsRouting0 = Routing(peerAddresses, routingBuilder, Message.Message.MessageType.Request1, cc);

            // we need to know other peers as well
            // this is important if this peer is passive and only replies on requests from other peers
            tcsRouting0.Task.ContinueWith(taskRouting0 =>
            {
                if (!taskRouting0.IsFaulted)
                {
                    // setting this to null causes to search for a random number
                    routingBuilder.LocationKey = null;
                    var tcsRouting1            = Routing(peerAddresses, routingBuilder, Message.Message.MessageType.Request1, cc);
                    tcsRouting1.Task.ContinueWith(taskRouting1 =>
                    {
                        var pair = new Pair <TcsRouting, TcsRouting>(tcsRouting0, tcsRouting1);
                        tcsDone.SetResult(pair);
                    });
                }
                else
                {
                    tcsDone.SetException(taskRouting0.TryGetException());
                }
            });

            return(tcsDone.Task);
        }
예제 #6
0
        private void AllIdleTimeoutTask(object state)
        {
            var ctx = state as ChannelHandlerContext;

            // .NET-specific: don't fire if session is already set to timed out
            if (ctx == null || !ctx.Channel.IsOpen || ctx.IsTimedOut)
            {
                return;
            }
            long currentTime = Convenient.CurrentTimeMillis();
            long lastIoTime  = Math.Max(_lastReadTime.Get(), _lastWriteTime.Get());
            long nextDelay   = (AllIdleTimeMillis - (currentTime - lastIoTime));

            if (nextDelay <= 0)
            {
                // both reader and writer are idle
                // --> set a new timeout and notify the callback
                //Logger.Debug("Both reader and writer are idle...");
                _cts = _executor.Schedule(AllIdleTimeoutTask, ctx, AllIdleTimeMillis);
                try
                {
                    ctx.FireUserEventTriggered(this);
                }
                catch (Exception ex)
                {
                    ctx.FireExceptionCaught(ex);
                }
            }
            else
            {
                // either read or write occurred before the timeout
                // --> set a new timeout with shorter delayMillis
                _cts = _executor.Schedule(AllIdleTimeoutTask, ctx, nextDelay);
            }
        }
예제 #7
0
파일: Data.cs 프로젝트: lanicon/TomP2P.NET
        /// <summary>
        /// Creates an empty Data object. The data can be filled at a later stage.
        /// </summary>
        /// <param name="header">The 8 bit header.</param>
        /// <param name="length">The length, depending on the header values.</param>
        public Data(int header, int length)
        {
            HasPublicKey     = CheckHasPublicKey(header);
            IsFlag1          = CheckIsFlag1(header);
            IsFlag2          = CheckIsFlag2(header);
            _basedOnFlag     = CheckHasBasedOn(header);
            IsSigned         = CheckIsSigned(header);
            _ttl             = CheckHasTtl(header);
            IsProtectedEntry = CheckIsProtectedEntry(header);
            _type            = Type(header);
            HasPrepareFlag   = CheckHasPrepareFlag(header);

            if (_type == DataType.Small && Length > 255)
            {
                throw new ArgumentException("DataType is small, but should be large.");
            }
            else if (_type == DataType.Large && (Length <= 255))
            {
                throw new ArgumentException("DataType is large, but should be small.");
            }

            Length          = length;
            _buffer         = new DataBuffer();
            ValidFromMillis = Convenient.CurrentTimeMillis();
            TtlSeconds      = -1;
            BasedOnSet      = new List <Number160>(0);
        }
예제 #8
0
        /// <summary>
        /// Indicates if a peer needs a maintenance check.
        /// </summary>
        /// <param name="peerStatistic">The peer with its statistics.</param>
        /// <param name="intervalSeconds"></param>
        /// <returns>True, if the peer needs a maintenance check.</returns>
        public static bool NeedMaintenance(PeerStatistic peerStatistic, int[] intervalSeconds)
        {
            int onlineSec = peerStatistic.OnlineTime / 1000;
            int index;

            if (onlineSec <= 0)
            {
                index = 0;
            }
            else
            {
                index = intervalSeconds.Length - 1;
                for (int i = 0; i < intervalSeconds.Length; i++)
                {
                    if (intervalSeconds[i] >= onlineSec)
                    {
                        index = i;
                        break;
                    }
                }
            }
            int  time = intervalSeconds[index];
            long lastTimeWhenChecked = Convenient.CurrentTimeMillis() - peerStatistic.LastSeenOnline;

            return(lastTimeWhenChecked > TimeSpan.FromSeconds(time).TotalSeconds);
        }
예제 #9
0
        private void Initialize(ChannelHandlerContext ctx)
        {
            switch (_state)
            {
            case 1:
                return;

            case 2:
                return;
            }
            _state = 1;

            // .NET-specific:
            if (_executor == null)
            {
                _executor = new ExecutorService();
            }
            var currentMillis = Convenient.CurrentTimeMillis();

            _lastReadTime.Set(currentMillis);
            _lastWriteTime.Set(currentMillis);

            if (AllIdleTimeMillis > 0)
            {
                _cts = _executor.Schedule(AllIdleTimeoutTask, ctx, AllIdleTimeMillis);
            }
        }
예제 #10
0
        public override async Task SendBytesAsync(byte[] bytes, IPEndPoint senderEp, IPEndPoint receiverEp = null)
        {
            // send bytes
            await _udpClient.SendAsync(bytes, bytes.Length, receiverEp);

            Logger.Debug("Sent UDP: Sender {0} --> Recipient {1}. {2} : {3}", senderEp, receiverEp,
                         Convenient.ToHumanReadable(bytes.Length), Convenient.ToString(bytes));
        }
예제 #11
0
        private void DiscoverTimeoutTask(object state)
        {
            var serverPeerAddress = state as PeerAddress;

            string msg = String.Format("Timeout in discover: {0}ms. However, I think my peer address is {1}.",
                                       Convenient.CurrentTimeMillis() - _start, serverPeerAddress);

            Failed(serverPeerAddress, msg);
        }
예제 #12
0
        public override async Task SendBytesAsync(byte[] bytes, IPEndPoint senderEp, IPEndPoint receiverEp = null)
        {
            // send bytes
            var recvEp = _tcpClient.Client.RemoteEndPoint;
            await _tcpClient.GetStream().WriteAsync(bytes, 0, bytes.Length);

            Logger.Debug("Sent TCP: Sender {0} --> Recipient {1}. {2} : {3}", senderEp, recvEp,
                         Convenient.ToHumanReadable(bytes.Length), Convenient.ToString(bytes));
        }
예제 #13
0
파일: Data.cs 프로젝트: lanicon/TomP2P.NET
 /// <summary>
 /// Creates a Data object that does have the complete data, but not the complete header.
 /// </summary>
 /// <param name="buffer">The buffer containing the data.</param>
 /// <param name="length">The expected length of the buffer. This does not include the header + size (2, 5 or 9).</param>
 public Data(DataBuffer buffer, int length)
 {
     Length          = length;
     _type           = Length < MaxByteSize ? DataType.Small : DataType.Large;
     _buffer         = buffer;
     ValidFromMillis = Convenient.CurrentTimeMillis();
     TtlSeconds      = -1;
     BasedOnSet      = new List <Number160>(0);
 }
예제 #14
0
            public Buffer Reply(PeerAddress sender, Buffer requestBuffer, bool complete)
            {
                Console.WriteLine("{0}.", ++_counter);
                Console.WriteLine("Request from {0}.", sender);
                Console.WriteLine("Buffer Size : {0}", Convenient.ToHumanReadable(requestBuffer.Length));

                // server returns just OK if same buffer is returned
                return(requestBuffer);
            }
예제 #15
0
        /// <summary>
        /// Creates a new future object and creates a timer that fires failed after a timeout.
        /// </summary>
        /// <param name="serverPeerAddress"></param>
        /// <param name="timer">.NET-specific: CTS instead of timer.</param>
        /// <param name="delaySec">The delay in seconds.</param>
        public void Timeout(PeerAddress serverPeerAddress, ExecutorService timer, int delaySec)
        {
            _start = Convenient.CurrentTimeMillis();
            var cts = timer.Schedule(DiscoverTimeoutTask, serverPeerAddress, TimeSpan.FromSeconds(delaySec).TotalMilliseconds);

// ReSharper disable once MethodSupportsCancellation
            // cancel timeout if we are done
            Task.ContinueWith(tDelay => cts.Cancel());
        }
예제 #16
0
 public PeerStatistic(PeerAddress peerAddress)
 {
     if (peerAddress == null)
     {
         throw new ArgumentException("PeerAddress cannot be null.");
     }
     Created     = Convenient.CurrentTimeMillis();
     _peerId     = peerAddress.PeerId;
     PeerAddress = peerAddress;
 }
예제 #17
0
        public override string ToString()
        {
            var sb = new StringBuilder("paddr[");

            return(sb.Append(PeerId)
                   .Append(PeerSocketAddress)
                   .Append("]/relay(").Append(IsRelayed)
                   .Append(",").Append(PeerSocketAddresses.Count)
                   .Append(")=").Append(Convenient.ToString(PeerSocketAddresses))
                   .ToString());
        }
예제 #18
0
        public async void TestPingTimeUdp()
        {
            Peer sender = null;
            Peer recv1  = null;

            try
            {
                sender = new PeerBuilder(new Number160("0x9876"))
                         .SetP2PId(55)
                         .SetPorts(2424)
                         .Start();
                recv1 = new PeerBuilder(new Number160("0x9876"))
                        .SetP2PId(55)
                        .SetPorts(8088)
                        .Start();

                long start = Convenient.CurrentTimeMillis();
                var  tasks = new List <Task <Message> >(1000);
                for (int i = 0; i < 20; i++)
                {
                    var cc = await recv1.ConnectionBean.Reservation.CreateAsync(50, 0);

                    for (int j = 0; j < 50; j++)
                    {
                        var taskResponse = sender.PingRpc.PingUdpAsync(recv1.PeerAddress, cc,
                                                                       new DefaultConnectionConfiguration());
                        tasks.Add(taskResponse);
                    }
                    foreach (var task in tasks)
                    {
                        await task;
                        Assert.IsTrue(!task.IsFaulted);
                    }
                    tasks.Clear();
                    await cc.ShutdownAsync();
                }
                Console.WriteLine("UDP time: {0}ms.", Convenient.CurrentTimeMillis() - start);
            }
            finally
            {
                if (sender != null)
                {
                    sender.ShutdownAsync().Wait();
                }

                if (recv1 != null)
                {
                    recv1.ShutdownAsync().Wait();
                }
            }
        }
예제 #19
0
        private void EncodeData(AlternativeCompositeByteBuf buffer, Data data, bool isConvertMeta, bool isReply)
        {
            data = isConvertMeta ? data.DuplicateMeta() : data.Duplicate();

            if (isReply)
            {
                var ttl = (int)((data.ExpirationMillis - Convenient.CurrentTimeMillis()) / 1000);
                data.SetTtlSeconds(ttl < 0 ? 0 : ttl);
            }

            data.EncodeHeader(buffer, _signatureFactory);
            data.EncodeBuffer(buffer);
            data.EncodeDone(buffer, _signatureFactory, Message.PrivateKey);
        }
예제 #20
0
        public IList <ByteBuf> Decompose(int offset, int length)
        {
            CheckIndex(offset, length);
            if (length == 0)
            {
                return(Convenient.EmptyList <ByteBuf>());
            }

            int             componentId = FindIndex(offset);
            IList <ByteBuf> slice       = new List <ByteBuf>(_components.Count);

            // the first component
            var firstC = _components[componentId];
            var first  = firstC.Buf.Duplicate();

            first.SetReaderIndex(offset - firstC.Offset);

            ByteBuf buf          = first;
            int     bytesToSlice = length;

            do
            {
                int readableBytes = buf.ReadableBytes;
                if (bytesToSlice <= readableBytes)
                {
                    // last component
                    buf.SetWriterIndex(buf.ReaderIndex + bytesToSlice);
                    slice.Add(buf);
                    break;
                }
                else
                {
                    // not the last component
                    slice.Add(buf);
                    bytesToSlice -= readableBytes;
                    componentId++;

                    // fetch the next component
                    buf = _components[componentId].Buf.Duplicate();
                }
            } while (bytesToSlice > 0);

            // slice all component because only readable bytes are interesting
            for (int i = 0; i < slice.Count; i++)
            {
                slice[i] = slice[i].Slice();
            }

            return(slice);
        }
예제 #21
0
        protected override async Task ProcessRequestAsync(object state)
        {
            var udpRes = (UdpReceiveResult)state;

            // prepare new session
            var buf     = AlternativeCompositeByteBuf.CompBuffer();
            var session = Pipeline.CreateNewServerSession(this);

            session.TriggerActive();

            // process content
            buf.WriteBytes(udpRes.Buffer.ToSByteArray());

            var localEp  = (IPEndPoint)_udpClient.Client.LocalEndPoint;
            var remoteEp = udpRes.RemoteEndPoint;

            var dgram = new DatagramPacket(buf, localEp, remoteEp);

            Logger.Debug("Received {0}. {1} : {2}", dgram, Convenient.ToHumanReadable(udpRes.Buffer.Length),
                         Convenient.ToString(udpRes.Buffer));

            // execute inbound pipeline
            var readRes = session.Read(dgram); // resets timeout

            if (session.IsTimedOut)
            {
                session.TriggerInactive();
                return;
            }

            // execute outbound pipeline
            var writeRes = session.Write(readRes); // resets timeout

            if (session.IsTimedOut)
            {
                session.TriggerInactive();
                return;
            }

            // send back
            var bytes = ConnectionHelper.ExtractBytes(writeRes);
            await _udpClient.SendAsync(bytes, bytes.Length, remoteEp);

            NotifyWriteCompleted(); // resets timeout
            Logger.Debug("Sent {0} : {1}", Convenient.ToHumanReadable(udpRes.Buffer.Length),
                         Convenient.ToString(udpRes.Buffer));

            session.TriggerInactive();
        }
예제 #22
0
파일: Data.cs 프로젝트: lanicon/TomP2P.NET
 /// <summary>
 /// Creates a Data object from an already existing buffer.
 /// </summary>
 /// <param name="buffer"></param>
 /// <param name="offset"></param>
 /// <param name="length"></param>
 public Data(sbyte[] buffer, int offset, int length)
 {
     if (buffer.Length == 0)
     {
         _buffer = new DataBuffer(0);
     }
     else
     {
         _buffer = new DataBuffer(buffer, offset, length);
     }
     Length          = length;
     _type           = Length < MaxByteSize ? DataType.Small : DataType.Large;
     ValidFromMillis = Convenient.CurrentTimeMillis();
     TtlSeconds      = -1;
     BasedOnSet      = new List <Number160>(0);
 }
예제 #23
0
        public TValue Put(TKey key, TValue value)
        {
            var            newValue = new ExpiringObject(value, Convenient.CurrentTimeMillis(), _timeToLiveSeconds);
            var            segment  = Segment(key);
            ExpiringObject oldValue;

            lock (segment)
            {
                oldValue = segment.Add(key, newValue);
            }
            if (oldValue == null || oldValue.IsExpired)
            {
                return(null);
            }
            return(oldValue.Value);
        }
예제 #24
0
        public override async Task DoReceiveMessageAsync()
        {
            // TODO find zero-copy way, use same buffer
            // receive bytes
            var bytesRecv = new byte[256];
            var buf       = AlternativeCompositeByteBuf.CompBuffer();

            var stream     = _tcpClient.GetStream();
            var pieceCount = 0;

            do
            {
                Array.Clear(bytesRecv, 0, bytesRecv.Length);
                buf.Clear();
                int nrBytes;
                try
                {
                    nrBytes = await stream.ReadAsync(bytesRecv, 0, bytesRecv.Length).WithCancellation(CloseToken);
                }
                catch (OperationCanceledException)
                {
                    // the socket has been closed
                    return;
                }
                buf.WriteBytes(bytesRecv.ToSByteArray(), 0, nrBytes);

                var localEp = (IPEndPoint)Socket.LocalEndPoint;
                RemoteEndPoint = (IPEndPoint)Socket.RemoteEndPoint;

                var piece = new StreamPiece(buf, localEp, RemoteEndPoint);
                Logger.Debug("[{0}] Received {1}. {2} : {3}", ++pieceCount, piece, Convenient.ToHumanReadable(nrBytes), Convenient.ToString(bytesRecv));

                // execute inbound pipeline, per piece (reset session!)
                if (Session.IsTimedOut)
                {
                    return;
                }
                Session.Read(piece);
                Session.Reset();
            } while (!IsClosed && stream.DataAvailable && !Session.IsTimedOut);
        }
예제 #25
0
        public ICollection <Number160> FindContentForResponsiblePeerId(Number160 peerId)
        {
            var lockResp = LockResponsibility(peerId);

            try
            {
                var contentIds = _backend.FindContentForResponsiblePeerId(peerId);
                if (contentIds == null)
                {
                    return(Convenient.EmptyList <Number160>());
                }
                else
                {
                    return(new List <Number160>(contentIds));
                }
            }
            finally
            {
                lockResp.Unlock();
            }
        }
예제 #26
0
        public override MemoryStream NioBuffer(int index, int length)
        {
            if (_components.Count == 1)
            {
                var buf = _components[0].Buf;
                if (buf.NioBufferCount() == 1)
                {
                    return(_components[0].Buf.NioBuffer(index, length));
                }
            }
            var merged  = Convenient.Allocate(length); // little-endian
            var buffers = NioBuffers(index, length);

            for (int i = 0; i < buffers.Length; i++)
            {
                merged.Put(buffers[i]);
            }

            merged.Flip();
            return(merged);
        }
예제 #27
0
        public bool Replace(TKey key, TValue oldValue, TValue newValue)
        {
            var oldValue2 = new ExpiringObject(oldValue, 0, _timeToLiveSeconds);
            var newValue2 = new ExpiringObject(newValue, Convenient.CurrentTimeMillis(), _timeToLiveSeconds);

            var            segment = Segment(key);
            ExpiringObject oldValue3;
            bool           replaced = false;

            lock (segment)
            {
                oldValue3 = segment.Get(key);
                if (oldValue3 != null && !oldValue3.IsExpired && oldValue2.Value.Equals(oldValue3.Value))
                {
                    segment.Add(key, newValue2);
                    replaced = true;
                }
            }
            if (oldValue3 != null)
            {
                Expire(segment, key, oldValue3);
            }
            return(replaced);
        }
예제 #28
0
        private void Initialize(ChannelHandlerContext ctx)
        {
            switch (_state)
            {
            case 1:
                return;

            case 2:
                return;
            }
            _state = 1;

            // .NET-specific:
            if (_executor == null)
            {
                _executor = new ExecutorService();
            }
            var currentMillis = Convenient.CurrentTimeMillis();

            _lastReadTime.Set(currentMillis);
            _lastWriteTime.Set(currentMillis);

            _timer = _executor.ScheduleAtFixedRate(Heartbeating, ctx, TimeToHeartBeatMillis, TimeToHeartBeatMillis);
        }
예제 #29
0
        public UnpooledDirectByteBuf(IByteBufAllocator alloc, int initialCapacity, int maxCapacity)
            : base(maxCapacity)
        {
            if (alloc == null)
            {
                throw new NullReferenceException("alloc");
            }
            if (initialCapacity < 0)
            {
                throw new ArgumentException("initialCapacity: " + initialCapacity);
            }
            if (maxCapacity < 0)
            {
                throw new ArgumentException("maxCapacity: " + maxCapacity);
            }
            if (initialCapacity > maxCapacity)
            {
                throw new ArgumentException(String.Format(
                                                "initialCapacity({0}) > maxCapacity({1})", initialCapacity, maxCapacity));
            }

            _alloc = alloc;
            SetByteBuffer(Convenient.AllocateDirect(initialCapacity));
        }
예제 #30
0
 public override void Write(ChannelHandlerContext ctx, object msg)
 {
     ctx.Channel.WriteCompleted += channel => _lastWriteTime.Set(Convenient.CurrentTimeMillis());
     //ctx.FireWrite(msg); // TODO needed?
 }