Exemple #1
0
        /// <summary>
        /// Reads the value from the data store with the given key. If the value doesn't
        /// exist, or it is of the wrong type then an error will occur.
        /// </summary>
        ///
        /// <param name="key">The key to look up.</param>
        ///
        /// <returns>The Json Object value.</returns>
        public ReadOnlyDictionary <string, object> GetJsonObject(string key)
        {
            ReleaseAssert.IsNotNull(key, "Cannot provide a null key.");

            object value = null;

            lock (m_lock)
            {
                m_dataStore.TryGetValue(key, out value);
            }

            ReleaseAssert.IsNotNull(value, "Value for key '" + key + "' is missing from data store.");
            ReleaseAssert.IsTrue(value is ReadOnlyDictionary <string, object>, "Value is incorrect type.");
            return((ReadOnlyDictionary <string, object>)value);
        }
Exemple #2
0
        /// <summary>
        /// Reads the value from the data store with the given key. If the value doesn't
        /// exist, or it is of the wrong type then an error will occur.
        /// </summary>
        ///
        /// <param name="key">The key to look up.</param>
        ///
        /// <returns>The integer value.</returns>
        public int GetInt(string key)
        {
            ReleaseAssert.IsNotNull(key, "Cannot provide a null key.");

            object value = null;

            lock (m_lock)
            {
                m_dataStore.TryGetValue(key, out value);
            }

            ReleaseAssert.IsNotNull(value, "Value for key '" + key + "' is missing from data store.");
            ReleaseAssert.IsTrue(value is int, "Value is incorrect type.");
            return((int)value);
        }
Exemple #3
0
        /// <summary>
        /// Parses the HTTP response code from the given HTTP STATUS string. The string should
        /// be in the format 'HTTP/X YYY...' or 'HTTP/X.X YYY...' where YYY is the response
        /// code.
        /// </summary>
        ///
        /// <returns>The response code.</returns>
        ///
        /// <param name="httpStatus">The HTTP status string in the format 'HTTP/X YYY...'
        /// or 'HTTP/X.X YYY...'.</param>
        private int ParseHttpStatus(string httpStatus)
        {
            ReleaseAssert.IsTrue(httpStatus != null, "The HTTP status string must not be null when parsing a response code.");

            var regex = new Regex("[a-zA-Z]*\\/\\d+(\\.\\d)?\\s(?<httpResponseCode>\\d+)\\s");
            var match = regex.Match(httpStatus);

            ReleaseAssert.IsTrue(match.Groups.Count == 3, "There must be exactly 3 match groups when using a regex on a HTTP status.");

            var responseCodeString = match.Groups ["httpResponseCode"].Value;

            ReleaseAssert.IsTrue(responseCodeString != null, "The response code string cannot be null when using a regex on a HTTP status.");

            return(Int32.Parse(responseCodeString));
        }
Exemple #4
0
        /// <summary>
        /// <para>The coroutine for processing the HTTP request. This will yield until the
        /// request has completed then get the data from the Web Request object.</para>
        /// </summary>
        ///
        /// <returns>The coroutine enumerator.</returns>
        ///
        /// <param name="url">The URL that the request is targetting.</param>
        /// <param name="headers">The headers for the HTTP request.</param>
        /// <param name="body">The body of the request. If null, a GET request will be sent.</param>
        /// <param name="callback">The callback providing the response from the server.</param>
        private IEnumerator ProcessRequest(String url, IDictionary <string, string> headers, byte[] body, Action <HttpResponse> callback)
        {
            ReleaseAssert.IsTrue(callback != null, "The callback must not be null when sending a request.");

            int   responseCode            = 500;
            float delayInSeconds          = 0.0f;
            float delayIncrementInSeconds = 1.0f;
            float delayMultiplier         = 2.0f;
            int   retryAttempt            = 1;

            for (int retries = 4; retries != 0; --retries)
            {
                if (retries < 4)
                {
                    headers.Remove("X-Chilli-Retry");
                    headers.Add("X-Chilli-Retry", retryAttempt.ToString());
                    retryAttempt++;
                }

                yield return(new WaitForSecondsRealtime(delayInSeconds));

                UnityWebRequest webRequest = CreateUnityWebRequest(url, headers, body);
                ReleaseAssert.IsTrue(webRequest != null, "The webRequest must not be null when sending a request.");

                m_logging.LogVerboseMessage(string.Format("Sending request after delay {1}. Retries remaining {0}.", retries, delayInSeconds));

                yield return(webRequest.Send());

                responseCode = (int)webRequest.responseCode;

                if (ERROR_CODES.Contains(responseCode) == false || retries == 1)
                {
                    m_logging.LogVerboseMessage(string.Format("Request sent with response code {0}", responseCode));
                    ProcessSentRequest(webRequest, responseCode, callback);
                    break;
                }

                if (delayInSeconds == 0.0f)
                {
                    delayInSeconds += delayIncrementInSeconds;
                }
                else
                {
                    delayInSeconds += delayMultiplier;
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Makes a HTTP POST request with the given request object. This is
        /// performed asynchronously, with the callback block run on a background
        /// thread.
        /// </summary>
        ///
        /// <param name="request">The POST HTTP request.</param>
        /// <param name="callback">The callback which will provide the response from the server.
        /// The callback will be made on a background thread.</param>
        public void SendRequest(HttpPostRequest request, Action <HttpPostRequest, HttpResponse> callback)
        {
            ReleaseAssert.IsTrue(request != null, "The HTTP POST request must not be null when sending a request.");
            ReleaseAssert.IsTrue(callback != null, "The callback must not be null when sending a request.");

            var headers = new Dictionary <string, string>(request.Headers);

            if (request.ContentType != null)
            {
                headers.Add("Content-Type", request.ContentType);
            }

            SendRequest(request.Url, headers, request.Body, (HttpResponse response) =>
            {
                callback(request, response);
            });
        }
Exemple #6
0
        /// <summary>
        /// Serialised a list to a Json compatible IList. A callback is provided for
        /// serialising each element in the input list.
        /// </summary>
        ///
        /// <param name="list">The list to be serialised.</param>
        /// <param name="elementCallback">The callback for serialising the elements in the list.</param>
        ///
        /// <returns>The serialised list.</returns>
        public static IList <object> Serialise <TType>(IList <TType> list, Func <TType, object> elementCallback)
        {
            var output = new List <object>();

            foreach (var obj in list)
            {
                ReleaseAssert.IsNotNull(obj, "List elements should not be null.");

                var serialisedObj = elementCallback(obj);
                ReleaseAssert.IsTrue(serialisedObj is bool || serialisedObj is int || serialisedObj is long || serialisedObj is float || serialisedObj is string ||
                                     serialisedObj is IList <object> || serialisedObj is IDictionary <string, object>, "Serialised element must be a valid Json type.");

                output.Add(serialisedObj);
            }

            return(output);
        }
Exemple #7
0
        /// <summary>
        /// Provides the means to send both GET and POST requests depending on the
        /// input data.
        /// </summary>
        ///
        /// <param name="url">The URL that the request is targetting.</param>
        /// <param name="headers">The headers for the HTTP request.</param>
        /// <param name="body">The body of the request. If null, a GET request will be sent.</param>
        /// <param name="callback">The callback providing the response from the server.</param>
        private void SendRequest(String url, IDictionary <string, string> headers, byte[] body, Action <HttpResponse> callback)
        {
            ReleaseAssert.IsTrue(url != null, "The URL must not be null when sending a request.");
            ReleaseAssert.IsTrue(headers != null, "The headers must not be null when sending a request.");
            ReleaseAssert.IsTrue(callback != null, "The callback must not be null when sending a request.");

            // Unity's WWW class works with the Dictionary concrete class rather than the abstract
            // IDictionary. Rather than cast a copy is made so we can be sure other dictionary types
            // will work.
            Dictionary <string, string> headersConcreteDict = new Dictionary <string, string>(headers);

            m_taskScheduler.ScheduleMainThreadTask(() =>
            {
                var www = new WWW(url, body, headersConcreteDict);
                m_taskScheduler.StartCoroutine(ProcessRequest(www, callback));
            });
        }
Exemple #8
0
        /// <summary>
        /// Deserialised a list from a Json compatible IList. A callback is
        /// provided for deserialising each element in the list.
        /// </summary>
        ///
        /// <param name="list">The list to be deserialised.</param>
        /// <param name="elementCallback">The callback for deserialising the elements in the list.</param>
        ///
        /// <returns>The deserialised list.</returns>
        public static ReadOnlyCollection <TType> DeserialiseList <TType>(IList <object> list, Func <object, TType> elementCallback)
        {
            var output = new List <TType>();

            foreach (var obj in list)
            {
                ReleaseAssert.IsNotNull(obj, "List elements should not be null.");
                ReleaseAssert.IsTrue(obj is bool || obj is int || obj is long || obj is float || obj is string ||
                                     obj is IList <object> || obj is IDictionary <string, object>, "Serialised element must be a valid Json type.");

                var deserialisedObj = elementCallback(obj);
                ReleaseAssert.IsNotNull(deserialisedObj, "Deserialised list elements should not be null.");

                output.Add(deserialisedObj);
            }

            return(new ReadOnlyCollection <TType>(output));
        }
Exemple #9
0
        /// <summary>
        /// Initialises the new instance of server response from the given HTTP
        /// response.
        /// </summary>
        ///
        /// <param name="httpResponse">The HTTP response.</param>
        public ServerResponse(HttpResponse httpResponse)
        {
            Result           = httpResponse.Result;
            HttpResponseCode = httpResponse.HttpResponseCode;

            if (httpResponse.Body.Length > 0)
            {
                var bodyString     = Encoding.UTF8.GetString(httpResponse.Body);
                var bodyDictionary = Json.Deserialize(bodyString) as Dictionary <string, object>;
                ReleaseAssert.IsTrue(bodyDictionary != null, "Invalid server response JSON.");

                Body = new ReadOnlyDictionary <string, object>(bodyDictionary);
            }
            else
            {
                Body = new ReadOnlyDictionary <string, object>();
            }
        }
Exemple #10
0
        /// <summary>
        /// Serialised a map to a Json compatible IDictionary. A callback is provided for
        /// serialising each element in the input map.
        /// </summary>
        ///
        /// <param name="map">The map to be serialised.</param>
        /// <param name="elementCallback">The callback for serialising the elements in the map.</param>
        ///
        /// <returns>The serialised map.</returns>
        public static IDictionary <string, object> Serialise <TType>(IDictionary <string, TType> map, Func <TType, object> elementCallback)
        {
            var output = new Dictionary <string, object>();

            foreach (var entry in map)
            {
                ReleaseAssert.IsNotNull(entry.Key, "Map keys should not be null.");
                ReleaseAssert.IsNotNull(entry.Value, "Map elements should not be null.");

                var serialisedObj = elementCallback(entry.Value);
                ReleaseAssert.IsNotNull(serialisedObj, "Serialised list elements should not be null.");
                ReleaseAssert.IsTrue(serialisedObj is bool || serialisedObj is int || serialisedObj is long || serialisedObj is float || serialisedObj is string ||
                                     serialisedObj is IList <object> || serialisedObj is IDictionary <string, object>, "Serialised element must be a valid Json type.");

                output.Add(entry.Key, serialisedObj);
            }

            return(output);
        }
Exemple #11
0
        /// <summary>
        /// Parses the HTTP response code from the given HTTP error string. The string should
        /// be in the format 'XXX ...' where XXX is the HTTP response code.
        /// </summary>
        ///
        /// <returns>The response code parsed from the error, or 0 if there wasn't one.</returns>
        ///
        /// <param name="httpError">The HTTP error string.</param>
        private int ParseHttpError(string httpError)
        {
            ReleaseAssert.IsTrue(httpError != null, "The HTTP error string must not be null when parsing a response code.");

            var regex = new Regex("(?<httpResponseCode>[0-9][0-9][0-9])\\s");

            if (regex.IsMatch(httpError))
            {
                var match = regex.Match(httpError);
                ReleaseAssert.IsTrue(match.Groups.Count == 2, "There must be exactly 2 match groups when using a regex on a HTTP error.");

                var responseCodeString = match.Groups ["httpResponseCode"].Value;
                ReleaseAssert.IsTrue(responseCodeString != null, "The response code string cannot be null when using a regex on a HTTP error.");

                return(Int32.Parse(responseCodeString));
            }

            return(0);
        }
Exemple #12
0
        /// <summary>
        /// Performs a server request with the given request parameters. This is
        /// performed asynchronously.
        /// </summary>
        ///
        /// <param name="request">The request that should be performed, which must adhere
        /// to the immediate request protocol.</param>
        /// <param name="callback">The callback containing the response. The callback
        /// will be on a background thread.</param>
        public void SendImmediateRequest(IImmediateServerRequest request, Action <IImmediateServerRequest, ServerResponse> callback)
        {
            m_taskScheduler.ScheduleBackgroundTask(() =>
            {
//                if (request.HttpRequestMethod == HttpRequestMethod.Post)
//                {
                var bodyString = MiniJSON.Json.Serialize(request.SerialiseBody());
                ReleaseAssert.IsTrue(bodyString != null, "Invalid body.");
                var bodyData = Encoding.UTF8.GetBytes(bodyString);

                var httpRequestDesc         = new HttpPostRequestDesc(request.Url, bodyData);
                httpRequestDesc.Headers     = request.SerialiseHeaders();
                httpRequestDesc.ContentType = "application/json";

                var httpRequest = new HttpPostRequest(httpRequestDesc);
                m_httpSystem.SendRequest(httpRequest, (HttpPostRequest receivedHttpRequest, HttpResponse httpResponse) =>
                {
                    ReleaseAssert.IsTrue(httpRequest == receivedHttpRequest, "Received response for wrong request.");

                    var serverResponse = new ServerResponse(httpResponse);
                    callback(request, serverResponse);
                });
//                }
//                else
//                {
//                    var httpRequestDesc = new HttpGetRequestDesc(request.Url);
//                    httpRequestDesc.Headers = request.SerialiseHeaders();
//
//                    var httpRequest = new HttpGetRequest(httpRequestDesc);
//                    m_httpSystem.SendRequest(httpRequest, (HttpGetRequest receivedHttpRequest, HttpResponse httpResponse) =>
//                    {
//                        ReleaseAssert.IsTrue(httpRequest == receivedHttpRequest, "Received response for wrong request.");
//
//                        var serverResponse = new ServerResponse(httpResponse);
//                        callback(request, serverResponse);
//                    });
//                }
            });
        }
        /// <summary>
        /// Deserialised a map from a Json compatible IDictionary. A callback is provided
        /// for deserialising each element in the IDictionary.
        /// </summary>
        ///
        /// <param name="map">The map to be deserialised.</param>
        /// <param name="elementCallback">The callback for deserialising the elements in the map.</param>
        ///
        /// <returns>The deserialised map.</returns>
        public static ReadOnlyDictionary <string, TType> DeserialiseMap <TType>(IDictionary <string, object> map, Func <object, TType> elementCallback)
        {
            var output = new Dictionary <string, TType>();

            foreach (var entry in map)
            {
                if (entry.Value == null)
                {
                    output.Add(entry.Key, default(TType));
                }
                else
                {
                    ReleaseAssert.IsTrue(entry.Value is bool || entry.Value is int || entry.Value is long || entry.Value is float || entry.Value is string || entry.Value == null ||
                                         entry.Value is IList <object> || entry.Value is IDictionary <string, object>, "Serialised element must be a valid Json type.");

                    var deserialisedObj = elementCallback(entry.Value);
                    ReleaseAssert.IsNotNull(deserialisedObj, "Deserialised list elements should not be null.");
                    output.Add(entry.Key, deserialisedObj);
                }
            }

            return(new ReadOnlyDictionary <string, TType>(output));
        }
Exemple #14
0
        /// <summary>
        /// Initializes a new instance of the HTTP system with the given task
        /// scheduler.
        /// </summary>
        ///
        /// <param name="taskScheduler">The task scheduler.</param>
        public HttpSystem(TaskScheduler taskScheduler)
        {
            ReleaseAssert.IsTrue(taskScheduler != null, "The task scheduler in a HTTP request system must not be null.");

            m_taskScheduler = taskScheduler;
        }
Exemple #15
0
        /// <summary>
        /// <para>The coroutine for processing the HTTP request. This will yield until the
        /// request has completed then parse the information required by a HTTP response
        /// from the WWW object.</para>
        /// </summary>
        ///
        /// <returns>The coroutine enumerator.</returns>
        ///
        /// <param name="www">The WWW object.</param>
        /// <param name="callback">The callback providing the response from the server.</param>
        private IEnumerator ProcessRequest(WWW www, Action <HttpResponse> callback)
        {
            ReleaseAssert.IsTrue(www != null, "The WWW must not be null when sending a request.");
            ReleaseAssert.IsTrue(callback != null, "The callback must not be null when sending a request.");

            yield return(www);

            HttpResponseDesc desc = null;

            if (string.IsNullOrEmpty(www.error))
            {
                ReleaseAssert.IsTrue(www.responseHeaders != null, "A successful HTTP response must have a headers object.");

                desc         = new HttpResponseDesc(HttpResult.Success);
                desc.Headers = new Dictionary <string, string>(www.responseHeaders);

                if (www.bytes != null)
                {
                    desc.Body = www.bytes;
                }

                var httpStatus = www.responseHeaders ["STATUS"];
                ReleaseAssert.IsTrue(!string.IsNullOrEmpty(httpStatus), "A successful HTTP response must have a HTTP status value in the header.");

                desc.HttpResponseCode = ParseHttpStatus(httpStatus);
            }
            else
            {
                var bytes            = www.bytes;
                int httpResponseCode = 0;

                                #if UNITY_IPHONE && !UNITY_EDITOR
                var text = www.text;
                if (!string.IsNullOrEmpty(text))
                {
                    var bodyDictionary = Json.Deserialize(text) as Dictionary <string, object>;
                    if (bodyDictionary != null && bodyDictionary.ContainsKey("HttpCode"))
                    {
                        httpResponseCode = Convert.ToInt32(bodyDictionary ["HttpCode"]);
                        bytes            = Encoding.UTF8.GetBytes(text);
                    }
                }
                                #else
                httpResponseCode = ParseHttpError(www.error);
                                #endif

                if (httpResponseCode != 0)
                {
                    desc         = new HttpResponseDesc(HttpResult.Success);
                    desc.Headers = new Dictionary <string, string>(www.responseHeaders);

                    if (www.bytes != null)
                    {
                        desc.Body = www.bytes;
                    }

                    desc.HttpResponseCode = httpResponseCode;
                }
                else
                {
                    desc = new HttpResponseDesc(HttpResult.CouldNotConnect);
                }
            }

            HttpResponse response = new HttpResponse(desc);
            m_taskScheduler.ScheduleBackgroundTask(() =>
            {
                callback(response);
            });
        }
Exemple #16
0
 /// <summary>
 /// Adds a new value to the dictionary description.
 /// </summary>
 ///
 /// <param name="key">The key this value should be stored under.</param>
 /// <param name="value">The value which should be added.</param>
 public MultiTypeDictionaryBuilder Add(string key, MultiTypeValue value)
 {
     ReleaseAssert.IsFalse(m_dictionary.ContainsKey(key), "Dictionary already contains the key '" + key + "'");
     m_dictionary.Add(key, value);
     return(this);
 }