ghostream/stream/telnet/telnet.go

123 lines
2.7 KiB
Go
Raw Normal View History

2020-10-18 14:14:08 +00:00
// Package telnet expose text version of stream.
package telnet
import (
"log"
"net"
2020-10-18 14:14:08 +00:00
"strings"
"time"
"gitlab.crans.org/nounous/ghostream/messaging"
2020-10-12 22:15:23 +00:00
)
// Options holds telnet package configuration
type Options struct {
Enabled bool
ListenAddress string
}
2020-10-17 16:12:25 +00:00
// Serve Telnet server
func Serve(streams *messaging.Streams, cfg *Options) {
2020-10-17 16:12:25 +00:00
if !cfg.Enabled {
// Telnet is not enabled, ignore
2020-10-12 22:15:23 +00:00
return
}
2020-10-17 16:12:25 +00:00
// Start TCP server
listener, err := net.Listen("tcp", cfg.ListenAddress)
if err != nil {
2020-10-17 16:12:25 +00:00
log.Fatalf("Error while listening to the address %s: %s", cfg.ListenAddress, err)
}
2020-10-17 16:12:25 +00:00
log.Printf("Telnet server listening on %s", cfg.ListenAddress)
2020-10-17 16:12:25 +00:00
// Handle each new client
for {
socket, err := listener.Accept()
2020-10-17 16:12:25 +00:00
if err != nil {
log.Printf("Error while accepting TCP socket: %s", err)
2020-10-17 16:12:25 +00:00
continue
}
go handleViewer(socket, streams, cfg)
}
}
2020-10-18 14:14:08 +00:00
func handleViewer(s net.Conn, streams *messaging.Streams, cfg *Options) {
2020-10-18 14:14:08 +00:00
// 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
stream, err := streams.Get(name)
if err != nil {
log.Printf("Stream does not exist, kicking new Telnet viewer: %s", err)
2020-10-18 14:14:08 +00:00
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
}
// Get requested quality
// FIXME: make qualities available
qualityName := "source"
q, err := stream.GetQuality(qualityName)
if err != nil {
log.Printf("Failed to get quality: %s", err)
s.Close()
return
}
log.Printf("New Telnet viewer for stream %s quality %s", name, qualityName)
2020-10-18 14:14:08 +00:00
// Register new client
c := make(chan []byte, 128)
q.Register(c)
stream.IncrementClientCount()
2020-10-18 14:14:08 +00:00
// 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
q.Unregister(c)
stream.DecrementClientCount()
2020-10-18 14:14:08 +00:00
s.Close()
}