home » torr/wssrv.git
Author C. Torres <torr.c@mailgw.com> 2024-12-16 00:52:36
Committer C. Torres <torr.c@mailgw.com> 2024-12-16 00:52:36
Commit 80ab375 (patch)
Tree 8086690
Parent(s)

Implement intervaled file serving mode Implement a serving mode where a file is repeatedly sent in the websocket according to an interval. Signed-off-by: C. Torres <torr.c@mailgw.com>


commits diff: 937e0f3..80ab375
3 files changed, 115 insertions, 14 deletionsdownload


Diffstat
-rw-r--r-- ws/common.go 24
-rw-r--r-- ws/file_interval.go 89
-rw-r--r-- ws/file_reply.go 16

Diff options
View
Side
Whitespace
Context lines
Inter-hunk lines
+24/-0 A   ws/common.go
index 0000000..fe8a586
old size: 0B - new size: 422B
new file mode: -rw-r--r--
@@ -0,0 +1,24 @@
1 + package ws
2 +
3 + import (
4 + "fmt"
5 + "os"
6 + )
7 +
8 + func checkFile(fileNa string) error {
9 + var (
10 + err error
11 + stat os.FileInfo
12 + )
13 +
14 + if stat, err = os.Stat(fileNa); err != nil {
15 + return fmt.Errorf("unable to check metadata for file '%s': %v", fileNa, err)
16 + }
17 + if !stat.Mode().IsRegular() {
18 + return fmt.Errorf("file '%s' is not regular")
19 + }
20 + if stat.Mode()&0444 == 0 {
21 + return fmt.Errorf("file '%s' is not readable")
22 + }
23 + return nil
24 + }

+89/-0 A   ws/file_interval.go
index 0000000..369d546
old size: 0B - new size: 2K
new file mode: -rw-r--r--
@@ -0,0 +1,89 @@
1 + package ws
2 +
3 + import (
4 + "context"
5 + "fmt"
6 + "io"
7 + "os"
8 + "time"
9 + "wssrv/log"
10 +
11 + "github.com/gorilla/websocket"
12 + )
13 +
14 + func readMessage(ctx context.Context, cancel context.CancelCauseFunc, con *websocket.Conn) {
15 + var (
16 + err error
17 + msg []byte
18 + )
19 + for err != io.EOF {
20 + select {
21 + case <-ctx.Done():
22 + return
23 + default:
24 + if _, msg, err = con.ReadMessage(); err != nil {
25 + // chErr <- fmt.Errorf("unable to read from websocket on '%s': %v", con.RemoteAddr(), err)
26 + cancel(fmt.Errorf("unable to read from websocket on '%s': %v", con.RemoteAddr(), err))
27 + return
28 + }
29 + fmt.Printf("(%s): %s\n", con.RemoteAddr(), msg)
30 + }
31 + }
32 + }
33 +
34 + func sendFile(ctx context.Context, cancel context.CancelCauseFunc, con *websocket.Conn, fileNa string, data []byte, interv time.Duration) {
35 + var err error
36 + for {
37 + select {
38 + case <-ctx.Done():
39 + return
40 + default:
41 + log.Info.Printf("sending file '%s'", fileNa)
42 + if err = con.WriteMessage(websocket.TextMessage, data); err != nil {
43 + // chErr <- fmt.Errorf("unable write on websocket on '%s': %v", con.RemoteAddr(), err)
44 + cancel(fmt.Errorf("unable write on websocket on '%s': %v", con.RemoteAddr(), err))
45 + return
46 + }
47 + log.Info.Printf("sleeping for '%v'", interv)
48 + time.Sleep(interv)
49 + }
50 + }
51 +
52 + }
53 +
54 + func sendFileByInterval(con *websocket.Conn, fileNa string, interv time.Duration) error {
55 + var (
56 + err error
57 + data []byte
58 +
59 + ctx, cancel = context.WithCancelCause(context.Background())
60 + )
61 +
62 + if data, err = os.ReadFile(fileNa); err != nil {
63 + return fmt.Errorf("unable to read file '%s': %v", fileNa, err)
64 + }
65 +
66 + go readMessage(ctx, cancel, con)
67 + go sendFile(ctx, cancel, con, fileNa, data, interv)
68 +
69 + <-ctx.Done()
70 + return context.Cause(ctx)
71 + }
72 +
73 + // SendFileByInterval repeatedly sends a given file in the websocket according
74 + // to an interval.
75 + func SendFileByInterval(con *websocket.Conn, fileNa string, interv time.Duration) error {
76 + switch {
77 + case con == nil:
78 + return fmt.Errorf("nil connection parameter")
79 + case len(fileNa) == 0:
80 + return fmt.Errorf("empty file parameter")
81 + case interv < 1:
82 + return fmt.Errorf("non positive interval parameter")
83 + }
84 + if err := checkFile(fileNa); err != nil {
85 + return err
86 + }
87 +
88 + return sendFileByInterval(con, fileNa, interv)
89 + }

+2/-14 M   ws/file_reply.go
index e76cc71..b5d985f
old size: 1K - new size: 1K
@@ -3,7 +3,6 @@ package ws
3 3 import (
4 4 "fmt"
5 5 "io"
6 - "io/fs"
7 6 "os"
8 7 "wssrv/log"
9 8
@@ -44,19 +43,8 @@ func SendFileReply(con *websocket.Conn, fileNa string) error {
44 43 case len(fileNa) == 0:
45 44 return fmt.Errorf("empty file parameter")
46 45 }
47 - var (
48 - err error
49 - stat fs.FileInfo
50 - )
51 -
52 - if stat, err = os.Stat(fileNa); err != nil {
53 - return fmt.Errorf("unable to check metadata for file '%s': %v", fileNa, err)
54 - }
55 - if !stat.Mode().IsRegular() {
56 - return fmt.Errorf("file '%s' is not regular")
57 - }
58 - if stat.Mode()&0444 == 0 {
59 - return fmt.Errorf("file '%s' is not readable")
46 + if err := checkFile(fileNa); err != nil {
47 + return err
60 48 }
61 49
62 50 return sendFileReply(con, fileNa)