mirror of
https://gitlab.crans.org/nounous/ghostream.git
synced 2025-06-29 09:50:56 +02:00
Restructure telnet package
This commit is contained in:
@ -2,20 +2,11 @@
|
||||
package telnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// Cfg contains the different options of the telnet package, see below
|
||||
// TODO Config should not be exported
|
||||
Cfg *Options
|
||||
currentMessage map[string]*string
|
||||
clientCount map[string]int
|
||||
"gitlab.crans.org/nounous/ghostream/stream"
|
||||
)
|
||||
|
||||
// Options holds telnet package configuration
|
||||
@ -27,152 +18,52 @@ type Options struct {
|
||||
Delay int
|
||||
}
|
||||
|
||||
// Serve starts the telnet server and listen to clients
|
||||
func Serve(config *Options) {
|
||||
Cfg = config
|
||||
|
||||
if !config.Enabled {
|
||||
// Serve Telnet server
|
||||
func Serve(streams map[string]*stream.Stream, cfg *Options) {
|
||||
if !cfg.Enabled {
|
||||
// Telnet is not enabled, ignore
|
||||
return
|
||||
}
|
||||
|
||||
currentMessage = make(map[string]*string)
|
||||
clientCount = make(map[string]int)
|
||||
// Start conversion routine
|
||||
textStreams := make(map[string]*[]byte)
|
||||
go autoStartConversion(streams, textStreams, cfg)
|
||||
|
||||
listener, err := net.Listen("tcp", config.ListenAddress)
|
||||
// Start TCP server
|
||||
listener, err := net.Listen("tcp", cfg.ListenAddress)
|
||||
if err != nil {
|
||||
log.Printf("Error while listening to the address %s: %s", config.ListenAddress, err)
|
||||
return
|
||||
log.Fatalf("Error while listening to the address %s: %s", cfg.ListenAddress, err)
|
||||
}
|
||||
log.Printf("Telnet server listening on %s", cfg.ListenAddress)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
s, err := listener.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Error while accepting TCP socket: %s", s)
|
||||
// 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, textStreams, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
// Convertion routine listen to existing stream and start text conversions
|
||||
func autoStartConversion(streams map[string]*stream.Stream, textStreams map[string]*[]byte, cfg *Options) {
|
||||
for {
|
||||
for name, stream := range streams {
|
||||
textStream, ok := textStreams[name]
|
||||
if ok {
|
||||
// Everything is fine
|
||||
continue
|
||||
}
|
||||
|
||||
go func(s net.Conn) {
|
||||
streamID := ""
|
||||
// Request for stream ID
|
||||
for {
|
||||
_, err = s.Write([]byte("[GHOSTREAM]\nEnter stream ID: "))
|
||||
if err != nil {
|
||||
log.Println("Error while requesting stream ID to telnet client")
|
||||
_ = s.Close()
|
||||
return
|
||||
}
|
||||
buff := make([]byte, 255)
|
||||
n, err := s.Read(buff)
|
||||
if err != nil {
|
||||
log.Println("Error while requesting stream ID to telnet client")
|
||||
_ = s.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// Avoid bruteforce
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
streamID = string(buff[:n])
|
||||
streamID = strings.Replace(streamID, "\r", "", -1)
|
||||
streamID = strings.Replace(streamID, "\n", "", -1)
|
||||
|
||||
if len(streamID) > 0 {
|
||||
if strings.ToLower(streamID) == "exit" {
|
||||
_, _ = s.Write([]byte("Goodbye!\n"))
|
||||
_ = s.Close()
|
||||
return
|
||||
}
|
||||
if _, ok := currentMessage[streamID]; !ok {
|
||||
_, err = s.Write([]byte("Unknown stream ID.\n"))
|
||||
if err != nil {
|
||||
log.Println("Error while requesting stream ID to telnet client")
|
||||
_ = s.Close()
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
clientCount[streamID]++
|
||||
|
||||
// Hide terminal cursor
|
||||
_, _ = s.Write([]byte("\033[?25l"))
|
||||
|
||||
for {
|
||||
n, err := s.Write([]byte(*currentMessage[streamID]))
|
||||
if err != nil {
|
||||
log.Printf("Error while sending TCP data: %s", err)
|
||||
_ = s.Close()
|
||||
clientCount[streamID]--
|
||||
break
|
||||
}
|
||||
if n == 0 {
|
||||
_ = s.Close()
|
||||
clientCount[streamID]--
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Duration(config.Delay) * time.Millisecond)
|
||||
}
|
||||
}(s)
|
||||
// Start conversion
|
||||
log.Print("Starting text conversion of %s", name)
|
||||
textStream = &[]byte{}
|
||||
textStreams[name] = textStream
|
||||
go streamToTextStream(stream, textStream, cfg)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Println("Telnet server initialized")
|
||||
}
|
||||
|
||||
// GetNumberConnectedSessions returns the numbers of clients that are viewing the stream through a telnet shell
|
||||
func GetNumberConnectedSessions(streamID string) int {
|
||||
if Cfg == nil || !Cfg.Enabled {
|
||||
return 0
|
||||
}
|
||||
return clientCount[streamID]
|
||||
}
|
||||
|
||||
// StartASCIIArtStream send all packets received by ffmpeg as ASCII Art to telnet clients
|
||||
func StartASCIIArtStream(streamID string, reader io.ReadCloser) {
|
||||
if !Cfg.Enabled {
|
||||
_ = reader.Close()
|
||||
return
|
||||
}
|
||||
|
||||
currentMessage[streamID] = new(string)
|
||||
pixelBuff := make([]byte, Cfg.Width*Cfg.Height)
|
||||
textBuff := strings.Builder{}
|
||||
for {
|
||||
n, err := reader.Read(pixelBuff)
|
||||
if err != nil {
|
||||
log.Printf("An error occurred while reading input: %s", err)
|
||||
break
|
||||
}
|
||||
if n == 0 {
|
||||
// Stream is finished
|
||||
break
|
||||
}
|
||||
|
||||
// Header
|
||||
textBuff.Reset()
|
||||
textBuff.Grow((40*Cfg.Width+6)*Cfg.Height + 47)
|
||||
for i := 0; i < 42; i++ {
|
||||
textBuff.WriteByte('\n')
|
||||
}
|
||||
|
||||
// Convert image to ASCII
|
||||
for i, pixel := range pixelBuff {
|
||||
if i%Cfg.Width == 0 {
|
||||
// New line
|
||||
textBuff.WriteString("\033[49m\n")
|
||||
}
|
||||
|
||||
// Print two times the character to make a square
|
||||
text := fmt.Sprintf("\033[48;2;%d;%d;%dm ", pixel, pixel, pixel)
|
||||
textBuff.WriteString(text)
|
||||
textBuff.WriteString(text)
|
||||
}
|
||||
textBuff.WriteString("\033[49m")
|
||||
|
||||
*(currentMessage[streamID]) = textBuff.String()
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user