@@ -2,19 +2,19 @@ package gateway
22
33import (
44 "bytes"
5- "compress/zlib"
65 "context"
76 "errors"
87 "fmt"
98 "io"
109 "log/slog"
1110 "math/rand/v2"
1211 "net"
12+ "net/url"
13+ "strconv"
1314 "sync"
1415 "syscall"
1516 "time"
1617
17- "github.com/disgoorg/json/v2"
1818 "github.com/gorilla/websocket"
1919
2020 "github.com/disgoorg/disgo/discord"
@@ -171,7 +171,7 @@ type gatewayImpl struct {
171171 closeHandlerFunc CloseHandlerFunc
172172 token string
173173
174- conn * websocket. Conn
174+ conn transport
175175 connMu sync.Mutex
176176 heartbeatCancel context.CancelFunc
177177 status Status
@@ -211,7 +211,7 @@ func (g *gatewayImpl) Open(ctx context.Context) error {
211211}
212212
213213func (g * gatewayImpl ) open (ctx context.Context ) error {
214- g .config .Logger .DebugContext (ctx , "opening gateway connection" )
214+ g .config .Logger .DebugContext (ctx , "opening gateway connection" , slog . String ( "compression" , g . config . Compression . String ()) )
215215
216216 g .connMu .Lock ()
217217 if g .conn != nil {
@@ -235,7 +235,17 @@ func (g *gatewayImpl) open(ctx context.Context) error {
235235 if g .config .ResumeURL != nil && g .config .EnableResumeURL {
236236 wsURL = * g .config .ResumeURL
237237 }
238- gatewayURL := fmt .Sprintf ("%s?v=%d&encoding=json" , wsURL , Version )
238+
239+ values := url.Values {}
240+ values .Set ("v" , strconv .Itoa (Version ))
241+ values .Set ("encoding" , "json" )
242+
243+ if g .config .Compression .IsStreamCompression () {
244+ values .Set ("compress" , string (g .config .Compression ))
245+ }
246+
247+ gatewayURL := wsURL + "?" + values .Encode ()
248+
239249 g .lastHeartbeatSent = time .Now ().UTC ()
240250 conn , rs , err := g .config .Dialer .DialContext (ctx , gatewayURL , nil )
241251 if err != nil {
@@ -263,7 +273,8 @@ func (g *gatewayImpl) open(ctx context.Context) error {
263273 return nil
264274 })
265275
266- g .conn = conn
276+ t := newTransport (g .config .Compression , conn , g .config .Logger )
277+ g .conn = t
267278 g .connMu .Unlock ()
268279
269280 // reset rate limiter when connecting
@@ -275,7 +286,7 @@ func (g *gatewayImpl) open(ctx context.Context) error {
275286
276287 var readyOnce sync.Once
277288 readyChan := make (chan error )
278- go g .listen (conn , func (err error ) {
289+ go g .listen (t , func (err error ) {
279290 readyOnce .Do (func () {
280291 readyChan <- err
281292 close (readyChan )
@@ -315,7 +326,7 @@ func (g *gatewayImpl) CloseWithCode(ctx context.Context, code int, message strin
315326 if g .conn != nil {
316327 g .config .RateLimiter .Close (ctx )
317328 g .config .Logger .DebugContext (ctx , "closing gateway connection" , slog .Int ("code" , code ), slog .String ("message" , message ))
318- if err := g .conn .WriteMessage ( websocket . CloseMessage , websocket . FormatCloseMessage ( code , message ) ); err != nil && ! errors .Is (err , websocket .ErrCloseSent ) {
329+ if err := g .conn .WriteClose ( code , message ); err != nil && ! errors .Is (err , websocket .ErrCloseSent ) {
319330 g .config .Logger .DebugContext (ctx , "error writing close code" , slog .Any ("err" , err ))
320331 }
321332 _ = g .conn .Close ()
@@ -350,17 +361,11 @@ func (g *gatewayImpl) Send(ctx context.Context, op Opcode, d MessageData) error
350361}
351362
352363func (g * gatewayImpl ) sendInternal (ctx context.Context , op Opcode , d MessageData ) error {
353- data , err := json . Marshal ( Message {
364+ data := Message {
354365 Op : op ,
355366 D : d ,
356- })
357- if err != nil {
358- return err
359367 }
360- return g .send (ctx , websocket .TextMessage , data )
361- }
362368
363- func (g * gatewayImpl ) send (ctx context.Context , messageType int , data []byte ) error {
364369 g .connMu .Lock ()
365370 defer g .connMu .Unlock ()
366371 if g .conn == nil {
@@ -372,8 +377,7 @@ func (g *gatewayImpl) send(ctx context.Context, messageType int, data []byte) er
372377 }
373378
374379 defer g .config .RateLimiter .Unlock ()
375- g .config .Logger .DebugContext (ctx , "sending gateway command" , slog .String ("data" , string (data )))
376- return g .conn .WriteMessage (messageType , data )
380+ return g .conn .WriteMessage (data )
377381}
378382
379383func (g * gatewayImpl ) Latency () time.Duration {
@@ -516,7 +520,7 @@ func (g *gatewayImpl) identify() error {
516520 Browser : g .config .Browser ,
517521 Device : g .config .Device ,
518522 },
519- Compress : g .config .Compress ,
523+ Compress : g .config .Compression . IsPayloadCompression () ,
520524 LargeThreshold : g .config .LargeThreshold ,
521525 Intents : g .config .Intents ,
522526 Presence : g .config .Presence ,
@@ -554,14 +558,14 @@ func (g *gatewayImpl) resume() error {
554558 return nil
555559}
556560
557- func (g * gatewayImpl ) listen (conn * websocket. Conn , ready func (error )) {
561+ func (g * gatewayImpl ) listen (conn transport , ready func (error )) {
558562 defer g .config .Logger .Debug ("exiting listen goroutine" )
559563
560564 // Ensure that we never leave this function without calling ready
561565 defer ready (nil )
562566
563567 for {
564- mt , r , err := conn .NextReader ()
568+ message , err := conn .ReceiveMessage ()
565569 if err != nil {
566570 g .statusMu .Lock ()
567571 if g .status != StatusReady {
@@ -620,10 +624,8 @@ func (g *gatewayImpl) listen(conn *websocket.Conn, ready func(error)) {
620624
621625 return
622626 }
623-
624- message , err := g .parseMessage (mt , r )
625- if err != nil {
626- g .config .Logger .Error ("error while parsing gateway message" , slog .Any ("err" , err ))
627+ if message == nil {
628+ // No message (probably parsing error), just continue as the transport already logged it
627629 continue
628630 }
629631
@@ -746,30 +748,3 @@ func (g *gatewayImpl) listen(conn *websocket.Conn, ready func(error)) {
746748 }
747749 }
748750}
749-
750- func (g * gatewayImpl ) parseMessage (mt int , r io.Reader ) (Message , error ) {
751- if mt == websocket .BinaryMessage {
752- g .config .Logger .Debug ("binary message received. decompressing" )
753-
754- reader , err := zlib .NewReader (r )
755- if err != nil {
756- return Message {}, fmt .Errorf ("failed to decompress zlib: %w" , err )
757- }
758- defer reader .Close ()
759- r = reader
760- }
761-
762- if g .config .Logger .Enabled (context .Background (), slog .LevelDebug ) {
763- buff := new (bytes.Buffer )
764- tr := io .TeeReader (r , buff )
765- data , err := io .ReadAll (tr )
766- if err != nil {
767- return Message {}, fmt .Errorf ("failed to read message: %w" , err )
768- }
769- g .config .Logger .Debug ("received gateway message" , slog .String ("data" , string (data )))
770- r = buff
771- }
772-
773- var message Message
774- return message , json .NewDecoder (r ).Decode (& message )
775- }
0 commit comments