Updating Group Chat invite, fixing test errors

This commit is contained in:
Sarah Jamie Lewis 2018-03-14 15:03:53 -07:00
parent 440ffb64ef
commit d47b165bab
10 changed files with 77 additions and 186 deletions

View File

@ -93,7 +93,10 @@ func (p *Profile) StartGroup(server string) (groupID string, invite []byte) {
GroupSharedKey: group.GroupKey[:],
ServerHost: server,
}
invite, err := proto.Marshal(gci)
cp := &protocol.CwtchPeerPacket{
GroupChatInvite: gci,
}
invite, err := proto.Marshal(cp)
utils.CheckError(err)
return
}

View File

@ -1 +1 @@
{"Name":"Sarah","Ed25519PublicKey":"a8pgrWp2v1IIQCyULC2iu1qL1drQ5t2U6IWP8StQbgQ=","Contacts":{},"Ed25519PrivateKey":"prCl0X2vmZf7Mk3llqvFtdorNumzHnGnD4jm3QMuSxZrymCtana/UghALJQsLaK7WovV2tDm3ZTohY/xK1BuBA==","OnionPrivateKey":{"N":131068731621357493720072929300222638098708595317493690917455701844894949969712456924415904360558466676729758490034054382690670564021915749623913489576811414808490682341447683428107033511871993975442547751364987326228375564356319863018740191894673856750381991533992750928853175751258987424504305668829389370781,"E":65537,"D":2627894370362753051683412867547988868298870779058954634260597711585699135758459624314242310904890751990828122372167591724606575234215745227975377653904361946969317142822427004567032046170712030718609055500182294452975841610151524604548863606200879307458625483418780389791138043842317728008422567429265129217,"Primes":[10788225097346971746043305034916905885872150156656727758248727746432901839298229013945049979389606656460780955780310528453022789715728380260987737082720253,12149239605094054781678325910916206629901461735333362155233083066169807219934646408991015480595627046734476920828757029582713785879808385848485040747462177],"Precomputed":{"Dp":5173284558864813480368386519558930089496071882650273635633043424129069168616589761833026926808934928248057785637240321920337324143555484786640548290258165,"Dq":6738186996138955142964184967422712034173952594044540452239377806264250008852778242428024332647052075845778218689956215744884274366529978620027377833723777,"Qinv":5251104905219058958861116066024964644816198404536226338388786686281405794213358346986237142459566456065203273657491361435682285121728843067653981338100228,"CRTValues":[]}},"Groups":{}}
{"Name":"Sarah","Ed25519PublicKey":"msKO36i2l86zvEL175TKZEC0nD73g2v7nV5xmK0Vphk=","Contacts":{},"Ed25519PrivateKey":"gY02OGDQrUZmtgrGE8Vc75m+YpveuiBnq7S04R6hDheawo7fqLaXzrO8QvXvlMpkQLScPveDa/udXnGYrRWmGQ==","OnionPrivateKey":{"N":149473818603978520797265583326345889632722230289009522405338669742795723417758103856403611357040387558433860451515052572608570172648790617938713499325164649087791083575310232535396589977906388592625399123963785709861980287466698616117387601534139103746310242068634673611193675737864910207364356589966194353473,"E":65537,"D":86372179235129264119389774334631106709052761967206167714270952639877840698086567786777007829029700426291870169505394524080848260344686218492440609418252045928103604805029397268780872419743985198533279610220673486415102569608190490192041308974054759325240302029165831212246096675348836655257812290267217972353,"Primes":[12798859654138079143364344404787850219664210052105976906571980247193551352543964631210504198681240048855374604305718740175510657834512957821516486884913417,11678682526661756792661834016830595869008788319138001870469300096518673413667724031509428867627103613547399458382675739150139741094498852501694360147458169],"Precomputed":{"Dp":8019280314598958509909975651827265416025626094719436802334028486053813863764176261522451957069254926623865104850782437826372799222707868639469788073228857,"Dq":8119140840742831728447418732545517936185336731870022143557414147696473718258828483507523964582237435959024888579450875492602146630873502261046407938088241,"Qinv":1212466450879442551713910248017765796626002260907864986369164997419826127998002105201194295184151193998884696413793530693071388392214893165411485014542824,"CRTValues":[]}},"Groups":{}}

View File

@ -29,7 +29,7 @@ func TestProfileIdentity(t *testing.T) {
if err != nil {
t.Errorf("alice should have added sarah as a contact %v", err)
}
alice.AddCwtchIdentity("sarah.onion", *ci)
alice.AddCwtchIdentity("sarah.onion", ci)
if alice.Contacts["sarah.onion"].Name != "Sarah" {
t.Errorf("alice should have added sarah as a contact %v", alice.Contacts)
}

View File

@ -2,24 +2,24 @@ package connections
import (
"crypto/rsa"
"git.mascherari.press/cwtch/model"
"git.mascherari.press/cwtch/peer/peer"
"git.mascherari.press/cwtch/protocol"
"github.com/s-rah/go-ricochet"
"github.com/s-rah/go-ricochet/channels"
"github.com/s-rah/go-ricochet/connection"
"github.com/s-rah/go-ricochet/identity"
"github.com/s-rah/go-ricochet/utils"
"github.com/s-rah/go-ricochet/channels"
"net"
"testing"
"time"
"git.mascherari.press/cwtch/model"
"git.mascherari.press/cwtch/protocol"
"git.mascherari.press/cwtch/peer/peer"
)
func PeerAuthValid(hostname string, publicKey rsa.PublicKey) (allowed, known bool) {
return true, true
}
func runtestpeer(t *testing.T,tp *TestPeer) {
func runtestpeer(t *testing.T, tp *TestPeer) {
ln, _ := net.Listen("tcp", "127.0.0.1:5452")
conn, _ := ln.Accept()
defer conn.Close()
@ -42,23 +42,40 @@ func runtestpeer(t *testing.T,tp *TestPeer) {
return peer
})
go func() {
alice := model.GenerateNewProfile("alice")
time.Sleep(time.Second * 1)
rc.Do(func() error {
channel := rc.Channel("im.cwtch.peer", channels.Inbound)
if channel != nil {
peerchannel, ok := channel.Handler.(*peer.CwtchPeerChannel)
if ok {
peerchannel.SendMessage(alice.GetCwtchIdentityPacket())
}
}
return nil
})
}()
rc.Process(tp)
}
type TestPeer struct {
connection.AutoConnectionHandler
ReceivedIdentityPacket bool
connection.AutoConnectionHandler
ReceivedIdentityPacket bool
ReceivedGroupInvite bool
}
func (tp *TestPeer) ClientIdentity(ci *protocol.CwtchIdentity) {
tp.ReceivedIdentityPacket = true
tp.ReceivedIdentityPacket = true
}
func (tp *TestPeer) HandleGroupInvite(gci *protocol.GroupChatInvite) {
tp.ReceivedGroupInvite = true
}
func TestPeerPeerConnection(t *testing.T) {
profile := model.GenerateNewProfile("sarah")
profile := model.GenerateNewProfile("sarah")
ppc := NewPeerPeerConnection("127.0.0.1:5452|kwke2hntvyfqm7dr", profile)
//numcalls := 0
tp := new(TestPeer)
@ -74,8 +91,16 @@ func TestPeerPeerConnection(t *testing.T) {
if state != AUTHENTICATED {
t.Errorf("connection state should be authenticated(3), was instead %v", state)
}
if tp.ReceivedIdentityPacket == false {
t.Errorf("should have received an identity packet")
t.Errorf("should have received an identity packet")
}
_, invite := profile.StartGroup("aaa.onion")
ppc.SendGroupInvite(invite)
time.Sleep(time.Second * 3)
if tp.ReceivedGroupInvite == false {
t.Errorf("should have received an group invite packet")
}
}

View File

@ -2,6 +2,7 @@ package connections
import (
"git.mascherari.press/cwtch/peer/fetch"
"git.mascherari.press/cwtch/peer/listen"
"git.mascherari.press/cwtch/peer/send"
"git.mascherari.press/cwtch/protocol"
"github.com/s-rah/go-ricochet"
@ -51,6 +52,11 @@ func (psc *PeerServerConnection) Run() error {
psc.connection.RequestOpenChannel("im.cwtch.server.fetch", &fetch.CwtchPeerFetchChannel{Handler: psc})
return nil
})
psc.connection.Do(func() error {
psc.connection.RequestOpenChannel("im.cwtch.server.listen", &listen.CwtchPeerListenChannel{Handler: psc})
return nil
})
}()
psc.connection.Process(psc)

View File

@ -3,12 +3,12 @@ package peer
import (
"encoding/json"
"git.mascherari.press/cwtch/model"
"git.mascherari.press/cwtch/peer/connections"
"git.mascherari.press/cwtch/peer/peer"
"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"
)
@ -35,11 +35,13 @@ func (cpi *CwtchPeerInstance) Init(rai *application.ApplicationInstance, ra *app
type CwtchPeer struct {
connection.AutoConnectionHandler
Profile *model.Profile
PendingContacts []string
PendingInvites map[string][]string
mutex sync.Mutex
Log chan string `json:"-"`
Profile *model.Profile
PendingContacts []string
PendingInvites map[string][]string
mutex sync.Mutex
Log chan string `json:"-"`
peerconnections map[string]*connections.PeerPeerConnection
serverconnections map[string]*connections.PeerServerConnection
}
func NewCwtchPeer(name string) *CwtchPeer {
@ -47,13 +49,15 @@ func NewCwtchPeer(name string) *CwtchPeer {
peer.Profile = model.GenerateNewProfile(name)
peer.PendingInvites = make(map[string][]string)
peer.Log = make(chan string)
peer.peerconnections = make(map[string]*connections.PeerPeerConnection)
peer.serverconnections = make(map[string]*connections.PeerServerConnection)
peer.Init()
return peer
}
func (cp *CwtchPeer) Save(profilefile string) error {
cp.mutex.Lock()
bytes,_ := json.Marshal(cp)
bytes, _ := json.Marshal(cp)
err := ioutil.WriteFile(profilefile, bytes, 0600)
cp.mutex.Unlock()
return err
@ -81,10 +85,6 @@ func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) {
cp.mutex.Unlock()
}
func (cp *CwtchPeer) PeerListen(onion string) {
}
func (cp *CwtchPeer) JoinServer(onion string) {
}
@ -110,9 +110,9 @@ func (cp *CwtchPeer) Listen() error {
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
cpc := new(peer.CwtchPeerChannel)
cpc.Handler = &CwtchPeerHandler{Onion: rai.RemoteHostname, Peer: cp}
return cpc
}
})
@ -123,52 +123,7 @@ func (cp *CwtchPeer) Listen() error {
}
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 {
@ -178,10 +133,11 @@ type CwtchPeerHandler struct {
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)
cph.Peer.Profile.AddCwtchIdentity(cph.Onion, ci)
}
func (cph *CwtchPeerHandler) HandleGroupInvite() {
func (cph *CwtchPeerHandler) HandleGroupInvite(gci *protocol.GroupChatInvite) {
cph.Peer.Profile.ProcessInvite(gci)
}
func (cph *CwtchPeerHandler) HandleGroupMessage(gm *protocol.GroupMessage) {

View File

@ -5,11 +5,13 @@ import (
)
func TestCwtchPeerGenerate(t *testing.T) {
sarah := NewCwtchPeer("sarah")
sarah.Save("./test_profile")
sarahLoaded, err := LoadCwtchPeer("./test_profile")
if err != nil || sarahLoaded.Profile.Name != "sarah" {
t.Errorf("something went wrong saving and loading profiles %v %v", err, sarahLoaded)
alice := NewCwtchPeer("alice")
alice.Save("./test_profile")
aliceLoaded, err := LoadCwtchPeer("./test_profile")
if err != nil || aliceLoaded.Profile.Name != "alice" {
t.Errorf("something went wrong saving and loading profiles %v %v", err, aliceLoaded)
}
//t.Logf("%v", sarahLoaded)
}

View File

@ -54,6 +54,8 @@ func TestPeerFetchChannel(t *testing.T) {
pfc.Handler = th
channel := new(channels.Channel)
channel.ID = 3
channel.SendMessage = func([]byte) {}
channel.CloseChannel = func() {}
result, err := pfc.OpenOutbound(channel)
if err != nil {
t.Errorf("expected result but also got non-nil error: result:%v, err: %v", result, err)

View File

@ -100,7 +100,7 @@ func (cpc *CwtchPeerChannel) Packet(data []byte) {
if cpp.GetCwtchIdentify() != nil {
cpc.Handler.ClientIdentity(cpp.GetCwtchIdentify())
} else if cpp.GetGroupChatInvite() != nil {
cpc.Handler.HandleGroupInvite(cpp.GetGroupChatInvite())
cpc.Handler.HandleGroupInvite(cpp.GetGroupChatInvite())
}
}
}

View File

@ -1,103 +0,0 @@
package protocol
import (
"github.com/golang/protobuf/proto"
"github.com/s-rah/go-ricochet/channels"
"github.com/s-rah/go-ricochet/utils"
"github.com/s-rah/go-ricochet/wire/control"
)
// CwtchPeerChannel implements the ChannelHandler interface for a channel of
// type "im.ricochet.Cwtch". The channel may be inbound or outbound.
//
// CwtchPeerChannel implements protocol-level sanity and state validation, but
// does not handle or acknowledge Cwtch messages. The application must provide
// a CwtchPeerChannelHandler implementation to handle Cwtch events.
type CwtchPeerChannel struct {
// Methods of Handler are called for Cwtch events on this channel
Handler CwtchPeerChannelHandler
channel *channels.Channel
}
// CwtchPeerChannelHandler is implemented by an application type to receive
// events from a CwtchPeerChannel.
type CwtchPeerChannelHandler interface {
ClientIdentity(*CwtchIdentity)
HandleGroupInvite()
}
// Type returns the type string for this channel, e.g. "im.ricochet.Cwtch".
func (cpc *CwtchPeerChannel) SendMessage(data []byte) {
cpc.channel.SendMessage(data)
}
// Type returns the type string for this channel, e.g. "im.ricochet.Cwtch".
func (cpc *CwtchPeerChannel) Type() string {
return "im.cwtch.peer"
}
// Closed is called when the channel is closed for any reason.
func (cpc *CwtchPeerChannel) Closed(err error) {
}
// OnlyClientCanOpen - for Cwtch channels any side can open
func (cpc *CwtchPeerChannel) OnlyClientCanOpen() bool {
return false
}
// Singleton - for Cwtch channels there can only be one instance per direction
func (cpc *CwtchPeerChannel) Singleton() bool {
return true
}
// Bidirectional - for Cwtch channels are not bidrectional
func (cpc *CwtchPeerChannel) Bidirectional() bool {
return false
}
// RequiresAuthentication - Cwtch channels require hidden service auth
func (cpc *CwtchPeerChannel) RequiresAuthentication() string {
return "im.ricochet.auth.hidden-service"
}
// OpenInbound is the first method called for an inbound channel request.
// If an error is returned, the channel is rejected. If a RawMessage is
// returned, it will be sent as the ChannelResult message.
func (cpc *CwtchPeerChannel) OpenInbound(channel *channels.Channel, raw *Protocol_Data_Control.OpenChannel) ([]byte, error) {
cpc.channel = channel
messageBuilder := new(utils.MessageBuilder)
return messageBuilder.AckOpenChannel(channel.ID), nil
}
// OpenOutbound is the first method called for an outbound channel request.
// If an error is returned, the channel is not opened. If a RawMessage is
// returned, it will be sent as the OpenChannel message.
func (cpc *CwtchPeerChannel) OpenOutbound(channel *channels.Channel) ([]byte, error) {
cpc.channel = channel
messageBuilder := new(utils.MessageBuilder)
return messageBuilder.OpenChannel(channel.ID, cpc.Type()), nil
}
// OpenOutboundResult is called when a response is received for an
// outbound OpenChannel request. If `err` is non-nil, the channel was
// rejected and Closed will be called immediately afterwards. `raw`
// contains the raw protocol message including any extension data.
func (cpc *CwtchPeerChannel) OpenOutboundResult(err error, crm *Protocol_Data_Control.ChannelResult) {
if err == nil {
if crm.GetOpened() {
cpc.channel.Pending = false
}
}
}
// Packet is called for each raw packet received on this channel.
func (cpc *CwtchPeerChannel) Packet(data []byte) {
cpp := &CwtchPeerPacket{}
err := proto.Unmarshal(data, cpp)
if err == nil {
if cpp.GetCwtchIdentify() != nil {
cpc.Handler.ClientIdentity(cpp.GetCwtchIdentify())
}
}
}