From f537fb4f76936c66523c65c0cadcab0916db3b40 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Mon, 1 Jan 2018 10:06:58 -0800 Subject: [PATCH] Adding Simple Application Broadcast & Features Enabled --- application/application.go | 33 ++++++++++++++++++++++++- application/examples/commandbot/main.go | 5 ++-- application/examples/echobot/main.go | 2 +- connection/autoconnectionhandler.go | 8 ++++++ connection/connection.go | 28 ++++++++++++++++----- connection/handler.go | 2 ++ connection/outboundconnectionhandler.go | 4 +++ 7 files changed, 71 insertions(+), 11 deletions(-) diff --git a/application/application.go b/application/application.go index 49b7fbe..2ed4dd6 100644 --- a/application/application.go +++ b/application/application.go @@ -9,6 +9,7 @@ import ( "log" "net" "time" + "sync" ) // RicochetApplication bundles many useful constructs that are @@ -18,7 +19,11 @@ type RicochetApplication struct { privateKey *rsa.PrivateKey chatMessageHandler func(*RicochetApplicationInstance, uint32, time.Time, string) chatMessageAckHandler func(*RicochetApplicationInstance, uint32) + onConnected func(*RicochetApplicationInstance) + onLeave func(*RicochetApplicationInstance) l net.Listener + instances []*RicochetApplicationInstance + lock sync.Mutex } type RicochetApplicationInstance struct { @@ -27,6 +32,7 @@ type RicochetApplicationInstance struct { RemoteHostname string ChatMessageHandler func(*RicochetApplicationInstance, uint32, time.Time, string) ChatMessageAckHandler func(*RicochetApplicationInstance, uint32) + OnLeave func(*RicochetApplicationInstance) } func (rai *RicochetApplicationInstance) ContactRequest(name string, message string) string { @@ -83,6 +89,14 @@ func (ra *RicochetApplication) OnChatMessageAck(call func(*RicochetApplicationIn ra.chatMessageAckHandler = call } +func (ra *RicochetApplication) OnConnected(call func(*RicochetApplicationInstance)) { + ra.onConnected = call +} + +func (ra *RicochetApplication) OnLeave(call func(*RicochetApplicationInstance)) { + ra.onLeave = call +} + func (ra *RicochetApplication) handleConnection(conn net.Conn) { rc, err := goricochet.NegotiateVersionInbound(conn) if err != nil { @@ -99,13 +113,14 @@ func (ra *RicochetApplication) handleConnection(conn net.Conn) { conn.Close() return } - + rc.TraceLog(true) rai := new(RicochetApplicationInstance) rai.Init() rai.RemoteHostname = rc.RemoteHostname rai.connection = rc rai.ChatMessageHandler = ra.chatMessageHandler rai.ChatMessageAckHandler = ra.chatMessageAckHandler + rai.OnLeave = ra.onLeave rai.RegisterChannelHandler("im.ricochet.contact.request", func() channels.Handler { contact := new(channels.ContactRequestChannel) @@ -117,9 +132,25 @@ func (ra *RicochetApplication) handleConnection(conn net.Conn) { chat.Handler = rai return chat }) + ra.lock.Lock() + ra.instances = append(ra.instances, rai) + ra.lock.Unlock() + go ra.onConnected(rai) rc.Process(rai) } +func (rai *RicochetApplicationInstance) OnClosed(err error) { + rai.OnLeave(rai) +} + +func (ra *RicochetApplication) Broadcast(message string) { + ra.lock.Lock() + for _,rai := range ra.instances { + rai.SendChatMessage(message) + } + ra.lock.Unlock() +} + func (ra *RicochetApplication) Shutdown() { log.Printf("Closing") ra.l.Close() diff --git a/application/examples/commandbot/main.go b/application/examples/commandbot/main.go index c4efb21..97897e2 100644 --- a/application/examples/commandbot/main.go +++ b/application/examples/commandbot/main.go @@ -23,9 +23,8 @@ func main() { commandbot.Init(pk, new(application.AcceptAllContactManager)) commandbot.OnChatMessage(func(rai *application.RicochetApplicationInstance, id uint32, timestamp time.Time, message string) { - if message == "/" { - rai.SendChatMessage(message) - } + log.Printf("message from %v - %v", rai.RemoteHostname, message) + go echobot.Broadcast(rai.RemoteHostname + " " + message) }) log.Printf("commandbot listening on %s", l.Addr().String()) commandbot.Run(l) diff --git a/application/examples/echobot/main.go b/application/examples/echobot/main.go index 5162062..ec3bb25 100644 --- a/application/examples/echobot/main.go +++ b/application/examples/echobot/main.go @@ -24,7 +24,7 @@ func main() { echobot.Init(pk, new(application.AcceptAllContactManager)) echobot.OnChatMessage(func(rai *application.RicochetApplicationInstance, id uint32, timestamp time.Time, message string) { log.Printf("message from %v - %v", rai.RemoteHostname, message) - rai.SendChatMessage(message) + go echobot.Broadcast(rai.RemoteHostname + " " + message) }) log.Printf("echobot listening on %s", l.Addr().String()) echobot.Run(l) diff --git a/connection/autoconnectionhandler.go b/connection/autoconnectionhandler.go index cbb96c3..e3fc887 100644 --- a/connection/autoconnectionhandler.go +++ b/connection/autoconnectionhandler.go @@ -34,6 +34,14 @@ func (ach *AutoConnectionHandler) OnReady(oc *Connection) { func (ach *AutoConnectionHandler) OnClosed(err error) { } +func (ach *AutoConnectionHandler) GetSupportedChannelTypes() []string { + supported := []string{} + for k,_ := range ach.handlerMap { + supported = append(supported, k) + } + return supported +} + // RegisterChannelHandler ... func (ach *AutoConnectionHandler) RegisterChannelHandler(ctype string, handler func() channels.Handler) { _, exists := ach.handlerMap[ctype] diff --git a/connection/connection.go b/connection/connection.go index 1d28dfe..bb323ef 100644 --- a/connection/connection.go +++ b/connection/connection.go @@ -44,6 +44,7 @@ type Connection struct { IsInbound bool Authentication map[string]bool RemoteHostname string + SupportChannels []string } func (rc *Connection) init() { @@ -458,18 +459,33 @@ func (rc *Connection) controlPacket(handler Handler, res *Protocol_Data_Control. rc.SendRicochetPacket(rc.Conn, 0, raw) } } else if res.GetEnableFeatures() != nil { - rc.traceLog("received features enabled packet") + rc.traceLog("received enable features packet") + featuresToEnable := res.GetEnableFeatures().GetFeature() + supportChannels := handler.GetSupportedChannelTypes() + result := []string{} + for _,v := range featuresToEnable { + for _,s := range supportChannels { + if v == s { + result = append(result, v) + } + } + } messageBuilder := new(utils.MessageBuilder) - raw := messageBuilder.FeaturesEnabled([]string{}) - rc.traceLog("sending featured enabled empty response") + raw := messageBuilder.FeaturesEnabled(result) + rc.traceLog(fmt.Sprintf("sending featured enabled: %v", result)) rc.SendRicochetPacket(rc.Conn, 0, raw) } else if res.GetFeaturesEnabled() != nil { - // TODO We should never send out an enabled features - // request. - rc.traceLog("sending unsolicited features enabled response") + rc.SupportChannels = res.GetFeaturesEnabled().GetFeature() + rc.traceLog(fmt.Sprintf("connection supports: %v", rc.SupportChannels)) } } +func (rc *Connection) EnableFeatures(features []string) { + messageBuilder := new(utils.MessageBuilder) + raw := messageBuilder.EnableFeatures(features) + rc.SendRicochetPacket(rc.Conn, 0, raw) +} + func (rc *Connection) traceLog(message string) { if rc.trace { log.Printf(message) diff --git a/connection/handler.go b/connection/handler.go index b2fd78b..e38c7f9 100644 --- a/connection/handler.go +++ b/connection/handler.go @@ -25,4 +25,6 @@ type Handler interface { // A non-nil return from this function does not guarantee that the channel // will be opened. OnOpenChannelRequest(ctype string) (channels.Handler, error) + + GetSupportedChannelTypes() []string } diff --git a/connection/outboundconnectionhandler.go b/connection/outboundconnectionhandler.go index a84413e..44bb2f3 100644 --- a/connection/outboundconnectionhandler.go +++ b/connection/outboundconnectionhandler.go @@ -88,3 +88,7 @@ func (och *OutboundConnectionHandler) ProcessAuthAsClient(identity identity.Iden } return false, utils.ServerRejectedClientConnectionError } + +func (och *OutboundConnectionHandler) GetSupportChannels() { + +}