github.com/devops-filetransfer/sshego@v7.0.4+incompatible/auto_test.go (about)

     1  package sshego
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	//"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	cv "github.com/glycerine/goconvey/convey"
    12  	ssh "github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh"
    13  )
    14  
    15  func Test060AutoRedialWithTricorder(t *testing.T) {
    16  	cv.Convey("sshego.Tricorder has auto-redial on disconnect capability.", t, func() {
    17  
    18  		// start a simple TCP server  that is the target of the forward through the sshd,
    19  		// so we can confirm the client has made the connection.
    20  
    21  		// generate a random payload for the client to send to the server.
    22  		payloadByteCount := 50
    23  		confirmationPayload := RandomString(payloadByteCount)
    24  		confirmationReply := RandomString(payloadByteCount)
    25  
    26  		tcpSrvLsn, tcpSrvPort := GetAvailPort()
    27  
    28  		var nc net.Conn
    29  		tcpServerMgr := ssh.NewHalter()
    30  		StartBackgroundTestTcpServer(
    31  			tcpServerMgr,
    32  			payloadByteCount,
    33  			confirmationPayload,
    34  			confirmationReply,
    35  			tcpSrvLsn,
    36  			&nc)
    37  
    38  		s := MakeTestSshClientAndServer(true)
    39  		defer TempDirCleanup(s.SrvCfg.Origdir, s.SrvCfg.Tempdir)
    40  
    41  		dest := fmt.Sprintf("127.0.0.1:%v", tcpSrvPort)
    42  		tofu := true
    43  		dc := &DialConfig{
    44  			ClientKnownHostsPath: s.CliCfg.ClientKnownHostsPath,
    45  			Mylogin:              s.Mylogin,
    46  			RsaPath:              s.RsaPath,
    47  			TotpUrl:              s.Totp,
    48  			Pw:                   s.Pw,
    49  			Sshdhost:             s.SrvCfg.EmbeddedSSHd.Host,
    50  			Sshdport:             s.SrvCfg.EmbeddedSSHd.Port,
    51  			DownstreamHostPort:   dest,
    52  			TofuAddIfNotKnown:    tofu,
    53  			LocalNickname:        "test060",
    54  		}
    55  
    56  		pp("060 1st time: tcpSrvPort = %v. dest='%v'", tcpSrvPort, dest)
    57  
    58  		var channelToTcpServer net.Conn
    59  		var err error
    60  		ctx := context.Background()
    61  
    62  		pp("making tri: s.CliCfg.LocalToRemote.Listen.Addr='%v'",
    63  			s.CliCfg.LocalToRemote.Listen.Addr)
    64  
    65  		tri, err := NewTricorder(dc, s.CliCfg.Halt, "test060")
    66  		panicOn(err)
    67  		bkg := context.Background()
    68  		channelToTcpServer, err = tri.SSHChannel(bkg, "direct-tcpip", dest)
    69  
    70  		cv.So(err, cv.ShouldBeNil)
    71  		cv.So(tri, cv.ShouldNotBeNil)
    72  
    73  		pp("fine with DialGetTricorder.")
    74  
    75  		<-tcpServerMgr.ReadyChan()
    76  		pp("060 1st time nc = '%#v'", nc)
    77  		pp("060 1st time nc.LocalAddr='%v'", nc.LocalAddr())
    78  
    79  		checkReconNeeded := tri.cfg.ClientReconnectNeededTower.Subscribe(nil)
    80  
    81  		VerifyClientServerExchangeAcrossSshd(channelToTcpServer, confirmationPayload, confirmationReply, payloadByteCount)
    82  
    83  		tcpServerMgr.RequestStop()
    84  		<-tcpServerMgr.DoneChan()
    85  
    86  		nc.Close()
    87  		nc = nil
    88  		channelToTcpServer.Close()
    89  
    90  		pp("starting on 2nd confirmation")
    91  
    92  		s.SrvCfg.Halt.RequestStop()
    93  		<-s.SrvCfg.Halt.DoneChan()
    94  
    95  		// after killing remote sshd
    96  
    97  		var uhp2 *UHP
    98  		select {
    99  		case uhp2 = <-checkReconNeeded:
   100  			pp("good, 060 got needReconnectCh to '%#v'", uhp2)
   101  
   102  		case <-time.After(5 * time.Second):
   103  			panic("never received <-checkReconNeeded: timeout after 5 seconds")
   104  		}
   105  
   106  		cv.So(uhp2.User, cv.ShouldEqual, s.Mylogin)
   107  		destHostPort := fmt.Sprintf("%v:%v", s.SrvCfg.EmbeddedSSHd.Host, s.SrvCfg.EmbeddedSSHd.Port)
   108  		cv.So(uhp2.HostPort, cv.ShouldEqual, destHostPort)
   109  
   110  		// so restart the sshd server
   111  
   112  		pp("waiting for destHostPort='%v' to be availble", destHostPort)
   113  		panicOn(s.SrvCfg.Esshd.Stop())
   114  		s.SrvCfg.Reset()
   115  		s.SrvCfg.NewEsshd()
   116  		s.SrvCfg.Esshd.Start(ctx)
   117  
   118  		serverDone2 := ssh.NewHalter()
   119  		confirmationPayload2 := RandomString(payloadByteCount)
   120  		confirmationReply2 := RandomString(payloadByteCount)
   121  
   122  		StartBackgroundTestTcpServer(
   123  			serverDone2,
   124  			payloadByteCount,
   125  			confirmationPayload2,
   126  			confirmationReply2,
   127  			tcpSrvLsn, &nc)
   128  		time.Sleep(time.Second)
   129  
   130  		// tri should automaticly re-Dial.
   131  		channelToTcpServer2, err := tri.SSHChannel(ctx, "direct-tcpip", dest)
   132  
   133  		panicOn(err)
   134  
   135  		<-serverDone2.ReadyChan()
   136  		pp("060 2nd time nc.LocalAddr='%v'", nc.LocalAddr())
   137  
   138  		i := 0
   139  		for k, v := range tri.sshChannels {
   140  			pp("tri.sshChannels[%v]=%p -> %p", i, k, v)
   141  			i++
   142  		}
   143  
   144  		VerifyClientServerExchangeAcrossSshd(channelToTcpServer2, confirmationPayload2, confirmationReply2, payloadByteCount)
   145  
   146  		// tcp-server should have exited because it got the expected
   147  		// message and replied with the agreed upon reply and then exited.
   148  		serverDone2.RequestStop()
   149  		<-serverDone2.DoneChan()
   150  		nc.Close()
   151  
   152  		// done with testing, cleanup
   153  		s.SrvCfg.Esshd.Stop()
   154  		<-s.SrvCfg.Esshd.Halt.DoneChan()
   155  		cv.So(true, cv.ShouldEqual, true) // we should get here.
   156  	})
   157  }