Exemple #1
0
        internal override void NotifySessionConnected(bool result, object context)
        {
            if (result == true)
            {
                var session = (LinkSession)context;
                using (new WriteLock(rwlock))
                {
                    this.session = session;
                }
            }

            base.NotifySessionConnected(result, context);
        }
Exemple #2
0
        internal void OnSessionResp(LinkSession session, SessionResp e)
        {
            LinkSession currentSession = Session;
            string sessionToken = null;
            if (!Object.ReferenceEquals(currentSession, null))
            {
                sessionToken = currentSession.Token;
            }

            // Save the session token from the server.
            session.Token = e.Token;

            Log.Trace("{0} {1} session token {2}",
                Name, session.InternalHandle, e.Token);

            if (!String.IsNullOrEmpty(sessionToken))
            {
                if (sessionToken.Equals(e.Token))
                {
                    // Recovered from instant disconnection.
                    session.InheritFrom(this.session);

                    session.Send(new SessionAck {
                        _Transform = false,
                        Recovered = true
                    });

                    OnLinkSessionRecoveredInternal(session.Handle, session, e.Retransmission);
                    return;
                }

                OnLinkSessionDisconnectedInternal(currentSession.Handle, currentSession);
            }

            session.Send(new SessionAck { _Transform = false });

            OnSessionSetup(session);
        }
        internal override void OnInstantDisconnect(LinkSession session)
        {
            LinkSession currentSession = Session;
            if (!Object.ReferenceEquals(session, currentSession))
            {
                Log.Warn("{0} gave up session recovery {1}", Name, session.Handle);
                return;
            }

            recovering = true;

            Reconnect();
        }
Exemple #4
0
        /// <summary>
        /// Called by a derived link class on a successful connect. 
        /// </summary>
        protected virtual void OnConnectInternal(LinkSession session)
        {
            session.Polarity = true;

            if (SessionRecoveryEnabled)
            {
                SendSessionReq(session);
            }
            else
            {
                OnSessionSetup(session);
            }
        }
Exemple #5
0
        internal override void OnInstantDisconnect(LinkSession session)
        {
            bool flag;
            // Ensure that the specified session is recoverable.
            LinkSession existing = null;
            lock (recoverable)
            {
                flag = recoverable.TryGetValue(session.Token, out existing);
            }
            if (!flag)
            {
                Log.Info("{0} {1} unrecoverable session", Name, session.Handle);

                OnLinkSessionDisconnectedInternal(session.Handle, session);
                return;
            }
            else if (!Object.ReferenceEquals(session, existing))
            {
                Log.Warn("{0} {1} gave up session recovery", Name, session.Handle);
                return;
            }

            existing = null;
            using (new ReadLock(rwlock))
            {
                sessions.TryGetValue(session.Handle, out existing);
            }
            if (!Object.ReferenceEquals(session, existing))
            {
                Log.Warn("{0} {1} gave up session recovery", Name, session.Handle);
                return;
            }

            var e = new TimeoutEvent { Key = session };

            Binder.Token binderToken = this.Flow.Subscribe(e, OnSessionRecoveryTimeout);
            TimeFlow.Default.Reserve(e, SessionRecoveryTimeout);
            lock (recoveryTokens)
            {
                recoveryTokens[session.Handle] = binderToken;
            }

            Log.Trace("{0} {1} started recovery timer", Name, session.Handle);
        }
Exemple #6
0
        internal void OnSessionReq(LinkSession session, SessionReq e)
        {
            string clientToken = e.Token;
            bool flag = false;
            if (!String.IsNullOrEmpty(clientToken))
            {
                int incomingRetransmission = 0;
                int outgoingRetransmission = 0;
                LinkSession existing;
                lock (recoverable)
                {
                    flag = recoverable.TryGetValue(clientToken, out existing);
                }
                if (flag)
                {
                    Log.Trace("{0} {1} rxC={2} txC={3} rxS={4} txS={5} txSc={6}",
                        Name, existing.Handle, e.RxCounter, e.TxCounter,
                        existing.RxCounter, existing.TxCounter, existing.TxCompleted);

                    if (e.RxCounter < existing.TxCounter)
                    {
                        outgoingRetransmission = (int)(existing.TxCounter - e.RxCounter);
                        if (outgoingRetransmission > existing.TxBuffered)
                        {
                            flag = false;
                        }
                    }
                    if (e.TxCounter > existing.RxCounter)
                    {
                        incomingRetransmission = (int)(e.TxCounter - existing.RxCounter);
                        if (incomingRetransmission > e.TxBuffered)
                        {
                            flag = false;
                        }
                    }
                    if (!flag)
                    {
                        Log.Warn("{0} {1} gave up session recovery",
                            Name, existing.Handle);

                        OnLinkSessionDisconnectedInternal(existing.Handle, existing);
                    }
                }
                if (flag)
                {
                    int handle;
                    lock (existing.SyncRoot)
                    {
                        handle = existing.Handle;
                    }

                    if (handle != 0)
                    {
                        lock (existing.SyncRoot)
                        {
                            CancelRecoveryTimer(handle);
                            session.InheritFrom(existing);
                        }

                        session.Send(new SessionResp {
                            _Transform = false,
                            Token = session.Token,
                            Retransmission = incomingRetransmission
                        });

                        OnLinkSessionRecoveredInternal(handle, session, outgoingRetransmission);
                        return;
                    }
                }
            }

            // Issue a new session token for the given session.
            session.Token = Guid.NewGuid().ToString("N");

            Log.Debug("{0} {1} issued session token {2}",
                Name, session.InternalHandle, session.Token);

            lock (recoverable)
            {
                recoverable[session.Token] = session;
            }

            session.Send(new SessionResp {
                _Transform = false,
                Token = session.Token
            });
        }
        public void Close(bool disconnect)
        {
            Dispose();

            if (LinkSession != null)
            {
                if (disconnect)
                {
                    LinkSession.Close();
                }
                else
                {
                    LinkSession = null;
                }
            }
        }
Exemple #8
0
        internal void InheritFrom(LinkSession oldSession)
        {
            lock (syncRoot)
            {
                handle = oldSession.Handle;
                Token = oldSession.Token;

                Log.Debug("{0} {1} session inheritance {2}",
                    link.Name, handle, Token);

                BufferTransform = oldSession.BufferTransform;
                rxTransformReady = oldSession.rxTransformReady;
                txTransformReady = oldSession.txTransformReady;
            }
        }
Exemple #9
0
 internal Diagnostics(LinkSession owner)
 {
     this.owner = owner;
 }
Exemple #10
0
        /// <summary>
        /// Frees managed or unmanaged resources.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposed) { return; }

            using (new WriteLock(rwlock))
            {
                if (session != null)
                {
                    session.Close();
                    session = null;
                }
            }

            base.Dispose(disposing);
        }
Exemple #11
0
        private void SendSessionReq(LinkSession session)
        {
            var req = new SessionReq { _Transform = false };

            LinkSession currentSession = Session;
            if (!Object.ReferenceEquals(currentSession, null) &&
                !String.IsNullOrEmpty(currentSession.Token))
            {
                req.Token = currentSession.Token;
                req.RxCounter = currentSession.RxCounter;
                req.TxCounter = currentSession.TxCounter;
                req.TxBuffered = currentSession.TxBuffered;
            }

            session.Send(req);
        }
Exemple #12
0
        protected override void OnSessionRecoveredInternal(
            int handle, object context, int retransmission)
        {
            LinkSession oldSession;
            var session = (LinkSession)context;
            using (new WriteLock(rwlock))
            {
                oldSession = this.session;
                this.session = session;
            }

            session.TakeOver(oldSession, retransmission);

            Log.Debug("{0} {1} reset session {2}",
                Name, session.Handle, session.Token);
        }
Exemple #13
0
        protected override void OnSessionDisconnectedInternal(int handle, object context)
        {
            using (new WriteLock(rwlock))
            {
                if (!Object.ReferenceEquals(session, null))
                {
                    Log.Debug("{0} {1} cleared session {2}",
                        Name, session.Handle, session.Token);

                    session = null;
                }
            }
        }
Exemple #14
0
        protected override void OnSessionConnectedInternal(bool result, object context)
        {
            if (result)
            {
                var session = (LinkSession)context;
                using (new WriteLock(rwlock))
                {
                    this.session = session;
                }

                Log.Debug("{0} {1} set session {2}",
                    Name, session.Handle, session.Token);
            }
        }
Exemple #15
0
        /// <summary>
        /// <see cref="ClientLink.OnConnectInternal"/>
        /// </summary>
        protected override void OnConnectInternal(LinkSession session)
        {
            var tcpSession = (AbstractTcpSession)session;
            Socket socket = tcpSession.Socket;

            // Adjust socket options.
            socket.NoDelay = NoDelay;

            // Save the remote endpoint to reconnect.
            remoteEndPoint = socket.RemoteEndPoint;

            tcpSession.BeginReceive(true);

            Log.Info("{0} {1} connected to {2}",
                Name, tcpSession.InternalHandle, socket.RemoteEndPoint);

            base.OnConnectInternal(session);
        }
        /// <summary>
        /// <see cref="ServerLink.OnAcceptInternal"/>
        /// </summary>
        protected override bool OnAcceptInternal(LinkSession session)
        {
            var tcpSession = (AbstractTcpSession)session;
            var clientSocket = tcpSession.Socket;

            // Adjust client socket options.
            clientSocket.NoDelay = NoDelay;

            tcpSession.BeginReceive(true);

            Log.Info("{0} {1} accepted from {2}",
                Name, session.Handle, clientSocket.RemoteEndPoint);

            return base.OnAcceptInternal(session);
        }
Exemple #17
0
        /// <summary>
        /// Called by a derived link class on a successful connect. 
        /// </summary>
        protected virtual void OnConnectInternal(LinkSession session)
        {
            session.Polarity = true;

            if (BufferTransform != null)
            {
                InitiateHandshake(session);
            }
            else
            {
                NotifySessionConnected(true, session);
            }
        }
Exemple #18
0
        public void TakeOver(LinkSession oldSession, int retransmission)
        {
            if (retransmission == 0)
            {
                lock (syncRoot)
                {
                    lock (oldSession.syncRoot)
                    {
                        if (oldSession.buffersSending.Count != 0)
                        {
                            // Dispose them
                            for (int i = 0, count = oldSession.buffersSending.Count; i < count; ++i)
                            {
                                oldSession.buffersSending[i].Dispose();
                            }
                            oldSession.buffersSending.Clear();
                        }
                        if (oldSession.buffersSent.Count != 0)
                        {
                            // Dispose them
                            for (int i = 0, count = oldSession.buffersSent.Count; i < count; ++i)
                            {
                                oldSession.buffersSent[i].Dispose();
                            }
                            oldSession.buffersSent.Clear();
                        }

                        Log.Info("{0} {1} pre-establishment buffered {2}",
                            link.Name, InternalHandle, preConnectionQueue.Count);

                        if (preConnectionQueue.Count != 0)
                        {
                            eventsToSend.InsertRange(0, preConnectionQueue);
                            preConnectionQueue.Clear();
                        }
                        if (oldSession.eventsToSend.Count != 0)
                        {
                            eventsToSend.InsertRange(0, oldSession.eventsToSend);
                            oldSession.eventsToSend.Clear();
                        }

                        Log.Info("{0} {1} eventsToSend {2}", link.Name, InternalHandle, eventsToSend.Count);
                    }

                    connected = true;

                    if (txFlag || eventsToSend.Count == 0)
                    {
                        return;
                    }

                    txFlag = true;
                }

                BeginSend();
            }
            else
            {
                Monitor.Enter(syncRoot);
                try
                {
                    // Wait for any existing send to complete
                    while (txFlag)
                    {
                        Monitor.Exit(syncRoot);
                        Thread.Sleep(1);
                        Monitor.Enter(syncRoot);
                    }

                    txBufferList.Clear();
                    lengthToSend = 0;
                    buffersSending.Clear();

                    lock (oldSession.syncRoot)
                    {
                        List<SendBuffer> buffers1, buffers2;

                        if (oldSession.TxCounter == oldSession.TxCompleted)
                        {
                            buffers1 = oldSession.buffersSending;
                            buffers2 = oldSession.buffersSent;
                        }
                        else
                        {
                            buffers1 = oldSession.buffersSent;
                            buffers2 = oldSession.buffersSending;
                        }

                        int numBuffers1ToDispose = oldSession.TxBuffered - retransmission;
                        if (numBuffers1ToDispose > buffers1.Count)
                        {
                            numBuffers1ToDispose = buffers1.Count;
                        }
                        int numBuffers2ToDispose = buffers2.Count - retransmission;
                        if (numBuffers2ToDispose < 0)
                        {
                            numBuffers2ToDispose = 0;
                        }

                        int i;

                        for (i = 0; i < numBuffers1ToDispose; ++i)
                        {
                            buffers1[i].Dispose();
                        }
                        for (; i < buffers1.Count; ++i)
                        {
                            SendBuffer buffer = buffers1[i];
                            buffersSending.Add(buffer);
                            buffer.ListOccupiedSegments(txBufferList);
                            lengthToSend += buffer.Length;
                        }
                        buffers1.Clear();

                        for (i = 0; i < numBuffers2ToDispose; ++i)
                        {
                            buffers2[i].Dispose();
                        }
                        for (; i < buffers2.Count; ++i)
                        {
                            SendBuffer buffer = buffers2[i];
                            buffersSending.Add(buffer);
                            buffer.ListOccupiedSegments(txBufferList);
                            lengthToSend += buffer.Length;
                        }
                        buffers2.Clear();

                        Log.Info("{0} {1} pre-establishment buffered {2}",
                            link.Name, InternalHandle, preConnectionQueue.Count);

                        if (preConnectionQueue.Count != 0)
                        {
                            eventsToSend.InsertRange(0, preConnectionQueue);
                            preConnectionQueue.Clear();
                        }
                        if (oldSession.eventsToSend.Count != 0)
                        {
                            eventsToSend.InsertRange(0, oldSession.eventsToSend);
                            oldSession.eventsToSend.Clear();
                        }

                        Log.Info("{0} {1} eventsToSend {2}", link.Name, InternalHandle, eventsToSend.Count);
                    }

                    Log.Warn("{0} {1} retransmitting {2} events ({3} bytes)",
                        link.Name, InternalHandle, retransmission, lengthToSend);

                    connected = true;

                    txFlag = true;
                }
                finally
                {
                    Monitor.Exit(syncRoot);
                }

                Interlocked.Add(ref txCounter, retransmission);

                SendInternal();
            }

            oldSession = null;
            retransmission = 0;
        }
Exemple #19
0
        internal override void NotifySessionDisconnected(int handle, object context)
        {
            using (new WriteLock(rwlock))
            {
                this.session = null;
            }

            base.NotifySessionDisconnected(handle, context);
        }
Exemple #20
0
 public Diagnostics(LinkSession owner)
 {
     this.owner = owner;
 }
Exemple #21
0
 /// <summary>
 /// Called by a derived link class on a successful accept.
 /// </summary>
 protected virtual bool OnAcceptInternal(LinkSession session)
 {
     if (BufferTransform != null)
     {
         InitiateHandshake(session);
     }
     else
     {
         NotifySessionConnected(true, session);
     }
     return true;
 }
Exemple #22
0
 internal void OnSessionAck(LinkSession session, SessionAck e)
 {
     if (!e.Recovered)
     {
         OnSessionSetup(session);
     }
 }
        /// <summary>
        /// Called by a derived class to initiate a buffer transform handshake.
        /// </summary>
        protected void InitiateHandshake(LinkSession session)
        {
            if (Object.ReferenceEquals(BufferTransform, null))
            {
                return;
            }

            var bufferTransform = (IBufferTransform)BufferTransform.Clone();
            session.BufferTransform = bufferTransform;

            session.Send(new HandshakeReq {
                _Transform = false,
                Data = bufferTransform.InitializeHandshake()
            });
        }
Exemple #24
0
 /// <summary>
 /// Called by a derived link class on a successful accept.
 /// </summary>
 protected virtual bool OnAcceptInternal(LinkSession session)
 {
     if (!SessionRecoveryEnabled)
     {
         OnSessionSetup(session);
     }
     return true;
 }
 protected internal void OnPreprocess(LinkSession session, Event e)
 {
     if (Preprocess != null)
     {
         Preprocess(session, e);
     }
 }
Exemple #26
0
        /// <summary>
        /// <see cref="ServerLink.OnAcceptInternal"/>
        /// </summary>
        protected override bool OnAcceptInternal(LinkSession session)
        {
            var tcpSession = (AbstractTcpSession)session;
            var clientSocket = tcpSession.Socket;

            try
            {
                // Adjust client socket options.
                clientSocket.NoDelay = NoDelay;

                tcpSession.BeginReceive(true);

                Log.Info("{0} {1} accepted from {2}",
                    Name, tcpSession.InternalHandle, clientSocket.RemoteEndPoint);

                return base.OnAcceptInternal(session);

            }
            catch (ObjectDisposedException ode)
            {
                Log.Warn("{0} {1} accept error: {2}",
                    Name, tcpSession.InternalHandle, ode);
                return false;
            }
        }
Exemple #27
0
        /// <summary>
        /// Frees managed or unmanaged resources.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposed) { return; }

            LinkSession session = null;
            using (new WriteLock(rwlock))
            {
                if (this.session != null)
                {
                    session = this.session;
                    this.session = null;
                }
            }
            if (session != null)
            {
                session.Close();
            }

            base.Dispose(disposing);
        }