func (c *appClient) controlConnection() (bool, error) { headers := http.Header{} c.ProbeConfig.authorizeHeaders(headers) url := sanitize.URL("ws://", 0, "/api/control/ws")(c.target) conn, _, err := xfer.DialWS(&c.wsDialer, url, headers) if err != nil { return false, err } defer conn.Close() doControl := func(req xfer.Request) xfer.Response { req.AppID = c.appID var res xfer.Response c.control.Handle(req, &res) return res } codec := xfer.NewJSONWebsocketCodec(conn) server := rpc.NewServer() if err := server.RegisterName("control", xfer.ControlHandlerFunc(doControl)); err != nil { return false, err } // Will return false if we are exiting if !c.registerConn("control", conn) { return true, nil } defer c.closeConn("control") server.ServeCodec(codec) return false, nil }
func (bc *bridgeConnection) loop() { log.Infof("%s: Client bridge connection started", bc.key) defer bc.wait.Done() defer log.Infof("%s: Client bridge connection stopped", bc.key) _, end := bc.pipe.Ends() url := fmt.Sprintf("ws://%s/private/api/pipe/%s", bc.addr, url.QueryEscape(bc.key)) for { bc.mtx.Lock() bc.conn = nil if bc.stopped { bc.mtx.Unlock() return } bc.mtx.Unlock() // connect to other pipes instance conn, _, err := xfer.DialWS(wsDialer, url, http.Header{}) if err != nil { log.Errorf("%s: Client bridge connection; Error connecting to %s: %v", bc.key, url, err) time.Sleep(time.Second) // TODO backoff continue } bc.mtx.Lock() if bc.stopped { bc.mtx.Unlock() conn.Close() return } bc.conn = conn bc.mtx.Unlock() if err := bc.pipe.CopyToWebsocket(end, conn); err != nil && !xfer.IsExpectedWSCloseError(err) { log.Errorf("%s: Client bridge connection; Error copying pipe to websocket: %v", bc.key, err) } conn.Close() } }
func (c *appClient) pipeConnection(id string, pipe xfer.Pipe) (bool, error) { headers := http.Header{} c.ProbeConfig.authorizeHeaders(headers) url := sanitize.URL("ws://", 0, fmt.Sprintf("/api/pipe/%s/probe", id))(c.target) conn, resp, err := xfer.DialWS(&c.wsDialer, url, headers) if resp != nil && resp.StatusCode == http.StatusNotFound { // Special handling - 404 means the app/user has closed the pipe pipe.Close() return true, nil } if err != nil { return false, err } // Will return false if we are exiting if !c.registerConn(id, conn) { return true, nil } defer c.closeConn(id) _, remote := pipe.Ends() return false, pipe.CopyToWebsocket(remote, conn) }