Пример #1
0
        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);
                }
            }
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        public async Task <TmqServerSocket> Connected(ITwinoServer server, IConnectionInfo connection, ConnectionData data)
        {
            string clientId;
            bool   found = data.Properties.TryGetValue(TmqHeaders.CLIENT_ID, out clientId);

            if (!found || string.IsNullOrEmpty(clientId))
            {
                clientId = _server.Server.ClientIdGenerator.Create();
            }

            //if another client with same unique id is online, do not accept new client
            MqClient foundClient = _server.Clients.Find(x => x.UniqueId == clientId);

            if (foundClient != null)
            {
                await connection.Socket.SendAsync(await _writer.Create(MessageBuilder.Busy()));

                return(null);
            }

            //creates new node client object
            MqClient client = new MqClient(_server.Server, connection);

            client.Data     = data;
            client.UniqueId = clientId.Trim();
            client.Token    = data.Properties.GetStringValue(TmqHeaders.CLIENT_TOKEN);
            client.Name     = data.Properties.GetStringValue(TmqHeaders.CLIENT_NAME);
            client.Type     = data.Properties.GetStringValue(TmqHeaders.CLIENT_TYPE);

            if (_server.Authenticator != null)
            {
                bool accepted = await _server.Authenticator.Authenticate(_server, client);

                if (!accepted)
                {
                    return(null);
                }
            }

            client.RemoteHost = client.Info.Client.Client.RemoteEndPoint.ToString().Split(':')[0];
            _server.Clients.Add(client);

            await client.SendAsync(MessageBuilder.Accepted(client.UniqueId));

            return(client);
        }
Пример #3
0
        public async Task Handle(MqClient client, TmqMessage message)
        {
            //if server is not set or there is no connected server
            if (_server.NodeServer.Connectors.Length == 0)
            {
                return;
            }

            byte[] mdata = await _writer.Create(message);

            foreach (TmqStickyConnector connector in _server.NodeServer.Connectors)
            {
                bool grant = _server.NodeServer.Authenticator == null || await _server.NodeServer.Authenticator.CanReceive(connector.GetClient(), message);

                if (grant)
                {
                    connector.Send(mdata);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Called when a new client is connected via TMQ protocol
        /// </summary>
        public async Task <TmqServerSocket> Connected(ITwinoServer server, IConnectionInfo connection, ConnectionData data)
        {
            string clientId;
            bool   found = data.Properties.TryGetValue(TmqHeaders.CLIENT_ID, out clientId);

            if (!found || string.IsNullOrEmpty(clientId))
            {
                clientId = _server.ClientIdGenerator.Create();
            }

            //if another client with same unique id is online, do not accept new client
            MqClient foundClient = _server.FindClient(clientId);

            if (foundClient != null)
            {
                await connection.Socket.SendAsync(await _writer.Create(MessageBuilder.Busy()));

                return(null);
            }

            //creates new mq client object
            MqClient client = new MqClient(_server, connection, _server.MessageIdGenerator, _server.Options.UseMessageId);

            client.Data     = data;
            client.UniqueId = clientId.Trim();
            client.Token    = data.Properties.GetStringValue(TmqHeaders.CLIENT_TOKEN);
            client.Name     = data.Properties.GetStringValue(TmqHeaders.CLIENT_NAME);
            client.Type     = data.Properties.GetStringValue(TmqHeaders.CLIENT_TYPE);

            //connecting client is a MQ server
            string serverValue = data.Properties.GetStringValue(TmqHeaders.TWINO_MQ_SERVER);

            if (!string.IsNullOrEmpty(serverValue) && (serverValue.Equals("1") || serverValue.Equals("true", StringComparison.InvariantCultureIgnoreCase)))
            {
                if (_server.ServerAuthenticator == null)
                {
                    return(null);
                }

                bool accepted = await _server.ServerAuthenticator.Authenticate(_server, client);

                if (!accepted)
                {
                    return(null);
                }

                client.IsInstanceServer = true;
                _server.SlaveInstances.Add(new SlaveInstance
                {
                    ConnectedDate = DateTime.UtcNow,
                    Client        = client,
                    RemoteHost    = client.Info.Client.Client.RemoteEndPoint.ToString().Split(':')[0]
                });

                await client.SendAsync(MessageBuilder.Accepted(client.UniqueId));
            }

            //connecting client is a producer/consumer client
            else
            {
                //authenticates client
                if (_server.Authenticator != null)
                {
                    client.IsAuthenticated = await _server.Authenticator.Authenticate(_server, client);

                    if (!client.IsAuthenticated)
                    {
                        await client.SendAsync(MessageBuilder.Unauthorized());

                        return(null);
                    }
                }

                //client authenticated, add it into the connected clients list
                _server.AddClient(client);

                //send response message to the client, client should check unique id,
                //if client's unique id isn't permitted, server will create new id for client and send it as response
                await client.SendAsync(MessageBuilder.Accepted(client.UniqueId));

                if (_server.ClientHandler != null)
                {
                    await _server.ClientHandler.Connected(_server, client);
                }
            }

            return(client);
        }
Пример #5
0
        private async Task <PushResult> ProcessMessage(QueueMessage message)
        {
            //if we need acknowledge from receiver, it has a deadline.
            DateTime?ackDeadline = null;

            if (_queue.Options.RequestAcknowledge)
            {
                ackDeadline = DateTime.UtcNow.Add(_queue.Options.AcknowledgeTimeout);
            }

            //if there are not receivers, complete send operation
            List <ChannelClient> clients = _queue.Channel.ClientsClone;

            if (clients.Count == 0)
            {
                _queue.AddMessage(message, false);
                return(PushResult.NoConsumers);
            }

            //if to process next message is requires previous message acknowledge, wait here
            if (_queue.Options.RequestAcknowledge && _queue.Options.WaitForAcknowledge)
            {
                await _queue.WaitForAcknowledge(message);
            }

            message.Decision = await _queue.DeliveryHandler.BeginSend(_queue, message);

            if (!await _queue.ApplyDecision(message.Decision, message))
            {
                return(PushResult.Success);
            }

            //create prepared message data
            byte[] messageData = await _writer.Create(message.Message);

            Decision final         = new Decision(false, false, false, DeliveryAcknowledgeDecision.None);
            bool     messageIsSent = false;

            //to all receivers
            foreach (ChannelClient client in clients)
            {
                //to only online receivers
                if (!client.Client.IsConnected)
                {
                    continue;
                }

                //somehow if code comes here (it should not cuz of last "break" in this foreach, break
                if (!message.Message.FirstAcquirer && _queue.Options.SendOnlyFirstAcquirer)
                {
                    break;
                }

                //call before send and check decision
                Decision ccrd = await _queue.DeliveryHandler.CanConsumerReceive(_queue, message, client.Client);

                final = ChannelQueue.CreateFinalDecision(final, ccrd);

                if (!ccrd.Allow)
                {
                    continue;
                }

                //create delivery object
                MessageDelivery delivery = new MessageDelivery(message, client, ackDeadline);
                delivery.FirstAcquirer = message.Message.FirstAcquirer;

                //send the message
                bool sent = client.Client.Send(messageData);

                if (sent)
                {
                    messageIsSent = true;

                    //adds the delivery to time keeper to check timing up
                    _queue.TimeKeeper.AddAcknowledgeCheck(delivery);

                    //set as sent, if message is sent to it's first acquirer,
                    //set message first acquirer false and re-create byte array data of the message
                    bool firstAcquirer = message.Message.FirstAcquirer;

                    //mark message is sent
                    delivery.MarkAsSent();

                    //do after send operations for per message
                    _queue.Info.AddDelivery();
                    Decision d = await _queue.DeliveryHandler.ConsumerReceived(_queue, delivery, client.Client);

                    final = ChannelQueue.CreateFinalDecision(final, d);

                    //if we are sending to only first acquirer, break
                    if (_queue.Options.SendOnlyFirstAcquirer && firstAcquirer)
                    {
                        break;
                    }

                    if (firstAcquirer && clients.Count > 1)
                    {
                        messageData = await _writer.Create(message.Message);
                    }
                }
                else
                {
                    Decision d = await _queue.DeliveryHandler.ConsumerReceiveFailed(_queue, delivery, client.Client);

                    final = ChannelQueue.CreateFinalDecision(final, d);
                }
            }

            message.Decision = final;
            if (!await _queue.ApplyDecision(final, message))
            {
                return(PushResult.Success);
            }

            //after all sending operations completed, calls implementation send completed method and complete the operation
            if (messageIsSent)
            {
                _queue.Info.AddMessageSend();
            }

            message.Decision = await _queue.DeliveryHandler.EndSend(_queue, message);

            await _queue.ApplyDecision(message.Decision, message);

            if (message.Decision.Allow && !message.Decision.KeepMessage)
            {
                _queue.Info.AddMessageRemove();
                _ = _queue.DeliveryHandler.MessageRemoved(_queue, message);
            }

            return(PushResult.Success);
        }
Пример #6
0
        private async Task <PushResult> ProcessMessage(QueueMessage message, ChannelClient receiver)
        {
            //if we need acknowledge from receiver, it has a deadline.
            DateTime?deadline = null;

            if (_queue.Options.RequestAcknowledge)
            {
                deadline = DateTime.UtcNow.Add(_queue.Options.AcknowledgeTimeout);
            }

            //if to process next message is requires previous message acknowledge, wait here
            if (_queue.Options.RequestAcknowledge && _queue.Options.WaitForAcknowledge)
            {
                await _queue.WaitForAcknowledge(message);
            }

            message.Decision = await _queue.DeliveryHandler.BeginSend(_queue, message);

            if (!await _queue.ApplyDecision(message.Decision, message))
            {
                return(PushResult.Success);
            }

            //create prepared message data
            byte[] messageData = await _writer.Create(message.Message);

            //call before send and check decision
            message.Decision = await _queue.DeliveryHandler.CanConsumerReceive(_queue, message, receiver.Client);

            if (!await _queue.ApplyDecision(message.Decision, message))
            {
                return(PushResult.Success);
            }

            //create delivery object
            MessageDelivery delivery = new MessageDelivery(message, receiver, deadline);

            delivery.FirstAcquirer = message.Message.FirstAcquirer;

            //send the message
            bool sent = receiver.Client.Send(messageData);

            if (sent)
            {
                //adds the delivery to time keeper to check timing up
                _queue.TimeKeeper.AddAcknowledgeCheck(delivery);

                //mark message is sent
                delivery.MarkAsSent();
                _queue.Info.AddMessageSend();

                //do after send operations for per message
                _queue.Info.AddDelivery();
                message.Decision = await _queue.DeliveryHandler.ConsumerReceived(_queue, delivery, receiver.Client);
            }
            else
            {
                message.Decision = await _queue.DeliveryHandler.ConsumerReceiveFailed(_queue, delivery, receiver.Client);
            }

            if (!await _queue.ApplyDecision(message.Decision, message))
            {
                return(PushResult.Success);
            }

            message.Decision = await _queue.DeliveryHandler.EndSend(_queue, message);

            await _queue.ApplyDecision(message.Decision, message);

            if (message.Decision.Allow && !message.Decision.KeepMessage)
            {
                _queue.Info.AddMessageRemove();
                _ = _queue.DeliveryHandler.MessageRemoved(_queue, message);
            }

            return(PushResult.Success);
        }
Пример #7
0
        /// <summary>
        /// Called when a new client is connected via TMQ protocol
        /// </summary>
        public async Task <TmqServerSocket> Connected(ITwinoServer server, IConnectionInfo connection, ConnectionData data)
        {
            string clientId;
            bool   found = data.Properties.TryGetValue(TmqHeaders.CLIENT_ID, out clientId);

            if (!found || string.IsNullOrEmpty(clientId))
            {
                clientId = _server.ClientIdGenerator.Create();
            }

            //if another client with same unique id is online, do not accept new client
            MqClient foundClient = _server.FindClient(clientId);

            if (foundClient != null)
            {
                await connection.Socket.SendAsync(await _writer.Create(MessageBuilder.Busy()));

                return(null);
            }

            if (_server.Options.ClientLimit > 0 && _server.GetOnlineClients() >= _server.Options.ClientLimit)
            {
                return(null);
            }

            //creates new mq client object
            MqClient client = new MqClient(_server, connection, _server.MessageIdGenerator, _server.Options.UseMessageId);

            client.Data     = data;
            client.UniqueId = clientId.Trim();
            client.Token    = data.Properties.GetStringValue(TmqHeaders.CLIENT_TOKEN);
            client.Name     = data.Properties.GetStringValue(TmqHeaders.CLIENT_NAME);
            client.Type     = data.Properties.GetStringValue(TmqHeaders.CLIENT_TYPE);

            //authenticates client
            if (_server.Authenticator != null)
            {
                client.IsAuthenticated = await _server.Authenticator.Authenticate(_server, client);

                if (!client.IsAuthenticated)
                {
                    await client.SendAsync(MessageBuilder.Unauthorized());

                    return(null);
                }
            }

            //client authenticated, add it into the connected clients list
            _server.AddClient(client);

            //send response message to the client, client should check unique id,
            //if client's unique id isn't permitted, server will create new id for client and send it as response
            await client.SendAsync(MessageBuilder.Accepted(client.UniqueId));

            if (_server.ClientHandler != null)
            {
                await _server.ClientHandler.Connected(_server, client);
            }

            return(client);
        }