forked from cwtch.im/cwtch
Lots of peerand serverstuff
This commit is contained in:
parent
c29186979f
commit
914be9e46a
|
@ -3,11 +3,12 @@ package model
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"git.mascherari.press/cwtch/protocol"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
"golang.org/x/crypto/nacl/secretbox"
|
"golang.org/x/crypto/nacl/secretbox"
|
||||||
"io"
|
"io"
|
||||||
"github.com/golang/protobuf/proto"
|
"log"
|
||||||
"git.mascherari.press/cwtch/protocol"
|
|
||||||
"github.com/s-rah/go-ricochet/utils"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,7 +53,9 @@ func (g *Group) Invite() []byte {
|
||||||
GroupName: g.GroupID,
|
GroupName: g.GroupID,
|
||||||
GroupSharedKey: g.GroupKey[:],
|
GroupSharedKey: g.GroupKey[:],
|
||||||
ServerHost: g.GroupServer,
|
ServerHost: g.GroupServer,
|
||||||
|
SignedGroupId: g.SignedGroupID[:],
|
||||||
}
|
}
|
||||||
|
log.Printf("INVITEBEFORE %v", gci)
|
||||||
cp := &protocol.CwtchPeerPacket{
|
cp := &protocol.CwtchPeerPacket{
|
||||||
GroupChatInvite: gci,
|
GroupChatInvite: gci,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"git.mascherari.press/cwtch/protocol"
|
"git.mascherari.press/cwtch/protocol"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ func TestGroup(t *testing.T) {
|
||||||
Timestamp: proto.Int32(int32(time.Now().Unix())),
|
Timestamp: proto.Int32(int32(time.Now().Unix())),
|
||||||
SignedGroupId: []byte{},
|
SignedGroupId: []byte{},
|
||||||
Signature: []byte{},
|
Signature: []byte{},
|
||||||
|
|
||||||
}
|
}
|
||||||
encMessage := g.EncryptMessage(dgm)
|
encMessage := g.EncryptMessage(dgm)
|
||||||
ok, message := g.DecryptMessage(encMessage)
|
ok, message := g.DecryptMessage(encMessage)
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// Message is a local representation of a given message sent over a group chat channel.
|
// Message is a local representation of a given message sent over a group chat channel.
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
|
|
|
@ -3,18 +3,18 @@ package model
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"encoding/asn1"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"git.mascherari.press/cwtch/protocol"
|
"git.mascherari.press/cwtch/protocol"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/s-rah/go-ricochet/utils"
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"time"
|
"log"
|
||||||
"encoding/asn1"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// PublicProfile is a local copy of a CwtchIdentity
|
// PublicProfile is a local copy of a CwtchIdentity
|
||||||
type PublicProfile struct {
|
type PublicProfile struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -23,7 +23,6 @@ type PublicProfile struct {
|
||||||
Blocked bool
|
Blocked bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Profile encapsulates all the attributes necessary to be a Cwtch Peer.
|
// Profile encapsulates all the attributes necessary to be a Cwtch Peer.
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
PublicProfile
|
PublicProfile
|
||||||
|
@ -96,6 +95,12 @@ func (p *Profile) VerifyMessage(onion string, message string, signature []byte)
|
||||||
return ed25519.Verify(p.Contacts[onion].Ed25519PublicKey, []byte(message), signature)
|
return ed25519.Verify(p.Contacts[onion].Ed25519PublicKey, []byte(message), signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyMessage confirms the authenticity of a message given an onion, message and signature.
|
||||||
|
func (p *Profile) VerifyGroupMessage(onion string, groupID string, message string, timestamp int32, signature []byte) bool {
|
||||||
|
m := message + groupID + strconv.Itoa(int(timestamp))
|
||||||
|
return ed25519.Verify(p.Contacts[onion].Ed25519PublicKey, []byte(m), signature)
|
||||||
|
}
|
||||||
|
|
||||||
// SignMessage takes a given message and returns an Ed21159 signature
|
// SignMessage takes a given message and returns an Ed21159 signature
|
||||||
func (p *Profile) SignMessage(message string) []byte {
|
func (p *Profile) SignMessage(message string) []byte {
|
||||||
sig := ed25519.Sign(p.Ed25519PrivateKey, []byte(message))
|
sig := ed25519.Sign(p.Ed25519PrivateKey, []byte(message))
|
||||||
|
@ -107,11 +112,14 @@ func (p *Profile) SignMessage(message string) []byte {
|
||||||
func (p *Profile) StartGroup(server string) (groupID string, invite []byte) {
|
func (p *Profile) StartGroup(server string) (groupID string, invite []byte) {
|
||||||
group := NewGroup(server)
|
group := NewGroup(server)
|
||||||
groupID = group.GroupID
|
groupID = group.GroupID
|
||||||
|
signedGroupId := p.SignMessage(groupID)
|
||||||
|
group.SignGroup(signedGroupId)
|
||||||
invite = group.Invite()
|
invite = group.Invite()
|
||||||
|
p.AddGroup(group)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Profile) GetGroupByGroupId(groupID string) (*Group) {
|
func (p *Profile) GetGroupByGroupId(groupID string) *Group {
|
||||||
return p.Groups[groupID]
|
return p.Groups[groupID]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +127,7 @@ func (p *Profile) GetGroupByGroupId(groupID string) (*Group) {
|
||||||
func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname string) {
|
func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname string) {
|
||||||
group := new(Group)
|
group := new(Group)
|
||||||
group.GroupID = gci.GetGroupName()
|
group.GroupID = gci.GetGroupName()
|
||||||
|
group.SignedGroupID = gci.GetSignedGroupId()
|
||||||
copy(group.GroupKey[:], gci.GetGroupSharedKey()[:])
|
copy(group.GroupKey[:], gci.GetGroupSharedKey()[:])
|
||||||
group.GroupServer = gci.GetServerHost()
|
group.GroupServer = gci.GetServerHost()
|
||||||
group.Accepted = false
|
group.Accepted = false
|
||||||
|
@ -126,7 +135,7 @@ func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname stri
|
||||||
p.AddGroup(group)
|
p.AddGroup(group)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddGroup is a conveniance method for adding a group to a profle.
|
// AddGroup is a conveniance method for adding a group to a profile.
|
||||||
func (p *Profile) AddGroup(group *Group) {
|
func (p *Profile) AddGroup(group *Group) {
|
||||||
existingGroup, exists := p.Groups[group.GroupID]
|
existingGroup, exists := p.Groups[group.GroupID]
|
||||||
if !exists {
|
if !exists {
|
||||||
|
@ -145,12 +154,13 @@ func (p *Profile) AddGroup(group *Group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AttemptDecryption takes a ciphertext and signature and attempts to decrypt it under known groups.
|
// AttemptDecryption takes a ciphertext and signature and attempts to decrypt it under known groups.
|
||||||
func (p *Profile) AttemptDecryption(ciphertext []byte, signature []byte) {
|
func (p *Profile) AttemptDecryption(ciphertext []byte) {
|
||||||
for _, group := range p.Groups {
|
for _, group := range p.Groups {
|
||||||
success, dgm := group.DecryptMessage(ciphertext)
|
success, dgm := group.DecryptMessage(ciphertext)
|
||||||
|
log.Printf("Decrypt Attempt %v %v", success, dgm)
|
||||||
if success {
|
if success {
|
||||||
// FIXME
|
// FIXME
|
||||||
verified := p.VerifyMessage(dgm.GetOnion(), dgm.GetText(), dgm.GetSignature())
|
verified := p.VerifyGroupMessage(dgm.GetOnion(), group.GroupID, dgm.GetText(), dgm.GetTimestamp(), dgm.GetSignature())
|
||||||
group.AddMessage(dgm, verified)
|
group.AddMessage(dgm, verified)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +175,7 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) (ciphert
|
||||||
dm := &protocol.DecryptedGroupMessage{
|
dm := &protocol.DecryptedGroupMessage{
|
||||||
Onion: proto.String(p.Onion),
|
Onion: proto.String(p.Onion),
|
||||||
Text: proto.String(message),
|
Text: proto.String(message),
|
||||||
SignedGroupId: group.SignedGroupID,
|
SignedGroupId: group.SignedGroupID[:],
|
||||||
Timestamp: proto.Int32(int32(timestamp)),
|
Timestamp: proto.Int32(int32(timestamp)),
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"Name":"Sarah","Ed25519PublicKey":"08Q49pmOe/8Edn/jR1Qq8d26SU1MzPbJ2PmJ64S6BY8=","Trusted":false,"Blocked":false,"Contacts":{},"Ed25519PrivateKey":"/hhjerGW66QyhAKPtwGbBBzhY5/auK6T2b/vjRGuXnjTxDj2mY57/wR2f+NHVCrx3bpJTUzM9snY+YnrhLoFjw==","OnionPrivateKey":{"N":146328154189193884086641737732621103864374553173215703384122944250992002089624680210913011506081609406766798073335357829207459154214042241028123233139603802979024475926282158611908322463042012748984945285776401165814190414695182764240512995788636041616865870623261762908273890987461235956226167821197856348839,"E":65537,"D":131000281712443101868127073809425903015557376501501621205628292187530749753611841209312116988644890475820095160882129401029342867327559796231167833968091809253818237330927694966481136799400760644381429766064366889564088512676631446803130802140311950212661905465119640487794003192289760147304713580532618877313,"Primes":[11046905119315044599912769443513046649297228971109751902148448569336221142449837623971448415395377389790939200512488865059980264758837294990542341171570219,13246076852180554978507253920836715985718751717246338099834768101497493531807293249274887847720805074264534287152405900588792629153510158525691602692356981],"Precomputed":{"Dp":9951771949347089936659442878755668922509550306762893515157001442446411893285295532588832483100280468945131000782113044435070797127756136171042614443284033,"Dq":6285403633811601060799526716666618760759292321939158372044213473615958219816946235957557750406970050497863607761501422044192947211740832046507430314584393,"Qinv":6371034795994819655941418536323418056681675622606010416374029760428023006446243689515420082688972242794843497150013283993628462297774942497647603736899599,"CRTValues":[]}},"Onion":"3qs4j52zt24qqnor","Groups":{}}
|
{"Name":"Sarah","Ed25519PublicKey":"57Vq0cuSR354/iWji5HYo1wRLejxtUHt3oG7Su/apTs=","Trusted":false,"Blocked":false,"Contacts":{},"Ed25519PrivateKey":"J8ccHg0nDRTt2hUcWFgcja7zp3q+stire73hfHQDlGDntWrRy5JHfnj+JaOLkdijXBEt6PG1Qe3egbtK79qlOw==","OnionPrivateKey":{"N":106324796443231372795329965451792784374908475257731042677987977989945962496419819543299936408371285042498791020833780363910141715665590232533252599354509160780458961503863367842703504977430864504358617442294691508603803037645994752383061089701523494391193738887906210739432038880652477581768063943643214298049,"E":65537,"D":52882540623824249319263554234503221073355763301661673056925036705376788585582196893867658378736750343245656531655368795367730890395281737333932003731626103306294071690361237344309695692052986927494790956908776032726936870574424804180862906949851814015510618834696423905205181829311680766288721499332239092113,"Primes":[10562771257917076828400600569279483678021278216385409474099349073602122852652613259317666843104807170827922546052248527778489213047126675685744594423055011,10065994410656021893110220970838146088057898596082565348257922502730196228417367015775815130802667391440031211811041050535960601302390904626913561708368459],"Precomputed":{"Dp":14666710170902757089650955213153379231578136284710503412469914181268492295823547104657028590300707272919739257072411249032493376066779490782348262698903,"Dq":8351748051846008307669886865591879879827216596130210009260002655117828861809706712999156561217721929245207091771627754763620453429647494239789002112611857,"Qinv":5157808396374745421942830050538059633959311365944586097995200192447276074688521466971512517666145546534306106545362826255395595072097617674779280863162908,"CRTValues":[]}},"Onion":"cf3nb4kb4ekfep7t","Groups":{}}
|
|
@ -38,41 +38,26 @@ func TestProfileIdentity(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProfileGroup(t *testing.T) {
|
func TestProfileGroup(t *testing.T) {
|
||||||
/**sarah := GenerateNewProfile("Sarah")
|
sarah := GenerateNewProfile("Sarah")
|
||||||
alice := GenerateNewProfile("Alice")
|
alice := GenerateNewProfile("Alice")
|
||||||
sarah.AddContact("alice.onion", alice.PublicProfile)
|
sarah.AddContact(alice.Onion, alice.PublicProfile)
|
||||||
alice.AddContact("sarah.onion", sarah.PublicProfile)
|
alice.AddContact(sarah.Onion, sarah.PublicProfile)
|
||||||
|
|
||||||
group := NewGroup("server.onion")
|
gid, invite := alice.StartGroup("aaa.onion")
|
||||||
alice.AddGroup(group)
|
gci := &protocol.CwtchPeerPacket{}
|
||||||
sarah.AddGroup(group)
|
proto.Unmarshal(invite, gci)
|
||||||
|
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
|
||||||
|
|
||||||
|
group := alice.GetGroupByGroupId(gid)
|
||||||
c, s := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
|
c, s := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
|
||||||
ok, gid, onion, message := alice.AttemptDecryption(c, s)
|
alice.AttemptDecryption(c, s)
|
||||||
|
|
||||||
if ok && gid == group.GroupID && onion == "sarah.onion" && message == "Hello World" {
|
gid2, invite2 := alice.StartGroup("bbb.onion")
|
||||||
t.Logf("Success!")
|
gci2 := &protocol.CwtchPeerPacket{}
|
||||||
} else {
|
proto.Unmarshal(invite2, gci2)
|
||||||
t.Errorf("Failed to decrypt group message %v %v %v %v", ok, gid, onion, message)
|
sarah.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion)
|
||||||
}
|
group2 := alice.GetGroupByGroupId(gid2)
|
||||||
|
|
||||||
group2 := NewGroup("server2.onion")
|
|
||||||
sarah.AddGroup(group2)
|
|
||||||
alice.AddGroup(group2)
|
|
||||||
c2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID)
|
c2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID)
|
||||||
ok, gid, onion, message = alice.AttemptDecryption(c2, s)
|
alice.AttemptDecryption(c2, s)
|
||||||
if onion != "not-verified" {
|
|
||||||
t.Errorf("verification should have failed %v %v %v %v", ok, gid, onion, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
bob := GenerateNewProfile("Bob")
|
|
||||||
bob.AddGroup(group)
|
|
||||||
c, s = bob.EncryptMessageToGroup("Hello", group.GroupID)
|
|
||||||
ok, gid, onion, message = alice.AttemptDecryption(c, s)
|
|
||||||
|
|
||||||
if ok && gid == group.GroupID && onion == "not-verified" && message == "Hello" {
|
|
||||||
t.Logf("Success!")
|
|
||||||
} else {
|
|
||||||
t.Errorf("Failed to decrypt unverified group message %v %v %v %v", ok, gid, onion, message)
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,9 @@ package connections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.mascherari.press/cwtch/model"
|
"git.mascherari.press/cwtch/model"
|
||||||
"time"
|
"git.mascherari.press/cwtch/protocol"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
|
@ -16,7 +17,7 @@ func NewConnectionsManager() *Manager {
|
||||||
m := new(Manager)
|
m := new(Manager)
|
||||||
m.peerConnections = make(map[string]*PeerPeerConnection)
|
m.peerConnections = make(map[string]*PeerPeerConnection)
|
||||||
m.serverConnections = make(map[string]*PeerServerConnection)
|
m.serverConnections = make(map[string]*PeerServerConnection)
|
||||||
return m;
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) ManagePeerConnection(host string, profile *model.Profile) {
|
func (m *Manager) ManagePeerConnection(host string, profile *model.Profile) {
|
||||||
|
@ -28,10 +29,11 @@ func (m *Manager) ManagePeerConnection(host string, profile *model.Profile) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) ManageServerConnection(host string) {
|
func (m *Manager) ManageServerConnection(host string, handler func(string, *protocol.GroupMessage)) {
|
||||||
m.lock.Lock()
|
m.lock.Lock()
|
||||||
psc := NewPeerServerConnection(host)
|
psc := NewPeerServerConnection(host)
|
||||||
go psc.Run()
|
go psc.Run()
|
||||||
|
psc.GroupMessageHandler = handler
|
||||||
m.serverConnections[host] = psc
|
m.serverConnections[host] = psc
|
||||||
m.lock.Unlock()
|
m.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package connections
|
package connections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"git.mascherari.press/cwtch/peer/fetch"
|
"git.mascherari.press/cwtch/peer/fetch"
|
||||||
"git.mascherari.press/cwtch/peer/listen"
|
"git.mascherari.press/cwtch/peer/listen"
|
||||||
"git.mascherari.press/cwtch/peer/send"
|
"git.mascherari.press/cwtch/peer/send"
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
"github.com/s-rah/go-ricochet/connection"
|
"github.com/s-rah/go-ricochet/connection"
|
||||||
"github.com/s-rah/go-ricochet/identity"
|
"github.com/s-rah/go-ricochet/identity"
|
||||||
"github.com/s-rah/go-ricochet/utils"
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@ func (psc *PeerServerConnection) GetState() ConnectionState {
|
||||||
|
|
||||||
// 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)
|
||||||
rc, err := goricochet.Open(psc.Server)
|
rc, err := goricochet.Open(psc.Server)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rc.TraceLog(true)
|
rc.TraceLog(true)
|
||||||
|
@ -58,7 +61,6 @@ func (psc *PeerServerConnection) Run() error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
psc.connection.Process(psc)
|
psc.connection.Process(psc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,25 +75,42 @@ func (psc *PeerServerConnection) Break() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) {
|
func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) {
|
||||||
|
for psc.state != AUTHENTICATED {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
}
|
||||||
|
log.Printf("Opening a Channel to Send")
|
||||||
psc.connection.Do(func() error {
|
psc.connection.Do(func() error {
|
||||||
psc.connection.RequestOpenChannel("im.cwtch.server.send", &send.CwtchPeerSendChannel{})
|
psc.connection.RequestOpenChannel("im.cwtch.server.send", &send.CwtchPeerSendChannel{})
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
log.Printf("Waiting...")
|
||||||
// TODO We have to wait to receive the channel result before we can continue
|
// TODO We have to wait to receive the channel result before we can continue
|
||||||
// We should have a better mechanism for this kindof interaction
|
// We should have a better mechanism for this kindof interaction
|
||||||
time.Sleep(time.Second * 1)
|
log.Printf("CWTCH PEER Sending...")
|
||||||
psc.connection.Do(func() error {
|
send:
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
err := psc.connection.Do(func() error {
|
||||||
channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound)
|
channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound)
|
||||||
if channel != nil {
|
if channel == nil {
|
||||||
|
return errors.New("No Channel")
|
||||||
|
}
|
||||||
sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel)
|
sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel)
|
||||||
if ok {
|
if ok {
|
||||||
sendchannel.SendGroupMessage(gm)
|
sendchannel.SendGroupMessage(gm)
|
||||||
}
|
} else {
|
||||||
|
return errors.New("Failed")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
for err != nil {
|
||||||
|
log.Printf("CHANNEL ERROR %v", err)
|
||||||
|
goto send
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Done")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (psc *PeerServerConnection) HandleGroupMessage(gm *protocol.GroupMessage) {
|
func (psc *PeerServerConnection) HandleGroupMessage(gm *protocol.GroupMessage) {
|
||||||
|
log.Printf("Received Group Message: %v", gm)
|
||||||
psc.GroupMessageHandler(psc.Server, gm)
|
psc.GroupMessageHandler(psc.Server, gm)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package peer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"git.mascherari.press/cwtch/model"
|
"git.mascherari.press/cwtch/model"
|
||||||
"git.mascherari.press/cwtch/peer/connections"
|
"git.mascherari.press/cwtch/peer/connections"
|
||||||
"git.mascherari.press/cwtch/peer/peer"
|
"git.mascherari.press/cwtch/peer/peer"
|
||||||
|
@ -11,7 +12,6 @@ import (
|
||||||
"github.com/s-rah/go-ricochet/connection"
|
"github.com/s-rah/go-ricochet/connection"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sync"
|
"sync"
|
||||||
"errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +24,6 @@ Move CwtchPeerChannel under peer/
|
||||||
Write tests for Peer Channel
|
Write tests for Peer Channel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
type CwtchPeer struct {
|
type CwtchPeer struct {
|
||||||
connection.AutoConnectionHandler
|
connection.AutoConnectionHandler
|
||||||
Profile *model.Profile
|
Profile *model.Profile
|
||||||
|
@ -73,15 +72,22 @@ func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
|
||||||
return errors.New("group id could not be found")
|
return errors.New("group id could not be found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cp *CwtchPeer) ReceiveGroupMessage(server string, gm *protocol.GroupMessage) {
|
||||||
|
cp.Profile.AttemptDecryption(gm.Ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
func (cp *CwtchPeer) JoinServer(onion string) {
|
func (cp *CwtchPeer) JoinServer(onion string) {
|
||||||
cp.connectionsManager.ManageServerConnection(onion)
|
cp.connectionsManager.ManageServerConnection(onion, cp.ReceiveGroupMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) {
|
func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) {
|
||||||
// Lookup Group
|
group := cp.Profile.GetGroupByGroupId(groupid)
|
||||||
// Lookup Sever Connection
|
psc := cp.connectionsManager.GetPeerServerConnectionForOnion(group.GroupServer)
|
||||||
// If no server connection, spin off server connection
|
ct, _ := cp.Profile.EncryptMessageToGroup(message, groupid)
|
||||||
// Else group.EncryptMessage(message) and send result to server
|
gm := &protocol.GroupMessage{
|
||||||
|
Ciphertext: ct,
|
||||||
|
}
|
||||||
|
psc.SendGroupMessage(gm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *CwtchPeer) Listen() error {
|
func (cp *CwtchPeer) Listen() error {
|
||||||
|
@ -110,7 +116,6 @@ func (cp *CwtchPeer) Listen() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type CwtchPeerInstance struct {
|
type CwtchPeerInstance struct {
|
||||||
rai *application.ApplicationInstance
|
rai *application.ApplicationInstance
|
||||||
ra *application.RicochetApplication
|
ra *application.RicochetApplication
|
||||||
|
@ -121,7 +126,6 @@ func (cpi *CwtchPeerInstance) Init(rai *application.ApplicationInstance, ra *app
|
||||||
cpi.ra = ra
|
cpi.ra = ra
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type CwtchPeerHandler struct {
|
type CwtchPeerHandler struct {
|
||||||
Onion string
|
Onion string
|
||||||
Peer *CwtchPeer
|
Peer *CwtchPeer
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package peer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
|
alice := NewCwtchPeer("Alice")
|
||||||
|
id, _ := alice.Profile.StartGroup("ylhbhtypevo4ympq")
|
||||||
|
alice.Profile.AddContact(alice.Profile.Onion, alice.Profile.PublicProfile)
|
||||||
|
alice.JoinServer("ylhbhtypevo4ympq")
|
||||||
|
// time.Sleep(time.Second *5)
|
||||||
|
alice.SendMessageToGroup(id, "Hello")
|
||||||
|
alice.SendMessageToGroup(id, "My")
|
||||||
|
alice.SendMessageToGroup(id, "Name Is")
|
||||||
|
alice.SendMessageToGroup(id, "ALICE!!!")
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
group := alice.Profile.Groups[id]
|
||||||
|
t.Logf("%v", group.Timeline)
|
||||||
|
}
|
|
@ -81,6 +81,7 @@ func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) {
|
||||||
}
|
}
|
||||||
packet, _ := proto.Marshal(csp)
|
packet, _ := proto.Marshal(csp)
|
||||||
cplc.channel.SendMessage(packet)
|
cplc.channel.SendMessage(packet)
|
||||||
|
cplc.channel.CloseChannel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packet should never be
|
// Packet should never be
|
||||||
|
|
|
@ -0,0 +1,325 @@
|
||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: ControlChannel.proto
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package protocol is a generated protocol buffer package.
|
||||||
|
|
||||||
|
It is generated from these files:
|
||||||
|
ControlChannel.proto
|
||||||
|
cwtch-profile.proto
|
||||||
|
group_message.proto
|
||||||
|
|
||||||
|
It has these top-level messages:
|
||||||
|
Packet
|
||||||
|
OpenChannel
|
||||||
|
ChannelResult
|
||||||
|
KeepAlive
|
||||||
|
EnableFeatures
|
||||||
|
FeaturesEnabled
|
||||||
|
CwtchPeerPacket
|
||||||
|
CwtchIdentity
|
||||||
|
GroupChatInvite
|
||||||
|
CwtchServerPacket
|
||||||
|
FetchMessage
|
||||||
|
GroupMessage
|
||||||
|
DecryptedGroupMessage
|
||||||
|
*/
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import proto "github.com/golang/protobuf/proto"
|
||||||
|
import fmt "fmt"
|
||||||
|
import math "math"
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
|
|
||||||
|
type ChannelResult_CommonError int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ChannelResult_GenericError ChannelResult_CommonError = 0
|
||||||
|
ChannelResult_UnknownTypeError ChannelResult_CommonError = 1
|
||||||
|
ChannelResult_UnauthorizedError ChannelResult_CommonError = 2
|
||||||
|
ChannelResult_BadUsageError ChannelResult_CommonError = 3
|
||||||
|
ChannelResult_FailedError ChannelResult_CommonError = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
var ChannelResult_CommonError_name = map[int32]string{
|
||||||
|
0: "GenericError",
|
||||||
|
1: "UnknownTypeError",
|
||||||
|
2: "UnauthorizedError",
|
||||||
|
3: "BadUsageError",
|
||||||
|
4: "FailedError",
|
||||||
|
}
|
||||||
|
var ChannelResult_CommonError_value = map[string]int32{
|
||||||
|
"GenericError": 0,
|
||||||
|
"UnknownTypeError": 1,
|
||||||
|
"UnauthorizedError": 2,
|
||||||
|
"BadUsageError": 3,
|
||||||
|
"FailedError": 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x ChannelResult_CommonError) Enum() *ChannelResult_CommonError {
|
||||||
|
p := new(ChannelResult_CommonError)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
func (x ChannelResult_CommonError) String() string {
|
||||||
|
return proto.EnumName(ChannelResult_CommonError_name, int32(x))
|
||||||
|
}
|
||||||
|
func (x *ChannelResult_CommonError) UnmarshalJSON(data []byte) error {
|
||||||
|
value, err := proto.UnmarshalJSONEnum(ChannelResult_CommonError_value, data, "ChannelResult_CommonError")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*x = ChannelResult_CommonError(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (ChannelResult_CommonError) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} }
|
||||||
|
|
||||||
|
type Packet struct {
|
||||||
|
// Must contain exactly one field
|
||||||
|
OpenChannel *OpenChannel `protobuf:"bytes,1,opt,name=open_channel,json=openChannel" json:"open_channel,omitempty"`
|
||||||
|
ChannelResult *ChannelResult `protobuf:"bytes,2,opt,name=channel_result,json=channelResult" json:"channel_result,omitempty"`
|
||||||
|
KeepAlive *KeepAlive `protobuf:"bytes,3,opt,name=keep_alive,json=keepAlive" json:"keep_alive,omitempty"`
|
||||||
|
EnableFeatures *EnableFeatures `protobuf:"bytes,4,opt,name=enable_features,json=enableFeatures" json:"enable_features,omitempty"`
|
||||||
|
FeaturesEnabled *FeaturesEnabled `protobuf:"bytes,5,opt,name=features_enabled,json=featuresEnabled" json:"features_enabled,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Packet) Reset() { *m = Packet{} }
|
||||||
|
func (m *Packet) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*Packet) ProtoMessage() {}
|
||||||
|
func (*Packet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
|
|
||||||
|
func (m *Packet) GetOpenChannel() *OpenChannel {
|
||||||
|
if m != nil {
|
||||||
|
return m.OpenChannel
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Packet) GetChannelResult() *ChannelResult {
|
||||||
|
if m != nil {
|
||||||
|
return m.ChannelResult
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Packet) GetKeepAlive() *KeepAlive {
|
||||||
|
if m != nil {
|
||||||
|
return m.KeepAlive
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Packet) GetEnableFeatures() *EnableFeatures {
|
||||||
|
if m != nil {
|
||||||
|
return m.EnableFeatures
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Packet) GetFeaturesEnabled() *FeaturesEnabled {
|
||||||
|
if m != nil {
|
||||||
|
return m.FeaturesEnabled
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenChannel struct {
|
||||||
|
ChannelIdentifier *int32 `protobuf:"varint,1,req,name=channel_identifier,json=channelIdentifier" json:"channel_identifier,omitempty"`
|
||||||
|
ChannelType *string `protobuf:"bytes,2,req,name=channel_type,json=channelType" json:"channel_type,omitempty"`
|
||||||
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *OpenChannel) Reset() { *m = OpenChannel{} }
|
||||||
|
func (m *OpenChannel) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*OpenChannel) ProtoMessage() {}
|
||||||
|
func (*OpenChannel) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||||
|
|
||||||
|
var extRange_OpenChannel = []proto.ExtensionRange{
|
||||||
|
{100, 536870911},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*OpenChannel) ExtensionRangeArray() []proto.ExtensionRange {
|
||||||
|
return extRange_OpenChannel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *OpenChannel) GetChannelIdentifier() int32 {
|
||||||
|
if m != nil && m.ChannelIdentifier != nil {
|
||||||
|
return *m.ChannelIdentifier
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *OpenChannel) GetChannelType() string {
|
||||||
|
if m != nil && m.ChannelType != nil {
|
||||||
|
return *m.ChannelType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChannelResult struct {
|
||||||
|
ChannelIdentifier *int32 `protobuf:"varint,1,req,name=channel_identifier,json=channelIdentifier" json:"channel_identifier,omitempty"`
|
||||||
|
Opened *bool `protobuf:"varint,2,req,name=opened" json:"opened,omitempty"`
|
||||||
|
CommonError *ChannelResult_CommonError `protobuf:"varint,3,opt,name=common_error,json=commonError,enum=protocol.ChannelResult_CommonError" json:"common_error,omitempty"`
|
||||||
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ChannelResult) Reset() { *m = ChannelResult{} }
|
||||||
|
func (m *ChannelResult) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*ChannelResult) ProtoMessage() {}
|
||||||
|
func (*ChannelResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||||
|
|
||||||
|
var extRange_ChannelResult = []proto.ExtensionRange{
|
||||||
|
{100, 536870911},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ChannelResult) ExtensionRangeArray() []proto.ExtensionRange {
|
||||||
|
return extRange_ChannelResult
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ChannelResult) GetChannelIdentifier() int32 {
|
||||||
|
if m != nil && m.ChannelIdentifier != nil {
|
||||||
|
return *m.ChannelIdentifier
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ChannelResult) GetOpened() bool {
|
||||||
|
if m != nil && m.Opened != nil {
|
||||||
|
return *m.Opened
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ChannelResult) GetCommonError() ChannelResult_CommonError {
|
||||||
|
if m != nil && m.CommonError != nil {
|
||||||
|
return *m.CommonError
|
||||||
|
}
|
||||||
|
return ChannelResult_GenericError
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeepAlive struct {
|
||||||
|
ResponseRequested *bool `protobuf:"varint,1,req,name=response_requested,json=responseRequested" json:"response_requested,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *KeepAlive) Reset() { *m = KeepAlive{} }
|
||||||
|
func (m *KeepAlive) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*KeepAlive) ProtoMessage() {}
|
||||||
|
func (*KeepAlive) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||||
|
|
||||||
|
func (m *KeepAlive) GetResponseRequested() bool {
|
||||||
|
if m != nil && m.ResponseRequested != nil {
|
||||||
|
return *m.ResponseRequested
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnableFeatures struct {
|
||||||
|
Feature []string `protobuf:"bytes,1,rep,name=feature" json:"feature,omitempty"`
|
||||||
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *EnableFeatures) Reset() { *m = EnableFeatures{} }
|
||||||
|
func (m *EnableFeatures) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*EnableFeatures) ProtoMessage() {}
|
||||||
|
func (*EnableFeatures) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||||
|
|
||||||
|
var extRange_EnableFeatures = []proto.ExtensionRange{
|
||||||
|
{100, 536870911},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EnableFeatures) ExtensionRangeArray() []proto.ExtensionRange {
|
||||||
|
return extRange_EnableFeatures
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *EnableFeatures) GetFeature() []string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Feature
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FeaturesEnabled struct {
|
||||||
|
Feature []string `protobuf:"bytes,1,rep,name=feature" json:"feature,omitempty"`
|
||||||
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FeaturesEnabled) Reset() { *m = FeaturesEnabled{} }
|
||||||
|
func (m *FeaturesEnabled) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*FeaturesEnabled) ProtoMessage() {}
|
||||||
|
func (*FeaturesEnabled) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||||
|
|
||||||
|
var extRange_FeaturesEnabled = []proto.ExtensionRange{
|
||||||
|
{100, 536870911},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FeaturesEnabled) ExtensionRangeArray() []proto.ExtensionRange {
|
||||||
|
return extRange_FeaturesEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FeaturesEnabled) GetFeature() []string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Feature
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterType((*Packet)(nil), "protocol.Packet")
|
||||||
|
proto.RegisterType((*OpenChannel)(nil), "protocol.OpenChannel")
|
||||||
|
proto.RegisterType((*ChannelResult)(nil), "protocol.ChannelResult")
|
||||||
|
proto.RegisterType((*KeepAlive)(nil), "protocol.KeepAlive")
|
||||||
|
proto.RegisterType((*EnableFeatures)(nil), "protocol.EnableFeatures")
|
||||||
|
proto.RegisterType((*FeaturesEnabled)(nil), "protocol.FeaturesEnabled")
|
||||||
|
proto.RegisterEnum("protocol.ChannelResult_CommonError", ChannelResult_CommonError_name, ChannelResult_CommonError_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { proto.RegisterFile("ControlChannel.proto", fileDescriptor0) }
|
||||||
|
|
||||||
|
var fileDescriptor0 = []byte{
|
||||||
|
// 461 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0x4d, 0x8f, 0xd3, 0x30,
|
||||||
|
0x10, 0x25, 0xe9, 0xee, 0x92, 0x4e, 0xfa, 0x91, 0x9a, 0x5d, 0x30, 0xb7, 0x12, 0x2e, 0x15, 0x12,
|
||||||
|
0x3d, 0x54, 0x20, 0x21, 0x0e, 0x48, 0x4b, 0xd9, 0x22, 0xc4, 0x01, 0x64, 0xd1, 0x73, 0x64, 0x92,
|
||||||
|
0x29, 0x1b, 0x35, 0x6b, 0x1b, 0xc7, 0x05, 0x2d, 0xa7, 0xfe, 0x0e, 0xfe, 0x0c, 0x7f, 0x0d, 0xc5,
|
||||||
|
0x89, 0x9b, 0x14, 0x09, 0x09, 0x4e, 0xc9, 0x9b, 0xf7, 0xde, 0x8c, 0xfc, 0x66, 0xe0, 0x7c, 0x29,
|
||||||
|
0x85, 0xd1, 0xb2, 0x58, 0x5e, 0x73, 0x21, 0xb0, 0x98, 0x2b, 0x2d, 0x8d, 0x24, 0x81, 0xfd, 0xa4,
|
||||||
|
0xb2, 0x88, 0x7f, 0xf9, 0x70, 0xf6, 0x91, 0xa7, 0x5b, 0x34, 0xe4, 0x05, 0x0c, 0xa4, 0x42, 0x91,
|
||||||
|
0xa4, 0xb5, 0x94, 0x7a, 0x53, 0x6f, 0x16, 0x2e, 0x2e, 0xe6, 0x4e, 0x3b, 0xff, 0xa0, 0x50, 0x34,
|
||||||
|
0x7d, 0x58, 0x28, 0x5b, 0x40, 0x5e, 0xc1, 0xa8, 0x31, 0x25, 0x1a, 0xcb, 0x5d, 0x61, 0xa8, 0x6f,
|
||||||
|
0xbd, 0x0f, 0x5a, 0xaf, 0xf3, 0x59, 0x9a, 0x0d, 0xd3, 0x2e, 0x24, 0x0b, 0x80, 0x2d, 0xa2, 0x4a,
|
||||||
|
0x78, 0x91, 0x7f, 0x43, 0xda, 0xb3, 0xde, 0x7b, 0xad, 0xf7, 0x3d, 0xa2, 0xba, 0xac, 0x28, 0xd6,
|
||||||
|
0xdf, 0xba, 0x5f, 0x72, 0x09, 0x63, 0x14, 0xfc, 0x73, 0x81, 0xc9, 0x06, 0xb9, 0xd9, 0x69, 0x2c,
|
||||||
|
0xe9, 0x89, 0x35, 0xd2, 0xd6, 0x78, 0x65, 0x05, 0xab, 0x86, 0x67, 0x23, 0x3c, 0xc2, 0xe4, 0x0d,
|
||||||
|
0x44, 0xce, 0x9b, 0xd4, 0x54, 0x46, 0x4f, 0x6d, 0x8f, 0x87, 0x6d, 0x0f, 0xa7, 0xae, 0x7b, 0x65,
|
||||||
|
0x6c, 0xbc, 0x39, 0x2e, 0xc4, 0x39, 0x84, 0x9d, 0x60, 0xc8, 0x53, 0x20, 0x2e, 0x8b, 0x3c, 0x43,
|
||||||
|
0x61, 0xf2, 0x4d, 0x8e, 0x9a, 0x7a, 0x53, 0x7f, 0x76, 0xca, 0x26, 0x0d, 0xf3, 0xee, 0x40, 0x90,
|
||||||
|
0x47, 0x30, 0x70, 0x72, 0x73, 0xab, 0x90, 0xfa, 0x53, 0x7f, 0xd6, 0x67, 0x61, 0x53, 0xfb, 0x74,
|
||||||
|
0xab, 0xf0, 0x49, 0x10, 0x64, 0xd1, 0x7e, 0xbf, 0xdf, 0xfb, 0xf1, 0x4f, 0x1f, 0x86, 0x47, 0x41,
|
||||||
|
0xfe, 0xef, 0xb4, 0xfb, 0x70, 0x56, 0xed, 0x0d, 0x33, 0x3b, 0x27, 0x60, 0x0d, 0x22, 0x2b, 0x18,
|
||||||
|
0xa4, 0xf2, 0xe6, 0x46, 0x8a, 0x04, 0xb5, 0x96, 0xda, 0xae, 0x60, 0xb4, 0x78, 0xfc, 0x97, 0xf5,
|
||||||
|
0xcd, 0x97, 0x56, 0x7b, 0x55, 0x49, 0x59, 0x98, 0xb6, 0x20, 0x56, 0x10, 0x76, 0x38, 0x12, 0xc1,
|
||||||
|
0xe0, 0x2d, 0x0a, 0xd4, 0x79, 0x6a, 0x71, 0x74, 0x87, 0x9c, 0x43, 0xb4, 0x16, 0x5b, 0x21, 0xbf,
|
||||||
|
0x8b, 0xea, 0x69, 0x75, 0xd5, 0x23, 0x17, 0x30, 0x59, 0x0b, 0xbe, 0x33, 0xd7, 0x52, 0xe7, 0x3f,
|
||||||
|
0x30, 0xab, 0xcb, 0x3e, 0x99, 0xc0, 0xf0, 0x35, 0xcf, 0xd6, 0x25, 0xff, 0xd2, 0x28, 0x7b, 0x64,
|
||||||
|
0x0c, 0xe1, 0x8a, 0xe7, 0x85, 0xd3, 0x9c, 0x74, 0xc2, 0x79, 0x09, 0xfd, 0xc3, 0xa1, 0x54, 0xb9,
|
||||||
|
0x68, 0x2c, 0x95, 0x14, 0x25, 0x26, 0x1a, 0xbf, 0xee, 0xb0, 0x34, 0x98, 0xd9, 0x5c, 0x02, 0x36,
|
||||||
|
0x71, 0x0c, 0x73, 0x44, 0xfc, 0x0c, 0x46, 0xc7, 0xb7, 0x42, 0x28, 0xdc, 0x6d, 0x16, 0x4d, 0xbd,
|
||||||
|
0x69, 0x6f, 0xd6, 0x67, 0x0e, 0x76, 0x26, 0x3e, 0x87, 0xf1, 0x1f, 0xd7, 0xf1, 0x2f, 0xb6, 0xdf,
|
||||||
|
0x01, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x32, 0x16, 0x1e, 0x93, 0x03, 0x00, 0x00,
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
syntax = "proto2";
|
||||||
|
package protocol;
|
||||||
|
|
||||||
|
message Packet {
|
||||||
|
// Must contain exactly one field
|
||||||
|
optional OpenChannel open_channel = 1;
|
||||||
|
optional ChannelResult channel_result = 2;
|
||||||
|
optional KeepAlive keep_alive = 3;
|
||||||
|
optional EnableFeatures enable_features = 4;
|
||||||
|
optional FeaturesEnabled features_enabled = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OpenChannel {
|
||||||
|
required int32 channel_identifier = 1; // Arbitrary unique identifier for this channel instance
|
||||||
|
required string channel_type = 2; // String identifying channel type; e.g. im.ricochet.chat
|
||||||
|
|
||||||
|
// It is valid to extend the OpenChannel message to add fields specific
|
||||||
|
// to the requested channel_type.
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChannelResult {
|
||||||
|
required int32 channel_identifier = 1; // Matching the value from OpenChannel
|
||||||
|
required bool opened = 2; // If the channel is now open
|
||||||
|
|
||||||
|
enum CommonError {
|
||||||
|
GenericError = 0;
|
||||||
|
UnknownTypeError = 1;
|
||||||
|
UnauthorizedError = 2;
|
||||||
|
BadUsageError = 3;
|
||||||
|
FailedError = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional CommonError common_error = 3;
|
||||||
|
|
||||||
|
// As with OpenChannel, it is valid to extend this message with fields specific
|
||||||
|
// to the channel type.
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message KeepAlive {
|
||||||
|
required bool response_requested = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnableFeatures {
|
||||||
|
repeated string feature = 1;
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FeaturesEnabled {
|
||||||
|
repeated string feature = 1;
|
||||||
|
extensions 100 to max;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
cwtchserver "git.mascherari.press/cwtch/server"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
server := new(cwtchserver.Server)
|
||||||
|
log.Printf("starting cwtch server...")
|
||||||
|
|
||||||
|
server.Run("./private_key")
|
||||||
|
}
|
|
@ -64,5 +64,6 @@ func (s *Server) Run(privateKeyFile string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
cwtchserver.Init(pk, af, new(application.AcceptAllContactManager))
|
cwtchserver.Init(pk, af, new(application.AcceptAllContactManager))
|
||||||
|
log.Printf("cwtch server running on cwtch:%s", l.Addr().String()[0:16])
|
||||||
cwtchserver.Run(l)
|
cwtchserver.Run(l)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/s-rah/go-ricochet/application"
|
"github.com/s-rah/go-ricochet/application"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServerInstance(t *testing.T) {
|
func TestServerInstance(t *testing.T) {
|
||||||
|
@ -27,4 +28,9 @@ func TestServerInstance(t *testing.T) {
|
||||||
if len(res) != 1 {
|
if len(res) != 1 {
|
||||||
t.Errorf("Expected Group Messages Instead got %v", res)
|
t.Errorf("Expected Group Messages Instead got %v", res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ra.HandleApplicationInstance(ai)
|
||||||
|
si.HandleGroupMessage(&gm)
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue