Exemple #1
0
        /// <summary>
        /// Tries to initiate a connection (1:1 conversation) by creating a request on behalf of
        /// the given requestor. This method does nothing, if a request for the same user already exists.
        /// </summary>
        /// <param name="requestor">The requestor conversation reference.</param>
        /// <param name="rejectConnectionRequestIfNoAggregationChannel">
        /// If true, will reject all requests, if there is no aggregation channel.</param>
        /// <returns>The result of the operation:
        /// - ConnectionRequestResultType.Created,
        /// - ConnectionRequestResultType.AlreadyExists,
        /// - ConnectionRequestResultType.NotSetup or
        /// - ConnectionRequestResultType.Error (see the error message for more details).
        /// </returns>
        public virtual ConnectionRequestResult CreateConnectionRequest(
            ConversationReference requestor, bool rejectConnectionRequestIfNoAggregationChannel = false)
        {
            if (requestor == null)
            {
                throw new ArgumentNullException("Requestor missing");
            }

            ConnectionRequestResult createConnectionRequestResult = null;

            RoutingDataManager.AddConversationReference(requestor);
            ConnectionRequest connectionRequest = new ConnectionRequest(requestor);

            if (RoutingDataManager.IsAssociatedWithAggregation(requestor))
            {
                createConnectionRequestResult = new ConnectionRequestResult()
                {
                    Type         = ConnectionRequestResultType.Error,
                    ErrorMessage = $"The given ConversationReference ({RoutingDataManager.GetChannelAccount(requestor)?.Name}) is associated with aggregation and hence invalid to request a connection"
                };
            }
            else
            {
                createConnectionRequestResult = RoutingDataManager.AddConnectionRequest(
                    connectionRequest, rejectConnectionRequestIfNoAggregationChannel);
            }

            return(createConnectionRequestResult);
        }
        public NetPeer AcceptIfKey(string key)
        {
            if (!TryActivate())
            {
                return(null);
            }
            try
            {
                if (Data.GetString() == key)
                {
                    Result = ConnectionRequestResult.Accept;
                }
            }
            catch
            {
                NetDebug.WriteError("[AC] Invalid incoming data");
            }

            if (Result == ConnectionRequestResult.Accept)
            {
                return(_listener.OnConnectionSolved(this, null, 0, 0));
            }

            Result = ConnectionRequestResult.Reject;
            _listener.OnConnectionSolved(this, null, 0, 0);
            return(null);
        }
        /// <summary>
        /// Removes the connection request of the user with the given conversation reference.
        /// </summary>
        /// <param name="connectionRequestToRemove">The connection request to remove.</param>
        /// <returns>The result of the operation:
        /// - ConnectionRequestResultType.Rejected or
        /// - ConnectionRequestResultType.Error (see the error message for more details).
        /// </returns>
        public virtual ConnectionRequestResult RemoveConnectionRequest(ConnectionRequest connectionRequestToRemove)
        {
            if (connectionRequestToRemove == null)
            {
                throw new ArgumentNullException("Connection request is null");
            }

            ConnectionRequestResult removeConnectionRequestResult = new ConnectionRequestResult
            {
                ConnectionRequest = connectionRequestToRemove
            };

            if (GetConnectionRequests().Contains(connectionRequestToRemove))
            {
                if (RoutingDataStore.RemoveConnectionRequest(connectionRequestToRemove))
                {
                    removeConnectionRequestResult.Type = ConnectionRequestResultType.Rejected;
                }
                else
                {
                    removeConnectionRequestResult.Type         = ConnectionRequestResultType.Error;
                    removeConnectionRequestResult.ErrorMessage = "Failed to remove the connection request associated with the given user";
                }
            }
            else
            {
                removeConnectionRequestResult.Type         = ConnectionRequestResultType.Error;
                removeConnectionRequestResult.ErrorMessage = "Could not find a connection request associated with the given user";
            }

            return(removeConnectionRequestResult);
        }
Exemple #4
0
 public void Reject(byte[] rejectData, int start, int length, bool force)
 {
     if (!TryActivate())
     {
         return;
     }
     Result = force ? ConnectionRequestResult.RejectForce : ConnectionRequestResult.Reject;
     _listener.OnConnectionSolved(this, rejectData, start, length);
 }
 /// <summary>
 ///     Accept connection and get new NetPeer as result
 /// </summary>
 /// <returns>Connected NetPeer</returns>
 public NetPeer Accept()
 {
     if (!TryActivate())
     {
         return(null);
     }
     Result = ConnectionRequestResult.Accept;
     return(_listener.OnConnectionSolved(this, null, 0, 0));
 }
Exemple #6
0
 public void Reject()
 {
     if (_used)
     {
         return;
     }
     _used  = true;
     Result = ConnectionRequestResult.Reject;
     _onUserAction(this);
 }
Exemple #7
0
 /// <summary>
 /// Accept connection and get new NetPeer as result
 /// </summary>
 /// <returns>Connected NetPeer</returns>
 public NetPeer Accept()
 {
     if (_used)
     {
         return(null);
     }
     _used  = true;
     Result = ConnectionRequestResult.Accept;
     return(_onUserAction(this));
 }
Exemple #8
0
        /// <summary>
        /// Tries to reject the connection request of the associated with the given conversation reference.
        /// </summary>
        /// <param name="requestorToReject">The conversation reference of the party whose request to reject.</param>
        /// <param name="rejecter">The conversation reference of the party  rejecting the request (optional).</param>
        /// <returns>The result of the operation:
        /// - ConnectionRequestResultType.Rejected or
        /// - ConnectionRequestResultType.Error (see the error message for more details).
        /// </returns>
        public virtual ConnectionRequestResult RejectConnectionRequest(
            ConversationReference requestorToReject, ConversationReference rejecter = null)
        {
            if (requestorToReject == null)
            {
                throw new ArgumentNullException("The conversation reference instance of the party whose request to reject cannot be null");
            }

            ConnectionRequestResult rejectConnectionRequestResult = null;
            ConnectionRequest       connectionRequest             =
                RoutingDataManager.FindConnectionRequest(requestorToReject);

            if (connectionRequest != null)
            {
                rejectConnectionRequestResult          = RoutingDataManager.RemoveConnectionRequest(connectionRequest);
                rejectConnectionRequestResult.Rejecter = rejecter;
            }

            return(rejectConnectionRequestResult);
        }
        /// <summary>
        /// Adds the given connection request.
        /// </summary>
        /// <param name="connectionRequestToAdd">The connection request to add.</param>
        /// <param name="rejectConnectionRequestIfNoAggregationChannel">
        /// If true, will reject all requests, if there is no aggregation channel.</param>
        /// <returns>The result of the operation:
        /// - ConnectionRequestResultType.Created,
        /// - ConnectionRequestResultType.AlreadyExists,
        /// - ConnectionRequestResultType.NotSetup or
        /// - ConnectionRequestResultType.Error (see the error message for more details).
        /// </returns>
        public virtual ConnectionRequestResult AddConnectionRequest(
            ConnectionRequest connectionRequestToAdd, bool rejectConnectionRequestIfNoAggregationChannel = false)
        {
            if (connectionRequestToAdd == null)
            {
                throw new ArgumentNullException("Connection request is null");
            }

            ConnectionRequestResult addConnectionRequestResult = new ConnectionRequestResult()
            {
                ConnectionRequest = connectionRequestToAdd
            };

            if (GetConnectionRequests().Contains(connectionRequestToAdd))
            {
                addConnectionRequestResult.Type = ConnectionRequestResultType.AlreadyExists;
            }
            else
            {
                if (!GetAggregationChannels().Any() && rejectConnectionRequestIfNoAggregationChannel)
                {
                    addConnectionRequestResult.Type = ConnectionRequestResultType.NotSetup;
                }
                else
                {
                    connectionRequestToAdd.ConnectionRequestTime = GetCurrentGlobalTime();

                    if (RoutingDataStore.AddConnectionRequest(connectionRequestToAdd))
                    {
                        addConnectionRequestResult.Type = ConnectionRequestResultType.Created;
                    }
                    else
                    {
                        addConnectionRequestResult.Type         = ConnectionRequestResultType.Error;
                        addConnectionRequestResult.ErrorMessage = "Failed to add the connection request - this is likely an error caused by the storage implementation";
                    }
                }
            }

            return(addConnectionRequestResult);
        }
Exemple #10
0
        /// <summary>
        /// Handles the given connection request result.
        /// </summary>
        /// <param name="connectionRequestResult">The result to handle.</param>
        /// <returns>True, if the result was handled. False, if no action was taken.</returns>
        protected virtual async Task <bool> HandleConnectionRequestResultAsync(
            ConnectionRequestResult connectionRequestResult)
        {
            ConnectionRequest connectionRequest = connectionRequestResult?.ConnectionRequest;

            if (connectionRequest == null || connectionRequest.Requestor == null)
            {
                System.Diagnostics.Debug.WriteLine("No client to inform about the connection request result");
                return(false);
            }

            switch (connectionRequestResult.Type)
            {
            case ConnectionRequestResultType.Created:
                foreach (ConversationReference aggregationChannel
                         in _messageRouter.RoutingDataManager.GetAggregationChannels())
                {
                    ConversationReference botConversationReference =
                        _messageRouter.RoutingDataManager.FindConversationReference(
                            aggregationChannel.ChannelId, aggregationChannel.Conversation.Id, null, true);

                    if (botConversationReference != null)
                    {
                        IMessageActivity messageActivity = Activity.CreateMessageActivity();
                        messageActivity.Conversation = aggregationChannel.Conversation;
                        messageActivity.Recipient    = RoutingDataManager.GetChannelAccount(aggregationChannel);
                        messageActivity.Attachments  = new List <Attachment>
                        {
                            CommandCardFactory.CreateConnectionRequestCard(
                                connectionRequest,
                                RoutingDataManager.GetChannelAccount(
                                    botConversationReference)?.Name).ToAttachment()
                        };

                        await _messageRouter.SendMessageAsync(aggregationChannel, messageActivity);
                    }
                }

                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NotifyClientWaitForRequestHandling);

                return(true);

            case ConnectionRequestResultType.AlreadyExists:
                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NotifyClientDuplicateRequest);

                return(true);

            case ConnectionRequestResultType.Rejected:
                if (connectionRequestResult.Rejecter != null)
                {
                    await _messageRouter.SendMessageAsync(
                        connectionRequestResult.Rejecter,
                        string.Format(Strings.NotifyOwnerRequestRejected, GetNameOrId(connectionRequest.Requestor)));
                }

                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NotifyClientRequestRejected);

                return(true);

            case ConnectionRequestResultType.NotSetup:
                await _messageRouter.SendMessageAsync(
                    connectionRequest.Requestor, Strings.NoAgentsAvailable);

                return(true);

            case ConnectionRequestResultType.Error:
                if (connectionRequestResult.Rejecter != null)
                {
                    await _messageRouter.SendMessageAsync(
                        connectionRequestResult.Rejecter,
                        string.Format(Strings.ConnectionRequestResultErrorWithResult, connectionRequestResult.ErrorMessage));
                }

                return(true);

            default:
                break;
            }

            return(false);
        }
Exemple #11
0
        /// <summary>
        /// Tries to accept/reject a pending connection request.
        /// </summary>
        /// <param name="messageRouter">The message router.</param>
        /// <param name="messageRouterResultHandler">The message router result handler.</param>
        /// <param name="sender">The sender party (accepter/rejecter).</param>
        /// <param name="doAccept">If true, will try to accept the request. If false, will reject.</param>
        /// <param name="requestorChannelAccountId">The channel account ID of the user/bot whose request to accept/reject.</param>
        /// <param name="requestorConversationAccountId">The conversation account ID of the user/bot whose request to accept/reject.</param>
        /// <returns>The result.</returns>
        public async Task <AbstractMessageRouterResult> AcceptOrRejectRequestAsync(
            MessageRouter messageRouter, MessageRouterResultHandler messageRouterResultHandler,
            ConversationReference sender, bool doAccept,
            ChannelAccount requestorChannelAccountId, ConversationAccount requestorConversationAccountId)
        {
            AbstractMessageRouterResult messageRouterResult = new ConnectionRequestResult()
            {
                Type = ConnectionRequestResultType.Error
            };

            ConversationReference requestor =
                new ConversationReference(
                    null, requestorChannelAccountId, null, requestorConversationAccountId);

            ConnectionRequest connectionRequest =
                messageRouter.RoutingDataManager.FindConnectionRequest(requestor);

            if (connectionRequest == null)
            {
                // Try bot
                requestor.Bot  = requestor.User;
                requestor.User = null;

                connectionRequest =
                    messageRouter.RoutingDataManager.FindConnectionRequest(requestor);
            }

            if (connectionRequest != null)
            {
                Connection connection = null;

                if (sender != null)
                {
                    connection = messageRouter.RoutingDataManager.FindConnection(sender);
                }

                ConversationReference senderInConnection = null;
                ConversationReference counterpart        = null;

                if (connection != null && connection.ConversationReference1 != null)
                {
                    if (RoutingDataManager.Match(sender, connection.ConversationReference1))
                    {
                        senderInConnection = connection.ConversationReference1;
                        counterpart        = connection.ConversationReference2;
                    }
                    else
                    {
                        senderInConnection = connection.ConversationReference2;
                        counterpart        = connection.ConversationReference1;
                    }
                }

                if (doAccept)
                {
                    if (senderInConnection != null)
                    {
                        // The sender (accepter/rejecter) is ALREADY connected to another party
                        if (counterpart != null)
                        {
                            messageRouterResult.ErrorMessage = string.Format(
                                Strings.AlreadyConnectedWithUser,
                                RoutingDataManager.GetChannelAccount(counterpart)?.Name);
                        }
                        else
                        {
                            messageRouterResult.ErrorMessage = Strings.ErrorOccured;
                        }
                    }
                    else
                    {
                        bool createNewDirectConversation =
                            (_noDirectConversationsWithChannels == null ||
                             !(_noDirectConversationsWithChannels.Contains(sender.ChannelId.ToLower())));

                        // Try to accept
                        messageRouterResult = await messageRouter.ConnectAsync(
                            sender,
                            connectionRequest.Requestor,
                            createNewDirectConversation);
                    }
                }
                else
                {
                    // Note: Rejecting is OK even if the sender is alreay connected
                    messageRouterResult = messageRouter.RejectConnectionRequest(connectionRequest.Requestor, sender);
                }
            }
            else
            {
                messageRouterResult.ErrorMessage = Strings.FailedToFindPendingRequest;
            }

            return(messageRouterResult);
        }
        /// <summary>
        /// Removes the specified ConversationReference from all possible containers.
        /// </summary>
        /// <param name="conversationReferenceToRemove">The ConversationReference to remove.</param>
        /// <returns>A list of operation result(s).</returns>
        public virtual IList <AbstractMessageRouterResult> RemoveConversationReference(
            ConversationReference conversationReferenceToRemove)
        {
            if (conversationReferenceToRemove == null)
            {
                throw new ArgumentNullException("The given conversation reference is null");
            }

            List <AbstractMessageRouterResult> messageRouterResults = new List <AbstractMessageRouterResult>();
            bool wasRemoved = false;

            // Check users and bots
            IList <ConversationReference> conversationReferenceToSearch =
                IsBot(conversationReferenceToRemove) ? GetBotInstances() : GetUsers();

            IList <ConversationReference> conversationReferencesToRemove = FindConversationReferences(
                conversationReferenceToSearch, null, null,
                GetChannelAccount(conversationReferenceToRemove)?.Id);

            foreach (ConversationReference conversationReference in conversationReferencesToRemove)
            {
                if (RoutingDataStore.RemoveConversationReference(conversationReference))
                {
                    messageRouterResults.Add(new ModifyRoutingDataResult()
                    {
                        Type = ModifyRoutingDataResultType.Removed
                    });
                }
                else
                {
                    messageRouterResults.Add(new ModifyRoutingDataResult()
                    {
                        Type         = ModifyRoutingDataResultType.Error,
                        ErrorMessage = "Failed to remove conversation reference"
                    });
                }
            }

            // Check connection requests
            wasRemoved = true;

            while (wasRemoved)
            {
                wasRemoved = false;

                foreach (ConnectionRequest connectionRequest in GetConnectionRequests())
                {
                    if (Match(conversationReferenceToRemove, connectionRequest.Requestor))
                    {
                        ConnectionRequestResult removeConnectionRequestResult =
                            RemoveConnectionRequest(connectionRequest);

                        if (removeConnectionRequestResult.Type == ConnectionRequestResultType.Rejected)
                        {
                            wasRemoved = true;
                            messageRouterResults.Add(removeConnectionRequestResult);
                            break;
                        }
                    }
                }
            }

            // Check the connections
            wasRemoved = true;

            while (wasRemoved)
            {
                wasRemoved = false;

                foreach (Connection connection in GetConnections())
                {
                    if (Match(conversationReferenceToRemove, connection.ConversationReference1) ||
                        Match(conversationReferenceToRemove, connection.ConversationReference2))
                    {
                        wasRemoved = true;
                        messageRouterResults.Add(Disconnect(connection)); // TODO: Check that the disconnect was successful
                        break;
                    }
                }
            }

            return(messageRouterResults);
        }