func (ep *WebsocketConnection) run() { // Theres some missing logic here when it comes to dealing with closes, including whats // actually returned from those closes for { if msgType, bytes, err := ep.conn.ReadMessage(); err != nil { if ep.closed { core.Info("peer connection closed") } else { core.Info("error reading from peer:", err) ep.conn.Close() } // ep.App.Close() break } else if msgType == websocket.CloseMessage { core.Info("Close message recieved") ep.conn.Close() // ep.App.Close() break } else { ep.app.ReceiveBytes(bytes) } } }
// Blocks on callbacks from the core. // TODO: trigger a close meta callback when connection is lost func (a *App) Receive() { Debug("Starting receive") for { cb := a.conn.app.CallbackListen() core.Debug("Have callback: %v", cb) if cb.Id == 0 { // Trigger onLeave for all domains core.Info("Terminating receive loop") return } if fn, ok := a.subscriptions[cb.Id]; ok { fn.Invoke(cb.Args) } if fn, ok := a.registrations[cb.Id]; ok { core.Debug("Invocation: %v", cb.Args) ret := fn.Invoke(cb.Args[1:]...) a.conn.app.Yield(cb.Args[0].(uint64), []interface{}{ret.Interface()}) } } }
// Who the hell do we call close first on? App or connection? // Either way one or the other may have to check on the other, which is no good func (ep *WebsocketConnection) Close(reason string) error { core.Info("Closing connection with reason: %s", reason) closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "goodbye") err := ep.conn.WriteControl(websocket.CloseMessage, closeMsg, time.Now().Add(5*time.Second)) if err != nil { log.Println("error sending close message:", err) } ep.lock = nil ep.closed = true return ep.conn.Close() }
// Blocks on callbacks from the core. // TODO: trigger a close meta callback when connection is lost func (a *App) Receive() { for { cb := a.conn.app.CallbackListen() if cb.Id == 0 { // TODO: Trigger onLeave for all domains core.Info("Terminating receive loop") return } if fn, ok := a.subscriptions[cb.Id]; ok { fn.Invoke(cb.Args...) } if fn, ok := a.registrations[cb.Id]; ok { ret := fn.Invoke(cb.Args[1:]...) a.conn.app.Yield(cb.Args[0].(uint64), []interface{}{ret.Interface()}) } } }
func Info(s string) { core.Info("%s", s) }
//export Info func Info(s *C.char) { core.Info("%s", C.GoString(s)) }