private static void OnConnectionRecylced(ConnectionBase conn) { lock (RecycledConnections) { RecycledConnections.Add(conn); } }
private static void RecycleConnection(ConnectionBase conn) { conn.Recycle(OnConnectionRecylced); }
/// <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(); } }
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); }