Пример #1
0
        /// <summary>
        /// Starts listening.
        /// </summary>
        /// <param name="port">Listening port.</param>
        /// <param name="guid">Listening Guid.</param>
        private void StartListener(int port, string guid)
        {
            this.listener = new HttpListener();

            string address   = String.Format(LISTEN_URL_PATTERN, port, guid);
            string validPath = String.Format(VALID_URL_PATTERN, guid);

            this.listener.Prefixes.Add(address);

            this.listener.Start();

            int threads = App.Settings.HttpListenerThreads;

            this.rateLimitManager.Reset();


            var counter = new HttpListenerCounter(threads);

            for (int i = 0; i < threads; i++)
            {
                Task.Run(
                    async() => {
                    await Listen(this.listener, validPath, counter);
                }
                    );
            }
        }
Пример #2
0
        /// <summary>
        /// Listens.
        /// </summary>
        /// <param name="listener">HTTP listener.</param>
        /// <param name="validPath">Valid path.</param>
        /// <param name="counter">Counter for HttpListener.</param>
        /// <returns>Task.</returns>
        private async Task Listen(HttpListener listener, string validPath, HttpListenerCounter counter)
        {
            Log.Information("Start HTTP Listen: ThreadId = {ThreadId}", Thread.CurrentThread.ManagedThreadId);

            try
            {
                counter.ReportListenerStarted();

                while (listener.IsListening)
                {
                    var context = await listener.GetContextAsync();

                    try
                    {
                        var request  = context.Request;
                        var response = context.Response;

                        var status = HttpStatusCode.Forbidden;

                        try
                        {
                            int retryAfter = this.rateLimitManager.CheckGlobalRetryAfterSecounds();

                            if (retryAfter <= 0 &&
                                request.RawUrl == validPath &&
                                request.HttpMethod == HttpMethod.Post.Method &&
                                request.ContentType.StartsWith("application/json") &&
                                request.ContentLength64 <= AppSettings.HTTP_LISTENER_LIMIT_REQUESTED_BYTES)
                            {
                                using var input  = request.InputStream;
                                using var reader = new StreamReader(input, UTF8);

                                string body = reader.ReadToEnd();

                                if (Log.IsVerboseEnabled)
                                {
                                    Log.Verbose("HTTP Listener received: body = {body}", body);
                                }

                                var audioRenerings = JsonSerializer.Deserialize <AudioRendering>(body, AppSettings.JsonSerializerOptionsForHttpRead);

                                if (audioRenerings.SoundId == this.SoundId &&
                                    audioRenerings.Secret == this.secretString &&
                                    !String.IsNullOrWhiteSpace(audioRenerings.Id) &&
                                    !String.IsNullOrWhiteSpace(audioRenerings.UserHash))
                                {
                                    retryAfter = this.rateLimitManager.CheckUserRetryAfterSecounds(audioRenerings.UserHash);

                                    if (retryAfter <= 0)
                                    {
                                        AudioItem audioItem;

                                        if (this.audioManager.TryGetAudioItem(audioRenerings.Id, out audioItem))
                                        {
                                            this.audioPlayer?.Play(audioItem.Data, PlaybackMode.Once, audioRenerings.Volume);

                                            this.notification.Notify(
                                                String.Format(LocalizedInfo.MessagePatternPlaying, audioItem.Name),
                                                Notification.NotificationLevel.Info);

                                            status = HttpStatusCode.NoContent;
                                        }
                                        else
                                        {
                                            status = HttpStatusCode.NotFound;
                                        }
                                    }
                                }
                            }

                            if (retryAfter > 0)
                            {
                                status = HttpStatusCode.TooManyRequests;
                                response.Headers.Add("Retry-After", retryAfter.ToString());
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error(ex, "Error on processing requested content.");

                            status = HttpStatusCode.InternalServerError;
                        }
                        finally
                        {
                            response.StatusCode = (int)status;
                            response.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Unexpected Error on receiving request.");
                    }
                }
            }
            catch (ObjectDisposedException ode)
            {
                Log.Error(ode, "Error on closing listener.");
            }
            catch (HttpListenerException hlex)
            {
                if (hlex.ErrorCode != 995)
                {
                    Log.Error(hlex, "Unexpected Error on listening context.");
                }
            }
            finally
            {
                if (listener.IsListening)
                {
                    counter.ReportListenerTerminatedUnexpectedly();

                    Log.Warning("HttpListener was stopped while listening.");
                }
                else
                {
                    counter.ReportListenerStopped();
                }

                if (!this.isStopProcessing && !counter.IsAlive)
                {
                    Log.Error("Service will be stopped automatically.");

                    this.notification.ShowNotification(LocalizedInfo.MessageStopServiceWithUnexpectedError, NotificationLevel.Error);

                    this.autoCloseAction();
                }

                Log.Information("Exit HTTP Listen: ThreadId = {ThreadId}", Thread.CurrentThread.ManagedThreadId);
            }
        }