Example #1
0
        /// <summary>
        /// Allows this instance to receive and process incoming requests.
        /// </summary>
        /// <exception cref="PlayerStateException"/>
        public void Start()
        {
            lock (statelock)
            {
                if (CurrentState != State.Off)
                {
                    throw new PlayerStateException(CurrentState, "Player has already started.");
                }

                httpListener.Start();

                Task.Run(() =>
                {
                    while (httpListener.IsListening)
                    {
                        var context        = httpListener.GetContext();
                        var playerRequest  = context.Request;
                        var playerResponse = context.Response;

                        lock (statelock)
                        {
                            try
                            {
                                switch (CurrentState)
                                {
                                case State.Playing:
                                    {
                                        var mock              = (JObject)record.Read();
                                        var mockRequest       = MockRequest.FromJson((JObject)mock["request"]);
                                        var mockPlayerRequest = MockRequest.FromHttpRequest(remoteAddress, playerRequest);

                                        MockResponse mockResponse;

                                        var differences = mockRequest.GetDifferences(mockPlayerRequest).ToArray();
                                        if (differences.Length == 0)
                                        {
                                            mockResponse = MockResponse.FromJson((JObject)mock["response"]);
                                        }
                                        else
                                        {
                                            var differencesMessage = string.Join(", ",
                                                                                 differences.Select(d =>
                                                                                                    $"{d.Property} (Recorded='{d.ThisValue}', Requested='{d.OtherValue}')"));
                                            var message =
                                                $"Player could not play the request at {playerRequest.Url.PathAndQuery}. " +
                                                $"The request doesn't match the current recorded one: {differencesMessage}";
                                            mockResponse = MockResponse.FromPlayerError(PlayerErrorCode.RequestNotFound, "Player request mismatch", message);
                                        }

                                        BuildResponse(playerResponse, mockResponse);
                                    }

                                    break;

                                case State.Recording:
                                    {
                                        var mockRequest = MockRequest.FromHttpRequest(remoteAddress, playerRequest);
                                        var request     = BuildRequest(mockRequest);

                                        MockResponse mockResponse;

                                        try
                                        {
                                            using (var response = (HttpWebResponse)request.GetResponse())
                                            {
                                                mockResponse = MockResponse.FromHttpResponse(response);
                                            }
                                        }
                                        catch (WebException ex)
                                        {
                                            if (ex.Response == null)
                                            {
                                                throw ex;
                                            }

                                            mockResponse = MockResponse.FromHttpResponse((HttpWebResponse)ex.Response);
                                        }

                                        var mock = JObject.FromObject(new
                                        {
                                            request  = mockRequest.ToJson(),
                                            response = mockResponse.ToJson()
                                        });
                                        record.Write(mock);

                                        BuildResponse(playerResponse, mockResponse);
                                    }

                                    break;

                                default:
                                    throw new PlayerStateException(CurrentState, "Player is not in operation.");
                                }
                            }
                            catch (Exception ex)
                            {
                                PlayerErrorCode errorCode;
                                string process;

                                switch (CurrentState)
                                {
                                case State.Playing:
                                    errorCode = PlayerErrorCode.PlayException;
                                    process   = "play";

                                    break;

                                case State.Recording:
                                    errorCode = PlayerErrorCode.RecordException;
                                    process   = "record";

                                    break;

                                default:
                                    errorCode = PlayerErrorCode.Exception;
                                    process   = "process";

                                    break;
                                }

                                var mockResponse = MockResponse.FromPlayerError(errorCode, "Player exception", $"Player could not {process} the request at {playerRequest.Url.PathAndQuery} because of exception: {ex}");

                                BuildResponse(playerResponse, mockResponse);
                            }
                            finally
                            {
                                playerResponse.Close();
                            }
                        }
                    }
                });

                CurrentState = State.Idle;
            }
        }