예제 #1
0
        public void DisconnectConnection(byte connectionId, ushort seq)
        {
            const long waitTime = 120000; // 2 minute disconnect time
            const int  disconnectRetryTimeout = 20000;

            Logger.Debug("Disconnecting tcp session " + connectionId);
            try
            {
                var packet = new StandardDisconnectPacket(connectionId);
                packet.Sequence = seq;
                long startTime = DateTime.Now.Ticks;
                _disconnectEvents[connectionId] = new AutoResetEvent(false);
                do
                {
                    // we only do this if we haven't received the ack of our disconnect
                    if (!_disconnectAcks.ContainsKey(connectionId))
                    {
                        _transport.SendData(packet);
                        packet.ResendCount++;
                    }
                    else
                    {
                        Logger.Debug("Will not resend disconnect request, remote side has acked it already");
                    }
                    var timeSpan = new TimeSpan(DateTime.Now.Ticks - startTime);
                    if (timeSpan.TotalMilliseconds > waitTime)
                    {
                        Logger.Debug("Disconnect timeout : " + timeSpan.TotalMilliseconds + "ms");
                        break;
                    }
                    Logger.Debug("Waiting for disconnect response for connection id " + connectionId);
                } while (_disconnectEvents.ContainsKey(connectionId) && !_disconnectEvents[connectionId].WaitOne(disconnectRetryTimeout));

                if (_disconnectEvents.ContainsKey(connectionId))
                {
                    // this means the disconnect wasn't acknowledged, oh well!
                    Logger.Warn("Failed to receive a disconnect response for connection id " + connectionId + ", closing regardless.");
                }
            }
            catch (Exception e)
            {
                Logger.Error("Failed to send the close packet, closing connection anyway. : " + e.Message, e);
            }
            if (_disconnectEvents.ContainsKey(connectionId))
            {
                _disconnectEvents.Remove(connectionId);
            }
            if (_disconnectAcks.ContainsKey(connectionId))
            {
                _disconnectAcks.Remove(connectionId);
            }
        }
예제 #2
0
        public BasicTcpPacket getPacket(byte[] bytes)
        {
            BasicTcpPacket packet;

            switch (bytes[BasicTcpPacket.PKT_POS_TYPE])
            {
            case BasicTcpPacket.PKT_TYPE_DISCONNECT:
                packet = new StandardDisconnectPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_DISCONNECT_ACK:
                packet = new StandardDisconnectAckPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_DISCONNECT_RS:
                packet = new StandardDisconnectRsPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_CONNECT_RS_ACK:
                packet = new StandardConnectRsAckPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_CONNECT_NAME_RS:
                packet = new StandardNamedConnectRsPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_CONNECT_NAME_RQ:
                packet = new StandardNamedConnectRqPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_DATA:
                packet = new StandardTcpDataPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_ACK:
                packet = new StandardAckPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_NOP:
                packet = new StandardTcpNopPacket();
                break;

            default:
                throw new UnknownPacketException("Failed to determine packet type");
            }
            packet.ProcessPacket(bytes);
            return(packet);
        }
예제 #3
0
 private void ProcessDisconnectPacket(StandardDisconnectPacket packet)
 {
     // immediately acknowlege that we got it (with remote connection id as the connection id)
     SendData(new StandardDisconnectAckPacket(packet.ConnectionId));
     // if we are not disconnecting, start the process.
     try
     {
         // do we have it in our list?
         TcpConnectionHolder connectionHolder = _tcpConnections.GetRemoteConnection(packet.ConnectionId);
         // this method will send the disconnectRs packet
         connectionHolder.Connection.ProcessDisconnect(packet);
     }
     catch (Exception e)
     {
         Logger.Error("Failed to close connection [remote id = " + packet.ConnectionId + "] : " + e.Message);
     }
 }
예제 #4
0
        public override void ProcessDisconnect(StandardDisconnectPacket packet)
        {
            if (!_isDisconnecting)
            {
                _isDisconnecting = true;
                // Turn off our data sender, remote host won't process the data anyway
                // release a potentially blocked data sender
                ReleaseDataSender();
                // clear the data retry timer
                if (_retryTimer.Enabled)
                {
                    _retryTimer.Stop();
                }

                if (Stats.DataPacketsReceived > 0 && packet.Sequence == (_nextDataSeqIn - 1))
                {
                    // Wait for all data to arrive (disconnect notified us of the last seq)
                    long      startTime   = Environment.TickCount;
                    int       elapsedTime = 0;
                    const int timeout     = 60000;
                    lock (_processDataLock)
                    {
#if DEBUG
                        Logger.Debug("Waiting for all data which was sent to arrive, up until " + packet.Sequence);
#endif
                        while (elapsedTime < timeout &&
                               (_lastAckedPacket == null || _lastAckedPacket.Sequence < packet.Sequence))
                        {
                            Monitor.Wait(_processDataLock, timeout - elapsedTime);
                            elapsedTime = (int)(Environment.TickCount - startTime);
                        }
                    }
                    if (_lastAckedPacket == null || _lastAckedPacket.Sequence < packet.Sequence)
                    {
                        Logger.Error(
                            "Failed to receive all the sent data packets during disconnect, timeout while waiting, last acked packet is " +
                            _lastAckedPacket + ", we wanted " + packet.Sequence);
                    }
                    else
                    {
                        Logger.Debug("We have successfully received all the data that was sent : expected " +
                                     packet.Sequence + ", got " + _lastAckedPacket.Sequence);
                    }
                }
                else
                {
                    Logger.Debug("Don't have to wait for all data to arrive, because none has been sent.");
                }
                // Mark it as disconnected
                _disconnected = true;

                // Now close upstream
                if (Established && !Closing && !Closed)
                {
                    Logger.Debug("Closing connection after disconnect " + ConnectionId + "-" + RemoteConnectionId);
                    Closing = true;
                    var closer = new Thread(CompleteClose)
                    {
                        IsBackground = true, Name = "closer[" + ConnectionId + "-" + RemoteConnectionId + "]"
                    };
                    closer.Start();
                }
            }
        }
 public override void ProcessDisconnect(StandardDisconnectPacket packet)
 {
     throw new NotImplementedException();
 }
예제 #6
0
 public abstract void ProcessDisconnect(StandardDisconnectPacket packet);