forked from cwtch.im/cwtch
Merge branch 'test-fetch' of dan/cwtch into master
This commit is contained in:
commit
6b0aaf174d
|
@ -107,7 +107,6 @@ func (ppc *PeerPeerConnection) Run() error {
|
||||||
// Close closes the connection
|
// Close closes the connection
|
||||||
func (ppc *PeerPeerConnection) Close() {
|
func (ppc *PeerPeerConnection) Close() {
|
||||||
ppc.state = KILLED
|
ppc.state = KILLED
|
||||||
ppc.connection.Break()
|
ppc.connection.Conn.Close()
|
||||||
// TODO We should kill the connection outright, but we need to add that to libricochet-go
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"cwtch.im/cwtch/protocol"
|
"cwtch.im/cwtch/protocol"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"github.com/s-rah/go-ricochet/application"
|
"github.com/s-rah/go-ricochet/application"
|
||||||
"github.com/s-rah/go-ricochet/channels"
|
"github.com/s-rah/go-ricochet/channels"
|
||||||
"github.com/s-rah/go-ricochet/connection"
|
"github.com/s-rah/go-ricochet/connection"
|
||||||
|
@ -86,7 +85,7 @@ 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 {
|
||||||
fmt.Printf("Constructing invite for group: %v\n", group)
|
log.Printf("Constructing invite for group: %v\n", group)
|
||||||
invite, err := group.Invite()
|
invite, err := group.Invite()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -96,7 +95,7 @@ func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
|
||||||
return errors.New("peer connection not setup for onion. peers must be trusted before sending")
|
return errors.New("peer connection not setup for onion. peers must be trusted before sending")
|
||||||
}
|
}
|
||||||
if ppc.GetState() == connections.AUTHENTICATED {
|
if ppc.GetState() == connections.AUTHENTICATED {
|
||||||
fmt.Printf("Got connection for group: %v - Sending Invite\n", ppc)
|
log.Printf("Got connection for group: %v - Sending Invite\n", ppc)
|
||||||
ppc.SendGroupInvite(invite)
|
ppc.SendGroupInvite(invite)
|
||||||
} else {
|
} else {
|
||||||
return errors.New("cannot send invite to onion: peer connection is not ready")
|
return errors.New("cannot send invite to onion: peer connection is not ready")
|
||||||
|
@ -120,7 +119,7 @@ func (cp *CwtchPeer) JoinServer(onion string) {
|
||||||
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 exit")
|
return errors.New("group does not exist")
|
||||||
}
|
}
|
||||||
psc := cp.connectionsManager.GetPeerServerConnectionForOnion(group.GroupServer)
|
psc := cp.connectionsManager.GetPeerServerConnectionForOnion(group.GroupServer)
|
||||||
if psc == nil {
|
if psc == nil {
|
||||||
|
|
|
@ -74,13 +74,18 @@ func (cpfc *CwtchPeerFetchChannel) OpenOutboundResult(err error, crm *Protocol_D
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchRequest sends a FetchMessage to the Server.
|
// FetchRequest sends a FetchMessage to the Server.
|
||||||
func (cpfc *CwtchPeerFetchChannel) FetchRequest() {
|
func (cpfc *CwtchPeerFetchChannel) FetchRequest() error {
|
||||||
|
if cpfc.channel.Pending == false {
|
||||||
fm := &protocol.FetchMessage{}
|
fm := &protocol.FetchMessage{}
|
||||||
csp := &protocol.CwtchServerPacket{
|
csp := &protocol.CwtchServerPacket{
|
||||||
FetchMessage: fm,
|
FetchMessage: fm,
|
||||||
}
|
}
|
||||||
packet, _ := proto.Marshal(csp)
|
packet, _ := proto.Marshal(csp)
|
||||||
cpfc.channel.SendMessage(packet)
|
cpfc.channel.SendMessage(packet)
|
||||||
|
} else {
|
||||||
|
return errors.New("channel isn't set up yet")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packet is called for each raw packet received on this channel.
|
// Packet is called for each raw packet received on this channel.
|
||||||
|
@ -88,13 +93,11 @@ func (cpfc *CwtchPeerFetchChannel) Packet(data []byte) {
|
||||||
csp := &protocol.CwtchServerPacket{}
|
csp := &protocol.CwtchServerPacket{}
|
||||||
err := proto.Unmarshal(data, csp)
|
err := proto.Unmarshal(data, csp)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if csp.GetGroupMessages() != nil {
|
if csp.GetGroupMessage() != nil {
|
||||||
gms := csp.GetGroupMessages()
|
gm := csp.GetGroupMessage()
|
||||||
for _, gm := range gms {
|
// We create a new go routine here to avoid leaking any information about processing time
|
||||||
cpfc.Handler.HandleGroupMessage(gm)
|
// TODO Server can probably try to use this to DoS a peer
|
||||||
|
go cpfc.Handler.HandleGroupMessage(gm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// After a fetch we close the channel.
|
|
||||||
cpfc.channel.CloseChannel()
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/s-rah/go-ricochet/channels"
|
"github.com/s-rah/go-ricochet/channels"
|
||||||
"github.com/s-rah/go-ricochet/wire/control"
|
"github.com/s-rah/go-ricochet/wire/control"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestHandler struct {
|
type TestHandler struct {
|
||||||
|
@ -72,14 +73,16 @@ func TestPeerFetchChannel(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
csp := &protocol.CwtchServerPacket{
|
csp := &protocol.CwtchServerPacket{
|
||||||
GroupMessages: []*protocol.GroupMessage{
|
GroupMessage: &protocol.GroupMessage{
|
||||||
{Ciphertext: []byte("hello"), Spamguard: []byte{}},
|
Ciphertext: []byte("hello"), Spamguard: []byte{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
packet, _ := proto.Marshal(csp)
|
packet, _ := proto.Marshal(csp)
|
||||||
|
|
||||||
pfc.Packet(packet)
|
pfc.Packet(packet)
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
|
||||||
if th.Received != true {
|
if th.Received != true {
|
||||||
t.Errorf("group message should not have been received")
|
t.Errorf("group message should not have been received")
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,71 +18,71 @@ type CwtchPeerSendChannel struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the type string for this channel, e.g. "im.ricochet.server.send".
|
// Type returns the type string for this channel, e.g. "im.ricochet.server.send".
|
||||||
func (cplc *CwtchPeerSendChannel) Type() string {
|
func (cpsc *CwtchPeerSendChannel) Type() string {
|
||||||
return "im.cwtch.server.send"
|
return "im.cwtch.server.send"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closed is called when the channel is closed for any reason.
|
// Closed is called when the channel is closed for any reason.
|
||||||
func (cplc *CwtchPeerSendChannel) Closed(err error) {
|
func (cpsc *CwtchPeerSendChannel) Closed(err error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnlyClientCanOpen - for Cwtch server channels only peers may open.
|
// OnlyClientCanOpen - for Cwtch server channels only peers may open.
|
||||||
func (cplc *CwtchPeerSendChannel) OnlyClientCanOpen() bool {
|
func (cpsc *CwtchPeerSendChannel) OnlyClientCanOpen() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Singleton - for Cwtch channels there can only be one instance per direction
|
// Singleton - for Cwtch channels there can only be one instance per direction
|
||||||
func (cplc *CwtchPeerSendChannel) Singleton() bool {
|
func (cpsc *CwtchPeerSendChannel) Singleton() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bidirectional - for Cwtch channels are not bidrectional
|
// Bidirectional - for Cwtch channels are not bidrectional
|
||||||
func (cplc *CwtchPeerSendChannel) Bidirectional() bool {
|
func (cpsc *CwtchPeerSendChannel) Bidirectional() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiresAuthentication - Cwtch channels require no auth
|
// RequiresAuthentication - Cwtch channels require no auth
|
||||||
func (cplc *CwtchPeerSendChannel) RequiresAuthentication() string {
|
func (cpsc *CwtchPeerSendChannel) RequiresAuthentication() string {
|
||||||
return "none"
|
return "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenInbound should never be called on peers.
|
// OpenInbound should never be called on peers.
|
||||||
func (cplc *CwtchPeerSendChannel) OpenInbound(channel *channels.Channel, raw *Protocol_Data_Control.OpenChannel) ([]byte, error) {
|
func (cpsc *CwtchPeerSendChannel) OpenInbound(channel *channels.Channel, raw *Protocol_Data_Control.OpenChannel) ([]byte, error) {
|
||||||
return nil, errors.New("client does not receive inbound listen channels")
|
return nil, errors.New("client does not receive inbound listen channels")
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenOutbound is used to set up a new send channel and initialize spamguard
|
// OpenOutbound is used to set up a new send channel and initialize spamguard
|
||||||
func (cplc *CwtchPeerSendChannel) OpenOutbound(channel *channels.Channel) ([]byte, error) {
|
func (cpsc *CwtchPeerSendChannel) OpenOutbound(channel *channels.Channel) ([]byte, error) {
|
||||||
cplc.spamGuard.Difficulty = 2
|
cpsc.spamGuard.Difficulty = 2
|
||||||
cplc.channel = channel
|
cpsc.channel = channel
|
||||||
messageBuilder := new(utils.MessageBuilder)
|
messageBuilder := new(utils.MessageBuilder)
|
||||||
return messageBuilder.OpenChannel(channel.ID, cplc.Type()), nil
|
return messageBuilder.OpenChannel(channel.ID, cpsc.Type()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenOutboundResult confirms the open channel request and sets the spamguard challenge
|
// OpenOutboundResult confirms the open channel request and sets the spamguard challenge
|
||||||
func (cplc *CwtchPeerSendChannel) OpenOutboundResult(err error, crm *Protocol_Data_Control.ChannelResult) {
|
func (cpsc *CwtchPeerSendChannel) OpenOutboundResult(err error, crm *Protocol_Data_Control.ChannelResult) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if crm.GetOpened() {
|
if crm.GetOpened() {
|
||||||
cplc.channel.Pending = false
|
cpsc.channel.Pending = false
|
||||||
ce, _ := proto.GetExtension(crm, protocol.E_ServerNonce)
|
ce, _ := proto.GetExtension(crm, protocol.E_ServerNonce)
|
||||||
cplc.challenge = ce.([]byte)[:]
|
cpsc.challenge = ce.([]byte)[:]
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendGroupMessage performs the spamguard proof of work and sends a message.
|
// SendGroupMessage performs the spamguard proof of work and sends a message.
|
||||||
func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) error {
|
func (cpsc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) error {
|
||||||
if cplc.channel.Pending == false {
|
if cpsc.channel.Pending == false {
|
||||||
sgsolve := cplc.spamGuard.SolveChallenge(cplc.challenge, gm.GetCiphertext())
|
sgsolve := cpsc.spamGuard.SolveChallenge(cpsc.challenge, gm.GetCiphertext())
|
||||||
gm.Spamguard = sgsolve[:]
|
gm.Spamguard = sgsolve[:]
|
||||||
csp := &protocol.CwtchServerPacket{
|
csp := &protocol.CwtchServerPacket{
|
||||||
GroupMessage: gm,
|
GroupMessage: gm,
|
||||||
}
|
}
|
||||||
packet, _ := proto.Marshal(csp)
|
packet, _ := proto.Marshal(csp)
|
||||||
cplc.channel.SendMessage(packet)
|
cpsc.channel.SendMessage(packet)
|
||||||
cplc.channel.CloseChannel()
|
cpsc.channel.CloseChannel()
|
||||||
} else {
|
} else {
|
||||||
return errors.New("channel isn't set up yet")
|
return errors.New("channel isn't set up yet")
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) er
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packet should never be
|
// Packet should never be
|
||||||
func (cplc *CwtchPeerSendChannel) Packet(data []byte) {
|
func (cpsc *CwtchPeerSendChannel) Packet(data []byte) {
|
||||||
// If we receive a packet on this channel, close the connection
|
// If we receive a packet on this channel, close the connection
|
||||||
cplc.channel.CloseChannel()
|
cpsc.channel.CloseChannel()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ var _ = math.Inf
|
||||||
type CwtchServerPacket struct {
|
type CwtchServerPacket struct {
|
||||||
GroupMessage *GroupMessage `protobuf:"bytes,1,opt,name=group_message,json=groupMessage" json:"group_message,omitempty"`
|
GroupMessage *GroupMessage `protobuf:"bytes,1,opt,name=group_message,json=groupMessage" json:"group_message,omitempty"`
|
||||||
FetchMessage *FetchMessage `protobuf:"bytes,2,opt,name=fetch_message,json=fetchMessage" json:"fetch_message,omitempty"`
|
FetchMessage *FetchMessage `protobuf:"bytes,2,opt,name=fetch_message,json=fetchMessage" json:"fetch_message,omitempty"`
|
||||||
GroupMessages []*GroupMessage `protobuf:"bytes,3,rep,name=group_messages,json=groupMessages" json:"group_messages,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,13 +38,6 @@ func (m *CwtchServerPacket) GetFetchMessage() *FetchMessage {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CwtchServerPacket) GetGroupMessages() []*GroupMessage {
|
|
||||||
if m != nil {
|
|
||||||
return m.GroupMessages
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type FetchMessage struct {
|
type FetchMessage struct {
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import "ControlChannel.proto";
|
||||||
message CwtchServerPacket {
|
message CwtchServerPacket {
|
||||||
optional GroupMessage group_message = 1;
|
optional GroupMessage group_message = 1;
|
||||||
optional FetchMessage fetch_message = 2;
|
optional FetchMessage fetch_message = 2;
|
||||||
repeated GroupMessage group_messages = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extend protocol.ChannelResult {
|
extend protocol.ChannelResult {
|
||||||
|
|
|
@ -75,13 +75,16 @@ func (cc *CwtchServerFetchChannel) OpenOutboundResult(err error, crm *Protocol_D
|
||||||
// NOTE: Should never be called
|
// NOTE: Should never be called
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendGroupMessages sends a batch of group messages to the client.
|
// SendGroupMessages sends a series of group messages to the client.
|
||||||
func (cc *CwtchServerFetchChannel) SendGroupMessages(gm []*protocol.GroupMessage) {
|
func (cc *CwtchServerFetchChannel) SendGroupMessages(gms []*protocol.GroupMessage) {
|
||||||
csp := &protocol.CwtchServerPacket{}
|
for _, gm := range gms {
|
||||||
csp.GroupMessages = gm
|
csp := &protocol.CwtchServerPacket{
|
||||||
|
GroupMessage: gm,
|
||||||
|
}
|
||||||
packet, _ := proto.Marshal(csp)
|
packet, _ := proto.Marshal(csp)
|
||||||
cc.channel.SendMessage(packet)
|
cc.channel.SendMessage(packet)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Packet is called for each raw packet received on this channel.
|
// Packet is called for each raw packet received on this channel.
|
||||||
func (cc *CwtchServerFetchChannel) Packet(data []byte) {
|
func (cc *CwtchServerFetchChannel) Packet(data []byte) {
|
||||||
|
|
|
@ -7,47 +7,57 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/s-rah/go-ricochet"
|
"github.com/s-rah/go-ricochet"
|
||||||
"github.com/s-rah/go-ricochet/utils"
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
"crypto/rsa"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
keyfile = "./private_key"
|
serverKeyfile = "./../server/app/private_key"
|
||||||
|
localKeyfile = "./private_key"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
aliceLines = []string{"Hello", "My name is Alice", "bye"}
|
aliceLines = []string{"Hello, I'm Alice", "bye"}
|
||||||
bobLines = []string{"Hi", "My name is Bob.", "toodles", "hello?"}
|
bobLines = []string{"Hi, my name is Bob.", "toodles", "welcome"}
|
||||||
|
carolLines = []string{"Howdy, thanks!"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkAndGenPrivateKey(privateKeyFile string) (generated bool) {
|
func loadOrGenPrivateKey(t *testing.T) (pk *rsa.PrivateKey, generated bool) {
|
||||||
if _, err := os.Stat(privateKeyFile); os.IsNotExist(err) {
|
if _, err := os.Stat(serverKeyfile); os.IsNotExist(err) {
|
||||||
fmt.Println("generating new private key...")
|
fmt.Println("generating new private key...")
|
||||||
pk, err := utils.GeneratePrivateKey()
|
pk, err := utils.GeneratePrivateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("error generating new private key: %v\n", err)
|
t.Fatalf("error generating new private key: %v\n", err)
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(privateKeyFile, []byte(utils.PrivateKeyToString(pk)), 0400)
|
err = ioutil.WriteFile(localKeyfile, []byte(utils.PrivateKeyToString(pk)), 0400)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("error writing new private key to file %s: %v\n", privateKeyFile, err)
|
log.Fatalf("error writing new private key to file %s: %v\n", localKeyfile, err)
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printAndVerifyTimeline(t *testing.T, timeline []model.Message) error {
|
return pk,true
|
||||||
|
}
|
||||||
|
fmt.Println("Found server key " + serverKeyfile + ", loading...")
|
||||||
|
pk, err := utils.LoadPrivateKeyFromFile(serverKeyfile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Could not load server's key from %v", serverKeyfile)
|
||||||
|
}
|
||||||
|
return pk, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func printAndCountVerifedTimeline(t *testing.T, timeline []model.Message) int {
|
||||||
|
numVerified := 0
|
||||||
for _, message := range timeline {
|
for _, message := range timeline {
|
||||||
fmt.Printf("%v %v> %s [%t]\n", message.Timestamp, message.PeerID, message.Message, message.Verified)
|
fmt.Printf("%v %v> %s [%t]\n", message.Timestamp, message.PeerID, message.Message, message.Verified)
|
||||||
if !message.Verified {
|
if message.Verified {
|
||||||
t.Errorf("Message '%s' from '%s' not verified!", message.Message, message.PeerID)
|
numVerified++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return numVerified
|
||||||
}
|
}
|
||||||
|
|
||||||
func serverCheck(serverAddr string) bool {
|
func serverCheck(serverAddr string) bool {
|
||||||
|
@ -68,12 +78,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
|
|
||||||
// ***** Cwtch Server managment *****
|
// ***** Cwtch Server managment *****
|
||||||
var server *cwtchserver.Server = nil
|
var server *cwtchserver.Server = nil
|
||||||
generatedKey := checkAndGenPrivateKey(keyfile)
|
serverKey, generatedKey := loadOrGenPrivateKey(t)
|
||||||
|
|
||||||
serverKey, err := utils.LoadPrivateKeyFromFile(keyfile)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Could not load server's key from %v", keyfile)
|
|
||||||
}
|
|
||||||
serverAddr, _ := utils.GetOnionAddress(serverKey)
|
serverAddr, _ := utils.GetOnionAddress(serverKey)
|
||||||
|
|
||||||
serverOnline := false
|
serverOnline := false
|
||||||
|
@ -86,7 +91,8 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
// launch app
|
// launch app
|
||||||
server = new(cwtchserver.Server)
|
server = new(cwtchserver.Server)
|
||||||
fmt.Printf("No server found\nStarting cwtch server...\n")
|
fmt.Printf("No server found\nStarting cwtch server...\n")
|
||||||
go server.Run(keyfile)
|
|
||||||
|
go server.Run(localKeyfile)
|
||||||
|
|
||||||
// let tor get established
|
// let tor get established
|
||||||
fmt.Printf("Establishing Tor hidden service: %v...\n", serverAddr)
|
fmt.Printf("Establishing Tor hidden service: %v...\n", serverAddr)
|
||||||
|
@ -109,24 +115,39 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
go bob.Listen()
|
go bob.Listen()
|
||||||
fmt.Println("Bob created:", bob.Profile.Onion)
|
fmt.Println("Bob created:", bob.Profile.Onion)
|
||||||
|
|
||||||
fmt.Println("Waiting for alice and bob to connection with onion network...")
|
fmt.Println("Creating Carol...")
|
||||||
time.Sleep(time.Second * 60)
|
carol := peer.NewCwtchPeer("Carol")
|
||||||
|
go carol.Listen()
|
||||||
|
fmt.Println("Carol created:", carol.Profile.Onion)
|
||||||
|
|
||||||
|
fmt.Println("Waiting for Alice, Bob, and Carol to connection with onion network...")
|
||||||
|
time.Sleep(time.Second * 70)
|
||||||
numGoRoutinesPostPeerStart := runtime.NumGoroutine()
|
numGoRoutinesPostPeerStart := runtime.NumGoroutine()
|
||||||
|
|
||||||
// ***** Peering and 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.Profile.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 start group: %v", err)
|
t.Errorf("Failed to init group: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Peering Alice peering with bob...")
|
fmt.Println("Alice peering with Bob...")
|
||||||
alice.PeerWithOnion(bob.Profile.Onion)
|
alice.PeerWithOnion(bob.Profile.Onion)
|
||||||
|
fmt.Println("Alice peering with Carol...")
|
||||||
|
alice.PeerWithOnion(carol.Profile.Onion)
|
||||||
|
|
||||||
time.Sleep(time.Second * 15)
|
fmt.Println("Alice joining server...")
|
||||||
|
alice.JoinServer(serverAddr)
|
||||||
|
|
||||||
|
fmt.Println("Bob joining server...")
|
||||||
|
bob.JoinServer(serverAddr)
|
||||||
|
|
||||||
|
fmt.Println("Waiting for peerings and server joins...")
|
||||||
|
|
||||||
|
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.Profile.Onion, groupId)
|
||||||
|
@ -144,19 +165,36 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
bob.AcceptInvite(group.GroupID)
|
bob.AcceptInvite(group.GroupID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second * 3)
|
time.Sleep(time.Second * 5)
|
||||||
|
|
||||||
numGoRoutinesPostPeer := runtime.NumGoroutine()
|
numGoRoutinesPostServerConnect := runtime.NumGoroutine()
|
||||||
|
|
||||||
fmt.Println("Alice joining server...")
|
// ***** Fill up message history of server ******
|
||||||
alice.JoinServer(serverAddr)
|
|
||||||
|
|
||||||
fmt.Println("Bob joining server...")
|
/*
|
||||||
bob.JoinServer(serverAddr)
|
// filler group will be used to fill up the servers message history a bit to stress test fetch later for carol
|
||||||
|
fillerGroupId, _, err := alice.Profile.StartGroup(serverAddr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to init filler group: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for them to join the server
|
fmt.Println("Alice filling message history of server...")
|
||||||
time.Sleep(time.Second * 40)
|
for i := 0; i < 100; i++ {
|
||||||
numGouRoutinesPostServerConnect := runtime.NumGoroutine()
|
|
||||||
|
go func (x int) {
|
||||||
|
time.Sleep(time.Second * time.Duration(x))
|
||||||
|
err := alice.SendMessageToGroup(fillerGroupId, aliceLines[0])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("SEND", x, "ERROR:", err)
|
||||||
|
} else {
|
||||||
|
fmt.Println("SEND", x, " SUCCESS!")
|
||||||
|
}
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 110)
|
||||||
|
*/
|
||||||
|
|
||||||
// ***** Conversation *****
|
// ***** Conversation *****
|
||||||
|
|
||||||
|
@ -176,23 +214,47 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second * 10)
|
time.Sleep(time.Second * 10)
|
||||||
|
|
||||||
// "instant" - could be either order?
|
|
||||||
fmt.Println("Alice> ", aliceLines[1])
|
fmt.Println("Alice> ", aliceLines[1])
|
||||||
alice.SendMessageToGroup(groupId, aliceLines[1])
|
alice.SendMessageToGroup(groupId, aliceLines[1])
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
|
|
||||||
fmt.Println("Bob> ", bobLines[1])
|
fmt.Println("Bob> ", bobLines[1])
|
||||||
bob.SendMessageToGroup(groupId, bobLines[1])
|
bob.SendMessageToGroup(groupId, bobLines[1])
|
||||||
time.Sleep(time.Second * 10)
|
time.Sleep(time.Second * 10)
|
||||||
|
|
||||||
fmt.Println("Alice> ", aliceLines[2])
|
fmt.Println("Alice inviting Carol to group...")
|
||||||
alice.SendMessageToGroup(groupId, aliceLines[2])
|
err = alice.InviteOnionToGroup(carol.Profile.Onion, groupId)
|
||||||
// Todo: Alice disconnects
|
if err != nil {
|
||||||
|
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...")
|
||||||
|
for _, group := range carol.Profile.Groups {
|
||||||
|
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)
|
||||||
|
carol.AcceptInvite(group.GroupID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Shutting down Alice...")
|
||||||
|
alice.Shutdown()
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
numGoRoutinesPostAlice := runtime.NumGoroutine()
|
||||||
|
|
||||||
|
fmt.Println("Carol joining server...")
|
||||||
|
carol.JoinServer(serverAddr)
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 60)
|
||||||
|
numGoRotinesPostCarolConnect := runtime.NumGoroutine()
|
||||||
|
|
||||||
fmt.Println("Bob> ", bobLines[2])
|
fmt.Println("Bob> ", bobLines[2])
|
||||||
bob.SendMessageToGroup(groupId, bobLines[2])
|
bob.SendMessageToGroup(groupId, bobLines[2])
|
||||||
time.Sleep(time.Second * 10)
|
time.Sleep(time.Second * 10)
|
||||||
|
|
||||||
// Todo: Alice reconects, gets missed messages (from bob)
|
fmt.Println("Carol> ", carolLines[0])
|
||||||
|
carol.SendMessageToGroup(groupId, carolLines[0])
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
|
|
||||||
// ***** Verify Test *****
|
// ***** Verify Test *****
|
||||||
|
|
||||||
|
@ -200,43 +262,71 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
time.Sleep(time.Second * 15)
|
time.Sleep(time.Second * 15)
|
||||||
|
|
||||||
alicesGroup := alice.Profile.GetGroupByGroupID(groupId)
|
alicesGroup := alice.Profile.GetGroupByGroupID(groupId)
|
||||||
fmt.Printf("alice Groups:\n")
|
|
||||||
for k := range alice.Profile.Groups {
|
|
||||||
fmt.Println(" " + k)
|
|
||||||
}
|
|
||||||
if alicesGroup == nil {
|
if alicesGroup == nil {
|
||||||
t.Error("aliceGroup == nil")
|
t.Error("aliceGroup == nil")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Alice TimeLine:\n")
|
fmt.Printf("Alice's TimeLine:\n")
|
||||||
printAndVerifyTimeline(t, alicesGroup.GetTimeline())
|
aliceVerified := printAndCountVerifedTimeline(t, alicesGroup.GetTimeline())
|
||||||
|
if aliceVerified != 4 {
|
||||||
|
t.Errorf("Alice did not have 4 verified messages")
|
||||||
|
}
|
||||||
|
|
||||||
bobsGroup := bob.Profile.GetGroupByGroupID(groupId)
|
bobsGroup := bob.Profile.GetGroupByGroupID(groupId)
|
||||||
fmt.Printf("bob Groups:\n")
|
|
||||||
for k := range bob.Profile.Groups {
|
|
||||||
fmt.Println(" " + k)
|
|
||||||
}
|
|
||||||
if bobsGroup == nil {
|
if bobsGroup == nil {
|
||||||
t.Error("bobGroup == nil")
|
t.Error("bobGroup == nil")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Printf("Bob TimeLine:\n")
|
fmt.Printf("Bob's TimeLine:\n")
|
||||||
printAndVerifyTimeline(t, bobsGroup.GetTimeline())
|
bobVerified := printAndCountVerifedTimeline(t, bobsGroup.GetTimeline())
|
||||||
|
if bobVerified != 5 {
|
||||||
|
t.Errorf("Bob did not have 5 verified messages")
|
||||||
|
}
|
||||||
|
|
||||||
if len(alicesGroup.Timeline.Messages) != 6 {
|
carolsGroup := carol.Profile.GetGroupByGroupID(groupId)
|
||||||
|
fmt.Printf("Carol's TimeLine:\n")
|
||||||
|
carolVerified := printAndCountVerifedTimeline(t, carolsGroup.GetTimeline())
|
||||||
|
if carolVerified != 3 {
|
||||||
|
t.Errorf("Carol did not have 3 verified messages")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(alicesGroup.GetTimeline()) != 4 {
|
||||||
t.Errorf("Alice's timeline does not have all messages")
|
t.Errorf("Alice's timeline does not have all messages")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check message 0,1 and 4,5 for content (2,3 could be out of order)
|
if len(bobsGroup.GetTimeline()) != 6 {
|
||||||
aliceGroupTimeline := alicesGroup.GetTimeline()
|
t.Errorf("Bob's timeline does not have all messages")
|
||||||
if aliceGroupTimeline[0].Message != aliceLines[0] || aliceGroupTimeline[1].Message != bobLines[0] ||
|
}
|
||||||
aliceGroupTimeline[4].Message != aliceLines[2] || aliceGroupTimeline[5].Message != bobLines[2] {
|
|
||||||
t.Errorf("Some of the messages did not have the expected content!")
|
// check message 0,1,2,3
|
||||||
|
aliceGroupTimeline := alicesGroup.GetTimeline()
|
||||||
|
if aliceGroupTimeline[0].Message != aliceLines[0] || aliceGroupTimeline[1].Message != bobLines[0] ||
|
||||||
|
aliceGroupTimeline[2].Message != aliceLines[1] || aliceGroupTimeline[3].Message != bobLines[1] {
|
||||||
|
t.Errorf("Some of Alice's timeline messages did not have the expected content!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check message 0,1,2,3,4,5
|
||||||
|
bobGroupTimeline := bobsGroup.GetTimeline()
|
||||||
|
if bobGroupTimeline[0].Message != aliceLines[0] || bobGroupTimeline[1].Message != bobLines[0] ||
|
||||||
|
bobGroupTimeline[2].Message != aliceLines[1] || bobGroupTimeline[3].Message != bobLines[1] ||
|
||||||
|
bobGroupTimeline[4].Message != bobLines[2] || bobGroupTimeline[5].Message != carolLines[0] {
|
||||||
|
t.Errorf("Some of Bob's timeline messages did not have the expected content!")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(carolsGroup.GetTimeline()) != 6 {
|
||||||
|
t.Errorf("Carol's timeline does not have all messages")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check message 0,1,2,3,4,5
|
||||||
|
carolGroupTimeline := carolsGroup.GetTimeline()
|
||||||
|
if carolGroupTimeline[0].Message != aliceLines[0] || carolGroupTimeline[1].Message != bobLines[0] ||
|
||||||
|
carolGroupTimeline[2].Message != aliceLines[1] || carolGroupTimeline[3].Message != bobLines[1] ||
|
||||||
|
carolGroupTimeline[4].Message != bobLines[2] || carolGroupTimeline[5].Message != carolLines[0] {
|
||||||
|
t.Errorf("Some of Carol's timeline messages did not have the expected content!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: shutdown users and server
|
|
||||||
fmt.Println("Shutting down Bob...")
|
fmt.Println("Shutting down Bob...")
|
||||||
bob.Shutdown()
|
bob.Shutdown()
|
||||||
time.Sleep(time.Second * 3)
|
time.Sleep(time.Second * 3)
|
||||||
|
@ -247,16 +337,18 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
time.Sleep(time.Second * 3)
|
time.Sleep(time.Second * 3)
|
||||||
}
|
}
|
||||||
numGoRoutinesPostServerShutdown := runtime.NumGoroutine()
|
numGoRoutinesPostServerShutdown := runtime.NumGoroutine()
|
||||||
fmt.Println("Shutting down Alice...")
|
|
||||||
alice.Shutdown()
|
fmt.Println("Shuttind down Carol...")
|
||||||
|
carol.Shutdown()
|
||||||
time.Sleep(time.Second * 3)
|
time.Sleep(time.Second * 3)
|
||||||
numGoRoutinesPostAlice := runtime.NumGoroutine()
|
numGoRoutinesPostCarol := runtime.NumGoroutine()
|
||||||
|
|
||||||
fmt.Printf("numGoRoutinesStart: %v\nnumGoRoutinesPostServer: %v\nnumGoRoutinesPostPeerStart: %v\nnumGoRoutinesPostPeer: %v\nnumGouRoutinesPostServerConnect: %v\nnumGoRoutinesPostBob: %v\nnumGoRoutinesPostServerShutdown: %v\nnumGoRoutinesPostAlice: %v\n",
|
fmt.Printf("numGoRoutinesStart: %v\nnumGoRoutinesPostServer: %v\nnumGoRoutinesPostPeerStart: %v\nnumGoRoutinesPostPeerAndServerConnect: %v\n" +
|
||||||
numGoRoutinesStart, numGoRoutinesPostServer, numGoRoutinesPostPeerStart, numGoRoutinesPostPeer, numGouRoutinesPostServerConnect,
|
"numGoRoutinesPostAlice: %v\nnumGoRotinesPostCarolConnect: %v\nnumGoRoutinesPostBob: %v\nnumGoRoutinesPostServerShutdown: %v\nnumGoRoutinesPostCarol: %v\n",
|
||||||
numGoRoutinesPostBob, numGoRoutinesPostServerShutdown, numGoRoutinesPostAlice)
|
numGoRoutinesStart, numGoRoutinesPostServer, numGoRoutinesPostPeerStart, numGoRoutinesPostServerConnect,
|
||||||
|
numGoRoutinesPostAlice, numGoRotinesPostCarolConnect, numGoRoutinesPostBob, numGoRoutinesPostServerShutdown, numGoRoutinesPostCarol)
|
||||||
|
|
||||||
if numGoRoutinesPostServer != numGoRoutinesPostAlice {
|
if numGoRoutinesPostServer != numGoRoutinesPostCarol {
|
||||||
t.Errorf("Number of GoRoutines once server checks were completed (%v) does not match number of goRoutines after cleanup of peers and servers (%v), clean up failed, leak detected!", numGoRoutinesPostServer, numGoRoutinesPostAlice)
|
t.Errorf("Number of GoRoutines once server checks were completed (%v) does not match number of goRoutines after cleanup of peers and servers (%v), clean up failed, leak detected!", numGoRoutinesPostServer, numGoRoutinesPostCarol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue