/// <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); }
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)); }
public void Reject() { if (_used) { return; } _used = true; Result = ConnectionRequestResult.Reject; _onUserAction(this); }
/// <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)); }
/// <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); }
/// <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); }
/// <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); }