cwtch/peer/connections/peerserverconnection.go

141 lines
4.0 KiB
Go
Raw Normal View History

package connections
import (
2018-10-05 03:18:34 +00:00
"crypto/rand"
2018-05-28 18:05:06 +00:00
"cwtch.im/cwtch/peer/fetch"
"cwtch.im/cwtch/peer/listen"
"cwtch.im/cwtch/peer/send"
"cwtch.im/cwtch/protocol"
2018-03-30 21:16:51 +00:00
"errors"
2018-06-23 16:15:36 +00:00
"git.openprivacy.ca/openprivacy/libricochet-go"
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
2018-06-23 16:15:36 +00:00
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
2018-12-04 02:52:11 +00:00
"git.openprivacy.ca/openprivacy/libricochet-go/log"
2018-10-05 03:18:34 +00:00
"golang.org/x/crypto/ed25519"
"time"
)
// PeerServerConnection encapsulates a single Peer->Server connection
type PeerServerConnection struct {
connection.AutoConnectionHandler
Server string
state ConnectionState
2018-05-20 18:29:46 +00:00
connection *connection.Connection
2018-11-22 18:01:04 +00:00
acn connectivity.ACN
2018-03-10 22:05:48 +00:00
GroupMessageHandler func(string, *protocol.GroupMessage)
}
// NewPeerServerConnection creates a new Peer->Server outbound connection
2018-11-22 18:01:04 +00:00
func NewPeerServerConnection(acn connectivity.ACN, serverhostname string) *PeerServerConnection {
psc := new(PeerServerConnection)
2018-11-22 18:01:04 +00:00
psc.acn = acn
psc.Server = serverhostname
psc.Init()
return psc
}
// GetState returns the current connection state
func (psc *PeerServerConnection) GetState() ConnectionState {
return psc.state
}
// WaitTilAuthenticated waits until the underlying connection is authenticated
func (psc *PeerServerConnection) WaitTilAuthenticated() {
for {
if psc.GetState() == AUTHENTICATED {
break
}
time.Sleep(time.Second * 1)
}
}
// Run manages the setup and teardown of a peer server connection
func (psc *PeerServerConnection) Run() error {
2018-12-04 02:52:11 +00:00
log.Infof("Connecting to %v", psc.Server)
2018-11-22 18:01:04 +00:00
rc, err := goricochet.Open(psc.acn, psc.Server)
if err == nil {
2018-05-20 18:29:46 +00:00
psc.connection = rc
psc.state = CONNECTED
2018-11-24 01:58:45 +00:00
pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err == nil {
2018-10-05 03:18:34 +00:00
_, err := connection.HandleOutboundConnection(psc.connection).ProcessAuthAsV3Client(identity.InitializeV3("cwtchpeer", &priv, &pub))
if err == nil {
psc.state = AUTHENTICATED
2018-03-10 22:05:48 +00:00
go func() {
psc.connection.Do(func() error {
psc.connection.RequestOpenChannel("im.cwtch.server.fetch", &fetch.CwtchPeerFetchChannel{Handler: psc})
return nil
})
psc.connection.Do(func() error {
psc.connection.RequestOpenChannel("im.cwtch.server.listen", &listen.CwtchPeerListenChannel{Handler: psc})
return nil
})
2018-03-10 22:05:48 +00:00
}()
psc.connection.Process(psc)
}
}
}
psc.state = FAILED
return err
}
// Break makes Run() return and prevents processing, but doesn't close the connection.
func (psc *PeerServerConnection) Break() error {
return psc.connection.Break()
}
// SendGroupMessage sends the given protocol message to the Server.
func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) error {
if psc.state != AUTHENTICATED {
return errors.New("peer is not yet connected & authenticated to server cannot send message")
2018-03-30 21:16:51 +00:00
}
err := psc.connection.Do(func() error {
2018-03-10 22:05:48 +00:00
psc.connection.RequestOpenChannel("im.cwtch.server.send", &send.CwtchPeerSendChannel{})
return nil
})
errCount := 0
for errCount < 5 {
time.Sleep(time.Second * 1)
err = psc.connection.Do(func() error {
channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound)
if channel == nil {
return errors.New("no channel found")
}
sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel)
if ok {
return sendchannel.SendGroupMessage(gm)
}
return errors.New("channel is not a peer send channel (this should definitely not happen)")
})
if err != nil {
errCount++
2018-03-30 21:16:51 +00:00
} else {
return nil
2018-03-10 22:05:48 +00:00
}
2018-03-30 21:16:51 +00:00
}
return err
}
// Close shuts down the connection (freeing the handler goroutines)
func (psc *PeerServerConnection) Close() {
psc.state = KILLED
2018-10-06 03:50:55 +00:00
if psc.connection != nil {
psc.connection.Conn.Close()
}
}
// HandleGroupMessage passes the given group message back to the profile.
2018-03-10 22:05:48 +00:00
func (psc *PeerServerConnection) HandleGroupMessage(gm *protocol.GroupMessage) {
2018-12-04 02:52:11 +00:00
log.Debugf("Received Group Message")
2018-03-10 22:05:48 +00:00
psc.GroupMessageHandler(psc.Server, gm)
}