示例#1
0
 private static void OnConnectionRecylced(ConnectionBase conn)
 {
     lock (RecycledConnections)
     {
         RecycledConnections.Add(conn);
     }
 }
示例#2
0
 private static void RecycleConnection(ConnectionBase conn)
 {
     conn.Recycle(OnConnectionRecylced);
 }
示例#3
0
 private static void RecycleConnection(ConnectionBase conn)
 {
     conn.Recycle(OnConnectionRecylced);
 }
示例#4
0
        /// <summary>
        /// Update function that should be called regularly from a Unity event(Update, LateUpdate). Callbacks are dispatched from this function.
        /// </summary>
        public static void OnUpdate()
        {
            lock (Locker)
            {
                IsCallingCallbacks = true;
                try
                {
                    for (int i = 0; i < ActiveConnections.Count; ++i)
                    {
                        ConnectionBase conn = ActiveConnections[i];

                        switch (conn.State)
                        {
                        case HTTPConnectionStates.Processing:
                            conn.HandleProgressCallback();

                            if (conn.CurrentRequest.UseStreaming && conn.CurrentRequest.Response != null && conn.CurrentRequest.Response.HasStreamedFragments())
                            {
                                conn.HandleCallback();
                            }

                            if (((!conn.CurrentRequest.UseStreaming && conn.CurrentRequest.UploadStream == null) || conn.CurrentRequest.EnableTimoutForStreaming) &&
                                DateTime.UtcNow - conn.StartTime > conn.CurrentRequest.Timeout)
                            {
                                conn.Abort(HTTPConnectionStates.TimedOut);
                            }

                            break;

                        case HTTPConnectionStates.TimedOut:
                            // The connection is still in TimedOut state, and if we waited enough time, we will dispatch the
                            //  callback and recycle the connection
                            if (DateTime.UtcNow - conn.TimedOutStart > TimeSpan.FromMilliseconds(500))
                            {
                                HTTPManager.Logger.Information("HTTPManager", "Hard aborting connection becouse of a long waiting TimedOut state");

                                conn.CurrentRequest.Response = null;
                                conn.CurrentRequest.State    = HTTPRequestStates.TimedOut;
                                conn.HandleCallback();

                                // this will set the connection's CurrentRequest to null
                                RecycleConnection(conn);
                            }
                            break;

                        case HTTPConnectionStates.Redirected:
                            // If the server redirected us, we need to find or create a connection to the new server and send out the request again.
                            SendRequest(conn.CurrentRequest);

                            RecycleConnection(conn);
                            break;

                        case HTTPConnectionStates.WaitForRecycle:
                            // If it's a streamed request, it's finished now
                            conn.CurrentRequest.FinishStreaming();

                            // Call the callback
                            conn.HandleCallback();

                            // Then recycle the connection
                            RecycleConnection(conn);
                            break;

                        case HTTPConnectionStates.Upgraded:
                            // The connection upgraded to an other protocol
                            conn.HandleCallback();
                            break;

                        case HTTPConnectionStates.WaitForProtocolShutdown:
                            var ws = conn.CurrentRequest.Response as IProtocol;
                            if (ws != null)
                            {
                                ws.HandleEvents();
                            }

                            if (ws == null || ws.IsClosed)
                            {
                                conn.HandleCallback();

                                // After both sending and receiving a Close message, an endpoint considers the WebSocket connection closed and MUST close the underlying TCP connection.
                                conn.Dispose();
                                RecycleConnection(conn);
                            }
                            break;

                        case HTTPConnectionStates.AbortRequested:
                            // Corner case: we aborted a WebSocket connection
                        {
                            ws = conn.CurrentRequest.Response as IProtocol;
                            if (ws != null)
                            {
                                ws.HandleEvents();

                                if (ws.IsClosed)
                                {
                                    conn.HandleCallback();
                                    conn.Dispose();

                                    RecycleConnection(conn);
                                }
                            }
                        }
                        break;

                        case HTTPConnectionStates.Closed:
                            // If it's a streamed request, it's finished now
                            conn.CurrentRequest.FinishStreaming();

                            // Call the callback
                            conn.HandleCallback();

                            // It will remove from the ActiveConnections
                            RecycleConnection(conn);
                            break;

                        case HTTPConnectionStates.Free:
                            RecycleConnection(conn);
                            break;
                        }
                    }
                }
                finally
                {
                    IsCallingCallbacks = false;
                }

                lock (RecycledConnections)
                {
                    if (RecycledConnections.Count > 0)
                    {
                        for (int i = 0; i < RecycledConnections.Count; ++i)
                        {
                            var connection = RecycledConnections[i];
                            // If in a callback made a request that aquired this connection, then we will not remove it from the
                            //  active connections.
                            if (connection.IsFree)
                            {
                                ActiveConnections.Remove(connection);
                                FreeConnections.Add(connection);
                            }
                        }
                        RecycledConnections.Clear();
                    }
                }

                if (FreeConnections.Count > 0)
                {
                    for (int i = 0; i < FreeConnections.Count; i++)
                    {
                        var connection = FreeConnections[i];

                        if (connection.IsRemovable)
                        {
                            // Remove the connection from the connection reference table
                            List <ConnectionBase> connections = null;
                            if (Connections.TryGetValue(connection.ServerAddress, out connections))
                            {
                                connections.Remove(connection);
                            }

                            // Dispose the connection
                            connection.Dispose();

                            FreeConnections.RemoveAt(i);
                            i--;
                        }
                    }
                }


                if (CanProcessFromQueue())
                {
                    // Sort the queue by priority, only if we have to
                    if (RequestQueue.Find((req) => req.Priority != 0) != null)
                    {
                        RequestQueue.Sort((req1, req2) => req1.Priority - req2.Priority);
                    }

                    // Create an array from the queue and clear it. When we call the SendRequest while still no room for new connections, the same queue will be rebuilt.

                    var queue = RequestQueue.ToArray();
                    RequestQueue.Clear();

                    for (int i = 0; i < queue.Length; ++i)
                    {
                        SendRequest(queue[i]);
                    }
                }
            } // lock(Locker)

            if (heartbeats != null)
            {
                heartbeats.Update();
            }
        }
示例#5
0
        private static ConnectionBase FindOrCreateFreeConnection(HTTPRequest request)
        {
            ConnectionBase        conn = null;
            List <ConnectionBase> connections;

            string serverUrl = GetKeyForRequest(request);

            if (Connections.TryGetValue(serverUrl, out connections))
            {
                // count active connections

                int activeConnections = 0;
                for (int i = 0; i < connections.Count; ++i)
                {
                    if (connections[i].IsActive)
                    {
                        activeConnections++;
                    }
                }

                if (activeConnections <= MaxConnectionPerServer)
                {
                    // search for a Free connection
                    for (int i = 0; i < connections.Count && conn == null; ++i)
                    {
                        var tmpConn = connections[i];

                        if (tmpConn != null &&
                            tmpConn.IsFree &&
                            (
#if !BESTHTTP_DISABLE_PROXY
                                !tmpConn.HasProxy ||
#endif
                                tmpConn.LastProcessedUri == null ||
                                tmpConn.LastProcessedUri.Host.Equals(request.CurrentUri.Host, StringComparison.OrdinalIgnoreCase)))
                        {
                            conn = tmpConn;
                        }
                    }
                }
            }
            else
            {
                Connections.Add(serverUrl, connections = new List <ConnectionBase>(MaxConnectionPerServer));
            }

            // No free connection found?
            if (conn == null)
            {
                // Max connection reached?
                if (connections.Count >= MaxConnectionPerServer)
                {
                    return(null);
                }

                // if no, create a new one
                connections.Add(conn = CreateConnection(request, serverUrl));
            }

            return(conn);
        }