forked from cwtch.im/cwtch
PeerServerConnection Definition and Tests
This commit is contained in:
parent
487ce6d2da
commit
5f94e82347
|
@ -0,0 +1 @@
|
||||||
|
*.out
|
|
@ -0,0 +1,79 @@
|
||||||
|
package connections
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/s-rah/go-ricochet"
|
||||||
|
"github.com/s-rah/go-ricochet/connection"
|
||||||
|
"github.com/s-rah/go-ricochet/channels"
|
||||||
|
"github.com/s-rah/go-ricochet/identity"
|
||||||
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
|
"git.mascherari.press/cwtch/client/send"
|
||||||
|
"git.mascherari.press/cwtch/protocol"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeerServerConnection struct {
|
||||||
|
connection.AutoConnectionHandler
|
||||||
|
Server string
|
||||||
|
state ConnectionState
|
||||||
|
connection connection.Connection
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPeerServerConnection(serverhostname string) *PeerServerConnection {
|
||||||
|
psc := new(PeerServerConnection)
|
||||||
|
psc.Server = serverhostname
|
||||||
|
psc.Init()
|
||||||
|
return psc
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetState returns the current connection state
|
||||||
|
func (psc *PeerServerConnection) GetState() ConnectionState {
|
||||||
|
return psc.state
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run manages the setup and teardown of a peer server connection
|
||||||
|
func (psc *PeerServerConnection) Run() error {
|
||||||
|
rc, err := goricochet.Open(psc.Server)
|
||||||
|
if err == nil {
|
||||||
|
psc.connection = *rc
|
||||||
|
psc.state = CONNECTED
|
||||||
|
pk, err := utils.GeneratePrivateKey()
|
||||||
|
if err == nil {
|
||||||
|
_, err := connection.HandleOutboundConnection(&psc.connection).ProcessAuthAsClient(identity.Initialize("cwtchpeer", pk))
|
||||||
|
if err == nil {
|
||||||
|
psc.state = AUTHENTICATED
|
||||||
|
psc.connection.Process(psc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Break makes Run() return and prevents processing, but doesn't close the connection.
|
||||||
|
func (psc *PeerServerConnection) Break() error {
|
||||||
|
return psc.connection.Break()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) {
|
||||||
|
psc.connection.Do(func() error {
|
||||||
|
psc.connection.RequestOpenChannel("im.cwtch.server.send", &send.CwtchPeerSendChannel{})
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
// 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 {
|
||||||
|
channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound)
|
||||||
|
if channel != nil {
|
||||||
|
sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel)
|
||||||
|
if ok {
|
||||||
|
sendchannel.SendGroupMessage(gm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psc *PeerServerConnection) HandleGroupMessage(*protocol.GroupMessage) {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
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"
|
||||||
|
"github.com/s-rah/go-ricochet/channels"
|
||||||
|
"git.mascherari.press/cwtch/server/send"
|
||||||
|
"git.mascherari.press/cwtch/protocol"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ServerAuthValid(hostname string, publicKey rsa.PublicKey) (allowed, known bool) {
|
||||||
|
return true, true
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestServer struct {
|
||||||
|
connection.AutoConnectionHandler
|
||||||
|
Received bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *TestServer) HandleGroupMessage(gm *protocol.GroupMessage) {
|
||||||
|
ts.Received = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtestserver(t *testing.T, ts *TestServer) {
|
||||||
|
ln, _ := net.Listen("tcp", "127.0.0.1:5451")
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
err = connection.HandleInboundConnection(rc).ProcessAuthAsServer(identity.Initialize("", privateKey), ServerAuthValid)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ServerAuth Error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ts.RegisterChannelHandler("im.cwtch.server.send", func() channels.Handler {
|
||||||
|
server := new(send.CwtchServerSendChannel)
|
||||||
|
server.Handler = ts
|
||||||
|
return server
|
||||||
|
})
|
||||||
|
|
||||||
|
rc.Process(ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerServerConnection(t *testing.T) {
|
||||||
|
ts := new(TestServer)
|
||||||
|
ts.Init()
|
||||||
|
go runtestserver(t, ts)
|
||||||
|
psc := NewPeerServerConnection("127.0.0.1:5451|kwke2hntvyfqm7dr")
|
||||||
|
state := psc.GetState()
|
||||||
|
if state != DISCONNECTED {
|
||||||
|
t.Errorf("new connections should start in disconnected state")
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
|
go psc.Run()
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
state = psc.GetState()
|
||||||
|
if state != AUTHENTICATED {
|
||||||
|
t.Errorf("connection should now be authed(%v), instead was %v", AUTHENTICATED, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
gm := &protocol.GroupMessage{Ciphertext: []byte("hello")}
|
||||||
|
psc.SendGroupMessage(gm)
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
if ts.Received == false {
|
||||||
|
t.Errorf("Should have received a group message in test server")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package connections
|
||||||
|
|
||||||
|
type ConnectionState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DISCONNECTED ConnectionState = iota
|
||||||
|
CONNECTING
|
||||||
|
CONNECTED
|
||||||
|
AUTHENTICATED
|
||||||
|
)
|
|
@ -13,6 +13,20 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
ServerConnectionPool
|
||||||
|
background thread running Process()
|
||||||
|
pointer to connection
|
||||||
|
Probably worthwhile defining a type called PeerServerConnection to manage background() and other commmands!
|
||||||
|
|
||||||
|
PeerConnectionPool
|
||||||
|
Background thread running Process()
|
||||||
|
Pointer to connections
|
||||||
|
|
||||||
|
Move CwtchPeerChannel under peer/
|
||||||
|
Write tests for Peer Channel
|
||||||
|
*/
|
||||||
|
|
||||||
type CwtchPeerInstance struct {
|
type CwtchPeerInstance struct {
|
||||||
rai *application.ApplicationInstance
|
rai *application.ApplicationInstance
|
||||||
ra *application.RicochetApplication
|
ra *application.RicochetApplication
|
||||||
|
@ -173,3 +187,6 @@ func (cph *CwtchPeerHandler) ClientIdentity(ci *protocol.CwtchIdentity) {
|
||||||
|
|
||||||
func (cph *CwtchPeerHandler) HandleGroupInvite() {
|
func (cph *CwtchPeerHandler) HandleGroupInvite() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cph *CwtchPeerHandler) HandleGroupMessage(gm *protocol.GroupMessage) {
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package listen
|
package send
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -67,6 +67,7 @@ func (cplc *CwtchPeerSendChannel) OpenOutboundResult(err error, crm *Protocol_Da
|
||||||
cplc.channel.Pending = false
|
cplc.channel.Pending = false
|
||||||
ce, _ := proto.GetExtension(crm, protocol.E_ServerNonce)
|
ce, _ := proto.GetExtension(crm, protocol.E_ServerNonce)
|
||||||
cplc.challenge = ce.([]byte)[:]
|
cplc.challenge = ce.([]byte)[:]
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +75,7 @@ func (cplc *CwtchPeerSendChannel) OpenOutboundResult(err error, crm *Protocol_Da
|
||||||
// SendGroupMessage performs the spamguard proof of work and sends a message.
|
// SendGroupMessage performs the spamguard proof of work and sends a message.
|
||||||
func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) {
|
func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) {
|
||||||
sgsolve := cplc.spamGuard.SolveChallenge(cplc.challenge, gm.GetCiphertext())
|
sgsolve := cplc.spamGuard.SolveChallenge(cplc.challenge, gm.GetCiphertext())
|
||||||
gm.Spamguard = sgsolve
|
gm.Spamguard = sgsolve[:]
|
||||||
csp := &protocol.CwtchServerPacket{
|
csp := &protocol.CwtchServerPacket{
|
||||||
GroupMessage: gm,
|
GroupMessage: gm,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package listen
|
package send
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.mascherari.press/cwtch/protocol"
|
"git.mascherari.press/cwtch/protocol"
|
||||||
|
@ -9,14 +9,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestHandler struct {
|
|
||||||
Received bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (th *TestHandler) HandleGroupMessage(m *protocol.GroupMessage) {
|
|
||||||
th.Received = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPeerSendChannelAttributes(t *testing.T) {
|
func TestPeerSendChannelAttributes(t *testing.T) {
|
||||||
cssc := new(CwtchPeerSendChannel)
|
cssc := new(CwtchPeerSendChannel)
|
||||||
if cssc.Type() != "im.cwtch.server.send" {
|
if cssc.Type() != "im.cwtch.server.send" {
|
||||||
|
|
|
@ -15,7 +15,6 @@ type SpamGuard struct {
|
||||||
nonce [24]byte
|
nonce [24]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//GenerateChallenge returns a channel result packet with a spamguard challenge nonce
|
//GenerateChallenge returns a channel result packet with a spamguard challenge nonce
|
||||||
func (sg *SpamGuard) GenerateChallenge(channelID int32) []byte {
|
func (sg *SpamGuard) GenerateChallenge(channelID int32) []byte {
|
||||||
|
|
||||||
|
@ -75,8 +74,8 @@ func (sg *SpamGuard) SolveChallenge(challenge []byte, message []byte) []byte {
|
||||||
// ValidateChallenge returns true if the message and spamguard pass the challenge
|
// ValidateChallenge returns true if the message and spamguard pass the challenge
|
||||||
func (sg *SpamGuard) ValidateChallenge(message []byte, spamguard []byte) bool {
|
func (sg *SpamGuard) ValidateChallenge(message []byte, spamguard []byte) bool {
|
||||||
if len(spamguard) != 24 {
|
if len(spamguard) != 24 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
solve := make([]byte, len(sg.nonce)+len(message)+len(spamguard))
|
solve := make([]byte, len(sg.nonce)+len(message)+len(spamguard))
|
||||||
copy(solve[0:], sg.nonce[:])
|
copy(solve[0:], sg.nonce[:])
|
||||||
copy(solve[len(sg.nonce):], message[:])
|
copy(solve[len(sg.nonce):], message[:])
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICXgIBAAKBgQC3xEJBH4oVFaotPJw6dezx67Gv4Xukw8CZRGqNFO8yF7Rejtcj
|
||||||
|
/0RTqqZwj6H6FjxY60dgYnN6IphW0juemNZhxOXeM/5Gb5xO+kWGi5Qt87aSDxnA
|
||||||
|
MDLgqw79ihuD3m1C1TBz0olmjXPU1VtadZuZcVBST7SLs2/k55GNNr7BoQIDAQAB
|
||||||
|
AoGBAK3ybVCdnSQWLM7DJ5LC23Wnx7sXceVlkiLCOyWuYjiFbatwBD/DupaD2yaD
|
||||||
|
HyzN7XOxyg93QZ2jr5XHTL30KEAn/3akNBsX3sjHZnjVfTwD5+oZKd7HYMMxekWf
|
||||||
|
87TIx2IHvGEo2NaFMLkEZ5TX3Gre8CYOofjFcpj4661ZfYp9AkEA9I0EmQX26ibs
|
||||||
|
CRGkwPuEj5q5N/PmIHgMWr1pepOlmzJjnxy6SI3NUwmzKrqM6YUM8loSywqfVMrJ
|
||||||
|
RVzA5jp76wJBAMBeu2hS8KcUTIu66j0pXMhI5wDA3yLiO53TEMwufCPXcaWUMH+e
|
||||||
|
5AIPL7aZ8ouf895OH0TZKxPNMnbrJ+5F0aMCQDoi/CDUxipMLnjJdP1bzdvF0Jp4
|
||||||
|
pRC6+VTpCpZVW11V0VEWJ0LwUwuWlr1ls/If60ACIc2bLN2fh9Gxhzo0VRkCQQCS
|
||||||
|
nKCAVhYLgLEGHaLAknGgQ8+rB1QIphuBoYc/1n3OYzi+VT7RRSvJVgGrTZFJUNLw
|
||||||
|
LuIt+sWWBeHcOETqmFO5AkEAwwfcxs8QZtX6hCj2MTPi8Q28LIoA/M6eAqYc2I0B
|
||||||
|
eXxf2J2Qco7sMmBLr1Jp3jZNd5W2fMtlhUZAomOj4piVOA==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
Loading…
Reference in New Issue