forked from cwtch.im/cwtch
make event.Queue use internal infinite channels; make event.Manager not use failable writes
This commit is contained in:
parent
dfcf7f8777
commit
bd75e44555
|
@ -209,9 +209,9 @@ func completer(d prompt.Document) []prompt.Suggest {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAppEvents(em event.Manager) {
|
func handleAppEvents(em event.Manager) {
|
||||||
queue := event.NewEventQueue(100)
|
queue := event.NewQueue()
|
||||||
em.Subscribe(event.NewPeer, queue.EventChannel)
|
em.Subscribe(event.NewPeer, queue)
|
||||||
em.Subscribe(event.PeerError, queue.EventChannel)
|
em.Subscribe(event.PeerError, queue)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
ev := queue.Next()
|
ev := queue.Next()
|
||||||
|
|
|
@ -27,8 +27,8 @@ func main() {
|
||||||
alice := utils.WaitGetPeer(app, "alice")
|
alice := utils.WaitGetPeer(app, "alice")
|
||||||
app.LaunchPeers()
|
app.LaunchPeers()
|
||||||
eventBus := app.GetEventBus(alice.GetProfile().Onion)
|
eventBus := app.GetEventBus(alice.GetProfile().Onion)
|
||||||
queue := event.NewEventQueue(100)
|
queue := event.NewQueue()
|
||||||
eventBus.Subscribe(event.NewMessageFromPeer, queue.EventChannel)
|
eventBus.Subscribe(event.NewMessageFromPeer, queue)
|
||||||
|
|
||||||
// For every new Data Packet Alice received she will Print it out.
|
// For every new Data Packet Alice received she will Print it out.
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -20,7 +20,7 @@ type peer struct {
|
||||||
|
|
||||||
type contactRetry struct {
|
type contactRetry struct {
|
||||||
bus event.Manager
|
bus event.Manager
|
||||||
queue *event.Queue
|
queue event.Queue
|
||||||
|
|
||||||
breakChan chan bool
|
breakChan chan bool
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ type contactRetry struct {
|
||||||
|
|
||||||
// NewContactRetry returns a Plugin that when started will retry connecting to contacts with a backoff timing
|
// NewContactRetry returns a Plugin that when started will retry connecting to contacts with a backoff timing
|
||||||
func NewContactRetry(bus event.Manager) Plugin {
|
func NewContactRetry(bus event.Manager) Plugin {
|
||||||
cr := &contactRetry{bus: bus, queue: event.NewEventQueue(1000), breakChan: make(chan bool), peers: sync.Map{}}
|
cr := &contactRetry{bus: bus, queue: event.NewQueue(), breakChan: make(chan bool), peers: sync.Map{}}
|
||||||
return cr
|
return cr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +38,10 @@ func (cr *contactRetry) Start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *contactRetry) run() {
|
func (cr *contactRetry) run() {
|
||||||
cr.bus.Subscribe(event.PeerStateChange, cr.queue.EventChannel)
|
cr.bus.Subscribe(event.PeerStateChange, cr.queue)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case e := <-cr.queue.EventChannel:
|
case e := <-cr.queue.OutChan():
|
||||||
switch e.EventType {
|
switch e.EventType {
|
||||||
case event.PeerStateChange:
|
case event.PeerStateChange:
|
||||||
state := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
|
state := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package event
|
|
||||||
|
|
||||||
// Queue is a wrapper around a channel for handling Events in a consistent way across subsystems.
|
|
||||||
// The expectation is that each subsystem in Cwtch will manage a given an event.Queue fed from
|
|
||||||
// the event.Manager.
|
|
||||||
type Queue struct {
|
|
||||||
EventChannel chan Event
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEventQueue initializes an event.Queue of the given buffer size.
|
|
||||||
func NewEventQueue(buffer int) *Queue {
|
|
||||||
queue := new(Queue)
|
|
||||||
queue.EventChannel = make(chan Event, buffer)
|
|
||||||
return queue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backlog returns the length of the queue backlog
|
|
||||||
func (eq *Queue) Backlog() int {
|
|
||||||
return len(eq.EventChannel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns the next available event from the front of the queue
|
|
||||||
func (eq *Queue) Next() (event Event) {
|
|
||||||
event = <-eq.EventChannel
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shutdown closes our EventChannel
|
|
||||||
func (eq *Queue) Shutdown() {
|
|
||||||
close(eq.EventChannel)
|
|
||||||
}
|
|
|
@ -34,7 +34,10 @@ const (
|
||||||
AcceptGroupInvite = Type("AcceptGroupInvite")
|
AcceptGroupInvite = Type("AcceptGroupInvite")
|
||||||
|
|
||||||
SendMessageToGroup = Type("SendMessagetoGroup")
|
SendMessageToGroup = Type("SendMessagetoGroup")
|
||||||
|
|
||||||
|
//Ciphertext, Signature:
|
||||||
EncryptedGroupMessage = Type("EncryptedGroupMessage")
|
EncryptedGroupMessage = Type("EncryptedGroupMessage")
|
||||||
|
//TimestampReceived, TimestampSent, Data(Message), GroupID, Signature, PreviousSignature, RemotePeer
|
||||||
NewMessageFromGroup = Type("NewMessageFromGroup")
|
NewMessageFromGroup = Type("NewMessageFromGroup")
|
||||||
|
|
||||||
// an error was encountered trying to send a particular Message to a group
|
// an error was encountered trying to send a particular Message to a group
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package event
|
||||||
|
|
||||||
|
type queue struct {
|
||||||
|
infChan infiniteChannel
|
||||||
|
}
|
||||||
|
|
||||||
|
type simpleQueue struct {
|
||||||
|
eventChannel chan Event
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue is a wrapper around a channel for handling Events in a consistent way across subsystems.
|
||||||
|
// The expectation is that each subsystem in Cwtch will manage a given an event.Queue fed from
|
||||||
|
// the event.Manager.
|
||||||
|
type Queue interface {
|
||||||
|
InChan() chan<- Event
|
||||||
|
OutChan() <-chan Event
|
||||||
|
Next() *Event
|
||||||
|
Shutdown()
|
||||||
|
Len() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewQueue initializes an event.Queue
|
||||||
|
func NewQueue() Queue {
|
||||||
|
queue := &queue{infChan: *newInfiniteChannel()}
|
||||||
|
return queue
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSimpleQueue initializes an event.Queue of the given buffer size.
|
||||||
|
func NewSimpleQueue(buffer int) Queue {
|
||||||
|
queue := new(simpleQueue)
|
||||||
|
queue.eventChannel = make(chan Event, buffer)
|
||||||
|
return queue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sq *simpleQueue) InChan() chan<- Event {
|
||||||
|
return sq.eventChannel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sq *simpleQueue) OutChan() <-chan Event {
|
||||||
|
return sq.eventChannel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backlog returns the length of the queue backlog
|
||||||
|
func (sq *simpleQueue) Len() int {
|
||||||
|
return len(sq.eventChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next available event from the front of the queue
|
||||||
|
func (sq *simpleQueue) Next() *Event {
|
||||||
|
event := <-sq.eventChannel
|
||||||
|
return &event
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown closes our eventChannel
|
||||||
|
func (sq *simpleQueue) Shutdown() {
|
||||||
|
close(sq.eventChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iq *queue) InChan() chan<- Event {
|
||||||
|
return iq.infChan.In()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iq *queue) OutChan() <-chan Event {
|
||||||
|
return iq.infChan.Out()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Out returns the next available event from the front of the queue
|
||||||
|
func (iq *queue) Next() *Event {
|
||||||
|
event := <-iq.infChan.Out()
|
||||||
|
return &event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iq *queue) Len() int {
|
||||||
|
return iq.infChan.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown closes our eventChannel
|
||||||
|
func (iq *queue) Shutdown() {
|
||||||
|
iq.infChan.Close()
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package event
|
package event
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
@ -33,7 +32,7 @@ func NewEventList(eventType Type, args ...interface{}) Event {
|
||||||
|
|
||||||
// Manager is an Event Bus which allows subsystems to subscribe to certain EventTypes and publish others.
|
// Manager is an Event Bus which allows subsystems to subscribe to certain EventTypes and publish others.
|
||||||
type manager struct {
|
type manager struct {
|
||||||
subscribers map[Type][]chan Event
|
subscribers map[Type][]chan<- Event
|
||||||
events chan Event
|
events chan Event
|
||||||
mapMutex sync.Mutex
|
mapMutex sync.Mutex
|
||||||
internal chan bool
|
internal chan bool
|
||||||
|
@ -42,7 +41,7 @@ type manager struct {
|
||||||
|
|
||||||
// Manager is an interface for an event bus
|
// Manager is an interface for an event bus
|
||||||
type Manager interface {
|
type Manager interface {
|
||||||
Subscribe(Type, chan Event)
|
Subscribe(Type, Queue)
|
||||||
Publish(Event)
|
Publish(Event)
|
||||||
PublishLocal(Event)
|
PublishLocal(Event)
|
||||||
Shutdown()
|
Shutdown()
|
||||||
|
@ -57,7 +56,7 @@ func NewEventManager() Manager {
|
||||||
|
|
||||||
// Initialize sets up the Manager.
|
// Initialize sets up the Manager.
|
||||||
func (em *manager) initialize() {
|
func (em *manager) initialize() {
|
||||||
em.subscribers = make(map[Type][]chan Event)
|
em.subscribers = make(map[Type][]chan<- Event)
|
||||||
em.events = make(chan Event)
|
em.events = make(chan Event)
|
||||||
em.internal = make(chan bool)
|
em.internal = make(chan bool)
|
||||||
em.closed = false
|
em.closed = false
|
||||||
|
@ -66,10 +65,10 @@ func (em *manager) initialize() {
|
||||||
|
|
||||||
// Subscribe takes an eventType and an Channel and associates them in the eventBus. All future events of that type
|
// Subscribe takes an eventType and an Channel and associates them in the eventBus. All future events of that type
|
||||||
// will be sent to the eventChannel.
|
// will be sent to the eventChannel.
|
||||||
func (em *manager) Subscribe(eventType Type, eventChannel chan Event) {
|
func (em *manager) Subscribe(eventType Type, queue Queue) {
|
||||||
em.mapMutex.Lock()
|
em.mapMutex.Lock()
|
||||||
defer em.mapMutex.Unlock()
|
defer em.mapMutex.Unlock()
|
||||||
em.subscribers[eventType] = append(em.subscribers[eventType], eventChannel)
|
em.subscribers[eventType] = append(em.subscribers[eventType], queue.InChan())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish takes an Event and sends it to the internal eventBus where it is distributed to all Subscribers
|
// Publish takes an Event and sends it to the internal eventBus where it is distributed to all Subscribers
|
||||||
|
@ -101,13 +100,7 @@ func (em *manager) eventBus() {
|
||||||
|
|
||||||
// Send the event to any subscribers to that event type
|
// Send the event to any subscribers to that event type
|
||||||
for _, subscriber := range subscribers {
|
for _, subscriber := range subscribers {
|
||||||
select {
|
subscriber <- event
|
||||||
case subscriber <- event:
|
|
||||||
log.Debugf("Sending %v to %v", event.EventType, subscriber)
|
|
||||||
default:
|
|
||||||
log.Errorf("Failed to send %v to %v. The subsystem might be running too slow!", event.EventType, subscriber)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@ func TestEventManager(t *testing.T) {
|
||||||
|
|
||||||
// We need to make this buffer at least 1, otherwise we will log an error!
|
// We need to make this buffer at least 1, otherwise we will log an error!
|
||||||
testChan := make(chan Event, 1)
|
testChan := make(chan Event, 1)
|
||||||
eventManager.Subscribe("TEST", testChan)
|
simpleQueue := &simpleQueue{testChan}
|
||||||
|
eventManager.Subscribe("TEST", simpleQueue)
|
||||||
eventManager.Publish(Event{EventType: "TEST", Data: map[Field]string{"Value": "Hello World"}})
|
eventManager.Publish(Event{EventType: "TEST", Data: map[Field]string{"Value": "Hello World"}})
|
||||||
|
|
||||||
event := <-testChan
|
event := <-testChan
|
||||||
|
@ -31,7 +32,8 @@ func TestEventManagerOverflow(t *testing.T) {
|
||||||
|
|
||||||
// Explicitly setting this to 0 log an error!
|
// Explicitly setting this to 0 log an error!
|
||||||
testChan := make(chan Event)
|
testChan := make(chan Event)
|
||||||
eventManager.Subscribe("TEST", testChan)
|
simpleQueue := &simpleQueue{testChan}
|
||||||
|
eventManager.Subscribe("TEST", simpleQueue)
|
||||||
eventManager.Publish(Event{EventType: "TEST"})
|
eventManager.Publish(Event{EventType: "TEST"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,15 +41,15 @@ func TestEventManagerMultiple(t *testing.T) {
|
||||||
log.SetLevel(log.LevelDebug)
|
log.SetLevel(log.LevelDebug)
|
||||||
eventManager := NewEventManager()
|
eventManager := NewEventManager()
|
||||||
|
|
||||||
groupEventQueue := NewEventQueue(10)
|
groupEventQueue := NewQueue()
|
||||||
peerEventQueue := NewEventQueue(10)
|
peerEventQueue := NewQueue()
|
||||||
allEventQueue := NewEventQueue(10)
|
allEventQueue := NewQueue()
|
||||||
|
|
||||||
eventManager.Subscribe("PeerEvent", peerEventQueue.EventChannel)
|
eventManager.Subscribe("PeerEvent", peerEventQueue)
|
||||||
eventManager.Subscribe("GroupEvent", groupEventQueue.EventChannel)
|
eventManager.Subscribe("GroupEvent", groupEventQueue)
|
||||||
eventManager.Subscribe("PeerEvent", allEventQueue.EventChannel)
|
eventManager.Subscribe("PeerEvent", allEventQueue)
|
||||||
eventManager.Subscribe("GroupEvent", allEventQueue.EventChannel)
|
eventManager.Subscribe("GroupEvent", allEventQueue)
|
||||||
eventManager.Subscribe("ErrorEvent", allEventQueue.EventChannel)
|
eventManager.Subscribe("ErrorEvent", allEventQueue)
|
||||||
|
|
||||||
eventManager.Publish(Event{EventType: "PeerEvent", Data: map[Field]string{"Value": "Hello World Peer"}})
|
eventManager.Publish(Event{EventType: "PeerEvent", Data: map[Field]string{"Value": "Hello World Peer"}})
|
||||||
eventManager.Publish(Event{EventType: "GroupEvent", Data: map[Field]string{"Value": "Hello World Group"}})
|
eventManager.Publish(Event{EventType: "GroupEvent", Data: map[Field]string{"Value": "Hello World Group"}})
|
||||||
|
@ -63,9 +65,9 @@ func TestEventManagerMultiple(t *testing.T) {
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
assertLength(groupEventQueue.Backlog(), 1, "Group Event Queue Length")
|
assertLength(groupEventQueue.Len(), 1, "Group Event Queue Length")
|
||||||
assertLength(peerEventQueue.Backlog(), 2, "Peer Event Queue Length")
|
assertLength(peerEventQueue.Len(), 2, "Peer Event Queue Length")
|
||||||
assertLength(allEventQueue.Backlog(), 4, "All Event Queue Length")
|
assertLength(allEventQueue.Len(), 4, "All Event Queue Length")
|
||||||
|
|
||||||
checkEvent := func(eventType Type, expected Type, label string) {
|
checkEvent := func(eventType Type, expected Type, label string) {
|
||||||
if eventType != expected {
|
if eventType != expected {
|
||||||
|
|
|
@ -29,8 +29,8 @@ func (ipcm *ipcManager) PublishLocal(ev Event) {
|
||||||
ipcm.manager.Publish(ev)
|
ipcm.manager.Publish(ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ipcm *ipcManager) Subscribe(eventType Type, eventChan chan Event) {
|
func (ipcm *ipcManager) Subscribe(eventType Type, queue Queue) {
|
||||||
ipcm.manager.Subscribe(eventType, eventChan)
|
ipcm.manager.Subscribe(eventType, queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ipcm *ipcManager) Shutdown() {
|
func (ipcm *ipcManager) Shutdown() {
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package event
|
||||||
|
|
||||||
|
/*
|
||||||
|
This package is taken from https://github.com/eapache/channels
|
||||||
|
as per their suggestion we are not importing the entire package and instead cherry picking and adapting what is needed
|
||||||
|
|
||||||
|
It is covered by the MIT License https://github.com/eapache/channels/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
// infiniteChannel implements the Channel interface with an infinite buffer between the input and the output.
|
||||||
|
type infiniteChannel struct {
|
||||||
|
input, output chan Event
|
||||||
|
length chan int
|
||||||
|
buffer *infiniteQueue
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInfiniteChannel() *infiniteChannel {
|
||||||
|
ch := &infiniteChannel{
|
||||||
|
input: make(chan Event),
|
||||||
|
output: make(chan Event),
|
||||||
|
length: make(chan int),
|
||||||
|
buffer: newInfinitQueue(),
|
||||||
|
}
|
||||||
|
go ch.infiniteBuffer()
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *infiniteChannel) In() chan<- Event {
|
||||||
|
return ch.input
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *infiniteChannel) Out() <-chan Event {
|
||||||
|
return ch.output
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *infiniteChannel) Len() int {
|
||||||
|
return <-ch.length
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *infiniteChannel) Close() {
|
||||||
|
close(ch.input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *infiniteChannel) infiniteBuffer() {
|
||||||
|
var input, output chan Event
|
||||||
|
var next Event
|
||||||
|
input = ch.input
|
||||||
|
|
||||||
|
for input != nil || output != nil {
|
||||||
|
select {
|
||||||
|
case elem, open := <-input:
|
||||||
|
if open {
|
||||||
|
ch.buffer.Add(elem)
|
||||||
|
} else {
|
||||||
|
input = nil
|
||||||
|
}
|
||||||
|
case output <- next:
|
||||||
|
ch.buffer.Remove()
|
||||||
|
case ch.length <- ch.buffer.Length():
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch.buffer.Length() > 0 {
|
||||||
|
output = ch.output
|
||||||
|
next = ch.buffer.Peek()
|
||||||
|
} else {
|
||||||
|
output = nil
|
||||||
|
//next = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ch.output)
|
||||||
|
close(ch.length)
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
package event
|
||||||
|
|
||||||
|
/*
|
||||||
|
This package is taken from https://github.com/eapache/channels
|
||||||
|
as per their suggestion we are not importing the entire package and instead cherry picking and adapting what is needed
|
||||||
|
|
||||||
|
It is covered by the MIT License https://github.com/eapache/channels/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Package queue provides a fast, ring-buffer queue based on the version suggested by Dariusz Górecki.
|
||||||
|
Using this instead of other, simpler, queue implementations (slice+append or linked list) provides
|
||||||
|
substantial memory and time benefits, and fewer GC pauses.
|
||||||
|
The queue implemented here is as fast as it is for an additional reason: it is *not* thread-safe.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// minQueueLen is smallest capacity that queue may have.
|
||||||
|
// Must be power of 2 for bitwise modulus: x % n == x & (n - 1).
|
||||||
|
const minQueueLen = 16
|
||||||
|
|
||||||
|
// Queue represents a single instance of the queue data structure.
|
||||||
|
type infiniteQueue struct {
|
||||||
|
buf []Event
|
||||||
|
head, tail, count int
|
||||||
|
}
|
||||||
|
|
||||||
|
// New constructs and returns a new Queue.
|
||||||
|
func newInfinitQueue() *infiniteQueue {
|
||||||
|
return &infiniteQueue{
|
||||||
|
buf: make([]Event, minQueueLen),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the number of elements currently stored in the queue.
|
||||||
|
func (q *infiniteQueue) Length() int {
|
||||||
|
return q.count
|
||||||
|
}
|
||||||
|
|
||||||
|
// resizes the queue to fit exactly twice its current contents
|
||||||
|
// this can result in shrinking if the queue is less than half-full
|
||||||
|
func (q *infiniteQueue) resize() {
|
||||||
|
newBuf := make([]Event, q.count<<1)
|
||||||
|
|
||||||
|
if q.tail > q.head {
|
||||||
|
copy(newBuf, q.buf[q.head:q.tail])
|
||||||
|
} else {
|
||||||
|
n := copy(newBuf, q.buf[q.head:])
|
||||||
|
copy(newBuf[n:], q.buf[:q.tail])
|
||||||
|
}
|
||||||
|
|
||||||
|
q.head = 0
|
||||||
|
q.tail = q.count
|
||||||
|
q.buf = newBuf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add puts an element on the end of the queue.
|
||||||
|
func (q *infiniteQueue) Add(elem Event) {
|
||||||
|
if q.count == len(q.buf) {
|
||||||
|
q.resize()
|
||||||
|
}
|
||||||
|
|
||||||
|
q.buf[q.tail] = elem
|
||||||
|
// bitwise modulus
|
||||||
|
q.tail = (q.tail + 1) & (len(q.buf) - 1)
|
||||||
|
q.count++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peek returns the element at the head of the queue. This call panics
|
||||||
|
// if the queue is empty.
|
||||||
|
func (q *infiniteQueue) Peek() Event {
|
||||||
|
if q.count <= 0 {
|
||||||
|
panic("queue: Peek() called on empty queue")
|
||||||
|
}
|
||||||
|
return q.buf[q.head]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the element at index i in the queue. If the index is
|
||||||
|
// invalid, the call will panic. This method accepts both positive and
|
||||||
|
// negative index values. Index 0 refers to the first element, and
|
||||||
|
// index -1 refers to the last.
|
||||||
|
func (q *infiniteQueue) Get(i int) Event {
|
||||||
|
// If indexing backwards, convert to positive index.
|
||||||
|
if i < 0 {
|
||||||
|
i += q.count
|
||||||
|
}
|
||||||
|
if i < 0 || i >= q.count {
|
||||||
|
panic("queue: Get() called with index out of range")
|
||||||
|
}
|
||||||
|
// bitwise modulus
|
||||||
|
return q.buf[(q.head+i)&(len(q.buf)-1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes and returns the element from the front of the queue. If the
|
||||||
|
// queue is empty, the call will panic.
|
||||||
|
func (q *infiniteQueue) Remove() Event {
|
||||||
|
if q.count <= 0 {
|
||||||
|
panic("queue: Remove() called on empty queue")
|
||||||
|
}
|
||||||
|
ret := q.buf[q.head]
|
||||||
|
//q.buf[q.head] = nil
|
||||||
|
// bitwise modulus
|
||||||
|
q.head = (q.head + 1) & (len(q.buf) - 1)
|
||||||
|
q.count--
|
||||||
|
// Resize down if buffer 1/4 full.
|
||||||
|
if len(q.buf) > minQueueLen && (q.count<<2) == len(q.buf) {
|
||||||
|
q.resize()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ type cwtchPeer struct {
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
shutdown bool
|
shutdown bool
|
||||||
|
|
||||||
queue *event.Queue
|
queue event.Queue
|
||||||
eventBus event.Manager
|
eventBus event.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,14 +84,14 @@ func FromProfile(profile *model.Profile) CwtchPeer {
|
||||||
|
|
||||||
// Init instantiates a cwtchPeer
|
// Init instantiates a cwtchPeer
|
||||||
func (cp *cwtchPeer) Init(eventBus event.Manager) {
|
func (cp *cwtchPeer) Init(eventBus event.Manager) {
|
||||||
cp.queue = event.NewEventQueue(100)
|
cp.queue = event.NewQueue()
|
||||||
go cp.eventHandler()
|
go cp.eventHandler()
|
||||||
|
|
||||||
cp.eventBus = eventBus
|
cp.eventBus = eventBus
|
||||||
cp.eventBus.Subscribe(event.EncryptedGroupMessage, cp.queue.EventChannel)
|
cp.eventBus.Subscribe(event.EncryptedGroupMessage, cp.queue)
|
||||||
cp.eventBus.Subscribe(event.NewGroupInvite, cp.queue.EventChannel)
|
cp.eventBus.Subscribe(event.NewGroupInvite, cp.queue)
|
||||||
cp.eventBus.Subscribe(event.ServerStateChange, cp.queue.EventChannel)
|
cp.eventBus.Subscribe(event.ServerStateChange, cp.queue)
|
||||||
cp.eventBus.Subscribe(event.PeerStateChange, cp.queue.EventChannel)
|
cp.eventBus.Subscribe(event.PeerStateChange, cp.queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportGroup intializes a group from an imported source rather than a peer invite
|
// ImportGroup intializes a group from an imported source rather than a peer invite
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type engine struct {
|
type engine struct {
|
||||||
queue *event.Queue
|
queue event.Queue
|
||||||
connectionsManager *Manager
|
connectionsManager *Manager
|
||||||
|
|
||||||
// Engine Attributes
|
// Engine Attributes
|
||||||
|
@ -55,7 +55,7 @@ func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateK
|
||||||
engine := new(engine)
|
engine := new(engine)
|
||||||
engine.identity = identity
|
engine.identity = identity
|
||||||
engine.privateKey = privateKey
|
engine.privateKey = privateKey
|
||||||
engine.queue = event.NewEventQueue(100)
|
engine.queue = event.NewQueue()
|
||||||
go engine.eventHandler()
|
go engine.eventHandler()
|
||||||
|
|
||||||
engine.acn = acn
|
engine.acn = acn
|
||||||
|
@ -68,17 +68,17 @@ func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateK
|
||||||
|
|
||||||
engine.eventManager = eventManager
|
engine.eventManager = eventManager
|
||||||
|
|
||||||
engine.eventManager.Subscribe(event.ProtocolEngineStartListen, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.ProtocolEngineStartListen, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.PeerRequest, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.PeerRequest, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.InvitePeerToGroup, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.InvitePeerToGroup, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.JoinServer, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.JoinServer, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.SendMessageToGroup, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.SendMessageToGroup, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.SendMessageToPeer, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.SendMessageToPeer, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.DeleteContact, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.DeleteContact, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.DeleteGroup, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.DeleteGroup, engine.queue)
|
||||||
|
|
||||||
engine.eventManager.Subscribe(event.BlockPeer, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.BlockPeer, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.UnblockPeer, engine.queue.EventChannel)
|
engine.eventManager.Subscribe(event.UnblockPeer, engine.queue)
|
||||||
for _, peer := range blockedPeers {
|
for _, peer := range blockedPeers {
|
||||||
engine.blocked.Store(peer, true)
|
engine.blocked.Store(peer, true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ func (cpfc *CwtchPeerFetchChannel) Packet(data []byte) {
|
||||||
gm := csp.GetGroupMessage()
|
gm := csp.GetGroupMessage()
|
||||||
// We create a new go routine here to avoid leaking any information about processing time
|
// We create a new go routine here to avoid leaking any information about processing time
|
||||||
// TODO Server can probably try to use this to DoS a peer
|
// TODO Server can probably try to use this to DoS a peer
|
||||||
go cpfc.Handler.HandleGroupMessage(gm)
|
cpfc.Handler.HandleGroupMessage(gm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ type profileStore struct {
|
||||||
password string
|
password string
|
||||||
profile *model.Profile
|
profile *model.Profile
|
||||||
eventManager event.Manager
|
eventManager event.Manager
|
||||||
queue *event.Queue
|
queue event.Queue
|
||||||
writer bool
|
writer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,27 +38,28 @@ type ProfileStore interface {
|
||||||
func NewProfileWriterStore(eventManager event.Manager, directory, password string, profile *model.Profile) ProfileStore {
|
func NewProfileWriterStore(eventManager event.Manager, directory, password string, profile *model.Profile) ProfileStore {
|
||||||
os.Mkdir(directory, 0700)
|
os.Mkdir(directory, 0700)
|
||||||
ps := &profileStore{fs: NewFileStore(directory, profileFilename, password), password: password, directory: directory, profile: profile, eventManager: eventManager, streamStores: map[string]StreamStore{}, writer: true}
|
ps := &profileStore{fs: NewFileStore(directory, profileFilename, password), password: password, directory: directory, profile: profile, eventManager: eventManager, streamStores: map[string]StreamStore{}, writer: true}
|
||||||
ps.queue = event.NewEventQueue(100)
|
//ps.queue = event.NewQueue(100)
|
||||||
|
ps.queue = event.NewQueue()
|
||||||
if profile != nil {
|
if profile != nil {
|
||||||
ps.save()
|
ps.save()
|
||||||
}
|
}
|
||||||
go ps.eventHandler()
|
go ps.eventHandler()
|
||||||
|
|
||||||
ps.eventManager.Subscribe(event.BlockPeer, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.BlockPeer, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.UnblockPeer, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.UnblockPeer, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.PeerCreated, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.PeerCreated, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.GroupCreated, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.GroupCreated, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetProfileName, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.SetProfileName, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetAttribute, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.SetAttribute, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetPeerAttribute, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.SetPeerAttribute, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetGroupAttribute, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.SetGroupAttribute, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.AcceptGroupInvite, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.AcceptGroupInvite, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.NewGroupInvite, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.NewGroupInvite, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.NewMessageFromGroup, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.NewMessageFromGroup, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.PeerStateChange, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.PeerStateChange, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.ServerStateChange, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.ServerStateChange, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.DeleteContact, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.DeleteContact, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.DeleteGroup, ps.queue.EventChannel)
|
ps.eventManager.Subscribe(event.DeleteGroup, ps.queue)
|
||||||
|
|
||||||
return ps
|
return ps
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue