/// <summary> /// Removes a router with it's bindings /// </summary> private async Task RemoveRouter(MqClient client, HorseMessage message) { IRouter found = _server.FindRouter(message.Target); if (found == null) { await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); return; } //check create queue access foreach (IClientAuthorization authorization in _server.Authorizations) { bool grant = await authorization.CanRemoveRouter(client, found); if (!grant) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); return; } } _server.RemoveRouter(found); await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); }
/// <summary> /// Handles pushing a message into a queue /// </summary> private async Task HandlePush(MqClient client, TmqMessage message, ChannelQueue queue) { //check authority if (_server.Authorization != null) { bool grant = await _server.Authorization.CanMessageToQueue(client, queue, message); if (!grant) { if (!string.IsNullOrEmpty(message.MessageId)) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.Unauthorized)); } return; } } //prepare the message QueueMessage queueMessage = new QueueMessage(message); queueMessage.Source = client; //push the message PushResult result = await queue.Push(queueMessage, client); if (result == PushResult.StatusNotSupported) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.Unacceptable)); } else if (result == PushResult.LimitExceeded) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.LimitExceeded)); } }
/// <summary> /// Called when a new message received from the client /// </summary> public async Task Received(ITwinoServer server, IConnectionInfo info, TmqServerSocket client, TmqMessage message) { MqClient mc = (MqClient)client; //if client sends anonymous messages and server needs message id, generate new if (string.IsNullOrEmpty(message.MessageId)) { //anonymous messages can't be responsed, do not wait response if (message.ResponseRequired) { message.ResponseRequired = false; } //if server want to use message id anyway, generate new. if (_server.Options.UseMessageId) { message.SetMessageId(_server.MessageIdGenerator.Create()); } } //if message does not have a source information, source will be set to sender's unique id if (string.IsNullOrEmpty(message.Source)) { message.SetSource(mc.UniqueId); } //if client sending messages like someone another, kick him else if (message.Source != mc.UniqueId) { client.Disconnect(); return; } await RouteToHandler(mc, message, info); }
/// <summary> /// Processes the client message which has multiple receivers (message by name or type) /// </summary> private async Task ProcessMultipleReceiverClientMessage(MqClient sender, List <MqClient> receivers, HorseMessage message) { if (receivers.Count < 1) { await sender.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); return; } foreach (MqClient receiver in receivers) { //check sending message authority foreach (IClientAuthorization authorization in _server.Authorizations) { bool grant = await authorization.CanDirectMessage(sender, message, receiver); if (!grant) { await sender.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); return; } } //send the message await receiver.SendAsync(message); } }
/// <summary> /// Finalizes an instance of an actor. /// </summary> public override async Task FinalizeInstance() { foreach (SubscriptionState State in this.subscriptions) { State.Dispose(); } foreach (SubscriptionState State in this.subscriptions) { await State.Stopped.Task; } this.client?.Dispose(); this.client = null; if (!(this.sniffer is null)) { if (this.sniffer is IDisposable Disposable) { Disposable.Dispose(); } this.sniffer = null; } }
/// <summary> /// Processes the client message which has multiple receivers (message by name or type) /// </summary> private async Task ProcessMultipleReceiverClientMessage(MqClient sender, List <MqClient> receivers, TmqMessage message) { if (receivers.Count < 1) { await sender.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.NotFound)); return; } foreach (MqClient receiver in receivers) { //check sending message authority if (_server.Authorization != null) { bool grant = await _server.Authorization.CanMessageToPeer(sender, message, receiver); if (!grant) { await sender.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.Unauthorized)); return; } } //send the message await receiver.SendAsync(message); } }
/// <summary> /// Sends the message to binding receivers /// </summary> public override Task <bool> Send(MqClient sender, HorseMessage message) { try { if (DateTime.UtcNow - _queueUpdateTime > _queueCacheDuration) { RefreshQueueCache(); } message.WaitResponse = Interaction == BindingInteraction.Response; switch (RouteMethod) { case RouteMethod.Distribute: return(SendDistribute(message)); case RouteMethod.OnlyFirst: return(SendOnlyFirst(message)); case RouteMethod.RoundRobin: return(SendRoundRobin(message)); default: return(Task.FromResult(false)); } } catch (Exception e) { Router.Server.SendError("BINDING_SEND", e, $"Type:Topic, Binding:{Name}"); return(Task.FromResult(false)); } }
/// <summary> /// Pushes a message to router /// </summary> public Task <RouterPublishResult> Publish(MqClient sender, HorseMessage message) { try { if (!IsEnabled) { return(Task.FromResult(RouterPublishResult.Disabled)); } if (Bindings.Length == 0) { return(Task.FromResult(RouterPublishResult.NoBindings)); } switch (Method) { case RouteMethod.Distribute: return(Distribute(sender, message)); case RouteMethod.OnlyFirst: return(OnlyFirst(sender, message)); case RouteMethod.RoundRobin: return(RoundRobin(sender, message)); default: return(Task.FromResult(RouterPublishResult.Disabled)); } } catch (Exception e) { Server.SendError("PUBLISH", e, $"Router:{Name}, Binding:{Name}"); return(Task.FromResult(RouterPublishResult.NoBindings)); } }
/// <summary> /// Sends the message to only first binding /// </summary> private async Task <RouterPublishResult> OnlyFirst(MqClient sender, HorseMessage message) { int index = 0; bool sent; RouterPublishResult result = RouterPublishResult.NoReceivers; do { if (index >= Bindings.Length) { return(RouterPublishResult.NoReceivers); } Binding binding = Bindings[index]; sent = await binding.Send(sender, message); if (sent) { result = binding.Interaction != BindingInteraction.None ? RouterPublishResult.OkAndWillBeRespond : RouterPublishResult.OkWillNotRespond; } index++; }while (!sent); return(result); }
public async Task Handle(MqClient client, HorseMessage message, bool fromNode) { HorseQueue queue = await FindQueue(client, message.Target, message); if (queue == null) { return; } //if there is at least one cc header //we need to create a clone of the message //clone does not have cc headers but others HorseMessage clone = null; List <string> ccList = null; List <KeyValuePair <string, string> > additionalHeaders = null; if (message.HasHeader && message.FindHeader(HorseHeaders.CC) != null) { additionalHeaders = message.Headers.Where(x => !x.Key.Equals(HorseHeaders.CC, StringComparison.InvariantCultureIgnoreCase)).ToList(); ccList = new List <string>(message.Headers.Where(x => x.Key.Equals(HorseHeaders.CC, StringComparison.InvariantCultureIgnoreCase)).Select(x => x.Value)); clone = message.Clone(false, true, _server.MessageIdGenerator.Create(), additionalHeaders); } await HandlePush(client, message, queue, true); //if there are cc headers, we will push the message to other queues if (clone != null) { await PushOtherQueues(client, clone, ccList, additionalHeaders); } }
static void Main(string[] args) { try { Console.WriteLine("Enter message text and press return to send."); Console.WriteLine("Press return with a blank line to exit"); string messageToSend = Console.ReadLine(); using (var client = new MqClient("localhost", "TEST.CHANNEL", "TEST.QUEUE")) { while (!String.IsNullOrEmpty(messageToSend)) { client.Put(messageToSend); Console.WriteLine($"Message Sent: {messageToSend}"); messageToSend = Console.ReadLine(); } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.WriteLine("Press any key to exit"); Console.ReadKey(); }
public async Task Handle(MqClient client, HorseMessage message, bool fromNode) { try { HorseQueue queue = _server.FindQueue(message.Target); //if auto creation active, try to create queue if (queue == null && _server.Options.AutoQueueCreation) { QueueOptions options = QueueOptions.CloneFrom(_server.Options); queue = await _server.CreateQueue(message.Target, options, message, _server.DeliveryHandlerFactory, true, true); } if (queue == null) { if (!string.IsNullOrEmpty(message.MessageId)) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); } return; } await HandlePullRequest(client, message, queue); } catch (Exception e) { _server.SendError("PULL_REQUEST", e, $"QueueName:{message.Target}"); } }
/// <summary> /// Removes the client from the server /// </summary> internal async Task RemoveClient(MqClient client) { _clients.Remove(client); await client.UnsubscribeFromAllQueues(); OnClientDisconnected.Trigger(client); }
/// <summary> /// Sends all routers /// </summary> private async Task ListRouters(MqClient client, HorseMessage message) { List <RouterInformation> items = new List <RouterInformation>(); foreach (IRouter router in _server.Routers) { RouterInformation info = new RouterInformation { Name = router.Name, IsEnabled = router.IsEnabled }; if (router is Router r) { info.Method = r.Method; } items.Add(info); } HorseMessage response = message.CreateResponse(HorseResultCode.Ok); response.Serialize(items, new NewtonsoftContentSerializer()); await client.SendAsync(response); }
static async Task Test() { using (MqClient client = new MqClient("localhost:15555")) { //1) Create MQ if necessary(empty in zbus), you may ommit this step const string mq = "MyMQ"; Message data = new Message(); data.Headers["cmd"] = "create"; data.Headers["mq"] = mq; var res = await client.InvokeAsync(data); Console.WriteLine(JsonKit.SerializeObject(res)); //2) Publish Message data = new Message(); data.Headers["cmd"] = "pub"; data.Headers["mq"] = mq; data.Body = "Hello from C#"; res = await client.InvokeAsync(data); Console.WriteLine(JsonKit.SerializeObject(res)); } }
/// <summary> /// Distributes the message to all bindings /// </summary> private async Task <RouterPublishResult> Distribute(MqClient sender, HorseMessage message) { RouterPublishResult result = RouterPublishResult.NoReceivers; foreach (Binding binding in Bindings) { bool oldWaitResponse = message.WaitResponse; bool sent = await binding.Send(sender, message); message.WaitResponse = oldWaitResponse; if (sent) { if (binding.Interaction != BindingInteraction.None) { result = RouterPublishResult.OkAndWillBeRespond; } else if (result == RouterPublishResult.NoReceivers) { result = RouterPublishResult.OkWillNotRespond; } } } return(result); }
/// <summary> /// Processes the client message which has single receiver (message by unique id) /// </summary> private async Task ProcessSingleReceiverClientMessage(MqClient client, TmqMessage message) { //find the receiver MqClient other = _server.FindClient(message.Target); if (other == null) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.NotFound)); return; } //check sending message authority if (_server.Authorization != null) { bool grant = await _server.Authorization.CanMessageToPeer(client, message, other); if (!grant) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.Unauthorized)); return; } } //send the message await other.SendAsync(message); }
/// <summary> /// Sends the message to only one binding within round robin algorithm /// </summary> private async Task <RouterPublishResult> RoundRobin(MqClient sender, HorseMessage message) { int len = Bindings.Length; for (int i = 0; i < len; i++) { Interlocked.Increment(ref _lastRoutedIndex); if (_lastRoutedIndex >= Bindings.Length) { Interlocked.Exchange(ref _lastRoutedIndex, 0); } Binding binding = Bindings[_lastRoutedIndex]; bool waitResponse = message.WaitResponse; bool sent = await binding.Send(sender, message); message.WaitResponse = waitResponse; if (sent) { return(binding.Interaction != BindingInteraction.None ? RouterPublishResult.OkAndWillBeRespond : RouterPublishResult.OkWillNotRespond); } } return(RouterPublishResult.NoReceivers); }
/// <summary> /// Sends the message to binding receivers /// </summary> public override async Task <bool> Send(MqClient sender, HorseMessage message) { try { HorseQueue queue = await GetQueue(message); if (queue == null) { return(false); } string messageId = Interaction == BindingInteraction.None ? Router.Server.MessageIdGenerator.Create() : message.MessageId; HorseMessage msg = message.Clone(true, true, messageId); msg.Type = MessageType.QueueMessage; msg.SetTarget(Target); msg.WaitResponse = Interaction == BindingInteraction.Response; QueueMessage queueMessage = new QueueMessage(msg); queueMessage.Source = sender; PushResult result = await queue.Push(queueMessage, sender); return(result == PushResult.Success); } catch (Exception e) { Router.Server.SendError("BINDING_SEND", e, $"Type:AutoQueue, Binding:{Name}"); return(false); } }
public void Client_prevents_times_out() { var clientConfig = new MqConfig { Ip = Config.Ip, Port = Config.Port, PingFrequency = 100 }; Client = new MqClient <SimpleMqSession, MqConfig>(clientConfig); Config.PingTimeout = 200; Server = new MqServer <SimpleMqSession, MqConfig>(Config); Client.Closed += (sender, args) => { if (args.CloseReason == SocketCloseReason.TimeOut) { TestStatus.Set(); } else { LastException = new Exception("Client closed for reason other than timeout."); } }; StartAndWait(false, 1500); if (TestStatus.IsSet) { throw new Exception("Client timed out."); } }
/// <summary> /// Processes the client message which has single receiver (message by unique id) /// </summary> private async Task ProcessSingleReceiverClientMessage(MqClient client, HorseMessage message) { //find the receiver MqClient other = _server.FindClient(message.Target); if (other == null) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); return; } //check sending message authority foreach (IClientAuthorization authorization in _server.Authorizations) { bool grant = await authorization.CanDirectMessage(client, message, other); if (!grant) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); return; } } //send the message await other.SendAsync(message); }
public void Client_times_out_while_connecting_for_too_long() { Config.ConnectionTimeout = 100; Client = new MqClient <SimpleMqSession, MqConfig>(Config); Server.Connected += (sender, args) => { args.Session.Socket.Close(); }; Client.Closed += (sender, args) => { if (args.CloseReason == SocketCloseReason.TimeOut) { TestStatus.Set(); } else { LastException = new Exception("Client closed for reason other than timeout."); } }; StartAndWait(false, 10000, false); if (TestStatus.IsSet == false) { throw new Exception("Socket did not timeout."); } }
/// <summary> /// Initializes an instance of an actor. /// </summary> public override async Task InitializeInstance() { this.credentials = await Database.FindFirstIgnoreRest <AccountCredentials>(new FilterAnd( new FilterFieldEqualTo("Host", this.host), new FilterFieldEqualTo("UserName", this.userName))); if (this.credentials is null) { this.credentials = new AccountCredentials() { Host = this.host, UserName = this.userName, Password = string.IsNullOrEmpty(this.password) ? string.Empty : await this.Model.GetKey(this.password, this.userName) }; } this.sniffer = this.Model.GetSniffer(this.InstanceId); if (this.sniffer is null) { this.client = new MqClient(this.queueManager, this.channel, this.cipher, this.cipherSuite, this.certificateStore, this.host, this.port); } else { this.client = new MqClient(this.queueManager, this.channel, this.cipher, this.cipherSuite, this.certificateStore, this.host, this.port, this.sniffer); } this.connectionTask = this.client.ConnectAsync(this.credentials.UserName, this.credentials.Password); }
/// <summary> /// Adds the client to the queue /// </summary> public async Task <QueueSubscriptionResult> AddClient(MqClient client) { foreach (IQueueAuthenticator authenticator in Server.QueueAuthenticators) { bool allowed = await authenticator.Authenticate(this, client); if (!allowed) { return(QueueSubscriptionResult.Unauthorized); } } if (Options.ClientLimit > 0 && _clients.Count >= Options.ClientLimit) { return(QueueSubscriptionResult.Full); } QueueClient cc = new QueueClient(this, client); _clients.Add(cc); client.AddSubscription(cc); foreach (IQueueEventHandler handler in Server.QueueEventHandlers) { await handler.OnConsumerSubscribed(cc); } _ = Trigger(); OnConsumerSubscribed.Trigger(cc); return(QueueSubscriptionResult.Success); }
public async Task Handle(MqClient client, TmqMessage message) { //to prevent receive same message from instanced server that already sent from this server if (client.IsInstanceServer) { return; } //if server is not set or there is no connected server if (_server.ServerAuthenticator == null || _server.InstanceConnectors.Length == 0) { return; } byte[] mdata = await _writer.Create(message); foreach (TmqStickyConnector connector in _server.InstanceConnectors) { bool grant = await _server.ServerAuthenticator.CanReceive(connector.GetClient(), message); if (grant) { connector.Send(mdata); } } }
/// <summary> /// Puts a message on a queue. /// </summary> /// <param name="Client">MQ Client</param> /// <param name="Queue">Queue Name</param> /// <param name="Message">Message to put.</param> public PutTask(MqClient Client, string Queue, string Message) : base(Client) { this.queue = Queue; this.message = Message; this.result = new TaskCompletionSource <bool>(); }
/// <summary> /// Removes a channel with it's queues /// </summary> private async Task RemoveChannel(MqClient client, TmqMessage message) { if (_server.AdminAuthorization == null) { if (message.ResponseRequired) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.Unauthorized)); } return; } Channel channel = _server.FindChannel(message.Target); if (channel == null) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.NotFound)); return; } bool grant = await _server.AdminAuthorization.CanRemoveChannel(client, _server, channel); if (!grant) { if (message.ResponseRequired) { await client.SendAsync(MessageBuilder.ResponseStatus(message, KnownContentTypes.Unauthorized)); } return; } await _server.RemoveChannel(channel); }
public void PassPassengers(string busId, string flightId, int capacity) { lock (flightLock) { var flight = Flights.Find(e => e.FlightId == flightId); if (flight == null) { return; } int count = flight.Passengers.Count; int passCount = (count > capacity) ? capacity : count; var passengers = flight.Passengers.GetRange(0, passCount); MqClient.Send <PassengersFromStorageResponse>(storageBus, new PassengersFromStorageResponse() { BusId = busId, PassengersCount = passCount, PassengersIds = passengers }); Console.WriteLine($"Sent to Bus: {busId}, {passCount}"); flight.Passengers.RemoveRange(0, passCount); MqClient.Send <PassengerPassMessage>(storagePas, new PassengerPassMessage() { ObjectId = busId, Status = PassengerStatus.InBus, PassengersIds = passengers }); Console.WriteLine($"Sent to Passenger: in {busId}"); TryToRemove(flightId); } }
/// <summary> /// Routes message to it's type handler /// </summary> private async Task RouteToHandler(MqClient mc, TmqMessage message, IConnectionInfo info) { switch (message.Type) { //client sends a queue message in a channel case MessageType.Channel: await _instanceHandler.Handle(mc, message); await _channelHandler.Handle(mc, message); break; //clients sends a message to another client case MessageType.Client: await _instanceHandler.Handle(mc, message); await _clientHandler.Handle(mc, message); break; //client sends an acknowledge message of a message case MessageType.Acknowledge: await _instanceHandler.Handle(mc, message); await _acknowledgeHandler.Handle(mc, message); break; //client sends a response message for a message case MessageType.Response: await _instanceHandler.Handle(mc, message); await _responseHandler.Handle(mc, message); break; //client sends a message to the server //this message may be join, header, info, some another server message case MessageType.Server: await _serverHandler.Handle(mc, message); break; //if client sends a ping message, response with pong case MessageType.Ping: await mc.SendAsync(PredefinedMessages.PONG); break; //client sends PONG message case MessageType.Pong: mc.KeepAlive(); break; //close the client's connection case MessageType.Terminate: mc.Disconnect(); break; } }
/// <summary> /// Creates new router /// </summary> private async Task CreateRouter(MqClient client, HorseMessage message) { IRouter found = _server.FindRouter(message.Target); if (found != null) { await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); return; } string methodHeader = message.FindHeader(HorseHeaders.ROUTE_METHOD); RouteMethod method = RouteMethod.Distribute; if (!string.IsNullOrEmpty(methodHeader)) { method = (RouteMethod)Convert.ToInt32(methodHeader); } //check create queue access foreach (IClientAuthorization authorization in _server.Authorizations) { bool grant = await authorization.CanCreateRouter(client, message.Target, method); if (!grant) { await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); return; } } _server.AddRouter(message.Target, method); await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); }