Merge branch 'echobotv3' of openprivacy/libricochet-go into master
This commit is contained in:
commit
49faf95ee7
|
@ -27,6 +27,22 @@ func (af *ApplicationInstanceFactory) AddHandler(ctype string, chandler func(*Ap
|
|||
af.handlerMap[ctype] = chandler
|
||||
}
|
||||
|
||||
func (af *ApplicationInstanceFactory) GetHandlers() []string {
|
||||
keys := make([]string, len(af.handlerMap))
|
||||
|
||||
i := 0
|
||||
for k := range af.handlerMap {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
func (af *ApplicationInstanceFactory) GetHandler(ctype string) func(*ApplicationInstance) func() channels.Handler {
|
||||
return af.handlerMap[ctype]
|
||||
}
|
||||
|
||||
// GetApplicationInstance builds a new application instance using a connection as a base.
|
||||
func (af *ApplicationInstanceFactory) GetApplicationInstance(rc *connection.Connection) *ApplicationInstance {
|
||||
rai := new(ApplicationInstance)
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type EchoBotInstance struct {
|
||||
rai *application.ApplicationInstance
|
||||
ra *application.RicochetApplication
|
||||
}
|
||||
|
||||
func (ebi *EchoBotInstance) Init(rai *application.ApplicationInstance, ra *application.RicochetApplication) {
|
||||
ebi.rai = rai
|
||||
ebi.ra = ra
|
||||
}
|
||||
|
||||
// We always want bidirectional chat channels
|
||||
func (ebi *EchoBotInstance) OpenInbound() {
|
||||
log.Println("OpenInbound() ChatChannel handler called...")
|
||||
outboutChatChannel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
||||
if outboutChatChannel == nil {
|
||||
ebi.rai.Connection.Do(func() error {
|
||||
ebi.rai.Connection.RequestOpenChannel("im.ricochet.chat",
|
||||
&channels.ChatChannel{
|
||||
Handler: ebi,
|
||||
})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (ebi *EchoBotInstance) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
||||
log.Printf("message from %v - %v", ebi.rai.RemoteHostname, message)
|
||||
go ebi.ra.Broadcast(func(rai *application.ApplicationInstance) {
|
||||
ebi.SendChatMessage(rai, ebi.rai.RemoteHostname+" "+message)
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
func (ebi *EchoBotInstance) ChatMessageAck(messageID uint32, accepted bool) {
|
||||
|
||||
}
|
||||
|
||||
func (ebi *EchoBotInstance) SendChatMessage(rai *application.ApplicationInstance, message string) {
|
||||
rai.Connection.Do(func() error {
|
||||
channel := rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
||||
if channel != nil {
|
||||
chatchannel, ok := channel.Handler.(*channels.ChatChannel)
|
||||
if ok {
|
||||
chatchannel.SendMessage(message)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
echobot := new(application.RicochetApplication)
|
||||
pk, err := utils.LoadPrivateKeyFromFile("./testing/private_key")
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("error reading private key file: %v", err)
|
||||
}
|
||||
|
||||
l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", pk, 9878)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("error setting up onion service: %v", err)
|
||||
}
|
||||
|
||||
af := application.ApplicationInstanceFactory{}
|
||||
af.Init()
|
||||
af.AddHandler("im.ricochet.chat", func(rai *application.ApplicationInstance) func() channels.Handler {
|
||||
ebi := new(EchoBotInstance)
|
||||
ebi.Init(rai, echobot)
|
||||
return func() channels.Handler {
|
||||
chat := new(channels.ChatChannel)
|
||||
chat.Handler = ebi
|
||||
return chat
|
||||
}
|
||||
})
|
||||
|
||||
echobot.Init("echobot", pk, af, new(application.AcceptAllContactManager))
|
||||
log.Printf("echobot listening on %s", l.Addr().String())
|
||||
echobot.Run(l)
|
||||
}
|
|
@ -3,9 +3,14 @@ package main
|
|||
import (
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"log"
|
||||
"time"
|
||||
"crypto/rand"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
|
||||
)
|
||||
|
||||
type EchoBotInstance struct {
|
||||
|
@ -35,9 +40,7 @@ func (ebi *EchoBotInstance) OpenInbound() {
|
|||
|
||||
func (ebi *EchoBotInstance) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
||||
log.Printf("message from %v - %v", ebi.rai.RemoteHostname, message)
|
||||
go ebi.ra.Broadcast(func(rai *application.ApplicationInstance) {
|
||||
ebi.SendChatMessage(rai, ebi.rai.RemoteHostname+" "+message)
|
||||
})
|
||||
ebi.SendChatMessage(ebi.rai, ebi.rai.RemoteHostname+" "+message)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -46,27 +49,31 @@ func (ebi *EchoBotInstance) ChatMessageAck(messageID uint32, accepted bool) {
|
|||
}
|
||||
|
||||
func (ebi *EchoBotInstance) SendChatMessage(rai *application.ApplicationInstance, message string) {
|
||||
rai.Connection.Do(func() error {
|
||||
channel := rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
||||
ebi.rai.Connection.Do(func() error {
|
||||
channel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
||||
if channel != nil {
|
||||
chatchannel, ok := channel.Handler.(*channels.ChatChannel)
|
||||
if ok {
|
||||
chatchannel.SendMessage(message)
|
||||
}
|
||||
}
|
||||
} //TODO: else?
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
////////////
|
||||
// SERVER //
|
||||
////////////
|
||||
|
||||
echobot := new(application.RicochetApplication)
|
||||
pk, err := utils.LoadPrivateKeyFromFile("./testing/private_key")
|
||||
cpubk, cprivk, err := ed25519.GenerateKey(rand.Reader)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("error reading private key file: %v", err)
|
||||
log.Fatalf("error generating random key: %v", err)
|
||||
}
|
||||
|
||||
l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", pk, 9878)
|
||||
l, err := application.SetupOnionV3("127.0.0.1:9051", "tcp4", "", cprivk, utils.GetTorV3Hostname(cpubk), 9878)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("error setting up onion service: %v", err)
|
||||
|
@ -84,7 +91,112 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
echobot.Init("echobot", pk, af, new(application.AcceptAllContactManager))
|
||||
echobot.InitV3("echobot", identity.InitializeV3("echobot", &cprivk, &cpubk), af, new(application.AcceptAllContactManager))
|
||||
log.Printf("echobot listening on %s", l.Addr().String())
|
||||
echobot.Run(l)
|
||||
go echobot.Run(l)
|
||||
|
||||
log.Printf("counting to five...")
|
||||
time.Sleep(time.Second * 5)
|
||||
|
||||
////////////
|
||||
// CLIENT //
|
||||
////////////
|
||||
|
||||
//alicebot should nominally be in another package to prevent initializing it directly
|
||||
alice := NewAliceBot(l.Addr().String()[:56])
|
||||
alice.SendMessage("be gay")
|
||||
alice.SendMessage("do crime")
|
||||
|
||||
// stick around and see what happens
|
||||
time.Sleep(time.Second * 30)
|
||||
}
|
||||
|
||||
|
||||
func NewAliceBot(onion string) alicebot {
|
||||
alice := alicebot{}
|
||||
alice.messages = make(map[uint32]string)
|
||||
|
||||
var err error
|
||||
alice.pub, alice.priv, err = ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
log.Fatalf("[alice] error generating key: %v", err)
|
||||
}
|
||||
|
||||
rc, err := goricochet.Open(onion)
|
||||
if err != nil {
|
||||
log.Fatalf("[alice] error connecting to echobot: %v", err)
|
||||
}
|
||||
|
||||
rc.TraceLog(false)
|
||||
_, err = connection.HandleOutboundConnection(rc).ProcessAuthAsV3Client(identity.InitializeV3("alice", &alice.priv, &alice.pub))
|
||||
if err != nil {
|
||||
log.Fatalf("[alice] failed to authenticate connection: %v", err)
|
||||
}
|
||||
|
||||
alice.rc = rc
|
||||
|
||||
ach := connection.AutoConnectionHandler{}
|
||||
ach.Init()
|
||||
|
||||
ach.RegisterChannelHandler("im.ricochet.chat", func() channels.Handler {
|
||||
chat := new(channels.ChatChannel)
|
||||
chat.Handler = &alice
|
||||
return chat
|
||||
})
|
||||
|
||||
go alice.rc.Process(&ach)
|
||||
|
||||
log.Printf("[alice] requesting channel...")
|
||||
alice.rc.Do(func() error {
|
||||
chatchannel := channels.ChatChannel{}
|
||||
chatchannel.Handler = &alice
|
||||
|
||||
_, err := alice.rc.RequestOpenChannel("im.ricochet.chat", &chatchannel)
|
||||
if err != nil {
|
||||
log.Fatalf("failed requestopenchannel: %v", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return alice
|
||||
}
|
||||
|
||||
type alicebot struct {
|
||||
messages map[uint32]string
|
||||
pub ed25519.PublicKey
|
||||
priv ed25519.PrivateKey
|
||||
mID int
|
||||
rc *connection.Connection
|
||||
}
|
||||
|
||||
func (this *alicebot) SendMessage(message string) {
|
||||
log.Printf("[alice] sending...")
|
||||
this.rc.Do(func() error {
|
||||
channel := this.rc.Channel("im.ricochet.chat", channels.Outbound)
|
||||
if channel != nil {
|
||||
peerchannel, ok := channel.Handler.(*channels.ChatChannel)
|
||||
if ok {
|
||||
log.Printf("[alice] sending '%s' to echobot", message)
|
||||
this.messages[peerchannel.SendMessage(message)] = message
|
||||
} else {
|
||||
log.Fatalf("couldn't cast channel:")
|
||||
}
|
||||
} else {
|
||||
log.Fatalf("couldn't create channel")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (this *alicebot) OpenInbound() {
|
||||
log.Printf("[alice] inbound connection established")
|
||||
}
|
||||
|
||||
func (this *alicebot) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
||||
log.Printf("[alice] got message from echobot: %s", message)
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *alicebot) ChatMessageAck(messageID uint32, accepted bool) {
|
||||
log.Printf("[alice] message \"%s\" ack'd", this.messages[messageID])
|
||||
}
|
|
@ -91,7 +91,7 @@ func (cc *ChatChannel) Bidirectional() bool {
|
|||
|
||||
// RequiresAuthentication - chat channels require hidden service auth
|
||||
func (cc *ChatChannel) RequiresAuthentication() string {
|
||||
return "im.ricochet.auth.hidden-service"
|
||||
return "im.ricochet.auth.3dh"
|
||||
}
|
||||
|
||||
// OpenInbound is the first method called for an inbound channel request.
|
||||
|
|
|
@ -27,4 +27,4 @@ type Handler interface {
|
|||
OnOpenChannelRequest(ctype string) (channels.Handler, error)
|
||||
|
||||
GetSupportedChannelTypes() []string
|
||||
}
|
||||
}
|
Reference in New Issue