home » torr/wssrv.git
ID: 369d546b8519a0b4262c91ab68b1d05eef599ff6
89 lines — 2K — View raw


package ws

import (
	"context"
	"fmt"
	"io"
	"os"
	"time"
	"wssrv/log"

	"github.com/gorilla/websocket"
)

func readMessage(ctx context.Context, cancel context.CancelCauseFunc, con *websocket.Conn) {
	var (
		err error
		msg []byte
	)
	for err != io.EOF {
		select {
		case <-ctx.Done():
			return
		default:
			if _, msg, err = con.ReadMessage(); err != nil {
				// chErr <- fmt.Errorf("unable to read from websocket on '%s': %v", con.RemoteAddr(), err)
				cancel(fmt.Errorf("unable to read from websocket on '%s': %v", con.RemoteAddr(), err))
				return
			}
			fmt.Printf("(%s): %s\n", con.RemoteAddr(), msg)
		}
	}
}

func sendFile(ctx context.Context, cancel context.CancelCauseFunc, con *websocket.Conn, fileNa string, data []byte, interv time.Duration) {
	var err error
	for {
		select {
		case <-ctx.Done():
			return
		default:
			log.Info.Printf("sending file '%s'", fileNa)
			if err = con.WriteMessage(websocket.TextMessage, data); err != nil {
				// chErr <- fmt.Errorf("unable write on websocket on '%s': %v", con.RemoteAddr(), err)
				cancel(fmt.Errorf("unable write on websocket on '%s': %v", con.RemoteAddr(), err))
				return
			}
			log.Info.Printf("sleeping for '%v'", interv)
			time.Sleep(interv)
		}
	}

}

func sendFileByInterval(con *websocket.Conn, fileNa string, interv time.Duration) error {
	var (
		err  error
		data []byte

		ctx, cancel = context.WithCancelCause(context.Background())
	)

	if data, err = os.ReadFile(fileNa); err != nil {
		return fmt.Errorf("unable to read file '%s': %v", fileNa, err)
	}

	go readMessage(ctx, cancel, con)
	go sendFile(ctx, cancel, con, fileNa, data, interv)

	<-ctx.Done()
	return context.Cause(ctx)
}

// SendFileByInterval repeatedly sends a given file in the websocket according
// to an interval.
func SendFileByInterval(con *websocket.Conn, fileNa string, interv time.Duration) error {
	switch {
	case con == nil:
		return fmt.Errorf("nil connection parameter")
	case len(fileNa) == 0:
		return fmt.Errorf("empty file parameter")
	case interv < 1:
		return fmt.Errorf("non positive interval parameter")
	}
	if err := checkFile(fileNa); err != nil {
		return err
	}

	return sendFileByInterval(con, fileNa, interv)
}