Пример #1
0
// New creates a new Telegraph instance
func New(userHash string, hostnames []string, checkInterval time.Duration,
	maxConnectionCount int, keyPair cryptochain.KeyPair, debug bool) (Telegraph, error) {
	cc := cryptochain.NewCryptoChain(userHash, keyPair)
	// Protocol input will be used to process Newton protocol messages.
	pi := make(chan store.ProtocolInput)
	// Dispatcher routes messages and runs appropriate functions to process messages correctly.
	dp, err := dispatcher.New(userHash, hostnames, checkInterval, maxConnectionCount, cc, pi, debug)
	if err != nil {
		return nil, err
	}

	l := logger.New("telegraph")

	// Get a message store
	ms := store.NewMessageStore(1000 * time.Millisecond)
	t := &telegraph{
		dispatcher:     dp,
		pool:           dp.GetPool(),
		log:            l,
		protocolOutput: make(chan ProtocolMessage, 100),
		protocolInput:  pi,
		messageStore:   ms,
		cryptoChain:    cc,
		waitGroup:      &sync.WaitGroup{},
		done:           make(chan struct{}),
	}

	t.waitGroup.Add(3)
	go t.processCryptoOutput()
	go t.processProtocolOutput()
	go t.processProtocolInput()
	return t, nil
}
Пример #2
0
func NewMessageStore(checkInterval time.Duration) MessageStore {
	m := make(map[int]chan ProtocolInput)
	pq := &PriorityQueue{}
	heap.Init(pq)
	l := logger.New("message-store")
	ms := messageStore{
		m:             m,
		checkInterval: checkInterval,
		done:          make(chan struct{}),
		pq:            pq,
		log:           l,
	}
	go ms.expireObsoleteMessages()
	return &ms
}
Пример #3
0
// New returns a new Dispatcher instade
func New(userHash string, hostnames []string, checkInterval time.Duration, maxConnectionCount int,
	cc *cryptochain.CryptoChain, protocolInput chan store.ProtocolInput, debug bool) (Dispatcher, error) {
	p, err := pool.New(userHash, hostnames, checkInterval, maxConnectionCount, cc.ConnectionStore, debug)
	if err != nil {
		return nil, err
	}
	// Create a new logger
	l := logger.New("dispatcher")
	//if debug {
	//	logger.SetLogLevel(log.DEBUG)
	//}

	d := &dispatcher{
		Pool:          p,
		log:           l,
		cryptoChain:   cc,
		protocolInput: protocolInput,
	}
	go d.dispatchIncomingMessages()
	return d, nil
}
Пример #4
0
// New returns a new Pool instance.
func New(userHash string, hostnames []string, checkInterval time.Duration, maxConnectionCount int,
	cs *cryptochain.ConnectionStore, debug bool) (Pool, error) {
	hc := len(hostnames)
	if hc == 0 {
		return nil, errors.New("We need hosts to run.")
	}
	hs := &hosts{
		h: map[string]struct{}{},
	}
	for _, host := range hostnames {
		hs.h[host] = struct{}{}
	}
	cn := &connections{
		c: make(map[string]*connection),
	}

	// Create a new logger
	l := logger.New("pool")
	if debug {
		logger.SetLogLevel(log.DEBUG)
	}
	p := &pool{
		maxConnectionCount: maxConnectionCount,
		checkInterval:      checkInterval,
		hosts:              hs,
		connections:        cn,
		incomingMessages:   make(chan []byte, 100),
		log:                l,
		userHash:           userHash,
		done:               make(chan struct{}),
		cs:                 cs,
	}

	// Here we select hosts randomly to connect.
	// We must use unique hosts
	u := make(map[int]struct{})
	// Determine the host limit
	limit := 0
	if hc < maxConnectionCount {
		limit = hc
	} else {
		limit = maxConnectionCount
	}
	// Select the hosts
	c := 0
	for {
		if len(hostnames) == 0 {
			return nil, ErrNoAvailableHost
		}
		r := rand.Intn(hc)
		if _, ok := u[r]; !ok {
			host := hostnames[r]
			// start a new newton connection
			// if it fails, the system tries to keep the number
			// at a constant value after initialization.
			err := p.newConnection(host)
			if err != nil {
				p.log.Error("Connection failed. Skipping:", err)
				hostnames = append(hostnames[:r], hostnames[r+1:]...)
				continue
			}
			u[r] = struct{}{}
			c++
			if c >= limit {
				break
			}
		}
	}
	// Check existing connections periodically and keep the number at maximum
	go p.checkConnections()
	return p, nil
}