2018-03-11 18:49:10 +00:00
|
|
|
package peer
|
2018-03-09 20:44:13 +00:00
|
|
|
|
|
|
|
import (
|
2019-01-04 21:44:21 +00:00
|
|
|
"cwtch.im/cwtch/event"
|
2018-05-28 18:05:06 +00:00
|
|
|
"cwtch.im/cwtch/model"
|
|
|
|
"cwtch.im/cwtch/protocol"
|
2019-01-04 21:44:21 +00:00
|
|
|
"cwtch.im/cwtch/protocol/connections"
|
2019-05-15 20:12:11 +00:00
|
|
|
"encoding/base32"
|
2018-06-09 07:49:18 +00:00
|
|
|
"encoding/base64"
|
2019-02-03 01:18:33 +00:00
|
|
|
"encoding/json"
|
2018-03-30 21:16:51 +00:00
|
|
|
"errors"
|
2019-01-13 23:48:17 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
2018-06-24 18:37:11 +00:00
|
|
|
"github.com/golang/protobuf/proto"
|
2018-06-09 07:49:18 +00:00
|
|
|
"strings"
|
2018-03-09 20:44:13 +00:00
|
|
|
"sync"
|
2019-01-22 19:11:25 +00:00
|
|
|
"time"
|
2018-03-09 20:44:13 +00:00
|
|
|
)
|
|
|
|
|
2018-10-06 03:50:55 +00:00
|
|
|
// cwtchPeer manages incoming and outgoing connections and all processing for a Cwtch cwtchPeer
|
2018-06-19 22:28:44 +00:00
|
|
|
type cwtchPeer struct {
|
2019-01-04 21:44:21 +00:00
|
|
|
Profile *model.Profile
|
|
|
|
mutex sync.Mutex
|
|
|
|
shutdown bool
|
|
|
|
|
2019-08-14 20:56:45 +00:00
|
|
|
queue event.Queue
|
2019-06-05 20:40:55 +00:00
|
|
|
eventBus event.Manager
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 18:53:10 +00:00
|
|
|
// CwtchPeer provides us with a way of testing systems built on top of cwtch without having to
|
2018-06-19 22:28:44 +00:00
|
|
|
// directly implement a cwtchPeer.
|
2018-09-21 18:53:10 +00:00
|
|
|
type CwtchPeer interface {
|
2019-06-21 21:50:43 +00:00
|
|
|
Init(event.Manager)
|
2019-07-17 19:10:52 +00:00
|
|
|
PeerWithOnion(string)
|
2018-06-19 22:28:44 +00:00
|
|
|
InviteOnionToGroup(string, string) error
|
2019-01-15 20:59:54 +00:00
|
|
|
SendMessageToPeer(string, string) string
|
2018-06-19 22:28:44 +00:00
|
|
|
|
|
|
|
TrustPeer(string) error
|
|
|
|
BlockPeer(string) error
|
2019-08-07 18:49:44 +00:00
|
|
|
UnblockPeer(string) error
|
2018-06-19 22:28:44 +00:00
|
|
|
AcceptInvite(string) error
|
|
|
|
RejectInvite(string)
|
2019-08-07 05:27:11 +00:00
|
|
|
DeleteContact(string)
|
|
|
|
DeleteGroup(string)
|
2018-06-19 22:28:44 +00:00
|
|
|
|
|
|
|
JoinServer(string)
|
|
|
|
SendMessageToGroup(string, string) error
|
2019-02-19 20:18:25 +00:00
|
|
|
SendMessageToGroupTracked(string, string) (string, error)
|
2018-06-19 22:28:44 +00:00
|
|
|
|
|
|
|
GetProfile() *model.Profile
|
2019-05-15 20:12:11 +00:00
|
|
|
GetPeerState(string) connections.ConnectionState
|
2018-06-19 22:28:44 +00:00
|
|
|
|
|
|
|
StartGroup(string) (string, []byte, error)
|
|
|
|
|
|
|
|
ImportGroup(string) (string, error)
|
|
|
|
ExportGroup(string) (string, error)
|
|
|
|
|
|
|
|
GetGroup(string) *model.Group
|
2019-05-15 20:12:11 +00:00
|
|
|
GetGroupState(string) connections.ConnectionState
|
2018-06-19 22:28:44 +00:00
|
|
|
GetGroups() []string
|
2019-05-15 20:12:11 +00:00
|
|
|
AddContact(nick, onion string, trusted bool)
|
2018-06-19 22:28:44 +00:00
|
|
|
GetContacts() []string
|
|
|
|
GetContact(string) *model.PublicProfile
|
|
|
|
|
2018-11-10 22:14:12 +00:00
|
|
|
Listen()
|
2019-05-15 20:12:11 +00:00
|
|
|
StartPeersConnections()
|
|
|
|
StartGroupConnections()
|
2018-06-19 22:28:44 +00:00
|
|
|
Shutdown()
|
|
|
|
}
|
|
|
|
|
2018-06-24 18:59:42 +00:00
|
|
|
// NewCwtchPeer creates and returns a new cwtchPeer with the given name.
|
2018-10-06 03:50:55 +00:00
|
|
|
func NewCwtchPeer(name string) CwtchPeer {
|
2018-06-23 23:56:51 +00:00
|
|
|
cp := new(cwtchPeer)
|
2018-05-01 20:44:45 +00:00
|
|
|
cp.Profile = model.GenerateNewProfile(name)
|
2018-11-10 22:14:12 +00:00
|
|
|
cp.shutdown = false
|
2018-10-06 03:50:55 +00:00
|
|
|
return cp
|
2018-10-15 00:59:53 +00:00
|
|
|
}
|
|
|
|
|
2018-10-06 03:50:55 +00:00
|
|
|
// FromProfile generates a new peer from a profile.
|
|
|
|
func FromProfile(profile *model.Profile) CwtchPeer {
|
|
|
|
cp := new(cwtchPeer)
|
|
|
|
cp.Profile = profile
|
|
|
|
return cp
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2018-10-06 03:50:55 +00:00
|
|
|
// Init instantiates a cwtchPeer
|
2019-06-21 21:50:43 +00:00
|
|
|
func (cp *cwtchPeer) Init(eventBus event.Manager) {
|
2019-08-14 20:56:45 +00:00
|
|
|
cp.queue = event.NewQueue()
|
2019-01-04 21:44:21 +00:00
|
|
|
go cp.eventHandler()
|
|
|
|
|
|
|
|
cp.eventBus = eventBus
|
2019-08-14 20:56:45 +00:00
|
|
|
cp.eventBus.Subscribe(event.EncryptedGroupMessage, cp.queue)
|
|
|
|
cp.eventBus.Subscribe(event.NewGroupInvite, cp.queue)
|
|
|
|
cp.eventBus.Subscribe(event.ServerStateChange, cp.queue)
|
|
|
|
cp.eventBus.Subscribe(event.PeerStateChange, cp.queue)
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2018-06-09 07:49:18 +00:00
|
|
|
// ImportGroup intializes a group from an imported source rather than a peer invite
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) ImportGroup(exportedInvite string) (groupID string, err error) {
|
2018-10-05 03:18:34 +00:00
|
|
|
if strings.HasPrefix(exportedInvite, "torv3") {
|
|
|
|
data, err := base64.StdEncoding.DecodeString(exportedInvite[5+44:])
|
2018-06-09 07:49:18 +00:00
|
|
|
if err == nil {
|
|
|
|
cpp := &protocol.CwtchPeerPacket{}
|
2019-01-19 23:16:38 +00:00
|
|
|
err = proto.Unmarshal(data, cpp)
|
2018-06-09 07:49:18 +00:00
|
|
|
if err == nil {
|
2019-02-13 02:46:23 +00:00
|
|
|
jsobj, err := proto.Marshal(cpp.GetGroupChatInvite())
|
2018-06-09 07:49:18 +00:00
|
|
|
if err == nil {
|
2019-02-13 02:00:05 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.NewGroupInvite, map[event.Field]string{
|
2019-07-06 00:46:51 +00:00
|
|
|
event.GroupInvite: string(jsobj),
|
2019-02-13 02:00:05 +00:00
|
|
|
}))
|
|
|
|
} else {
|
|
|
|
log.Errorf("error serializing group: %v", err)
|
2018-06-09 07:49:18 +00:00
|
|
|
}
|
2019-02-13 02:00:05 +00:00
|
|
|
return cpp.GroupChatInvite.GetGroupName(), nil
|
2018-06-09 07:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
err = errors.New("unsupported exported group type")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// ExportGroup serializes a group invite so it can be given offline
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) ExportGroup(groupID string) (string, error) {
|
2018-06-09 07:49:18 +00:00
|
|
|
group := cp.Profile.GetGroupByGroupID(groupID)
|
|
|
|
if group != nil {
|
2018-10-03 05:46:00 +00:00
|
|
|
invite, err := group.Invite(group.GetInitialMessage())
|
2018-06-09 07:49:18 +00:00
|
|
|
if err == nil {
|
2018-10-05 03:18:34 +00:00
|
|
|
exportedInvite := "torv3" + base64.StdEncoding.EncodeToString(cp.Profile.Ed25519PublicKey) + base64.StdEncoding.EncodeToString(invite)
|
2018-06-09 07:49:18 +00:00
|
|
|
return exportedInvite, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "", errors.New("group id could not be found")
|
|
|
|
}
|
|
|
|
|
2018-06-19 22:28:44 +00:00
|
|
|
// 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) {
|
2019-02-03 01:18:33 +00:00
|
|
|
return cp.StartGroupWithMessage(server, []byte{})
|
2018-06-19 22:28:44 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 18:02:46 +00:00
|
|
|
// StartGroupWithMessage create a new group linked to the given server and returns the group ID, an invite or an error.
|
2019-02-03 01:18:33 +00:00
|
|
|
func (cp *cwtchPeer) StartGroupWithMessage(server string, initialMessage []byte) (groupID string, invite []byte, err error) {
|
|
|
|
groupID, invite, err = cp.Profile.StartGroupWithMessage(server, initialMessage)
|
|
|
|
if err == nil {
|
|
|
|
group := cp.GetGroup(groupID)
|
|
|
|
jsobj, err := json.Marshal(group)
|
2019-02-03 03:24:42 +00:00
|
|
|
if err == nil {
|
2019-02-03 01:18:33 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.GroupCreated, map[event.Field]string{
|
|
|
|
event.Data: string(jsobj),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Errorf("error creating group: %v", err)
|
|
|
|
}
|
|
|
|
return
|
2018-09-21 18:02:46 +00:00
|
|
|
}
|
|
|
|
|
2018-06-19 22:28:44 +00:00
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2019-05-15 20:12:11 +00:00
|
|
|
func (cp *cwtchPeer) AddContact(nick, onion string, trusted bool) {
|
|
|
|
decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion))
|
|
|
|
pp := &model.PublicProfile{Name: nick, Ed25519PublicKey: decodedPub, Trusted: trusted, Blocked: false, Onion: onion, Attributes: map[string]string{"nick": nick}}
|
2019-02-03 01:18:33 +00:00
|
|
|
cp.Profile.AddContact(onion, pp)
|
2019-02-04 19:39:58 +00:00
|
|
|
pd, _ := json.Marshal(pp)
|
2019-02-03 01:18:33 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{
|
2019-02-04 19:39:58 +00:00
|
|
|
event.Data: string(pd),
|
2019-02-03 01:18:33 +00:00
|
|
|
event.RemotePeer: onion,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2018-06-19 22:28:44 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2018-10-06 03:50:55 +00:00
|
|
|
// GetProfile returns the profile associated with this cwtchPeer.
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) GetProfile() *model.Profile {
|
|
|
|
return cp.Profile
|
|
|
|
}
|
|
|
|
|
2019-05-15 20:12:11 +00:00
|
|
|
func (cp *cwtchPeer) GetPeerState(onion string) connections.ConnectionState {
|
2019-07-26 20:51:29 +00:00
|
|
|
return connections.ConnectionStateToType[cp.Profile.Contacts[onion].State]
|
2019-05-15 20:12:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *cwtchPeer) GetGroupState(groupid string) connections.ConnectionState {
|
2019-07-26 20:51:29 +00:00
|
|
|
return connections.ConnectionStateToType[cp.Profile.Groups[groupid].State]
|
2019-05-15 20:12:11 +00:00
|
|
|
}
|
|
|
|
|
2018-06-19 22:28:44 +00:00
|
|
|
// PeerWithOnion is the entry point for cwtchPeer relationships
|
2019-07-17 19:10:52 +00:00
|
|
|
func (cp *cwtchPeer) PeerWithOnion(onion string) {
|
2019-01-21 20:08:03 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.PeerRequest, map[event.Field]string{event.RemotePeer: onion}))
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2019-08-07 05:27:11 +00:00
|
|
|
// DeleteContact deletes a peer from the profile, storage, and handling
|
|
|
|
func (cp *cwtchPeer) DeleteContact(onion string) {
|
|
|
|
cp.Profile.DeleteContact(onion)
|
|
|
|
cp.eventBus.Publish(event.NewEventList(event.DeleteContact, event.RemotePeer, onion))
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteGroup deletes a Group from the profile, storage, and handling
|
|
|
|
func (cp *cwtchPeer) DeleteGroup(groupID string) {
|
|
|
|
cp.Profile.DeleteGroup(groupID)
|
|
|
|
cp.eventBus.Publish(event.NewEventList(event.DeleteGroup, event.GroupID, groupID))
|
|
|
|
}
|
|
|
|
|
2018-03-09 20:44:13 +00:00
|
|
|
// InviteOnionToGroup kicks off the invite process
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
|
2018-05-16 20:53:09 +00:00
|
|
|
group := cp.Profile.GetGroupByGroupID(groupid)
|
2019-01-04 21:44:21 +00:00
|
|
|
if group == nil {
|
|
|
|
return errors.New("invalid group id")
|
2018-03-15 20:53:22 +00:00
|
|
|
}
|
2018-03-09 20:44:13 +00:00
|
|
|
|
2019-01-04 21:44:21 +00:00
|
|
|
invite, err := group.Invite(group.InitialMessage)
|
|
|
|
if err == nil {
|
2019-01-21 20:08:03 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.InvitePeerToGroup, map[event.Field]string{event.RemotePeer: onion, event.GroupInvite: string(invite)}))
|
2019-01-04 21:44:21 +00:00
|
|
|
}
|
|
|
|
return err
|
2018-03-30 21:16:51 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 21:31:06 +00:00
|
|
|
// JoinServer manages a new server connection with the given onion address
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) JoinServer(onion string) {
|
2019-01-21 20:08:03 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.JoinServer, map[event.Field]string{event.GroupServer: onion}))
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2019-01-28 20:09:25 +00:00
|
|
|
// SendMessageToGroup attempts to sent the given message to the given group id.
|
2019-02-19 20:18:25 +00:00
|
|
|
// TODO: Deprecate in favour of SendMessageToGroupTracked
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) SendMessageToGroup(groupid string, message string) error {
|
2019-02-19 20:18:25 +00:00
|
|
|
_, err := cp.SendMessageToGroupTracked(groupid, message)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendMessageToGroup attempts to sent the given message to the given group id.
|
|
|
|
// It returns the signature of the message which can be used to identify it in any UX layer.
|
|
|
|
func (cp *cwtchPeer) SendMessageToGroupTracked(groupid string, message string) (string, error) {
|
2018-05-16 20:53:09 +00:00
|
|
|
group := cp.Profile.GetGroupByGroupID(groupid)
|
2018-05-03 04:12:45 +00:00
|
|
|
if group == nil {
|
2019-02-19 20:18:25 +00:00
|
|
|
return "", errors.New("invalid group id")
|
2018-05-09 19:09:00 +00:00
|
|
|
}
|
2018-06-22 18:11:23 +00:00
|
|
|
ct, sig, err := cp.Profile.EncryptMessageToGroup(message, groupid)
|
2019-01-04 21:44:21 +00:00
|
|
|
|
|
|
|
if err == nil {
|
2019-01-21 20:08:03 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.SendMessageToGroup, map[event.Field]string{event.GroupServer: group.GroupServer, event.Ciphertext: string(ct), event.Signature: string(sig)}))
|
2018-03-30 21:16:51 +00:00
|
|
|
}
|
2019-01-04 21:44:21 +00:00
|
|
|
|
2019-02-19 20:18:25 +00:00
|
|
|
return string(sig), err
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 20:59:54 +00:00
|
|
|
func (cp *cwtchPeer) SendMessageToPeer(onion string, message string) string {
|
2019-01-21 20:08:03 +00:00
|
|
|
event := event.NewEvent(event.SendMessageToPeer, map[event.Field]string{event.RemotePeer: onion, event.Data: message})
|
2019-01-15 20:59:54 +00:00
|
|
|
cp.eventBus.Publish(event)
|
|
|
|
return event.EventID
|
2019-01-04 21:44:21 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 21:31:06 +00:00
|
|
|
// TrustPeer sets an existing peer relationship to trusted
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) TrustPeer(peer string) error {
|
2018-05-30 17:41:02 +00:00
|
|
|
err := cp.Profile.TrustPeer(peer)
|
|
|
|
if err == nil {
|
|
|
|
cp.PeerWithOnion(peer)
|
2018-05-03 19:23:02 +00:00
|
|
|
}
|
2018-05-30 17:41:02 +00:00
|
|
|
return err
|
2018-05-03 19:23:02 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 21:31:06 +00:00
|
|
|
// BlockPeer blocks an existing peer relationship.
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) BlockPeer(peer string) error {
|
2018-05-30 17:41:02 +00:00
|
|
|
err := cp.Profile.BlockPeer(peer)
|
2019-01-21 20:08:03 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.BlockPeer, map[event.Field]string{event.RemotePeer: peer}))
|
2018-05-30 17:41:02 +00:00
|
|
|
return err
|
2018-05-03 19:23:02 +00:00
|
|
|
}
|
|
|
|
|
2019-08-07 18:49:44 +00:00
|
|
|
// UnblockPeer blocks an existing peer relationship.
|
|
|
|
func (cp *cwtchPeer) UnblockPeer(peer string) error {
|
|
|
|
err := cp.Profile.UnblockPeer(peer)
|
|
|
|
cp.eventBus.Publish(event.NewEvent(event.UnblockPeer, map[event.Field]string{event.RemotePeer: peer}))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-05-16 21:31:06 +00:00
|
|
|
// AcceptInvite accepts a given existing group invite
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) AcceptInvite(groupID string) error {
|
2019-04-23 20:30:50 +00:00
|
|
|
err := cp.Profile.AcceptInvite(groupID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-02-14 01:57:42 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.AcceptGroupInvite, map[event.Field]string{event.GroupID: groupID}))
|
2019-04-23 20:30:50 +00:00
|
|
|
cp.JoinServer(cp.Profile.Groups[groupID].GroupServer)
|
|
|
|
|
|
|
|
return nil
|
2018-05-03 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 21:31:06 +00:00
|
|
|
// RejectInvite rejects a given group invite.
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) RejectInvite(groupID string) {
|
2018-05-30 17:41:02 +00:00
|
|
|
cp.Profile.RejectInvite(groupID)
|
|
|
|
}
|
|
|
|
|
2019-05-15 20:12:11 +00:00
|
|
|
// Listen makes the peer open a listening port to accept incoming connections (and be detactably online)
|
2018-11-10 22:14:12 +00:00
|
|
|
func (cp *cwtchPeer) Listen() {
|
2019-07-19 17:27:50 +00:00
|
|
|
log.Debugf("cwtchPeer Listen sending ProtocolEngineStartListen\n")
|
2019-01-21 18:47:07 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.ProtocolEngineStartListen, map[event.Field]string{}))
|
2018-03-09 20:44:13 +00:00
|
|
|
}
|
|
|
|
|
2019-05-15 20:12:11 +00:00
|
|
|
// StartGroupConnections attempts to connect to all group servers (thus initiating reconnect attempts in the conectionsmanager)
|
|
|
|
func (cp *cwtchPeer) StartPeersConnections() {
|
|
|
|
for _, contact := range cp.GetContacts() {
|
|
|
|
cp.PeerWithOnion(contact)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// StartPeerConnections attempts to connect to all peers (thus initiating reconnect attempts in the conectionsmanager)
|
|
|
|
func (cp *cwtchPeer) StartGroupConnections() {
|
|
|
|
joinedServers := map[string]bool{}
|
|
|
|
for _, groupID := range cp.GetGroups() {
|
|
|
|
// Only send a join server packet if we haven't joined this server yet...
|
|
|
|
group := cp.GetGroup(groupID)
|
|
|
|
if joined := joinedServers[groupID]; group.Accepted && !joined {
|
2019-06-21 21:50:43 +00:00
|
|
|
log.Infof("Join Server %v (%v)\n", group.GroupServer, joined)
|
2019-05-15 20:12:11 +00:00
|
|
|
cp.JoinServer(group.GroupServer)
|
|
|
|
joinedServers[group.GroupServer] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-15 16:21:07 +00:00
|
|
|
// Shutdown kills all connections and cleans up all goroutines for the peer
|
2018-06-19 22:28:44 +00:00
|
|
|
func (cp *cwtchPeer) Shutdown() {
|
2018-11-10 22:14:12 +00:00
|
|
|
cp.shutdown = true
|
2019-01-04 21:44:21 +00:00
|
|
|
cp.queue.Shutdown()
|
2018-05-30 18:42:17 +00:00
|
|
|
}
|
|
|
|
|
2019-01-04 21:44:21 +00:00
|
|
|
// eventHandler process events from other subsystems
|
|
|
|
func (cp *cwtchPeer) eventHandler() {
|
|
|
|
for {
|
|
|
|
ev := cp.queue.Next()
|
|
|
|
switch ev.EventType {
|
|
|
|
case event.EncryptedGroupMessage:
|
2019-02-03 03:24:42 +00:00
|
|
|
ok, groupID, message, seen := cp.Profile.AttemptDecryption([]byte(ev.Data[event.Ciphertext]), []byte(ev.Data[event.Signature]))
|
|
|
|
if ok && !seen {
|
2019-02-04 01:55:13 +00:00
|
|
|
cp.eventBus.Publish(event.NewEvent(event.NewMessageFromGroup, map[event.Field]string{event.TimestampReceived: message.Received.Format(time.RFC3339Nano), event.TimestampSent: message.Timestamp.Format(time.RFC3339Nano), event.Data: message.Message, event.GroupID: groupID, event.Signature: string(message.Signature), event.PreviousSignature: string(message.PreviousMessageSig), event.RemotePeer: message.PeerID}))
|
2019-01-04 21:44:21 +00:00
|
|
|
}
|
|
|
|
case event.NewGroupInvite:
|
|
|
|
var groupInvite protocol.GroupChatInvite
|
2019-07-06 00:46:51 +00:00
|
|
|
err := proto.Unmarshal([]byte(ev.Data[event.GroupInvite]), &groupInvite)
|
2019-06-21 21:50:43 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Errorf("NewGroupInvite could not json decode invite: %v\n", err)
|
|
|
|
}
|
2019-01-21 20:08:03 +00:00
|
|
|
cp.Profile.ProcessInvite(&groupInvite, ev.Data[event.RemotePeer])
|
2019-05-15 20:12:11 +00:00
|
|
|
case event.PeerStateChange:
|
|
|
|
if _, exists := cp.Profile.Contacts[ev.Data[event.RemotePeer]]; exists {
|
|
|
|
cp.Profile.Contacts[ev.Data[event.RemotePeer]].State = ev.Data[event.ConnectionState]
|
|
|
|
}
|
|
|
|
case event.ServerStateChange:
|
|
|
|
for _, group := range cp.Profile.Groups {
|
|
|
|
if group.GroupServer == ev.Data[event.GroupServer] {
|
|
|
|
group.State = ev.Data[event.ConnectionState]
|
|
|
|
}
|
|
|
|
}
|
2019-01-04 21:44:21 +00:00
|
|
|
default:
|
|
|
|
if ev.EventType != "" {
|
2019-01-13 23:48:17 +00:00
|
|
|
log.Errorf("peer event handler received an event it was not subscribed for: %v", ev.EventType)
|
2019-01-04 21:44:21 +00:00
|
|
|
}
|
2019-01-21 20:08:03 +00:00
|
|
|
return
|
2019-01-04 21:44:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-10-04 19:15:03 +00:00
|
|
|
}
|