From 67d4d5f1d90253d331862f1669d924bcb98d6b06 Mon Sep 17 00:00:00 2001 From: Giovanni Harting <539@idlegandalf.com> Date: Wed, 13 Dec 2017 16:26:29 +0100 Subject: [PATCH] some errors still causing crashes, error handling work needed --- ledd.go | 223 ++++++++++++++++++++++++++++++++++++++++---------------- proto | 2 +- 2 files changed, 163 insertions(+), 62 deletions(-) diff --git a/ledd.go b/ledd.go index ff5a586..ad9841b 100644 --- a/ledd.go +++ b/ledd.go @@ -3,6 +3,7 @@ package main import ( "encoding/binary" "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" "net" "os" "os/signal" @@ -132,7 +133,13 @@ func (manager *LEDManager) start() { for { select { case led := <-manager.add: - log.Debugf("[%s] Request to add led: %s", led.backend, led.name) + log.Debugf("[%s] Request to add LED: %s (%s)", led.backend, led.name, led.channel) + + if led.name == "" || len(led.channel) == 0 || led.backend == "" { + log.Warningf("[%s] Can't add LED without required information! (%s)", LOG_CLIENTS, led) + continue + } + manager.leds[led.name] = led go manager.color(led) err := LEDCollection.Insert(led) @@ -141,7 +148,8 @@ func (manager *LEDManager) start() { } case led := <-manager.remove: if _, ok := manager.leds[led.name]; ok { - log.Debugf("[%s] Request to remove led %s", led.backend, led.name) + log.Debugf("[%s] Request to remove %s", led.backend, led.name) + LEDCollection.RemoveAll(bson.M{"name": led.name}) delete(manager.leds, led.name) } case color := <-manager.broadcast: @@ -158,7 +166,33 @@ func (manager *LEDManager) color(led *LED) { for { select { case color := <-led.color: - led.setColor(color) + if backend, ok := backManager.backends[led.backend]; ok { + if len(led.channel) != 3 { + log.Warningf("[%s] Currently only RGB LEDs are supported", led.name) + return + } + + cMap := make(map[int32]int32) + r, g, b := color.Clamped().RGB255() + + cMap[led.channel[0]] = int32((float64(r) / 255) * float64(backend.resolution)) + cMap[led.channel[1]] = int32((float64(g) / 255) * float64(backend.resolution)) + cMap[led.channel[2]] = int32((float64(b) / 255) * float64(backend.resolution)) + + wrapperMsg := &ledd.BackendWrapperMessage{ + Msg: &ledd.BackendWrapperMessage_MSetChannel{ + MSetChannel: &ledd.BackendSetChannel{ + NewChannelValues: cMap}}} + + data, err := proto.Marshal(wrapperMsg) + if err != nil { + log.Warningf("[%s] Failed to encode protobuf msg to %s: %s", led.name, backend.name, err) + } + + backend.data <- prepareProtobuf(data) + } else { + log.Warningf("[LM] Failed to set color for %s: backend %s not found", led.name, led.backend) + } } } } @@ -170,7 +204,7 @@ func (manager *BackendManager) start() { select { case backend := <-manager.register: manager.backends[backend.name] = backend - log.Debugf("[%s] New backend: %s", LOG_BACKEND, backend.niceName()) + log.Debugf("[%s] %s registered", LOG_BACKEND, backend.niceName()) wrapperMsg := &ledd.BackendWrapperMessage{ Msg: &ledd.BackendWrapperMessage_MLedd{ MLedd: &ledd.LedD{ @@ -187,7 +221,7 @@ func (manager *BackendManager) start() { backend.data <- prepareProtobuf(data) case backend := <-manager.unregister: if _, ok := manager.backends[backend.name]; ok { - log.Debugf("[%s] Backend %s removed: connection terminated", LOG_BACKEND, backend.socket.RemoteAddr()) + log.Debugf("[%s] %s removed: connection terminated", LOG_BACKEND, backend.socket.RemoteAddr()) close(backend.data) delete(manager.backends, backend.name) } @@ -238,10 +272,10 @@ func (manager *BackendManager) receive(backend *Backend) { if length > 0 { msgLen := binary.BigEndian.Uint32(message[0:4]) - log.Debugf("[%s] Read %d bytes, first protobuf is %d long", backend.niceName(), length, msgLen) + // log.Debugf("[%s] Read %d bytes, first protobuf is %d long", backend.niceName(), length, msgLen) backendMsg := &ledd.BackendWrapperMessage{} - err = proto.Unmarshal(message[4:msgLen+1], backendMsg) + err = proto.Unmarshal(message[4:msgLen+4], backendMsg) if err != nil { log.Warningf("[%s] Couldn't decode protobuf msg!", backend.niceName()) continue @@ -269,10 +303,46 @@ func (manager *ClientManager) start() { select { case client := <-manager.register: manager.clients[client] = true - log.Debugf("[%s] New frontend (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform) + log.Debugf("[%s] Client %s (%s) registered", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform) + + backends := make([]*ledd.Backend, 0, len(backManager.backends)) + leds := make([]*ledd.LED, 0, len(ledManager.leds)) + + for _, led := range ledManager.leds { + leds = append(leds, &ledd.LED{ + Name: led.name, + }) + } + + for _, backend := range backManager.backends { + backends = append(backends, &ledd.Backend{ + Name: backend.name, + Channel: backend.channel, + Resolution: backend.resolution, + Type: backend.platformType, + Version: backend.version, + }) + } + + wrapperMsg := &ledd.ClientWrapperMessage{ + Leds: leds, + Backends: backends, + Msg: &ledd.ClientWrapperMessage_MLedd{ + MLedd: &ledd.LedD{ + Name: config.Name, + }, + }, + } + + data, err := proto.Marshal(wrapperMsg) + if err != nil { + log.Warningf("[%s] Failed to encode protobuf msg: %s", client.socket.RemoteAddr(), err) + } + + client.data <- prepareProtobuf(data) case client := <-manager.unregister: if _, ok := manager.clients[client]; ok { - log.Debugf("[%s] Removed client (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform) + log.Debugf("[%s] %s (%s) removed", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform) close(client.data) delete(manager.clients, client) } @@ -313,55 +383,95 @@ func (manager *ClientManager) receive(client *Client) { break } if length > 0 { - msgLen := binary.BigEndian.Uint32(message[0:4]) + //log.Debugf("[%s] Read %d bytes", client.socket.RemoteAddr(), length) - log.Debugf("[%s] Read %d bytes, first protobuf is %d long", client.socket.RemoteAddr(), length, msgLen) + for i := 0; i < length; { + msgLen := int(binary.BigEndian.Uint32(message[i:i+4])) - clientMsg := &ledd.ClientWrapperMessage{} - err = proto.Unmarshal(message[4:msgLen+1], clientMsg) - if err != nil { - log.Warningf("[%s] Couldn't decode protobuf msg!", client.socket.RemoteAddr()) - continue - } + // log.Debugf("[%s] Reading protobuf after %d (len=%d)", client.socket.RemoteAddr(), i+4, msgLen) - switch msg := clientMsg.Msg.(type) { - case *ledd.ClientWrapperMessage_MClient: - client.platform = msg.MClient.Type - log.Infof("[%s] %s is now identified as client (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform) - clientManager.register <- client - case *ledd.ClientWrapperMessage_MGetLed: - allLED := make([]*ledd.LED, 0) - - for _, led := range ledManager.leds { - allLED = append(allLED, &ledd.LED{Name: led.name}) - } - - data, err := proto.Marshal(&ledd.ClientWrapperMessage{Leds: allLED}) + clientMsg := &ledd.ClientWrapperMessage{} + err = proto.Unmarshal(message[i+4:i+msgLen+4], clientMsg) + i += msgLen + 4 if err != nil { - log.Errorf("[%s] Error encoding protobuf: %s", client.socket.RemoteAddr(), err) + log.Warningf("[%s] Couldn't decode protobuf msg!", client.socket.RemoteAddr()) + continue } - client.data <- prepareProtobuf(data) - case *ledd.ClientWrapperMessage_MAddLed: - backend, ok := backManager.backends[msg.MAddLed.Backend] - if !ok { - log.Warningf("[%s] Can't add LED for non-existing backend %s", client.socket.RemoteAddr(), msg.MAddLed.Backend) - } + switch msg := clientMsg.Msg.(type) { + case *ledd.ClientWrapperMessage_MClient: + client.platform = msg.MClient.Type + log.Infof("[%s] %s is now identified as client (%s)", LOG_CLIENTS, client.socket.RemoteAddr(), client.platform) + clientManager.register <- client + case *ledd.ClientWrapperMessage_MGetLed: + allLED := make([]*ledd.LED, 0) - nLED := &LED{ - name: msg.MAddLed.Name, - channel: msg.MAddLed.Channel, - backend: backend.name, - } + for _, led := range ledManager.leds { + allLED = append(allLED, &ledd.LED{Name: led.name}) + } - ledManager.add <- nLED - case *ledd.ClientWrapperMessage_MSetLed: - led, ok := ledManager.leds[msg.MSetLed.Name] - if !ok { - log.Warningf("[%s] Failed to set LED %s: LED not found", client.socket.RemoteAddr(), msg.MSetLed.Name) - } + data, err := proto.Marshal(&ledd.ClientWrapperMessage{Leds: allLED}) + if err != nil { + log.Errorf("[%s] Error encoding protobuf: %s", client.socket.RemoteAddr(), err) + break + } - led.color <- colorful.Hcl(msg.MSetLed.Colour.Hue, msg.MSetLed.Colour.Chroma, msg.MSetLed.Colour.Light) + client.data <- prepareProtobuf(data) + case *ledd.ClientWrapperMessage_MAddLed: + backend, ok := backManager.backends[msg.MAddLed.Backend] + if !ok { + log.Warningf("[%s] Can't add LED for non-existing backend %s", client.socket.RemoteAddr(), msg.MAddLed.Backend) + break + } + + if _, ok := ledManager.leds[msg.MAddLed.Name]; ok { + log.Warningf("[%s] Can't add LED with exisiting name %s", client.socket.RemoteAddr(), msg.MAddLed.Name) + break + } + + nLED := &LED{ + name: msg.MAddLed.Name, + channel: msg.MAddLed.Channel, + backend: backend.name, + color: make(chan colorful.Color), + } + + ledManager.add <- nLED + case *ledd.ClientWrapperMessage_MSetLed: + leds := clientMsg.Leds + + if len(leds) == 0 { + log.Warningf("[%s] Got setLED with no LEDs attached!", client.socket.RemoteAddr()) + break + } + + for _, pLED := range leds { + led, ok := ledManager.leds[pLED.Name] + if !ok { + log.Warningf("[%s] Failed to set %s: not found", client.socket.RemoteAddr(), pLED.Name) + break + } + // log.Debugf("[%s] Set %s to %s", client.socket.RemoteAddr(), led.name, colorful.Hcl(msg.MSetLed.Colour.Hue, msg.MSetLed.Colour.Chroma, msg.MSetLed.Colour.Light)) + + led.color <- colorful.Hcl(msg.MSetLed.Colour.Hue, msg.MSetLed.Colour.Chroma, msg.MSetLed.Colour.Light) + } + case *ledd.ClientWrapperMessage_MSetDirect: + backend, ok := backManager.backends[msg.MSetDirect.Backend] + if !ok { + log.Warningf("[%s] Can't set channel for non-existing backend %s", client.socket.RemoteAddr(), msg.MSetDirect.Backend) + break + } + + backend.setChannel(msg.MSetDirect.Channel, msg.MSetDirect.Value) + case *ledd.ClientWrapperMessage_MRemoveLed: + led, ok := ledManager.leds[msg.MRemoveLed.Name] + if !ok { + log.Warningf("[%s] Failed to remove %s: not found", client.socket.RemoteAddr(), msg.MRemoveLed.Name) + break + } + + ledManager.remove <- led + } } } } @@ -383,19 +493,10 @@ func (backend *Backend) niceName() string { } } -func (led *LED) setColor(color colorful.Color) { - backend := backManager.backends[led.backend] - - if len(led.channel) != 3 { - log.Warningf("[%s] Currently only RGB LEDs are supported", led.name) - return - } - +func (backend Backend) setChannel(channel int32, val int32) { cMap := make(map[int32]int32) - cMap[led.channel[0]] = int32(color.R * float64(backend.resolution)) - cMap[led.channel[1]] = int32(color.G * float64(backend.resolution)) - cMap[led.channel[2]] = int32(color.B * float64(backend.resolution)) + cMap[channel] = val wrapperMsg := &ledd.BackendWrapperMessage{ Msg: &ledd.BackendWrapperMessage_MSetChannel{ @@ -404,7 +505,7 @@ func (led *LED) setColor(color colorful.Color) { data, err := proto.Marshal(wrapperMsg) if err != nil { - log.Warningf("[%s] Failed to encode protobuf msg to %s: %s", led.name, backend.name, err) + log.Warningf("[%s] Failed to encode protobuf msg: %s", backend.niceName(), err) } backend.data <- prepareProtobuf(data) diff --git a/proto b/proto index c0b46db..b0f65bb 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit c0b46db0cf38cfd192d6a787c0328cbff8db42fb +Subproject commit b0f65bb09ae34aabcb84b12561a46d0972e2ddc9