public async Task <HttpResponseMessage> OnInboundMessageReceived(string connectorName, HttpRequestMessage request, CancellationToken cancellationToken) { try { var metadata = await this.credentialManager.GetMetadata(connectorName); if (metadata != null) { InboundAgent agent = null; try { agent = new InboundAgent(metadata.ConnectorUri); // Get credential var connectorId = await agent.ParseConnectorIdFromInboundMessageAsync(request, cancellationToken); if (string.IsNullOrEmpty(connectorId)) { SmsProviderEventSource.Current.Warning(SmsProviderEventSource.EmptyTrackingId, this, nameof(OnInboundMessageReceived), OperationStates.FailedMatch, $"Failed to get connector key for '{connectorName}'."); return(request.CreateResponse(HttpStatusCode.Unauthorized)); } var identifier = new ConnectorIdentifier(connectorName, connectorId); SmsConnectorCredential credential = null; try { credential = await this.credentialManager.GetConnectorCredentialByIdAsync(identifier); } catch { SmsProviderEventSource.Current.Warning(SmsProviderEventSource.EmptyTrackingId, this, nameof(OnInboundMessageReceived), OperationStates.FailedMatch, $"Failed to get credential for {identifier}."); return(request.CreateResponse(HttpStatusCode.Unauthorized)); } // Parse and save messages var result = await agent.ParseInboundRequestAsync(request, credential.ToDataContract(metadata), cancellationToken); SmsProviderEventSource.Current.Info(SmsProviderEventSource.EmptyTrackingId, this, nameof(OnInboundMessageReceived), OperationStates.InProgress, $"Complete parsing code={result.Response.HttpStatusCode} message={result.Messages?.Count ?? 0}"); if (result.Type == InboundType.MoMessage) { await SaveMoMessageAsync(result.Messages, agent, cancellationToken); } else if (result.Type == InboundType.Report) { var saveResult = await SaveReportMessageAsync(result.Messages, identifier); if (!saveResult) { result.Response.HttpStatusCode = (int)HttpStatusCode.InternalServerError; } } SmsProviderEventSource.Current.Info(SmsProviderEventSource.EmptyTrackingId, this, nameof(OnInboundMessageReceived), OperationStates.Succeeded, $"Complete parsing code={result.Response.HttpStatusCode} message={result.Messages?.Count ?? 0}"); return(result.Response.ToHttpResponseMessage()); } finally { if (agent != null) { agent.Dispose(); } } } SmsProviderEventSource.Current.Warning(SmsProviderEventSource.EmptyTrackingId, this, nameof(OnInboundMessageReceived), OperationStates.FailedMatch, $"Inbound message received from invalid connector '{connectorName}'."); return(request.CreateResponse(HttpStatusCode.Forbidden)); } catch (Exception ex) { SmsProviderEventSource.Current.ErrorException(SmsProviderEventSource.EmptyTrackingId, this, nameof(this.OnInboundMessageReceived), OperationStates.Failed, "Failed to process inbound message", ex); return(request.CreateResponse(HttpStatusCode.InternalServerError)); } }
private async Task SaveMoMessageAsync(Dictionary <ConnectorIdentifier, List <InboundMessage> > messages, InboundAgent agent, CancellationToken cancellationToken) { if (messages == null || messages.Count <= 0) { return; } foreach (var kv in messages) { var sharedAccounts = await this.credentialManager.ListCredentialAssignmentsById(kv.Key, true); if (sharedAccounts == null || sharedAccounts.Count <= 0) { continue; } var groups = kv.Value.Where(v => v.MoMessage != null).GroupBy(m => m.MoMessage.ExtendedCode); foreach (var group in groups) { var extended = group.Key; var segments = await agent.ParseExtendedCodeAsync(extended, Constants.ExtendedCodeSegmentLengths, cancellationToken); if (segments != null && segments.Count != 3) { SmsProviderEventSource.Current.Error(SmsProviderEventSource.EmptyTrackingId, this, nameof(this.SaveMoMessageAsync), OperationStates.Dropped, $"Dropped the message as connector parsing extended code error with segment={segments.Count}."); continue; } var accountCode = segments?[0]; var sigCode = segments?[1]; var customCode = segments?[2]; ConnectorCredentialAssignment account = null; // case #1: credential is not shared by multiple accounts if ((segments == null || string.IsNullOrEmpty(accountCode)) && sharedAccounts.Count == 1) { account = sharedAccounts.SingleOrDefault(); } // case #2: credentials are shared between accounts else if (!string.IsNullOrEmpty(accountCode) && !string.IsNullOrEmpty(sigCode)) { account = sharedAccounts.SingleOrDefault(a => a.ExtendedCode.Equals(accountCode, StringComparison.OrdinalIgnoreCase)); } if (account != null) { Signature signature = null; if (!string.IsNullOrEmpty(sigCode)) { var signatureList = await this.store.ListSignaturesAsync(account.EngagementAccount, new Common.Pagination.DbContinuationToken(null), -1); signature = signatureList?.Signatures?.SingleOrDefault(s => s.ExtendedCode.Equals(sigCode)); } else { signature = new Signature { EngagementAccount = account.EngagementAccount, Value = null }; } if (signature != null) { await this.telemetryManager.InsertInboundMessagesAsync(signature, group.ToList(), customCode); continue; } } SmsProviderEventSource.Current.Warning(SmsProviderEventSource.EmptyTrackingId, this, nameof(this.SaveMoMessageAsync), OperationStates.Dropped, $"Dropped the message as we cannot find the owner. connector={kv.Key} extended={extended}"); } } }