From af9fa4ab4b0ce94915c848ce54d0755faa57ed19 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Wed, 24 Apr 2024 01:18:49 -0600 Subject: [PATCH] Update client ncurses with borders --- channel.go | 1 + cmd/client/main.go | 70 ++++++++++++++++++++++++++-------------------- go-ncurses | 2 +- server.go | 43 +++++++++++++++------------- 4 files changed, 65 insertions(+), 51 deletions(-) diff --git a/channel.go b/channel.go index d2635d7..818a5bd 100644 --- a/channel.go +++ b/channel.go @@ -55,6 +55,7 @@ func NewChannel(modes map[ModeID]Mode) (*Channel, error) { } channel.Members.Store([]*ServerSession{}) + channel.BasePermissions.Store(Permissions{}) channel.RolePermissions.Store(map[Role]Permissions{}) channel.UserPermissions.Store(map[PeerID]Permissions{}) diff --git a/cmd/client/main.go b/cmd/client/main.go index 70d5ec4..42aee83 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -271,16 +271,35 @@ func get_private_key(path string, generate bool) ed25519.PrivateKey { } } -func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Window, packet_chan chan pnyx.Payload, user_chan chan rune) { - max_y := ncurses.GetMaxY(window) - max_x := ncurses.GetMaxX(window) - titlebar := ncurses.NewWin(1, max_x, 0, 0) - channels := ncurses.NewWin(max_y - 1, max_x / 3, 1, 0) - body := ncurses.NewWin(max_y - 1, max_x * 2 / 3, 1, max_x / 3) +func print_decoration(window, channels, body ncurses.Window, top_left string) { + max_y := ncurses.GetMaxY(*ncurses.CurScr) + max_x := ncurses.GetMaxX(*ncurses.CurScr) - ncurses.MvWAddStr(titlebar, 0, 0, fmt.Sprintf("pnyx client %X:%X", client.Key.Public().(ed25519.PublicKey)[:2], client.Session.ID[:2])) - ncurses.MvWAddStr(body, 0, max_x-len(client.Remote()), client.Remote()) - ncurses.WRefresh(titlebar) + ncurses.WResize(channels, max_y - 2, (max_x / 4) - 1) + ncurses.WResize(body, max_y - 2, max_x - (max_x / 4) - 1) + ncurses.MvWin(body, 2, (max_x / 4) + 1) + + ncurses.MvWAddStr(window, 0, 0, top_left) + + for i := 0; i < max_x; i++ { + ncurses.MvWAddStr(window, 1, i, "═") + } + + ncurses.MvWAddStr(window, 1, max_x/4, "╦") + for i := 2; i < max_y; i++ { + ncurses.MvWAddStr(window, i, max_x/4, "║") + } + + ncurses.WRefresh(window) + ncurses.WRefresh(channels) + ncurses.WRefresh(body) +} + +func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Window, packet_chan chan pnyx.Payload, user_chan chan []byte) { + channels := ncurses.NewWin(0, 0, 2, 0) + body := ncurses.NewWin(0, 0, 2, 0) + + print_decoration(window, channels, body, fmt.Sprintf("pnyx client %X:%X", client.Key.Public().(ed25519.PublicKey)[:2], client.Session.ID[:2])) for client.Active() { select { @@ -325,30 +344,12 @@ func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Wind } } case char := <-user_chan: - ncurses.MvWAddStr(body, 0, 0, string(char)) + ncurses.WAddStr(body, string(char)) ncurses.WRefresh(body) - - ncurses.MvWAddStr(channels, 0, 0, string(char)) - ncurses.WRefresh(channels) } } } -func bitmatch(b byte, pattern byte, length int) bool { - mask := ^(byte(1 << (8 - length)) - 1) - return (b ^ pattern) & mask == 0 -} - -func ch_listen(client *pnyx.Client, user_chan chan rune) { - b := [4]byte{} - for client.Active() { - os.Stdin.Read(b[0:1]) - if bitmatch(b[0], 0b00000000, 1) { - user_chan <- rune(b[0]) - } // TODO: further utf-8 support - } -} - func process_mic(client *pnyx.Client, mic chan []byte) { for true { data := <- mic @@ -380,7 +381,7 @@ func main() { defer inDevice.Stop() - user_chan := make(chan rune, 1024) + user_chan := make(chan []byte, 1024) packet_chan := make(chan pnyx.Payload, 1024) key := get_private_key(os.ExpandEnv(*key_file_arg), *generate_key_arg) @@ -409,15 +410,24 @@ func main() { } go process_mic(client, mic) - go ch_listen(client, user_chan) + locale := ncurses.SetLocale(0, "") + fmt.Printf("locale: %s\n", locale) + + user_chan, stdin_active := ncurses.UTF8Listener(100, os.Stdin) window := ncurses.InitScr() + ret := ncurses.StartColor() + if ret != 0 { + panic(ret) + } + go main_loop(client, audio_data, window, packet_chan, user_chan) os_sigs := make(chan os.Signal, 1) signal.Notify(os_sigs, syscall.SIGINT, syscall.SIGABRT) <-os_sigs + stdin_active.Store(false) client.Close() ncurses.EndWin() } diff --git a/go-ncurses b/go-ncurses index 281f038..e345e72 160000 --- a/go-ncurses +++ b/go-ncurses @@ -1 +1 @@ -Subproject commit 281f038f5f113180749d3af477311cd874208a3e +Subproject commit e345e72ff0e54e5c25271223849cad34ce8620b3 diff --git a/server.go b/server.go index 41f960a..f196838 100644 --- a/server.go +++ b/server.go @@ -40,8 +40,9 @@ type Server struct { key ed25519.PrivateKey active atomic.Bool connection *net.UDPConn - stopped chan error commands chan Payload + + threads sync.WaitGroup sessions_lock sync.Mutex sessions map[SessionID]*ServerSession @@ -79,7 +80,6 @@ func NewServer(listen string, key ed25519.PrivateKey, channels map[ChannelID]*Ch key: key, connection: connection, active: atomic.Bool{}, - stopped: make(chan error, 0), commands: make(chan Payload, SERVER_COMMAND_BUFFER_SIZE), sessions: map[SessionID]*ServerSession{}, @@ -87,6 +87,7 @@ func NewServer(listen string, key ed25519.PrivateKey, channels map[ChannelID]*Ch peers: map[PeerID][]RoleID{}, } + server.channels.Store(channels) server.BasePermissions.Store(Permissions{}) @@ -95,6 +96,7 @@ func NewServer(listen string, key ed25519.PrivateKey, channels map[ChannelID]*Ch server.active.Store(true) + server.threads.Add(2) go server.listen_udp() go server.update_state() @@ -107,11 +109,9 @@ func(server *Server) Log(format string, fields ...interface{}) { func(server *Server) Stop() error { if server.active.CompareAndSwap(true, false) { - err := server.connection.Close() - if err != nil { - return err - } - return <-server.stopped + close(server.commands) + server.threads.Wait() + return nil } else { return fmt.Errorf("Called stop on stopped server") } @@ -332,9 +332,8 @@ func(server *Server) handle_session_data(data []byte, from *net.UDPAddr) error { } func(server *Server) listen_udp() { - server.Log("Started server on %s", server.connection.LocalAddr()) - var buf [SERVER_UDP_BUFFER_SIZE]byte + server.Log("UDP_START: %s", server.connection.LocalAddr()) for true { read, from, err := server.connection.ReadFromUDP(buf[:]) if err == nil { @@ -374,6 +373,19 @@ func(server *Server) listen_udp() { server.Log("UDP_READ_ERROR: %s", err) } } + server.threads.Done() +} + +func(server *Server) update_state() { + for server.active.Load() { + select { + case command := <-server.commands: + if command == nil { + break + } + server.Log("Incoming server command %+v", command) + } + } channels := server.channels.Load().(map[ChannelID]*Channel) for _, channel := range(channels) { @@ -389,10 +401,10 @@ func(server *Server) listen_udp() { for _, session := range(sessions) { server.close_session(session) } + server.connection.Close() server.sessions_lock.Unlock() - server.Log("Shut down server on %s", server.connection.LocalAddr()) - server.stopped <- nil + server.threads.Done() } func(server *Server) close_session(session *ServerSession) { @@ -404,12 +416,3 @@ func(server *Server) close_session(session *ServerSession) { session_closed := NewSessionTimed(SESSION_CLOSED, server.key, &session.Session, time.Now()) server.connection.WriteToUDP(session_closed, session.remote) } - -func(server *Server) update_state() { - for server.active.Load() { - select { - case command := <-server.commands: - server.Log("Incoming server command %+v", command) - } - } -}