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