예제 #1
0
func (this *Client) Send(data []byte) error {
	if this.Debug {
		utils.Printf("Sending data: %s\n", string(data))
	}
	client := this.GetClient()
	if client == nil {
		return fmt.Errorf("maybe not connected\n")
	}
	n, err := client.Write(data)
	if err != nil {
		utils.Println("Send data failed:", err)
		this.Close()
		return err
	}
	if n != len(data) {
		utils.Println("Write() has blocked, send: %d, all: %d", n, len(data))
		this.Close()
		return fmt.Errorf("Write() has blocked, send: %d, all: %d", n, len(data))
	}

	return nil
}
예제 #2
0
func (this *Client) GetClient() net.Conn {
	if this.InternalClient == nil {
		address := net.JoinHostPort(this.Host, this.Port)
		conn, err := net.DialTimeout("tcp", address, this.Timeout)
		if err != nil {
			utils.Println(err)
			return nil
		}

		this.InternalClient = conn
		this.BufReader = bufio.NewReader(conn)
		this.BufWriter = bufio.NewWriter(conn)

		if this.Debug {
			utils.Printf("Client connected with gucad server (%s %s %s)\n",
				this.Host, this.Port, this.Timeout)
		}
		return this.InternalClient
	}

	return this.InternalClient
}
예제 #3
0
func (this *Client) HandShake(protocol, width, height, dpi string, audio []string, video []string, KWArgs map[string]string) bool {
	var found_protocol bool
	for index := range PROTOCOLS {
		if protocol == PROTOCOLS[index] {
			found_protocol = true
			break
		}
	}
	if !found_protocol {
		utils.Printf("Invalid protocol: %s\n", protocol)
		return false
	}

	// 1. Send "select" instruction
	utils.Println("Send 'select' instruction")
	err := this.SendInstruction(inst.NewInstruction("select", protocol))
	if err != nil {
		utils.Println("Send 'select' failed:", err)
		return false
	}

	// 2. Receive "args" instruction
	instruction := this.ReadInstruction()
	utils.Printf("Expecting 'args' instruction, received: %s\n", instruction.String())

	if instruction == nil {
		utils.Println("Cannot establish Handshake. Connection Lost!")
		return false
	}

	if instruction.OpCode != "args" {
		utils.Printf("Cannot establish Handshake. Expected opcode 'args', received '%s' instead.\n", instruction.OpCode)
		return false
	}

	// 3. Respond with size, audio & video support
	utils.Printf("Send 'size' instruction (%s %s %s)\n", width, height, dpi)
	size_instruction := inst.NewInstruction("size", width, height, dpi)
	err = this.SendInstruction(size_instruction)
	if err != nil {
		utils.Println("Send 'size' failed:", err)
		return false
	}

	utils.Printf("Send 'audio' instruction (%s)\n", audio)
	err = this.SendInstruction(inst.NewInstruction("audio", audio...))
	if err != nil {
		utils.Println("Send 'audio' failed:", err)
		return false
	}

	utils.Printf("Send 'video' instruction (%s)\n", video)
	err = this.SendInstruction(inst.NewInstruction("video", video...))
	if err != nil {
		utils.Println("Send 'video' failed:", err)
		return false
	}

	var connect_args []string
	for idx := range instruction.Args {
		arg := strings.Replace(instruction.Args[idx], "-", "_", -1)
		if v, ok := KWArgs[arg]; ok {
			connect_args = append(connect_args, v)
		} else {
			connect_args = append(connect_args, "")
		}
	}

	// 4. Send connect arguments
	utils.Printf("Send 'connect' instruction (%s)\n", connect_args)
	err = this.SendInstruction(inst.NewInstruction("connect", connect_args...))
	if err != nil {
		utils.Println("Send 'connect' failed:", err)
		return false
	}

	return true
}
예제 #4
0
func main() {
	ret := libvirt.EventRegisterDefaultImpl()
	utils.Println("EventRegisterDefaultImpl ret:", ret)

	runtime.GOMAXPROCS(runtime.NumCPU())

	defer func() {
		if err := recover(); err != nil {
			utils.Println("Server Error: ", err.(string))
		}
	}()

	// 解析命令行参数
	flag.Parse()

	// 自定义初始化
	Init()

	// 设置guacd客户端连接时的调试信息
	client.ClientDebug = Config.ServerDebug

	// 初始化guacd服务连接池
	client.Pool.Init(Config.GuacdServer)

	utils.Println("Try connect to:", Config.MongoURL)

	// 初始化MongoDB的连接
	timeout := time.Duration(Config.MongoTimeout) * time.Second
	err := mongo.InitMongoDB(Config.MongoURL, timeout)
	if err != nil {
		utils.Println(err)
		os.Exit(1)
	}

	// 启动独立的线程测试MongoDB连接
	go mongo.TouchMongoDB(Config.ShowCheckConn)

	utils.Println("Connect to MongoDB OK")

	// 捕捉信号并设置回调函数
	SignalChan = make(chan os.Signal, 1)
	signal.Notify(SignalChan,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT,
		syscall.SIGPIPE,
		syscall.SIGALRM,
		syscall.SIGPIPE)

	go SignalCallback()

	// 启动性能调试接口
	if Config.ServerProfile == true {
		go func() {
			http.ListenAndServe(Config.ProfileAddress, nil)
		}()
	}

	utils.Printf("http profile server Running on %s\n", Config.ProfileAddress)

	addr_splited := strings.Split(Config.ListenAddress, ":")
	if len(addr_splited) < 2 {
		utils.Println("the format of listen address is invalid!")
		os.Exit(1)
	}

	beego.HttpAddr = addr_splited[0]
	beego.HttpPort, err = strconv.Atoi(addr_splited[1])

	beego.SetStaticPath("/static", "./static")
	beego.Router("/connect", &controllers.MainController{})
	beego.Router("/ws", &wscontrollers.WebSocketController{})
	beego.Router("/ws/spice", &spicecontrollers.SpiceController{})
	beego.Router("/ws/libvirt", &libvirtcontrollers.LibvirtController{})

	beego.Router("/api/conn/list", &managercontrollers.ConnectionManagerController{}, "get:ListConnection")
	beego.Router("/api/conn/create/:conn_type([a-z]+)", &managercontrollers.ConnectionManagerController{}, "post:CreateConnection")
	beego.Router("/api/conn/update/:conn_type([a-z]+)", &managercontrollers.ConnectionManagerController{}, "put:UpdateConnection")
	beego.Router("/api/conn/delete", &managercontrollers.ConnectionManagerController{}, "delete:DeleteConnection")

	beego.Router("/api/libvirt/host", &libvirtcontrollers.HostController{})

	beego.Run()
}
예제 #5
0
func (this *SpiceController) Get() {
	ws, err := upgrader.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request, nil)
	if err != nil {
		utils.Println("websocket upgrade failed:", err)
		return
	}

	defer func() {
		utils.Println("websocket client disconnected:", ws.RemoteAddr())
		ws.Close()
	}()

	Type := this.GetString("type")

	if Type != "spice" {
		utils.Printf("invalid protocol: %s\n", Type)
		return
	}

	spice_args, err := GetSPICEArgs(this.Ctx)
	if err != nil {
		utils.Println("get args for SPICE failed:", err)
		return
	}

	if spice_args == nil {
		utils.Println("empty args for SPICE")
		return
	}

	hostname := spice_args["hostname"]
	port := spice_args["port"]

	spice_conn, err := net.DialTimeout("tcp", hostname+":"+port, 3*time.Second)
	if err != nil {
		utils.Println("Can not connect to spice server:", err)
		return
	}

	writer_buf := make([]byte, 4096)

	go func() {
		for {
			n, err := spice_conn.Read(writer_buf)
			if err != nil {
				utils.Println("Error read from spice server:", err)
				return
			}

			err = ws.WriteMessage(websocket.BinaryMessage, writer_buf[:n])
			if err != nil {
				utils.Println("websocket write failed:", err)
				return
			}
		}
	}()

	// TODO: use ws.NextReader to reuse memory allocation

	for {
		_, data, err := ws.ReadMessage()
		if err != nil {
			utils.Println("websocket readmessage failed:", err)
			return
		}

		spice_conn.Write(data)
	}
}