Skip to content

Commit

Permalink
Close the websocket connection when a write error occurs (#17)
Browse files Browse the repository at this point in the history
This was causing the server to not receive a close error so it would not
clear the clients public key from it's list of connected clients. This in turn
would cause the client to be unable to connect again as the server believes
that the client is already connected
  • Loading branch information
jkongie authored Mar 3, 2022
1 parent 686b3b7 commit be729b0
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 2 deletions.
2 changes: 2 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ func (ac *addrConn) resetTransport() {
// Block until the created transport is down. When this happens, we
// attempt to reconnect by starting again from the top
<-reconnect.Done()

log.Println("[wsrpc] Reconnecting to server...")
}
}

Expand Down
9 changes: 9 additions & 0 deletions dialoptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package wsrpc
import (
"crypto/ed25519"
"log"
"time"

"github.com/smartcontractkit/wsrpc/credentials"
"github.com/smartcontractkit/wsrpc/internal/backoff"
Expand Down Expand Up @@ -65,6 +66,14 @@ func WithBlock() DialOption {
})
}

// WithWriteTimeout returns a DialOption which sets the write timeout for a
// message to be sent on the wire.
func WithWriteTimeout(d time.Duration) DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.copts.WriteTimeout = d
})
}

func defaultDialOptions() dialOptions {
return dialOptions{
copts: transport.ConnectOptions{},
Expand Down
11 changes: 9 additions & 2 deletions internal/transport/websocket_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package transport
import (
"context"
"fmt"
"log"
"net/http"
"time"

Expand Down Expand Up @@ -98,8 +99,8 @@ func (c WebsocketClient) start() {
}

// readPump pumps messages from the websocket connection. When a websocket
// connection closure is detected, it closes the done channel to shutdown
// writePump.
// connection closure is detected through a read error, it closes the done
// channel to shutdown writePump.
//
// The application runs readPump in a per-connection goroutine. This ensures
// that there is at most one reader on a connection by executing all reads from
Expand Down Expand Up @@ -147,6 +148,10 @@ func (c *WebsocketClient) writePump() {
c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
err := c.conn.WriteMessage(websocket.BinaryMessage, msg)
if err != nil {
log.Printf("[wsrpc] write error: %v\n", err)

c.conn.Close()

return
}
case <-ticker.C:
Expand All @@ -155,6 +160,8 @@ func (c *WebsocketClient) writePump() {
//nolint:errcheck
c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
c.conn.Close()

return
}
case <-c.interrupt:
Expand Down

0 comments on commit be729b0

Please sign in to comment.