From b044011d047be8ab05ffbfbfa16f16ce7993d68f Mon Sep 17 00:00:00 2001 From: Semen Shaplygin Date: Mon, 4 Sep 2023 12:40:53 +0400 Subject: [PATCH] ref: clint file (#614) --- client.go | 183 +++++++++++++++++++++++++----------------------------- 1 file changed, 86 insertions(+), 97 deletions(-) diff --git a/client.go b/client.go index fe172f8b..1d2503de 100644 --- a/client.go +++ b/client.go @@ -2,7 +2,6 @@ package socketio import ( "errors" - "fmt" "net/url" "path" "strings" @@ -14,150 +13,151 @@ import ( "github.com/googollee/go-socket.io/parser" ) -// Server is a go-socket.io server. +var EmptyAddrErr = errors.New("empty addr") + +// Client is client for socket.io server type Client struct { - conn *conn namespace string - handlers *namespaceHandlers url string - opts *engineio.Options + + conn *conn + handlers *namespaceHandlers + + opts *engineio.Options } -// NewServer returns a server. -func NewClient(uri string, opts *engineio.Options) (*Client, error) { - // uri like http://asd.com:8080/namesapce +// NewClient returns a server +// addr like http://asd.com:8080/{$namespace} +func NewClient(addr string, opts *engineio.Options) (*Client, error) { + if addr == "" { + return nil, EmptyAddrErr + } - url, err := url.Parse(uri) + u, err := url.Parse(addr) if err != nil { return nil, err } - namespace := url.Path + + namespace := fmtNS(u.Path) // Not allowing other than default - url.Path = path.Join("/socket.io", namespace) - url.Path = url.EscapedPath() - if strings.HasSuffix(url.Path, "socket.io") { - url.Path += "/" + u.Path = path.Join("/socket.io", namespace) + u.Path = u.EscapedPath() + if strings.HasSuffix(u.Path, "socket.io") { + u.Path += "/" } - client := &Client{ - conn: nil, + return &Client{ namespace: namespace, - url: url.String(), + url: u.String(), handlers: newNamespaceHandlers(), opts: opts, - } + }, nil +} - fmt.Println(client) +func fmtNS(ns string) string { + if ns == aliasRootNamespace { + return rootNamespace + } - return client, nil + return ns } -func (s *Client) Connect() error { +func (c *Client) Connect() error { dialer := engineio.Dialer{ Transports: []transport.Transport{polling.Default}, } - enginioCon, err := dialer.Dial(s.url, nil) + + enginioCon, err := dialer.Dial(c.url, nil) if err != nil { return err } - // Set the engine connection - c := newConn(enginioCon, s.handlers) - - s.conn = c + c.conn = newConn(enginioCon, c.handlers) - if err := c.connectClient(); err != nil { + if err := c.conn.connectClient(); err != nil { _ = c.Close() - if root, ok := s.handlers.Get(rootNamespace); ok && root.onError != nil { + if root, ok := c.handlers.Get(rootNamespace); ok && root.onError != nil { root.onError(nil, err) } return err } - go s.clientError(c) - go s.clientWrite(c) - go s.clientRead(c) + go c.clientError() + go c.clientWrite() + go c.clientRead() + return nil } // Close closes server. -func (s *Client) Close() error { - return s.conn.Close() +func (c *Client) Close() error { + return c.conn.Close() } -func (s *Client) Emit(event string, args ...interface{}) { - nsp := s.namespace - if nsp == aliasRootNamespace { - nsp = rootNamespace - } - - ns, ok := s.conn.namespaces.Get(nsp) +func (c *Client) Emit(event string, args ...interface{}) { + nsConn, ok := c.conn.namespaces.Get(c.namespace) if !ok { logger.Info("Connection Namespace not initialized") return } - ns.Emit(event, args...) + + nsConn.Emit(event, args...) } // OnConnect set a handler function f to handle open event for namespace. -func (s *Client) OnConnect(f func(Conn) error) { - h := s.getNamespace(s.namespace) +func (c *Client) OnConnect(f func(Conn) error) { + h := c.getNamespace(c.namespace) if h == nil { - h = s.createNamespace(s.namespace) + h = c.createNamespace(c.namespace) } h.OnConnect(f) } // OnDisconnect set a handler function f to handle disconnect event for namespace. -func (s *Client) OnDisconnect(f func(Conn, string)) { - h := s.getNamespace(s.namespace) +func (c *Client) OnDisconnect(f func(Conn, string)) { + h := c.getNamespace(c.namespace) if h == nil { - h = s.createNamespace(s.namespace) + h = c.createNamespace(c.namespace) } h.OnDisconnect(f) } // OnError set a handler function f to handle error for namespace. -func (s *Client) OnError(f func(Conn, error)) { - h := s.getNamespace(s.namespace) +func (c *Client) OnError(f func(Conn, error)) { + h := c.getNamespace(c.namespace) if h == nil { - h = s.createNamespace(s.namespace) + h = c.createNamespace(c.namespace) } h.OnError(f) } // OnEvent set a handler function f to handle event for namespace. -func (s *Client) OnEvent(event string, f interface{}) { - h := s.getNamespace(s.namespace) +func (c *Client) OnEvent(event string, f interface{}) { + h := c.getNamespace(c.namespace) if h == nil { - h = s.createNamespace(s.namespace) + h = c.createNamespace(c.namespace) } h.OnEvent(event, f) } -///////////////////////// -// Private Functions -///////////////////////// - -func (s *Client) clientError(c *conn) { +func (c *Client) clientError() { defer func() { if err := c.Close(); err != nil { logger.Error("close connect:", err) } - }() for { select { - case <-c.quitChan: + case <-c.conn.quitChan: return - case err := <-c.errorChan: + case err := <-c.conn.errorChan: logger.Error("clientError", err) var errMsg *errorMessage @@ -165,9 +165,9 @@ func (s *Client) clientError(c *conn) { continue } - if handler := c.namespace(errMsg.namespace); handler != nil { + if handler := c.conn.namespace(errMsg.namespace); handler != nil { if handler.onError != nil { - nsConn, ok := c.namespaces.Get(errMsg.namespace) + nsConn, ok := c.conn.namespaces.Get(errMsg.namespace) if !ok { continue } @@ -178,7 +178,7 @@ func (s *Client) clientError(c *conn) { } } -func (s *Client) clientWrite(c *conn) { +func (c *Client) clientWrite() { defer func() { if err := c.Close(); err != nil { logger.Error("close connect:", err) @@ -188,18 +188,18 @@ func (s *Client) clientWrite(c *conn) { for { select { - case <-c.quitChan: + case <-c.conn.quitChan: logger.Info("clientWrite Writer loop has stopped") return - case pkg := <-c.writeChan: - if err := c.encoder.Encode(pkg.Header, pkg.Data); err != nil { - c.onError(pkg.Header.Namespace, err) + case pkg := <-c.conn.writeChan: + if err := c.conn.encoder.Encode(pkg.Header, pkg.Data); err != nil { + c.conn.onError(pkg.Header.Namespace, err) } } } } -func (s *Client) clientRead(c *conn) { +func (c *Client) clientRead() { defer func() { if err := c.Close(); err != nil { logger.Error("close connect:", err) @@ -211,9 +211,11 @@ func (s *Client) clientRead(c *conn) { for { var header parser.Header - if err := c.decoder.DecodeHeader(&header, &event); err != nil { - c.onError(rootNamespace, err) + if err := c.conn.decoder.DecodeHeader(&header, &event); err != nil { + c.conn.onError(rootNamespace, err) + logger.Error("clientRead Error in Decoder", err) + return } @@ -224,39 +226,34 @@ func (s *Client) clientRead(c *conn) { var err error switch header.Type { case parser.Ack: - err = ackPacketHandler(c, header) + err = ackPacketHandler(c.conn, header) case parser.Connect: - err = clientConnectPacketHandler(c, header) + err = clientConnectPacketHandler(c.conn, header) case parser.Disconnect: - err = clientDisconnectPacketHandler(c, header) + err = clientDisconnectPacketHandler(c.conn, header) case parser.Event: - err = eventPacketHandler(c, event, header) + err = eventPacketHandler(c.conn, event, header) + default: + } if err != nil { logger.Error("client read:", err) + return } } } -func (s *Client) createNamespace(nsp string) *namespaceHandler { - if nsp == aliasRootNamespace { - nsp = rootNamespace - } - - handler := newNamespaceHandler(nsp, nil) - s.handlers.Set(nsp, handler) +func (c *Client) createNamespace(ns string) *namespaceHandler { + handler := newNamespaceHandler(ns, nil) + c.handlers.Set(ns, handler) return handler } -func (s *Client) getNamespace(nsp string) *namespaceHandler { - if nsp == aliasRootNamespace { - nsp = rootNamespace - } - - ret, ok := s.handlers.Get(nsp) +func (c *Client) getNamespace(ns string) *namespaceHandler { + ret, ok := c.handlers.Get(ns) if !ok { return nil } @@ -264,10 +261,6 @@ func (s *Client) getNamespace(nsp string) *namespaceHandler { return ret } -//// -// Handlers -//// - func (c *conn) connectClient() error { rootHandler, ok := c.handlers.Get(rootNamespace) if !ok { @@ -287,9 +280,5 @@ func (c *conn) connectClient() error { Type: parser.Connect, } - if err := c.encoder.Encode(header); err != nil { - return err - } - - return nil + return c.encoder.Encode(header) }