Exemple #1
0
func (vm *KvmVM) connectVNC() error {
	l, err := net.Listen("tcp", "")
	if err != nil {
		return err
	}

	// Keep track of shim so that we can close it later
	vm.vncShim = l
	vm.VNCPort = l.Addr().(*net.TCPAddr).Port
	ns := fmt.Sprintf("%v:%v", vm.Namespace, vm.Name)

	go func() {
		defer l.Close()

		for {
			// Sit waiting for new connections
			remote, err := l.Accept()
			if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
				return
			} else if err != nil {
				log.Errorln(err)
				return
			}

			go func() {
				defer remote.Close()

				// Dial domain socket
				local, err := net.Dial("unix", vm.path("vnc"))
				if err != nil {
					log.Error("unable to dial vm vnc: %v", err)
					return
				}
				defer local.Close()

				// copy local -> remote
				go io.Copy(remote, local)

				// Reads will implicitly copy from remote -> local
				tee := io.TeeReader(remote, local)
				for {
					// Read
					msg, err := vnc.ReadClientMessage(tee)
					if err != nil {
						if err == io.EOF || strings.Contains(err.Error(), "closed network") {
							break
						}
						log.Errorln(err)
					}
					if r, ok := vncKBRecording[ns]; ok {
						r.RecordMessage(msg)
					}
				}
			}()
		}
	}()

	return nil
}
Exemple #2
0
func vncWsHandler(w http.ResponseWriter, r *http.Request) {
	// we assume that if we got here, then the url must be sane and of
	// the format /ws/<host>/<port>
	path := r.URL.Path
	if !strings.HasSuffix(path, "/") {
		path += "/"
	}
	fields := strings.Split(path, "/")
	if len(fields) != 5 {
		http.NotFound(w, r)
		return
	}
	fields = fields[2:]

	rhost := fmt.Sprintf("%v:%v", fields[0], fields[1])

	// connect to the remote host
	remote, err := net.Dial("tcp", rhost)
	if err != nil {
		log.Errorln(err)
		http.StatusText(500)
		return
	}

	websocket.Handler(func(ws *websocket.Conn) {
		go func() {
			decoder := base64.NewDecoder(base64.StdEncoding, ws)
			tee := io.TeeReader(decoder, remote)

			for {
				// Read
				msg, err := vnc.ReadClientMessage(tee)
				if err != nil {
					if err == io.EOF || strings.Contains(err.Error(), "closed network") {
						break
					}

					log.Debugln(err)
					continue
				}

				if r, ok := vncKBRecording[rhost]; ok {
					r.RecordMessage(msg)
				}
			}

			remote.Close()
		}()
		func() {
			sbuf := make([]byte, VNC_WS_BUF)
			dbuf := make([]byte, 2*VNC_WS_BUF)
			for {
				n, err := remote.Read(sbuf)
				if err != nil {
					if !strings.Contains(err.Error(), "closed network connection") && err != io.EOF {
						log.Errorln(err)
					}
					break
				}
				base64.StdEncoding.Encode(dbuf, sbuf[0:n])
				n = base64.StdEncoding.EncodedLen(n)

				_, err = ws.Write(dbuf[0:n])
				if err != nil {
					log.Errorln(err)
					break
				}
			}
			ws.Close()
		}()
	}).ServeHTTP(w, r)
}