Example #1
0
// takes the base connection, determines the ID of the source and stashes it in the map
func (c *Connector) processIncoming(conn net.Conn) {
	var err error
	defer func() {
		if err != nil && conn != nil {
			conn.Close()
		}
	}()

	for {
		if conn == nil {
			log.Infof("attach connector: connection closed")
			return
		}

		serial.PurgeIncoming(conn)

		// TODO needs timeout handling.  This could take 30s.

		// Timeout for client handshake should be reasonably small.
		// Server will try to drain a buffer and if the buffer doesn't contain
		// 2 or more bytes it will just wait, so client should timeout.
		// However, if timeout is too short, client will flood server with Syn requests.
		ctx, cancel := context.WithTimeout(context.TODO(), time.Second)
		deadline, ok := ctx.Deadline()
		if ok {
			conn.SetReadDeadline(deadline)
		}
		if err = serial.HandshakeClient(conn, c.debug); err == nil {
			conn.SetReadDeadline(time.Time{})
			log.Debugf("attach connector: New connection")
			cancel()
			break
		} else if err == io.EOF {
			log.Debugf("caught EOF")
			conn.Close()
			return
		} else if _, ok := err.(*serial.HandshakeError); ok {
			log.Debugf("HandshakeClient: %v", err)
		} else {
			log.Errorf("HandshakeClient: %v", err)
		}
	}

	callback := func(hostname string, remote net.Addr, key ssh.PublicKey) error {
		return nil
	}

	config := &ssh.ClientConfig{
		User:            "******",
		HostKeyCallback: callback,
	}

	log.Debugf("Initiating ssh handshake with new connection attempt")
	var (
		ccon    ssh.Conn
		newchan <-chan ssh.NewChannel
		request <-chan *ssh.Request
	)

	ccon, newchan, request, err = ssh.NewClientConn(conn, "", config)
	if err != nil {
		log.Errorf("SSH connection could not be established: %s", errors.ErrorStack(err))
		return
	}

	client := ssh.NewClient(ccon, newchan, request)

	var ids []string
	ids, err = SSHls(client)
	if err != nil {
		log.Errorf("SSH connection could not be established: %s", errors.ErrorStack(err))
		return
	}

	var si SessionInteraction
	for _, id := range ids {
		si, err = SSHAttach(client, id)
		if err != nil {
			log.Errorf("SSH connection could not be established (id=%s): %s", id, errors.ErrorStack(err))
			return
		}

		log.Infof("Established connection with container VM: %s", id)

		c.mutex.Lock()
		connection := &Connection{
			spty: si,
			id:   id,
		}

		c.connections[connection.id] = connection

		c.cond.Broadcast()
		c.mutex.Unlock()
	}

	return
}
Example #2
0
// takes the base connection, determines the ID of the source and stashes it in the map
func (c *Connector) processIncoming(conn net.Conn) {
	var err error
	defer func() {
		if err != nil && conn != nil {
			conn.Close()
		}
	}()

	for {
		if conn == nil {
			log.Infof("attach connector: connection closed")
			return
		}

		serial.PurgeIncoming(conn)

		// TODO needs timeout handling.  This could take 30s.

		// This needs to timeout with a *longer* wait than the ticker set on
		// the tether side (in tether_linux.go) or alignment may not happen.
		// The PL sends the first SYN in the handshake and if the tether is not
		// waiting, the handshake may never succeed.
		ctx, cancel := context.WithTimeout(context.TODO(), 50*time.Millisecond)
		if err = serial.HandshakeClient(ctx, conn); err == nil {
			log.Debugf("attach connector: New connection")
			cancel()
			break
		} else if err == io.EOF {
			log.Debugf("caught EOF")
			conn.Close()
			return
		}
	}

	callback := func(hostname string, remote net.Addr, key ssh.PublicKey) error {
		return nil
	}

	config := &ssh.ClientConfig{
		User:            "******",
		HostKeyCallback: callback,
	}

	log.Debugf("Initiating ssh handshake with new connection attempt")
	var (
		ccon    ssh.Conn
		newchan <-chan ssh.NewChannel
		request <-chan *ssh.Request
	)

	ccon, newchan, request, err = ssh.NewClientConn(conn, "", config)
	if err != nil {
		log.Errorf("SSH connection could not be established: %s", errors.ErrorStack(err))
		return
	}

	client := ssh.NewClient(ccon, newchan, request)

	var ids []string
	ids, err = SSHls(client)
	if err != nil {
		log.Errorf("SSH connection could not be established: %s", errors.ErrorStack(err))
		return
	}

	var si SessionInteraction
	for _, id := range ids {
		si, err = SSHAttach(client, id)
		if err != nil {
			log.Errorf("SSH connection could not be established (id=%s): %s", id, errors.ErrorStack(err))
			return
		}

		log.Infof("Established connection with container VM: %s", id)

		c.mutex.Lock()
		connection := &Connection{
			spty: si,
			id:   id,
		}

		c.connections[connection.id] = connection

		c.cond.Broadcast()
		c.mutex.Unlock()
	}

	return
}