private async Task WriteRunningModuleEntryAsync(
            ModuleIdentifier module,
            EndPointAddress endPoint,
            ICollection <ReadOnlyMemory <char> > prefixes,
            Session session,
            CancellationToken cancellation)
        {
            var path = GetRunningModulePath(module, session);

            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write(endPoint);
                    writer.Write(prefixes.Count());

                    foreach (var prefix in prefixes)
                    {
                        WritePrefix(writer, prefix);
                    }
                }

                var payload = stream.ToArray();
                await _coordinationManager.GetOrCreateAsync(path, payload, EntryCreationModes.Ephemeral, cancellation);
            }
        }
        private static bool IsCategoryValidV2(string category)
        {
            //Test V2 API
            //It may take a while until the category is loaded on server
            bool returnvalue = true;

            for (int i = 0; i < 3; i++)
            {
                try
                {
                    string headerValue = GetHeaderValue();
                    var    bind        = new BasicHttpBinding {
                        Name = "BasicHttpBinding_LanguageService"
                    };
                    var epa = new EndpointAddress(EndPointAddress.Replace("https", "http") + "/V2/soap.svc");
                    LanguageServiceClient client = new LanguageServiceClient(bind, epa);
                    client.Translate(headerValue, "Test", "en", "fr", "text/plain", category, string.Empty);
                    returnvalue = true;
                    break;
                }
                catch (Exception e)
                {
                    string error = e.Message;
                    returnvalue = false;
                    Thread.Sleep(1000);
                    continue;
                }
            }
            return(returnvalue);
        }
Exemple #3
0
 public SerializedMessageHandlerProxy(ClientManager owner, EndPointAddress endPoint)
 {
     Assert(owner != null);
     Assert(endPoint != default);
     _owner    = owner;
     _endPoint = endPoint;
 }
        private async Task <(EndPointAddress endPoint, string securityToken)> AddClientCoreAsync(CancellationToken cancellation)
        {
            var now                     = _dateTimeProvider.GetCurrentTime();
            var securityToken           = Guid.NewGuid().ToString();
            var leaseEnd                = now + Timeout;
            var securityTokenBytesCount = Encoding.UTF8.GetByteCount(securityToken);

            using (ArrayPool <byte> .Shared.Rent(8 + 4 + securityTokenBytesCount, out var bytes))
            {
                var payloadLength = EncodePayload(bytes, securityToken.AsSpan(), leaseEnd);
                var payload       = bytes.AsMemory().Slice(start: 0, payloadLength);

                EndPointAddress endPoint;
                do
                {
                    endPoint = AllocateEndPointAddress();
                    var path = GetPath(endPoint);

                    try
                    {
                        await _coordinationManager.CreateAsync(path, payload, cancellation : cancellation);

                        _logger?.LogDebug($"Assigning end-point '{endPoint.ToString()}' to recently connected client.");

                        break;
                    }
                    catch (DuplicateEntryException) // TODO: Add a TryCreateAsync method to the coordination service.
                    {
                        continue;
                    }
                }while (cancellation.ThrowOrContinue());

                return(endPoint, securityToken);
            }
        }
 public AckLookupEntry(int seqNum, EndPointAddress endPoint, ReadOnlyMemory <byte> bytes, TaskCompletionSource <object> ackSource)
 {
     SeqNum    = seqNum;
     EndPoint  = endPoint;
     Bytes     = bytes;
     AckSource = ackSource;
 }
        public async ValueTask <IMessage> RouteAsync(
            Route route,
            IMessage serializedMessage,
            bool publish,
            EndPointAddress endPoint,
            CancellationToken cancellation)
        {
            if (route == null)
            {
                throw new ArgumentNullException(nameof(route));
            }

            if (serializedMessage == null)
            {
                throw new ArgumentNullException(nameof(serializedMessage));
            }

            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            var idx = serializedMessage.FrameIndex;

            using (CheckDisposal(ref cancellation, out var disposal))
            {
                try
                {
                    try
                    {
                        EncodeRouteRequest(serializedMessage, route, publish, endPoint);

                        var response = await SendInternalAsync(serializedMessage, cancellation);

                        return(response);
                    }
                    catch
                    {
                        Assert(serializedMessage.FrameIndex >= idx);

                        while (serializedMessage.FrameIndex > idx)
                        {
                            serializedMessage.PopFrame();
                        }

                        throw;
                    }
                }
                catch (OperationCanceledException) when(disposal.IsCancellationRequested)
                {
                    throw new ObjectDisposedException(GetType().FullName);
                }
            }
        }
Exemple #7
0
        private static DebugModuleProperties Decode(ReadOnlySpan <byte> memory)
        {
            var reader       = new BinarySpanReader(memory, ByteOrder.LittleEndian);
            var endPoint     = new EndPointAddress(reader.Read().ToArray()); // TODO: This copies
            var module       = new ModuleIdentifier(reader.ReadString());
            var major        = reader.ReadInt32();
            var minor        = reader.ReadInt32();
            var revision     = reader.ReadInt32();
            var isPreRelease = reader.ReadBool();
            var version      = new ModuleVersion(major, minor, revision, isPreRelease);

            return(new DebugModuleProperties(endPoint, module, version));
        }
 public async Task <bool> ValidateClientAsync(EndPointAddress endPoint, string securityToken, CancellationToken cancellation)
 {
     using (CheckDisposal(ref cancellation, out var disposal))
     {
         try
         {
             return(await ValidateClientCoreAsync(endPoint, securityToken, cancellation));
         }
         catch (OperationCanceledException) when(disposal.IsCancellationRequested)
         {
             throw new ObjectDisposedException(GetType().FullName);
         }
     }
 }
 public DecodedMessage(MessageType messageType,
                       bool handled,
                       int seqNum,
                       int corr,
                       EndPointAddress txEndPoint,
                       EndPointAddress rxEndPoint)
 {
     MessageType = messageType;
     Handled     = handled;
     SeqNum      = seqNum;
     Corr        = corr;
     TxEndPoint  = txEndPoint;
     RxEndPoint  = rxEndPoint;
 }
        public LogicalEndPointSkeleton(IEndPointManager endPointManager, EndPointAddress endPoint)
        {
            if (endPointManager == null)
            {
                throw new ArgumentNullException(nameof(endPointManager));
            }

            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            _endPointManager = endPointManager;

            _logicalEndPoint = _endPointManager.CreateLogicalEndPoint(endPoint);
        }
        public async Task AddModuleAsync(ModuleIdentifier module, EndPointAddress endPoint, IEnumerable <ReadOnlyMemory <char> > prefixes, CancellationToken cancellation)
        {
            if (module == default)
            {
                throw new ArgumentDefaultException(nameof(module));
            }

            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            if (prefixes == null)
            {
                throw new ArgumentNullException(nameof(prefixes));
            }

            if (!prefixes.Any())
            {
                throw new ArgumentException("The collection must not be empty.", nameof(prefixes));
            }

            if (prefixes.Any(prefix => prefix.Span.IsEmptyOrWhiteSpace()))
            {
                throw new ArgumentException("The collection must not contain null entries or entries that are empty or contain whitespace only.", nameof(prefixes));
            }

            var prefixCollection = (prefixes as ICollection <ReadOnlyMemory <char> >) ?? prefixes.ToList();
            var session          = await _coordinationManager.GetSessionAsync(cancellation);

            var tasks = new List <Task>(capacity: prefixCollection.Count());

            foreach (var prefix in prefixCollection)
            {
                tasks.Add(WriteModulePrefixEntryAsync(prefix, endPoint, session, cancellation));
            }

            await Task.WhenAll(tasks);

            await WriteRunningModuleEntryAsync(module, endPoint, prefixCollection, session, cancellation);

            // TODO: When cancelled, alls completed operations should be reverted.
            // TODO: The RemoveModuleAsync alogrithm assumes that there are no prefix entries, if the running module entry is not present. We should reflect this assumtion here.
        }
        /// <summary>
        /// Call once to initialize the static variables
        /// </summary>
        public static void Initialize()
        {
            LoadCredentials();

            //Inspect the given Azure Key to see if this is host with appid auth
            string[] AuthComponents = _AzureKey.Split('?');
            if (AuthComponents.Length > 1)
            {
                EndPointAddress = AuthComponents[0];
                string[] appidComponents = AuthComponents[1].ToLowerInvariant().Split('=');
                if (appidComponents[0] == "appid")
                {
                    authMode = AuthMode.AppId;
                    appid    = appidComponents[1];
                }
                else
                {
                    return;
                }
            }
            try { if (!IsTranslationServiceReady())
                  {
                      return;
                  }
            }
            catch { return; }
            var bind = new BasicHttpBinding {
                Name = "BasicHttpBinding_LanguageService"
            };
            var epa = new EndpointAddress(EndPointAddress.Replace("https:", "http:") + "/V2/soap.svc");   //for some reason GetLanguagesForTranslate doesn't work with SSL.
            LanguageServiceClient client = new LanguageServiceClient(bind, epa);
            string headerValue           = GetHeaderValue();

            string[] languages     = client.GetLanguagesForTranslate(headerValue);
            string[] languagenames = client.GetLanguageNames(headerValue, Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName, languages, false);
            for (int i = 0; i < languages.Length; i++)
            {
                if (!AvailableLanguages.ContainsKey(languages[i]))
                {
                    AvailableLanguages.Add(languages[i], languagenames[i]);
                }
            }
            client.Close();
        }
        //public async Task<bool> DisconnectAsync(EndPointAddress endPoint, string securityToken, CancellationToken cancellation)

        // TODO: WaitForDisconnectAsync must return a completed task, if the client is not connected at the time of call.
        public async Task WaitForDisconnectAsync(EndPointAddress endPoint, CancellationToken cancellation)
        {
            using (CheckDisposal(ref cancellation, out var disposal))
            {
                try
                {
                    async Task BuildClientDisconnectCacheEntry()
                    {
                        try
                        {
                            // Yields back the task, that represents the asnyc state machine immediately to leave the critical section as fast as possible.
                            await Task.Yield();
                            await WaitForDisconnectCoreAsync(endPoint);
                        }
                        finally
                        {
                            lock (_lock)
                            {
                                _clientDisconnectCache.Remove(endPoint);
                            }
                        }
                    }

                    Task task;

                    lock (_lock)
                    {
                        if (!_clientDisconnectCache.TryGetValue(endPoint, out task))
                        {
                            task = BuildClientDisconnectCacheEntry();
                            _clientDisconnectCache.Add(endPoint, task);
                        }
                    }

                    await task.WithCancellation(cancellation);
                }
                catch (OperationCanceledException) when(disposal.IsCancellationRequested)
                {
                    throw new ObjectDisposedException(GetType().FullName);
                }
            }
        }
        /// <summary>
        /// Check if the Translation service is ready to use, with a valid client ID and secret
        /// </summary>
        /// <returns>true if ready, false if not</returns>
        public static bool IsTranslationServiceReady()
        {
            switch (authMode)
            {
            case AuthMode.Azure:
                try
                {
                    AzureAuthToken authTokenSource = new AzureAuthToken(_AzureKey);
                    string         headerValue     = authTokenSource.GetAccessToken();
                    var            bind            = new BasicHttpBinding {
                        Name = "BasicHttpBinding_LanguageService"
                    };
                    var epa = new EndpointAddress(EndPointAddress.Replace("https:", "http:") + "/V2/soap.svc");
                    LanguageServiceClient client = new LanguageServiceClient(bind, epa);
                    string[] languages           = new string[1];
                    languages[0] = "en";
                    client.GetLanguageNames(GetHeaderValue(), Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName, languages, false);
                }
                catch { return(false); }
                break;

            case AuthMode.AppId:
                try
                {
                    var bind = new BasicHttpBinding {
                        Name = "BasicHttpBinding_LanguageService"
                    };
                    var epa = new EndpointAddress(EndPointAddress.Replace("https:", "http:") + "/V2/soap.svc");
                    LanguageServiceClient client = new LanguageServiceClient(bind, epa);
                    string[] languages           = new string[1];
                    languages[0] = "en";
                    client.GetLanguageNames(GetHeaderValue(), Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName, languages, false);
                }
                catch { return(false); }
                break;

            default:
                return(false);
            }
            return(true);
        }
        public DebugLogicalEndPoint(DebugConnection debugConnection, EndPointAddress endPoint, ILogger <DebugLogicalEndPoint> logger = null)
        {
            if (debugConnection == null)
            {
                throw new ArgumentNullException(nameof(debugConnection));
            }

            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            _debugConnection = debugConnection;
            EndPoint         = endPoint;
            _logger          = logger;

            _proxyLazy = new DisposableAsyncLazy <IProxy <LogicalEndPointSkeleton> >(
                factory: CreateProxyAsync,
                disposal: p => p.DisposeAsync(),
                options: DisposableAsyncLazyOptions.Autostart | DisposableAsyncLazyOptions.ExecuteOnCallingThread);
        }
        public async Task <byte[]> SendAsync(byte[] messageBuffer, EndPointAddress remoteEndPoint, CancellationToken cancellation = default)
        {
            var message = new Message();

            using (var stream = new MemoryStream(messageBuffer))
            {
                await message.ReadAsync(stream, cancellation);
            }

            var(response, handled) = await _logicalEndPoint.SendAsync(message, remoteEndPoint, cancellation);

            response.Trim();

            using (var stream = response.PushFrame().OpenStream())
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write(handled);
                }

            return(response.ToArray());
        }
        private async Task WriteModulePrefixEntryAsync(ReadOnlyMemory <char> prefix, EndPointAddress endPoint, Session session, CancellationToken cancellation)
        {
            var normalizedPrefix = NormalizePrefix(prefix);

            if (normalizedPrefix.Span[0] == '_')
            {
                throw new ArgumentException("A prefix must not begin with an underscore.");
            }

            var path = GetPrefixPath(normalizedPrefix, endPoint, session, normalize: false);

            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write(endPoint);
                }

                var payload = stream.ToArray();
                var entry   = await _coordinationManager.GetOrCreateAsync(path, payload, EntryCreationModes.Ephemeral, cancellation);
            }
        }
        // This does not receive a cancellation token, as the result of this is cached and must not depend on a callers cancellation token.
        private async Task WaitForDisconnectCoreAsync(EndPointAddress endPoint)
        {
            var disposalSource = _disposalSource; // Volatile read op.

            if (disposalSource.IsCancellationRequested)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            var disposal = disposalSource.Token;

            try
            {
                var path  = GetPath(endPoint);
                var entry = await _coordinationManager.GetAsync(path, disposal);

                while (entry != null)
                {
                    var now = _dateTimeProvider.GetCurrentTime();
                    var(_, leaseEnd) = DecodePayload(entry.Value.Span);

                    if (now >= leaseEnd)
                    {
                        return;
                    }

                    var timeToWait = leaseEnd - now;
                    await Task.Delay(timeToWait, disposal);

                    entry = await _coordinationManager.GetAsync(path, disposal);
                }
            }
            catch (OperationCanceledException)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
        }
        private static CoordinationEntryPath GetPrefixPath(ReadOnlyMemory <char> prefix, EndPointAddress endPoint, Session session, bool normalize = true)
        {
            if (normalize)
            {
                prefix = NormalizePrefix(prefix);
            }

            var uniqueEntryName = IdGenerator.GenerateId(endPoint.ToString(), session.ToString());

            return(_rootPrefixesPath.GetChildPath(prefix, uniqueEntryName.AsMemory()));
        }
        public async Task <(IMessage response, bool handled)> SendAsync(IMessage message, EndPointAddress remoteEndPoint, CancellationToken cancellation = default)
        {
            var proxy = await GetProxyAsync(cancellation);

            var buffer = new byte[message.Length];

            using (var stream = new MemoryStream(buffer, writable: true))
            {
                await message.WriteAsync(stream, cancellation);
            }

            var responseBuffer = await proxy.ExecuteAsync(p => p.SendAsync(buffer, remoteEndPoint, cancellation));

            var response = new Message();

            using (var stream = new MemoryStream(responseBuffer))
            {
                await response.ReadAsync(stream, cancellation);
            }

            bool handled;

            using (var stream = response.PopFrame().OpenStream())
                using (var reader = new BinaryReader(stream))
                {
                    handled = reader.ReadBoolean();
                }

            response.Trim();

            return(response, handled);
        }
        private async Task <bool> ValidateClientCoreAsync(EndPointAddress endPoint,
                                                          string securityToken,
                                                          CancellationToken cancellation)
        {
            var now  = _dateTimeProvider.GetCurrentTime();
            var path = GetPath(endPoint);

            do
            {
                var entry = await _coordinationManager.GetAsync(path, cancellation : cancellation);

                if (entry == null)
                {
                    _logger?.LogDebug($"Cannot update session for client with end-point '{endPoint.ToString()}'. Session is terminated.");

                    return(false);
                }

                var(comparandSecurityToken, leaseEnd) = DecodePayload(entry.Value.Span);

                // We have to assume that the client is not connected anymore.
                // This is a race condition, that has to be prevented.
                if (now >= leaseEnd)
                {
                    await _coordinationManager.DeleteAsync(entry.Path, cancellation : cancellation);

                    _logger?.LogDebug($"Session for client with end-point '{endPoint.ToString()}' is terminated. Removing entry.");
                    _logger?.LogDebug($"Cannot update session for client with end-point '{endPoint.ToString()}'. Session is terminated.");
                    return(false);
                }

                if (securityToken != comparandSecurityToken)
                {
                    _logger?.LogDebug($"Cannot update session for client with end-point '{endPoint.ToString()}'. Session is terminated.");
                    return(false);
                }

                var newLeaseEnd = now + Timeout;

                if (newLeaseEnd > leaseEnd)
                {
                    leaseEnd = newLeaseEnd;
                }

                var securityTokenBytesCount = Encoding.UTF8.GetByteCount(securityToken);

                using (ArrayPool <byte> .Shared.Rent(8 + 4 + securityTokenBytesCount, out var bytes))
                {
                    var payloadLength = EncodePayload(bytes, securityToken.AsSpan(), leaseEnd);
                    var payload       = bytes.AsMemory().Slice(start: 0, payloadLength);
                    endPoint = new EndPointAddress("client/" + Guid.NewGuid().ToString());

                    var version = await _coordinationManager.SetValueAsync(path, payload, version : entry.Version, cancellation : cancellation);

                    if (version == entry.Version)
                    {
                        _logger?.LogDebug($"Updated session for client with end-point '{endPoint.ToString()}'.");

                        return(true);
                    }
                }
            }while (true);
        }
 private CoordinationEntryPath GetPath(EndPointAddress endPoint)
 {
     return(BasePath.GetChildPath(endPoint.ToString()));
 }
Exemple #23
0
 private async Task <IDispatchResult> DispatchToEndPointAsync(EndPointAddress endPoint, ModuleHttpRequest moduleHttpRequest, CancellationToken cancellation)
 {
     return(await _dispatcher.DispatchAsync(new DispatchDataDictionary <ModuleHttpRequest>(moduleHttpRequest), publish : false, endPoint, cancellation));
 }
        private static void EncodeRouteRequest(IMessage message, Route route, bool publish, EndPointAddress endPoint)
        {
            var routeBytes = Encoding.UTF8.GetBytes(route.ToString());

            using (var stream = message.PushFrame().OpenStream())
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write((short)MessageType.RouteToEndPoint);
                    writer.Write((short)0);
                    writer.Write(routeBytes.Length);
                    writer.Write(routeBytes);
                    writer.Write(endPoint);

                    writer.Write(publish);
                }
        }
 public EndPointDisconnected(EndPointAddress endPoint)
 {
     EndPoint = endPoint;
 }
Exemple #26
0
 public DebugModuleProperties(EndPointAddress endPoint, ModuleIdentifier module, ModuleVersion version)
 {
     EndPoint = endPoint;
     Module   = module;
     Version  = version;
 }
Exemple #27
0
 public Task <(IMessage message, bool handled)> SendAsync(IMessage message, EndPointAddress remoteEndPoint, CancellationToken cancellation = default)
 {
     return(_reqRplyEndPoint.SendAsync(new Packet <EndPointAddress>(message, remoteEndPoint), cancellation));
 }