core: Implement contact list monitor and contact removal

This commit is contained in:
John Brooks 2016-09-02 11:51:24 -05:00
parent 2c4a1c8b37
commit 20700414fc
3 changed files with 78 additions and 7 deletions

View File

@ -93,6 +93,9 @@ func (core *RicochetCore) GetIdentity(ctx context.Context, req *rpc.IdentityRequ
} }
func (core *RicochetCore) MonitorContacts(req *rpc.MonitorContactsRequest, stream rpc.RicochetCore_MonitorContactsServer) error { func (core *RicochetCore) MonitorContacts(req *rpc.MonitorContactsRequest, stream rpc.RicochetCore_MonitorContactsServer) error {
monitor := core.Identity().ContactList().EventMonitor().Subscribe(20)
defer core.Identity().ContactList().EventMonitor().Unsubscribe(monitor)
// Populate // Populate
contacts := core.Identity().ContactList().Contacts() contacts := core.Identity().ContactList().Contacts()
for _, contact := range contacts { for _, contact := range contacts {
@ -123,7 +126,19 @@ func (core *RicochetCore) MonitorContacts(req *rpc.MonitorContactsRequest, strea
} }
} }
return NotImplementedError for {
event, ok := (<-monitor).(rpc.ContactEvent)
if !ok {
break
}
log.Printf("Contact event: %v", event)
if err := stream.Send(&event); err != nil {
return err
}
}
return nil
} }
func (core *RicochetCore) AddContactRequest(ctx context.Context, req *rpc.ContactRequest) (*rpc.Contact, error) { func (core *RicochetCore) AddContactRequest(ctx context.Context, req *rpc.ContactRequest) (*rpc.Contact, error) {
@ -135,7 +150,17 @@ func (core *RicochetCore) UpdateContact(ctx context.Context, req *rpc.Contact) (
} }
func (core *RicochetCore) DeleteContact(ctx context.Context, req *rpc.DeleteContactRequest) (*rpc.DeleteContactReply, error) { func (core *RicochetCore) DeleteContact(ctx context.Context, req *rpc.DeleteContactRequest) (*rpc.DeleteContactReply, error) {
return nil, NotImplementedError contactList := core.Identity().ContactList()
contact := contactList.ContactByAddress(req.Address)
if contact == nil || (req.Id != 0 && contact.Id() != int(req.Id)) {
return nil, errors.New("Contact not found")
}
if err := contactList.RemoveContact(contact); err != nil {
return nil, err
}
return &rpc.DeleteContactReply{}, nil
} }
func (core *RicochetCore) AcceptInboundRequest(ctx context.Context, req *rpc.ContactRequest) (*rpc.Contact, error) { func (core *RicochetCore) AcceptInboundRequest(ctx context.Context, req *rpc.ContactRequest) (*rpc.Contact, error) {

View File

@ -3,17 +3,26 @@ package core
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/special/notricochet/core/utils"
"github.com/special/notricochet/rpc"
"strconv" "strconv"
"sync"
) )
type ContactList struct { type ContactList struct {
mutex sync.RWMutex
events *utils.Publisher
contacts map[int]*Contact contacts map[int]*Contact
outboundRequests map[int]*OutboundContactRequest outboundRequests map[int]*OutboundContactRequest
inboundRequests map[int]*InboundContactRequest inboundRequests map[int]*InboundContactRequest
} }
func LoadContactList(core Ricochet) (*ContactList, error) { func LoadContactList(core Ricochet) (*ContactList, error) {
list := &ContactList{} list := &ContactList{
events: utils.CreatePublisher(),
}
config := core.Config().OpenRead() config := core.Config().OpenRead()
defer config.Close() defer config.Close()
@ -38,7 +47,13 @@ func LoadContactList(core Ricochet) (*ContactList, error) {
return list, nil return list, nil
} }
func (this *ContactList) EventMonitor() utils.Subscribable {
return this.events
}
func (this *ContactList) Contacts() []*Contact { func (this *ContactList) Contacts() []*Contact {
this.mutex.RLock()
defer this.mutex.RUnlock()
re := make([]*Contact, 0, len(this.contacts)) re := make([]*Contact, 0, len(this.contacts))
for _, contact := range this.contacts { for _, contact := range this.contacts {
re = append(re, contact) re = append(re, contact)
@ -47,6 +62,8 @@ func (this *ContactList) Contacts() []*Contact {
} }
func (this *ContactList) OutboundRequests() []*OutboundContactRequest { func (this *ContactList) OutboundRequests() []*OutboundContactRequest {
this.mutex.RLock()
defer this.mutex.RUnlock()
re := make([]*OutboundContactRequest, 0, len(this.outboundRequests)) re := make([]*OutboundContactRequest, 0, len(this.outboundRequests))
for _, request := range this.outboundRequests { for _, request := range this.outboundRequests {
re = append(re, request) re = append(re, request)
@ -55,6 +72,8 @@ func (this *ContactList) OutboundRequests() []*OutboundContactRequest {
} }
func (this *ContactList) InboundRequests() []*InboundContactRequest { func (this *ContactList) InboundRequests() []*InboundContactRequest {
this.mutex.RLock()
defer this.mutex.RUnlock()
re := make([]*InboundContactRequest, 0, len(this.inboundRequests)) re := make([]*InboundContactRequest, 0, len(this.inboundRequests))
for _, request := range this.inboundRequests { for _, request := range this.inboundRequests {
re = append(re, request) re = append(re, request)
@ -63,10 +82,14 @@ func (this *ContactList) InboundRequests() []*InboundContactRequest {
} }
func (this *ContactList) ContactById(id int) *Contact { func (this *ContactList) ContactById(id int) *Contact {
this.mutex.RLock()
defer this.mutex.RUnlock()
return this.contacts[id] return this.contacts[id]
} }
func (this *ContactList) ContactByAddress(address string) *Contact { func (this *ContactList) ContactByAddress(address string) *Contact {
this.mutex.RLock()
defer this.mutex.RUnlock()
for _, contact := range this.contacts { for _, contact := range this.contacts {
if contact.Address() == address { if contact.Address() == address {
return contact return contact
@ -75,10 +98,33 @@ func (this *ContactList) ContactByAddress(address string) *Contact {
return nil return nil
} }
func (contacts *ContactList) AddContact(address string, name string) (*Contact, error) { func (this *ContactList) AddContact(address string, name string) (*Contact, error) {
return nil, errors.New("Not implemented") return nil, errors.New("Not implemented")
} }
func (contacts *ContactList) RemoveContactById(id int) error { func (this *ContactList) RemoveContact(contact *Contact) error {
return errors.New("Not implemented") this.mutex.Lock()
defer this.mutex.Unlock()
if this.contacts[contact.Id()] != contact {
return errors.New("Not in contact list")
}
// XXX Not persisting in config
// XXX This will have to do some things to the contact itself
// eventually too, such as killing connections and other resources.
delete(this.contacts, contact.Id())
event := ricochet.ContactEvent{
Type: ricochet.ContactEvent_DELETE,
Subject: &ricochet.ContactEvent_Contact{
Contact: &ricochet.Contact{
Id: int32(contact.Id()),
Address: contact.Address(),
},
},
}
this.events.Publish(event)
return nil
} }

View File

@ -120,7 +120,7 @@ func (n *Network) GetStatus() ricochet.NetworkStatus {
// May return nil on failure, and the returned connection can be closed // May return nil on failure, and the returned connection can be closed
// or otherwise fail at any time. // or otherwise fail at any time.
func (n *Network) getConnection() *bulb.Conn { func (n *Network) getConnection() *bulb.Conn {
// Optimistically try to get a connection before subscribin to events // Optimistically try to get a connection before subscribing to events
n.controlMutex.Lock() n.controlMutex.Lock()
conn := n.conn conn := n.conn
n.controlMutex.Unlock() n.controlMutex.Unlock()