github.com/glide-im/glide@v1.6.0/pkg/gate/gateway.go (about)

     1  package gate
     2  
     3  import (
     4  	"errors"
     5  	"github.com/glide-im/glide/pkg/conn"
     6  	"github.com/glide-im/glide/pkg/logger"
     7  	"github.com/glide-im/glide/pkg/messages"
     8  	"github.com/panjf2000/ants/v2"
     9  	"log"
    10  	"sync"
    11  )
    12  
    13  // Gateway is the basic and common interface for all gate implementations.
    14  // As the basic gate, it is used to provide a common gate interface for other modules to interact with the gate.
    15  type Gateway interface {
    16  
    17  	// SetClientID sets the client id with the new id.
    18  	SetClientID(old ID, new_ ID) error
    19  
    20  	UpdateClient(id ID, info *ClientSecrets) error
    21  
    22  	// ExitClient exits the client with the given id.
    23  	ExitClient(id ID) error
    24  
    25  	// EnqueueMessage enqueues the message to the client with the given id.
    26  	EnqueueMessage(id ID, message *messages.GlideMessage) error
    27  }
    28  
    29  // Server is the interface for the gateway server, which is used to handle and manager client connections.
    30  type Server interface {
    31  	Gateway
    32  
    33  	// SetMessageHandler sets the client message handler.
    34  	SetMessageHandler(h MessageHandler)
    35  
    36  	// HandleConnection handles the new client connection and returns the random and temporary id set for the connection.
    37  	HandleConnection(c conn.Connection) ID
    38  
    39  	Run() error
    40  }
    41  
    42  // MessageHandler used to handle messages from the gate.
    43  type MessageHandler func(cliInfo *Info, message *messages.GlideMessage)
    44  
    45  // DefaultGateway is gateway default implements.
    46  type DefaultGateway interface {
    47  	Gateway
    48  
    49  	GetClient(id ID) Client
    50  
    51  	GetAll() map[ID]Info
    52  
    53  	SetMessageHandler(h MessageHandler)
    54  
    55  	AddClient(cs Client)
    56  }
    57  
    58  type Options struct {
    59  	// ID is the gateway id.
    60  	ID string
    61  	// SecretKey is the secret key used to encrypt and decrypt authentication token.
    62  	SecretKey string
    63  	// MaxMessageConcurrency is the max message concurrency.
    64  	MaxMessageConcurrency int
    65  }
    66  
    67  var _ DefaultGateway = (*Impl)(nil)
    68  
    69  type Impl struct {
    70  	id string
    71  
    72  	// clients is a map of all connected clients
    73  	clients map[ID]Client
    74  	mu      sync.RWMutex
    75  
    76  	// msgHandler client message handler
    77  	msgHandler MessageHandler
    78  
    79  	authenticator *Authenticator
    80  
    81  	// pool of ants, used to process messages concurrently.
    82  	pool *ants.Pool
    83  
    84  	emptyInfo *Info
    85  }
    86  
    87  func NewServer(options *Options) (*Impl, error) {
    88  
    89  	ret := new(Impl)
    90  	ret.clients = map[ID]Client{}
    91  	ret.mu = sync.RWMutex{}
    92  	ret.id = options.ID
    93  	ret.emptyInfo = &Info{
    94  		ID: NewID(ret.id, "", ""),
    95  	}
    96  
    97  	if options.SecretKey != "" {
    98  		ret.authenticator = NewAuthenticator(ret, options.SecretKey)
    99  	}
   100  
   101  	pool, err := ants.NewPool(options.MaxMessageConcurrency,
   102  		ants.WithNonblocking(true),
   103  		ants.WithPanicHandler(func(i interface{}) {
   104  			log.Printf("panic: %v", i)
   105  		}),
   106  		ants.WithPreAlloc(false),
   107  	)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	ret.pool = pool
   112  	return ret, nil
   113  }
   114  
   115  // GetClient returns the client with specified id
   116  func (c *Impl) GetClient(id ID) Client {
   117  	c.mu.RLock()
   118  	defer c.mu.RUnlock()
   119  	return c.clients[id]
   120  }
   121  
   122  // GetAll returns all clients in the gateway.
   123  func (c *Impl) GetAll() map[ID]Info {
   124  	c.mu.RLock()
   125  	defer c.mu.RUnlock()
   126  
   127  	result := map[ID]Info{}
   128  	for id, client := range c.clients {
   129  		result[id] = client.GetInfo()
   130  	}
   131  	return result
   132  }
   133  
   134  func (c *Impl) SetMessageHandler(h MessageHandler) {
   135  	c.msgHandler = h
   136  }
   137  
   138  func (c *Impl) UpdateClient(id ID, info *ClientSecrets) error {
   139  	c.mu.Lock()
   140  	defer c.mu.Unlock()
   141  
   142  	id.SetGateway(c.id)
   143  
   144  	logger.D("gateway", "update client %s, %v", id, info)
   145  
   146  	cli, ok := c.clients[id]
   147  	if !ok || cli == nil {
   148  		return errors.New(errClientNotExist)
   149  	}
   150  
   151  	dc, ok := cli.(DefaultClient)
   152  	if ok {
   153  		credentials := dc.GetCredentials()
   154  		credentials.Secrets = info
   155  		dc.SetCredentials(credentials)
   156  	}
   157  
   158  	return nil
   159  }
   160  
   161  func (c *Impl) AddClient(cs Client) {
   162  	c.mu.Lock()
   163  	defer c.mu.Unlock()
   164  
   165  	id := cs.GetInfo().ID
   166  	id.SetGateway(c.id)
   167  
   168  	dc, ok := cs.(DefaultClient)
   169  	if ok {
   170  		dc.AddMessageInterceptor(c.interceptClientMessage)
   171  	}
   172  
   173  	c.clients[id] = cs
   174  	c.msgHandler(c.emptyInfo, messages.NewMessage(0, messages.ActionInternalOnline, id))
   175  }
   176  
   177  // SetClientID replace the oldID with newID of the client.
   178  // If the oldID is not exist, return errClientNotExist.
   179  // If the newID is existed, return errClientAlreadyExist.
   180  func (c *Impl) SetClientID(oldID, newID ID) error {
   181  	c.mu.Lock()
   182  	defer c.mu.Unlock()
   183  
   184  	oldID.SetGateway(c.id)
   185  	newID.SetGateway(c.id)
   186  
   187  	cli, ok := c.clients[oldID]
   188  	if !ok || cli == nil {
   189  		return errors.New(errClientNotExist)
   190  	}
   191  	cliLogged, exist := c.clients[newID]
   192  	if exist && cliLogged != nil {
   193  		return errors.New(errClientAlreadyExist)
   194  	}
   195  
   196  	cli.SetID(newID)
   197  	delete(c.clients, oldID)
   198  	c.msgHandler(c.emptyInfo, messages.NewMessage(0, messages.ActionInternalOffline, oldID))
   199  	c.msgHandler(c.emptyInfo, messages.NewMessage(0, messages.ActionInternalOnline, newID))
   200  
   201  	c.clients[newID] = cli
   202  	return nil
   203  }
   204  
   205  // ExitClient close the client with the specified id.
   206  // If the client is not exist, return errClientNotExist.
   207  func (c *Impl) ExitClient(id ID) error {
   208  	c.mu.Lock()
   209  	defer c.mu.Unlock()
   210  
   211  	id.SetGateway(c.id)
   212  
   213  	cli, ok := c.clients[id]
   214  	if !ok || cli == nil {
   215  		return errors.New(errClientNotExist)
   216  	}
   217  
   218  	cli.SetID("")
   219  	delete(c.clients, id)
   220  	c.msgHandler(c.emptyInfo, messages.NewMessage(0, messages.ActionInternalOffline, id))
   221  	cli.Exit()
   222  
   223  	return nil
   224  }
   225  
   226  // EnqueueMessage to the client with the specified id.
   227  func (c *Impl) EnqueueMessage(id ID, msg *messages.GlideMessage) error {
   228  
   229  	c.mu.RLock()
   230  	defer c.mu.RUnlock()
   231  
   232  	id.SetGateway(c.id)
   233  	cli, ok := c.clients[id]
   234  	if !ok || cli == nil {
   235  		return errors.New(errClientNotExist)
   236  	}
   237  
   238  	return c.enqueueMessage(cli, msg)
   239  }
   240  
   241  func (c *Impl) interceptClientMessage(dc DefaultClient, m *messages.GlideMessage) bool {
   242  
   243  	if m.Action == messages.ActionAuthenticate {
   244  		if c.authenticator != nil {
   245  			return c.authenticator.ClientAuthMessageInterceptor(dc, m)
   246  		}
   247  	}
   248  
   249  	return c.authenticator.MessageInterceptor(dc, m)
   250  }
   251  
   252  func (c *Impl) enqueueMessage(cli Client, msg *messages.GlideMessage) error {
   253  	if !cli.IsRunning() {
   254  		return errors.New(errClientClosed)
   255  	}
   256  	err := c.pool.Submit(func() {
   257  		_ = cli.EnqueueMessage(msg)
   258  	})
   259  	if err != nil {
   260  		return errors.New("enqueue message to client failed")
   261  	}
   262  	return nil
   263  }