forked from cwtch.im/cwtch
merging
This commit is contained in:
commit
9734540aca
11
app/app.go
11
app/app.go
|
@ -18,7 +18,7 @@ import (
|
||||||
|
|
||||||
type application struct {
|
type application struct {
|
||||||
peers map[string]peer.CwtchPeer
|
peers map[string]peer.CwtchPeer
|
||||||
mn connectivity.Mixnet
|
acn connectivity.ACN
|
||||||
directory string
|
directory string
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
primaryonion string
|
primaryonion string
|
||||||
|
@ -42,9 +42,9 @@ type Application interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewApp creates a new app with some environment awareness and initializes a Tor Manager
|
// NewApp creates a new app with some environment awareness and initializes a Tor Manager
|
||||||
func NewApp(mn connectivity.Mixnet, appDirectory string) Application {
|
func NewApp(acn connectivity.ACN, appDirectory string) Application {
|
||||||
log.Printf("NewApp(%v)\n", appDirectory)
|
log.Printf("NewApp(%v)\n", appDirectory)
|
||||||
app := &application{peers: make(map[string]peer.CwtchPeer), storage: make(map[string]storage.ProfileStore), directory: appDirectory, mn: mn}
|
app := &application{peers: make(map[string]peer.CwtchPeer), storage: make(map[string]storage.ProfileStore), directory: appDirectory, acn: acn}
|
||||||
os.Mkdir(path.Join(app.directory, "profiles"), 0700)
|
os.Mkdir(path.Join(app.directory, "profiles"), 0700)
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func (app *application) CreatePeer(name string, password string) (peer.CwtchPeer
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p.Init(app.mn)
|
p.Init(app.acn)
|
||||||
p.Listen()
|
p.Listen()
|
||||||
_, exists := app.peers[p.GetProfile().Onion]
|
_, exists := app.peers[p.GetProfile().Onion]
|
||||||
if exists {
|
if exists {
|
||||||
|
@ -110,8 +110,9 @@ func (app *application) LoadProfiles(password string) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Init(app.mn)
|
p.Init(app.acn)
|
||||||
p.Listen()
|
p.Listen()
|
||||||
|
|
||||||
app.mutex.Lock()
|
app.mutex.Lock()
|
||||||
app.peers[p.GetProfile().Onion] = p
|
app.peers[p.GetProfile().Onion] = p
|
||||||
app.storage[p.GetProfile().Onion] = fileStore
|
app.storage[p.GetProfile().Onion] = fileStore
|
||||||
|
|
|
@ -255,11 +255,11 @@ func main() {
|
||||||
log.Fatalf("\nError: could not load current user: %v\n", err)
|
log.Fatalf("\nError: could not load current user: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mn, err := connectivity.StartTor(path.Join(usr.HomeDir, ".cwtch"), "")
|
acn, err := connectivity.StartTor(path.Join(usr.HomeDir, ".cwtch"), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("\nError connecting to Tor: %v\n", err)
|
log.Fatalf("\nError connecting to Tor: %v\n", err)
|
||||||
}
|
}
|
||||||
app = app2.NewApp(mn, path.Join(usr.HomeDir, ".cwtch"))
|
app = app2.NewApp(acn, path.Join(usr.HomeDir, ".cwtch"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error initializing application: %v", err)
|
log.Fatalf("Error initializing application: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -602,6 +602,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Shutdown()
|
app.Shutdown()
|
||||||
mn.Close()
|
acn.Close()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,11 @@ type Group struct {
|
||||||
// NewGroup initializes a new group associated with a given CwtchServer
|
// NewGroup initializes a new group associated with a given CwtchServer
|
||||||
func NewGroup(server string) (*Group, error) {
|
func NewGroup(server string) (*Group, error) {
|
||||||
group := new(Group)
|
group := new(Group)
|
||||||
|
|
||||||
|
if utils.IsValidHostname(server) == false {
|
||||||
|
return nil, errors.New("Server is not a valid v3 onion")
|
||||||
|
}
|
||||||
|
|
||||||
group.GroupServer = server
|
group.GroupServer = server
|
||||||
|
|
||||||
var groupID [16]byte
|
var groupID [16]byte
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGroup(t *testing.T) {
|
func TestGroup(t *testing.T) {
|
||||||
g, _ := NewGroup("server.onion")
|
g, _ := NewGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd")
|
||||||
dgm := &protocol.DecryptedGroupMessage{
|
dgm := &protocol.DecryptedGroupMessage{
|
||||||
Onion: proto.String("onion"),
|
Onion: proto.String("onion"),
|
||||||
Text: proto.String("Hello World!"),
|
Text: proto.String("Hello World!"),
|
||||||
|
@ -30,3 +30,10 @@ func TestGroup(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Logf("Got message %v", message)
|
t.Logf("Got message %v", message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGroupErr(t *testing.T) {
|
||||||
|
_, err := NewGroup("not a real group name")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Group Setup Should Have Failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -55,11 +55,11 @@ func (t *Timeline) Swap(i, j int) {
|
||||||
t.Messages[i], t.Messages[j] = t.Messages[j], t.Messages[i]
|
t.Messages[i], t.Messages[j] = t.Messages[j], t.Messages[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Less checks 2 messages (i and j) in the timeline and returns true if i occcured before j, else false
|
// Less checks 2 messages (i and j) in the timeline and returns true if i occurred before j, else false
|
||||||
func (t *Timeline) Less(i, j int) bool {
|
func (t *Timeline) Less(i, j int) bool {
|
||||||
|
|
||||||
if t.Messages[i].Timestamp.Before(t.Messages[j].Timestamp) {
|
if t.Messages[j].Timestamp.Before(t.Messages[i].Timestamp) {
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if compareSignatures(t.Messages[i].PreviousMessageSig, t.SignedGroupID) {
|
if compareSignatures(t.Messages[i].PreviousMessageSig, t.SignedGroupID) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ func TestMessagePadding(t *testing.T) {
|
||||||
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
||||||
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
||||||
|
|
||||||
gid, invite, _ := alice.StartGroup("aaa.onion")
|
gid, invite, _ := alice.StartGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd")
|
||||||
gci := &protocol.CwtchPeerPacket{}
|
gci := &protocol.CwtchPeerPacket{}
|
||||||
proto.Unmarshal(invite, gci)
|
proto.Unmarshal(invite, gci)
|
||||||
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
||||||
|
@ -50,7 +50,7 @@ func TestTranscriptConsistency(t *testing.T) {
|
||||||
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
||||||
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
||||||
|
|
||||||
gid, invite, _ := alice.StartGroup("aaa.onion")
|
gid, invite, _ := alice.StartGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd")
|
||||||
gci := &protocol.CwtchPeerPacket{}
|
gci := &protocol.CwtchPeerPacket{}
|
||||||
proto.Unmarshal(invite, gci)
|
proto.Unmarshal(invite, gci)
|
||||||
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
||||||
|
|
|
@ -22,6 +22,7 @@ type PublicProfile struct {
|
||||||
Blocked bool
|
Blocked bool
|
||||||
Onion string
|
Onion string
|
||||||
Attributes map[string]string
|
Attributes map[string]string
|
||||||
|
Timeline Timeline
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +103,24 @@ func (p *Profile) RejectInvite(groupID string) {
|
||||||
p.lock.Unlock()
|
p.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddMessageToContactTimeline allows the saving of a message sent via a direct connection chat to the profile.
|
||||||
|
func (p *Profile) AddMessageToContactTimeline(onion string, fromMe bool, message string, sent time.Time) {
|
||||||
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
contact, ok := p.Contacts[onion]
|
||||||
|
|
||||||
|
// We don't really need a Signature here, but we use it to maintain order
|
||||||
|
now := time.Now()
|
||||||
|
sig := p.SignMessage(onion + message + sent.String() + now.String())
|
||||||
|
if ok {
|
||||||
|
if fromMe {
|
||||||
|
contact.Timeline.Insert(&Message{PeerID: p.Onion, Message: message, Timestamp: sent, Received: now, Signature: sig})
|
||||||
|
} else {
|
||||||
|
contact.Timeline.Insert(&Message{PeerID: onion, Message: message, Timestamp: sent, Received: now, Signature: sig})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AcceptInvite accepts a group invite
|
// AcceptInvite accepts a group invite
|
||||||
func (p *Profile) AcceptInvite(groupID string) (err error) {
|
func (p *Profile) AcceptInvite(groupID string) (err error) {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
|
|
|
@ -4,8 +4,31 @@ import (
|
||||||
"cwtch.im/cwtch/protocol"
|
"cwtch.im/cwtch/protocol"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestP2P(t *testing.T) {
|
||||||
|
sarah := GenerateNewProfile("Sarah")
|
||||||
|
alice := GenerateNewProfile("Alice")
|
||||||
|
|
||||||
|
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
||||||
|
|
||||||
|
sarah.AddMessageToContactTimeline(alice.Onion, false, "hello", time.Now())
|
||||||
|
sarah.AddMessageToContactTimeline(alice.Onion, true, "world", time.Now())
|
||||||
|
|
||||||
|
contact, _ := sarah.GetContact(alice.Onion)
|
||||||
|
for i, m := range contact.Timeline.GetMessages() {
|
||||||
|
if i == 0 && (m.Message != "hello" || m.PeerID != alice.Onion) {
|
||||||
|
t.Fatalf("Timeline is invalid: %v", m)
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == 1 && (m.Message != "world" || m.PeerID != sarah.Onion) {
|
||||||
|
t.Fatalf("Timeline is invalid: %v", m)
|
||||||
|
}
|
||||||
|
t.Logf("Message: %v", m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProfileIdentity(t *testing.T) {
|
func TestProfileIdentity(t *testing.T) {
|
||||||
sarah := GenerateNewProfile("Sarah")
|
sarah := GenerateNewProfile("Sarah")
|
||||||
alice := GenerateNewProfile("Alice")
|
alice := GenerateNewProfile("Alice")
|
||||||
|
@ -77,7 +100,7 @@ func TestRejectGroupInvite(t *testing.T) {
|
||||||
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
||||||
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
||||||
|
|
||||||
gid, invite, _ := alice.StartGroup("aaa.onion")
|
gid, invite, _ := alice.StartGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd")
|
||||||
gci := &protocol.CwtchPeerPacket{}
|
gci := &protocol.CwtchPeerPacket{}
|
||||||
proto.Unmarshal(invite, gci)
|
proto.Unmarshal(invite, gci)
|
||||||
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
||||||
|
@ -101,7 +124,7 @@ func TestProfileGroup(t *testing.T) {
|
||||||
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
||||||
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
||||||
|
|
||||||
gid, invite, _ := alice.StartGroupWithMessage("aaa.onion", []byte("Hello World"))
|
gid, invite, _ := alice.StartGroupWithMessage("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd", []byte("Hello World"))
|
||||||
gci := &protocol.CwtchPeerPacket{}
|
gci := &protocol.CwtchPeerPacket{}
|
||||||
proto.Unmarshal(invite, gci)
|
proto.Unmarshal(invite, gci)
|
||||||
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
||||||
|
@ -114,7 +137,7 @@ func TestProfileGroup(t *testing.T) {
|
||||||
c, s1, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
|
c, s1, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
|
||||||
alice.AttemptDecryption(c, s1)
|
alice.AttemptDecryption(c, s1)
|
||||||
|
|
||||||
gid2, invite2, _ := alice.StartGroup("bbb.onion")
|
gid2, invite2, _ := alice.StartGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd")
|
||||||
gci2 := &protocol.CwtchPeerPacket{}
|
gci2 := &protocol.CwtchPeerPacket{}
|
||||||
proto.Unmarshal(invite2, gci2)
|
proto.Unmarshal(invite2, gci2)
|
||||||
sarah.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion)
|
sarah.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion)
|
||||||
|
|
|
@ -15,13 +15,13 @@ type Manager struct {
|
||||||
serverConnections map[string]*PeerServerConnection
|
serverConnections map[string]*PeerServerConnection
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
breakChannel chan bool
|
breakChannel chan bool
|
||||||
mn connectivity.Mixnet
|
acn connectivity.ACN
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConnectionsManager creates a new instance of Manager.
|
// NewConnectionsManager creates a new instance of Manager.
|
||||||
func NewConnectionsManager(mn connectivity.Mixnet) *Manager {
|
func NewConnectionsManager(acn connectivity.ACN) *Manager {
|
||||||
m := new(Manager)
|
m := new(Manager)
|
||||||
m.mn = mn
|
m.acn = acn
|
||||||
m.peerConnections = make(map[string]*PeerPeerConnection)
|
m.peerConnections = make(map[string]*PeerPeerConnection)
|
||||||
m.serverConnections = make(map[string]*PeerServerConnection)
|
m.serverConnections = make(map[string]*PeerServerConnection)
|
||||||
m.breakChannel = make(chan bool)
|
m.breakChannel = make(chan bool)
|
||||||
|
@ -35,7 +35,7 @@ func (m *Manager) ManagePeerConnection(host string, profile *model.Profile, data
|
||||||
|
|
||||||
_, exists := m.peerConnections[host]
|
_, exists := m.peerConnections[host]
|
||||||
if !exists {
|
if !exists {
|
||||||
ppc := NewPeerPeerConnection(m.mn, host, profile, dataHandler, aif)
|
ppc := NewPeerPeerConnection(m.acn, host, profile, dataHandler, aif)
|
||||||
go ppc.Run()
|
go ppc.Run()
|
||||||
m.peerConnections[host] = ppc
|
m.peerConnections[host] = ppc
|
||||||
return ppc
|
return ppc
|
||||||
|
@ -49,7 +49,7 @@ func (m *Manager) ManageServerConnection(host string, handler func(string, *prot
|
||||||
|
|
||||||
_, exists := m.serverConnections[host]
|
_, exists := m.serverConnections[host]
|
||||||
if !exists {
|
if !exists {
|
||||||
psc := NewPeerServerConnection(m.mn, host)
|
psc := NewPeerServerConnection(m.acn, host)
|
||||||
go psc.Run()
|
go psc.Run()
|
||||||
psc.GroupMessageHandler = handler
|
psc.GroupMessageHandler = handler
|
||||||
m.serverConnections[host] = psc
|
m.serverConnections[host] = psc
|
||||||
|
|
|
@ -23,13 +23,13 @@ type PeerPeerConnection struct {
|
||||||
profile *model.Profile
|
profile *model.Profile
|
||||||
dataHandler func(string, []byte) []byte
|
dataHandler func(string, []byte) []byte
|
||||||
aif application.ApplicationInstanceFactory
|
aif application.ApplicationInstanceFactory
|
||||||
mn connectivity.Mixnet
|
acn connectivity.ACN
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPeerPeerConnection creates a new peer connection for the given hostname and profile.
|
// NewPeerPeerConnection creates a new peer connection for the given hostname and profile.
|
||||||
func NewPeerPeerConnection(mn connectivity.Mixnet, peerhostname string, profile *model.Profile, dataHandler func(string, []byte) []byte, aif application.ApplicationInstanceFactory) *PeerPeerConnection {
|
func NewPeerPeerConnection(acn connectivity.ACN, peerhostname string, profile *model.Profile, dataHandler func(string, []byte) []byte, aif application.ApplicationInstanceFactory) *PeerPeerConnection {
|
||||||
ppc := new(PeerPeerConnection)
|
ppc := new(PeerPeerConnection)
|
||||||
ppc.mn = mn
|
ppc.acn = acn
|
||||||
ppc.PeerHostname = peerhostname
|
ppc.PeerHostname = peerhostname
|
||||||
ppc.profile = profile
|
ppc.profile = profile
|
||||||
ppc.dataHandler = dataHandler
|
ppc.dataHandler = dataHandler
|
||||||
|
@ -110,7 +110,7 @@ func (ppc *PeerPeerConnection) WaitTilAuthenticated() {
|
||||||
// Run manages the setup and teardown of a peer->peer connection
|
// Run manages the setup and teardown of a peer->peer connection
|
||||||
func (ppc *PeerPeerConnection) Run() error {
|
func (ppc *PeerPeerConnection) Run() error {
|
||||||
ppc.state = CONNECTING
|
ppc.state = CONNECTING
|
||||||
rc, err := goricochet.Open(ppc.mn, ppc.PeerHostname)
|
rc, err := goricochet.Open(ppc.acn, ppc.PeerHostname)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rc.TraceLog(false)
|
rc.TraceLog(false)
|
||||||
ppc.connection = rc
|
ppc.connection = rc
|
||||||
|
@ -150,5 +150,7 @@ 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.Conn.Close()
|
if ppc.connection != nil {
|
||||||
|
ppc.connection.Conn.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,9 @@ func PeerAuthValid(hostname string, key ed25519.PublicKey) (allowed, known bool)
|
||||||
return true, true
|
return true, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func runtestpeer(t *testing.T, tp *TestPeer, identity identity.Identity) {
|
func runtestpeer(t *testing.T, tp *TestPeer, identity identity.Identity, listenChan chan bool) {
|
||||||
ln, _ := net.Listen("tcp", "127.0.0.1:5452")
|
ln, _ := net.Listen("tcp", "127.0.0.1:5452")
|
||||||
|
listenChan <- true
|
||||||
conn, _ := ln.Accept()
|
conn, _ := ln.Accept()
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
@ -65,7 +66,9 @@ func TestPeerPeerConnection(t *testing.T) {
|
||||||
|
|
||||||
tp := new(TestPeer)
|
tp := new(TestPeer)
|
||||||
tp.Init()
|
tp.Init()
|
||||||
go runtestpeer(t, tp, identity)
|
listenChan := make(chan bool)
|
||||||
|
go runtestpeer(t, tp, identity, listenChan)
|
||||||
|
<-listenChan
|
||||||
state := ppc.GetState()
|
state := ppc.GetState()
|
||||||
if state != DISCONNECTED {
|
if state != DISCONNECTED {
|
||||||
fmt.Println("ERROR state should be disconnected")
|
fmt.Println("ERROR state should be disconnected")
|
||||||
|
@ -77,7 +80,7 @@ func TestPeerPeerConnection(t *testing.T) {
|
||||||
if state != AUTHENTICATED {
|
if state != AUTHENTICATED {
|
||||||
t.Errorf("connection state should be authenticated(3), was instead %v", state)
|
t.Errorf("connection state should be authenticated(3), was instead %v", state)
|
||||||
}
|
}
|
||||||
_, invite, _ := profile.StartGroup("aaa.onion")
|
_, invite, _ := profile.StartGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd")
|
||||||
ppc.SendGroupInvite(invite)
|
ppc.SendGroupInvite(invite)
|
||||||
time.Sleep(time.Second * 3)
|
time.Sleep(time.Second * 3)
|
||||||
if tp.ReceivedGroupInvite == false {
|
if tp.ReceivedGroupInvite == false {
|
||||||
|
|
|
@ -23,15 +23,15 @@ type PeerServerConnection struct {
|
||||||
Server string
|
Server string
|
||||||
state ConnectionState
|
state ConnectionState
|
||||||
connection *connection.Connection
|
connection *connection.Connection
|
||||||
mn connectivity.Mixnet
|
acn connectivity.ACN
|
||||||
|
|
||||||
GroupMessageHandler func(string, *protocol.GroupMessage)
|
GroupMessageHandler func(string, *protocol.GroupMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPeerServerConnection creates a new Peer->Server outbound connection
|
// NewPeerServerConnection creates a new Peer->Server outbound connection
|
||||||
func NewPeerServerConnection(mn connectivity.Mixnet, serverhostname string) *PeerServerConnection {
|
func NewPeerServerConnection(acn connectivity.ACN, serverhostname string) *PeerServerConnection {
|
||||||
psc := new(PeerServerConnection)
|
psc := new(PeerServerConnection)
|
||||||
psc.mn = mn
|
psc.acn = acn
|
||||||
psc.Server = serverhostname
|
psc.Server = serverhostname
|
||||||
psc.Init()
|
psc.Init()
|
||||||
return psc
|
return psc
|
||||||
|
@ -55,7 +55,7 @@ func (psc *PeerServerConnection) WaitTilAuthenticated() {
|
||||||
// Run manages the setup and teardown of a peer server connection
|
// Run manages the setup and teardown of a peer server connection
|
||||||
func (psc *PeerServerConnection) Run() error {
|
func (psc *PeerServerConnection) Run() error {
|
||||||
log.Printf("Connecting to %v", psc.Server)
|
log.Printf("Connecting to %v", psc.Server)
|
||||||
rc, err := goricochet.Open(psc.mn, psc.Server)
|
rc, err := goricochet.Open(psc.acn, psc.Server)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rc.TraceLog(true)
|
rc.TraceLog(true)
|
||||||
psc.connection = rc
|
psc.connection = rc
|
||||||
|
|
|
@ -33,8 +33,9 @@ func (ts *TestServer) HandleFetchRequest() []*protocol.GroupMessage {
|
||||||
return []*protocol.GroupMessage{{Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{}}, {Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{}}}
|
return []*protocol.GroupMessage{{Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{}}, {Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runtestserver(t *testing.T, ts *TestServer, identity identity.Identity) {
|
func runtestserver(t *testing.T, ts *TestServer, identity identity.Identity, listenChan chan bool) {
|
||||||
ln, _ := net.Listen("tcp", "127.0.0.1:5451")
|
ln, _ := net.Listen("tcp", "127.0.0.1:5451")
|
||||||
|
listenChan <- true
|
||||||
conn, _ := ln.Accept()
|
conn, _ := ln.Accept()
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
@ -70,7 +71,9 @@ func TestPeerServerConnection(t *testing.T) {
|
||||||
|
|
||||||
ts := new(TestServer)
|
ts := new(TestServer)
|
||||||
ts.Init()
|
ts.Init()
|
||||||
go runtestserver(t, ts, identity)
|
listenChan := make(chan bool)
|
||||||
|
go runtestserver(t, ts, identity, listenChan)
|
||||||
|
<-listenChan
|
||||||
onionAddr := identity.Hostname()
|
onionAddr := identity.Hostname()
|
||||||
|
|
||||||
psc := NewPeerServerConnection(connectivity.LocalProvider(), "127.0.0.1:5451|"+onionAddr)
|
psc := NewPeerServerConnection(connectivity.LocalProvider(), "127.0.0.1:5451|"+onionAddr)
|
||||||
|
|
|
@ -28,19 +28,19 @@ type cwtchPeer struct {
|
||||||
connection.AutoConnectionHandler
|
connection.AutoConnectionHandler
|
||||||
Profile *model.Profile
|
Profile *model.Profile
|
||||||
app *application.RicochetApplication
|
app *application.RicochetApplication
|
||||||
mn connectivity.Mixnet
|
acn connectivity.ACN
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
connectionsManager *connections.Manager
|
connectionsManager *connections.Manager
|
||||||
dataHandler func(string, []byte) []byte
|
dataHandler func(string, []byte) []byte
|
||||||
aif application.ApplicationInstanceFactory
|
shutdown bool
|
||||||
|
aif application.ApplicationInstanceFactory
|
||||||
started bool
|
started bool
|
||||||
shutdown bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CwtchPeer provides us with a way of testing systems built on top of cwtch without having to
|
// CwtchPeer provides us with a way of testing systems built on top of cwtch without having to
|
||||||
// directly implement a cwtchPeer.
|
// directly implement a cwtchPeer.
|
||||||
type CwtchPeer interface {
|
type CwtchPeer interface {
|
||||||
Init(connectivity.Mixnet)
|
Init(connectivity.ACN)
|
||||||
PeerWithOnion(string) *connections.PeerPeerConnection
|
PeerWithOnion(string) *connections.PeerPeerConnection
|
||||||
InviteOnionToGroup(string, string) error
|
InviteOnionToGroup(string, string) error
|
||||||
|
|
||||||
|
@ -91,9 +91,9 @@ func FromProfile(profile *model.Profile) CwtchPeer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init instantiates a cwtchPeer
|
// Init instantiates a cwtchPeer
|
||||||
func (cp *cwtchPeer) Init(mn connectivity.Mixnet) {
|
func (cp *cwtchPeer) Init(acn connectivity.ACN) {
|
||||||
cp.mn = mn
|
cp.acn = acn
|
||||||
cp.connectionsManager = connections.NewConnectionsManager(cp.mn)
|
cp.connectionsManager = connections.NewConnectionsManager(cp.acn)
|
||||||
go cp.connectionsManager.AttemptReconnections()
|
go cp.connectionsManager.AttemptReconnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ func (cp *cwtchPeer) Listen() {
|
||||||
// Listen sets up an onion listener to process incoming cwtch messages
|
// Listen sets up an onion listener to process incoming cwtch messages
|
||||||
func (cp *cwtchPeer) listenFn() error {
|
func (cp *cwtchPeer) listenFn() error {
|
||||||
ra := new(application.RicochetApplication)
|
ra := new(application.RicochetApplication)
|
||||||
onionService, err := cp.mn.Listen(cp.Profile.Ed25519PrivateKey, application.RicochetPort)
|
onionService, err := cp.acn.Listen(cp.Profile.Ed25519PrivateKey, application.RicochetPort)
|
||||||
if err != nil /*&& fmt.Sprintf("%v", err) != "550 Unspecified Tor error: Onion address collision"*/ {
|
if err != nil /*&& fmt.Sprintf("%v", err) != "550 Unspecified Tor error: Onion address collision"*/ {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -351,7 +351,7 @@ func (cp *cwtchPeer) listenFn() error {
|
||||||
af.AddHandler(handlers[i], cp.aif.GetHandler(handlers[i]))
|
af.AddHandler(handlers[i], cp.aif.GetHandler(handlers[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
ra.Init(cp.mn, cp.Profile.Name, identity.InitializeV3(cp.Profile.Name, &cp.Profile.Ed25519PrivateKey, &cp.Profile.Ed25519PublicKey), af, cp)
|
ra.Init(cp.acn, cp.Profile.Name, identity.InitializeV3(cp.Profile.Name, &cp.Profile.Ed25519PrivateKey, &cp.Profile.Ed25519PublicKey), af, cp)
|
||||||
log.Printf("Running cwtch peer on %v", onionService.AddressFull())
|
log.Printf("Running cwtch peer on %v", onionService.AddressFull())
|
||||||
cp.app = ra
|
cp.app = ra
|
||||||
cp.started = true
|
cp.started = true
|
||||||
|
|
|
@ -20,11 +20,13 @@ func TestCwtchPeerGenerate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrustPeer(t *testing.T) {
|
func TestTrustPeer(t *testing.T) {
|
||||||
groupName := "test.server"
|
groupName := "2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd"
|
||||||
alice := NewCwtchPeer("alice")
|
alice := NewCwtchPeer("alice")
|
||||||
alice.Init(connectivity.LocalProvider())
|
alice.Init(connectivity.LocalProvider())
|
||||||
|
defer alice.Shutdown()
|
||||||
bob := NewCwtchPeer("bob")
|
bob := NewCwtchPeer("bob")
|
||||||
bob.Init(connectivity.LocalProvider())
|
bob.Init(connectivity.LocalProvider())
|
||||||
|
defer bob.Shutdown()
|
||||||
|
|
||||||
bobOnion := bob.GetProfile().Onion
|
bobOnion := bob.GetProfile().Onion
|
||||||
aliceOnion := alice.GetProfile().Onion
|
aliceOnion := alice.GetProfile().Onion
|
||||||
|
|
|
@ -17,16 +17,16 @@ func main() {
|
||||||
|
|
||||||
serverConfig := cwtchserver.LoadConfig(configDir, serverConfigFile)
|
serverConfig := cwtchserver.LoadConfig(configDir, serverConfigFile)
|
||||||
|
|
||||||
mn, err := connectivity.StartTor(path.Join(configDir, "tor"), "")
|
acn, err := connectivity.StartTor(path.Join(configDir, "tor"), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("\nError connecting to Tor: %v\n", err)
|
log.Fatalf("\nError connecting to Tor: %v\n", err)
|
||||||
}
|
}
|
||||||
defer mn.Close()
|
defer acn.Close()
|
||||||
|
|
||||||
server := new(cwtchserver.Server)
|
server := new(cwtchserver.Server)
|
||||||
log.Printf("starting cwtch server...")
|
log.Printf("starting cwtch server...")
|
||||||
|
|
||||||
// TODO load params from .cwtch/server.conf or command line flag
|
// TODO load params from .cwtch/server.conf or command line flag
|
||||||
// TODO: respond to HUP so t.Close is gracefully called
|
// TODO: respond to HUP so t.Close is gracefully called
|
||||||
server.Run(mn, serverConfig)
|
server.Run(acn, serverConfig)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
||||||
"github.com/dballard/pidusage"
|
"github.com/struCoder/pidusage"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
|
@ -23,12 +23,12 @@ type Server struct {
|
||||||
// TODO: surface errors
|
// TODO: surface errors
|
||||||
// TODO: handle HUP/KILL signals to exit and close Tor gracefully
|
// TODO: handle HUP/KILL signals to exit and close Tor gracefully
|
||||||
// TODO: handle user input to exit
|
// TODO: handle user input to exit
|
||||||
func (s *Server) Run(mn connectivity.Mixnet, serverConfig Config) {
|
func (s *Server) Run(acn connectivity.ACN, serverConfig Config) {
|
||||||
s.config = serverConfig
|
s.config = serverConfig
|
||||||
cwtchserver := new(application.RicochetApplication)
|
cwtchserver := new(application.RicochetApplication)
|
||||||
s.metricsPack.Start(cwtchserver, serverConfig.ConfigDir, s.config.ServerReporting.LogMetricsToFile)
|
s.metricsPack.Start(cwtchserver, serverConfig.ConfigDir, s.config.ServerReporting.LogMetricsToFile)
|
||||||
|
|
||||||
listenService, err := mn.Listen(s.config.PrivateKey, application.RicochetPort)
|
listenService, err := acn.Listen(s.config.PrivateKey, application.RicochetPort)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("error setting up onion service: %v", err)
|
log.Fatalf("error setting up onion service: %v", err)
|
||||||
|
@ -68,7 +68,7 @@ func (s *Server) Run(mn connectivity.Mixnet, serverConfig Config) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
cwtchserver.Init(mn, "cwtch server for "+listenService.AddressIdentity(), s.config.Identity(), af, new(application.AcceptAllContactManager))
|
cwtchserver.Init(acn, "cwtch server for "+listenService.AddressIdentity(), s.config.Identity(), af, new(application.AcceptAllContactManager))
|
||||||
log.Printf("cwtch server running on cwtch:%s", listenService.AddressFull())
|
log.Printf("cwtch server running on cwtch:%s", listenService.AddressFull())
|
||||||
s.app = cwtchserver
|
s.app = cwtchserver
|
||||||
s.app.Run(listenService)
|
s.app.Run(listenService)
|
||||||
|
|
|
@ -101,7 +101,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
log.SetOutput(ioutil.Discard)
|
log.SetOutput(ioutil.Discard)
|
||||||
numGoRoutinesStart := runtime.NumGoroutine()
|
numGoRoutinesStart := runtime.NumGoroutine()
|
||||||
|
|
||||||
mn, err := connectivity.StartTor(".", "")
|
acn, err := connectivity.StartTor(".", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not start Tor: %v", err)
|
t.Fatalf("Could not start Tor: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
config := cwtchserver.LoadConfig(".", "server-test.json")
|
config := cwtchserver.LoadConfig(".", "server-test.json")
|
||||||
identity := config.Identity()
|
identity := config.Identity()
|
||||||
serverAddr = identity.Hostname()
|
serverAddr = identity.Hostname()
|
||||||
go server.Run(mn, config)
|
go server.Run(acn, config)
|
||||||
|
|
||||||
// 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)
|
||||||
|
@ -135,19 +135,19 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
|
|
||||||
fmt.Println("Creating Alice...")
|
fmt.Println("Creating Alice...")
|
||||||
alice := peer.NewCwtchPeer("Alice")
|
alice := peer.NewCwtchPeer("Alice")
|
||||||
alice.Init(mn)
|
alice.Init(acn)
|
||||||
alice.Listen()
|
alice.Listen()
|
||||||
fmt.Println("Alice created:", alice.GetProfile().Onion)
|
fmt.Println("Alice created:", alice.GetProfile().Onion)
|
||||||
|
|
||||||
fmt.Println("Creating Bob...")
|
fmt.Println("Creating Bob...")
|
||||||
bob := peer.NewCwtchPeer("Bob")
|
bob := peer.NewCwtchPeer("Bob")
|
||||||
bob.Init(mn)
|
bob.Init(acn)
|
||||||
bob.Listen()
|
bob.Listen()
|
||||||
fmt.Println("Bob created:", bob.GetProfile().Onion)
|
fmt.Println("Bob created:", bob.GetProfile().Onion)
|
||||||
|
|
||||||
fmt.Println("Creating Carol...")
|
fmt.Println("Creating Carol...")
|
||||||
carol := peer.NewCwtchPeer("Carol")
|
carol := peer.NewCwtchPeer("Carol")
|
||||||
carol.Init(mn)
|
carol.Init(acn)
|
||||||
carol.Listen()
|
carol.Listen()
|
||||||
fmt.Println("Carol created:", carol.GetProfile().Onion)
|
fmt.Println("Carol created:", carol.GetProfile().Onion)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue