func (c *SessionClient) dialWebsocketJS(service string, action string) (net.Conn, error) { var wsurl string if c.WSURL == "" { burl, err := url.Parse(c.APIURL) if err != nil { return nil, err } if burl.Scheme == "https" { burl.Scheme = "wss" } else { burl.Scheme = "ws" } wsurl = burl.String() } else { wsurl = c.WSURL } wsurl += fmt.Sprintf(c.Prefix+"/session/%s/conn/%s%s/websocket", c.ID, service, action) return jswebsocket.Dial(wsurl) }
func main() { if true { wsBaseURL := fmt.Sprintf("ws://%s:%s/ws/", location.Get("hostname"), location.Get("port")) ws, err := websocket.Dial(wsBaseURL + "rpc/foo") if err != nil { log.Fatal("Dial ", err) return } l := &Listener{} rpc = weeb.NewRpc(ws, l) l.rpc = rpc // go HelloRpcClient(rpc) go rpc.Serve() } if false { fu() } jq().Ready(func() { screenPixelsPerPoint = findScreenPixelsPerPoint() doc.AddEventListeners(document) jqBind(jq(":root")) }) }
//New connects websocket and returns Browser obj. func New(dest string, str interface{}) (*Browser, error) { var err error b := &Browser{} if err := rpc.Register(str); err != nil { return nil, err } b.s, err = websocket.Dial("ws://" + dest + "/ws-client") // Blocks until connection is established if err != nil { return nil, err } log.Println("ws-client connected") go jsonrpc.ServeConn(b.s) b.c, err = websocket.Dial("ws://" + dest + "/ws-server") // Blocks until connection is established if err != nil { return nil, err } log.Println("client connected") b.Client = jsonrpc.NewClient(b.c) return b, nil }
func rpcInit() error { conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/rpc") if err != nil { return err } conn.WebSocket.Call("addEventListener", "close", func(*js.Object) { xjs.RemoveChildren(xdom.Body()).AppendChild(xjs.SetInnerText(xdom.H1(), "Connection Lost")) }, false) dom.GetWindow().AddEventListener("beforeunload", false, func(dom.Event) { switch conn.ReadyState { case websocket.Connecting, websocket.Open: conn.Close() } }) RPC = jRPC{jsonrpc.NewClient(conn)} return nil }
func connect(wsEndpoint string) *websocket.Conn { count := 0 ticker := time.NewTicker(time.Duration(1) * time.Second) defer ticker.Stop() // connect for { count++ console.Log(fmt.Printf("trying to connect to server at %s, attempt %d", wsEndpoint, count)) conn, err := websocket.Dial(wsEndpoint) // Blocks until connection is established if err == nil { return conn } console.Error(err.Error()) <-ticker.C } }
func main() { wsBaseURL := getWSBaseURL() qunit.Module("websocket.WebSocket") qunit.Test("Invalid URL", func(assert qunit.QUnitAssert) { qunit.Expect(1) ws, err := websocket.New("blah://blah.example/invalid") if err == nil { ws.Close() assert.Ok(false, "Got no error, but expected an invalid URL error") return } assert.Ok(true, fmt.Sprintf("Received an error: %s", err)) }) qunit.AsyncTest("Immediate close", func() interface{} { qunit.Expect(2) ws, err := websocket.New(wsBaseURL + "immediate-close") if err != nil { qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err)) qunit.Start() return nil } ws.AddEventListener("open", false, func(ev *js.Object) { qunit.Ok(true, "WebSocket opened") }) ws.AddEventListener("close", false, func(ev *js.Object) { const ( CloseNormal = 1000 CloseNoReasonSpecified = 1005 // IE10 hates it when the server closes without sending a close reason ) closeEvent := dom.WrapEvent(ev).(*dom.CloseEvent) if closeEvent.Code != CloseNormal && closeEvent.Code != CloseNoReasonSpecified { qunit.Ok(false, fmt.Sprintf("WebSocket close was not clean (code %d)", closeEvent.Code)) qunit.Start() return } qunit.Ok(true, "WebSocket closed") qunit.Start() }) return nil }) qunit.Module("websocket.Conn") qunit.AsyncTest("Immediate close", func() interface{} { go func() { defer qunit.Start() ws, err := websocket.Dial(wsBaseURL + "immediate-close") if err != nil { qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err)) return } qunit.Ok(true, "WebSocket opened") _, err = ws.Read(nil) if err == io.EOF { qunit.Ok(true, "Received EOF") } else if err != nil { qunit.Ok(false, fmt.Sprintf("Unexpected error in second read: %s", err)) } else { qunit.Ok(false, "Expected EOF in second read, got no error") } }() return nil }) qunit.AsyncTest("Failed open", func() interface{} { go func() { defer qunit.Start() ws, err := websocket.Dial(wsBaseURL + "404-not-found") if err == nil { ws.Close() qunit.Ok(false, "Got no error, but expected an error in opening the WebSocket.") return } qunit.Ok(true, fmt.Sprintf("WebSocket failed to open: %s", err)) }() return nil }) qunit.AsyncTest("Binary read", func() interface{} { qunit.Expect(3) go func() { defer qunit.Start() ws, err := websocket.Dial(wsBaseURL + "binary-static") if err != nil { qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err)) return } qunit.Ok(true, "WebSocket opened") var expectedData = []byte{0x00, 0x01, 0x02, 0x03, 0x04} receivedData := make([]byte, len(expectedData)) n, err := ws.Read(receivedData) if err != nil { qunit.Ok(false, fmt.Sprintf("Error in first read: %s", err)) return } receivedData = receivedData[:n] if !bytes.Equal(receivedData, expectedData) { qunit.Ok(false, fmt.Sprintf("Received data did not match expected data. Got % x, expected % x.", receivedData, expectedData)) } else { qunit.Ok(true, fmt.Sprintf("Received data: % x", receivedData)) } _, err = ws.Read(receivedData) if err == io.EOF { qunit.Ok(true, "Received EOF") } else if err != nil { qunit.Ok(false, fmt.Sprintf("Unexpected error in second read: %s", err)) } else { qunit.Ok(false, "Expected EOF in second read, got no error") } }() return nil }) qunit.AsyncTest("Timeout", func() interface{} { qunit.Expect(2) go func() { defer qunit.Start() ws, err := websocket.Dial(wsBaseURL + "wait-30s") if err != nil { qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err)) return } qunit.Ok(true, "WebSocket opened") start := time.Now() ws.SetReadDeadline(start.Add(1 * time.Second)) _, err = ws.Read(nil) if err != nil && err.Error() == "i/o timeout: deadline reached" { totalTime := time.Now().Sub(start) if totalTime < 750*time.Millisecond { qunit.Ok(false, fmt.Sprintf("Timeout was too short: Received timeout after %s", totalTime)) return } qunit.Ok(true, fmt.Sprintf("Received timeout after %s", totalTime)) } else if err != nil { qunit.Ok(false, fmt.Sprintf("Unexpected error in read: %s", err)) } else { qunit.Ok(false, "Expected timeout in read, got no error") } }() return nil }) }
func transferFile(typeName, method string, typeID uint8, o *overlay.Overlay) dom.Node { name := xform.InputText("name", "") url := xform.InputRadio("url", "switch", true) upload := xform.InputRadio("upload", "switch", false) fileI := xform.InputUpload("") urlI := xform.InputURL("", "") s := xform.InputSubmit(method) name.Required = true typeFunc := func(dom.Event) { if url.Checked { urlI.Style().RemoveProperty("display") fileI.Style().SetProperty("display", "none", "") urlI.Required = true fileI.Required = false fileI.SetID("") urlI.SetID("file") } else { fileI.Style().RemoveProperty("display") urlI.Style().SetProperty("display", "none", "") fileI.Required = true urlI.Required = false urlI.SetID("") fileI.SetID("file") } } typeFunc(nil) url.AddEventListener("change", false, typeFunc) upload.AddEventListener("change", false, typeFunc) f := xjs.AppendChildren(xdom.Form(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), method+" "+typeName), xform.Label(typeName+" Name", "name"), name, xdom.Br(), xform.Label("URL", "url"), url, xdom.Br(), xform.Label("Upload", "upload"), upload, xdom.Br(), xform.Label("File", "file"), fileI, urlI, xdom.Br(), s, )) s.AddEventListener("click", false, func(e dom.Event) { if name.Value == "" { return } if url.Checked { if urlI.Value == "" { return } } else if len(fileI.Files()) != 1 { return } s.Disabled = true name.Disabled = true url.Disabled = true upload.Disabled = true fileI.Disabled = true urlI.Disabled = true e.PreventDefault() go func() { d := xdom.Div() uo := overlay.New(d) uo.OnClose(func() { o.Close() }) xjs.Body().AppendChild(uo) status := xdom.Div() d.AppendChild(xjs.SetInnerText(status, "Transferring...")) conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/transfer") if err != nil { xjs.SetInnerText(status, err.Error()) return } defer conn.Close() w := byteio.StickyWriter{Writer: byteio.LittleEndianWriter{Writer: conn}} r := byteio.StickyReader{Reader: byteio.LittleEndianReader{Reader: conn}} pb := progress.New(color.RGBA{255, 0, 0, 0}, color.RGBA{0, 0, 255, 0}, 400, 50) d.AppendChild(pb) if url.Checked { w.WriteUint8(typeID << 1) data.WriteString(&w, urlI.Value) length := int(r.ReadInt32()) total := 0 for total < length { switch v := r.ReadUint8(); v { case 1: i := int(r.ReadInt32()) total += i pb.Percent(100 * total / length) default: xjs.SetInnerText(status, ReadError(&r).Error()) return } } } else { f := files.NewFileReader(files.NewFile(fileI.Files()[0])) l := f.Len() if l == 0 { xjs.SetInnerText(status, "Zero-length file") return } w.WriteUint8(typeID<<1 | 1) w.WriteInt32(int32(l)) io.Copy(&w, pb.Reader(f, l)) } d.RemoveChild(pb) xjs.SetInnerText(status, "Checking File") data.WriteString(&w, name.Value) var ctx *dom.CanvasRenderingContext2D for { switch v := r.ReadUint8(); v { case 0: if r.Err != nil { xjs.SetInnerText(status, r.Err.Error()) } else { xjs.SetInnerText(status, ReadError(&r).Error()) } return case 1: files := make([]xform.Option, r.ReadInt16()) for i := range files { files[i] = xform.Option{ Value: strconv.Itoa(i), Label: data.ReadString(&r), } } j := xform.SelectBox("files", files...) sel := xjs.SetInnerText(xdom.Button(), "Select") fo := overlay.New(xjs.AppendChildren(xdom.Div(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), "Please select the "+typeName+" file"), xform.Label("File", "files"), j, xdom.Br(), sel, ))) c := make(chan int16, 0) done := false fo.OnClose(func() { if !done { done = true c <- -1 } }) sel.AddEventListener("click", false, func(dom.Event) { if !done { done = true v, err := strconv.Atoi(j.Value) if err != nil { v = -1 } c <- int16(v) fo.Close() } }) xjs.Body().AppendChild(fo) w.WriteInt16(<-c) close(c) case 2: w := r.ReadInt32() h := r.ReadInt32() canvas := xdom.Canvas() canvas.Width = int(w) * 8 canvas.Height = int(h) * 8 d.AppendChild(canvas) ctx = canvas.GetContext2d() ctx.Scale(8, 8) case 3: xjs.SetInnerText(status, data.ReadString(&r)) case 4: x := r.ReadInt32() y := r.ReadInt32() red := r.ReadUint8() green := r.ReadUint8() blue := r.ReadUint8() alpha := r.ReadUint8() ctx.FillStyle = "rgba(" + strconv.Itoa(int(red)) + ", " + strconv.Itoa(int(green)) + ", " + strconv.Itoa(int(blue)) + ", " + strconv.FormatFloat(float64(alpha)/255, 'f', -1, 32) + ")" ctx.FillRect(int(x), int(y), 1, 1) case 255: uo.Close() return } } }() }) return f }
func serverConsole(s data.Server) func(dom.Element) { return func(c dom.Element) { log := xform.TextArea("log", "") log.ReadOnly = true command := xform.InputText("command", "") command.Required = true send := xform.InputSubmit("Send") c.AppendChild(xjs.AppendChildren(xdom.Form(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), "Console"), xform.Label("Log", ""), log, xdom.Br(), xform.Label("Command", "command"), command, send, ))) if s.State == data.StateStopped { send.Disabled = true command.Disabled = true } else { send.AddEventListener("click", false, func(e dom.Event) { if command.Value == "" { return } e.PreventDefault() send.Disabled = true cmd := command.Value log.Value += "\n>" + cmd + "\n" log.Set("scrollTop", log.Get("scrollHeight")) command.Value = "" go func() { err := RPC.WriteCommand(s.ID, cmd) if err != nil { xjs.Alert("Error sending command: %s", err) return } send.Disabled = false }() }) } go func() { conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/console") if err != nil { xjs.Alert("Failed to connect to console: %s", err) return } defer conn.Close() w := byteio.StickyWriter{Writer: byteio.LittleEndianWriter{Writer: conn}} r := byteio.StickyReader{Reader: byteio.LittleEndianReader{Reader: conn}} updateStop := make(chan struct{}) registerUpdateStopper(c, updateStop) done := false go func() { <-updateStop done = true conn.Close() }() w.WriteInt32(int32(s.ID)) for { state := r.ReadUint8() switch state { case 0: if !done { err := ReadError(&r) if r.Err != nil { err = r.Err } log.Value += "\n\nError reading from console: " + err.Error() log.Set("scrollTop", log.Get("scrollHeight")) } return case 1: log.Value += data.ReadString(&r) log.Set("scrollTop", log.Get("scrollHeight")) } } }() } }
func Start() error { loc := dom.GetWindow().Location() addr := fmt.Sprintf("ws://%s:%s/_rpc", loc.Hostname, loc.Port) ws, err := websocket.Dial(addr) if err != nil { return kerr.Wrap("HNQFLPFAJD", err) } app := &stores.App{ Conn: connection.New(rpc.NewClient(ws)), Fail: make(chan error), } // We parse the info attribute from the body tag info, err := getInfo(getRawInfo()) if err != nil { return kerr.Wrap("MGLVIQIDDY", err) } var ctx context.Context ctx = context.Background() ctx = envctx.NewContext(ctx, &envctx.Env{Path: info.Path, Aliases: info.Aliases}) ctx = sysctx.NewContext(ctx) ctx = jsonctx.AutoContext(ctx) ctx = stores.NewContext(ctx, app) ctx = clientctx.NewContext(ctx) app.Init(ctx) // Don't do this. Implement the Editable interface instead. We can't do // this for system types so we use this method instead. editors.Register(ctx) if _, err := registerTypes(ctx, info.Path, info.Imports); err != nil { return kerr.Wrap("MMJDDOBAUK", err) } p := views.NewPage(ctx) vecty.RenderBody(p) // TODO: work out why I can't seem to call this without using eval js.Global.Get("window").Call("eval", "Split(['#tree', '#main'], {sizes:[25, 75]});") app.Dispatch(&actions.InitialState{ Info: info, }) go func() { err, open := <-app.Fail if !open { // Channel has been closed, so app should gracefully exit. fmt.Println("Server disconnected") } else { // Error received, so app should display error. fmt.Println(err.Error()) } }() return nil }
func run() error { webSocketClosed := false ws, err := websocket.Dial(js.Global.Get("WebSocketAddress").String()) if err != nil { return err } defer ws.Close() ws.AddEventListener("close", false, func(_ *js.Object) { webSocketClosed = true }) enc := json.NewEncoder(ws) dec := json.NewDecoder(ws) // Clear all markers (possibly left over from previous connection). for _, marker := range markers { marker.RemoveFromMap(mapView) } var bounds *mapview.LatLngBounds var lat, lng float64 var accuracy float64 foundLocation := false shareIcon := document.GetElementByID("share-icon").(*dom.HTMLImageElement) shareIcon.AddEventListener("click", false, func(event dom.Event) { event.PreventDefault() shareBox := document.GetElementByID("share-box").(*dom.HTMLInputElement) shareBox.Style().SetProperty("display", "initial", "") shareBox.Focus() shareBox.Select() shareBox.Value = dom.GetWindow().Location().Href shareIcon.Style().SetProperty("display", "none", "") shareBox.AddEventListener("blur", false, func(event dom.Event) { event.PreventDefault() shareBox.Style().SetProperty("display", "none", "") shareIcon.Style().SetProperty("display", "initial", "") }) }) go func() { for { if webSocketClosed { break } time.Sleep(time.Second) if !foundLocation { continue } clientState := common.ClientState{ Name: document.GetElementByID("message").(*dom.HTMLInputElement).Value, Lat: lat, Lng: lng, Accuracy: accuracy, } err = enc.Encode(clientState) if err != nil { log.Println("enc.Encode:", err) break } } }() mapView.OnLocFound(func(loc *js.Object) { document.GetElementByID("spinner-container").(dom.HTMLElement).Style().SetProperty("display", "none", "") foundLocation = true latlng := loc.Get("latlng") lat = latlng.Get("lat").Float() lng = latlng.Get("lng").Float() accuracy = loc.Get("accuracy").Float() }) mapView.StartLocate() for { var msg common.ServerUpdate originalIds := make(map[int64]struct{}) for k := range markers { originalIds[k] = struct{}{} } err = dec.Decode(&msg) if err != nil || webSocketClosed { log.Println("dec.Decode:", err) break } for i, clientState := range msg.Clients { if markers[clientState.Id] == nil { markers[clientState.Id] = mapView.AddMarkerWithMessage(clientState.Lat, clientState.Lng, clientState.Accuracy, clientState.Name) } else { markers[clientState.Id].SetLatLng(clientState.Lat, clientState.Lng) markers[clientState.Id].SetMessage(clientState.Name) markers[clientState.Id].SetAccuracy(clientState.Accuracy) delete(originalIds, clientState.Id) } if i == 0 { bounds = mapview.NewLatLngBounds( mapview.NewLatLng(clientState.Lat, clientState.Lng), mapview.NewLatLng(clientState.Lat, clientState.Lng)) } else { bounds.Extend(mapview.NewLatLng(clientState.Lat, clientState.Lng)) } } for key := range originalIds { markers[key].RemoveFromMap(mapView) } if bounds != nil { bounds.Pad(0.10) mapView.FitBounds(bounds) } log.Printf("%#v\n", msg) } mapView.StopLocate() return nil }