// Dial will open a websocket to socketURL, pass the display string to the // server and return a DisplayClient implementing ioext.ReadWriteCloser using // the websocket. // // Use ListDisplays() to find available displays. func Dial(socketURL string, display string) (*DisplayClient, error) { // Parse socketURL and get query string u, err := url.Parse(socketURL) if err != nil { return nil, fmt.Errorf("Invalid socketURL: %s, parsing error: %s", socketURL, err) } q := u.Query() // Ensure the URL has ws or wss as scheme switch u.Scheme { case "http": u.Scheme = "ws" case "https": u.Scheme = "wss" } // Set display q.Set("display", display) // Set querystring on url u.RawQuery = q.Encode() // Dial up to the constructed URL ws, res, err := dialer.Dial(u.String(), nil) // Upgrade failed then we most likely got some error response if err == websocket.ErrBadHandshake { // Attempt to read and parse the body (limit to 2MiB for sanity) data, _ := ioext.ReadAtMost(res.Body, 2*1024*1024) var errorMsg displayconsts.ErrorMessage perr := json.Unmarshal(data, &errorMsg) if perr == nil { return nil, &errorMsg } // return a generic error message if body parsing failed return nil, fmt.Errorf("Failed to connect to display, statusCode: %d", res.StatusCode) } if err != nil { return nil, fmt.Errorf("Failed to open websocket, error: %s", err) } // Return a new DisplayClient wrapping the websocket return New(ws), nil }
func (g *guestTools) poll(ctx context.Context) { // Poll the metaservice for an action to perform req, err := http.NewRequest(http.MethodGet, g.url("engine/v1/poll"), nil) if err != nil { g.log.Panicln("Failed to create polling request, error: ", err) } // Do request with a timeout c, _ := context.WithTimeout(ctx, pollTimeout) res, err := ctxhttp.Do(c, nil, req) //res, res := http.DefaultClient.Do(req) if err != nil { g.log.Info("Poll request failed, error: ", err) // if this wasn't a deadline exceeded error, we'll sleep a second to avoid // spinning the CPU while waiting for DHCP to come up. if err != context.DeadlineExceeded && err != context.Canceled { time.Sleep(1 * time.Second) } return } // Read the request body defer res.Body.Close() data, err := ioext.ReadAtMost(res.Body, 2*1024*1024) if err != nil { g.log.Error("Failed to read poll request body, error: ", err) return } // Parse the request body action := metaservice.Action{} err = json.Unmarshal(data, &action) if err != nil { g.log.Error("Failed to parse poll request body, error: ", err) return } g.dispatchAction(action) }