func WSGlassHandler(c *websocket.Conn) { defer c.Close() fmt.Println("Connected with glass") path := strings.Split(c.Request().URL.Path, "/") if len(path) != 4 { fmt.Println("Bad path") WSSend(c, &[]interface{}{[]uint8("error"), []uint8("Bad url path")}) return } userId, err := getSecretUser("ws", secretHash(path[len(path)-1])) if err != nil { fmt.Println(err) WSSend(c, &[]interface{}{[]uint8("error"), []uint8("Invalid credentials please setup glass")}) return } userId = SanitizeUserId(userId) svc, err := mirror.New(authTransport(userId).Client()) if err != nil { LogPrintf("ws: mirror") WSSend(c, &[]interface{}{[]uint8("error"), []uint8("Unable to create mirror transport")}) return } // TODO: make buffer size configurable if Locks[userId] == nil { Locks[userId] = &sync.Mutex{} } Locks[userId].Lock() wsSendChan := make(chan *[]interface{}, 5) DeviceChannels[userId] = append(DeviceChannels[userId], wsSendChan) Locks[userId].Unlock() WSUpdateConnections(userId) wsSendChan <- &[]interface{}{[]uint8("version"), version} if ravenDSN != "" { wsSendChan <- &[]interface{}{[]uint8("raven"), []uint8(ravenDSN)} } defer func() { Locks[userId].Lock() var p []chan *[]interface{} for _, v := range DeviceChannels[userId] { if v != wsSendChan { p = append(p, v) } } DeviceChannels[userId] = p Locks[userId].Unlock() WSUpdateConnections(userId) }() var latestSensors, latestImage *[]interface{} // Initialize delays die := false // Websocket sender go func() { for { request, ok := <-wsSendChan if !ok { die = true break } fmt.Println("Sending to glass") msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} err = msgcodec.Send(c, request) if err != nil { die = true break } } }() // Data from glass loop for { request := []interface{}{} requestP := &request msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} err := msgcodec.Receive(c, &request) if err != nil { LogPrintf("ws: from glass") fmt.Println(err) die = true close(wsSendChan) break } if die { break } action := string(request[0].([]uint8)) //fmt.Println(action) if action == "timeline" { ti := mirror.TimelineItem{} err = json.Unmarshal(request[1].([]uint8), &ti) if err != nil { LogPrintf("ws: timeline: js") continue } req := svc.Timeline.Insert(&ti) //req.Media(strings.NewReader(image)) _, err := req.Do() if err != nil { LogPrintf("ws: timeline: send") continue } } else if action == "log" { fmt.Println(request[1].([]uint8)) WSSendWeb(userId, &requestP) } else if action == "sensors" { latestSensors = requestP WSSendWeb(userId, &latestSensors) } else if action == "image" { latestImage = requestP WSSendWeb(userId, &latestImage) } else if strings.HasPrefix(action, "gist_") { responseGH := GithubGistHandle(userId, request) if responseGH != nil { wsSendChan <- responseGH } } else { WSSendWeb(userId, &requestP) } } }
func WSGlassHandler(c *websocket.Conn) { defer c.Close() fmt.Println("Connected with glass") path := strings.Split(c.Request().URL.Path, "/") if len(path) != 4 { fmt.Println("Bad path") return } userId, err := getSecretUser("ws", secretHash(path[len(path)-1])) if err != nil { fmt.Println(err) return } uflags, err := getUserFlags(userId, "uflags") if err != nil { fmt.Println(fmt.Errorf("Couldn't get flags: %s", err)) return } svc, err := mirror.New(authTransport(userId).Client()) if err != nil { LogPrintf("ws: mirror") return } // TODO: Look into locking and add defer to cleanup later, make buffer size configurable wsSendChan := make(chan *[]interface{}, 5) wsSendChan <- &[]interface{}{[]uint8("version"), version} DeviceChannels[userId] = append(DeviceChannels[userId], wsSendChan) visionChan := make(chan *[]interface{}) var latestSensors, latestImage *[]interface{} // Initialize delays die := false // Websocket sender go func() { for { request, ok := <-wsSendChan if !ok { die = true break } fmt.Println("Sending to glass") msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} err = msgcodec.Send(c, request) if err != nil { die = true break } } }() // Flags sender go func() { for { if die { break } // TODO: Make a subscription and have this repeated only when things change uflags, err = getUserFlags(userId, "uflags") if err != nil { fmt.Println(fmt.Errorf("Couldn't get flags: %s", err)) time.Sleep(time.Millisecond * 2000) continue } fmt.Println("Sending flags") wsSendChan <- &[]interface{}{"flags", uflags} time.Sleep(time.Millisecond * 2000) } }() // Vision go func() { for { request, ok := <-visionChan if !ok { die = true break } input := string((*request)[3].([]uint8)) output := process_image(&input) if output != nil { WSSendDevice(userId, &[]interface{}{[]uint8("image"), (*request)[1], (*request)[2], []uint8(*output)}) } } }() // Data from glass loop for { request := []interface{}{} requestP := &request msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} err := msgcodec.Receive(c, &request) if err != nil { LogPrintf("ws: from glass") fmt.Println(err) die = true break } if die { break } action := string(request[0].([]uint8)) fmt.Println(action) if action == "timeline" { ti := mirror.TimelineItem{} err = json.Unmarshal(request[1].([]uint8), &ti) if err != nil { LogPrintf("ws: timeline: js") continue } req := svc.Timeline.Insert(&ti) //req.Media(strings.NewReader(image)) _, err := req.Do() if err != nil { LogPrintf("ws: timeline: send") continue } } else if action == "log" { fmt.Println(request[1].([]uint8)) WSSendWeb(userId, &requestP) } else if action == "sensors" { latestSensors = requestP WSSendWeb(userId, &latestSensors) } else if action == "image" { latestImage = requestP WSSendWeb(userId, &latestImage) select { case visionChan <- requestP: default: fmt.Println("Image skipped vision processing, it was busy...") } } else { WSSendWeb(userId, &requestP) } } }
func WSWebHandler(c *websocket.Conn) { defer c.Close() userId, err := userID(c.Request()) if err != nil || userId == "" { path := strings.Split(c.Request().URL.Path, "/") if len(path) != 4 { fmt.Println("Bad path") return } userId, err = getSecretUser("client", secretHash(path[len(path)-1])) if err != nil { fmt.Println(err) return } } userId = SanitizeUserId(userId) fmt.Println("Websocket connected") // TODO: make buffer size configurable if Locks[userId] == nil { Locks[userId] = &sync.Mutex{} } die := false Locks[userId].Lock() wsSendChan := make(chan **[]interface{}, 5) WebChannels[userId] = append(WebChannels[userId], wsSendChan) Locks[userId].Unlock() WSUpdateConnections(userId) versionRequestP := &[]interface{}{[]uint8("version"), version} wsSendChan <- &versionRequestP if ravenDSN != "" { ravenRequestP := &[]interface{}{[]uint8("raven"), []uint8(ravenDSN)} wsSendChan <- &ravenRequestP } defer func() { Locks[userId].Lock() var p []chan **[]interface{} for _, v := range WebChannels[userId] { if v != wsSendChan { p = append(p, v) } } WebChannels[userId] = p Locks[userId].Unlock() WSUpdateConnections(userId) }() var lastSensors, lastImage *[]interface{} // Websocket sender go func() { for { request, ok := <-wsSendChan if !ok || die { break } msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} action := string((**request)[0].([]uint8)) /* NOTE(brandyn): This assumes that the pointer changes between samples, I believe this is safe and it greatly simplifies sending the latest image/sensors. If this doesn't hold, then we would only miss sending a sample so the harm is minimal. */ if action == "image" { if *request == lastImage { fmt.Println("Already sent image, skipping") continue } lastImage = *request } else if action == "sensors" { if *request == lastSensors { fmt.Println("Already sent sensors, skipping") continue } lastSensors = *request } err := msgcodec.Send(c, **request) if err != nil { return } } }() // Data from web loop for { request := []interface{}{} msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} err := msgcodec.Receive(c, &request) if err != nil { fmt.Println(err) die = true close(wsSendChan) return } action := string(request[0].([]uint8)) fmt.Println(action) if action == "signScript" { scriptBytes, err := SignatureSignScript(userId, request[1].([]byte)) if err != nil { LogPrintf("notify: request") continue } request[1] = scriptBytes requestP := &request wsSendChan <- &requestP } else if strings.HasPrefix(action, "gist_") { responseGH := GithubGistHandle(userId, request) if responseGH != nil { wsSendChan <- &responseGH } } else { WSSendDevice(userId, &request) } } }
func WSWebHandler(c *websocket.Conn) { defer c.Close() userId, err := userID(c.Request()) if err != nil || userId == "" { path := strings.Split(c.Request().URL.Path, "/") if len(path) != 4 { fmt.Println("Bad path") return } userId, err = getSecretUser("ws", secretHash(path[len(path)-1])) if err != nil { fmt.Println(err) return } } fmt.Println("Websocket connected") // TODO: Look into locking and add defer to cleanup later, make buffer size configurable // TODO: This needs the "die" code added, look into glass side also wsSendChan := make(chan **[]interface{}, 5) versionRequestP := &[]interface{}{[]uint8("version"), version} wsSendChan <- &versionRequestP WebChannels[userId] = append(WebChannels[userId], wsSendChan) var lastSensors, lastImage *[]interface{} // Websocket sender go func() { for { request, ok := <-wsSendChan if !ok { break } msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} action := string((**request)[0].([]uint8)) /* NOTE(brandyn): This assumes that the pointer changes between samples, I believe this is safe and it greatly simplifies sending the latest image/sensors. If this doesn't hold, then we would only miss sending a sample so the harm is minimal. */ if action == "image" { if *request == lastImage { fmt.Println("Already sent image, skipping") continue } lastImage = *request } else if action == "sensors" { if *request == lastSensors { fmt.Println("Already sent sensors, skipping") continue } lastSensors = *request } err := msgcodec.Send(c, **request) if err != nil { return } } }() // Data from web loop for { request := []interface{}{} msgcodec := websocket.Codec{MsgpackMarshal, MsgpackUnmarshal} err := msgcodec.Receive(c, &request) if err != nil { fmt.Println(err) return } action := string(request[0].([]uint8)) fmt.Println(action) if action == "sendTimelineImage" { trans := authTransport(userId) if trans == nil { LogPrintf("notify: auth") continue } svc, err := mirror.New(trans.Client()) if err != nil { LogPrintf("notify: mirror") continue } sendImageCard(request[1].(string), "", svc) } else if action == "signScript" { scriptBytes, err := SignatureSignScript(userId, request[1].([]byte)) if err != nil { LogPrintf("notify: request") continue } request[1] = scriptBytes requestP := &request wsSendChan <- &requestP } else { WSSendDevice(userId, &request) } } }