reworked hub

This commit is contained in:
9seconds
2019-10-07 17:26:03 +03:00
parent c9743b5675
commit 413cafeeb6
7 changed files with 189 additions and 148 deletions
+38 -26
View File
@@ -1,48 +1,60 @@
package hub
import (
"errors"
"encoding/binary"
"fmt"
"strings"
"sync"
"github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/protocol"
)
type Concentrator struct {
hubs sync.Map
type hub struct {
subs map[string]*connectionHub
mutex sync.RWMutex
}
func (c *Concentrator) Write(packet conntypes.Packet, req *protocol.TelegramRequest) error {
hub := c.getHub(req)
connectionChan := make(chan *connection)
hub.connectionRequestsChan <- &connectionHubRequest{
req: req,
responseChan: connectionChan,
func (h *hub) Write(packet conntypes.Packet, req *protocol.TelegramRequest) error {
sub := h.getHub(req)
connections := make(chan *connection)
sub.channelConnectionRequests <- &connectionHubRequest{
request: req,
response: connections,
}
conn, ok := <-connectionChan
conn, ok := <-connections
if !ok {
return errors.New("cannot establish connection to telegram")
return ErrCannotCreateConnection
}
if err := conn.write(packet); err != nil {
return fmt.Errorf("cannot send packet: %w", err)
}
return nil
}
func (c *Concentrator) getHub(req *protocol.TelegramRequest) *connectionHub {
dcMapRaw, ok := c.hubs.Load(req.ClientProtocol.DC())
if !ok {
dcMapRaw, _ = c.hubs.LoadOrStore(req.ClientProtocol.DC(), &sync.Map{})
}
dcMap := dcMapRaw.(*sync.Map)
func (h *hub) getHub(req *protocol.TelegramRequest) *connectionHub {
keyBuilder := strings.Builder{}
binary.Write(&keyBuilder, binary.LittleEndian, int16(req.ClientProtocol.DC()))
keyBuilder.WriteRune('_')
binary.Write(&keyBuilder, binary.LittleEndian, uint8(req.ClientProtocol.ConnectionProtocol()))
key := keyBuilder.String()
h.mutex.RLock()
rv, ok := h.subs[key]
h.mutex.RUnlock()
loaded := true
hubRaw, ok := dcMap.Load(req.ClientProtocol.ConnectionProtocol())
if !ok {
hubRaw, loaded = dcMap.LoadOrStore(req.ClientProtocol.ConnectionProtocol(),
newConnectionHub())
}
hub := hubRaw.(*connectionHub)
if !loaded {
go hub.run()
h.mutex.Lock()
defer h.mutex.Unlock()
rv, ok = h.subs[key]
if !ok {
rv = newConnectionHub()
h.subs[key] = rv
}
}
return hub
return rv
}