pull/62/head
Darien Raymond 2015-12-11 14:56:10 +00:00
parent a540d7dc99
commit b6ed26aedf
8 changed files with 162 additions and 2 deletions

View File

@ -10,6 +10,7 @@ import (
type SpaceController struct { type SpaceController struct {
packetDispatcher internal.PacketDispatcherWithContext packetDispatcher internal.PacketDispatcherWithContext
dnsCache internal.DnsCacheWithContext dnsCache internal.DnsCacheWithContext
pubsub internal.PubsubWithContext
} }
func New() *SpaceController { func New() *SpaceController {
@ -24,8 +25,12 @@ func (this *SpaceController) Bind(object interface{}) {
if dnsCache, ok := object.(internal.DnsCacheWithContext); ok { if dnsCache, ok := object.(internal.DnsCacheWithContext); ok {
this.dnsCache = dnsCache this.dnsCache = dnsCache
} }
if pubsub, ok := object.(internal.PubsubWithContext); ok {
this.pubsub = pubsub
}
} }
func (this *SpaceController) ForContext(tag string) app.Space { func (this *SpaceController) ForContext(tag string) app.Space {
return internal.NewSpace(tag, this.packetDispatcher, this.dnsCache) return internal.NewSpace(tag, this.packetDispatcher, this.dnsCache, this.pubsub)
} }

23
app/internal/pubsub.go Normal file
View File

@ -0,0 +1,23 @@
package internal
import (
"github.com/v2ray/v2ray-core/app"
)
type PubsubWithContext interface {
Publish(context app.Context, topic string, message app.PubsubMessage)
Subscribe(context app.Context, topic string, handler app.TopicHandler)
}
type contextedPubsub struct {
context app.Context
pubsub PubsubWithContext
}
func (this *contextedPubsub) Publish(topic string, message app.PubsubMessage) {
this.pubsub.Publish(this.context, topic, message)
}
func (this *contextedPubsub) Subscribe(topic string, handler app.TopicHandler) {
this.pubsub.Subscribe(this.context, topic, handler)
}

View File

@ -7,14 +7,16 @@ import (
type Space struct { type Space struct {
packetDispatcher PacketDispatcherWithContext packetDispatcher PacketDispatcherWithContext
dnsCache DnsCacheWithContext dnsCache DnsCacheWithContext
pubsub PubsubWithContext
tag string tag string
} }
func NewSpace(tag string, packetDispatcher PacketDispatcherWithContext, dnsCache DnsCacheWithContext) *Space { func NewSpace(tag string, packetDispatcher PacketDispatcherWithContext, dnsCache DnsCacheWithContext, pubsub PubsubWithContext) *Space {
return &Space{ return &Space{
tag: tag, tag: tag,
packetDispatcher: packetDispatcher, packetDispatcher: packetDispatcher,
dnsCache: dnsCache, dnsCache: dnsCache,
pubsub: pubsub,
} }
} }
@ -43,3 +45,16 @@ func (this *Space) DnsCache() app.DnsCache {
}, },
} }
} }
func (this *Space) HasPubsub() bool {
return this.pubsub != nil
}
func (this *Space) Pubsub() app.Pubsub {
return &contextedPubsub{
pubsub: this.pubsub,
context: &contextImpl{
callerTag: this.tag,
},
}
}

9
app/pubsub.go Normal file
View File

@ -0,0 +1,9 @@
package app
type PubsubMessage []byte
type TopicHandler func(PubsubMessage)
type Pubsub interface {
Publish(topic string, message PubsubMessage)
Subscribe(topic string, handler TopicHandler)
}

64
app/pubsub/pubsub.go Normal file
View File

@ -0,0 +1,64 @@
package pubsub
import (
"sync"
"github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/app/internal"
)
type TopicHandlerList struct {
sync.RWMutex
handlers []app.TopicHandler
}
func NewTopicHandlerList(handlers ...app.TopicHandler) *TopicHandlerList {
return &TopicHandlerList{
handlers: handlers,
}
}
func (this *TopicHandlerList) Add(handler app.TopicHandler) {
this.Lock()
this.handlers = append(this.handlers, handler)
this.Unlock()
}
func (this *TopicHandlerList) Dispatch(message app.PubsubMessage) {
this.RLock()
for _, handler := range this.handlers {
go handler(message)
}
this.RUnlock()
}
type Pubsub struct {
topics map[string]*TopicHandlerList
sync.RWMutex
}
func New() internal.PubsubWithContext {
return &Pubsub{
topics: make(map[string]*TopicHandlerList),
}
}
func (this *Pubsub) Publish(context app.Context, topic string, message app.PubsubMessage) {
this.RLock()
list, found := this.topics[topic]
this.RUnlock()
if found {
list.Dispatch(message)
}
}
func (this *Pubsub) Subscribe(context app.Context, topic string, handler app.TopicHandler) {
this.Lock()
defer this.Unlock()
if list, found := this.topics[topic]; found {
list.Add(handler)
} else {
this.topics[topic] = NewTopicHandlerList(handler)
}
}

38
app/pubsub/pubsub_test.go Normal file
View File

@ -0,0 +1,38 @@
package pubsub_test
import (
"testing"
"time"
"github.com/v2ray/v2ray-core/app"
. "github.com/v2ray/v2ray-core/app/pubsub"
apptesting "github.com/v2ray/v2ray-core/app/testing"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestPubsub(t *testing.T) {
v2testing.Current(t)
messages := make(map[string]app.PubsubMessage)
pubsub := New()
pubsub.Subscribe(&apptesting.Context{}, "t1", func(message app.PubsubMessage) {
messages["t1"] = message
})
pubsub.Subscribe(&apptesting.Context{}, "t2", func(message app.PubsubMessage) {
messages["t2"] = message
})
message := app.PubsubMessage([]byte("This is a pubsub message."))
pubsub.Publish(&apptesting.Context{}, "t2", message)
<-time.Tick(time.Second)
_, found := messages["t1"]
assert.Bool(found).IsFalse()
actualMessage, found := messages["t2"]
assert.Bool(found).IsTrue()
assert.StringLiteral(string(actualMessage)).Equals(string(message))
}

View File

@ -13,4 +13,7 @@ type Space interface {
HasDnsCache() bool HasDnsCache() bool
DnsCache() DnsCache DnsCache() DnsCache
HasPubsub() bool
Pubsub() Pubsub
} }

View File

@ -0,0 +1,3 @@
package command
type ResponseCmd byte