internal HubConnectionStatus(ServerConfiguration configuration, WebChannel channel, HubRepository repository, bool isValid, HubStatus status, string message) { Configuration = configuration; Channel = channel; Repository = repository; Status = status; Message = message; IsValid = isValid; }
private async Task <WebChannel> GetCurrentChannel() { WebChannel currentChannel; lock (m_ChannelLock) { currentChannel = m_CurrentChannel; System.Threading.Monitor.PulseAll(m_ChannelLock); } //CAREFUL: Between here and the end of this if do not access a property that //checks m_HaveTriedToConnect because if so we get into a big bad loop. if (currentChannel == null) { try { //try to connect. var connectionStatus = await Connect().ConfigureAwait(false); WebChannel newChannel = connectionStatus.Channel; //before we return, lets set our status to track what we just calculated. lock (m_StatusLock) { //make a copy of the connection status without the connection so they can't accidentally call it. m_HubStatus = new HubConnectionStatus(connectionStatus.Configuration, null, connectionStatus.Repository, connectionStatus.IsValid, connectionStatus.Status, connectionStatus.Message); m_HubRepository = connectionStatus.Repository; } //if we couldn't connect we'll have a null channel (connect returns null) if (newChannel == null) { throw new WebChannelConnectFailureException(connectionStatus.Message); } //otherwise we need to bind up our events and release the existing - use our setter for that SetCurrentChannel(newChannel); currentChannel = newChannel; } finally { //whether we succeeded or failed, we tried. m_HaveTriedToConnect = true; } } return(currentChannel); }
/// <summary> /// Attempts to connect to the server and returns information about the connection status. /// </summary> /// <remarks>This method will keep the connection if it is made, improving efficiency if you are then going to use the connection.</remarks> /// <returns>True if the configuration is valid and the server is available, false otherwise.</returns> public async Task <HubConnectionStatus> CanConnect() { WebChannel currentChannel; lock (m_ChannelLock) { currentChannel = m_CurrentChannel; System.Threading.Monitor.PulseAll(m_ChannelLock); } //if we have a current connection we'll need to see if we can keep using it if (currentChannel != null) { var status = HubStatus.Maintenance; try { var configurationGetRequest = new HubConfigurationGetRequest(); await currentChannel.ExecuteRequest(configurationGetRequest, 1).ConfigureAwait(false); //we'd like it to succeed, so we'll give it one retry //now, if we got back a redirect we need to go THERE to get the status. HubConfigurationXml configurationXml = configurationGetRequest.Configuration; if ((configurationXml.redirectRequested == false) && (configurationXml.status == HubStatusXml.available)) { //we can just keep using this connection, so lets do that. return(new HubConnectionStatus(null, true, HubStatus.Available, null)); } status = (HubStatus)configurationXml.status; //we define these to be equal. } catch (Exception ex) { if (!Logger.SilentMode) { Logger.Write(LogMessageSeverity.Information, ex, false, LogCategory, "Unable to get server configuration, connection will be assumed unavailable.", "Due to an exception we were unable to retrieve the server configuration. We'll assume the server is in maintenance until we can succeed. Exception: {0}\r\n", ex.Message); } } //drop the connection - we might do better, unless we're already at the root. if (IsRootHub(currentChannel.HostName, currentChannel.Port, currentChannel.UseSsl, currentChannel.ApplicationBaseDirectory)) { //we are the root - what we are is the best we are. string message = null; switch (status) { case HubStatus.Expired: message = "your subscription is expired"; break; case HubStatus.Maintenance: message = "the repository is in maintenance"; break; } return(new HubConnectionStatus(null, false, status, message)); } } //if we don't have a connection (either we didn't before or we just invalidated the current connection) get a new one. var connectionStatus = await Connect().ConfigureAwait(false); SetCurrentChannel(connectionStatus.Channel); //before we return, lets set our status to track what we just calculated. lock (m_StatusLock) { //make a copy of the connection status so the caller does NOT get our connection object. m_HubStatus = new HubConnectionStatus(connectionStatus.Configuration, null, connectionStatus.Repository, connectionStatus.IsValid, connectionStatus.Status, connectionStatus.Message); m_HubRepository = connectionStatus.Repository; } return(connectionStatus); }