3535//! [Session]: client::Session
3636
3737use std:: cell:: RefCell ;
38- use std:: collections:: HashMap ;
38+ use std:: collections:: { HashMap , VecDeque } ;
3939use std:: num:: Wrapping ;
4040use std:: pin:: Pin ;
4141use std:: sync:: Arc ;
@@ -55,12 +55,15 @@ use tokio::pin;
5555use tokio:: sync:: mpsc:: {
5656 channel, unbounded_channel, Receiver , Sender , UnboundedReceiver , UnboundedSender ,
5757} ;
58- use tokio:: sync:: Mutex ;
58+ use tokio:: sync:: { oneshot , Mutex } ;
5959
6060use crate :: channels:: { Channel , ChannelMsg , ChannelRef } ;
6161use crate :: cipher:: { self , clear, CipherPair , OpeningKey } ;
6262use crate :: key:: PubKey ;
63- use crate :: session:: { CommonSession , EncryptedState , Exchange , Kex , KexDhDone , KexInit , NewKeys } ;
63+ use crate :: session:: {
64+ CommonSession , EncryptedState , Exchange , GlobalRequestResponse , Kex , KexDhDone , KexInit ,
65+ NewKeys ,
66+ } ;
6467use crate :: ssh_read:: SshRead ;
6568use crate :: sshbuffer:: { SSHBuffer , SshId } ;
6669use crate :: {
@@ -87,6 +90,7 @@ pub struct Session {
8790 pending_len : u32 ,
8891 inbound_channel_sender : Sender < Msg > ,
8992 inbound_channel_receiver : Receiver < Msg > ,
93+ open_global_requests : VecDeque < GlobalRequestResponse > ,
9094}
9195
9296const STRICT_KEX_MSG_ORDER : & [ u8 ] = & [ msg:: KEXINIT , msg:: KEX_ECDH_REPLY , msg:: NEWKEYS ] ;
@@ -146,12 +150,14 @@ pub enum Msg {
146150 channel_ref : ChannelRef ,
147151 } ,
148152 TcpIpForward {
149- want_reply : bool ,
153+ /// Provide a channel for the reply result to request a reply from the server
154+ reply_channel : Option < oneshot:: Sender < Option < u32 > > > ,
150155 address : String ,
151156 port : u32 ,
152157 } ,
153158 CancelTcpIpForward {
154- want_reply : bool ,
159+ /// Provide a channel for the reply result to request a reply from the server
160+ reply_channel : Option < oneshot:: Sender < bool > > ,
155161 address : String ,
156162 port : u32 ,
157163 } ,
@@ -507,39 +513,57 @@ impl<H: Handler> Handle<H> {
507513 . await
508514 }
509515
516+ /// Requests the server to open a TCP/IP forward channel
517+ ///
518+ /// If port == 0 the server will choose a port that will be returned, returns 0 otherwise
510519 pub async fn tcpip_forward < A : Into < String > > (
511520 & mut self ,
512521 address : A ,
513522 port : u32 ,
514- ) -> Result < bool , crate :: Error > {
523+ ) -> Result < u32 , crate :: Error > {
524+ let ( reply_send, reply_recv) = oneshot:: channel ( ) ;
515525 self . sender
516526 . send ( Msg :: TcpIpForward {
517- want_reply : true ,
527+ reply_channel : Some ( reply_send ) ,
518528 address : address. into ( ) ,
519529 port,
520530 } )
521531 . await
522532 . map_err ( |_| crate :: Error :: SendError ) ?;
523- if port == 0 {
524- self . wait_recv_reply ( ) . await ?;
533+
534+ match reply_recv. await {
535+ Ok ( Some ( port) ) => Ok ( port) ,
536+ Ok ( None ) => Err ( crate :: Error :: RequestDenied ) ,
537+ Err ( e) => {
538+ error ! ( "Unable to receive TcpIpForward result: {e:?}" ) ;
539+ Err ( crate :: Error :: Disconnect )
540+ }
525541 }
526- Ok ( true )
527542 }
528543
529544 pub async fn cancel_tcpip_forward < A : Into < String > > (
530545 & self ,
531546 address : A ,
532547 port : u32 ,
533- ) -> Result < bool , crate :: Error > {
548+ ) -> Result < ( ) , crate :: Error > {
549+ let ( reply_send, reply_recv) = oneshot:: channel ( ) ;
534550 self . sender
535551 . send ( Msg :: CancelTcpIpForward {
536- want_reply : true ,
552+ reply_channel : Some ( reply_send ) ,
537553 address : address. into ( ) ,
538554 port,
539555 } )
540556 . await
541557 . map_err ( |_| crate :: Error :: SendError ) ?;
542- Ok ( true )
558+
559+ match reply_recv. await {
560+ Ok ( true ) => Ok ( ( ) ) ,
561+ Ok ( false ) => Err ( crate :: Error :: RequestDenied ) ,
562+ Err ( e) => {
563+ error ! ( "Unable to receive CancelTcpIpForward result: {e:?}" ) ;
564+ Err ( crate :: Error :: Disconnect )
565+ }
566+ }
543567 }
544568
545569 /// Sends a disconnect message.
@@ -707,6 +731,7 @@ impl Session {
707731 channels : HashMap :: new ( ) ,
708732 pending_reads : Vec :: new ( ) ,
709733 pending_len : 0 ,
734+ open_global_requests : VecDeque :: new ( ) ,
710735 }
711736 }
712737
@@ -931,15 +956,15 @@ impl Session {
931956 self . channels . insert ( id, channel_ref) ;
932957 }
933958 Msg :: TcpIpForward {
934- want_reply ,
959+ reply_channel ,
935960 address,
936961 port,
937- } => self . tcpip_forward ( want_reply , & address, port) ,
962+ } => self . tcpip_forward ( reply_channel , & address, port) ,
938963 Msg :: CancelTcpIpForward {
939- want_reply ,
964+ reply_channel ,
940965 address,
941966 port,
942- } => self . cancel_tcpip_forward ( want_reply , & address, port) ,
967+ } => self . cancel_tcpip_forward ( reply_channel , & address, port) ,
943968 Msg :: Disconnect {
944969 reason,
945970 description,
0 commit comments