/// <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); } }; }
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); } }); }
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); }; }
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); }