// Listen to a remote stream func (h *Handler) Listen(conn *message.Conn) { defer (func() { // Will be executed when the connection is closed conn.Close() var session *message.Session if h.ctx.IsServer() { session = h.ctx.Auth.GetSession(conn.Id) if session != nil { h.ctx.Auth.Logout(conn.Id) conn.Broadcast(func(w io.Writer) error { return builder.SendPlayerLeft(w, h.ctx.Clock.GetRelativeTick(), session.Entity.Id) }) } } if h.ctx.IsClient() { session = h.ctx.Me } if session != nil && session.Entity != nil { // TODO: move this elsewhere h.ctx.Entity.Delete(session.Entity.Id, h.ctx.Clock.GetAbsoluteTick()) } })() var msgType message.Type for { err := read(conn, &msgType) if err == io.EOF { log.Println("Connection closed.") return } else if err != nil { log.Println("binary.Read failed:", err) return } done := make(chan error, 1) go func() { done <- h.Handle(msgType, conn) }() select { case err = <-done: if err != nil { log.Printf("Message handling failed for %q: %v\n", message.GetTypeName(msgType), err) return } case <-time.After(time.Second * 15): log.Printf("Message handling timed out for %q\n", message.GetTypeName(msgType)) err = fmt.Errorf("Message handling timed out for %q", message.GetTypeName(msgType)) return } } }