Example #1
0
func (cli *HyperClient) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer, started chan io.Closer, data interface{}, hostname string) error {
	defer func() {
		if started != nil {
			close(started)
		}
	}()

	params, err := cli.encodeData(data)
	if err != nil {
		return err
	}
	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", utils.APIVERSION, path), params)
	if err != nil {
		return err
	}
	req.Header.Set("User-Agent", "Hyper-Client/"+utils.VERSION)
	req.Header.Set("Content-Type", "text/plain")
	req.Header.Set("Connection", "Upgrade")
	req.Header.Set("Upgrade", "tcp")
	req.Host = cli.addr

	dial, err := cli.dial()
	if err != nil {
		return err
	}
	// When we set up a TCP connection for hijack, there could be long periods
	// of inactivity (a long running command with no output) that in certain
	// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
	// state. Setting TCP KeepAlive on the socket connection will prohibit
	// ECONNTIMEOUT unless the socket connection truly is broken
	if tcpConn, ok := dial.(*net.TCPConn); ok {
		tcpConn.SetKeepAlive(true)
		tcpConn.SetKeepAlivePeriod(30 * time.Second)
	}
	if err != nil {
		if strings.Contains(err.Error(), "connection refused") {
			return fmt.Errorf("Cannot connect to the Hyper daemon. Is 'hyperd' running on this host?")
		}
		return err
	}
	clientconn := httputil.NewClientConn(dial, nil)
	defer clientconn.Close()

	// Server hijacks the connection, error 'connection closed' expected
	_, err = clientconn.Do(req)
	if err != nil {
		fmt.Printf("Client DO: %s\n", err.Error())
	}

	rwc, _ := clientconn.Hijack()
	defer rwc.Close()

	if started != nil {
		started <- rwc
	}

	_, err = term.TtySplice(rwc)
	return err
}
Example #2
0
File: tty.go Project: ZJU-SEL/runv
// stdin/stdout <-> conn
func containerTtySplice(root, container string, conn net.Conn, isContainer bool) (int, error) {
	tag, err := runvGetTag(conn)
	if err != nil {
		return -1, err
	}
	fmt.Printf("tag=%s\n", tag)

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)
	newTty(root, container, tag, outFd, isTerminalOut).monitorTtySize()
	_, err = term.TtySplice(conn)
	if err != nil {
		return -1, err
	}

	cmd := &ttyTagCmd{Root: root, Container: "", Tag: tag}
	if isContainer {
		cmd.Container = container
	}
	conn, err = runvRequest(root, container, RUNV_EXITSTATUS, cmd)
	if err != nil {
		fmt.Printf("runvRequest failed: %v\n", err)
		return -1, err
	}
	defer conn.Close()

	msg, err := hypervisor.ReadVmMessage(conn.(*net.UnixConn))
	if err != nil {
		fmt.Printf("read runv server data failed: %v\n", err)
		return -1, err
	}

	if msg.Code != RUNV_EXITSTATUS {
		return -1, fmt.Errorf("unexpected respond code")
	}

	return int(msg.Message[0]), nil
}