예제 #1
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="type">packet type (message number)</param>
 public SSH1Packet(SSH1PacketType type)
 {
     if (_lockFlag.Value)
     {
         throw new InvalidOperationException(
                   "simultaneous editing packet detected: " + typeof(SSH1Packet).FullName);
     }
     _lockFlag.Value = true;
     _type           = type;
     _payload        = _payloadBuffer.Value;
     _payload.Clear();
 }
예제 #2
0
 //alternative version
 internal void TraceTransmissionEvent(SSH1PacketType pt, string message, params object[] args)
 {
     ISSHEventTracer t = _param.EventTracer;
     if (t != null)
         t.OnTranmission(pt.ToString(), String.Format(message, args));
 }
예제 #3
0
        /// <summary>
        /// Process packet about this channel.
        /// </summary>
        /// <param name="packetType">a packet type (message number)</param>
        /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
        public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment)
        {
            if (_state == State.Closed)
            {
                return; // ignore
            }

            DataFragment dataFragmentArg;

            lock (_stateSync) {
                switch (_state)
                {
                case State.Initial:
                    break;

                case State.WaitStartPTYResponse:
                    if (packetType == SSH1PacketType.SSH_SMSG_SUCCESS)
                    {
                        _state = State.StartPTYSuccess;
                        Monitor.PulseAll(_stateSync);       // notifies state change
                        _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT);
                    }
                    else if (packetType == SSH1PacketType.SSH_SMSG_FAILURE)
                    {
                        _state = State.StartPTYFailure;
                        Monitor.PulseAll(_stateSync);       // notifies state change
                        _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT);
                    }
                    break;

                case State.Established:
                    break;

                case State.Ready:
                    switch (packetType)
                    {
                    case SSH1PacketType.SSH_SMSG_STDOUT_DATA: {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        int            len    = reader.ReadInt32();
                        dataFragmentArg = reader.GetRemainingDataView(len);
                    }
                        goto OnData;            // do it out of the lock block

                    case SSH1PacketType.SSH_SMSG_STDERR_DATA: {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        int            len    = reader.ReadInt32();
                        dataFragmentArg = reader.GetRemainingDataView(len);
                    }
                        goto OnData;            // do it out of the lock block

                    case SSH1PacketType.SSH_SMSG_EXITSTATUS:
                        Transmit(
                            new SSH1Packet(SSH1PacketType.SSH_CMSG_EXIT_CONFIRMATION)
                            );
                        goto SetStateClosedByServer; // do it out of the lock block
                    }
                    goto OnUnhandledPacket;          // do it out of the lock block
                }
            }

            return;

OnData:
            Handler.OnData(dataFragmentArg);
            return;

SetStateClosedByServer:
            Trace("CH[{0}] closed by server", LocalChannel);
            SetStateClosed(true);
            return;

OnUnhandledPacket:
            Handler.OnUnhandledPacket((byte)packetType, packetFragment);
            return;
        }
예제 #4
0
 /// <summary>
 /// Process packet about this channel.
 /// </summary>
 /// <param name="packetType">a packet type (message number)</param>
 /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
 public abstract void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment);
예제 #5
0
        /// <summary>
        /// Process packet about this channel.
        /// </summary>
        /// <param name="packetType">a packet type (message number)</param>
        /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
        public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment)
        {
            if (_state == State.Closed)
            {
                return; // ignore
            }

            DataFragment dataFragmentArg;

            lock (_stateSync) {
                switch (_state)
                {
                case State.InitiatedByServer:
                    break;

                case State.InitiatedByClient:
                    if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION)
                    {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        SetRemoteChannel(reader.ReadUInt32());
                        _state = State.Established;
                        Monitor.PulseAll(_stateSync); // notifies state change
                        dataFragmentArg = new DataFragment(0);
                        goto OnEstablished;           // do it out of the lock block
                    }
                    if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE)
                    {
                        goto RequestFailed;     // do it out of the lock block
                    }
                    break;

                case State.Closing:
                    if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION)
                    {
                        goto SetStateClosedByClient;        // do it out of the lock block
                    }
                    break;

                case State.Established:
                case State.Ready:
                    if (ProcessPacketSub(packetType, packetFragment) == SubPacketProcessResult.Consumed)
                    {
                        return;
                    }
                    switch (packetType)
                    {
                    case SSH1PacketType.SSH_MSG_CHANNEL_DATA: {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        int            len    = reader.ReadInt32();
                        dataFragmentArg = reader.GetRemainingDataView(len);
                    }
                        goto OnData;            // do it out of the lock block

                    case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE:
                        Transmit(
                            new SSH1Packet(SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION)
                            .WriteUInt32(RemoteChannel)
                            );
                        goto SetStateClosedByServer; // do it out of the lock block
                    }
                    goto OnUnhandledPacket;          // do it out of the lock block
                }
            }

            return;

OnEstablished:
            Trace("CH[{0}] channel opend : remoteChannel={1}", LocalChannel, RemoteChannel);
            Handler.OnEstablished(dataFragmentArg);
            OnChannelEstablished();
            return;

RequestFailed:
            Trace("CH[{0}] request failed", LocalChannel);
            RequestFailed();
            return;

SetStateClosedByClient:
            Trace("CH[{0}] closed by client", LocalChannel);
            SetStateClosed(false);
            return;

SetStateClosedByServer:
            Trace("CH[{0}] closed by server", LocalChannel);
            SetStateClosed(true);
            return;

OnData:
            Handler.OnData(dataFragmentArg);
            return;

OnUnhandledPacket:
            Handler.OnUnhandledPacket((byte)packetType, packetFragment);
            return;
        }
예제 #6
0
 /// <summary>
 /// Process packet additionally.
 /// </summary>
 /// <remarks>
 /// This method will be called repeatedly while <see cref="State"/> is <see cref="State.Established"/> or <see cref="State.Ready"/>.
 /// </remarks>
 /// <param name="packetType">a packet type (message number)</param>
 /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
 /// <returns>result</returns>
 protected virtual SubPacketProcessResult ProcessPacketSub(SSH1PacketType packetType, DataFragment packetFragment)
 {
     // derived class can override this.
     return(SubPacketProcessResult.NotConsumed);
 }
예제 #7
0
        /// <summary>
        /// Process packet about this channel.
        /// </summary>
        /// <param name="packetType">a packet type (message number)</param>
        /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
        public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment)
        {
            if (_state == State.Closed) {
                return; // ignore
            }

            DataFragment dataFragmentArg;

            lock (_stateSync) {
                switch (_state) {
                    case State.Initial:
                        break;
                    case State.WaitStartPTYResponse:
                        if (packetType == SSH1PacketType.SSH_SMSG_SUCCESS) {
                            _state = State.StartPTYSuccess;
                            Monitor.PulseAll(_stateSync);   // notifies state change
                            _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT);
                        }
                        else if (packetType == SSH1PacketType.SSH_SMSG_FAILURE) {
                            _state = State.StartPTYFailure;
                            Monitor.PulseAll(_stateSync);   // notifies state change
                            _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT);
                        }
                        break;
                    case State.Established:
                        break;
                    case State.Ready:
                        switch (packetType) {
                            case SSH1PacketType.SSH_SMSG_STDOUT_DATA: {
                                    SSH1DataReader reader = new SSH1DataReader(packetFragment);
                                    int len = reader.ReadInt32();
                                    dataFragmentArg = reader.GetRemainingDataView(len);
                                }
                                goto OnData;    // do it out of the lock block
                            case SSH1PacketType.SSH_SMSG_STDERR_DATA: {
                                    SSH1DataReader reader = new SSH1DataReader(packetFragment);
                                    int len = reader.ReadInt32();
                                    dataFragmentArg = reader.GetRemainingDataView(len);
                                }
                                goto OnData;    // do it out of the lock block
                            case SSH1PacketType.SSH_SMSG_EXITSTATUS:
                                Transmit(
                                    new SSH1Packet(SSH1PacketType.SSH_CMSG_EXIT_CONFIRMATION)
                                );
                                goto SetStateClosedByServer;    // do it out of the lock block
                        }
                        goto OnUnhandledPacket; // do it out of the lock block
                }
            }

            return;

            OnData:
            Handler.OnData(dataFragmentArg);
            return;

            SetStateClosedByServer:
            Trace("CH[{0}] closed by server", LocalChannel);
            SetStateClosed(true);
            return;

            OnUnhandledPacket:
            Handler.OnUnhandledPacket((byte)packetType, packetFragment);
            return;
        }
예제 #8
0
 /// <summary>
 /// Process packet about this channel.
 /// </summary>
 /// <param name="packetType">a packet type (message number)</param>
 /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
 public abstract void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment);
예제 #9
0
 /// <summary>
 /// Process packet additionally.
 /// </summary>
 /// <remarks>
 /// This method will be called repeatedly while <see cref="State"/> is <see cref="State.Established"/> or <see cref="State.Ready"/>.
 /// </remarks>
 /// <param name="packetType">a packet type (message number)</param>
 /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
 /// <returns>result</returns>
 protected virtual SubPacketProcessResult ProcessPacketSub(SSH1PacketType packetType, DataFragment packetFragment)
 {
     // derived class can override this.
     return SubPacketProcessResult.NotConsumed;
 }
예제 #10
0
        /// <summary>
        /// Process packet about this channel.
        /// </summary>
        /// <param name="packetType">a packet type (message number)</param>
        /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
        public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment)
        {
            if (_state == State.Closed) {
                return; // ignore
            }

            DataFragment dataFragmentArg;

            lock (_stateSync) {
                switch (_state) {
                    case State.InitiatedByServer:
                        break;
                    case State.InitiatedByClient:
                        if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
                            SSH1DataReader reader = new SSH1DataReader(packetFragment);
                            SetRemoteChannel(reader.ReadUInt32());
                            _state = State.Established;
                            Monitor.PulseAll(_stateSync);   // notifies state change
                            dataFragmentArg = new DataFragment(0);
                            goto OnEstablished; // do it out of the lock block
                        }
                        if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE) {
                            goto RequestFailed; // do it out of the lock block
                        }
                        break;
                    case State.Closing:
                        if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION) {
                            goto SetStateClosedByClient;    // do it out of the lock block
                        }
                        break;
                    case State.Established:
                    case State.Ready:
                        if (ProcessPacketSub(packetType, packetFragment) == SubPacketProcessResult.Consumed) {
                            return;
                        }
                        switch (packetType) {
                            case SSH1PacketType.SSH_MSG_CHANNEL_DATA: {
                                    SSH1DataReader reader = new SSH1DataReader(packetFragment);
                                    int len = reader.ReadInt32();
                                    dataFragmentArg = reader.GetRemainingDataView(len);
                                }
                                goto OnData;    // do it out of the lock block
                            case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE:
                                Transmit(
                                    new SSH1Packet(SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION)
                                        .WriteUInt32(RemoteChannel)
                                );
                                goto SetStateClosedByServer;    // do it out of the lock block
                        }
                        goto OnUnhandledPacket; // do it out of the lock block
                }
            }

            return;

            OnEstablished:
            Trace("CH[{0}] channel opend : remoteChannel={1}", LocalChannel, RemoteChannel);
            Handler.OnEstablished(dataFragmentArg);
            OnChannelEstablished();
            return;

            RequestFailed:
            Trace("CH[{0}] request failed", LocalChannel);
            RequestFailed();
            return;

            SetStateClosedByClient:
            Trace("CH[{0}] closed by client", LocalChannel);
            SetStateClosed(false);
            return;

            SetStateClosedByServer:
            Trace("CH[{0}] closed by server", LocalChannel);
            SetStateClosed(true);
            return;

            OnData:
            Handler.OnData(dataFragmentArg);
            return;

            OnUnhandledPacket:
            Handler.OnUnhandledPacket((byte)packetType, packetFragment);
            return;
        }