forked from cwtch.im/cwtch
Adding peer channels, renaming client->peer
This commit is contained in:
parent
fbf42b3a79
commit
335a8d76c3
|
@ -1,4 +1,4 @@
|
||||||
package client
|
package peer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
|
@ -0,0 +1,42 @@
|
||||||
|
package connections
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"git.mascherari.press/cwtch/peer/peer"
|
||||||
|
//"git.mascherari.press/cwtch/protocol"
|
||||||
|
"github.com/s-rah/go-ricochet"
|
||||||
|
//"github.com/s-rah/go-ricochet/channels"
|
||||||
|
"github.com/s-rah/go-ricochet/connection"
|
||||||
|
//"github.com/s-rah/go-ricochet/identity"
|
||||||
|
//"github.com/s-rah/go-ricochet/utils"
|
||||||
|
//"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeerPeerConnection struct {
|
||||||
|
connection.AutoConnectionHandler
|
||||||
|
PeerHostname string
|
||||||
|
state ConnectionState
|
||||||
|
connection connection.Connection
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPeerPeerConnection(peerhostname string) *PeerPeerConnection {
|
||||||
|
ppc := new(PeerPeerConnection)
|
||||||
|
ppc.PeerHostname = peerhostname
|
||||||
|
ppc.Init()
|
||||||
|
return ppc
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetState returns the current connection state
|
||||||
|
func (ppc *PeerPeerConnection) GetState() ConnectionState {
|
||||||
|
return ppc.state
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run manages the setup and teardown of a peer->peer connection
|
||||||
|
func (ppc *PeerPeerConnection) Run() error {
|
||||||
|
rc, err := goricochet.Open(ppc.PeerHostname)
|
||||||
|
if err == nil {
|
||||||
|
rc.TraceLog(true)
|
||||||
|
ppc.connection = *rc
|
||||||
|
ppc.state = CONNECTED
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package connections
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
|
"github.com/s-rah/go-ricochet"
|
||||||
|
"github.com/s-rah/go-ricochet/connection"
|
||||||
|
"github.com/s-rah/go-ricochet/identity"
|
||||||
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PeerAuthValid(hostname string, publicKey rsa.PublicKey) (allowed, known bool) {
|
||||||
|
return true, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtestserver(t *testing.T) {
|
||||||
|
ln, _ := net.Listen("tcp", "127.0.0.1:5452")
|
||||||
|
conn, _ := ln.Accept()
|
||||||
|
defer conn.Close()
|
||||||
|
privateKey, err := utils.LoadPrivateKeyFromFile("../../testing/private_key")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Private Key Error %v", err)
|
||||||
|
}
|
||||||
|
rc, err := goricochet.NegotiateVersionInbound(conn)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Negotiate Version Error: %v", err)
|
||||||
|
}
|
||||||
|
rc.TraceLog(true)
|
||||||
|
err = connection.HandleInboundConnection(rc).ProcessAuthAsServer(identity.Initialize("", privateKey), PeerAuthValid)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ServerAuth Error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerPeerConnection(t *testing.T) {
|
||||||
|
ppc := NewPeerPeerConnection("127.0.0.1:5452|kwke2hntvyfqm7dr")
|
||||||
|
//numcalls := 0
|
||||||
|
go runtestserver(t)
|
||||||
|
state := ppc.GetState()
|
||||||
|
if state != DISCONNECTED {
|
||||||
|
t.Errorf("new connections should start in disconnected state")
|
||||||
|
}
|
||||||
|
go ppc.Run()
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
|
state = ppc.GetState()
|
||||||
|
if state != CONNECTED {
|
||||||
|
t.Errorf("connection state should be connected, was instead %v", state)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package connections
|
package connections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.mascherari.press/cwtch/client/fetch"
|
"git.mascherari.press/cwtch/peer/fetch"
|
||||||
"git.mascherari.press/cwtch/client/send"
|
"git.mascherari.press/cwtch/peer/send"
|
||||||
"git.mascherari.press/cwtch/protocol"
|
"git.mascherari.press/cwtch/protocol"
|
||||||
"github.com/s-rah/go-ricochet"
|
"github.com/s-rah/go-ricochet"
|
||||||
"github.com/s-rah/go-ricochet/channels"
|
"github.com/s-rah/go-ricochet/channels"
|
|
@ -1,4 +1,4 @@
|
||||||
package client
|
package peer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -14,10 +14,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
ServerConnectionPool
|
|
||||||
background thread running Process()
|
|
||||||
pointer to connection
|
|
||||||
Probably worthwhile defining a type called PeerServerConnection to manage background() and other commmands!
|
|
||||||
|
|
||||||
PeerConnectionPool
|
PeerConnectionPool
|
||||||
Background thread running Process()
|
Background thread running Process()
|
|
@ -1,4 +1,4 @@
|
||||||
package client
|
package peer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -0,0 +1,104 @@
|
||||||
|
package peer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.mascherari.press/cwtch/protocol"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/s-rah/go-ricochet/channels"
|
||||||
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
|
"github.com/s-rah/go-ricochet/wire/control"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CwtchPeerChannel implements the ChannelHandler interface for a channel of
|
||||||
|
// type "im.ricochet.Cwtch". The channel may be inbound or outbound.
|
||||||
|
//
|
||||||
|
// CwtchPeerChannel implements protocol-level sanity and state validation, but
|
||||||
|
// does not handle or acknowledge Cwtch messages. The application must provide
|
||||||
|
// a CwtchPeerChannelHandler implementation to handle Cwtch events.
|
||||||
|
type CwtchPeerChannel struct {
|
||||||
|
// Methods of Handler are called for Cwtch events on this channel
|
||||||
|
Handler CwtchPeerChannelHandler
|
||||||
|
channel *channels.Channel
|
||||||
|
}
|
||||||
|
|
||||||
|
// CwtchPeerChannelHandler is implemented by an application type to receive
|
||||||
|
// events from a CwtchPeerChannel.
|
||||||
|
type CwtchPeerChannelHandler interface {
|
||||||
|
ClientIdentity(*protocol.CwtchIdentity)
|
||||||
|
HandleGroupInvite()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the type string for this channel, e.g. "im.ricochet.Cwtch".
|
||||||
|
func (cpc *CwtchPeerChannel) SendMessage(data []byte) {
|
||||||
|
cpc.channel.SendMessage(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the type string for this channel, e.g. "im.ricochet.Cwtch".
|
||||||
|
func (cpc *CwtchPeerChannel) Type() string {
|
||||||
|
return "im.cwtch.peer"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closed is called when the channel is closed for any reason.
|
||||||
|
func (cpc *CwtchPeerChannel) Closed(err error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlyClientCanOpen - for Cwtch channels any side can open
|
||||||
|
func (cpc *CwtchPeerChannel) OnlyClientCanOpen() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Singleton - for Cwtch channels there can only be one instance per direction
|
||||||
|
func (cpc *CwtchPeerChannel) Singleton() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bidirectional - for Cwtch channels are not bidrectional
|
||||||
|
func (cpc *CwtchPeerChannel) Bidirectional() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequiresAuthentication - Cwtch channels require hidden service auth
|
||||||
|
func (cpc *CwtchPeerChannel) RequiresAuthentication() string {
|
||||||
|
return "im.ricochet.auth.hidden-service"
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenInbound is the first method called for an inbound channel request.
|
||||||
|
// If an error is returned, the channel is rejected. If a RawMessage is
|
||||||
|
// returned, it will be sent as the ChannelResult message.
|
||||||
|
func (cpc *CwtchPeerChannel) OpenInbound(channel *channels.Channel, raw *Protocol_Data_Control.OpenChannel) ([]byte, error) {
|
||||||
|
cpc.channel = channel
|
||||||
|
messageBuilder := new(utils.MessageBuilder)
|
||||||
|
return messageBuilder.AckOpenChannel(channel.ID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenOutbound is the first method called for an outbound channel request.
|
||||||
|
// If an error is returned, the channel is not opened. If a RawMessage is
|
||||||
|
// returned, it will be sent as the OpenChannel message.
|
||||||
|
func (cpc *CwtchPeerChannel) OpenOutbound(channel *channels.Channel) ([]byte, error) {
|
||||||
|
cpc.channel = channel
|
||||||
|
messageBuilder := new(utils.MessageBuilder)
|
||||||
|
return messageBuilder.OpenChannel(channel.ID, cpc.Type()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenOutboundResult is called when a response is received for an
|
||||||
|
// outbound OpenChannel request. If `err` is non-nil, the channel was
|
||||||
|
// rejected and Closed will be called immediately afterwards. `raw`
|
||||||
|
// contains the raw protocol message including any extension data.
|
||||||
|
func (cpc *CwtchPeerChannel) OpenOutboundResult(err error, crm *Protocol_Data_Control.ChannelResult) {
|
||||||
|
if err == nil {
|
||||||
|
if crm.GetOpened() {
|
||||||
|
cpc.channel.Pending = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Packet is called for each raw packet received on this channel.
|
||||||
|
func (cpc *CwtchPeerChannel) Packet(data []byte) {
|
||||||
|
cpp := &protocol.CwtchPeerPacket{}
|
||||||
|
err := proto.Unmarshal(data, cpp)
|
||||||
|
if err == nil {
|
||||||
|
if cpp.GetCwtchIdentify() != nil {
|
||||||
|
cpc.Handler.ClientIdentity(cpp.GetCwtchIdentify())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package peer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.mascherari.press/cwtch/protocol"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/s-rah/go-ricochet/channels"
|
||||||
|
"github.com/s-rah/go-ricochet/wire/control"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPeerChannelAttributes(t *testing.T) {
|
||||||
|
cssc := new(CwtchPeerChannel)
|
||||||
|
if cssc.Type() != "im.cwtch.peer" {
|
||||||
|
t.Errorf("cwtch channel type is incorrect %v", cssc.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
if cssc.OnlyClientCanOpen() {
|
||||||
|
t.Errorf("either side should be able to open im.cwtch.peer channel")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cssc.Bidirectional() {
|
||||||
|
t.Errorf("im.cwtch.peer should not be bidirectional")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cssc.Singleton() {
|
||||||
|
t.Errorf("im.cwtch.server.listen should be a Singleton")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cssc.RequiresAuthentication() != "im.ricochet.auth.hidden-service" {
|
||||||
|
t.Errorf("cwtch channel required auth is incorrect %v", cssc.RequiresAuthentication())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestHandler struct {
|
||||||
|
Received bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (th *TestHandler) ClientIdentity(ci *protocol.CwtchIdentity) {
|
||||||
|
if ci.GetName() == "hello" {
|
||||||
|
th.Received = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (th *TestHandler) HandleGroupInvite() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerChannel(t *testing.T) {
|
||||||
|
th := new(TestHandler)
|
||||||
|
cpc := new(CwtchPeerChannel)
|
||||||
|
cpc.Handler = th
|
||||||
|
channel := new(channels.Channel)
|
||||||
|
channel.ID = 3
|
||||||
|
result, err := cpc.OpenOutbound(channel)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("should have send open channel request instead %v, %v", result, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cpc2 := new(CwtchPeerChannel)
|
||||||
|
channel2 := new(channels.Channel)
|
||||||
|
channel2.ID = 3
|
||||||
|
sent := false
|
||||||
|
channel2.SendMessage = func(message []byte) {
|
||||||
|
sent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
control := new(Protocol_Data_Control.Packet)
|
||||||
|
proto.Unmarshal(result[:], control)
|
||||||
|
ack, err := cpc2.OpenInbound(channel2, control.GetOpenChannel())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("should have ack open channel request instead %v, %v", ack, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ackpacket := new(Protocol_Data_Control.Packet)
|
||||||
|
proto.Unmarshal(ack[:], ackpacket)
|
||||||
|
cpc.OpenOutboundResult(nil, ackpacket.GetChannelResult())
|
||||||
|
if channel.Pending != false {
|
||||||
|
t.Errorf("Channel should no longer be pending")
|
||||||
|
}
|
||||||
|
|
||||||
|
gm := &protocol.CwtchIdentity{
|
||||||
|
Name: "hello",
|
||||||
|
Ed25519PublicKey: []byte{},
|
||||||
|
}
|
||||||
|
|
||||||
|
cpp := &protocol.CwtchPeerPacket{
|
||||||
|
CwtchIdentify: gm,
|
||||||
|
}
|
||||||
|
packet, _ := proto.Marshal(cpp)
|
||||||
|
cpc.Packet(packet)
|
||||||
|
if th.Received == false {
|
||||||
|
t.Errorf("Should have sent packet to handler")
|
||||||
|
}
|
||||||
|
|
||||||
|
cpc2.SendMessage(packet)
|
||||||
|
if sent == false {
|
||||||
|
t.Errorf("Should have sent packet to channel")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue