File: disconnect.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 (157 lines) | stat: -rw-r--r-- 4,985 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package centrifuge

import (
	"encoding/json"
	"fmt"
	"strings"
	"sync"
)

// Disconnect allows to configure how client will be disconnected from server.
// The important note that Disconnect serialized to JSON must be less than 127 bytes
// due to WebSocket protocol limitations (because at moment we send Disconnect inside
// reason field of WebSocket close handshake).
// Note that due to performance reasons we cache Disconnect text representation
// for Close Frame on first send to client so changing field values inside existing
// Disconnect instance won't be reflected in WebSocket/Sockjs Close frames.
type Disconnect struct {
	// Code is disconnect code.
	Code uint32 `json:"code,omitempty"`
	// Reason is a short description of disconnect.
	Reason string `json:"reason"`
	// Reconnect gives client an advice to reconnect after disconnect or not.
	Reconnect bool `json:"reconnect"`

	closeTextOnce   sync.Once
	cachedCloseText string
}

var _ error = (*Disconnect)(nil)

// String representation.
func (d *Disconnect) String() string {
	return fmt.Sprintf("code: %d, reason: %s, reconnect: %t", d.Code, d.Reason, d.Reconnect)
}

// Error representation.
func (d *Disconnect) Error() string {
	return fmt.Sprintf("disconnected: code: %d, reason: %s, reconnect: %t", d.Code, d.Reason, d.Reconnect)
}

// CloseText allows to build disconnect advice sent inside Close frame.
// At moment we don't encode Code here to not duplicate information
// since it is sent separately as Code of WebSocket/SockJS Close Frame.
func (d *Disconnect) CloseText() string {
	d.closeTextOnce.Do(func() {
		buf := strings.Builder{}
		buf.WriteString(`{"reason":`)
		reason, _ := json.Marshal(d.Reason)
		buf.Write(reason)
		buf.WriteString(`,"reconnect":`)
		if d.Reconnect {
			buf.WriteString("true")
		} else {
			buf.WriteString("false")
		}
		buf.WriteString(`}`)
		d.cachedCloseText = buf.String()
	})
	return d.cachedCloseText
}

// Some predefined disconnect structures used by library internally. Though
// it's always possible to create Disconnect with any field values on the fly.
// Library users supposed to use codes in range 4000-4999 for custom disconnects.
var (
	// DisconnectNormal is clean disconnect when client cleanly closed connection.
	DisconnectNormal = &Disconnect{
		Code:      3000,
		Reason:    "normal",
		Reconnect: true,
	}
	// DisconnectShutdown sent when node is going to shut down.
	DisconnectShutdown = &Disconnect{
		Code:      3001,
		Reason:    "shutdown",
		Reconnect: true,
	}
	// DisconnectInvalidToken sent when client came with invalid token.
	DisconnectInvalidToken = &Disconnect{
		Code:      3002,
		Reason:    "invalid token",
		Reconnect: false,
	}
	// DisconnectBadRequest sent when client uses malformed protocol
	// frames or wrong order of commands.
	DisconnectBadRequest = &Disconnect{
		Code:      3003,
		Reason:    "bad request",
		Reconnect: false,
	}
	// DisconnectServerError sent when internal error occurred on server.
	DisconnectServerError = &Disconnect{
		Code:      3004,
		Reason:    "internal server error",
		Reconnect: true,
	}
	// DisconnectExpired sent when client connection expired.
	DisconnectExpired = &Disconnect{
		Code:      3005,
		Reason:    "expired",
		Reconnect: true,
	}
	// DisconnectSubExpired sent when client subscription expired.
	DisconnectSubExpired = &Disconnect{
		Code:      3006,
		Reason:    "subscription expired",
		Reconnect: true,
	}
	// DisconnectStale sent to close connection that did not become
	// authenticated in configured interval after dialing.
	DisconnectStale = &Disconnect{
		Code:      3007,
		Reason:    "stale",
		Reconnect: false,
	}
	// DisconnectSlow sent when client can't read messages fast enough.
	DisconnectSlow = &Disconnect{
		Code:      3008,
		Reason:    "slow",
		Reconnect: true,
	}
	// DisconnectWriteError sent when an error occurred while writing to
	// client connection.
	DisconnectWriteError = &Disconnect{
		Code:      3009,
		Reason:    "write error",
		Reconnect: true,
	}
	// DisconnectInsufficientState sent when server detects wrong client
	// position in channel Publication stream. Disconnect allows client
	// to restore missed publications on reconnect.
	DisconnectInsufficientState = &Disconnect{
		Code:      3010,
		Reason:    "insufficient state",
		Reconnect: true,
	}
	// DisconnectForceReconnect sent when server disconnects connection.
	DisconnectForceReconnect = &Disconnect{
		Code:      3011,
		Reason:    "force reconnect",
		Reconnect: true,
	}
	// DisconnectForceNoReconnect sent when server disconnects connection
	// and asks it to not reconnect again.
	DisconnectForceNoReconnect = &Disconnect{
		Code:      3012,
		Reason:    "force disconnect",
		Reconnect: false,
	}
	// DisconnectConnectionLimit can be sent when client connection exceeds a
	// configured connection limit (per user ID or due to other rule).
	DisconnectConnectionLimit = &Disconnect{
		Code:      3013,
		Reason:    "connection limit",
		Reconnect: false,
	}
)