public IFrame Process(IStompClient client, IFrame request)
        {
            var versions = request.Headers["accept-version"];
            if (versions == null)
            {
                var error = request.CreateError("Missing the 'accept-version' header.");
                error.Headers["version"] = "2.0";
                return error;
            }

            if (!versions.Contains("2.0"))
            {
                var error = request.CreateError("Only accepting stomp 2.0 clients.");
                error.Headers["version"] = "2.0";
                return error;
            }

            IFrame frame;
            if (!CheckCredentials(client, request, out frame)) 
                return frame;

            //TODO: Heartbeating.


            var response = new BasicFrame("CONNECTED");
            response.Headers["version"] = "2.0";
            response.Headers["server"] = _serverName;

            if (client.SessionKey != null)
                response.Headers["session"] = client.SessionKey;

            return response;
        }
예제 #2
0
        /// <summary>
        ///     We've received bytes from the socket. Build a message out of them.
        /// </summary>
        /// <param name="buffer">Buffer</param>
        /// <remarks></remarks>
        public void ProcessReadBytes(ISocketBuffer buffer)
        {
            int receiveBufferOffset = buffer.Offset;
            int bytesLeftInReceiveBuffer = buffer.BytesTransferred;
            while (true)
            {
                if (bytesLeftInReceiveBuffer <= 0)
                    break;

                if (!_isHeaderParsed)
                {
                    var offsetBefore = receiveBufferOffset;
                    receiveBufferOffset = _headerParser.Parse(buffer, receiveBufferOffset);
                    if (!_isHeaderParsed)
                        return;

                    bytesLeftInReceiveBuffer -= receiveBufferOffset - offsetBefore;
                    _frameContentBytesLeft = _frame.ContentLength;
                    if (_frameContentBytesLeft == 0)
                    {
                        // the NULL message delimiter
                        if (bytesLeftInReceiveBuffer == 1)
                            bytesLeftInReceiveBuffer = 0;

                        MessageReceived(_frame);
                        _frame = null;
                        _isHeaderParsed = false;
                        continue;
                    }

                    _frame.Body = new MemoryStream();
                }

                var bytesRead = BytesProcessed(buffer.Offset, receiveBufferOffset);
                var bytesToWrite = Math.Min(_frameContentBytesLeft, buffer.BytesTransferred - bytesRead);
                _frame.Body.Write(buffer.Buffer, receiveBufferOffset, bytesToWrite);
                _frameContentBytesLeft -= bytesToWrite;
                receiveBufferOffset += bytesToWrite;
                bytesLeftInReceiveBuffer -= bytesToWrite;
                bytesRead += bytesToWrite;
                if (_frameContentBytesLeft == 0)
                {
                    // ignore NULL (message delimiter)
                    //TODO: Maybe verify it? ;)
                    var bytesRemaining = buffer.BytesTransferred - bytesRead;
                    if (bytesRemaining == 1)
                    {
                        bytesLeftInReceiveBuffer--;
                        receiveBufferOffset++;
                    }


                    _frame.Body.Position = 0;
                    MessageReceived(_frame);
                    Clear();
                }
            }

        }
        public void do_not_create_receipt_if_the_header_is_missing()
        {
            var frame = new BasicFrame("SEND");

            var response = frame.CreateReceiptIfRequired();

            response.Should().BeNull();
        }
        public void cant_ack_without_message_id()
        {
            var frame = new BasicFrame("ACK");
            var client = Substitute.For<IStompClient>();

            var sut = new AckHandler();
            Action actual = () => sut.Process(client, frame);

            actual.ShouldThrow<BadRequestException>();
        }
        public void transaction_must_be_specified()
        {
            var frame = new BasicFrame("COMMIT");
            var client = Substitute.For<IStompClient>();

            var sut = new CommitHandler();
            Action actual = () => sut.Process(client, frame);

            actual.ShouldThrow<BadRequestException>();
        }
        public void create_receipt_with_correct_id()
        {
            var frame = new BasicFrame("SEND");
            frame.Headers["receipt"] = "1";

            var response = frame.CreateReceiptIfRequired();

            response.Should().NotBeNull();
            response.Headers["receipt-id"] = "1";
        }
        public void cant_abort_without_transaction_identifier()
        {
            var frame = new BasicFrame("ABORT");
            var client = Substitute.For<IStompClient>();
            
            var sut = new AbortHandler();
            Action actual = () => sut.Process(client, frame);

            actual.ShouldThrow<BadRequestException>();
        }
        public void destination_is_required_according_to_the_specification()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("SEND");

            var handler = new SendHandler(repos);
            Action actual = () => handler.Process(client, msg);

            actual.ShouldThrow<BadRequestException>();
        }
        public void id_is_required()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("UNSUBSCRIBE");

            var sut = new UnsubscribeHandler(repos);
            Action actual =()=> sut.Process(client, msg);

            actual.ShouldThrow<BadRequestException>();
        }
        public void subscription_id_must_be_specified_according_to_the_specification()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("SUBSCRIBE");

            var sut = new SubscribeHandler(repos);
            Action actual = () => sut.Process(client, msg);

            actual.ShouldThrow<BadRequestException>();
        }
        public void succeed_if_transaction_was_specified()
        {
            var frame = new BasicFrame("COMMIT");
            frame.Headers["transaction"] = "aa";
            var client = Substitute.For<IStompClient>();

            var sut = new CommitHandler();
            sut.Process(client, frame);

            client.Received().CommitTransaction("aa");
        }
        public void abort_if_transaction_was_specified()
        {
            var frame = new BasicFrame("ABORT");
            frame.Headers["transaction"] = "aa";
            var client = Substitute.For<IStompClient>();

            var sut = new AbortHandler();
            sut.Process(client, frame);

            client.Received().RollbackTransaction("aa");
        }
        public void cant_ack_if_message_Was_not_found()
        {
            var frame = new BasicFrame("ACK");
            frame.Headers["id"] = "aa";
            var client = Substitute.For<IStompClient>();
            client.IsFramePending("aa").Returns(false);

            var sut = new AckHandler();
            Action actual = () => sut.Process(client, frame);

            actual.ShouldThrow<BadRequestException>();
        }
        public void subscription_must_exist()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("UNSUBSCRIBE");
            msg.Headers["id"] = "1";

            var sut = new UnsubscribeHandler(repos);
            Action actual = () => sut.Process(client, msg);

            actual.ShouldThrow<BadRequestException>();
        }
        /// <summary>
        /// Check if the 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static IFrame CreateReceiptIfRequired(this IFrame request)
        {
            var receipt = request.Headers["receipt"];
            if (receipt != null)
            {
                var response = new BasicFrame("RECEIPT");
                response.Headers["receipt-id"] = receipt;
                return response;
            }

            return null;
        }
        public void version_is_required_according_to_the_specification()
        {
            var authService = Substitute.For<IAuthenticationService>();
            var frame = new BasicFrame("STOMP");
            var client = Substitute.For<IStompClient>();

            var sut = new ConnectHandler(authService, "Kickass");
            var actual = sut.Process(client, frame);

            actual.Should().NotBeNull();
            actual.Headers["version"].Should().Be("2.0");
            actual.Headers["message"].Should().Be("Missing the 'accept-version' header.");
        }
        public void may_not_subscribe_on_previously_created_subscription()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("SUBSCRIBE");
            msg.Headers["id"] = "123";
            client.SubscriptionExists("123").Returns(true);

            var sut = new SubscribeHandler(repos);
            Action actual = () => sut.Process(client, msg);

            actual.ShouldThrow<BadRequestException>();
        }
        public void NoOp_message()
        {
            var frame = new BasicFrame("NoOp");
            var expected = "\n";
            var buffer = new SocketBufferFake();

            var encoder = new StompEncoder();
            encoder.Prepare(frame);
            encoder.Send(buffer);
            var actual = Encoding.ASCII.GetString(buffer.Buffer, 0, buffer.Count);

            actual.Should().Be(expected);
        }
        public void Test()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("UNSUBSCRIBE");
            msg.Headers["id"] = "1";
            client.RemoveSubscription("1").Returns(new Subscription(client, "1"));

            var sut = new UnsubscribeHandler(repos);
            var actual = sut.Process(client, msg);

            actual.Should().BeNull();
        }
        public void message_in_its_simplest_form()
        {
            var frame = new BasicFrame("STOMP");
            var expected = "STOMP\n\n\0";
            var buffer = new SocketBufferFake();

            var encoder = new StompEncoder();
            encoder.Prepare(frame);
            encoder.Send(buffer);
            var actual = Encoding.ASCII.GetString(buffer.Buffer, 0, buffer.Count);

            actual.Should().Be(expected);
        }
        public void may_not_begin_an_already_created_transaction()
        {
            var frame = new BasicFrame("BEGIN");
            frame.Headers["transaction"] = "aa";
            var client = Substitute.For<IStompClient>();
            client.When(x => x.BeginTransaction("aa"))
                .Do(x => { throw new InvalidOperationException("Transaction already exist"); });

            var sut = new BeginHandler();
            Action actual = () => sut.Process(client, frame);

            actual.ShouldThrow<InvalidOperationException>();
        }
        public void content_length_is_required_if_a_body_is_present()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("SEND");
            msg.Headers["destination"] = "/queue/momas";
            msg.Headers["content-type"] = "text/plain";
            msg.Body = new MemoryStream();

            var handler = new SendHandler(repos);
            Action actual = () => handler.Process(client, msg);

            actual.ShouldThrow<BadRequestException>();
        }
        public void ack()
        {
            var frame = new BasicFrame("ACK");
            frame.Headers["id"] = "aa";
            var client = Substitute.For<IStompClient>();
            var subscription = Substitute.For<Subscription>(client, "aa");
            client.IsFramePending("aa").Returns(true);
            client.GetSubscription("aa").Returns(subscription);

            var sut = new AckHandler();
            sut.Process(client, frame);

            subscription.Received().Ack("aa");
        }
        public void only_accepting_20_clients()
        {
            var authService = Substitute.For<IAuthenticationService>();
            var frame = new BasicFrame("STOMP");
            var client = Substitute.For<IStompClient>();
            frame.Headers["accept-version"] = "1.1";

            var sut = new ConnectHandler(authService, "Kickass");
            var actual = sut.Process(client, frame);

            actual.Should().NotBeNull();
            actual.Headers["version"].Should().Be("2.0");
            actual.Headers["message"].Should().Be("Only accepting stomp 2.0 clients.");
        }
        public void successful_subcribe()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("SUBSCRIBE");
            msg.Headers["id"] = "123";
            msg.Headers["destination"] = "/queue/mamma";
            repos.Get("/queue/mamma").Returns(new StompQueue());

            var sut = new SubscribeHandler(repos);
            var actual = sut.Process(client, msg);

        
        }
        public IFrame Process(IStompClient client, IFrame request)
        {
            var id = request.Headers["receipt"];
            if (string.IsNullOrEmpty(id))
                throw new BadRequestException(request, "Missing the 'receipt' header in the frame. It's required so that we can notify you when the DISCONNECT frame has been received.");

            if (client.HasActiveTransactions)
                throw new BadRequestException(request,
                    "Got pending transactions. Just close the socket to abort them, or send proper commits/rollbacks before the DISCONNECT frame..");

            var response = new BasicFrame("RECEIPT");
            response.AddHeader("receipt-id", id);
            return response;
        }
        public void copy_all_unknown_headers()
        {
            var repos = Substitute.For<IQueueRepository>();
            var client = Substitute.For<IStompClient>();
            var msg = new BasicFrame("SEND");
            msg.Headers["destination"] = "/queue/momas";
            msg.Headers["feck"] = "fock";
            msg.Headers["fack"] = "fick";

            var handler = new SendHandler(repos);
            var actual = handler.Process(client, msg);

            actual.Headers["feck"].Should().Be("fock");
            actual.Headers["fack"].Should().Be("fick");
        }
        public void send_message()
        {
            var frame = new BasicFrame("SEND");
            frame.AddHeader("destination", "/queue/a");
            frame.AddHeader("receipt", "message-12345");
            frame.Body = new MemoryStream(Encoding.ASCII.GetBytes("hello queue a"));
            var expected = "SEND\ndestination:/queue/a\nreceipt:message-12345\ncontent-length:13\n\nhello queue a\0";
            var buffer = new SocketBufferFake();

            var encoder = new StompEncoder();
            encoder.Prepare(frame);
            encoder.Send(buffer);
            var actual = Encoding.ASCII.GetString(buffer.Buffer, 0, buffer.Count);

            actual.Should().Be(expected);
        }
        public void enqueue_if_transaction_was_specified()
        {
            var frame = new BasicFrame("ACK");
            frame.Headers["id"] = "aa";
            frame.Headers["transaction"] = "sdfsd";
            var client = Substitute.For<IStompClient>();
            var subscription = Substitute.For<Subscription>(client, "aa");
            client.IsFramePending("aa").Returns(true);
            client.GetSubscription("aa").Returns(subscription);

            var sut = new AckHandler();
            sut.Process(client, frame);

            client.Received().EnqueueInTransaction("sdfsd", Arg.Any<Action>(), Arg.Any<Action>());
            subscription.DidNotReceive().Ack("aa");
        }
        public void always_accept_when_authentication_is_turned_off()
        {
            var authService = Substitute.For<IAuthenticationService>();
            var frame = new BasicFrame("STOMP");
            var client = Substitute.For<IStompClient>();
            frame.Headers["accept-version"] = "2.0";
            client.SessionKey.Returns(Guid.NewGuid().ToString());

            var sut = new ConnectHandler(authService, "Kickass");
            var actual = sut.Process(client, frame);

            actual.Should().NotBeNull();
            actual.Headers["version"].Should().Be("2.0");
            actual.Headers["server"].Should().Be("Kickass");
            actual.Headers["session"].Should().NotBeNullOrEmpty();
            client.ReceivedWithAnyArgs().SetAsAuthenticated(null);
        }