113 lines
2.4 KiB
Go
113 lines
2.4 KiB
Go
// Package telnet expose text version of stream.
|
|
package telnet
|
|
|
|
import (
|
|
"log"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
"gitlab.crans.org/nounous/ghostream/stream"
|
|
)
|
|
|
|
// Options holds telnet package configuration
|
|
type Options struct {
|
|
Enabled bool
|
|
ListenAddress string
|
|
}
|
|
|
|
// Serve Telnet server
|
|
func Serve(streams map[string]*stream.Stream, cfg *Options) {
|
|
if !cfg.Enabled {
|
|
// Telnet is not enabled, ignore
|
|
return
|
|
}
|
|
|
|
// Start TCP server
|
|
listener, err := net.Listen("tcp", cfg.ListenAddress)
|
|
if err != nil {
|
|
log.Fatalf("Error while listening to the address %s: %s", cfg.ListenAddress, err)
|
|
}
|
|
log.Printf("Telnet server listening on %s", cfg.ListenAddress)
|
|
|
|
// Handle each new client
|
|
for {
|
|
s, err := listener.Accept()
|
|
if err != nil {
|
|
log.Printf("Error while accepting TCP socket: %s", s)
|
|
continue
|
|
}
|
|
|
|
go handleViewer(s, streams, cfg)
|
|
}
|
|
}
|
|
|
|
func handleViewer(s net.Conn, streams map[string]*stream.Stream, cfg *Options) {
|
|
// Prompt user about stream name
|
|
if _, err := s.Write([]byte("[GHOSTREAM]\nEnter stream name: ")); err != nil {
|
|
log.Printf("Error while writing to TCP socket: %s", err)
|
|
s.Close()
|
|
return
|
|
}
|
|
buff := make([]byte, 255)
|
|
n, err := s.Read(buff)
|
|
if err != nil {
|
|
log.Printf("Error while requesting stream ID to telnet client: %s", err)
|
|
s.Close()
|
|
return
|
|
}
|
|
name := strings.TrimSpace(string(buff[:n])) + "@text"
|
|
if len(name) < 1 {
|
|
// Too short, exit
|
|
s.Close()
|
|
return
|
|
}
|
|
|
|
// Wait a bit
|
|
time.Sleep(time.Second)
|
|
|
|
// Get requested stream
|
|
st, ok := streams[name]
|
|
if !ok {
|
|
log.Println("Stream does not exist, kicking new Telnet viewer")
|
|
if _, err := s.Write([]byte("This stream is inactive.\n")); err != nil {
|
|
log.Printf("Error while writing to TCP socket: %s", err)
|
|
}
|
|
s.Close()
|
|
return
|
|
}
|
|
|
|
// Register new client
|
|
log.Printf("New Telnet viewer for stream '%s'", name)
|
|
c := make(chan []byte, 128)
|
|
st.Register(c)
|
|
st.IncrementClientCount()
|
|
|
|
// Hide terminal cursor
|
|
if _, err = s.Write([]byte("\033[?25l")); err != nil {
|
|
log.Printf("Error while writing to TCP socket: %s", err)
|
|
s.Close()
|
|
return
|
|
}
|
|
|
|
// Receive data and send them
|
|
for data := range c {
|
|
if len(data) < 1 {
|
|
log.Print("Remove Telnet viewer because of end of stream")
|
|
break
|
|
}
|
|
|
|
// Send data
|
|
_, err := s.Write(data)
|
|
if err != nil {
|
|
log.Printf("Remove Telnet viewer because of sending error, %s", err)
|
|
break
|
|
}
|
|
}
|
|
|
|
// Close output
|
|
st.Unregister(c)
|
|
st.DecrementClientCount()
|
|
s.Close()
|
|
}
|