cwtch/peer/cwtch_peer.go

189 lines
4.8 KiB
Go
Raw Normal View History

package peer
2018-03-09 20:44:13 +00:00
import (
"encoding/json"
"git.mascherari.press/cwtch/model"
"git.mascherari.press/cwtch/protocol"
"github.com/s-rah/go-ricochet"
"github.com/s-rah/go-ricochet/application"
"github.com/s-rah/go-ricochet/channels"
"github.com/s-rah/go-ricochet/connection"
"github.com/s-rah/go-ricochet/identity"
"io/ioutil"
"sync"
)
/**
PeerConnectionPool
Background thread running Process()
Pointer to connections
Move CwtchPeerChannel under peer/
Write tests for Peer Channel
*/
2018-03-09 20:44:13 +00:00
type CwtchPeerInstance struct {
rai *application.ApplicationInstance
ra *application.RicochetApplication
}
func (cpi *CwtchPeerInstance) Init(rai *application.ApplicationInstance, ra *application.RicochetApplication) {
cpi.rai = rai
cpi.ra = ra
}
type CwtchPeer struct {
connection.AutoConnectionHandler
Profile *model.Profile
PendingContacts []string
PendingInvites map[string][]string
mutex sync.Mutex
2018-03-12 18:43:51 +00:00
Log chan string `json:"-"`
2018-03-09 20:44:13 +00:00
}
func NewCwtchPeer(name string) *CwtchPeer {
peer := new(CwtchPeer)
peer.Profile = model.GenerateNewProfile(name)
peer.PendingInvites = make(map[string][]string)
peer.Log = make(chan string)
peer.Init()
return peer
}
func (cp *CwtchPeer) Save(profilefile string) error {
cp.mutex.Lock()
2018-03-12 18:43:51 +00:00
bytes,_ := json.Marshal(cp)
2018-03-09 20:44:13 +00:00
err := ioutil.WriteFile(profilefile, bytes, 0600)
cp.mutex.Unlock()
return err
}
func LoadCwtchPeer(profilefile string) (*CwtchPeer, error) {
bytes, _ := ioutil.ReadFile(profilefile)
peer := new(CwtchPeer)
err := json.Unmarshal(bytes, &peer)
return peer, err
}
// AddContactRequest is the entry point for CwtchPeer relationships
func (cp *CwtchPeer) AddContactRequest(onion string) {
cp.mutex.Lock()
cp.PendingContacts = append(cp.PendingContacts, onion)
go cp.EstablishContact(onion)
cp.mutex.Unlock()
}
// InviteOnionToGroup kicks off the invite process
func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) {
cp.mutex.Lock()
cp.PendingInvites[onion] = append(cp.PendingInvites[onion], groupid)
cp.mutex.Unlock()
}
func (cp *CwtchPeer) PeerListen(onion string) {
}
func (cp *CwtchPeer) JoinServer(onion string) {
}
func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) {
// Lookup Group
// Lookup Sever Connection
// If no server connection, spin off server connection
// Else group.EncryptMessage(message) and send result to server
}
func (cp *CwtchPeer) Listen() error {
cwtchpeer := new(application.RicochetApplication)
l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", cp.Profile.OnionPrivateKey, 9878)
if err != nil {
return err
}
af := application.ApplicationInstanceFactory{}
af.Init()
af.AddHandler("im.cwtch.peer", func(rai *application.ApplicationInstance) func() channels.Handler {
cpi := new(CwtchPeerInstance)
cpi.Init(rai, cwtchpeer)
return func() channels.Handler {
chat := new(protocol.CwtchPeerChannel)
chat.Handler = &CwtchPeerHandler{Onion: rai.RemoteHostname, Peer: cp}
return chat
}
})
cwtchpeer.Init(cp.Profile.OnionPrivateKey, af, new(application.AcceptAllContactManager))
cp.Log <- "Running cwtch peer on " + l.Addr().String()
cwtchpeer.Run(l)
return nil
}
func (cp *CwtchPeer) EstablishContact(onion string) {
rc, err := goricochet.Open(onion)
if err == nil {
cp.Log <- "Connected to " + onion
cp.RegisterChannelHandler("im.cwtch.peer", func() channels.Handler {
peer := new(protocol.CwtchPeerChannel)
peer.Handler = &CwtchPeerHandler{Onion: onion, Peer: cp}
return peer
})
if err == nil {
_, err := connection.HandleOutboundConnection(rc).ProcessAuthAsClient(identity.Initialize("", cp.Profile.OnionPrivateKey))
if err == nil {
cp.Log <- "Authed to " + onion
go func() {
rc.Do(func() error {
rc.RequestOpenChannel("im.cwtch.peer", &protocol.CwtchPeerChannel{
Handler: &CwtchPeerHandler{Onion: onion, Peer: cp},
})
return nil
})
sendIdentity := func(message []byte) {
rc.Do(func() error {
channel := rc.Channel("im.cwtch.peer", channels.Outbound)
if channel != nil {
cwtchchannel, ok := channel.Handler.(*protocol.CwtchPeerChannel)
if ok {
cwtchchannel.SendMessage(message)
}
} else {
cp.Log <- "Error finding cwtch channel " + onion
}
return nil
})
}
sendIdentity(cp.Profile.GetCwtchIdentityPacket())
}()
rc.Process(cp)
}
}
}
// onion is offline
// TODO Sleep, Wake, Retry (assuming contact still exists)
}
type CwtchPeerHandler struct {
Onion string
Peer *CwtchPeer
}
func (cph *CwtchPeerHandler) ClientIdentity(ci *protocol.CwtchIdentity) {
cph.Peer.Log <- "Received Client Identity from " + cph.Onion + " " + ci.String()
cph.Peer.Profile.AddCwtchIdentity(cph.Onion, *ci)
}
func (cph *CwtchPeerHandler) HandleGroupInvite() {
}
func (cph *CwtchPeerHandler) HandleGroupMessage(gm *protocol.GroupMessage) {
}