func (m *multiplexer) routeMessages(ws *websocket.Conn) { stopSignal := make(chan bool, 1) // Read messages from backend go func(stop chan<- bool) { for { msgType, msg, err := ws.ReadMessage() if err != nil { m.shutdown(stop) return } if msgType != websocket.TextMessage { continue } message := common.ParseMessage(string(msg)) m.frontendMu.RLock() frontendChan, ok := m.frontendChans[message.Key] if ok { frontendChan <- message } m.frontendMu.RUnlock() if !ok && message.Type != common.Close { m.sendClose(message.Key) } } }(stopSignal) // Write messages to backend go func(stop <-chan bool) { ticker := time.NewTicker(time.Second * 5) defer ticker.Stop() for { select { case message, ok := <-m.messagesToBackend: if !ok { return } err := ws.WriteMessage(websocket.TextMessage, []byte(message)) if err != nil { log.WithFields(log.Fields{"error": err, "msg": message}).Error("Could not write message.") } case <-ticker.C: ws.WriteControl(websocket.PingMessage, []byte(""), time.Now().Add(time.Second)) case <-stop: return } } }(stopSignal) }
func (m *multiplexer) routeMessages(ws *websocket.Conn) { stopSignal := make(chan bool, 1) // Read messages from backend go func(stop chan<- bool) { for { _, msg, err := ws.ReadMessage() if err != nil { m.shutdown(stop) return } message := common.ParseMessage(string(msg)) m.frontendMu.RLock() frontendChan, ok := m.frontendChans[message.Key] if ok { frontendChan <- message } m.frontendMu.RUnlock() if !ok && message.Type != common.Close { log.WithFields(log.Fields{"Message": message}).Warn( "Could not find channel for message. Dropping message and sending close to backend.") m.sendClose(message.Key) } } }(stopSignal) // Write messages to backend go func(stop <-chan bool) { for { select { case message, ok := <-m.messagesToBackend: if !ok { return } err := ws.WriteMessage(websocket.TextMessage, []byte(message)) if err != nil { log.WithFields(log.Fields{"error": err, "msg": message}).Error("Could not write message.") } case <-stop: return } } }(stopSignal) }
func connectToProxyWS(ws *websocket.Conn, handlers map[string]Handler) { responders := make(map[string]chan string) responseChannel := make(chan common.Message, 10) // Write messages to proxy go func() { for { message, ok := <-responseChannel if !ok { return } data := common.FormatMessage(message.Key, message.Type, message.Body) ws.WriteMessage(1, []byte(data)) } }() // Read and route messages from proxy for { _, msg, err := ws.ReadMessage() if err != nil { log.WithFields(log.Fields{"error": err}).Error("Received error reading from socket. Exiting.") close(responseChannel) return } message := common.ParseMessage(string(msg)) switch message.Type { case common.Connect: requestUrl, err := url.Parse(message.Body) if err != nil { continue } handler, ok := getHandler(requestUrl.Path, handlers) if ok { msgChan := make(chan string, 10) responders[message.Key] = msgChan go handler.Handle(message.Key, message.Body, msgChan, responseChannel) } else { log.WithFields(log.Fields{"path": requestUrl.Path}).Warn("Could not find appropriate message handler for supplied path.") responseChannel <- common.Message{ Key: message.Key, Type: common.Close, Body: ""} } case common.Body: if msgChan, ok := responders[message.Key]; ok { msgChan <- message.Body } else { log.WithFields(log.Fields{"key": message.Key}).Warn("Could not find responder for specified key.") responseChannel <- common.Message{ Key: message.Key, Type: common.Close, } } case common.Close: closeHandler(responders, message.Key) default: log.WithFields(log.Fields{"messageType": message.Type}).Warn("Unrecognized message type. Closing connection.") closeHandler(responders, message.Key) SignalHandlerClosed(message.Key, responseChannel) continue } } }