public bool UpdateConversation(ConversationRequest conversationRequest) { if (conversationRequest.requestTime == null) { conversationRequest.requestTime = DateTime.Now; } var queueItem = new ConversationQueueItem { ConversationName = conversationRequest.name, RequestTime = conversationRequest.requestTime }; if (!ConversationTracker.requestQueue.Any(i => i.ConversationName == queueItem.ConversationName && i.RequestTime == queueItem.RequestTime)) { ConversationTracker.requestQueue.Enqueue(queueItem); } ConversationQueueItem peekedQueueItem; if (ConversationTracker.requestQueue.TryPeek(out peekedQueueItem)) { if (peekedQueueItem.ConversationName == queueItem.ConversationName && peekedQueueItem.RequestTime == queueItem.RequestTime) { var updated = updateDatabasesService.UpdateDatabases(conversationRequest); ConversationTracker.requestQueue.TryDequeue(out peekedQueueItem); return(updated); } CleanQueue(); } return(Task.Delay(queueDelay).ContinueWith((task) => { return UpdateConversation(conversationRequest); }).Result); }
private static void Conversational() { string s = string.Empty, conversationId = string.Empty, host = string.Empty; while (true) { Console.Write("> "); string input = Console.ReadLine(); var request = new ConversationRequest(input); if (!string.IsNullOrWhiteSpace(s)) { request.S = s; } if (!string.IsNullOrWhiteSpace(conversationId)) { request.Conversationid = conversationId; } if (!string.IsNullOrWhiteSpace(host)) { request.Host = host; } var result = service.Compute(request).GetAwaiter().GetResult(); s = result.S; conversationId = result.ConversationId; host = result.Host; Console.WriteLine(!string.IsNullOrWhiteSpace(result.Error) ? result.Error : result.Result); } }
public static bool IsHealthCheck(string requestBody, ILogger log) { bool isHealthCheck = false; ConversationRequest convReq = null; try { convReq = JsonConvert.DeserializeObject <ConversationRequest>(requestBody); } catch (Exception ex) { log.LogInformation(ex, "Web hook request is not a health check. Cannot deserialize request as a health check."); } var firstInput = convReq?.Inputs?.FirstOrDefault(x => (x.Intent?.Equals(INTENT_MAIN)).GetValueOrDefault(false)); if (firstInput != null) { var arg = firstInput.Arguments?.FirstOrDefault(x => (x.Name?.Equals("is_health_check")).GetValueOrDefault(false)); if (arg != null) { isHealthCheck = arg.BoolValue; } } return(isHealthCheck); }
public BaseResponse Create(ConversationRequest conversationRequest) { var isSaved = true; var conversation = Include(x => x.UserConversations).FirstOrDefault(x => x.UserConversations.Exists(uc => uc.UserId == conversationRequest.UserId) && x.UserConversations.Exists(uc => uc.UserId == conversationRequest.FriendId)); if (conversation == null) { conversation = Create(new Conversation(), out isSaved); _userConversationService.CreateMany(new[] { new UserConversation { ConversationId = conversation.Id, UserId = conversationRequest.UserId }, new UserConversation { ConversationId = conversation.Id, UserId = conversationRequest.FriendId } }, out isSaved); } if (!isSaved) { throw new InternalServerErrorException("Cannot create conversation between the 2 users"); } return(new BaseResponse(HttpStatusCode.OK, data: conversation.Id)); }
public bool UpdateDatabases(ConversationRequest conversationRequest) { if (_conversationService.ConversationLength(conversationRequest.name, conversationRequest.type) >= conversationRequest.responses.Count()) { return(false); } var conversation = new Conversation { name = conversationRequest.name, responses = conversationRequest.responses }; var analyzedConversation = _analyzationService.AnalyzeConversationAsync(conversation); var conversationUdpdated = _covnersationUpdateService.UpdateConversation(analyzedConversation, conversationRequest.type); AnalyzedChat previousChat = null; foreach (var analyziedChat in analyzedConversation.responses) { _userService.UpdateUsers(analyziedChat, previousChat); previousChat = analyziedChat; } return(conversationUdpdated); }
public ActionResult GetConversationResponse(ConversationRequest request = null) { Task <ConversationResponse> result = null; result = mailChimpManager.Conversations.GetResponseAsync(request); return(View(result.Result)); }
public ActionResult GetAllConversation(ConversationRequest request) { Task <IEnumerable <Conversation> > result = null; result = mailChimpManager.Conversations.GetAllAsync(request); return(View(result.Result)); }
public override void BeforeEachTest() { base.BeforeEachTest(); usersInConversation = new List <int> { DefaultUser.Id, 3 }; conversationRequest = new ConversationRequest(usersInConversation); }
public Activity RequestToActivity(ConversationRequest request) { var activity = new Activity(); var actionIntent = request.Inputs.FirstOrDefault(i => i.Intent.ToLowerInvariant().StartsWith("actions.intent"))?.Intent; switch (actionIntent?.ToLowerInvariant()) { case "actions.intent.permission": case "actions.intent.datetime": case "ask_for_sign_in_confirmation": case "actions.intent.place": case "actions.intent.confirmation": activity.Type = ActivityTypes.Event; activity = SetGeneralActivityProperties(activity, request); activity.Name = actionIntent; activity.Value = request; return(activity); case "actions.intent.sign_in": activity.Type = ActivityTypes.Event; activity = SetGeneralActivityProperties(activity, request); activity.Name = actionIntent; var signinStatusArgument = request.Inputs.First()?.Arguments?.Where(a => a.Name == "SIGN_IN").FirstOrDefault(); var argumentExtension = signinStatusArgument?.Extension; activity.Value = argumentExtension?["status"]; return(activity); case "actions.intent.option": activity.Type = ActivityTypes.Message; activity = SetGeneralActivityProperties(activity, request); activity.Text = StripInvocation(request.Inputs[0]?.RawInputs[0]?.Query, Options.ActionInvocationName); return(activity); } var text = StripInvocation(request.Inputs[0]?.RawInputs[0]?.Query, Options.ActionInvocationName); if (string.IsNullOrEmpty(text)) { activity.Type = ActivityTypes.ConversationUpdate; activity = SetGeneralActivityProperties(activity, request); activity.MembersAdded = new List <ChannelAccount>() { new ChannelAccount() { Id = activity.From?.Id ?? "anonymous" } }; return(activity); } activity.Type = ActivityTypes.Message; activity = SetGeneralActivityProperties(activity, request); activity.Text = text; return(activity); }
public bool Put([FromBody] ConversationRequest conversationRequest) { if (_requestValidationService.ValidRequest(conversationRequest)) { conversationRequest.requestTime = DateTime.Now; var result = _queueService.UpdateConversation(conversationRequest); return(result); } return(false); }
public async Task <IActionResult> CreateConversationAsync(ConversationRequest request) { //var currentUser = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value; //var user = await _userManager.FindByNameAsync(currentUser); //if (user != null) //{ // request.ParticipantIds.Add(user.Id); //} var result = await _conversationService.CreateConversationAsync(request); return(Ok(result)); }
/// <summary> /// The get all async. /// </summary> /// <param name="request"> /// The request. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref> /// <name>uriString</name> /// </paramref> /// is null. </exception> /// <exception cref="ArgumentOutOfRangeException">Enlarging the value of this instance would exceed <see cref="P:System.Text.StringBuilder.MaxCapacity" />. </exception> /// <exception cref="MailChimpException"> /// Custom Mail Chimp Exception /// </exception> /// <exception cref="UriFormatException">In the .NET for Windows Store apps or the Portable Class Library, catch the base class exception, <see cref="T:System.FormatException" />, instead.<paramref name="uriString" /> is empty.-or- The scheme specified in <paramref name="uriString" /> is not correctly formed. See <see cref="M:System.Uri.CheckSchemeName(System.String)" />.-or- <paramref name="uriString" /> contains too many slashes.-or- The password specified in <paramref name="uriString" /> is not valid.-or- The host name specified in <paramref name="uriString" /> is not valid.-or- The file name specified in <paramref name="uriString" /> is not valid. -or- The user name specified in <paramref name="uriString" /> is not valid.-or- The host or authority name specified in <paramref name="uriString" /> cannot be terminated by backslashes.-or- The port number specified in <paramref name="uriString" /> is not valid or cannot be parsed.-or- The length of <paramref name="uriString" /> exceeds 65519 characters.-or- The length of the scheme specified in <paramref name="uriString" /> exceeds 1023 characters.-or- There is an invalid character sequence in <paramref name="uriString" />.-or- The MS-DOS path specified in <paramref name="uriString" /> must start with c:\\.</exception> /// <exception cref="NotSupportedException"><paramref name="element" /> is not a constructor, method, property, event, type, or field. </exception> /// <exception cref="TypeLoadException">A custom attribute type cannot be loaded. </exception> public async Task <ConversationResponse> GetResponseAsync(ConversationRequest request = null) { using (var client = CreateMailClient("conversations")) { var response = await client.GetAsync(request?.ToQueryString()).ConfigureAwait(false); await response.EnsureSuccessMailChimpAsync().ConfigureAwait(false); var conversationResponse = await response.Content.ReadAsAsync <ConversationResponse>().ConfigureAwait(false); return(conversationResponse); } }
public async Task <IEnumerable <Conversation> > GetAllAsync(ConversationRequest request = null) { using (var client = CreateMailClient("conversations")) { var response = await client.GetAsync(request?.ToQueryString()); await response.EnsureSuccessMailChimpAsync(); var conversationResponse = await response.Content.ReadAsAsync <ConversationResponse>(); return(conversationResponse.Conversations); } }
public Activity SetGeneralActivityProperties(Activity activity, ConversationRequest request) { activity.DeliveryMode = DeliveryModes.ExpectReplies; activity.ChannelId = Options.ChannelId; activity.ServiceUrl = Options.ServiceUrl; activity.Recipient = new ChannelAccount("", "action"); activity.Conversation = new ConversationAccount(false, id: $"{request.Conversation.ConversationId}"); activity.From = new ChannelAccount(GetOrSetUserId(request)); activity.Id = Guid.NewGuid().ToString(); activity.Timestamp = DateTime.UtcNow; activity.Locale = request.User.Locale; activity.ChannelData = request; return(activity); }
public void DoesNotProcessConversationRequestIfThereAreDuplicateConversationUserIdsInRequest() { var usersToMakeInConversation = new List <int> { 1, 2, 3, 4, 1 }; var invalidConversationRequest = new ConversationRequest(usersToMakeInConversation); IEnumerable <Conversation> currentConversationsInRepository = ServiceRegistry.GetService <RepositoryManager>().GetRepository <Conversation>().GetAllEntities(); IEnumerable <Participation> currentParticipationsInRepository = ServiceRegistry.GetService <RepositoryManager>().GetRepository <Participation>().GetAllEntities(); var previousParticipationsInRepository = new List <Participation>(currentParticipationsInRepository); var previousConversationsInRepository = new List <Conversation>(currentConversationsInRepository); HandleMessage(invalidConversationRequest); Assert.AreEqual(previousConversationsInRepository, currentConversationsInRepository); Assert.AreEqual(previousParticipationsInRepository, currentParticipationsInRepository); }
private async void CreateConversation(UsersIdRequest request) { var connection = await this.apiService.CheckConnection(); if (!connection.IsSuccess) { await Application.Current.MainPage.DisplayAlert( Languages.Error, connection.Message, Languages.AcceptDisplay); return; } var conversation = new ConversationRequest { UserIdOne = request.UserFrom, UserIdTwo = request.UserTo, Date = DateTime.Now, RouteId = this.route.RouteId, ConnectionId = request.UserFrom + request.UserTo }; var url = Application.Current.Resources["APIMovilidad"].ToString(); var prefix = Application.Current.Resources["APIprefix"].ToString(); var controller = Application.Current.Resources["ConversationController"].ToString(); var response = await this.apiService.PostConversationAsync <Conversation>( url, prefix, controller, conversation, Settings.TokenType, Settings.AccessToken); if (!response.IsSuccess) { await Application.Current.MainPage.DisplayAlert( Languages.Error, response.Message, Languages.AcceptDisplay); return; } this.Conversation = (Conversation)response.Result; this.Messages = new ObservableCollection <MessageItemViewModel>(); this.MessagesRT = new ObservableCollection <ChatMessage>(); }
public async Task <ConversationViewModel> CreateConversationAsync(ConversationRequest request) { var conversation = new Models.Conversation() { Id = Guid.NewGuid() }; var result = new ConversationViewModel() { Id = conversation.Id, }; var currentUsername = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value; var currentUser = await _userManager.FindByNameAsync(currentUsername); if (!request.IsAutoCreate) { conversation.Name = request.Name; result.Name = request.Name; } else { var participant = await _userManager.FindByIdAsync(request.ParticipantIds.FirstOrDefault().ToString()); result.Name = $"{participant.FirstName} {participant.LastName}"; } _conversationRepository.Add(conversation); request.ParticipantIds.Add(currentUser.Id); foreach (var participantId in request.ParticipantIds) { var participant = new Participant() { Id = Guid.NewGuid(), ConversationId = conversation.Id, UserId = participantId }; _participantRepository.Add(participant); } await _unitOfWork.SaveChangeAsync(); return(result); }
public bool ValidRequest(ConversationRequest conversation) { if (conversation == null || conversation.responses == null || string.IsNullOrWhiteSpace(conversation.name) || string.IsNullOrWhiteSpace(conversation.type)) { return(false); } if (conversation.responses.Count == 0) { return(false); } foreach (var response in conversation.responses) { if (response?.chat == null || string.IsNullOrWhiteSpace(response.chat.message) || string.IsNullOrWhiteSpace(response.chat.user)) { return(false); } } return(true); }
public bool UpdateDatabases(ConversationRequest conversationRequest) { var conversation = new Conversation { name = conversationRequest.name, responses = conversationRequest.responses }; var analyzedConversation = analyzationService.AnalyzeConversation(conversation); var conversationUdpdated = covnersationUpdateService.UpdateConversation(analyzedConversation, conversationRequest.type); AnalyzedChat previousChat = null; foreach (var analyziedChat in analyzedConversation.responses) { userService.UpdateUsers(analyziedChat, previousChat); previousChat = analyziedChat; } return(conversationUdpdated); }
/// <summary> /// Makes a Conversational API request /// </summary> /// <param name="request"></param> /// <returns></returns> public async Task <ConversationResult> Compute(ConversationRequest request) { string baseUrl = ApiBaseUrl; if (!string.IsNullOrWhiteSpace(request?.Host)) { baseUrl = $"https://{request.Host}/api/"; } baseUrl += ConversationalApiUrl; string url = BuildUrl(baseUrl, request); using (var client = new HttpClient()) { var httpRequest = await client.GetAsync(url); var response = await httpRequest.Content.ReadAsStringAsync(); ConversationResult result = JsonConvert.DeserializeObject <ConversationResult>(response); return(result); } }
public async Task <IEnumerable <Conversation> > GetAllAsync(ConversationRequest request = null) { try { using (var client = CreateMailClient("conversations")) { var response = await client.GetAsync(request?.ToQueryString()); response.EnsureSuccessStatusCode(); var conversationResponse = await response.Content.ReadAsAsync <ConversationResponse>(); return(conversationResponse.Conversations); } } catch (Exception ex) { } return(null); }
public async Task groupsGetMembers(IOutgoingMessage message) { try { var tmessage = (OutgoingMessage)message; var request = new ConversationRequest { offset = 0, count = 10, filter = "managers", //fields = group_id = _options.groupId, //major_sort_id = }; await vkService.sendRequest(request, "groups.getMembers", _options); } catch (Exception e) { _logger.Log(NLog.LogLevel.Error, e, "SendMessageAsync error"); } }
public static string GetOrSetUserId(ConversationRequest request) { if (request.User.UserVerificationStatus != "VERIFIED") { request.User.UserStorage = request.Conversation.ConversationId; return(request.Conversation.ConversationId); } if (!string.IsNullOrEmpty(request.User.UserStorage?.ToString())) { Guid.TryParse(request.User.UserStorage.ToString(), out Guid currentUserId); if (currentUserId != Guid.Empty) { return(currentUserId.ToString()); } } var newUserId = Guid.NewGuid(); request.User.UserStorage = newUserId; return(newUserId.ToString()); }
public ConversationWebhookResponse ActivityToResponse(Activity activity, ConversationRequest request) { var response = new ConversationWebhookResponse { UserStorage = request.User.UserStorage }; // Send default empty response if no activity or invalid activity type sent if (activity == null || activity.Type != ActivityTypes.Message) { response.ExpectUserResponse = false; return(response); } _attachmentConverter.ConvertAttachments(activity); // Grab any adaptive card attachment to get fallback speak property var adaptiveCardAttachment = activity.Attachments.FirstOrDefault(a => a.ContentType == AdaptiveCard.ContentType)?.Content as AdaptiveCard; var simpleResponse = new SimpleResponse { Content = new SimpleResponseContent { DisplayText = activity.Text, Ssml = (activity.Speak ?? adaptiveCardAttachment?.Speak), TextToSpeech = activity.Speak == null && adaptiveCardAttachment?.Speak == null ? activity.Text : null } }; var processedIntentStatus = ProcessHelperIntentAttachments(activity); // If we have a system intent to send - send it - with or without additional simple prompt if (processedIntentStatus.Intent != null) { response.ExpectUserResponse = true; response.ExpectedInputs = new ExpectedInput[] { new ExpectedInput() { PossibleIntents = new SystemIntent[] { processedIntentStatus.Intent }, InputPrompt = processedIntentStatus.AllowAdditionalInputPrompt ? new InputPrompt() { RichInitialPrompt = new RichResponse() { Items = new ResponseItem[] { simpleResponse } } } : null } }; return(response); } ; // We haven't sent a response using a SystemIntent, so send simple response // plus any card activities var responseItems = new List <ResponseItem> { simpleResponse }; responseItems.AddRange(GetResponseItemsFromActivityAttachments(activity)); // ensure InputHint is set as required for response if (activity.InputHint == null || activity.InputHint == InputHints.AcceptingInput) { activity.InputHint = Options.ShouldEndSessionByDefault ? InputHints.IgnoringInput : InputHints.ExpectingInput; } // check if we should be listening for more input from the user switch (activity.InputHint) { case InputHints.IgnoringInput: response.ExpectUserResponse = false; response.FinalResponse = new FinalResponse() { RichResponse = new RichResponse() { Items = responseItems.ToArray() } }; break; case InputHints.ExpectingInput: response.ExpectUserResponse = true; response.ExpectedInputs = new ExpectedInput[] { new ExpectedInput() { PossibleIntents = new SystemIntent[] { new TextIntent(), }, InputPrompt = new InputPrompt() { RichInitialPrompt = new RichResponse() { Items = responseItems.ToArray() } } } }; response.ExpectedInputs.First().InputPrompt.RichInitialPrompt.Suggestions = ConvertIMAndMessageBackSuggestedActionsToSuggestionChips(activity)?.ToArray(); response.ExpectedInputs.First().InputPrompt.RichInitialPrompt.LinkOutSuggestion = GetLinkOutSuggestionFromActivity(activity); break; } return(response); }
public async Task <Paged <Conversation> > ListConversationsForCustomer(int mailboxId, int customerId, ConversationRequest requestArg = null) { string endpoint = string.Format("mailboxes/{0}/customers/{1}/conversations.json", mailboxId, customerId); return(await Get <Paged <Conversation> >(endpoint, requestArg)); }
/// <summary> /// Waits until the profile server receives a conversation request message of certain type. /// </summary> /// <param name="Role">Specifies the role of the server to which the message had to arrive to be accepted by this wait function.</param> /// <param name="RequestType">Type of the conversation request to wait for.</param> /// <param name="ClearMessageList">If set to true, the message list will be cleared once the wait is finished.</param> /// <returns>Message the profile server received.</returns> public async Task <IncomingServerMessage> WaitForConversationRequest(ServerRole Role, ConversationRequest.RequestTypeOneofCase RequestType, bool ClearMessageList = true) { log.Trace("()"); IncomingServerMessage res = null; bool done = false; while (!done) { lock (messageListLock) { foreach (IncomingServerMessage ism in messageList) { if (!Role.HasFlag(ism.Role)) { continue; } Message message = ism.IncomingMessage; if (message.MessageTypeCase != Message.MessageTypeOneofCase.Request) { continue; } Request request = message.Request; if (request.ConversationTypeCase != Request.ConversationTypeOneofCase.ConversationRequest) { continue; } ConversationRequest conversationRequest = request.ConversationRequest; if (conversationRequest.RequestTypeCase != RequestType) { continue; } res = ism; done = true; break; } if (done && ClearMessageList) { messageList.Clear(); } } if (!done) { try { await Task.Delay(1000, shutdownCancellationTokenSource.Token); } catch { } } } log.Trace("(-)"); return(res); }
public async Task <Response> PostConversationAsync <T>(string urlBase, string prefix, string controller, ConversationRequest model, string tokenType, string accessToken) { try { var request = JsonConvert.SerializeObject(model); var content = new StringContent(request, Encoding.UTF8, "application/json"); var client = new HttpClient { BaseAddress = new Uri(urlBase) }; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken); var url = $"{prefix}{controller}"; var response = await client.PostAsync(url, content); var answer = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { return(new Response { IsSuccess = false, Message = answer, }); } var obj = JsonConvert.DeserializeObject <T>(answer); return(new Response { IsSuccess = true, Result = obj, }); } catch (Exception ex) { return(new Response { IsSuccess = false, Message = ex.Message, }); } }
/// <summary> /// The get all async. /// </summary> /// <param name="request"> /// The request. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref> /// <name>uriString</name> /// </paramref> /// is null. </exception> /// <exception cref="ArgumentOutOfRangeException">Enlarging the value of this instance would exceed <see cref="P:System.Text.StringBuilder.MaxCapacity" />. </exception> /// <exception cref="MailChimpException"> /// Custom Mail Chimp Exception /// </exception> /// <exception cref="UriFormatException">In the .NET for Windows Store apps or the Portable Class Library, catch the base class exception, <see cref="T:System.FormatException" />, instead.<paramref name="uriString" /> is empty.-or- The scheme specified in <paramref name="uriString" /> is not correctly formed. See <see cref="M:System.Uri.CheckSchemeName(System.String)" />.-or- <paramref name="uriString" /> contains too many slashes.-or- The password specified in <paramref name="uriString" /> is not valid.-or- The host name specified in <paramref name="uriString" /> is not valid.-or- The file name specified in <paramref name="uriString" /> is not valid. -or- The user name specified in <paramref name="uriString" /> is not valid.-or- The host or authority name specified in <paramref name="uriString" /> cannot be terminated by backslashes.-or- The port number specified in <paramref name="uriString" /> is not valid or cannot be parsed.-or- The length of <paramref name="uriString" /> exceeds 65519 characters.-or- The length of the scheme specified in <paramref name="uriString" /> exceeds 1023 characters.-or- There is an invalid character sequence in <paramref name="uriString" />.-or- The MS-DOS path specified in <paramref name="uriString" /> must start with c:\\.</exception> /// <exception cref="NotSupportedException"><paramref name="element" /> is not a constructor, method, property, event, type, or field. </exception> /// <exception cref="TypeLoadException">A custom attribute type cannot be loaded. </exception> public async Task <IEnumerable <Conversation> > GetAllAsync(ConversationRequest request = null) { return((await GetResponseAsync(request).ConfigureAwait(false))?.Conversations); }
public async Task <ActionResult <ObservableCollection <MessageModel> > > GetByConversationIdAsync([FromBody, Required] ConversationRequest conversationRequest) { if (!ModelState.IsValid) { return(BadRequest()); } var login = HttpContext.User.Identity.Name; var userAuth = await _authService.GetActiveUserByLoginAsNoTrackingAsync(login); if (userAuth == null || userAuth.IsBanned) { throw new ValidationException(_stringLocalizer["UserIsDeletedOrBanned"]); } if (userAuth.ForceRelogin) { throw new UnauthorizedException(string.Empty); } // var trip = await _tripService.GetByIdAsync(conversationRequest.TripId); // if (trip != null && trip.UserId == userAuth.UserId) // throw new ValidationException(Messages.UserCannotWriteToYourself); return(await _messageService.GetByConversationIdAsync(conversationRequest.Guid, userAuth.UserId)); }
/// <summary> /// Processing of a message received from a client. /// </summary> /// <param name="Client">TCP client who send the message.</param> /// <param name="IncomingMessage">Full ProtoBuf message to be processed.</param> /// <returns>true if the conversation with the client should continue, false if a protocol violation error occurred and the client should be disconnected.</returns> public async Task <bool> ProcessMessageAsync(ClientBase Client, IProtocolMessage IncomingMessage) { IncomingClient client = (IncomingClient)Client; ProxProtocolMessage incomingMessage = (ProxProtocolMessage)IncomingMessage; ProxMessageBuilder messageBuilder = client.MessageBuilder; bool res = false; log.Debug("()"); try { // Update time until this client's connection is considered inactive. client.NextKeepAliveTime = DateTime.UtcNow.AddMilliseconds(client.KeepAliveIntervalMs); log.Trace("Client ID {0} NextKeepAliveTime updated to {1}.", client.Id.ToHex(), client.NextKeepAliveTime.ToString("yyyy-MM-dd HH:mm:ss")); log.Trace("Received message type is {0}, message ID is {1}.", incomingMessage.MessageTypeCase, incomingMessage.Id); switch (incomingMessage.MessageTypeCase) { case Message.MessageTypeOneofCase.Request: { ProxProtocolMessage responseMessage = messageBuilder.CreateErrorProtocolViolationResponse(incomingMessage); Request request = incomingMessage.Request; log.Trace("Request conversation type is {0}.", request.ConversationTypeCase); switch (request.ConversationTypeCase) { case Request.ConversationTypeOneofCase.SingleRequest: { SingleRequest singleRequest = request.SingleRequest; SemVer version = new SemVer(singleRequest.Version); log.Trace("Single request type is {0}, version is {1}.", singleRequest.RequestTypeCase, version); if (!version.IsValid()) { responseMessage.Response.Details = "version"; break; } switch (singleRequest.RequestTypeCase) { case SingleRequest.RequestTypeOneofCase.Ping: responseMessage = ProcessMessagePingRequest(client, incomingMessage); break; case SingleRequest.RequestTypeOneofCase.ListRoles: responseMessage = ProcessMessageListRolesRequest(client, incomingMessage); break; default: log.Warn("Invalid request type '{0}'.", singleRequest.RequestTypeCase); break; } break; } case Request.ConversationTypeOneofCase.ConversationRequest: { ConversationRequest conversationRequest = request.ConversationRequest; log.Trace("Conversation request type is {0}.", conversationRequest.RequestTypeCase); if (conversationRequest.Signature.Length > 0) { log.Trace("Conversation signature is '{0}'.", conversationRequest.Signature.ToByteArray().ToHex()); } else { log.Trace("No signature provided."); } switch (conversationRequest.RequestTypeCase) { case ConversationRequest.RequestTypeOneofCase.Start: responseMessage = ProcessMessageStartConversationRequest(client, incomingMessage); break; case ConversationRequest.RequestTypeOneofCase.VerifyIdentity: responseMessage = ProcessMessageVerifyIdentityRequest(client, incomingMessage); break; default: log.Warn("Invalid request type '{0}'.", conversationRequest.RequestTypeCase); // Connection will be closed in ReceiveMessageLoop. break; } break; } default: log.Error("Unknown conversation type '{0}'.", request.ConversationTypeCase); // Connection will be closed in ReceiveMessageLoop. break; } if (responseMessage != null) { // Send response to client. res = await client.SendMessageAsync(responseMessage); if (res) { // If the message was sent successfully to the target, we close the connection in case it was a protocol violation error response. if (responseMessage.MessageTypeCase == Message.MessageTypeOneofCase.Response) { res = responseMessage.Response.Status != Status.ErrorProtocolViolation; } } } else { // If there is no response to send immediately to the client, // we want to keep the connection open. res = true; } break; } case Message.MessageTypeOneofCase.Response: { Response response = incomingMessage.Response; log.Trace("Response status is {0}, details are '{1}', conversation type is {2}.", response.Status, response.Details, response.ConversationTypeCase); // Find associated request. If it does not exist, disconnect the client as it // send a response without receiving a request. This is protocol violation, // but as this is a reponse, we have no how to inform the client about it, // so we just disconnect it. UnfinishedRequest unfinishedRequest = client.GetAndRemoveUnfinishedRequest(incomingMessage.Id); if ((unfinishedRequest != null) && (unfinishedRequest.RequestMessage != null)) { ProxProtocolMessage requestMessage = (ProxProtocolMessage)unfinishedRequest.RequestMessage; Request request = requestMessage.Request; // We now check whether the response message type corresponds with the request type. // This is only valid if the status is Ok. If the message types do not match, we disconnect // for the protocol violation again. bool typeMatch = false; bool isErrorResponse = response.Status != Status.Ok; if (!isErrorResponse) { if (response.ConversationTypeCase == Response.ConversationTypeOneofCase.SingleResponse) { typeMatch = (request.ConversationTypeCase == Request.ConversationTypeOneofCase.SingleRequest) && ((int)response.SingleResponse.ResponseTypeCase == (int)request.SingleRequest.RequestTypeCase); } else { typeMatch = (request.ConversationTypeCase == Request.ConversationTypeOneofCase.ConversationRequest) && ((int)response.ConversationResponse.ResponseTypeCase == (int)request.ConversationRequest.RequestTypeCase); } } else { typeMatch = true; } if (typeMatch) { // Now we know the types match, so we can rely on request type even if response is just an error. switch (request.ConversationTypeCase) { case Request.ConversationTypeOneofCase.SingleRequest: { SingleRequest singleRequest = request.SingleRequest; switch (singleRequest.RequestTypeCase) { default: log.Warn("Invalid conversation type '{0}' of the corresponding request.", request.ConversationTypeCase); // Connection will be closed in ReceiveMessageLoop. break; } break; } case Request.ConversationTypeOneofCase.ConversationRequest: { ConversationRequest conversationRequest = request.ConversationRequest; switch (conversationRequest.RequestTypeCase) { default: log.Warn("Invalid type '{0}' of the corresponding request.", conversationRequest.RequestTypeCase); // Connection will be closed in ReceiveMessageLoop. break; } break; } default: log.Error("Unknown conversation type '{0}' of the corresponding request.", request.ConversationTypeCase); // Connection will be closed in ReceiveMessageLoop. break; } } else { log.Warn("Message type of the response ID {0} does not match the message type of the request ID {1}, the connection will be closed.", incomingMessage.Id, unfinishedRequest.RequestMessage.Id); // Connection will be closed in ReceiveMessageLoop. } } else { log.Warn("No unfinished request found for incoming response ID {0}, the connection will be closed.", incomingMessage.Id); // Connection will be closed in ReceiveMessageLoop. } break; } default: log.Error("Unknown message type '{0}', connection to the client will be closed.", incomingMessage.MessageTypeCase); await SendProtocolViolation(client); // Connection will be closed in ReceiveMessageLoop. break; } } catch (Exception e) { log.Error("Exception occurred, connection to the client will be closed: {0}", e.ToString()); await SendProtocolViolation(client); // Connection will be closed in ReceiveMessageLoop. } if (res && client.ForceDisconnect) { log.Debug("Connection to the client will be forcefully closed."); res = false; } log.Debug("(-):{0}", res); return(res); }