/// <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(); }
//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)); }
/// <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; }
/// <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);
/// <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; }
/// <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); }
/// <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; }