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); }
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(); }
/// <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); } }
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); }
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; } } }
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; } }
internal Diagnostics(LinkSession owner) { this.owner = owner; }
/// <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); }
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); }
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); }
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; } } }
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); } }
/// <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); }
/// <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); } }
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; }
internal override void NotifySessionDisconnected(int handle, object context) { using (new WriteLock(rwlock)) { this.session = null; } base.NotifySessionDisconnected(handle, context); }
public Diagnostics(LinkSession owner) { this.owner = owner; }
/// <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; }
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() }); }
/// <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); } }
/// <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; } }
/// <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); }