Exemplo n.º 1
0
        /// <summary>
        /// Reestablish connection to server.
        /// </summary>
        /// <remarks>
        /// This method checks if the session is valid. If not, a new logon in perfomed automatically.
        /// Handle the NewLogonNeeded event to provide credentials.
        /// </remarks>
        /// <returns>True, if reconnecting was successfull, otherwis false </returns>
        internal bool InternalReconnect()
        {
            // When the session isn´t valid, the server process must have been restarted
            if (!RemoteDispatcher.ExistSession(_sessionID))
            {
                AuthCredentials credentials     = null;
                var             performNewLogon = true;

                // If cached auto login credentials are present
                if (_autoLoginOnExpiredSession)
                {
                    credentials = _autoLoginCredentials;
                }
                else
                {
                    var newLogonNeededEventArgs = new NewLogonNeededEventArgs();
                    if (OnNewLogonNeeded(newLogonNeededEventArgs))
                    {
                        performNewLogon = !newLogonNeededEventArgs.Cancel;
                        credentials     = newLogonNeededEventArgs.Credentials;
                    }
                    else
                    {
                        performNewLogon = false;
                    }
                }

                if (performNewLogon)
                {
                    if (credentials == null)
                    {
                        credentials = new AuthCredentials();
                    }

                    credentials.Authenticate(_sessionID, RemoteDispatcher);
                    ReconnectRemoteEvents();

                    RemoteDispatcher.ReceiveClientHeartbeat(_sessionID);
                    return(true);
                }
            }
            else
            {
                RemoteDispatcher.ReceiveClientHeartbeat(_sessionID);
                return(true);
            }
            return(false);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Will be called from session keep alive timer on ervery interval.
        /// </summary>
        /// <param name="state">State (not used)</param>
        private void KeepSessionAlive(object state)
        {
            try
            {
                PrepareCallContext(false);

                int serverSessionAgeLimit = RemoteDispatcher.RenewSession();

                if (_sessionAgeLimit != serverSessionAgeLimit)
                {
                    _sessionAgeLimit = serverSessionAgeLimit;
                    StartKeepSessionAliveTimer();
                }
            }
            catch
            {
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Reconnects to all remote events or delegates of any known proxy for this connection, after a server restart.
        /// </summary>
        /// <remarks>
        /// Does not check, if the event handler registrations are truly lost.
        /// </remarks>
        private void ReconnectRemoteEventsCore()
        {
            if (_isDisposed)
            {
                return;
            }

            try
            {
                lock (RemoteEventsLock)
                {
                    var subscriptions   = AliveProxies.Select(p => p.GetActiveSubscriptions()).Where(s => !s.DelegateCorrelationSet.IsNullOrEmpty()).ToArray();
                    var correlationSets = subscriptions.SelectMany(s => s.DelegateCorrelationSet).ToArray();
                    _localSubscriptionTracker.Reset(correlationSets);

                    PrepareCallContext(false);
                    RemoteDispatcher.ReconnectEventHandlers(subscriptions);
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Error while restoring client subscriptions: {0}", ex);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Will be called from polling timer on every interval.
        /// </summary>
        /// <param name="state">State (not used)</param>
        internal void SendHeartbeat(object state)
        {
            if (_sendingHeartbeat)
            {
                // if polling timer interval is less than
                // channel timeout, skip sending a heartbeat
                return;
            }

            try
            {
                _sendingHeartbeat = true;
                try
                {
                    PrepareCallContext(false);
                    RemoteDispatcher.ReceiveClientHeartbeat(_sessionID);
                }
                finally
                {
                    _sendingHeartbeat = false;
                }
            }
            catch (Exception ex)
            {
                PollingEnabled = false;
                bool problemSolved = false;

                DisconnectedEventArgs e = new DisconnectedEventArgs()
                {
                    Exception  = ex,
                    RetryCount = 0,
                    Retry      = false
                };

                OnDisconnected(e);

                while (e.Retry)
                {
                    e.Retry = false;

                    Thread.Sleep(Convert.ToInt32(_pollingInterval.TotalMilliseconds));

                    try
                    {
                        problemSolved = InternalReconnect();
                    }
                    catch (Exception retryEx)
                    {
                        e.Exception = retryEx;
                        e.RetryCount++;
                        OnDisconnected(e);
                    }
                }

                if (problemSolved)
                {
                    PollingEnabled = true;
                    OnReconnected(EventArgs.Empty);
                }
                else
                {
                    // connection wasn't restored, make sure
                    // that the polling timer is stopped
                    PollingEnabled = false;
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Releases unmanaged and — optionally — managed resources.
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposing)
            {
                return;
            }

            if (!_isDisposed)
            {
                _isDisposed = true;

                if (_pollingTimer != null)
                {
                    _pollingTimer.Dispose();
                    _pollingTimer = null;
                }
                _pollingEnabled = false;

                if (_keepSessionAliveTimer != null)
                {
                    _keepSessionAliveTimer.Dispose();
                    _keepSessionAliveTimer = null;
                }
                try
                {
                    foreach (var zyanProxy in AliveProxies)
                    {
                        zyanProxy.RemoveAllRemoteEventHandlers();
                    }
                    RemoteDispatcher.Logoff(_sessionID);
                }
                catch (RemotingException)
                { }
                catch (SocketException)
                { }
                catch (WebException)
                { }
                catch (MessageException)
                { }
                catch (Exception ex)
                {
                    Trace.WriteLine("Unexpected exception of type {0} caught while disposing ZyanConnection: {1}", ex.GetType(), ex.Message);
                }
                finally
                {
                    lock (_connections)
                    {
                        _connections.Remove(this);
                    }
                }
                if (_remotingChannel != null)
                {
                    // unsubscribe from connection notifications
                    var connectionNotification = _remotingChannel as IConnectionNotification;
                    if (connectionNotification != null)
                    {
                        connectionNotification.ConnectionEstablished -= Channel_ConnectionEstablished;
                    }

                    // unregister remoting channel
                    var registeredChannel = ChannelServices.GetChannel(_remotingChannel.ChannelName);
                    if (registeredChannel != null && registeredChannel == _remotingChannel)
                    {
                        ChannelServices.UnregisterChannel(_remotingChannel);
                    }

                    // dispose remoting channel, if it's disposable
                    var disposableChannel = _remotingChannel as IDisposable;
                    if (disposableChannel != null)
                    {
                        disposableChannel.Dispose();
                    }

                    _remotingChannel = null;
                }
                _remoteDispatcher      = null;
                _serverUrl             = string.Empty;
                _sessionID             = Guid.Empty;
                _protocolSetup         = null;
                _serializationHandling = null;
                _componentHostName     = string.Empty;

                if (_registeredComponents != null)
                {
                    _registeredComponents.Clear();
                    _registeredComponents = null;
                }
                if (_callInterceptors != null)
                {
                    _callInterceptors.Clear();
                    _callInterceptors = null;
                }
                if (_autoLoginCredentials != null)
                {
                    _autoLoginCredentials = null;
                }
                GC.WaitForPendingFinalizers();
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a new instance of the ZyanConnection class.
        /// </summary>
        /// <param name="serverUrl">URL of remote server (e.G. "tcp://server1:46123/myapp").</param>
        /// <param name="protocolSetup">Protocol and communication settings.</param>
        /// <param name="credentials">Login credentials.</param>
        /// <param name="autoLoginOnExpiredSession">Specifies whether the proxy should relogin automatically when the session expired.</param>
        /// <param name="keepSessionAlive">Specifies whether the session should be automaticly kept alive.</param>
        public ZyanConnection(string serverUrl, IClientProtocolSetup protocolSetup, AuthCredentials credentials, bool autoLoginOnExpiredSession, bool keepSessionAlive)
        {
            if (string.IsNullOrEmpty(serverUrl))
            {
                throw new ArgumentException(LanguageResource.ArgumentException_ServerUrlMissing, "serverUrl");
            }

            if (protocolSetup == null)
            {
                // try to select the protocol automatically
                protocolSetup = ClientProtocolSetup.GetClientProtocol(serverUrl);
                if (protocolSetup == null)
                {
                    throw new ArgumentNullException("protocolSetup");
                }
            }

            if (!protocolSetup.IsUrlValid(serverUrl))
            {
                throw new ArgumentException(LanguageResource.ArgumentException_ServerUrlIsInvalid, "serverUrl");
            }

            _proxies                   = new List <WeakReference>();
            _protocolSetup             = protocolSetup;
            _sessionID                 = Guid.NewGuid();
            _serverUrl                 = serverUrl;
            _autoLoginOnExpiredSession = autoLoginOnExpiredSession;
            _keepSessionAlive          = keepSessionAlive;

            if (_autoLoginOnExpiredSession)
            {
                _autoLoginCredentials = credentials;
            }

            _serializationHandling  = new SerializationHandlerRepository();
            CallInterceptionEnabled = false;
            _callInterceptors       = new CallInterceptorCollection();
            RegisterStandardSerializationHandlers();
            string[] addressParts = _serverUrl.Split('/');
            _componentHostName = addressParts[addressParts.Length - 1];

            _remotingChannel = _protocolSetup.CreateChannel();
            if (!ZyanSettings.DisableUrlRandomization)
            {
                _remotingChannel = ChannelWrapper.WrapChannel(_remotingChannel, _protocolSetup.ChannelName);
            }

            if (_remotingChannel != null)
            {
                var registeredChannel = ChannelServices.GetChannel(_remotingChannel.ChannelName);

                if (registeredChannel == null)
                {
                    ChannelServices.RegisterChannel(_remotingChannel, false);
                }
                else
                {
                    _remotingChannel = registeredChannel;
                }
            }
            else
            {
                throw new ApplicationException(LanguageResource.ApplicationException_NoChannelCreated);
            }

            var connectionNotification = _remotingChannel as IConnectionNotification;

            if (connectionNotification != null)
            {
                connectionNotification.ConnectionEstablished += Channel_ConnectionEstablished;
            }

            string channelName = _remotingChannel.ChannelName;

            if (credentials == null)
            {
                credentials = new AuthCredentials();
            }

            try
            {
                credentials.Authenticate(_sessionID, RemoteDispatcher);

                _registeredComponents = new List <ComponentInfo>(RemoteDispatcher.GetRegisteredComponents());
                _sessionAgeLimit      = RemoteDispatcher.SessionAgeLimit;
            }
            catch (Exception ex)
            {
                // unregister remoting channel
                var registeredChannel = ChannelServices.GetChannel(channelName);
                if (registeredChannel != null)
                {
                    ChannelServices.UnregisterChannel(registeredChannel);
                }

                // dispose channel if it's disposable
                var disposableChannel = registeredChannel as IDisposable;
                if (disposableChannel != null)
                {
                    disposableChannel.Dispose();
                }

                _remotingChannel  = null;
                _remoteDispatcher = null;
                throw ex.PreserveStackTrace();
            }

            var reconnectEvents  = new Action(ReconnectRemoteEventsCore);
            var debounceInterval = ZyanSettings.ReconnectRemoteEventsDebounceInterval.TotalMilliseconds;

            ReconnectRemoteEvents = reconnectEvents.Debounce((int)debounceInterval);

            StartKeepSessionAliveTimer();
            lock (_connections)
            {
                _connections.Add(this);
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Refreshes the list of server-side components.
 /// </summary>
 public void RefreshRegisteredComponents()
 {
     _registeredComponents = new List <ComponentInfo>(RemoteDispatcher.GetRegisteredComponents());
 }