Beispiel #1
0
        /// <summary>Reads the response buffer little by little.</summary>
        private void ReadCallBack(IAsyncResult asyncResult)
        {
            RequestState state = asyncResult.AsyncState as RequestState;
            try {
                Stream responseStream = state.StreamResponse;
                int read = responseStream.EndRead(asyncResult);
                // Read the HTML page and then print it to the console.
                if (read > 0) {
                    state.ResponseBuffer.Write(state.BufferRead, 0, read);
                    responseStream.BeginRead(state.BufferRead, 0, RequestState.BufferSize, new AsyncCallback(ReadCallBack), state);
                    return;
                }
                else {
                    // Finished reading
                    responseStream.Close();

                    HttpResponse result = new HttpResponse();
                    HttpWebResponse response = state.Response;
                    result.StatusCode = (int) response.StatusCode;
                    foreach (string key in response.Headers) {
                        result.Headers[key] = response.Headers[key];
                    }
                    // Read the body
                    result.Body = state.ResponseBuffer.ToArray();
                    // Logging
                    state.LogResponse(result);
                    FinishWithRequest(state, result);
                }
            }
            catch (Exception e) {
                Common.LogWarning("Failed to read response: " + e.ToString());
                FinishWithRequest(state, new HttpResponse(e));
            }
        }
Beispiel #2
0
        /// <summary>Called after an HTTP request has been processed in any way (error or failure). Decides what to do next.</summary>
        protected void FinishWithRequest(WebRequest state, HttpResponse response)
        {
            // This "hack" is needed because sometimes the callback is called multiple times for a single request (notably from RespCallback)
            if (state.AlreadyFinished) return;
            state.AlreadyFinished = true;
            // IDEA This function could probably be moved to another file with a little gymnastic…
            HttpRequest nextReq;
            // Avoid timeout to be triggered after that
            AllDone.Set();
            lock (this) {
                // No need to continue, dismiss the result
                if (Terminated) return;
                RunningRequests.Remove(state);
            }
            // Has failed?
            if (response.ShouldBeRetried(state.OriginalRequest) && !state.Aborted) {
                if (state.OriginalRequest.FailedHandler != null) {
                    // See whether to try again
                    var eventArgs = new HttpRequestFailedEventArgs(state.OriginalRequest, state.PreviousUserData);
                    // Invoke the failure handler
                    try {
                        state.OriginalRequest.FailedHandler(eventArgs);
                        if (eventArgs.RetryDelay < 0) throw new InvalidOperationException("HTTP request failed handler called but didn't tell what to do next.");
                        if (eventArgs.RetryDelay > 0) {
                            Common.LogWarning("[" + state.RequestId + "] Request failed, retrying in " + eventArgs.RetryDelay + "ms.");
                            Thread.Sleep(eventArgs.RetryDelay);
                            ChooseLoadBalancer(state.OriginalRequest);
                            ProcessRequest(state.OriginalRequest, eventArgs.UserData);
                            return;
                        }
                    }
                    catch (Exception e) {
                        Common.LogError("Error in failure handler: " + e.ToString());
                    }
                }
                // Maximum failure count reached, will simply process the next request
                Common.LogWarning("[" + state.RequestId + "] Request failed.");
            }
            // Final result for this request
            if (state.OriginalRequest.Callback != null) {
                Cotc.RunOnMainThread(() => state.OriginalRequest.Callback(response));
            }
            // Was independent?
            if (state.OriginalRequest.DoNotEnqueue) return;

            // Process next request
            lock (this) {
                // Note: currently another request is only launched after synchronously processed by the callback. This behavior is slower but might be safer.
                if (!state.OriginalRequest.DoNotEnqueue && PendingRequests.Count == 0) {
                    IsProcessingRequest = false;
                    return;
                }
                nextReq = PendingRequests[0];
                PendingRequests.RemoveAt(0);
            }
            ProcessRequest(nextReq);
        }
Beispiel #3
0
 /// <summary>To be used when an HTTP request has failed. Will extract a default error code (server error, network error) from the HTTP request.</summary>
 internal CotcException(HttpResponse response, string failureDescription = null)
 {
     Json = response.BodyJson;
     HttpStatusCode = response.StatusCode;
     if (response.HasFailed) {
         ErrorCode = ErrorCode.NetworkError;
         ErrorInformation = failureDescription;
     }
     else if (response.StatusCode < 200 || response.StatusCode >= 300) {
         ErrorCode = ErrorCode.ServerError;
         ErrorInformation = failureDescription;
     }
     else {
         throw new InvalidOperationException("Should only call this for a failed request");
     }
 }
Beispiel #4
0
 /// <summary>Called upon timeout.</summary>
 private static void TimeoutCallback(object state, bool timedOut)
 {
     if (timedOut) {
         WebRequest requestState = state as WebRequest;
         requestState.AbortRequest();
         HttpResponse response = new HttpResponse(new HttpTimeoutException());
         Common.LogWarning("Request timed out");
         requestState.Client.FinishWithRequest(requestState, response);
     }
 }
Beispiel #5
0
            /// <summary>Prints information about the response for debugging purposes.</summary>
            internal void LogResponse(HttpResponse response)
            {
                if (!VerboseMode) { return; }

                StringBuilder sb = new StringBuilder();
                HttpWebRequest req = Request;
                sb.AppendLine("[" + RequestId + "] " + response.StatusCode + " on " + req.Method + "ed on " + req.RequestUri);
                sb.AppendLine("Recv. headers:");
                foreach (var pair in response.Headers) {
                    sb.AppendLine("\t" + pair.Key + ": " + pair.Value);
                }
                if (response.HasBody) {
                    sb.AppendLine("Body: " + response.BodyString);
                }
                Common.Log(sb.ToString());
            }
            private IEnumerator ProcessRequest(UnityWebRequest req)
            {
                yield return req.Send();

                if (req.isError) {
                    if (!WasAborted) {
                        string errorMessage = "Failed web request: " + req.error;
                        Common.Log(errorMessage);
                        self.FinishWithRequest(this, new HttpResponse(new Exception(errorMessage)));
                    }
                }
                else {
                    // Extracts asset bundle
                    HttpResponse response = new HttpResponse();
                    response.Body = Request.downloadHandler.data;
                    response.StatusCode = (int)Request.responseCode;
                    foreach (var pair in Request.GetResponseHeaders()) {
                        response.Headers[pair.Key] = pair.Value;
                    }
                    LogResponse(response);
                    self.FinishWithRequest(this, response);
                }
            }
            /// <summary>Prints information about the response for debugging purposes.</summary>
            internal void LogResponse(HttpResponse response)
            {
                if (!VerboseMode) { return; }

                StringBuilder sb = new StringBuilder();
                sb.AppendLine("[" + RequestId + "] " + response.StatusCode + " on " + Request.method + "ed on " + Request.url);
                sb.AppendLine("Recv. headers:");
                foreach (var pair in response.Headers) {
                    if (String.Compare(pair.Key, "Content-Type", true) == 0) {
                        ContentType = pair.Value;
                    }
                    else {
                        sb.AppendLine("\t" + pair.Key + ": " + pair.Value);
                    }
                }
                if (response.HasBody) {
                    sb.AppendLine("Body: " + response.BodyString);
                }
                Common.Log(sb.ToString());
            }
Beispiel #8
0
 private void ProcessEvent(HttpResponse res)
 {
     try {
         EventLoopArgs args = new EventLoopArgs(res.BodyJson);
         if (receivedEvent != null) receivedEvent(this, args);
         Cotc.NotifyReceivedMessage(this, args);
     }
     catch (Exception e) {
         Common.LogError("Exception in the event chain: " + e.ToString());
     }
 }