// 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 }
// 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 }