forked from cwtch.im/cwtch
Encapsualting Profile behind Peer interface
This commit is contained in:
parent
7f99747100
commit
89ffc737bc
|
@ -5,12 +5,12 @@ import (
|
|||
"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 {
|
||||
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 {
|
||||
profile := peer.NewCwtchPeer(name)
|
||||
app.Peer = profile
|
||||
|
|
|
@ -62,8 +62,9 @@ func completer(d prompt.Document) []prompt.Suggest {
|
|||
w := d.CurrentLine()
|
||||
if strings.HasPrefix(w, "send") || strings.HasPrefix(w, "timeline") {
|
||||
s = []prompt.Suggest{}
|
||||
groups := app.Peer.Profile.Groups
|
||||
for _, group := range groups {
|
||||
groups := app.Peer.GetGroups()
|
||||
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})
|
||||
}
|
||||
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") {
|
||||
s = []prompt.Suggest{}
|
||||
contacts := app.Peer.Profile.Contacts
|
||||
for _, contact := range contacts {
|
||||
contacts := app.Peer.GetContacts()
|
||||
for _, onion := range contacts {
|
||||
contact := app.Peer.GetContact(onion)
|
||||
s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name})
|
||||
}
|
||||
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
|
||||
|
@ -82,15 +84,17 @@ func completer(d prompt.Document) []prompt.Suggest {
|
|||
|
||||
if d.FindStartOfPreviousWordWithSpace() == 0 {
|
||||
s = []prompt.Suggest{}
|
||||
contacts := app.Peer.Profile.Contacts
|
||||
for _, contact := range contacts {
|
||||
contacts := app.Peer.GetContacts()
|
||||
for _, onion := range contacts {
|
||||
contact := app.Peer.GetContact(onion)
|
||||
s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name})
|
||||
}
|
||||
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
|
||||
}
|
||||
s = []prompt.Suggest{}
|
||||
groups := app.Peer.Profile.Groups
|
||||
for _, group := range groups {
|
||||
groups := app.Peer.GetGroups()
|
||||
for _, groupID := range groups {
|
||||
group := app.Peer.GetGroup(groupID)
|
||||
if group.Owner == "self" {
|
||||
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") {
|
||||
s = []prompt.Suggest{}
|
||||
groups := app.Peer.Profile.Groups
|
||||
for _, group := range groups {
|
||||
groups := app.Peer.GetGroups()
|
||||
for _, groupID := range groups {
|
||||
group := app.Peer.GetGroup(groupID)
|
||||
if group.Accepted == false {
|
||||
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 {
|
||||
profile := "unset"
|
||||
if app.Peer != nil {
|
||||
profile = app.Peer.Profile.Name
|
||||
profile = app.Peer.GetProfile().Name
|
||||
}
|
||||
prmpt := fmt.Sprintf("cwtch [%v]> ", profile)
|
||||
|
||||
|
@ -200,7 +205,7 @@ func main() {
|
|||
|
||||
case "info":
|
||||
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 {
|
||||
fmt.Printf("Profile needs to be set\n")
|
||||
}
|
||||
|
@ -222,12 +227,15 @@ func main() {
|
|||
fmt.Printf("Name: %v Status: %v\n", s, st)
|
||||
}
|
||||
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)
|
||||
}
|
||||
case "groups":
|
||||
for gid, g := range app.Peer.Profile.Groups {
|
||||
fmt.Printf("Group Id: %v Owner: %v Accepted:%v \n", gid, g.Owner, g.Accepted)
|
||||
for _, gid := range app.Peer.GetGroups() {
|
||||
g := app.Peer.GetGroup(gid)
|
||||
fmt.Printf("Group Id: %v Owner: %v Accepted:%v\n", gid, g.Owner, g.Accepted)
|
||||
}
|
||||
case "trust":
|
||||
if len(commands) == 2 {
|
||||
|
@ -249,7 +257,7 @@ func main() {
|
|||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
app.Peer.Save(profilefile)
|
||||
group := app.Peer.Profile.GetGroupByGroupID(groupID)
|
||||
group := app.Peer.GetGroup(groupID)
|
||||
if group == nil {
|
||||
fmt.Printf("Error: group does not exist\n")
|
||||
} else {
|
||||
|
@ -272,11 +280,11 @@ func main() {
|
|||
case "new-group":
|
||||
if len(commands) == 2 {
|
||||
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 {
|
||||
fmt.Printf("New Group [%v] created for server %v\n", id, commands[1])
|
||||
app.Peer.Save(profilefile)
|
||||
group := app.Peer.Profile.GetGroupByGroupID(id)
|
||||
group := app.Peer.GetGroup(id)
|
||||
if group == nil {
|
||||
fmt.Printf("Error: group does not exist\n")
|
||||
} else {
|
||||
|
@ -300,7 +308,7 @@ func main() {
|
|||
}
|
||||
case "timeline":
|
||||
if len(commands) == 2 {
|
||||
group := app.Peer.Profile.GetGroupByGroupID(commands[1])
|
||||
group := app.Peer.GetGroup(commands[1])
|
||||
if group == nil {
|
||||
fmt.Printf("Error: group does not exist\n")
|
||||
} else {
|
||||
|
@ -311,12 +319,12 @@ func main() {
|
|||
verified = "verified"
|
||||
}
|
||||
|
||||
p, ok := app.Peer.Profile.Contacts[m.PeerID]
|
||||
p := app.Peer.GetContact(m.PeerID)
|
||||
name := "unknown"
|
||||
if ok {
|
||||
if p != nil {
|
||||
name = p.Name
|
||||
} else if app.Peer.Profile.Onion == m.PeerID {
|
||||
name = app.Peer.Profile.Name
|
||||
} else if app.Peer.GetProfile().Onion == m.PeerID {
|
||||
name = app.Peer.GetProfile().Name
|
||||
}
|
||||
|
||||
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":
|
||||
if len(commands) == 2 {
|
||||
group := app.Peer.Profile.GetGroupByGroupID(commands[1])
|
||||
group := app.Peer.GetGroup(commands[1])
|
||||
if group == nil {
|
||||
fmt.Printf("Error: group does not exist\n")
|
||||
} else {
|
||||
|
@ -345,7 +353,7 @@ func main() {
|
|||
}
|
||||
case "sendlots":
|
||||
if len(commands) == 2 {
|
||||
group := app.Peer.Profile.GetGroupByGroupID(commands[1])
|
||||
group := app.Peer.GetGroup(commands[1])
|
||||
if group == nil {
|
||||
fmt.Printf("Error: group does not exist\n")
|
||||
} else {
|
||||
|
@ -365,7 +373,7 @@ func main() {
|
|||
for i := 0; i < 100; i++ {
|
||||
found := false
|
||||
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
|
||||
latency := m.Received.Sub(m.Timestamp)
|
||||
fmt.Printf("Latency for Message %v was %v\n", i, latency)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -103,6 +103,30 @@ func (p *Profile) AcceptInvite(groupID string) (err error) {
|
|||
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
|
||||
func (p *Profile) BlockPeer(onion string) (err error) {
|
||||
p.lock.Lock()
|
||||
|
|
|
@ -22,6 +22,10 @@ func TestProfileIdentity(t *testing.T) {
|
|||
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)
|
||||
}
|
||||
|
||||
|
@ -94,6 +98,10 @@ func TestProfileGroup(t *testing.T) {
|
|||
gci := &protocol.CwtchPeerPacket{}
|
||||
proto.Unmarshal(invite, gci)
|
||||
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)
|
||||
sarah.AcceptInvite(group.GroupID)
|
||||
c, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
|
||||
|
|
|
@ -20,8 +20,8 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
// CwtchPeer manages incoming and outgoing connections and all processing for a Cwtch Peer
|
||||
type CwtchPeer struct {
|
||||
// cwtchPeer manages incoming and outgoing connections and all processing for a Cwtch Peer
|
||||
type cwtchPeer struct {
|
||||
connection.AutoConnectionHandler
|
||||
Profile *model.Profile
|
||||
app *application.RicochetApplication
|
||||
|
@ -31,7 +31,41 @@ type CwtchPeer struct {
|
|||
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.connectionsManager = connections.NewConnectionsManager()
|
||||
cp.Init()
|
||||
|
@ -51,16 +85,16 @@ func (cp *CwtchPeer) setup() {
|
|||
}
|
||||
}
|
||||
|
||||
// NewCwtchPeer creates and returns a new CwtchPeer with the given name.
|
||||
func NewCwtchPeer(name string) *CwtchPeer {
|
||||
cp := new(CwtchPeer)
|
||||
// NewCwtchPeer creates and returns a new cwtchPeer with the given name.
|
||||
func NewCwtchPeer(name string) CwtchPeerInterface {
|
||||
cp := new(cwtchPeer)
|
||||
cp.Profile = model.GenerateNewProfile(name)
|
||||
cp.setup()
|
||||
return cp
|
||||
}
|
||||
|
||||
// Save saves the CwtchPeer profile state to a file.
|
||||
func (cp *CwtchPeer) Save(profilefile string) error {
|
||||
// Save saves the cwtchPeer profile state to a file.
|
||||
func (cp *cwtchPeer) Save(profilefile string) error {
|
||||
cp.mutex.Lock()
|
||||
bytes, _ := json.MarshalIndent(cp, "", "\t")
|
||||
err := ioutil.WriteFile(profilefile, bytes, 0600)
|
||||
|
@ -69,10 +103,10 @@ func (cp *CwtchPeer) Save(profilefile string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// LoadCwtchPeer loads an existing CwtchPeer from a file.
|
||||
func LoadCwtchPeer(profilefile string) (*CwtchPeer, error) {
|
||||
// LoadCwtchPeer loads an existing cwtchPeer from a file.
|
||||
func LoadCwtchPeer(profilefile string) (CwtchPeerInterface, error) {
|
||||
bytes, _ := ioutil.ReadFile(profilefile)
|
||||
cp := new(CwtchPeer)
|
||||
cp := new(cwtchPeer)
|
||||
err := json.Unmarshal(bytes, &cp)
|
||||
cp.setup()
|
||||
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
|
||||
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") {
|
||||
data, err := base64.StdEncoding.DecodeString(exportedInvite[21+44:])
|
||||
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
|
||||
func (cp *CwtchPeer) ExportGroup(groupID string) (string, error) {
|
||||
func (cp *cwtchPeer) ExportGroup(groupID string) (string, error) {
|
||||
group := cp.Profile.GetGroupByGroupID(groupID)
|
||||
if group != nil {
|
||||
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")
|
||||
}
|
||||
|
||||
// PeerWithOnion is the entry point for CwtchPeer relationships
|
||||
func (cp *CwtchPeer) PeerWithOnion(onion string) {
|
||||
// StartGroup create a new group linked to the given server and returns the group ID, an invite or an error.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
func (cp *CwtchPeer) ReceiveGroupMessage(server string, gm *protocol.GroupMessage) {
|
||||
func (cp *cwtchPeer) ReceiveGroupMessage(server string, gm *protocol.GroupMessage) {
|
||||
cp.Profile.AttemptDecryption(gm.Ciphertext)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
if group == nil {
|
||||
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.
|
||||
func (cp *CwtchPeer) GetPeers() map[string]connections.ConnectionState {
|
||||
func (cp *cwtchPeer) GetPeers() map[string]connections.ConnectionState {
|
||||
return cp.connectionsManager.GetPeers()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err == nil {
|
||||
cp.PeerWithOnion(peer)
|
||||
|
@ -197,35 +263,35 @@ func (cp *CwtchPeer) TrustPeer(peer string) error {
|
|||
}
|
||||
|
||||
// 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)
|
||||
cp.connectionsManager.ClosePeerConnection(peer)
|
||||
return err
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// RejectInvite rejects a given group invite.
|
||||
func (cp *CwtchPeer) RejectInvite(groupID string) {
|
||||
func (cp *cwtchPeer) RejectInvite(groupID string) {
|
||||
cp.Profile.RejectInvite(groupID)
|
||||
}
|
||||
|
||||
// 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)
|
||||
return !blocked, true
|
||||
}
|
||||
|
||||
// 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"
|
||||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
func (cp *CwtchPeer) Shutdown() {
|
||||
func (cp *cwtchPeer) Shutdown() {
|
||||
cp.connectionsManager.Shutdown()
|
||||
cp.app.Shutdown()
|
||||
}
|
||||
|
@ -272,7 +338,7 @@ func (cpi *CwtchPeerInstance) Init(rai *application.ApplicationInstance, ra *app
|
|||
// CwtchPeerHandler encapsulates handling of incoming CwtchPackets
|
||||
type CwtchPeerHandler struct {
|
||||
Onion string
|
||||
Peer *CwtchPeer
|
||||
Peer *cwtchPeer
|
||||
}
|
||||
|
||||
// ClientIdentity handles incoming ClientIdentity packets
|
||||
|
|
|
@ -10,16 +10,16 @@ func TestCwtchPeerGenerate(t *testing.T) {
|
|||
alice.Save("./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)
|
||||
}
|
||||
|
||||
groupID, _, _ := aliceLoaded.Profile.StartGroup("test.server")
|
||||
groupID, _, _ := aliceLoaded.StartGroup("test.server")
|
||||
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)
|
||||
group := alice.Profile.GetGroupByGroupID(importedGroupID)
|
||||
group := alice.GetGroup(importedGroupID)
|
||||
t.Logf("Imported Group: %v, err := %v %v", group, err, importedGroupID)
|
||||
|
||||
}
|
||||
|
|
|
@ -83,14 +83,14 @@ func serverCheck(t *testing.T, serverAddr string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func waitForPeerConnection(t *testing.T, peer *peer.CwtchPeer, server string) {
|
||||
func waitForPeerConnection(t *testing.T, peer peer.CwtchPeerInterface, server string) {
|
||||
for {
|
||||
servers := peer.GetServers()
|
||||
fmt.Println(servers)
|
||||
state, ok := servers[server]
|
||||
if ok {
|
||||
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 {
|
||||
time.Sleep(time.Second * 10)
|
||||
|
@ -145,17 +145,17 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
fmt.Println("Creating Alice...")
|
||||
alice := peer.NewCwtchPeer("Alice")
|
||||
go alice.Listen()
|
||||
fmt.Println("Alice created:", alice.Profile.Onion)
|
||||
fmt.Println("Alice created:", alice.GetProfile().Onion)
|
||||
|
||||
fmt.Println("Creating Bob...")
|
||||
bob := peer.NewCwtchPeer("Bob")
|
||||
go bob.Listen()
|
||||
fmt.Println("Bob created:", bob.Profile.Onion)
|
||||
fmt.Println("Bob created:", bob.GetProfile().Onion)
|
||||
|
||||
fmt.Println("Creating Carol...")
|
||||
carol := peer.NewCwtchPeer("Carol")
|
||||
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...")
|
||||
time.Sleep(time.Second * 70)
|
||||
|
@ -164,7 +164,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
// ***** Peering, server joining, group creation / invite *****
|
||||
|
||||
fmt.Println("Creating group on ", serverAddr, "...")
|
||||
groupID, _, err := alice.Profile.StartGroup(serverAddr)
|
||||
groupID, _, err := alice.StartGroup(serverAddr)
|
||||
fmt.Printf("Created group: %v!\n", groupID)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to init group: %v", err)
|
||||
|
@ -172,9 +172,9 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
}
|
||||
|
||||
fmt.Println("Alice peering with Bob...")
|
||||
alice.PeerWithOnion(bob.Profile.Onion)
|
||||
alice.PeerWithOnion(bob.GetProfile().Onion)
|
||||
fmt.Println("Alice peering with Carol...")
|
||||
alice.PeerWithOnion(carol.Profile.Onion)
|
||||
alice.PeerWithOnion(carol.GetProfile().Onion)
|
||||
|
||||
fmt.Println("Alice joining server...")
|
||||
alice.JoinServer(serverAddr)
|
||||
|
@ -185,7 +185,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
time.Sleep(time.Second * 60)
|
||||
|
||||
fmt.Println("Alice inviting Bob to group...")
|
||||
err = alice.InviteOnionToGroup(bob.Profile.Onion, groupID)
|
||||
err = alice.InviteOnionToGroup(bob.GetProfile().Onion, groupID)
|
||||
if err != nil {
|
||||
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)
|
||||
|
||||
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)
|
||||
if group.Accepted == false {
|
||||
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)
|
||||
|
||||
fmt.Println("Alice inviting Carol to group...")
|
||||
err = alice.InviteOnionToGroup(carol.Profile.Onion, groupID)
|
||||
err = alice.InviteOnionToGroup(carol.GetProfile().Onion, groupID)
|
||||
if err != nil {
|
||||
t.Fatalf("Error for Alice inviting Carol to group: %v", err)
|
||||
}
|
||||
time.Sleep(time.Second * 10)
|
||||
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)
|
||||
if group.Accepted == false {
|
||||
fmt.Printf("Carol received and accepting group invite: %v\n", group.GroupID)
|
||||
|
@ -299,7 +301,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
// final syncing time...
|
||||
time.Sleep(time.Second * 15)
|
||||
|
||||
alicesGroup := alice.Profile.GetGroupByGroupID(groupID)
|
||||
alicesGroup := alice.GetGroup(groupID)
|
||||
if alicesGroup == nil {
|
||||
t.Error("aliceGroup == nil")
|
||||
return
|
||||
|
@ -311,7 +313,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
t.Errorf("Alice did not have 4 verified messages")
|
||||
}
|
||||
|
||||
bobsGroup := bob.Profile.GetGroupByGroupID(groupID)
|
||||
bobsGroup := bob.GetGroup(groupID)
|
||||
if bobsGroup == nil {
|
||||
t.Error("bobGroup == nil")
|
||||
return
|
||||
|
@ -322,7 +324,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
t.Errorf("Bob did not have 5 verified messages")
|
||||
}
|
||||
|
||||
carolsGroup := carol.Profile.GetGroupByGroupID(groupID)
|
||||
carolsGroup := carol.GetGroup(groupID)
|
||||
fmt.Printf("Carol's TimeLine:\n")
|
||||
carolVerified := printAndCountVerifedTimeline(t, carolsGroup.GetTimeline())
|
||||
if carolVerified != 3 {
|
||||
|
|
Loading…
Reference in New Issue