File: main.go

package info (click to toggle)
golang-github-centrifugal-centrifuge 0.15.0%2Bgit20210306.f435ba2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,612 kB
  • sloc: javascript: 102; makefile: 2
file content (110 lines) | stat: -rw-r--r-- 2,837 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	_ "net/http/pprof"

	"github.com/centrifugal/centrifuge"
)

func handleLog(e centrifuge.LogEntry) {
	log.Printf("%s: %v", e.Message, e.Fields)
}

func waitExitSignal(n *centrifuge.Node) {
	sigCh := make(chan os.Signal, 1)
	done := make(chan bool, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		<-sigCh
		_ = n.Shutdown(context.Background())
		done <- true
	}()
	<-done
}

func main() {
	cfg := centrifuge.DefaultConfig

	cfg.LogLevel = centrifuge.LogLevelInfo
	cfg.LogHandler = handleLog

	// Better to keep default in production. Here we just speeding up things a bit.
	cfg.ClientExpiredCloseDelay = 5 * time.Second

	node, _ := centrifuge.New(cfg)

	broker, _ := centrifuge.NewMemoryBroker(node, centrifuge.MemoryBrokerConfig{
		HistoryMetaTTL: 120 * time.Second,
	})
	node.SetBroker(broker)

	node.OnConnecting(func(ctx context.Context, e centrifuge.ConnectEvent) (centrifuge.ConnectReply, error) {
		// We need to apply token parsing logic here and return connection credentials.
		if !strings.HasPrefix(e.Token, "I am ") {
			return centrifuge.ConnectReply{}, centrifuge.DisconnectInvalidToken
		}
		userID := strings.TrimPrefix(e.Token, "I am ")
		credentials := &centrifuge.Credentials{
			UserID:   userID,
			ExpireAt: time.Now().Unix() + 5, // Expire in 5 seconds.
		}

		return centrifuge.ConnectReply{
			ClientSideRefresh: true, // This is required to use client-side refresh.
			Credentials:       credentials,
		}, nil
	})

	node.OnConnect(func(client *centrifuge.Client) {
		log.Printf("user %s connected", client.UserID())

		client.OnRefresh(func(e centrifuge.RefreshEvent, cb centrifuge.RefreshCallback) {
			log.Printf("user %s sent refresh command with token: %s", client.UserID(), e.Token)
			if !strings.HasPrefix(e.Token, "I am ") {
				cb(centrifuge.RefreshReply{}, centrifuge.DisconnectInvalidToken)
				return
			}
			userID := strings.TrimPrefix(e.Token, "I am ")
			if userID != client.UserID() {
				cb(centrifuge.RefreshReply{}, centrifuge.DisconnectInvalidToken)
				return
			}
			cb(centrifuge.RefreshReply{
				ExpireAt: time.Now().Unix() + 5,
			}, nil)
		})

		client.OnDisconnect(func(e centrifuge.DisconnectEvent) {
			log.Printf("user %s disconnected, disconnect: %s", client.UserID(), e.Disconnect)
		})
	})

	if err := node.Run(); err != nil {
		log.Fatal(err)
	}

	websocketHandler := centrifuge.NewWebsocketHandler(node, centrifuge.WebsocketConfig{
		ReadBufferSize:     1024,
		UseWriteBufferPool: true,
	})
	http.Handle("/connection/websocket", websocketHandler)
	http.Handle("/", http.FileServer(http.Dir("./")))

	go func() {
		if err := http.ListenAndServe(":8000", nil); err != nil {
			log.Fatal(err)
		}
	}()

	waitExitSignal(node)
	log.Println("bye!")
}