OutboundConnectionHandler(StreamsTransport transport, Address remoteAddress, EndPoint remoteSocketAddr)
        {
            var settings           = transport.Settings;
            var transmissionHandle =
                Source.ActorRef <Google.Protobuf.ByteString>(settings.BufferedMessages, OverflowStrategy.Backpressure);
            var fromLocalActors = FromProtobuf().Via(Encode(4, settings.MaxFrameSize, settings.ByteOrder));


            var fromRemoteActors = Decode(4, settings.MaxFrameSize, settings.ByteOrder).Via(ToProtobuf());

            var transmissionRef = transmissionHandle.PreMaterialize(transport.StreamMaterializer);

            var finalOutput = new RemoteOutboundAssociationSink(transport, remoteAddress, remoteSocketAddr, transmissionRef.Item1);

            var dsl = GraphDsl.Create(finalOutput, (builder, remoteOutput) =>
            {
                // local stages
                var localInput       = builder.Add(transmissionRef.Item2);
                var compilerCeremony = builder.Add(Flow.Create <Google.Protobuf.ByteString>());
                var local            = builder.Add(fromLocalActors);
                var merge            = builder.Add(new Merge <Google.Protobuf.ByteString, Google.Protobuf.ByteString>(2, false));
                builder.From(localInput.Outlet).To(merge.In(0));
                builder.From(compilerCeremony.Outlet).To(merge.In(1));
                builder.From(merge.Out).To(local.Inlet);

                // remote stages
                var remote = builder.Add(fromRemoteActors);
                builder.From(remote.Outlet).To(remoteOutput.Inlet);

                return(new BidiShape <ByteString, Google.Protobuf.ByteString, Google.Protobuf.ByteString, ByteString>(remote.Inlet, remote.Outlet, compilerCeremony.Inlet, local.Outlet));
            });

            return(BidiFlow.FromGraph(dsl));
        }
Exemple #2
0
        public void IdleTimeoutBidi_must_signal_error_to_all_outputs()
        {
            this.AssertAllStagesStopped(() =>
            {
                var upWrite = this.CreatePublisherProbe <string>();
                var upRead  = this.CreateSubscriberProbe <int>();

                var downWrite = this.CreatePublisherProbe <int>();
                var downRead  = this.CreateSubscriberProbe <string>();

                RunnableGraph.FromGraph(GraphDsl.Create(b =>
                {
                    var timeoutStage = b.Add(BidiFlow.BidirectionalIdleTimeout <string, int>(TimeSpan.FromSeconds(2)));

                    b.From(Source.FromPublisher(upWrite)).To(timeoutStage.Inlet1);
                    b.From(timeoutStage.Outlet1).To(Sink.FromSubscriber(downRead));
                    b.From(timeoutStage.Outlet2).To(Sink.FromSubscriber(upRead));
                    b.From(Source.FromPublisher(downWrite)).To(timeoutStage.Inlet2);

                    return(ClosedShape.Instance);
                })).Run(Materializer);

                var te = new TestException("test");

                upWrite.SendError(te);

                upRead.ExpectSubscriptionAndError().ShouldBeEquivalentTo(te);
                downRead.ExpectSubscriptionAndError().ShouldBeEquivalentTo(te);
                downWrite.ExpectCancellation();
            }, Materializer);
        }
Exemple #3
0
        public void IdleTimeoutBidi_must_not_signal_error_if_traffic_is_one_way()
        {
            this.AssertAllStagesStopped(() =>
            {
                var upstreamWriter   = this.CreatePublisherProbe <int>();
                var downstreamWriter = this.CreatePublisherProbe <string>();

                var upstream = Flow.FromSinkAndSource(Sink.Ignore <string>(),
                                                      Source.FromPublisher(upstreamWriter), Keep.Left);
                var downstream = Flow.FromSinkAndSource(Sink.Ignore <int>(),
                                                        Source.FromPublisher(downstreamWriter), Keep.Left);

                var assembly = upstream.JoinMaterialized(
                    BidiFlow.BidirectionalIdleTimeout <int, string>(TimeSpan.FromSeconds(2)),
                    Keep.Left).JoinMaterialized(downstream, Keep.Both);
                var r            = assembly.Run(Materializer);
                var upFinished   = r.Item1;
                var downFinished = r.Item2;

                upstreamWriter.SendNext(1);
                Thread.Sleep(1000);
                upstreamWriter.SendNext(1);
                Thread.Sleep(1000);
                upstreamWriter.SendNext(1);
                Thread.Sleep(1000);

                upstreamWriter.SendComplete();
                downstreamWriter.SendComplete();

                upFinished.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                downFinished.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            }, Materializer);
        }
Exemple #4
0
 private static BidiFlow <long, int, string, ByteString, NotUsed> Inverse()
 {
     return
         (BidiFlow.FromFlows(
              Flow.Create <long>().Select(x => ((int)x) + 2).WithAttributes(Attributes.CreateName("top")),
              Flow.Create <string>()
              .Select(ByteString.FromString)
              .WithAttributes(Attributes.CreateName("bottom"))));
 }
Exemple #5
0
 private static BidiFlow <int, long, ByteString, string, NotUsed> Bidi()
 {
     return
         (BidiFlow.FromFlows(
              Flow.Create <int>().Select(x => ((long)x) + 2).WithAttributes(Attributes.CreateName("top")),
              Flow.Create <ByteString>()
              .Select(x => x.ToString(Encoding.UTF8))
              .WithAttributes(Attributes.CreateName("bottom"))));
 }
Exemple #6
0
        private static BidiFlow <int, long, ByteString, string, Task <int> > BidiMaterialized()
        {
            return(BidiFlow.FromGraph(GraphDsl.Create(Sink.First <int>(), (b, s) =>
            {
                b.From(Source.Single(42).MapMaterializedValue(_ => Task.FromResult(0))).To(s);

                var top = b.Add(Flow.Create <int>().Select(x => ((long)x) + 2));
                var bottom = b.Add(Flow.Create <ByteString>().Select(x => x.ToString(Encoding.UTF8)));
                return new BidiShape <int, long, ByteString, string>(top.Inlet, top.Outlet, bottom.Inlet, bottom.Outlet);
            })));
        }
Exemple #7
0
        public void IdleTimeoutBidi_must_be_able_to_signal_timeout_once_no_traffic_on_either_sides()
        {
            this.AssertAllStagesStopped(() =>
            {
                var upWrite = this.CreatePublisherProbe <string>();
                var upRead  = this.CreateSubscriberProbe <int>();

                var downWrite = this.CreatePublisherProbe <int>();
                var downRead  = this.CreateSubscriberProbe <string>();

                RunnableGraph.FromGraph(GraphDsl.Create(b =>
                {
                    var timeoutStage = b.Add(BidiFlow.BidirectionalIdleTimeout <string, int>(TimeSpan.FromSeconds(2)));

                    b.From(Source.FromPublisher(upWrite)).To(timeoutStage.Inlet1);
                    b.From(timeoutStage.Outlet1).To(Sink.FromSubscriber(downRead));
                    b.From(timeoutStage.Outlet2).To(Sink.FromSubscriber(upRead));
                    b.From(Source.FromPublisher(downWrite)).To(timeoutStage.Inlet2);

                    return(ClosedShape.Instance);
                })).Run(Materializer);

                // Request enough for the whole test
                upRead.Request(100);
                downRead.Request(100);

                upWrite.SendNext("DATA1");
                downRead.ExpectNext("DATA1");
                Thread.Sleep(1500);

                downWrite.SendNext(1);
                upRead.ExpectNext(1);
                Thread.Sleep(1500);

                upWrite.SendNext("DATA2");
                downRead.ExpectNext("DATA2");
                Thread.Sleep(1000);

                downWrite.SendNext(2);
                upRead.ExpectNext(2);

                upRead.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
                var error1 = upRead.ExpectError();
                var error2 = downRead.ExpectError();

                error1.Should().BeOfType <TimeoutException>();
                error1.Message.Should().Be($"No elements passed in the last {TimeSpan.FromSeconds(2)}.");
                error2.ShouldBeEquivalentTo(error1);

                upWrite.ExpectCancellation();
                downWrite.ExpectCancellation();
            }, Materializer);
        }
Exemple #8
0
        public void IdleTimeoutBidi_must_not_signal_error_in_simple_loopback_case_and_pass_through_elements_unmodified()
        {
            this.AssertAllStagesStopped(() =>
            {
                var timeoutIdentity = BidiFlow.BidirectionalIdleTimeout <int, int>(TimeSpan.FromSeconds(2)).Join(Flow.Create <int>());

                var t = Source.From(Enumerable.Range(1, 100))
                        .Via(timeoutIdentity).Grouped(200)
                        .RunWith(Sink.First <IEnumerable <int> >(), Materializer);

                t.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                t.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 100));
            }, Materializer);
        }
Exemple #9
0
        public void ActorGraphInterpreter_should_be_able_to_interpret_a_simple_bidi_stage()
        {
            this.AssertAllStagesStopped(() =>
            {
                var identityBidi = new IdentityBidiGraphStage();
                var identity     = BidiFlow.FromGraph(identityBidi).Join(Flow.Identity <int>().Select(x => x));

                var task = Source.From(Enumerable.Range(1, 10))
                           .Via(identity)
                           .Grouped(100)
                           .RunWith(Sink.First <IEnumerable <int> >(), Materializer);

                task.AwaitResult().Should().Equal(Enumerable.Range(1, 10));
            }, Materializer);
        }
Exemple #10
0
        public static BidiFlow <ByteString, ByteString, ByteString, ByteString, NotUsed> Create(TimeSpan idleTimeout, EndPoint remoteAddress = null)
        {
            var connectionString = remoteAddress == null ? "" : $" on connection to [{remoteAddress}]";

            var idleException = new TcpIdleTimeoutException(
                $"TCP idle-timeout encountered{connectionString}, no bytes passed in the last {idleTimeout}",
                idleTimeout);

            var toNetTimeout = BidiFlow.FromFlows(
                Flow.Create <ByteString>().SelectError(e => e is TimeoutException ? idleException : e),
                Flow.Create <ByteString>());

            var fromNetTimeout = toNetTimeout.Reversed(); // now the bottom flow transforms the exception, the top one doesn't (since that one is "fromNet")

            return(fromNetTimeout.Atop(BidiFlow.BidirectionalIdleTimeout <ByteString, ByteString>(idleTimeout))
                   .Atop(toNetTimeout));
        }
        public void ActorGraphInterpreter_should_be_able_to_interpret_and_reuse_a_simple_bidi_stage()
        {
            this.AssertAllStagesStopped(() =>
            {
                var identityBidi     = new IdentityBidiGraphStage();
                var identityBidiFlow = BidiFlow.FromGraph(identityBidi);
                var identity         = identityBidiFlow.Atop(identityBidiFlow).Atop(identityBidiFlow).Join(Flow.Identity <int>().Select(x => x));

                var task = Source.From(Enumerable.Range(1, 10))
                           .Via(identity)
                           .Grouped(100)
                           .RunWith(Sink.First <IEnumerable <int> >(), _materializer);

                task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                task.Result.Should().Equal(Enumerable.Range(1, 10));
            }, _materializer);
        }
Exemple #12
0
        public void Length_field_based_framing_must_support_simple_framing_adapter()
        {
            var rechunkBidi = BidiFlow.FromFlowsMat(Rechunk, Rechunk, Keep.Left);
            var codecFlow   = Framing.SimpleFramingProtocol(1024)
                              .Atop(rechunkBidi)
                              .Atop(Framing.SimpleFramingProtocol(1024).Reversed())
                              .Join(Flow.Create <ByteString>()); // Loopback

            var random       = new Random();
            var testMessages = Enumerable.Range(1, 100).Select(_ => ReferenceChunk.Slice(0, random.Next(1024))).ToList();

            var task = Source.From(testMessages)
                       .Via(codecFlow)
                       .Limit(1000)
                       .RunWith(Sink.Seq <ByteString>(), Materializer);

            task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            task.Result.ShouldAllBeEquivalentTo(testMessages);
        }
Exemple #13
0
            private StreamTcp.IncomingConnection ConnectionFor(Tcp.Connected connected, IActorRef connection)
            {
                _connectionFlowsAwaitingInitialization.IncrementAndGet();

                var tcpFlow =
                    Flow.FromGraph(new IncomingConnectionStage(connection, connected.RemoteAddress, _stage._halfClose))
                    .Via(new Detacher <ByteString>()) // must read ahead for proper completions
                    .MapMaterializedValue(unit =>
                {
                    _connectionFlowsAwaitingInitialization.DecrementAndGet();
                    return(unit);
                });

                // FIXME: Previous code was wrong, must add new tests
                var handler = tcpFlow;

                if (_stage._idleTimeout.HasValue)
                {
                    handler = tcpFlow.Join(BidiFlow.BidirectionalIdleTimeout <ByteString, ByteString>(_stage._idleTimeout.Value));
                }

                return(new StreamTcp.IncomingConnection(connected.LocalAddress, connected.RemoteAddress, handler));
            }
Exemple #14
0
 public static BidiFlow <Emitted <T>, IPersistentRepresentation, Delivery <IPersistentRepresentation>, Delivery <Durable <T> >, NotUsed> Create(string persistenceId) =>
 BidiFlow.FromFlows(Encoder(persistenceId), Decoder);