A game about forced loneliness, made by TACStudios
at master 6.6 kB view raw
1using System; 2using System.Threading; 3 4using UnityEditor; 5 6using Codice.Client.Common.EventTracking; 7using Codice.Client.Common.Connection; 8using Codice.Client.Common.Threading; 9using Codice.CM.Common; 10using Codice.LogWrapper; 11using PlasticPipe; 12using Unity.PlasticSCM.Editor.UI; 13 14namespace Unity.PlasticSCM.Editor 15{ 16 internal class PlasticConnectionMonitor : 17 HandleCredsAliasAndServerCert.IHostUnreachableExceptionListener 18 { 19 internal bool IsTryingReconnection { get { return mIsTryingReconnection; } } 20 internal bool IsConnected { get { return PlasticPlugin.IsUnitTesting || mIsConnected; } } 21 22 internal void CheckConnection() 23 { 24 mIsTryingReconnection = true; 25 mResetEvent.Set(); 26 } 27 28 internal void SetAsConnected() 29 { 30 mIsConnected = true; 31 } 32 33 internal void Stop() 34 { 35 if (!mIsMonitoringServerConnection) 36 return; 37 38 mLog.Debug("Stop"); 39 40 mIsMonitoringServerConnection = false; 41 mResetEvent.Set(); 42 } 43 44 internal void SetRepositorySpecForEventTracking(RepositorySpec repSpec) 45 { 46 mRepSpecForEventTracking = repSpec; 47 } 48 49 internal void OnConnectionError(Exception ex, string server) 50 { 51 lock (mOnConnectionErrorLock) 52 { 53 LogConnectionError(ex, mIsConnected); 54 55 if (!mIsConnected) 56 return; 57 58 mIsConnected = false; 59 } 60 61 HandleConnectionLost( 62 mRepSpecForEventTracking, 63 () => StartMonitoring(server)); 64 } 65 66 void HandleCredsAliasAndServerCert.IHostUnreachableExceptionListener.OnHostUnreachableException( 67 Exception ex, 68 PlasticServer plasticServer) 69 { 70 OnConnectionError(ex, plasticServer.OriginalUrl); 71 } 72 73 void StartMonitoring(string server) 74 { 75 mLog.Debug("StartMonitoring"); 76 77 mIsMonitoringServerConnection = true; 78 79 Thread thread = new Thread(MonitorServerConnection); 80 thread.IsBackground = true; 81 thread.Name = "Plastic SCM Connection Monitor thread"; 82 thread.Start(server); 83 } 84 85 void MonitorServerConnection(object obj) 86 { 87 string server = (string)obj; 88 89 while (true) 90 { 91 if (!mIsMonitoringServerConnection) 92 break; 93 94 try 95 { 96 mResetEvent.Reset(); 97 98 if (HasConnectionToServer(server)) 99 { 100 mIsConnected = true; 101 HandleConnectionRestored(mRepSpecForEventTracking); 102 break; 103 } 104 105 RepaintPlasticWindowIfOpened(); 106 107 mResetEvent.WaitOne(CONNECTION_POLL_TIME_MS); 108 } 109 catch (Exception ex) 110 { 111 mLog.Error("Error checking network connectivity", ex); 112 mLog.DebugFormat("Stacktrace: {0}", ex.StackTrace); 113 } 114 finally 115 { 116 mIsTryingReconnection = false; 117 } 118 } 119 } 120 121 static void HandleConnectionLost( 122 RepositorySpec repSpecForEventTracking, 123 Action startMonitoringAction) 124 { 125 TrackConnectionLostEvent(repSpecForEventTracking); 126 127 EditorDispatcher.Dispatch(() => 128 { 129 PlasticPlugin.Disable(); 130 131 startMonitoringAction(); 132 133 PlasticWindow window = GetWindowIfOpened.Plastic(); 134 135 if (window != null) 136 window.Repaint(); 137 }); 138 } 139 140 static void HandleConnectionRestored( 141 RepositorySpec repSpecForEventTracking) 142 { 143 TrackConnectionRestoredEvent(repSpecForEventTracking); 144 145 EditorDispatcher.Dispatch(() => 146 { 147 PlasticPlugin.Enable(); 148 149 PlasticWindow window = GetWindowIfOpened.Plastic(); 150 151 if (window != null) 152 window.RefreshWorkspaceUI(); 153 }); 154 } 155 156 static void RepaintPlasticWindowIfOpened() 157 { 158 EditorDispatcher.Dispatch(() => 159 { 160 PlasticWindow window = GetWindowIfOpened.Plastic(); 161 162 if (window != null) 163 window.Repaint(); 164 }); 165 } 166 167 static void LogConnectionError(Exception ex, bool isConnected) 168 { 169 mLog.WarnFormat(isConnected ? 170 "A network exception will cause the plugin to go offline" : 171 "A network exception happened while the plugin was offline!"); 172 173 ExceptionsHandler.LogException("PlasticConnectionMonitor", ex); 174 } 175 176 static void TrackConnectionLostEvent(RepositorySpec repSpec) 177 { 178 if (repSpec == null) 179 return; 180 181 TrackFeatureUseEvent.For( 182 repSpec, 183 TrackFeatureUseEvent.Features.UnityPackage.DisableAutomatically); 184 } 185 186 static void TrackConnectionRestoredEvent(RepositorySpec repSpec) 187 { 188 if (repSpec == null) 189 return; 190 191 TrackFeatureUseEvent.For( 192 repSpec, 193 TrackFeatureUseEvent.Features.UnityPackage.EnableAutomatically); 194 } 195 196 static bool HasConnectionToServer(string server) 197 { 198 try 199 { 200 mLog.DebugFormat("Checking connection to {0}...", server); 201 202 return PlasticGui.Plastic.API.CheckServerConnection(server); 203 } 204 catch (Exception ex) 205 { 206 mLog.DebugFormat("Checking connection to {0} failed: {1}", 207 server, 208 ex.Message); 209 return false; 210 } 211 } 212 213 volatile bool mIsMonitoringServerConnection; 214 volatile bool mIsTryingReconnection; 215 volatile bool mIsConnected = true; 216 217 RepositorySpec mRepSpecForEventTracking; 218 219 readonly object mOnConnectionErrorLock = new object(); 220 readonly ManualResetEvent mResetEvent = new ManualResetEvent(false); 221 222 const int CONNECTION_POLL_TIME_MS = 30000; 223 224 static readonly ILog mLog = PlasticApp.GetLogger("PlasticConnectionMonitor"); 225 } 226}