Encapsualting Profile behind Peer interface

This commit is contained in:
Sarah Jamie Lewis 2018-06-19 15:28:44 -07:00
parent 7f99747100
commit 89ffc737bc
8 changed files with 186 additions and 167 deletions

View File

@ -5,12 +5,12 @@ import (
"log" "log"
) )
// Application is a facade over a CwtchPeer that provides some wrapping logic. // Application is a facade over a cwtchPeer that provides some wrapping logic.
type Application struct { type Application struct {
Peer *peer.CwtchPeer Peer peer.CwtchPeerInterface
} }
// NewProfile creates a new CwtchPeer with a given name. // NewProfile creates a new cwtchPeer with a given name.
func (app *Application) NewProfile(name string, filename string) error { func (app *Application) NewProfile(name string, filename string) error {
profile := peer.NewCwtchPeer(name) profile := peer.NewCwtchPeer(name)
app.Peer = profile app.Peer = profile

View File

@ -62,8 +62,9 @@ func completer(d prompt.Document) []prompt.Suggest {
w := d.CurrentLine() w := d.CurrentLine()
if strings.HasPrefix(w, "send") || strings.HasPrefix(w, "timeline") { if strings.HasPrefix(w, "send") || strings.HasPrefix(w, "timeline") {
s = []prompt.Suggest{} s = []prompt.Suggest{}
groups := app.Peer.Profile.Groups groups := app.Peer.GetGroups()
for _, group := range groups { for _, groupID := range groups {
group := app.Peer.GetGroup(groupID)
s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer}) s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer})
} }
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
@ -71,8 +72,9 @@ func completer(d prompt.Document) []prompt.Suggest {
if strings.HasPrefix(w, "block") || strings.HasPrefix(w, "trust") { if strings.HasPrefix(w, "block") || strings.HasPrefix(w, "trust") {
s = []prompt.Suggest{} s = []prompt.Suggest{}
contacts := app.Peer.Profile.Contacts contacts := app.Peer.GetContacts()
for _, contact := range contacts { for _, onion := range contacts {
contact := app.Peer.GetContact(onion)
s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name}) s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name})
} }
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
@ -82,15 +84,17 @@ func completer(d prompt.Document) []prompt.Suggest {
if d.FindStartOfPreviousWordWithSpace() == 0 { if d.FindStartOfPreviousWordWithSpace() == 0 {
s = []prompt.Suggest{} s = []prompt.Suggest{}
contacts := app.Peer.Profile.Contacts contacts := app.Peer.GetContacts()
for _, contact := range contacts { for _, onion := range contacts {
contact := app.Peer.GetContact(onion)
s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name}) s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name})
} }
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
} }
s = []prompt.Suggest{} s = []prompt.Suggest{}
groups := app.Peer.Profile.Groups groups := app.Peer.GetGroups()
for _, group := range groups { for _, groupID := range groups {
group := app.Peer.GetGroup(groupID)
if group.Owner == "self" { if group.Owner == "self" {
s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer}) s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer})
} }
@ -100,8 +104,9 @@ func completer(d prompt.Document) []prompt.Suggest {
if strings.HasPrefix(w, "accept-invite") { if strings.HasPrefix(w, "accept-invite") {
s = []prompt.Suggest{} s = []prompt.Suggest{}
groups := app.Peer.Profile.Groups groups := app.Peer.GetGroups()
for _, group := range groups { for _, groupID := range groups {
group := app.Peer.GetGroup(groupID)
if group.Accepted == false { if group.Accepted == false {
s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer}) s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer})
} }
@ -159,7 +164,7 @@ func main() {
for !quit { for !quit {
profile := "unset" profile := "unset"
if app.Peer != nil { if app.Peer != nil {
profile = app.Peer.Profile.Name profile = app.Peer.GetProfile().Name
} }
prmpt := fmt.Sprintf("cwtch [%v]> ", profile) prmpt := fmt.Sprintf("cwtch [%v]> ", profile)
@ -200,7 +205,7 @@ func main() {
case "info": case "info":
if app.Peer != nil { if app.Peer != nil {
fmt.Printf("Address cwtch:%v\n", app.Peer.Profile.Onion) fmt.Printf("Address cwtch:%v\n", app.Peer.GetProfile().Onion)
} else { } else {
fmt.Printf("Profile needs to be set\n") fmt.Printf("Profile needs to be set\n")
} }
@ -222,12 +227,15 @@ func main() {
fmt.Printf("Name: %v Status: %v\n", s, st) fmt.Printf("Name: %v Status: %v\n", s, st)
} }
case "contacts": case "contacts":
for _, c := range app.Peer.Profile.Contacts { contacts := app.Peer.GetContacts()
for _, onion := range contacts {
c := app.Peer.GetContact(onion)
fmt.Printf("Name: %v Onion: %v Trusted: %v\n", c.Name, c.Onion, c.Trusted) fmt.Printf("Name: %v Onion: %v Trusted: %v\n", c.Name, c.Onion, c.Trusted)
} }
case "groups": case "groups":
for gid, g := range app.Peer.Profile.Groups { for _, gid := range app.Peer.GetGroups() {
fmt.Printf("Group Id: %v Owner: %v Accepted:%v \n", gid, g.Owner, g.Accepted) g := app.Peer.GetGroup(gid)
fmt.Printf("Group Id: %v Owner: %v Accepted:%v\n", gid, g.Owner, g.Accepted)
} }
case "trust": case "trust":
if len(commands) == 2 { if len(commands) == 2 {
@ -249,7 +257,7 @@ func main() {
fmt.Printf("Error: %v\n", err) fmt.Printf("Error: %v\n", err)
} else { } else {
app.Peer.Save(profilefile) app.Peer.Save(profilefile)
group := app.Peer.Profile.GetGroupByGroupID(groupID) group := app.Peer.GetGroup(groupID)
if group == nil { if group == nil {
fmt.Printf("Error: group does not exist\n") fmt.Printf("Error: group does not exist\n")
} else { } else {
@ -272,11 +280,11 @@ func main() {
case "new-group": case "new-group":
if len(commands) == 2 { if len(commands) == 2 {
fmt.Printf("Setting up a new group on server:%v\n", commands[1]) fmt.Printf("Setting up a new group on server:%v\n", commands[1])
id, _, err := app.Peer.Profile.StartGroup(commands[1]) id, _, err := app.Peer.StartGroup(commands[1])
if err == nil { if err == nil {
fmt.Printf("New Group [%v] created for server %v\n", id, commands[1]) fmt.Printf("New Group [%v] created for server %v\n", id, commands[1])
app.Peer.Save(profilefile) app.Peer.Save(profilefile)
group := app.Peer.Profile.GetGroupByGroupID(id) group := app.Peer.GetGroup(id)
if group == nil { if group == nil {
fmt.Printf("Error: group does not exist\n") fmt.Printf("Error: group does not exist\n")
} else { } else {
@ -300,7 +308,7 @@ func main() {
} }
case "timeline": case "timeline":
if len(commands) == 2 { if len(commands) == 2 {
group := app.Peer.Profile.GetGroupByGroupID(commands[1]) group := app.Peer.GetGroup(commands[1])
if group == nil { if group == nil {
fmt.Printf("Error: group does not exist\n") fmt.Printf("Error: group does not exist\n")
} else { } else {
@ -311,12 +319,12 @@ func main() {
verified = "verified" verified = "verified"
} }
p, ok := app.Peer.Profile.Contacts[m.PeerID] p := app.Peer.GetContact(m.PeerID)
name := "unknown" name := "unknown"
if ok { if p != nil {
name = p.Name name = p.Name
} else if app.Peer.Profile.Onion == m.PeerID { } else if app.Peer.GetProfile().Onion == m.PeerID {
name = app.Peer.Profile.Name name = app.Peer.GetProfile().Name
} }
fmt.Printf("%v %v (%v): %v [%s]\n", m.Timestamp, name, m.PeerID, m.Message, verified) fmt.Printf("%v %v (%v): %v [%s]\n", m.Timestamp, name, m.PeerID, m.Message, verified)
@ -327,7 +335,7 @@ func main() {
} }
case "export-group": case "export-group":
if len(commands) == 2 { if len(commands) == 2 {
group := app.Peer.Profile.GetGroupByGroupID(commands[1]) group := app.Peer.GetGroup(commands[1])
if group == nil { if group == nil {
fmt.Printf("Error: group does not exist\n") fmt.Printf("Error: group does not exist\n")
} else { } else {
@ -345,7 +353,7 @@ func main() {
} }
case "sendlots": case "sendlots":
if len(commands) == 2 { if len(commands) == 2 {
group := app.Peer.Profile.GetGroupByGroupID(commands[1]) group := app.Peer.GetGroup(commands[1])
if group == nil { if group == nil {
fmt.Printf("Error: group does not exist\n") fmt.Printf("Error: group does not exist\n")
} else { } else {
@ -365,7 +373,7 @@ func main() {
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
found := false found := false
for _, m := range timeline { for _, m := range timeline {
if m.Message == fmt.Sprintf("this is message %v", i) && m.PeerID == app.Peer.Profile.Onion { if m.Message == fmt.Sprintf("this is message %v", i) && m.PeerID == app.Peer.GetProfile().Onion {
found = true found = true
latency := m.Received.Sub(m.Timestamp) latency := m.Received.Sub(m.Timestamp)
fmt.Printf("Latency for Message %v was %v\n", i, latency) fmt.Printf("Latency for Message %v was %v\n", i, latency)

View File

@ -1,89 +0,0 @@
package main
import (
"cwtch.im/cwtch/peer"
"fmt"
"github.com/marcusolsson/tui-go"
"io/ioutil"
"log"
"os"
"strings"
"time"
)
func main() {
log.SetOutput(ioutil.Discard)
peer := peer.NewCwtchPeer("cwtchbot")
groupID, err := peer.ImportGroup(os.Args[1])
peer.AcceptInvite(groupID)
group := peer.Profile.GetGroupByGroupID(groupID)
peer.JoinServer(group.GroupServer)
history := tui.NewVBox()
historyScroll := tui.NewScrollArea(history)
historyScroll.SetAutoscrollToBottom(true)
historyBox := tui.NewVBox(historyScroll)
historyBox.SetBorder(true)
historyBox.SetTitle("cwtchat:" + group.GroupID + "@" + group.GroupServer)
input := tui.NewEntry()
input.SetFocused(true)
input.SetSizePolicy(tui.Expanding, tui.Maximum)
inputBox := tui.NewHBox(input)
inputBox.SetBorder(true)
inputBox.SetSizePolicy(tui.Expanding, tui.Maximum)
chat := tui.NewVBox(historyBox, inputBox)
chat.SetSizePolicy(tui.Expanding, tui.Expanding)
input.OnSubmit(func(e *tui.Entry) {
if strings.Trim(e.Text(), " ") != "" {
go peer.SendMessageToGroup(groupID, e.Text())
e.SetText("")
}
})
seen := make(map[string]bool)
root := tui.NewHBox(chat)
ui, err := tui.New(root)
if err != nil {
log.Fatal(err)
}
ui.SetKeybinding("Esc", func() { ui.Quit() })
go func() {
for {
group = peer.Profile.GetGroupByGroupID(groupID)
if group == nil {
log.Fatalf("group does not exist")
}
timeline := group.GetTimeline()
for _, m := range timeline {
old, _ := seen[string(m.Signature)]
if !old {
ui.Update(func() {
history.Append(tui.NewHBox(
tui.NewLabel(m.Timestamp.Format("15:04")),
tui.NewPadder(1, 0, tui.NewLabel(fmt.Sprintf("<%s>", m.PeerID))),
tui.NewLabel(m.Message),
tui.NewSpacer(),
))
})
seen[string(m.Signature)] = true
}
}
time.Sleep(time.Second * 1)
}
}()
if err := ui.Run(); err != nil {
log.Fatal(err)
}
}

View File

@ -103,6 +103,30 @@ func (p *Profile) AcceptInvite(groupID string) (err error) {
return return
} }
// GetGroups returns an unordered list of group IDs associated with this profile.
func (p *Profile) GetGroups() []string {
p.lock.Lock()
defer p.lock.Unlock()
var keys []string
for onion := range p.Groups {
keys = append(keys, onion)
}
return keys
}
// GetContacts returns an unordered list of contact onions associated with this profile.
func (p *Profile) GetContacts() []string {
p.lock.Lock()
defer p.lock.Unlock()
var keys []string
for onion := range p.Contacts {
if onion != p.Onion {
keys = append(keys, onion)
}
}
return keys
}
// BlockPeer blocks a contact // BlockPeer blocks a contact
func (p *Profile) BlockPeer(onion string) (err error) { func (p *Profile) BlockPeer(onion string) (err error) {
p.lock.Lock() p.lock.Lock()

View File

@ -22,6 +22,10 @@ func TestProfileIdentity(t *testing.T) {
t.Errorf("alice should have added sarah as a contact %v", alice.Contacts) t.Errorf("alice should have added sarah as a contact %v", alice.Contacts)
} }
if len(alice.GetContacts()) != 1 {
t.Errorf("alice should be only contact: %v", alice.GetContacts())
}
t.Logf("%v", alice) t.Logf("%v", alice)
} }
@ -94,6 +98,10 @@ func TestProfileGroup(t *testing.T) {
gci := &protocol.CwtchPeerPacket{} gci := &protocol.CwtchPeerPacket{}
proto.Unmarshal(invite, gci) proto.Unmarshal(invite, gci)
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion) sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
if len(sarah.GetGroups()) != 1 {
t.Errorf("sarah should only be in 1 group instead: %v", sarah.GetGroups())
}
group := alice.GetGroupByGroupID(gid) group := alice.GetGroupByGroupID(gid)
sarah.AcceptInvite(group.GroupID) sarah.AcceptInvite(group.GroupID)
c, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID) c, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID)

View File

@ -20,8 +20,8 @@ import (
"sync" "sync"
) )
// CwtchPeer manages incoming and outgoing connections and all processing for a Cwtch Peer // cwtchPeer manages incoming and outgoing connections and all processing for a Cwtch Peer
type CwtchPeer struct { type cwtchPeer struct {
connection.AutoConnectionHandler connection.AutoConnectionHandler
Profile *model.Profile Profile *model.Profile
app *application.RicochetApplication app *application.RicochetApplication
@ -31,7 +31,41 @@ type CwtchPeer struct {
profilefile string profilefile string
} }
func (cp *CwtchPeer) setup() { // CwtchPeerInterface provides us with a way of testing systems built on top of cwtch without having to
// directly implement a cwtchPeer.
type CwtchPeerInterface interface {
Save(string) error
PeerWithOnion(string)
InviteOnionToGroup(string, string) error
TrustPeer(string) error
BlockPeer(string) error
AcceptInvite(string) error
RejectInvite(string)
JoinServer(string)
SendMessageToGroup(string, string) error
GetProfile() *model.Profile
GetPeers() map[string]connections.ConnectionState
GetServers() map[string]connections.ConnectionState
StartGroup(string) (string, []byte, error)
ImportGroup(string) (string, error)
ExportGroup(string) (string, error)
GetGroup(string) *model.Group
GetGroups() []string
GetContacts() []string
GetContact(string) *model.PublicProfile
Listen() error
Shutdown()
}
func (cp *cwtchPeer) setup() {
cp.Log = make(chan string) cp.Log = make(chan string)
cp.connectionsManager = connections.NewConnectionsManager() cp.connectionsManager = connections.NewConnectionsManager()
cp.Init() cp.Init()
@ -51,16 +85,16 @@ func (cp *CwtchPeer) setup() {
} }
} }
// NewCwtchPeer creates and returns a new CwtchPeer with the given name. // NewCwtchPeer creates and returns a new cwtchPeer with the given name.
func NewCwtchPeer(name string) *CwtchPeer { func NewCwtchPeer(name string) CwtchPeerInterface {
cp := new(CwtchPeer) cp := new(cwtchPeer)
cp.Profile = model.GenerateNewProfile(name) cp.Profile = model.GenerateNewProfile(name)
cp.setup() cp.setup()
return cp return cp
} }
// Save saves the CwtchPeer profile state to a file. // Save saves the cwtchPeer profile state to a file.
func (cp *CwtchPeer) Save(profilefile string) error { func (cp *cwtchPeer) Save(profilefile string) error {
cp.mutex.Lock() cp.mutex.Lock()
bytes, _ := json.MarshalIndent(cp, "", "\t") bytes, _ := json.MarshalIndent(cp, "", "\t")
err := ioutil.WriteFile(profilefile, bytes, 0600) err := ioutil.WriteFile(profilefile, bytes, 0600)
@ -69,10 +103,10 @@ func (cp *CwtchPeer) Save(profilefile string) error {
return err return err
} }
// LoadCwtchPeer loads an existing CwtchPeer from a file. // LoadCwtchPeer loads an existing cwtchPeer from a file.
func LoadCwtchPeer(profilefile string) (*CwtchPeer, error) { func LoadCwtchPeer(profilefile string) (CwtchPeerInterface, error) {
bytes, _ := ioutil.ReadFile(profilefile) bytes, _ := ioutil.ReadFile(profilefile)
cp := new(CwtchPeer) cp := new(cwtchPeer)
err := json.Unmarshal(bytes, &cp) err := json.Unmarshal(bytes, &cp)
cp.setup() cp.setup()
cp.profilefile = profilefile cp.profilefile = profilefile
@ -80,7 +114,7 @@ func LoadCwtchPeer(profilefile string) (*CwtchPeer, error) {
} }
// ImportGroup intializes a group from an imported source rather than a peer invite // ImportGroup intializes a group from an imported source rather than a peer invite
func (cp *CwtchPeer) ImportGroup(exportedInvite string) (groupID string, err error) { func (cp *cwtchPeer) ImportGroup(exportedInvite string) (groupID string, err error) {
if strings.HasPrefix(exportedInvite, "torv2") { if strings.HasPrefix(exportedInvite, "torv2") {
data, err := base64.StdEncoding.DecodeString(exportedInvite[21+44:]) data, err := base64.StdEncoding.DecodeString(exportedInvite[21+44:])
if err == nil { if err == nil {
@ -104,7 +138,7 @@ func (cp *CwtchPeer) ImportGroup(exportedInvite string) (groupID string, err err
} }
// ExportGroup serializes a group invite so it can be given offline // ExportGroup serializes a group invite so it can be given offline
func (cp *CwtchPeer) ExportGroup(groupID string) (string, error) { func (cp *cwtchPeer) ExportGroup(groupID string) (string, error) {
group := cp.Profile.GetGroupByGroupID(groupID) group := cp.Profile.GetGroupByGroupID(groupID)
if group != nil { if group != nil {
invite, err := group.Invite() invite, err := group.Invite()
@ -116,13 +150,45 @@ func (cp *CwtchPeer) ExportGroup(groupID string) (string, error) {
return "", errors.New("group id could not be found") return "", errors.New("group id could not be found")
} }
// PeerWithOnion is the entry point for CwtchPeer relationships // StartGroup create a new group linked to the given server and returns the group ID, an invite or an error.
func (cp *CwtchPeer) PeerWithOnion(onion string) { func (cp *cwtchPeer) StartGroup(server string) (string, []byte, error) {
return cp.Profile.StartGroup(server)
}
// GetGroups returns an unordered list of all group IDs.
func (cp *cwtchPeer) GetGroups() []string {
return cp.Profile.GetGroups()
}
// GetGroup returns a pointer to a specific group, nil if no group exists.
func (cp *cwtchPeer) GetGroup(groupID string) *model.Group {
return cp.Profile.GetGroupByGroupID(groupID)
}
// GetContacts returns an unordered list of onions
func (cp *cwtchPeer) GetContacts() []string {
return cp.Profile.GetContacts()
}
// GetContact returns a given contact, nil is no such contact exists
func (cp *cwtchPeer) GetContact(onion string) *model.PublicProfile {
contact, _ := cp.Profile.GetContact(onion)
return contact
}
// GetProfile returns the profile associated with this Peer.
// TODO While it is probably "safe", it is not really "safe", to call functions on this profile. This only exists to return things like Name and Onion,we should gate these.
func (cp *cwtchPeer) GetProfile() *model.Profile {
return cp.Profile
}
// PeerWithOnion is the entry point for cwtchPeer relationships
func (cp *cwtchPeer) PeerWithOnion(onion string) {
cp.connectionsManager.ManagePeerConnection(onion, cp.Profile) cp.connectionsManager.ManagePeerConnection(onion, cp.Profile)
} }
// InviteOnionToGroup kicks off the invite process // InviteOnionToGroup kicks off the invite process
func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) error { func (cp *cwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
group := cp.Profile.GetGroupByGroupID(groupid) group := cp.Profile.GetGroupByGroupID(groupid)
if group != nil { if group != nil {
@ -147,17 +213,17 @@ func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
} }
// ReceiveGroupMessage is a callback function that processes GroupMessages from a given server // ReceiveGroupMessage is a callback function that processes GroupMessages from a given server
func (cp *CwtchPeer) ReceiveGroupMessage(server string, gm *protocol.GroupMessage) { func (cp *cwtchPeer) ReceiveGroupMessage(server string, gm *protocol.GroupMessage) {
cp.Profile.AttemptDecryption(gm.Ciphertext) cp.Profile.AttemptDecryption(gm.Ciphertext)
} }
// JoinServer manages a new server connection with the given onion address // JoinServer manages a new server connection with the given onion address
func (cp *CwtchPeer) JoinServer(onion string) { func (cp *cwtchPeer) JoinServer(onion string) {
cp.connectionsManager.ManageServerConnection(onion, cp.ReceiveGroupMessage) cp.connectionsManager.ManageServerConnection(onion, cp.ReceiveGroupMessage)
} }
// SendMessageToGroup attemps to sent the given message to the given group id. // SendMessageToGroup attemps to sent the given message to the given group id.
func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) error { func (cp *cwtchPeer) SendMessageToGroup(groupid string, message string) error {
group := cp.Profile.GetGroupByGroupID(groupid) group := cp.Profile.GetGroupByGroupID(groupid)
if group == nil { if group == nil {
return errors.New("group does not exist") return errors.New("group does not exist")
@ -178,17 +244,17 @@ func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) error {
} }
// GetPeers returns a list of peer connections. // GetPeers returns a list of peer connections.
func (cp *CwtchPeer) GetPeers() map[string]connections.ConnectionState { func (cp *cwtchPeer) GetPeers() map[string]connections.ConnectionState {
return cp.connectionsManager.GetPeers() return cp.connectionsManager.GetPeers()
} }
// GetServers returns a list of server connections // GetServers returns a list of server connections
func (cp *CwtchPeer) GetServers() map[string]connections.ConnectionState { func (cp *cwtchPeer) GetServers() map[string]connections.ConnectionState {
return cp.connectionsManager.GetServers() return cp.connectionsManager.GetServers()
} }
// TrustPeer sets an existing peer relationship to trusted // TrustPeer sets an existing peer relationship to trusted
func (cp *CwtchPeer) TrustPeer(peer string) error { func (cp *cwtchPeer) TrustPeer(peer string) error {
err := cp.Profile.TrustPeer(peer) err := cp.Profile.TrustPeer(peer)
if err == nil { if err == nil {
cp.PeerWithOnion(peer) cp.PeerWithOnion(peer)
@ -197,35 +263,35 @@ func (cp *CwtchPeer) TrustPeer(peer string) error {
} }
// BlockPeer blocks an existing peer relationship. // BlockPeer blocks an existing peer relationship.
func (cp *CwtchPeer) BlockPeer(peer string) error { func (cp *cwtchPeer) BlockPeer(peer string) error {
err := cp.Profile.BlockPeer(peer) err := cp.Profile.BlockPeer(peer)
cp.connectionsManager.ClosePeerConnection(peer) cp.connectionsManager.ClosePeerConnection(peer)
return err return err
} }
// AcceptInvite accepts a given existing group invite // AcceptInvite accepts a given existing group invite
func (cp *CwtchPeer) AcceptInvite(groupID string) error { func (cp *cwtchPeer) AcceptInvite(groupID string) error {
return cp.Profile.AcceptInvite(groupID) return cp.Profile.AcceptInvite(groupID)
} }
// RejectInvite rejects a given group invite. // RejectInvite rejects a given group invite.
func (cp *CwtchPeer) RejectInvite(groupID string) { func (cp *cwtchPeer) RejectInvite(groupID string) {
cp.Profile.RejectInvite(groupID) cp.Profile.RejectInvite(groupID)
} }
// LookupContact returns that a contact is known and allowed to communicate for all cases. // LookupContact returns that a contact is known and allowed to communicate for all cases.
func (cp *CwtchPeer) LookupContact(hostname string, publicKey rsa.PublicKey) (allowed, known bool) { func (cp *cwtchPeer) LookupContact(hostname string, publicKey rsa.PublicKey) (allowed, known bool) {
blocked := cp.Profile.IsBlocked(hostname) blocked := cp.Profile.IsBlocked(hostname)
return !blocked, true return !blocked, true
} }
// ContactRequest needed to implement ContactRequestHandler Interface // ContactRequest needed to implement ContactRequestHandler Interface
func (cp *CwtchPeer) ContactRequest(name string, message string) string { func (cp *cwtchPeer) ContactRequest(name string, message string) string {
return "Accepted" return "Accepted"
} }
// Listen sets up an onion listener to process incoming cwtch messages // Listen sets up an onion listener to process incoming cwtch messages
func (cp *CwtchPeer) Listen() error { func (cp *cwtchPeer) Listen() error {
cwtchpeer := new(application.RicochetApplication) cwtchpeer := new(application.RicochetApplication)
l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", cp.Profile.OnionPrivateKey, 9878) l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", cp.Profile.OnionPrivateKey, 9878)
@ -252,7 +318,7 @@ func (cp *CwtchPeer) Listen() error {
} }
// Shutdown kills all connections and cleans up all goroutines for the peer // Shutdown kills all connections and cleans up all goroutines for the peer
func (cp *CwtchPeer) Shutdown() { func (cp *cwtchPeer) Shutdown() {
cp.connectionsManager.Shutdown() cp.connectionsManager.Shutdown()
cp.app.Shutdown() cp.app.Shutdown()
} }
@ -272,7 +338,7 @@ func (cpi *CwtchPeerInstance) Init(rai *application.ApplicationInstance, ra *app
// CwtchPeerHandler encapsulates handling of incoming CwtchPackets // CwtchPeerHandler encapsulates handling of incoming CwtchPackets
type CwtchPeerHandler struct { type CwtchPeerHandler struct {
Onion string Onion string
Peer *CwtchPeer Peer *cwtchPeer
} }
// ClientIdentity handles incoming ClientIdentity packets // ClientIdentity handles incoming ClientIdentity packets

View File

@ -10,16 +10,16 @@ func TestCwtchPeerGenerate(t *testing.T) {
alice.Save("./test_profile") alice.Save("./test_profile")
aliceLoaded, err := LoadCwtchPeer("./test_profile") aliceLoaded, err := LoadCwtchPeer("./test_profile")
if err != nil || aliceLoaded.Profile.Name != "alice" { if err != nil || aliceLoaded.GetProfile().Name != "alice" {
t.Errorf("something went wrong saving and loading profiles %v %v", err, aliceLoaded) t.Errorf("something went wrong saving and loading profiles %v %v", err, aliceLoaded)
} }
groupID, _, _ := aliceLoaded.Profile.StartGroup("test.server") groupID, _, _ := aliceLoaded.StartGroup("test.server")
exportedGroup, _ := aliceLoaded.ExportGroup(groupID) exportedGroup, _ := aliceLoaded.ExportGroup(groupID)
t.Logf("Exported Group: %v from %v", exportedGroup, aliceLoaded.Profile.Onion) t.Logf("Exported Group: %v from %v", exportedGroup, aliceLoaded.GetProfile().Onion)
importedGroupID, err := alice.ImportGroup(exportedGroup) importedGroupID, err := alice.ImportGroup(exportedGroup)
group := alice.Profile.GetGroupByGroupID(importedGroupID) group := alice.GetGroup(importedGroupID)
t.Logf("Imported Group: %v, err := %v %v", group, err, importedGroupID) t.Logf("Imported Group: %v, err := %v %v", group, err, importedGroupID)
} }

View File

@ -83,14 +83,14 @@ func serverCheck(t *testing.T, serverAddr string) bool {
return true return true
} }
func waitForPeerConnection(t *testing.T, peer *peer.CwtchPeer, server string) { func waitForPeerConnection(t *testing.T, peer peer.CwtchPeerInterface, server string) {
for { for {
servers := peer.GetServers() servers := peer.GetServers()
fmt.Println(servers) fmt.Println(servers)
state, ok := servers[server] state, ok := servers[server]
if ok { if ok {
if state == connections.FAILED { if state == connections.FAILED {
t.Fatalf("%v could not connect to %v", peer.Profile.Onion, server) t.Fatalf("%v could not connect to %v", peer.GetProfile().Onion, server)
} }
if state != connections.AUTHENTICATED { if state != connections.AUTHENTICATED {
time.Sleep(time.Second * 10) time.Sleep(time.Second * 10)
@ -145,17 +145,17 @@ func TestCwtchPeerIntegration(t *testing.T) {
fmt.Println("Creating Alice...") fmt.Println("Creating Alice...")
alice := peer.NewCwtchPeer("Alice") alice := peer.NewCwtchPeer("Alice")
go alice.Listen() go alice.Listen()
fmt.Println("Alice created:", alice.Profile.Onion) fmt.Println("Alice created:", alice.GetProfile().Onion)
fmt.Println("Creating Bob...") fmt.Println("Creating Bob...")
bob := peer.NewCwtchPeer("Bob") bob := peer.NewCwtchPeer("Bob")
go bob.Listen() go bob.Listen()
fmt.Println("Bob created:", bob.Profile.Onion) fmt.Println("Bob created:", bob.GetProfile().Onion)
fmt.Println("Creating Carol...") fmt.Println("Creating Carol...")
carol := peer.NewCwtchPeer("Carol") carol := peer.NewCwtchPeer("Carol")
go carol.Listen() go carol.Listen()
fmt.Println("Carol created:", carol.Profile.Onion) fmt.Println("Carol created:", carol.GetProfile().Onion)
fmt.Println("Waiting for Alice, Bob, and Carol to connection with onion network...") fmt.Println("Waiting for Alice, Bob, and Carol to connection with onion network...")
time.Sleep(time.Second * 70) time.Sleep(time.Second * 70)
@ -164,7 +164,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
// ***** Peering, server joining, group creation / invite ***** // ***** Peering, server joining, group creation / invite *****
fmt.Println("Creating group on ", serverAddr, "...") fmt.Println("Creating group on ", serverAddr, "...")
groupID, _, err := alice.Profile.StartGroup(serverAddr) groupID, _, err := alice.StartGroup(serverAddr)
fmt.Printf("Created group: %v!\n", groupID) fmt.Printf("Created group: %v!\n", groupID)
if err != nil { if err != nil {
t.Errorf("Failed to init group: %v", err) t.Errorf("Failed to init group: %v", err)
@ -172,9 +172,9 @@ func TestCwtchPeerIntegration(t *testing.T) {
} }
fmt.Println("Alice peering with Bob...") fmt.Println("Alice peering with Bob...")
alice.PeerWithOnion(bob.Profile.Onion) alice.PeerWithOnion(bob.GetProfile().Onion)
fmt.Println("Alice peering with Carol...") fmt.Println("Alice peering with Carol...")
alice.PeerWithOnion(carol.Profile.Onion) alice.PeerWithOnion(carol.GetProfile().Onion)
fmt.Println("Alice joining server...") fmt.Println("Alice joining server...")
alice.JoinServer(serverAddr) alice.JoinServer(serverAddr)
@ -185,7 +185,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
time.Sleep(time.Second * 60) time.Sleep(time.Second * 60)
fmt.Println("Alice inviting Bob to group...") fmt.Println("Alice inviting Bob to group...")
err = alice.InviteOnionToGroup(bob.Profile.Onion, groupID) err = alice.InviteOnionToGroup(bob.GetProfile().Onion, groupID)
if err != nil { if err != nil {
t.Fatalf("Error for Alice inviting Bob to group: %v", err) t.Fatalf("Error for Alice inviting Bob to group: %v", err)
} }
@ -193,7 +193,8 @@ func TestCwtchPeerIntegration(t *testing.T) {
time.Sleep(time.Second * 10) time.Sleep(time.Second * 10)
fmt.Println("Bob examining groups and accepting invites...") fmt.Println("Bob examining groups and accepting invites...")
for _, group := range bob.Profile.Groups { for _, groupID := range bob.GetGroups() {
group := bob.GetGroup(groupID)
fmt.Printf("Bob group: %v (Accepted: %v)\n", group.GroupID, group.Accepted) fmt.Printf("Bob group: %v (Accepted: %v)\n", group.GroupID, group.Accepted)
if group.Accepted == false { if group.Accepted == false {
fmt.Printf("Bob received and accepting group invite: %v\n", group.GroupID) fmt.Printf("Bob received and accepting group invite: %v\n", group.GroupID)
@ -262,13 +263,14 @@ func TestCwtchPeerIntegration(t *testing.T) {
time.Sleep(time.Second * 10) time.Sleep(time.Second * 10)
fmt.Println("Alice inviting Carol to group...") fmt.Println("Alice inviting Carol to group...")
err = alice.InviteOnionToGroup(carol.Profile.Onion, groupID) err = alice.InviteOnionToGroup(carol.GetProfile().Onion, groupID)
if err != nil { if err != nil {
t.Fatalf("Error for Alice inviting Carol to group: %v", err) t.Fatalf("Error for Alice inviting Carol to group: %v", err)
} }
time.Sleep(time.Second * 10) time.Sleep(time.Second * 10)
fmt.Println("Carol examining groups and accepting invites...") fmt.Println("Carol examining groups and accepting invites...")
for _, group := range carol.Profile.Groups { for _, groupID := range carol.GetGroups() {
group := carol.GetGroup(groupID)
fmt.Printf("Carol group: %v (Accepted: %v)\n", group.GroupID, group.Accepted) fmt.Printf("Carol group: %v (Accepted: %v)\n", group.GroupID, group.Accepted)
if group.Accepted == false { if group.Accepted == false {
fmt.Printf("Carol received and accepting group invite: %v\n", group.GroupID) fmt.Printf("Carol received and accepting group invite: %v\n", group.GroupID)
@ -299,7 +301,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
// final syncing time... // final syncing time...
time.Sleep(time.Second * 15) time.Sleep(time.Second * 15)
alicesGroup := alice.Profile.GetGroupByGroupID(groupID) alicesGroup := alice.GetGroup(groupID)
if alicesGroup == nil { if alicesGroup == nil {
t.Error("aliceGroup == nil") t.Error("aliceGroup == nil")
return return
@ -311,7 +313,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
t.Errorf("Alice did not have 4 verified messages") t.Errorf("Alice did not have 4 verified messages")
} }
bobsGroup := bob.Profile.GetGroupByGroupID(groupID) bobsGroup := bob.GetGroup(groupID)
if bobsGroup == nil { if bobsGroup == nil {
t.Error("bobGroup == nil") t.Error("bobGroup == nil")
return return
@ -322,7 +324,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
t.Errorf("Bob did not have 5 verified messages") t.Errorf("Bob did not have 5 verified messages")
} }
carolsGroup := carol.Profile.GetGroupByGroupID(groupID) carolsGroup := carol.GetGroup(groupID)
fmt.Printf("Carol's TimeLine:\n") fmt.Printf("Carol's TimeLine:\n")
carolVerified := printAndCountVerifedTimeline(t, carolsGroup.GetTimeline()) carolVerified := printAndCountVerifedTimeline(t, carolsGroup.GetTimeline())
if carolVerified != 3 { if carolVerified != 3 {