2017-07-04 18:29:11 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-11-09 21:33:35 +00:00
|
|
|
"crypto/rand"
|
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go"
|
2018-06-08 21:54:31 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
2018-11-09 21:33:35 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
|
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
2018-11-30 21:04:38 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
2017-07-04 18:29:11 +00:00
|
|
|
"time"
|
2018-11-09 21:33:35 +00:00
|
|
|
|
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
|
|
|
"golang.org/x/crypto/ed25519"
|
2018-11-30 21:04:38 +00:00
|
|
|
"os"
|
2017-07-04 18:29:11 +00:00
|
|
|
)
|
|
|
|
|
2018-01-08 00:51:46 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2018-05-30 17:51:40 +00:00
|
|
|
// We always want bidirectional chat channels
|
|
|
|
func (ebi *EchoBotInstance) OpenInbound() {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Degubln("OpenInbound() ChatChannel handler called...")
|
2018-05-30 17:51:40 +00:00
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-08 00:51:46 +00:00
|
|
|
func (ebi *EchoBotInstance) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("message from %v - %v", ebi.rai.RemoteHostname, message)
|
2018-10-27 09:17:35 +00:00
|
|
|
ebi.SendChatMessage(ebi.rai, ebi.rai.RemoteHostname+" "+message)
|
2018-01-08 00:51:46 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ebi *EchoBotInstance) ChatMessageAck(messageID uint32, accepted bool) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ebi *EchoBotInstance) SendChatMessage(rai *application.ApplicationInstance, message string) {
|
2018-10-27 09:17:35 +00:00
|
|
|
ebi.rai.Connection.Do(func() error {
|
|
|
|
channel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
2018-01-08 00:51:46 +00:00
|
|
|
if channel != nil {
|
|
|
|
chatchannel, ok := channel.Handler.(*channels.ChatChannel)
|
|
|
|
if ok {
|
|
|
|
chatchannel.SendMessage(message)
|
|
|
|
}
|
2018-10-27 09:17:35 +00:00
|
|
|
} //TODO: else?
|
2018-01-08 00:51:46 +00:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-07-04 18:29:11 +00:00
|
|
|
func main() {
|
2018-10-26 02:20:58 +00:00
|
|
|
////////////
|
|
|
|
// SERVER //
|
|
|
|
////////////
|
2018-11-30 21:04:38 +00:00
|
|
|
log.SetLevel(log.LevelInfo)
|
|
|
|
log.AddEverythingFromPattern("connectivity")
|
2018-10-26 02:20:58 +00:00
|
|
|
|
2017-07-04 18:29:11 +00:00
|
|
|
echobot := new(application.RicochetApplication)
|
2018-10-26 02:20:58 +00:00
|
|
|
cpubk, cprivk, err := ed25519.GenerateKey(rand.Reader)
|
2017-07-04 18:29:11 +00:00
|
|
|
|
2018-11-22 06:15:35 +00:00
|
|
|
acn, err := connectivity.StartTor(".", "")
|
2017-07-04 18:29:11 +00:00
|
|
|
if err != nil {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("Unable to start Tor: %v", err)
|
|
|
|
os.Exit(1)
|
2017-07-04 18:29:11 +00:00
|
|
|
}
|
2018-11-22 06:15:35 +00:00
|
|
|
defer acn.Close()
|
2017-07-04 18:29:11 +00:00
|
|
|
|
2018-11-22 06:15:35 +00:00
|
|
|
listenService, err := acn.Listen(cprivk, application.RicochetPort)
|
2017-07-04 18:29:11 +00:00
|
|
|
|
|
|
|
if err != nil {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("error setting up onion service: %v", err)
|
|
|
|
os.Exit(1)
|
2017-07-04 18:29:11 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 00:51:46 +00:00
|
|
|
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
|
|
|
|
}
|
2017-07-04 18:29:11 +00:00
|
|
|
})
|
2018-01-08 00:51:46 +00:00
|
|
|
|
2018-11-22 06:15:35 +00:00
|
|
|
echobot.Init(acn, "echobot", identity.InitializeV3("echobot", &cprivk, &cpubk), af, new(application.AcceptAllContactManager))
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("echobot listening on %v", listenService.AddressFull())
|
2018-11-09 21:33:35 +00:00
|
|
|
go echobot.Run(listenService)
|
2018-10-26 02:20:58 +00:00
|
|
|
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infoln("counting to five ...")
|
2018-10-26 02:20:58 +00:00
|
|
|
time.Sleep(time.Second * 5)
|
|
|
|
|
|
|
|
////////////
|
|
|
|
// CLIENT //
|
|
|
|
////////////
|
|
|
|
|
|
|
|
//alicebot should nominally be in another package to prevent initializing it directly
|
2018-11-22 06:15:35 +00:00
|
|
|
alice := NewAliceBot(acn, listenService.AddressIdentity())
|
2018-10-26 02:20:58 +00:00
|
|
|
alice.SendMessage("be gay")
|
|
|
|
alice.SendMessage("do crime")
|
|
|
|
|
|
|
|
// stick around and see what happens
|
|
|
|
time.Sleep(time.Second * 30)
|
|
|
|
}
|
|
|
|
|
2018-11-22 06:15:35 +00:00
|
|
|
func NewAliceBot(acn connectivity.ACN, onion string) alicebot {
|
2018-10-26 02:20:58 +00:00
|
|
|
alice := alicebot{}
|
|
|
|
alice.messages = make(map[uint32]string)
|
|
|
|
|
|
|
|
var err error
|
|
|
|
alice.pub, alice.priv, err = ed25519.GenerateKey(rand.Reader)
|
|
|
|
if err != nil {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("[alice] error generating key: %v", err)
|
|
|
|
os.Exit(1)
|
2018-10-26 02:20:58 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 06:15:35 +00:00
|
|
|
rc, err := goricochet.Open(acn, onion)
|
2018-10-26 02:20:58 +00:00
|
|
|
if err != nil {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("[alice] error connecting to echobot: %v", err)
|
|
|
|
os.Exit(1)
|
2018-10-26 02:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_, err = connection.HandleOutboundConnection(rc).ProcessAuthAsV3Client(identity.InitializeV3("alice", &alice.priv, &alice.pub))
|
|
|
|
if err != nil {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("[alice] failed to authenticate connection: %v", err)
|
|
|
|
os.Exit(1)
|
2018-10-26 02:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("[alice] requesting channel...")
|
2018-10-26 02:20:58 +00:00
|
|
|
alice.rc.Do(func() error {
|
|
|
|
chatchannel := channels.ChatChannel{}
|
|
|
|
chatchannel.Handler = &alice
|
|
|
|
|
|
|
|
_, err := alice.rc.RequestOpenChannel("im.ricochet.chat", &chatchannel)
|
|
|
|
if err != nil {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("failed requestopenchannel: %v", err)
|
|
|
|
os.Exit(1)
|
2018-10-26 02:20:58 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
return alice
|
|
|
|
}
|
|
|
|
|
|
|
|
type alicebot struct {
|
|
|
|
messages map[uint32]string
|
2018-11-09 21:33:35 +00:00
|
|
|
pub ed25519.PublicKey
|
|
|
|
priv ed25519.PrivateKey
|
|
|
|
mID int
|
|
|
|
rc *connection.Connection
|
2017-07-04 18:29:11 +00:00
|
|
|
}
|
2018-10-26 02:20:58 +00:00
|
|
|
|
|
|
|
func (this *alicebot) SendMessage(message string) {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("[alice] sending...")
|
2018-10-26 02:20:58 +00:00
|
|
|
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 {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("[alice] sending '%s' to echobot", message)
|
2018-10-26 02:20:58 +00:00
|
|
|
this.messages[peerchannel.SendMessage(message)] = message
|
|
|
|
} else {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("couldn't cast channel:")
|
|
|
|
os.Exit(1)
|
2018-10-26 02:20:58 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Errorf("couldn't create channel")
|
|
|
|
os.Exit(1)
|
2018-10-26 02:20:58 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *alicebot) OpenInbound() {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("[alice] inbound connection established")
|
2018-10-26 02:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *alicebot) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("[alice] got message from echobot: %s", message)
|
2018-10-26 02:20:58 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *alicebot) ChatMessageAck(messageID uint32, accepted bool) {
|
2018-11-30 21:04:38 +00:00
|
|
|
log.Infof("[alice] message \"%s\" ack'd", this.messages[messageID])
|
2018-11-09 21:33:35 +00:00
|
|
|
}
|