/// <summary> /// Create a new subscription to this hub for the supplied repository information and shared secret. /// </summary> /// <param name="repositoryXml"></param> /// <remarks></remarks> /// <returns>The client repository information retrieved from the server.</returns> public async Task <ClientRepositoryXml> CreateSubscription(ClientRepositoryXml repositoryXml) { var request = new ClientRepositoryUploadRequest(repositoryXml); //we have to use distinct credentials for this so we have to swap the credentials on the connection. var channel = await GetCurrentChannel().ConfigureAwait(false); bool retry; do { retry = false; //so we'll exit by default try { await channel.ExecuteRequest(request, 1).ConfigureAwait(false); } catch (WebChannelAuthorizationException ex) { //request better credentials.. Logger.Write(LogMessageSeverity.Warning, ex, true, LogCategory, "Requesting updated credentials for the server connection due to " + ex.GetType(), "We're going to assume the user can provide current credentials.\r\nDetails: {0}", ex.Message); retry = CachedCredentialsManager.UpdateCredentials(channel, m_ClientRepositoryId, true); if (retry == false) { throw; } } } while (retry); return(request.ResponseRepository); }
/// <summary> /// Execute the provided request. /// </summary> /// <param name="newRequest"></param> /// <param name="maxRetries">The maximum number of times to retry the connection. Use -1 to retry indefinitely.</param> public async Task ExecuteRequest(IWebRequest newRequest, int maxRetries) { //make sure we have a channel WebChannel channel = await GetCurrentChannel().ConfigureAwait(false); //this throws exceptions when it can't connect and is thread safe. //if we have a channel and NOW get an exception, here is where we would recheck the status of our connection. bool retryAuthentication = false; bool resetAndRetry = false; try { await channel.ExecuteRequest(newRequest, maxRetries).ConfigureAwait(false); } catch (WebChannelAuthorizationException ex) { //request better credentials.. Logger.Write(LogMessageSeverity.Warning, ex, true, LogCategory, "Requesting updated credentials for the server connection due to " + ex.GetType(), "We're going to assume the user can provide current credentials.\r\nDetails: {0}", ex.Message); if (CachedCredentialsManager.UpdateCredentials(channel, m_ClientRepositoryId, false)) { //they entered new creds.. lets give them a go. retryAuthentication = true; } else { //they canceled, lets call it. throw; } } catch (WebChannelConnectFailureException) { //clear our current channel and try again if we're on a child server. if (IsRootHub(channel.HostName, channel.Port, channel.UseSsl, channel.ApplicationBaseDirectory) == false) { resetAndRetry = true; } } if (retryAuthentication) { await ExecuteRequest(newRequest, maxRetries).ConfigureAwait(false); } else if (resetAndRetry) { await ResetChannel().ConfigureAwait(false); //safely clears the current channel and gets a fresh one if possible } }
/// <summary> /// Connect to the hub (or another hub if the configured hub is redirecting) /// </summary> /// <returns>The last web channel it was able to connect to after processing redirections, if that channel is available.</returns> private async Task <HubConnectionStatus> Connect() { var connectionStatus = await Connect(m_RootConfiguration).ConfigureAwait(false); if (connectionStatus.Channel != null) { //copy our current settings into it. lock (m_Lock) { connectionStatus.Channel.EnableLogging = m_EnableLogging; if (m_UseCredentials) { connectionStatus.Channel.AuthenticationProvider = CachedCredentialsManager.GetCredentials(connectionStatus.Channel, m_UseRepositoryCredentials, m_ClientRepositoryId, m_KeyContainerName, m_UseMachineStore); } System.Threading.Monitor.PulseAll(m_Lock); } } return(connectionStatus); }