ソースを参照

Lots of peerand serverstuff

blocking-thread-safe
コミット
914be9e46a

+ 11
- 8
model/group.go ファイルの表示

@@ -3,11 +3,12 @@ package model
import (
"crypto/rand"
"fmt"
"golang.org/x/crypto/nacl/secretbox"
"io"
"github.com/golang/protobuf/proto"
"git.mascherari.press/cwtch/protocol"
"github.com/golang/protobuf/proto"
"github.com/s-rah/go-ricochet/utils"
"golang.org/x/crypto/nacl/secretbox"
"io"
"log"
"time"
)

@@ -52,7 +53,9 @@ func (g *Group) Invite() []byte {
GroupName: g.GroupID,
GroupSharedKey: g.GroupKey[:],
ServerHost: g.GroupServer,
SignedGroupId: g.SignedGroupID[:],
}
log.Printf("INVITEBEFORE %v", gci)
cp := &protocol.CwtchPeerPacket{
GroupChatInvite: gci,
}
@@ -63,11 +66,11 @@ func (g *Group) Invite() []byte {

func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, verified bool) {
timelineMessage := Message{
Message: message.GetText(),
Timestamp: time.Unix(int64(message.GetTimestamp()),0),
Message: message.GetText(),
Timestamp: time.Unix(int64(message.GetTimestamp()), 0),
Signature: message.GetSignature(),
Verified:verified,
PeerID: message.GetOnion(),
Verified: verified,
PeerID: message.GetOnion(),
}
g.Timeline = append(g.Timeline, timelineMessage)
}
@@ -88,7 +91,7 @@ func (g *Group) EncryptMessage(message *protocol.DecryptedGroupMessage) []byte {
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
panic(err)
}
wire,err := proto.Marshal(message)
wire, err := proto.Marshal(message)
utils.CheckError(err)
encrypted := secretbox.Seal(nonce[:], []byte(wire), &nonce, &g.GroupKey)
return encrypted

+ 5
- 6
model/group_test.go ファイルの表示

@@ -1,21 +1,20 @@
package model

import (
"testing"
"git.mascherari.press/cwtch/protocol"
"github.com/golang/protobuf/proto"
"testing"
"time"
)

func TestGroup(t *testing.T) {
g := NewGroup("server.onion")
dgm := &protocol.DecryptedGroupMessage{
Onion: proto.String("onion"),
Text: proto.String("Hello World!"),
Timestamp: proto.Int32(int32(time.Now().Unix())),
Onion: proto.String("onion"),
Text: proto.String("Hello World!"),
Timestamp: proto.Int32(int32(time.Now().Unix())),
SignedGroupId: []byte{},
Signature: []byte{},

Signature: []byte{},
}
encMessage := g.EncryptMessage(dgm)
ok, message := g.DecryptMessage(encMessage)

+ 0
- 1
model/message.go ファイルの表示

@@ -4,7 +4,6 @@ import (
"time"
)


// Message is a local representation of a given message sent over a group chat channel.
type Message struct {
Timestamp time.Time

+ 27
- 17
model/profile.go ファイルの表示

@@ -3,34 +3,33 @@ package model
import (
"crypto/rand"
"crypto/rsa"
"encoding/asn1"
"encoding/json"
"git.mascherari.press/cwtch/protocol"
"github.com/golang/protobuf/proto"
"github.com/s-rah/go-ricochet/utils"
"golang.org/x/crypto/ed25519"
"io/ioutil"
"time"
"encoding/asn1"
"log"
"strconv"
"time"
)


// PublicProfile is a local copy of a CwtchIdentity
type PublicProfile struct {
Name string
Ed25519PublicKey ed25519.PublicKey
Trusted bool
Blocked bool
Trusted bool
Blocked bool
}


// Profile encapsulates all the attributes necessary to be a Cwtch Peer.
type Profile struct {
PublicProfile
Contacts map[string]PublicProfile
Ed25519PrivateKey ed25519.PrivateKey
OnionPrivateKey *rsa.PrivateKey
Onion string
Onion string
Groups map[string]*Group
}

@@ -96,6 +95,12 @@ func (p *Profile) VerifyMessage(onion string, message string, signature []byte)
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
func (p *Profile) SignMessage(message string) []byte {
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) {
group := NewGroup(server)
groupID = group.GroupID
signedGroupId := p.SignMessage(groupID)
group.SignGroup(signedGroupId)
invite = group.Invite()
p.AddGroup(group)
return
}

func (p *Profile) GetGroupByGroupId(groupID string) (*Group) {
func (p *Profile) GetGroupByGroupId(groupID string) *Group {
return p.Groups[groupID]
}

@@ -119,6 +127,7 @@ func (p *Profile) GetGroupByGroupId(groupID string) (*Group) {
func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname string) {
group := new(Group)
group.GroupID = gci.GetGroupName()
group.SignedGroupID = gci.GetSignedGroupId()
copy(group.GroupKey[:], gci.GetGroupSharedKey()[:])
group.GroupServer = gci.GetServerHost()
group.Accepted = false
@@ -126,7 +135,7 @@ func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname stri
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) {
existingGroup, exists := p.Groups[group.GroupID]
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.
func (p *Profile) AttemptDecryption(ciphertext []byte, signature []byte) {
func (p *Profile) AttemptDecryption(ciphertext []byte) {
for _, group := range p.Groups {
success, dgm := group.DecryptMessage(ciphertext)
log.Printf("Decrypt Attempt %v %v", success, dgm)
if success {
// 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)
}
}
@@ -162,12 +172,12 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) (ciphert
group := p.Groups[groupID]
timestamp := time.Now().Unix()
signature = p.SignMessage(message + groupID + strconv.Itoa(int(timestamp)))
dm := &protocol.DecryptedGroupMessage {
Onion: proto.String(p.Onion),
Text: proto.String(message),
SignedGroupId: group.SignedGroupID,
Timestamp: proto.Int32(int32(timestamp)),
Signature: signature,
dm := &protocol.DecryptedGroupMessage{
Onion: proto.String(p.Onion),
Text: proto.String(message),
SignedGroupId: group.SignedGroupID[:],
Timestamp: proto.Int32(int32(timestamp)),
Signature: signature,
}
ciphertext = group.EncryptMessage(dm)
return

+ 1
- 1
model/profile_test ファイルの表示

@@ -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":{}}

+ 15
- 30
model/profile_test.go ファイルの表示

@@ -38,41 +38,26 @@ func TestProfileIdentity(t *testing.T) {
}

func TestProfileGroup(t *testing.T) {
/**sarah := GenerateNewProfile("Sarah")
sarah := GenerateNewProfile("Sarah")
alice := GenerateNewProfile("Alice")
sarah.AddContact("alice.onion", alice.PublicProfile)
alice.AddContact("sarah.onion", sarah.PublicProfile)
sarah.AddContact(alice.Onion, alice.PublicProfile)
alice.AddContact(sarah.Onion, sarah.PublicProfile)

group := NewGroup("server.onion")
alice.AddGroup(group)
sarah.AddGroup(group)
gid, invite := alice.StartGroup("aaa.onion")
gci := &protocol.CwtchPeerPacket{}
proto.Unmarshal(invite, gci)
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)

group := alice.GetGroupByGroupId(gid)
c, s := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
ok, gid, onion, message := alice.AttemptDecryption(c, s)

if ok && gid == group.GroupID && onion == "sarah.onion" && message == "Hello World" {
t.Logf("Success!")
} else {
t.Errorf("Failed to decrypt group message %v %v %v %v", ok, gid, onion, message)
}
alice.AttemptDecryption(c, s)

group2 := NewGroup("server2.onion")
sarah.AddGroup(group2)
alice.AddGroup(group2)
gid2, invite2 := alice.StartGroup("bbb.onion")
gci2 := &protocol.CwtchPeerPacket{}
proto.Unmarshal(invite2, gci2)
sarah.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion)
group2 := alice.GetGroupByGroupId(gid2)
c2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID)
ok, gid, onion, message = 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)
alice.AttemptDecryption(c2, 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)
}*/
}

+ 7
- 5
peer/connections/connectionsmanager.go ファイルの表示

@@ -2,21 +2,22 @@ package connections

import (
"git.mascherari.press/cwtch/model"
"time"
"git.mascherari.press/cwtch/protocol"
"sync"
"time"
)

type Manager struct {
peerConnections map[string]*PeerPeerConnection
serverConnections map[string]*PeerServerConnection
lock sync.Mutex
lock sync.Mutex
}

func NewConnectionsManager() *Manager {
m := new(Manager)
m.peerConnections = make(map[string]*PeerPeerConnection)
m.serverConnections = make(map[string]*PeerServerConnection)
return m;
return m
}

func (m *Manager) ManagePeerConnection(host string, profile *model.Profile) {
@@ -28,17 +29,18 @@ 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()
psc := NewPeerServerConnection(host)
go psc.Run()
psc.GroupMessageHandler = handler
m.serverConnections[host] = psc
m.lock.Unlock()
}

func (m *Manager) GetPeerPeerConnectionForOnion(host string) (ppc *PeerPeerConnection) {
m.lock.Lock()
ppc = m.peerConnections[host]
ppc = m.peerConnections[host]
m.lock.Unlock()
return
}

+ 27
- 8
peer/connections/peerserverconnection.go ファイルの表示

@@ -1,6 +1,7 @@
package connections

import (
"errors"
"git.mascherari.press/cwtch/peer/fetch"
"git.mascherari.press/cwtch/peer/listen"
"git.mascherari.press/cwtch/peer/send"
@@ -10,6 +11,7 @@ import (
"github.com/s-rah/go-ricochet/connection"
"github.com/s-rah/go-ricochet/identity"
"github.com/s-rah/go-ricochet/utils"
"log"
"time"
)

@@ -36,6 +38,7 @@ func (psc *PeerServerConnection) GetState() ConnectionState {

// Run manages the setup and teardown of a peer server connection
func (psc *PeerServerConnection) Run() error {
log.Printf("Connecting to %v", psc.Server)
rc, err := goricochet.Open(psc.Server)
if err == nil {
rc.TraceLog(true)
@@ -58,7 +61,6 @@ func (psc *PeerServerConnection) Run() error {
return nil
})
}()

psc.connection.Process(psc)
}
}
@@ -73,25 +75,42 @@ func (psc *PeerServerConnection) Break() error {
}

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.RequestOpenChannel("im.cwtch.server.send", &send.CwtchPeerSendChannel{})
return nil
})
log.Printf("Waiting...")
// TODO We have to wait to receive the channel result before we can continue
// We should have a better mechanism for this kindof interaction
time.Sleep(time.Second * 1)
psc.connection.Do(func() error {
log.Printf("CWTCH PEER Sending...")
send:
time.Sleep(time.Second * 2)
err := psc.connection.Do(func() error {
channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound)
if channel != nil {
sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel)
if ok {
sendchannel.SendGroupMessage(gm)
}
if channel == nil {
return errors.New("No Channel")
}
sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel)
if ok {
sendchannel.SendGroupMessage(gm)
} else {
return errors.New("Failed")
}
return nil
})
for err != nil {
log.Printf("CHANNEL ERROR %v", err)
goto send
}

log.Printf("Done")
}

func (psc *PeerServerConnection) HandleGroupMessage(gm *protocol.GroupMessage) {
log.Printf("Received Group Message: %v", gm)
psc.GroupMessageHandler(psc.Server, gm)
}

+ 18
- 14
peer/cwtch_peer.go ファイルの表示

@@ -2,6 +2,7 @@ package peer

import (
"encoding/json"
"errors"
"git.mascherari.press/cwtch/model"
"git.mascherari.press/cwtch/peer/connections"
"git.mascherari.press/cwtch/peer/peer"
@@ -11,7 +12,6 @@ import (
"github.com/s-rah/go-ricochet/connection"
"io/ioutil"
"sync"
"errors"
)

/**
@@ -24,12 +24,11 @@ Move CwtchPeerChannel under peer/
Write tests for Peer Channel
*/


type CwtchPeer struct {
connection.AutoConnectionHandler
Profile *model.Profile
mutex sync.Mutex
Log chan string `json:"-"`
Profile *model.Profile
mutex sync.Mutex
Log chan string `json:"-"`
connectionsManager *connections.Manager
}

@@ -64,8 +63,8 @@ func (cp *CwtchPeer) PeerWithOnion(onion string) {

// InviteOnionToGroup kicks off the invite process
func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
group:= cp.Profile.GetGroupByGroupId(groupid)
if group == nil {
group := cp.Profile.GetGroupByGroupId(groupid)
if group == nil {
invite := group.Invite()
ppc := cp.connectionsManager.GetPeerPeerConnectionForOnion(onion)
ppc.SendGroupInvite(invite)
@@ -73,15 +72,22 @@ func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
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) {
cp.connectionsManager.ManageServerConnection(onion)
cp.connectionsManager.ManageServerConnection(onion, cp.ReceiveGroupMessage)
}

func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) {
// Lookup Group
// Lookup Sever Connection
// If no server connection, spin off server connection
// Else group.EncryptMessage(message) and send result to server
group := cp.Profile.GetGroupByGroupId(groupid)
psc := cp.connectionsManager.GetPeerServerConnectionForOnion(group.GroupServer)
ct, _ := cp.Profile.EncryptMessageToGroup(message, groupid)
gm := &protocol.GroupMessage{
Ciphertext: ct,
}
psc.SendGroupMessage(gm)
}

func (cp *CwtchPeer) Listen() error {
@@ -110,7 +116,6 @@ func (cp *CwtchPeer) Listen() error {
return nil
}


type CwtchPeerInstance struct {
rai *application.ApplicationInstance
ra *application.RicochetApplication
@@ -121,7 +126,6 @@ func (cpi *CwtchPeerInstance) Init(rai *application.ApplicationInstance, ra *app
cpi.ra = ra
}


type CwtchPeerHandler struct {
Onion string
Peer *CwtchPeer

+ 21
- 0
peer/cwtch_peer_server_intergration_test.go ファイルの表示

@@ -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)
}

+ 1
- 0
peer/send/peer_send_channel.go ファイルの表示

@@ -81,6 +81,7 @@ func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) {
}
packet, _ := proto.Marshal(csp)
cplc.channel.SendMessage(packet)
cplc.channel.CloseChannel()
}

// Packet should never be

+ 325
- 0
protocol/ControlChannel.pb.go ファイルの表示

@@ -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,
}

+ 53
- 0
protocol/ControlChannel.proto ファイルの表示

@@ -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;
}

+ 13
- 0
server/app/main.go ファイルの表示

@@ -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")
}

+ 1
- 0
server/server.go ファイルの表示

@@ -64,5 +64,6 @@ func (s *Server) Run(privateKeyFile string) {
})

cwtchserver.Init(pk, af, new(application.AcceptAllContactManager))
log.Printf("cwtch server running on cwtch:%s", l.Addr().String()[0:16])
cwtchserver.Run(l)
}

+ 6
- 0
server/server_instance_test.go ファイルの表示

@@ -6,6 +6,7 @@ import (
"github.com/s-rah/go-ricochet/application"
"os"
"testing"
"time"
)

func TestServerInstance(t *testing.T) {
@@ -27,4 +28,9 @@ func TestServerInstance(t *testing.T) {
if len(res) != 1 {
t.Errorf("Expected Group Messages Instead got %v", res)
}

// ra.HandleApplicationInstance(ai)
si.HandleGroupMessage(&gm)

time.Sleep(time.Second * 2)
}

読み込み中…
キャンセル
保存