slidge-whatsapp 0.3.7__cp312-cp312-manylinux_2_41_aarch64.whl → 0.3.8__cp312-cp312-manylinux_2_41_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. slidge_whatsapp/config.py +7 -2
  2. slidge_whatsapp/contact.py +3 -2
  3. slidge_whatsapp/event.go +14 -9
  4. slidge_whatsapp/gateway.go +7 -1
  5. slidge_whatsapp/generated/_whatsapp.cpython-312-aarch64-linux-gnu.h +182 -178
  6. slidge_whatsapp/generated/_whatsapp.cpython-312-aarch64-linux-gnu.so +0 -0
  7. slidge_whatsapp/generated/build.py +146 -142
  8. slidge_whatsapp/generated/whatsapp.c +1456 -1376
  9. slidge_whatsapp/generated/whatsapp.go +1069 -1045
  10. slidge_whatsapp/generated/whatsapp.py +1324 -1298
  11. slidge_whatsapp/generated/whatsapp_go.h +182 -178
  12. slidge_whatsapp/go.mod +6 -6
  13. slidge_whatsapp/go.sum +12 -12
  14. slidge_whatsapp/group.py +25 -0
  15. slidge_whatsapp/session.go +69 -67
  16. slidge_whatsapp/session.py +11 -1
  17. slidge_whatsapp/vendor/github.com/coder/websocket/LICENSE.txt +13 -0
  18. slidge_whatsapp/vendor/github.com/coder/websocket/Makefile +18 -0
  19. slidge_whatsapp/vendor/github.com/coder/websocket/README.md +162 -0
  20. slidge_whatsapp/vendor/github.com/coder/websocket/accept.go +378 -0
  21. slidge_whatsapp/vendor/github.com/coder/websocket/close.go +335 -0
  22. slidge_whatsapp/vendor/github.com/coder/websocket/compress.go +234 -0
  23. slidge_whatsapp/vendor/github.com/coder/websocket/conn.go +306 -0
  24. slidge_whatsapp/vendor/github.com/coder/websocket/dial.go +347 -0
  25. slidge_whatsapp/vendor/github.com/coder/websocket/doc.go +33 -0
  26. slidge_whatsapp/vendor/github.com/coder/websocket/errors.go +8 -0
  27. slidge_whatsapp/vendor/github.com/coder/websocket/frame.go +173 -0
  28. slidge_whatsapp/vendor/github.com/coder/websocket/hijack.go +33 -0
  29. slidge_whatsapp/vendor/github.com/coder/websocket/internal/bpool/bpool.go +25 -0
  30. slidge_whatsapp/vendor/github.com/coder/websocket/internal/errd/wrap.go +14 -0
  31. slidge_whatsapp/vendor/github.com/coder/websocket/internal/util/util.go +15 -0
  32. slidge_whatsapp/vendor/github.com/coder/websocket/internal/wsjs/wsjs_js.go +169 -0
  33. slidge_whatsapp/vendor/github.com/coder/websocket/mask.go +128 -0
  34. slidge_whatsapp/vendor/github.com/coder/websocket/mask_amd64.s +127 -0
  35. slidge_whatsapp/vendor/github.com/coder/websocket/mask_arm64.s +72 -0
  36. slidge_whatsapp/vendor/github.com/coder/websocket/mask_asm.go +26 -0
  37. slidge_whatsapp/vendor/github.com/coder/websocket/mask_go.go +7 -0
  38. slidge_whatsapp/vendor/github.com/coder/websocket/netconn.go +233 -0
  39. slidge_whatsapp/vendor/github.com/coder/websocket/netconn_js.go +11 -0
  40. slidge_whatsapp/vendor/github.com/coder/websocket/netconn_notjs.go +19 -0
  41. slidge_whatsapp/vendor/github.com/coder/websocket/read.go +540 -0
  42. slidge_whatsapp/vendor/github.com/coder/websocket/stringer.go +91 -0
  43. slidge_whatsapp/vendor/github.com/coder/websocket/write.go +384 -0
  44. slidge_whatsapp/vendor/github.com/coder/websocket/ws_js.go +598 -0
  45. slidge_whatsapp/vendor/github.com/ebitengine/purego/func.go +1 -1
  46. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_amd64.go +1 -1
  47. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_arm64.go +3 -1
  48. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_loong64.go +1 -1
  49. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/directive.go +3 -0
  50. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/selection.go +3 -0
  51. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/value.go +4 -3
  52. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/encode.go +3 -0
  53. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +18 -4
  54. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/broadcast.go +3 -3
  55. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +6 -4
  56. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/client.go +90 -80
  57. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/connectionevents.go +14 -11
  58. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download.go +4 -1
  59. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +47 -48
  60. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/handshake.go +3 -2
  61. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +79 -75
  62. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/keepalive.go +8 -6
  63. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/mediaconn.go +1 -2
  64. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/mediaretry.go +2 -2
  65. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +42 -40
  66. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/newsletter.go +35 -32
  67. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +2 -3
  68. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair-code.go +2 -4
  69. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair.go +19 -19
  70. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/prekeys.go +9 -8
  71. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/presence.go +9 -9
  72. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/privacysettings.go +4 -5
  73. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.pb.go +1 -1
  74. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.pb.go +1 -1
  75. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.pb.go +1 -1
  76. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.pb.go +1 -1
  77. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.pb.go +1 -1
  78. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.pb.go +1 -1
  79. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.pb.go +1 -1
  80. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.pb.go +1 -1
  81. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.pb.go +1 -1
  82. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.pb.go +1 -1
  83. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.pb.go +1 -1
  84. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAICommon/WAAICommon.pb.go +1145 -335
  85. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAICommon/WAAICommon.proto +78 -0
  86. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAdv/WAAdv.pb.go +1 -1
  87. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloApplication/WAArmadilloApplication.pb.go +1 -1
  88. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.pb.go +1 -1
  89. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCert/WACert.pb.go +1 -1
  90. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waChatLockSettings/WAProtobufsChatLockSettings.pb.go +1 -1
  91. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCommon/WACommon.pb.go +1 -1
  92. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.pb.go +22 -4
  93. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.proto +2 -0
  94. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waConsumerApplication/WAConsumerApplication.pb.go +1 -1
  95. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.pb.go +104 -30
  96. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.proto +7 -0
  97. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +1037 -963
  98. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +15 -8
  99. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.go +1 -1
  100. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.pb.go +1 -1
  101. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMediaTransport/WAMediaTransport.pb.go +1 -1
  102. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMmsRetry/WAMmsRetry.pb.go +1 -1
  103. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgApplication/WAMsgApplication.pb.go +1 -1
  104. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgTransport/WAMsgTransport.pb.go +1 -1
  105. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMultiDevice/WAMultiDevice.pb.go +1 -1
  106. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waServerSync/WAServerSync.pb.go +1 -1
  107. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +40 -35
  108. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +1 -0
  109. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +921 -653
  110. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +44 -15
  111. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waUserPassword/WAProtobufsUserPassword.pb.go +1 -1
  112. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waVnameCert/WAWebProtobufsVnameCert.pb.go +1 -1
  113. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.go +9 -5
  114. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.proto +1 -0
  115. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +193 -115
  116. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +9 -0
  117. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/push.go +2 -4
  118. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +12 -12
  119. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/request.go +25 -19
  120. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +2 -2
  121. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +43 -27
  122. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +4 -4
  123. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/constants.go +1 -1
  124. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/framesocket.go +43 -56
  125. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/noisehandshake.go +9 -3
  126. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/noisesocket.go +36 -22
  127. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +24 -4
  128. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +12 -0
  129. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/events/appstate.go +2 -1
  130. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/upload.go +1 -1
  131. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +79 -40
  132. slidge_whatsapp/vendor/golang.org/x/sys/unix/mkerrors.sh +2 -0
  133. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_linux.go +6 -0
  134. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux.go +359 -0
  135. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_linux.go +10 -0
  136. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux.go +31 -0
  137. slidge_whatsapp/vendor/golang.org/x/sys/windows/syscall_windows.go +15 -0
  138. slidge_whatsapp/vendor/golang.org/x/sys/windows/types_windows.go +76 -0
  139. slidge_whatsapp/vendor/golang.org/x/sys/windows/zsyscall_windows.go +37 -0
  140. slidge_whatsapp/vendor/modules.txt +12 -8
  141. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/METADATA +1 -1
  142. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/RECORD +145 -136
  143. slidge_whatsapp/vendor/github.com/gorilla/websocket/.gitignore +0 -25
  144. slidge_whatsapp/vendor/github.com/gorilla/websocket/AUTHORS +0 -9
  145. slidge_whatsapp/vendor/github.com/gorilla/websocket/LICENSE +0 -22
  146. slidge_whatsapp/vendor/github.com/gorilla/websocket/README.md +0 -33
  147. slidge_whatsapp/vendor/github.com/gorilla/websocket/client.go +0 -434
  148. slidge_whatsapp/vendor/github.com/gorilla/websocket/compression.go +0 -148
  149. slidge_whatsapp/vendor/github.com/gorilla/websocket/conn.go +0 -1238
  150. slidge_whatsapp/vendor/github.com/gorilla/websocket/doc.go +0 -227
  151. slidge_whatsapp/vendor/github.com/gorilla/websocket/join.go +0 -42
  152. slidge_whatsapp/vendor/github.com/gorilla/websocket/json.go +0 -60
  153. slidge_whatsapp/vendor/github.com/gorilla/websocket/mask.go +0 -55
  154. slidge_whatsapp/vendor/github.com/gorilla/websocket/mask_safe.go +0 -16
  155. slidge_whatsapp/vendor/github.com/gorilla/websocket/prepared.go +0 -102
  156. slidge_whatsapp/vendor/github.com/gorilla/websocket/proxy.go +0 -77
  157. slidge_whatsapp/vendor/github.com/gorilla/websocket/server.go +0 -365
  158. slidge_whatsapp/vendor/github.com/gorilla/websocket/tls_handshake.go +0 -21
  159. slidge_whatsapp/vendor/github.com/gorilla/websocket/tls_handshake_116.go +0 -21
  160. slidge_whatsapp/vendor/github.com/gorilla/websocket/util.go +0 -298
  161. slidge_whatsapp/vendor/github.com/gorilla/websocket/x_net_proxy.go +0 -473
  162. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/WHEEL +0 -0
  163. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/entry_points.txt +0 -0
  164. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,306 @@
1
+ //go:build !js
2
+
3
+ package websocket
4
+
5
+ import (
6
+ "bufio"
7
+ "context"
8
+ "fmt"
9
+ "io"
10
+ "net"
11
+ "runtime"
12
+ "strconv"
13
+ "sync"
14
+ "sync/atomic"
15
+ )
16
+
17
+ // MessageType represents the type of a WebSocket message.
18
+ // See https://tools.ietf.org/html/rfc6455#section-5.6
19
+ type MessageType int
20
+
21
+ // MessageType constants.
22
+ const (
23
+ // MessageText is for UTF-8 encoded text messages like JSON.
24
+ MessageText MessageType = iota + 1
25
+ // MessageBinary is for binary messages like protobufs.
26
+ MessageBinary
27
+ )
28
+
29
+ // Conn represents a WebSocket connection.
30
+ // All methods may be called concurrently except for Reader and Read.
31
+ //
32
+ // You must always read from the connection. Otherwise control
33
+ // frames will not be handled. See Reader and CloseRead.
34
+ //
35
+ // Be sure to call Close on the connection when you
36
+ // are finished with it to release associated resources.
37
+ //
38
+ // On any error from any method, the connection is closed
39
+ // with an appropriate reason.
40
+ //
41
+ // This applies to context expirations as well unfortunately.
42
+ // See https://github.com/nhooyr/websocket/issues/242#issuecomment-633182220
43
+ type Conn struct {
44
+ noCopy noCopy
45
+
46
+ subprotocol string
47
+ rwc io.ReadWriteCloser
48
+ client bool
49
+ copts *compressionOptions
50
+ flateThreshold int
51
+ br *bufio.Reader
52
+ bw *bufio.Writer
53
+
54
+ readTimeoutStop atomic.Pointer[func() bool]
55
+ writeTimeoutStop atomic.Pointer[func() bool]
56
+
57
+ // Read state.
58
+ readMu *mu
59
+ readHeaderBuf [8]byte
60
+ readControlBuf [maxControlPayload]byte
61
+ msgReader *msgReader
62
+
63
+ // Write state.
64
+ msgWriter *msgWriter
65
+ writeFrameMu *mu
66
+ writeBuf []byte
67
+ writeHeaderBuf [8]byte
68
+ writeHeader header
69
+
70
+ // Close handshake state.
71
+ closeStateMu sync.RWMutex
72
+ closeReceivedErr error
73
+ closeSentErr error
74
+
75
+ // CloseRead state.
76
+ closeReadMu sync.Mutex
77
+ closeReadCtx context.Context
78
+ closeReadDone chan struct{}
79
+
80
+ closing atomic.Bool
81
+ closeMu sync.Mutex // Protects following.
82
+ closed chan struct{}
83
+
84
+ pingCounter atomic.Int64
85
+ activePingsMu sync.Mutex
86
+ activePings map[string]chan<- struct{}
87
+ onPingReceived func(context.Context, []byte) bool
88
+ onPongReceived func(context.Context, []byte)
89
+ }
90
+
91
+ type connConfig struct {
92
+ subprotocol string
93
+ rwc io.ReadWriteCloser
94
+ client bool
95
+ copts *compressionOptions
96
+ flateThreshold int
97
+ onPingReceived func(context.Context, []byte) bool
98
+ onPongReceived func(context.Context, []byte)
99
+
100
+ br *bufio.Reader
101
+ bw *bufio.Writer
102
+ }
103
+
104
+ func newConn(cfg connConfig) *Conn {
105
+ c := &Conn{
106
+ subprotocol: cfg.subprotocol,
107
+ rwc: cfg.rwc,
108
+ client: cfg.client,
109
+ copts: cfg.copts,
110
+ flateThreshold: cfg.flateThreshold,
111
+
112
+ br: cfg.br,
113
+ bw: cfg.bw,
114
+
115
+ closed: make(chan struct{}),
116
+ activePings: make(map[string]chan<- struct{}),
117
+ onPingReceived: cfg.onPingReceived,
118
+ onPongReceived: cfg.onPongReceived,
119
+ }
120
+
121
+ c.readMu = newMu(c)
122
+ c.writeFrameMu = newMu(c)
123
+
124
+ c.msgReader = newMsgReader(c)
125
+
126
+ c.msgWriter = newMsgWriter(c)
127
+ if c.client {
128
+ c.writeBuf = extractBufioWriterBuf(c.bw, c.rwc)
129
+ }
130
+
131
+ if c.flate() && c.flateThreshold == 0 {
132
+ c.flateThreshold = 128
133
+ if !c.msgWriter.flateContextTakeover() {
134
+ c.flateThreshold = 512
135
+ }
136
+ }
137
+
138
+ runtime.SetFinalizer(c, func(c *Conn) {
139
+ c.close()
140
+ })
141
+
142
+ return c
143
+ }
144
+
145
+ // Subprotocol returns the negotiated subprotocol.
146
+ // An empty string means the default protocol.
147
+ func (c *Conn) Subprotocol() string {
148
+ return c.subprotocol
149
+ }
150
+
151
+ func (c *Conn) close() error {
152
+ c.closeMu.Lock()
153
+ defer c.closeMu.Unlock()
154
+
155
+ if c.isClosed() {
156
+ return net.ErrClosed
157
+ }
158
+ runtime.SetFinalizer(c, nil)
159
+ close(c.closed)
160
+
161
+ // Have to close after c.closed is closed to ensure any goroutine that wakes up
162
+ // from the connection being closed also sees that c.closed is closed and returns
163
+ // closeErr.
164
+ err := c.rwc.Close()
165
+ // With the close of rwc, these become safe to close.
166
+ c.msgWriter.close()
167
+ c.msgReader.close()
168
+ return err
169
+ }
170
+
171
+ func (c *Conn) setupWriteTimeout(ctx context.Context) {
172
+ stop := context.AfterFunc(ctx, func() {
173
+ c.clearWriteTimeout()
174
+ c.close()
175
+ })
176
+ swapTimeoutStop(&c.writeTimeoutStop, &stop)
177
+ }
178
+
179
+ func (c *Conn) clearWriteTimeout() {
180
+ swapTimeoutStop(&c.writeTimeoutStop, nil)
181
+ }
182
+
183
+ func (c *Conn) setupReadTimeout(ctx context.Context) {
184
+ stop := context.AfterFunc(ctx, func() {
185
+ c.clearReadTimeout()
186
+ c.close()
187
+ })
188
+ swapTimeoutStop(&c.readTimeoutStop, &stop)
189
+ }
190
+
191
+ func (c *Conn) clearReadTimeout() {
192
+ swapTimeoutStop(&c.readTimeoutStop, nil)
193
+ }
194
+
195
+ func swapTimeoutStop(p *atomic.Pointer[func() bool], newStop *func() bool) {
196
+ oldStop := p.Swap(newStop)
197
+ if oldStop != nil {
198
+ (*oldStop)()
199
+ }
200
+ }
201
+
202
+ func (c *Conn) flate() bool {
203
+ return c.copts != nil
204
+ }
205
+
206
+ // Ping sends a ping to the peer and waits for a pong.
207
+ // Use this to measure latency or ensure the peer is responsive.
208
+ // Ping must be called concurrently with Reader as it does
209
+ // not read from the connection but instead waits for a Reader call
210
+ // to read the pong.
211
+ //
212
+ // TCP Keepalives should suffice for most use cases.
213
+ func (c *Conn) Ping(ctx context.Context) error {
214
+ p := c.pingCounter.Add(1)
215
+
216
+ err := c.ping(ctx, strconv.FormatInt(p, 10))
217
+ if err != nil {
218
+ return fmt.Errorf("failed to ping: %w", err)
219
+ }
220
+ return nil
221
+ }
222
+
223
+ func (c *Conn) ping(ctx context.Context, p string) error {
224
+ pong := make(chan struct{}, 1)
225
+
226
+ c.activePingsMu.Lock()
227
+ c.activePings[p] = pong
228
+ c.activePingsMu.Unlock()
229
+
230
+ defer func() {
231
+ c.activePingsMu.Lock()
232
+ delete(c.activePings, p)
233
+ c.activePingsMu.Unlock()
234
+ }()
235
+
236
+ err := c.writeControl(ctx, opPing, []byte(p))
237
+ if err != nil {
238
+ return err
239
+ }
240
+
241
+ select {
242
+ case <-c.closed:
243
+ return net.ErrClosed
244
+ case <-ctx.Done():
245
+ return fmt.Errorf("failed to wait for pong: %w", ctx.Err())
246
+ case <-pong:
247
+ return nil
248
+ }
249
+ }
250
+
251
+ type mu struct {
252
+ c *Conn
253
+ ch chan struct{}
254
+ }
255
+
256
+ func newMu(c *Conn) *mu {
257
+ return &mu{
258
+ c: c,
259
+ ch: make(chan struct{}, 1),
260
+ }
261
+ }
262
+
263
+ func (m *mu) forceLock() {
264
+ m.ch <- struct{}{}
265
+ }
266
+
267
+ func (m *mu) tryLock() bool {
268
+ select {
269
+ case m.ch <- struct{}{}:
270
+ return true
271
+ default:
272
+ return false
273
+ }
274
+ }
275
+
276
+ func (m *mu) lock(ctx context.Context) error {
277
+ select {
278
+ case <-m.c.closed:
279
+ return net.ErrClosed
280
+ case <-ctx.Done():
281
+ return fmt.Errorf("failed to acquire lock: %w", ctx.Err())
282
+ case m.ch <- struct{}{}:
283
+ // To make sure the connection is certainly alive.
284
+ // As it's possible the send on m.ch was selected
285
+ // over the receive on closed.
286
+ select {
287
+ case <-m.c.closed:
288
+ // Make sure to release.
289
+ m.unlock()
290
+ return net.ErrClosed
291
+ default:
292
+ }
293
+ return nil
294
+ }
295
+ }
296
+
297
+ func (m *mu) unlock() {
298
+ select {
299
+ case <-m.ch:
300
+ default:
301
+ }
302
+ }
303
+
304
+ type noCopy struct{}
305
+
306
+ func (*noCopy) Lock() {}
@@ -0,0 +1,347 @@
1
+ //go:build !js
2
+
3
+ package websocket
4
+
5
+ import (
6
+ "bufio"
7
+ "bytes"
8
+ "context"
9
+ "crypto/rand"
10
+ "encoding/base64"
11
+ "fmt"
12
+ "io"
13
+ "net/http"
14
+ "net/url"
15
+ "strings"
16
+ "sync"
17
+ "time"
18
+
19
+ "github.com/coder/websocket/internal/errd"
20
+ )
21
+
22
+ // DialOptions represents Dial's options.
23
+ type DialOptions struct {
24
+ // HTTPClient is used for the connection.
25
+ // Its Transport must return writable bodies for WebSocket handshakes.
26
+ // http.Transport does beginning with Go 1.12.
27
+ HTTPClient *http.Client
28
+
29
+ // HTTPHeader specifies the HTTP headers included in the handshake request.
30
+ HTTPHeader http.Header
31
+
32
+ // Host optionally overrides the Host HTTP header to send. If empty, the value
33
+ // of URL.Host will be used.
34
+ Host string
35
+
36
+ // Subprotocols lists the WebSocket subprotocols to negotiate with the server.
37
+ Subprotocols []string
38
+
39
+ // CompressionMode controls the compression mode.
40
+ // Defaults to CompressionDisabled.
41
+ //
42
+ // See docs on CompressionMode for details.
43
+ CompressionMode CompressionMode
44
+
45
+ // CompressionThreshold controls the minimum size of a message before compression is applied.
46
+ //
47
+ // Defaults to 512 bytes for CompressionNoContextTakeover and 128 bytes
48
+ // for CompressionContextTakeover.
49
+ CompressionThreshold int
50
+
51
+ // OnPingReceived is an optional callback invoked synchronously when a ping frame is received.
52
+ //
53
+ // The payload contains the application data of the ping frame.
54
+ // If the callback returns false, the subsequent pong frame will not be sent.
55
+ // To avoid blocking, any expensive processing should be performed asynchronously using a goroutine.
56
+ OnPingReceived func(ctx context.Context, payload []byte) bool
57
+
58
+ // OnPongReceived is an optional callback invoked synchronously when a pong frame is received.
59
+ //
60
+ // The payload contains the application data of the pong frame.
61
+ // To avoid blocking, any expensive processing should be performed asynchronously using a goroutine.
62
+ //
63
+ // Unlike OnPingReceived, this callback does not return a value because a pong frame
64
+ // is a response to a ping and does not trigger any further frame transmission.
65
+ OnPongReceived func(ctx context.Context, payload []byte)
66
+ }
67
+
68
+ func (opts *DialOptions) cloneWithDefaults(ctx context.Context) (context.Context, context.CancelFunc, *DialOptions) {
69
+ var cancel context.CancelFunc
70
+
71
+ var o DialOptions
72
+ if opts != nil {
73
+ o = *opts
74
+ }
75
+ if o.HTTPClient == nil {
76
+ o.HTTPClient = http.DefaultClient
77
+ }
78
+ if o.HTTPClient.Timeout > 0 {
79
+ ctx, cancel = context.WithTimeout(ctx, o.HTTPClient.Timeout)
80
+
81
+ newClient := *o.HTTPClient
82
+ newClient.Timeout = 0
83
+ o.HTTPClient = &newClient
84
+ }
85
+ if o.HTTPHeader == nil {
86
+ o.HTTPHeader = http.Header{}
87
+ }
88
+ newClient := *o.HTTPClient
89
+ oldCheckRedirect := o.HTTPClient.CheckRedirect
90
+ newClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
91
+ switch req.URL.Scheme {
92
+ case "ws":
93
+ req.URL.Scheme = "http"
94
+ case "wss":
95
+ req.URL.Scheme = "https"
96
+ }
97
+ if oldCheckRedirect != nil {
98
+ return oldCheckRedirect(req, via)
99
+ }
100
+ return nil
101
+ }
102
+ o.HTTPClient = &newClient
103
+
104
+ return ctx, cancel, &o
105
+ }
106
+
107
+ // Dial performs a WebSocket handshake on url.
108
+ //
109
+ // The response is the WebSocket handshake response from the server.
110
+ // You never need to close resp.Body yourself.
111
+ //
112
+ // If an error occurs, the returned response may be non nil.
113
+ // However, you can only read the first 1024 bytes of the body.
114
+ //
115
+ // This function requires at least Go 1.12 as it uses a new feature
116
+ // in net/http to perform WebSocket handshakes.
117
+ // See docs on the HTTPClient option and https://github.com/golang/go/issues/26937#issuecomment-415855861
118
+ //
119
+ // URLs with http/https schemes will work and are interpreted as ws/wss.
120
+ func Dial(ctx context.Context, u string, opts *DialOptions) (*Conn, *http.Response, error) {
121
+ return dial(ctx, u, opts, nil)
122
+ }
123
+
124
+ func dial(ctx context.Context, urls string, opts *DialOptions, rand io.Reader) (_ *Conn, _ *http.Response, err error) {
125
+ defer errd.Wrap(&err, "failed to WebSocket dial")
126
+
127
+ var cancel context.CancelFunc
128
+ ctx, cancel, opts = opts.cloneWithDefaults(ctx)
129
+ if cancel != nil {
130
+ defer cancel()
131
+ }
132
+
133
+ secWebSocketKey, err := secWebSocketKey(rand)
134
+ if err != nil {
135
+ return nil, nil, fmt.Errorf("failed to generate Sec-WebSocket-Key: %w", err)
136
+ }
137
+
138
+ var copts *compressionOptions
139
+ if opts.CompressionMode != CompressionDisabled {
140
+ copts = opts.CompressionMode.opts()
141
+ }
142
+
143
+ resp, err := handshakeRequest(ctx, urls, opts, copts, secWebSocketKey)
144
+ if err != nil {
145
+ return nil, resp, err
146
+ }
147
+ respBody := resp.Body
148
+ resp.Body = nil
149
+ defer func() {
150
+ if err != nil {
151
+ // We read a bit of the body for easier debugging.
152
+ r := io.LimitReader(respBody, 1024)
153
+
154
+ timer := time.AfterFunc(time.Second*3, func() {
155
+ respBody.Close()
156
+ })
157
+ defer timer.Stop()
158
+
159
+ b, _ := io.ReadAll(r)
160
+ respBody.Close()
161
+ resp.Body = io.NopCloser(bytes.NewReader(b))
162
+ }
163
+ }()
164
+
165
+ copts, err = verifyServerResponse(opts, copts, secWebSocketKey, resp)
166
+ if err != nil {
167
+ return nil, resp, err
168
+ }
169
+
170
+ rwc, ok := respBody.(io.ReadWriteCloser)
171
+ if !ok {
172
+ return nil, resp, fmt.Errorf("response body is not a io.ReadWriteCloser: %T", respBody)
173
+ }
174
+
175
+ return newConn(connConfig{
176
+ subprotocol: resp.Header.Get("Sec-WebSocket-Protocol"),
177
+ rwc: rwc,
178
+ client: true,
179
+ copts: copts,
180
+ flateThreshold: opts.CompressionThreshold,
181
+ onPingReceived: opts.OnPingReceived,
182
+ onPongReceived: opts.OnPongReceived,
183
+ br: getBufioReader(rwc),
184
+ bw: getBufioWriter(rwc),
185
+ }), resp, nil
186
+ }
187
+
188
+ func handshakeRequest(ctx context.Context, urls string, opts *DialOptions, copts *compressionOptions, secWebSocketKey string) (*http.Response, error) {
189
+ u, err := url.Parse(urls)
190
+ if err != nil {
191
+ return nil, fmt.Errorf("failed to parse url: %w", err)
192
+ }
193
+
194
+ switch u.Scheme {
195
+ case "ws":
196
+ u.Scheme = "http"
197
+ case "wss":
198
+ u.Scheme = "https"
199
+ case "http", "https":
200
+ default:
201
+ return nil, fmt.Errorf("unexpected url scheme: %q", u.Scheme)
202
+ }
203
+
204
+ req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
205
+ if err != nil {
206
+ return nil, fmt.Errorf("failed to create new http request: %w", err)
207
+ }
208
+ if len(opts.Host) > 0 {
209
+ req.Host = opts.Host
210
+ }
211
+ req.Header = opts.HTTPHeader.Clone()
212
+ req.Header.Set("Connection", "Upgrade")
213
+ req.Header.Set("Upgrade", "websocket")
214
+ req.Header.Set("Sec-WebSocket-Version", "13")
215
+ req.Header.Set("Sec-WebSocket-Key", secWebSocketKey)
216
+ if len(opts.Subprotocols) > 0 {
217
+ req.Header.Set("Sec-WebSocket-Protocol", strings.Join(opts.Subprotocols, ","))
218
+ }
219
+ if copts != nil {
220
+ req.Header.Set("Sec-WebSocket-Extensions", copts.String())
221
+ }
222
+
223
+ resp, err := opts.HTTPClient.Do(req)
224
+ if err != nil {
225
+ return nil, fmt.Errorf("failed to send handshake request: %w", err)
226
+ }
227
+ return resp, nil
228
+ }
229
+
230
+ func secWebSocketKey(rr io.Reader) (string, error) {
231
+ if rr == nil {
232
+ rr = rand.Reader
233
+ }
234
+ b := make([]byte, 16)
235
+ _, err := io.ReadFull(rr, b)
236
+ if err != nil {
237
+ return "", fmt.Errorf("failed to read random data from rand.Reader: %w", err)
238
+ }
239
+ return base64.StdEncoding.EncodeToString(b), nil
240
+ }
241
+
242
+ func verifyServerResponse(opts *DialOptions, copts *compressionOptions, secWebSocketKey string, resp *http.Response) (*compressionOptions, error) {
243
+ if resp.StatusCode != http.StatusSwitchingProtocols {
244
+ return nil, fmt.Errorf("expected handshake response status code %v but got %v", http.StatusSwitchingProtocols, resp.StatusCode)
245
+ }
246
+
247
+ if !headerContainsTokenIgnoreCase(resp.Header, "Connection", "Upgrade") {
248
+ return nil, fmt.Errorf("WebSocket protocol violation: Connection header %q does not contain Upgrade", resp.Header.Get("Connection"))
249
+ }
250
+
251
+ if !headerContainsTokenIgnoreCase(resp.Header, "Upgrade", "WebSocket") {
252
+ return nil, fmt.Errorf("WebSocket protocol violation: Upgrade header %q does not contain websocket", resp.Header.Get("Upgrade"))
253
+ }
254
+
255
+ if resp.Header.Get("Sec-WebSocket-Accept") != secWebSocketAccept(secWebSocketKey) {
256
+ return nil, fmt.Errorf("WebSocket protocol violation: invalid Sec-WebSocket-Accept %q, key %q",
257
+ resp.Header.Get("Sec-WebSocket-Accept"),
258
+ secWebSocketKey,
259
+ )
260
+ }
261
+
262
+ err := verifySubprotocol(opts.Subprotocols, resp)
263
+ if err != nil {
264
+ return nil, err
265
+ }
266
+
267
+ return verifyServerExtensions(copts, resp.Header)
268
+ }
269
+
270
+ func verifySubprotocol(subprotos []string, resp *http.Response) error {
271
+ proto := resp.Header.Get("Sec-WebSocket-Protocol")
272
+ if proto == "" {
273
+ return nil
274
+ }
275
+
276
+ for _, sp2 := range subprotos {
277
+ if strings.EqualFold(sp2, proto) {
278
+ return nil
279
+ }
280
+ }
281
+
282
+ return fmt.Errorf("WebSocket protocol violation: unexpected Sec-WebSocket-Protocol from server: %q", proto)
283
+ }
284
+
285
+ func verifyServerExtensions(copts *compressionOptions, h http.Header) (*compressionOptions, error) {
286
+ exts := websocketExtensions(h)
287
+ if len(exts) == 0 {
288
+ return nil, nil
289
+ }
290
+
291
+ ext := exts[0]
292
+ if ext.name != "permessage-deflate" || len(exts) > 1 || copts == nil {
293
+ return nil, fmt.Errorf("WebSocket protcol violation: unsupported extensions from server: %+v", exts[1:])
294
+ }
295
+
296
+ _copts := *copts
297
+ copts = &_copts
298
+
299
+ for _, p := range ext.params {
300
+ switch p {
301
+ case "client_no_context_takeover":
302
+ copts.clientNoContextTakeover = true
303
+ continue
304
+ case "server_no_context_takeover":
305
+ copts.serverNoContextTakeover = true
306
+ continue
307
+ }
308
+ if strings.HasPrefix(p, "server_max_window_bits=") {
309
+ // We can't adjust the deflate window, but decoding with a larger window is acceptable.
310
+ continue
311
+ }
312
+
313
+ return nil, fmt.Errorf("unsupported permessage-deflate parameter: %q", p)
314
+ }
315
+
316
+ return copts, nil
317
+ }
318
+
319
+ var bufioReaderPool sync.Pool
320
+
321
+ func getBufioReader(r io.Reader) *bufio.Reader {
322
+ br, ok := bufioReaderPool.Get().(*bufio.Reader)
323
+ if !ok {
324
+ return bufio.NewReader(r)
325
+ }
326
+ br.Reset(r)
327
+ return br
328
+ }
329
+
330
+ func putBufioReader(br *bufio.Reader) {
331
+ bufioReaderPool.Put(br)
332
+ }
333
+
334
+ var bufioWriterPool sync.Pool
335
+
336
+ func getBufioWriter(w io.Writer) *bufio.Writer {
337
+ bw, ok := bufioWriterPool.Get().(*bufio.Writer)
338
+ if !ok {
339
+ return bufio.NewWriter(w)
340
+ }
341
+ bw.Reset(w)
342
+ return bw
343
+ }
344
+
345
+ func putBufioWriter(bw *bufio.Writer) {
346
+ bufioWriterPool.Put(bw)
347
+ }
@@ -0,0 +1,33 @@
1
+ //go:build !js
2
+
3
+ // Package websocket implements the RFC 6455 WebSocket protocol.
4
+ //
5
+ // https://tools.ietf.org/html/rfc6455
6
+ //
7
+ // Use Dial to dial a WebSocket server.
8
+ //
9
+ // Use Accept to accept a WebSocket client.
10
+ //
11
+ // Conn represents the resulting WebSocket connection.
12
+ //
13
+ // The examples are the best way to understand how to correctly use the library.
14
+ //
15
+ // The wsjson subpackage contain helpers for JSON and protobuf messages.
16
+ //
17
+ // More documentation at https://github.com/coder/websocket.
18
+ //
19
+ // # Wasm
20
+ //
21
+ // The client side supports compiling to Wasm.
22
+ // It wraps the WebSocket browser API.
23
+ //
24
+ // See https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
25
+ //
26
+ // Some important caveats to be aware of:
27
+ //
28
+ // - Accept always errors out
29
+ // - Conn.Ping is no-op
30
+ // - Conn.CloseNow is Close(StatusGoingAway, "")
31
+ // - HTTPClient, HTTPHeader and CompressionMode in DialOptions are no-op
32
+ // - *http.Response from Dial is &http.Response{} with a 101 status code on success
33
+ package websocket // import "github.com/coder/websocket"
@@ -0,0 +1,8 @@
1
+ package websocket
2
+
3
+ import (
4
+ "errors"
5
+ )
6
+
7
+ // ErrMessageTooBig is returned when a message exceeds the read limit.
8
+ var ErrMessageTooBig = errors.New("websocket: message too big")