From ed75b79764a4b666debc2a408499a14dc776fd16 Mon Sep 17 00:00:00 2001 From: kehiy Date: Sun, 15 Sep 2024 13:43:07 +0330 Subject: [PATCH 1/4] feat:(conn): add RemoteAddr method --- accept.go | 1 + conn.go | 8 ++++++++ internal/examples/echo/server.go | 2 ++ 3 files changed, 11 insertions(+) diff --git a/accept.go b/accept.go index 774ea285..313290f3 100644 --- a/accept.go +++ b/accept.go @@ -156,6 +156,7 @@ func accept(w http.ResponseWriter, r *http.Request, opts *AcceptOptions) (_ *Con client: false, copts: copts, flateThreshold: opts.CompressionThreshold, + remoteAddr: r.RemoteAddr, br: brw.Reader, bw: brw.Writer, diff --git a/conn.go b/conn.go index d7434a9d..c5a30e5a 100644 --- a/conn.go +++ b/conn.go @@ -49,6 +49,7 @@ type Conn struct { client bool copts *compressionOptions flateThreshold int + remoteAddr string br *bufio.Reader bw *bufio.Writer @@ -88,6 +89,7 @@ type connConfig struct { client bool copts *compressionOptions flateThreshold int + remoteAddr string br *bufio.Reader bw *bufio.Writer @@ -100,6 +102,7 @@ func newConn(cfg connConfig) *Conn { client: cfg.client, copts: cfg.copts, flateThreshold: cfg.flateThreshold, + remoteAddr: cfg.remoteAddr, br: cfg.br, bw: cfg.bw, @@ -192,6 +195,11 @@ func (c *Conn) flate() bool { return c.copts != nil } +// RemoteAddr returns the remote address of websocket connection. +func (c *Conn) RemoteAddr() string { + return c.remoteAddr +} + // Ping sends a ping to the peer and waits for a pong. // Use this to measure latency or ensure the peer is responsive. // Ping must be called concurrently with Reader as it does diff --git a/internal/examples/echo/server.go b/internal/examples/echo/server.go index 37e2f2c4..5f83b8b7 100644 --- a/internal/examples/echo/server.go +++ b/internal/examples/echo/server.go @@ -30,6 +30,8 @@ func (s echoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } defer c.CloseNow() + s.logf("new incoming connection: %s", c.RemoteAddr()) + if c.Subprotocol() != "echo" { c.Close(websocket.StatusPolicyViolation, "client must speak the echo subprotocol") return From 46be8dcad0661e4d3424a328b517a52314f004a6 Mon Sep 17 00:00:00 2001 From: kehiy Date: Tue, 17 Sep 2024 19:51:21 +0330 Subject: [PATCH 2/4] return net.Addr instead of string --- accept.go | 25 ++++++++++++++++++++++++- conn.go | 6 +++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/accept.go b/accept.go index 313290f3..283664cb 100644 --- a/accept.go +++ b/accept.go @@ -11,10 +11,12 @@ import ( "fmt" "io" "log" + "net" "net/http" "net/textproto" "net/url" "path" + "strconv" "strings" "github.com/coder/websocket/internal/errd" @@ -150,13 +152,34 @@ func accept(w http.ResponseWriter, r *http.Request, opts *AcceptOptions) (_ *Con b, _ := brw.Reader.Peek(brw.Reader.Buffered()) brw.Reader.Reset(io.MultiReader(bytes.NewReader(b), netConn)) + ipStr, portStr, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + err = errors.New("*http.Request contains invalid RemoteAddr") + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + return nil, err + } + + ip := net.ParseIP(ipStr) + if ip == nil { + err = errors.New("*http.Request contains invalid IP address") + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + return nil, err + } + + port, err := strconv.Atoi(portStr) + if err != nil { + err = errors.New("*http.Request contains invalid port number") + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + return nil, err + } + return newConn(connConfig{ subprotocol: w.Header().Get("Sec-WebSocket-Protocol"), rwc: netConn, client: false, copts: copts, flateThreshold: opts.CompressionThreshold, - remoteAddr: r.RemoteAddr, + remoteAddr: &net.TCPAddr{IP: ip, Port: port}, br: brw.Reader, bw: brw.Writer, diff --git a/conn.go b/conn.go index c5a30e5a..9071d1dc 100644 --- a/conn.go +++ b/conn.go @@ -49,7 +49,7 @@ type Conn struct { client bool copts *compressionOptions flateThreshold int - remoteAddr string + remoteAddr net.Addr br *bufio.Reader bw *bufio.Writer @@ -89,7 +89,7 @@ type connConfig struct { client bool copts *compressionOptions flateThreshold int - remoteAddr string + remoteAddr net.Addr br *bufio.Reader bw *bufio.Writer @@ -196,7 +196,7 @@ func (c *Conn) flate() bool { } // RemoteAddr returns the remote address of websocket connection. -func (c *Conn) RemoteAddr() string { +func (c *Conn) RemoteAddr() net.Addr { return c.remoteAddr } From b5355de5fc16e3058933e3f5dee6da08b9abf98e Mon Sep 17 00:00:00 2001 From: kehiy Date: Tue, 17 Sep 2024 19:52:14 +0330 Subject: [PATCH 3/4] return net.Addr instead of string --- internal/examples/echo/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/examples/echo/server.go b/internal/examples/echo/server.go index 5f83b8b7..3e22bd36 100644 --- a/internal/examples/echo/server.go +++ b/internal/examples/echo/server.go @@ -30,7 +30,7 @@ func (s echoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } defer c.CloseNow() - s.logf("new incoming connection: %s", c.RemoteAddr()) + s.logf("new incoming connection: %s", c.RemoteAddr().String()) if c.Subprotocol() != "echo" { c.Close(websocket.StatusPolicyViolation, "client must speak the echo subprotocol") From 4a7c292248a9d0543980c1a8dd0f68d8fd9de7ea Mon Sep 17 00:00:00 2001 From: kehiy Date: Wed, 18 Sep 2024 17:16:03 +0330 Subject: [PATCH 4/4] fix(conn): add local and remote address --- accept.go | 24 ------------------------ conn.go | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/accept.go b/accept.go index 283664cb..774ea285 100644 --- a/accept.go +++ b/accept.go @@ -11,12 +11,10 @@ import ( "fmt" "io" "log" - "net" "net/http" "net/textproto" "net/url" "path" - "strconv" "strings" "github.com/coder/websocket/internal/errd" @@ -152,34 +150,12 @@ func accept(w http.ResponseWriter, r *http.Request, opts *AcceptOptions) (_ *Con b, _ := brw.Reader.Peek(brw.Reader.Buffered()) brw.Reader.Reset(io.MultiReader(bytes.NewReader(b), netConn)) - ipStr, portStr, err := net.SplitHostPort(r.RemoteAddr) - if err != nil { - err = errors.New("*http.Request contains invalid RemoteAddr") - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - return nil, err - } - - ip := net.ParseIP(ipStr) - if ip == nil { - err = errors.New("*http.Request contains invalid IP address") - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - return nil, err - } - - port, err := strconv.Atoi(portStr) - if err != nil { - err = errors.New("*http.Request contains invalid port number") - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - return nil, err - } - return newConn(connConfig{ subprotocol: w.Header().Get("Sec-WebSocket-Protocol"), rwc: netConn, client: false, copts: copts, flateThreshold: opts.CompressionThreshold, - remoteAddr: &net.TCPAddr{IP: ip, Port: port}, br: brw.Reader, bw: brw.Writer, diff --git a/conn.go b/conn.go index 9071d1dc..0f6abbf2 100644 --- a/conn.go +++ b/conn.go @@ -49,7 +49,6 @@ type Conn struct { client bool copts *compressionOptions flateThreshold int - remoteAddr net.Addr br *bufio.Reader bw *bufio.Writer @@ -89,7 +88,6 @@ type connConfig struct { client bool copts *compressionOptions flateThreshold int - remoteAddr net.Addr br *bufio.Reader bw *bufio.Writer @@ -102,7 +100,6 @@ func newConn(cfg connConfig) *Conn { client: cfg.client, copts: cfg.copts, flateThreshold: cfg.flateThreshold, - remoteAddr: cfg.remoteAddr, br: cfg.br, bw: cfg.bw, @@ -197,7 +194,18 @@ func (c *Conn) flate() bool { // RemoteAddr returns the remote address of websocket connection. func (c *Conn) RemoteAddr() net.Addr { - return c.remoteAddr + if unc, ok := c.rwc.(net.Conn); ok { + return unc.RemoteAddr() + } + return websocketAddr{} +} + +// LocalAddr returns the local address of websocket connection. +func (c *Conn) LocalAddr() net.Addr { + if unc, ok := c.rwc.(net.Conn); ok { + return unc.LocalAddr() + } + return websocketAddr{} } // Ping sends a ping to the peer and waits for a pong.