Skip to content
This repository has been archived by the owner on Sep 29, 2024. It is now read-only.

Commit

Permalink
ref: clint file (#614)
Browse files Browse the repository at this point in the history
  • Loading branch information
sshaplygin authored Sep 4, 2023
1 parent cd0c86b commit b044011
Showing 1 changed file with 86 additions and 97 deletions.
183 changes: 86 additions & 97 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package socketio

import (
"errors"
"fmt"
"net/url"
"path"
"strings"
Expand All @@ -14,160 +13,161 @@ 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
if !errors.As(err, &errMsg) {
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
}
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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
}

Expand All @@ -224,50 +226,41 @@ 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
}

return ret
}

////
// Handlers
////

func (c *conn) connectClient() error {
rootHandler, ok := c.handlers.Get(rootNamespace)
if !ok {
Expand All @@ -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)
}

0 comments on commit b044011

Please sign in to comment.