Beispiel #1
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="ev">TBD</param>
 public void Notify(IHandleEvent ev)
 {
     if (!_gremlinAdapter.ShouldDropInbound(WrappedHandle.RemoteAddress, ev, "handler.notify"))
     {
         _upstreamListener.Notify(ev);
     }
 }
            private void SetListener(IHandleEventListener handleEventListener)
            {
                _listener = handleEventListener;
                foreach (var msg in _pendingMessages)
                {
                    _listener.Notify(new InboundPayload(msg));
                }
                _pendingMessages.Clear();
                _pendingMessages = null; // GC the collection right away

                SetHandler(_sink.In, () => Recv(Grab(_sink.In)), Finish, OnUpstreamFailure);
            }
 private UntypedReceive Receiving(IHandleEventListener el)
 {
     return(message =>
     {
         if (message is Tcp.Received)
         {
             var received = message as Tcp.Received;
             el.Notify(new InboundPayload(ByteString.CopyFrom(received.Data.ToArray())));
         }
         if (message is ByteString)
         {
             var bs = message as ByteString;
             _connection.Tell(Tcp.Write.Create(IO.ByteString.Create(bs.ToByteArray())));
         }
         else
         {
             Unhandled(message);
         }
     });
 }
 private UntypedReceive Receiving(IHandleEventListener el)
 {
     return message =>
     {
         if (message is Tcp.Received)
         {
             var received = message as Tcp.Received;
             el.Notify(new InboundPayload(ByteString.CopyFrom(received.Data.ToArray())));
         }
         if (message is ByteString)
         {
             var bs = message as ByteString;
             _connection.Tell(Tcp.Write.Create(IO.ByteString.Create(bs.ToByteArray())));
         }
         else
         {
             Unhandled(message);
         }
     };
 }
Beispiel #5
0
 private UntypedReceive WaitingForBody(IHandleEventListener el, IO.ByteString buffer, int length)
 {
     if (buffer.Count >= length)
     {
         var parts = buffer.SplitAt(length);
         el.Notify(new InboundPayload(ByteString.CopyFrom(parts.Item1.ToArray())));
         return(WaitingForPrefix(el, parts.Item2));
     }
     return(message =>
     {
         if (message is Tcp.Received)
         {
             var received = message as Tcp.Received;
             Become(WaitingForBody(el, buffer.Concat(received.Data), length));
         }
         else
         {
             HandleWrite(message);
         }
     });
 }
Beispiel #6
0
        private void InitializeFSM()
        {
            When(ThrottlerState.WaitExposedHandle, @event =>
            {
                if (@event.FsmEvent is ThrottlerManager.Handle && @event.StateData is Uninitialized)
                {
                    // register to downstream layer and wait for origin
                    OriginalHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(Self));
                    return
                    (GoTo(ThrottlerState.WaitOrigin)
                     .Using(
                         new ExposedHandle(
                             @event.FsmEvent.AsInstanceOf <ThrottlerManager.Handle>().ThrottlerHandle)));
                }
                return(null);
            });

            When(ThrottlerState.WaitOrigin, @event =>
            {
                if (@event.FsmEvent is InboundPayload && @event.StateData is ExposedHandle)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>().Payload;
                    ThrottledMessages.Enqueue(b);
                    var origin = PeekOrigin(b);
                    if (origin != null)
                    {
                        Manager.Tell(new ThrottlerManager.Checkin(origin, @event.StateData.AsInstanceOf <ExposedHandle>().Handle));
                        return(GoTo(ThrottlerState.WaitMode));
                    }
                    return(Stay());
                }
                return(null);
            });

            When(ThrottlerState.WaitMode, @event =>
            {
                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>().Payload;
                    ThrottledMessages.Enqueue(b);
                    return(Stay());
                }

                if (@event.FsmEvent is ThrottleMode && @event.StateData is ExposedHandle)
                {
                    var mode            = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    var exposedHandle   = @event.StateData.AsInstanceOf <ExposedHandle>().Handle;
                    InboundThrottleMode = mode;
                    try
                    {
                        if (mode is Blackhole)
                        {
                            ThrottledMessages = new Queue <ByteString>();
                            exposedHandle.Disassociate();
                            return(Stop());
                        }
                        else
                        {
                            AssociationHandler.Notify(new InboundAssociation(exposedHandle));
                            var self = Self;
                            exposedHandle.ReadHandlerSource.Task.ContinueWith(
                                r => new ThrottlerManager.Listener(r.Result),
                                TaskContinuationOptions.ExecuteSynchronously)
                            .PipeTo(self);
                            return(GoTo(ThrottlerState.WaitUpstreamListener));
                        }
                    }
                    finally
                    {
                        Sender.Tell(SetThrottleAck.Instance);
                    }
                }

                return(null);
            });

            When(ThrottlerState.WaitUpstreamListener, @event =>
            {
                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>();
                    ThrottledMessages.Enqueue(b.Payload);
                    return(Stay());
                }

                if (@event.FsmEvent is ThrottlerManager.Listener)
                {
                    UpstreamListener = @event.FsmEvent.AsInstanceOf <ThrottlerManager.Listener>().HandleEventListener;
                    Self.Tell(new Dequeue());
                    return(GoTo(ThrottlerState.Throttling));
                }

                return(null);
            });

            When(ThrottlerState.WaitModeAndUpstreamListener, @event =>
            {
                if (@event.FsmEvent is ThrottlerManager.ListenerAndMode)
                {
                    var listenerAndMode = @event.FsmEvent.AsInstanceOf <ThrottlerManager.ListenerAndMode>();
                    UpstreamListener    = listenerAndMode.HandleEventListener;
                    InboundThrottleMode = listenerAndMode.Mode;
                    Self.Tell(new Dequeue());
                    return(GoTo(ThrottlerState.Throttling));
                }

                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>();
                    ThrottledMessages.Enqueue(b.Payload);
                    return(Stay());
                }

                return(null);
            });

            When(ThrottlerState.Throttling, @event =>
            {
                if (@event.FsmEvent is ThrottleMode)
                {
                    var mode            = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    InboundThrottleMode = mode;
                    if (mode is Blackhole)
                    {
                        ThrottledMessages = new Queue <ByteString>();
                    }
                    CancelTimer(DequeueTimerName);
                    if (ThrottledMessages.Any())
                    {
                        ScheduleDequeue(InboundThrottleMode.TimeToAvailable(MonotonicClock.GetNanos(), ThrottledMessages.Peek().Length));
                    }
                    Sender.Tell(SetThrottleAck.Instance);
                    return(Stay());
                }

                if (@event.FsmEvent is InboundPayload)
                {
                    ForwardOrDelay(@event.FsmEvent.AsInstanceOf <InboundPayload>().Payload);
                    return(Stay());
                }

                if (@event.FsmEvent is Dequeue)
                {
                    if (ThrottledMessages.Any())
                    {
                        var payload = ThrottledMessages.Dequeue();
                        UpstreamListener.Notify(new InboundPayload(payload));
                        InboundThrottleMode = InboundThrottleMode.TryConsumeTokens(MonotonicClock.GetNanos(),
                                                                                   payload.Length).Item1;
                        if (ThrottledMessages.Any())
                        {
                            ScheduleDequeue(InboundThrottleMode.TimeToAvailable(MonotonicClock.GetNanos(), ThrottledMessages.Peek().Length));
                        }
                    }
                    return(Stay());
                }

                return(null);
            });

            WhenUnhandled(@event =>
            {
                // we should always set the throttling mode
                if (@event.FsmEvent is ThrottleMode)
                {
                    InboundThrottleMode = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    Sender.Tell(SetThrottleAck.Instance);
                    return(Stay());
                }

                if (@event.FsmEvent is Disassociated)
                {
                    return(Stop()); // not notifying the upstream handler is intentional: we are relying on heartbeating
                }

                if (@event.FsmEvent is FailWith)
                {
                    var reason = @event.FsmEvent.AsInstanceOf <FailWith>().FailReason;
                    if (UpstreamListener != null)
                    {
                        UpstreamListener.Notify(new Disassociated(reason));
                    }
                    return(Stop());
                }

                return(null);
            });

            if (Inbound)
            {
                StartWith(ThrottlerState.WaitExposedHandle, Uninitialized.Instance);
            }
            else
            {
                OriginalHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(Self));
                StartWith(ThrottlerState.WaitModeAndUpstreamListener, Uninitialized.Instance);
            }
        }
 private UntypedReceive WaitingForBody(IHandleEventListener el, IO.ByteString buffer, int length)
 {
     if (buffer.Count >= length)
     {
         var parts = buffer.SplitAt(length);
         el.Notify(new InboundPayload(ByteString.CopyFrom(parts.Item1.ToArray())));
         return WaitingForPrefix(el, parts.Item2);
     }
     return message =>
     {
         if (message is Tcp.Received)
         {
             var received = message as Tcp.Received;
             Become(WaitingForBody(el, buffer.Concat(received.Data), length));
         }
         else HandleWrite(message);
     };
 }
Beispiel #8
0
 protected void NotifyListener(IHandleEvent msg)
 {
     _listener?.Notify(msg);
 }
        private async Task <bool> ReadLoop()
        {
            try
            {
                if (!await _initialized.Task)
                {
                    return(false);
                }

                byte[] readBuffer   = _readBuffer;
                int    bufferLength = readBuffer.Length;

                int readBytes = 0;
                int readIndex = 0;

                while (true)
                {
                    int available = readBytes - readIndex;
                    if (available < sizeof(int))
                    {
                        // To simplify the message length read logic, we enforce the length bytes to be whole in the buffer

                        // Copy the partial length at the start of the buffer
                        if (available != 0)
                        {
                            Buffer.BlockCopy(readBuffer, readIndex, readBuffer, 0, available);
                        }

                        readIndex = 0;
                        readBytes = await _stream.ReadAsync(readBuffer, available, bufferLength - available).ConfigureAwait(false);

                        if (readBytes == 0)
                        {
                            return(true);
                        }

                        // Adjust readBytes to include the partial length that we copied earlier
                        readBytes += available;
                    }

                    int payloadLength = LittleEndian.ReadInt32(readBuffer, readIndex);
                    readIndex += sizeof(int);

                    byte[] payloadBuffer = null;

                    if (payloadLength < 0 || payloadLength > _settings.FrameSizeHardLimit)
                    {
                        //TODO Log Error
                        return(false);
                    }

                    if (payloadLength > _settings.MaximumFrameSize)
                    {
                        // This could happen if the MaximumFrameSize is configured bigger on the remote association.
                        // Normally they are dropped before getting sent so we don't receive them.

                        #region Skip the bytes

                        //TODO Log Error

                        int payloadOffset = 0;

                        while (payloadOffset < payloadLength)
                        {
                            if (readIndex == readBytes)
                            {
                                readIndex = 0;
                                readBytes = await _stream.ReadAsync(readBuffer, 0, bufferLength).ConfigureAwait(false);

                                if (readBytes == 0)
                                {
                                    return(true);
                                }
                            }

                            available      = Math.Min(readBytes - readIndex, payloadLength - payloadOffset);
                            readIndex     += available;
                            payloadOffset += available;
                        }

                        #endregion
                    }
                    else if (payloadLength > _settings.ChunkedReadThreshold && payloadLength > bufferLength - readIndex)
                    {
                        // The payload is chunked as a protection against denial of service. Otherwise a malicious remote endpoint
                        // could make the node allocate big buffers without sending the data first.

                        #region Read Chunked

                        //TODO Could allow direct read if Socket.Available include the full payload length
                        //TODO The chunked buffers could be pooled (See RecyclableMemoryStream)

                        var chunks        = new List <byte[]>();
                        int payloadOffset = 0;

                        while (payloadOffset < payloadLength)
                        {
                            if (readIndex == readBytes)
                            {
                                readIndex = 0;
                                readBytes = await _stream.ReadAsync(readBuffer, 0, bufferLength).ConfigureAwait(false);

                                if (readBytes == 0)
                                {
                                    return(true);
                                }
                            }

                            available = Math.Min(readBytes - readIndex, payloadLength - payloadOffset);
                            byte[] chunk = new byte[available];
                            Buffer.BlockCopy(readBuffer, readIndex, chunk, 0, available);
                            chunks.Add(chunk);

                            readIndex     += available;
                            payloadOffset += available;
                        }

                        payloadOffset = 0;
                        payloadBuffer = new byte[payloadLength];

                        foreach (byte[] chunk in chunks)
                        {
                            int chunkLength = chunk.Length;
                            Buffer.BlockCopy(chunk, 0, payloadBuffer, payloadOffset, chunkLength);
                            payloadOffset += chunkLength;
                        }

                        #endregion
                    }
                    else
                    {
                        payloadBuffer = new byte[payloadLength];
                        int payloadOffset = 0;

                        while (payloadOffset < payloadLength)
                        {
                            if (readIndex == readBytes)
                            {
                                readIndex = 0;
                                readBytes = await _stream.ReadAsync(readBuffer, 0, bufferLength).ConfigureAwait(false);

                                if (readBytes == 0)
                                {
                                    return(true);
                                }
                            }

                            available = Math.Min(readBytes - readIndex, payloadLength - payloadOffset);

                            Buffer.BlockCopy(readBuffer, readIndex, payloadBuffer, payloadOffset, available);
                            readIndex     += available;
                            payloadOffset += available;
                        }
                    }

                    if (payloadBuffer != null)
                    {
                        //Log(LogLevel.DebugLevel, "Payload received");
                        var payload = new InboundPayload(ByteString.Unsafe.FromBytes(payloadBuffer));
                        _eventListener.Notify(payload);
                    }
                }
            }
            catch (Exception)
            {
                //TODO Log
                return(false);
            }
        }
 private void Recv(Google.Protobuf.ByteString msg)
 {
     _listener.Notify(new InboundPayload(msg));
     PullOrComplete();
 }
 private void OnUpstreamFailure(Exception exception)
 {
     _listener?.Notify(new UnderlyingTransportError(exception, "Failure in Akka.Streams processing pipeline."));
     FailStage(exception);
 }