libs5-go/protocol/signed_handshake_done.go

166 lines
3.2 KiB
Go

package protocol
import (
"bytes"
"errors"
"fmt"
"git.lumeweb.com/LumeWeb/libs5-go/types"
"git.lumeweb.com/LumeWeb/libs5-go/utils"
"github.com/vmihailenco/msgpack/v5"
"net/url"
)
var _ IncomingMessageSigned = (*HandshakeDone)(nil)
var _ EncodeableMessage = (*HandshakeDone)(nil)
type HandshakeDone struct {
challenge []byte
networkId string
supportedFeatures int
connectionUris []*url.URL
handshake []byte
HandshakeRequirement
}
func NewHandshakeDoneRequest(handshake []byte, supportedFeatures int, connectionUris []*url.URL) *HandshakeDone {
ho := &HandshakeDone{
handshake: handshake,
supportedFeatures: supportedFeatures,
connectionUris: connectionUris,
}
ho.SetRequiresHandshake(false)
return ho
}
func (m HandshakeDone) EncodeMsgpack(enc *msgpack.Encoder) error {
err := enc.EncodeUint(uint64(types.ProtocolMethodHandshakeDone))
if err != nil {
return err
}
err = enc.EncodeBytes(m.handshake)
if err != nil {
return err
}
err = enc.EncodeInt(int64(m.supportedFeatures))
if err != nil {
return err
}
err = utils.EncodeMsgpackArray(enc, m.connectionUris)
if err != nil {
return err
}
return nil
}
func (m *HandshakeDone) SetChallenge(challenge []byte) {
m.challenge = challenge
}
func (m *HandshakeDone) SetNetworkId(networkId string) {
m.networkId = networkId
}
func NewHandshakeDone() *HandshakeDone {
hn := &HandshakeDone{challenge: nil, networkId: "", supportedFeatures: -1}
hn.SetRequiresHandshake(false)
return hn
}
func (h HandshakeDone) HandleMessage(message IncomingMessageDataSigned) error {
mediator := message.Mediator
peer := message.Peer
verifyId := message.VerifyId
nodeId := message.NodeId
logger := message.Logger
if !mediator.ServicesStarted() {
err := peer.End()
if err != nil {
return nil
}
return nil
}
if !bytes.Equal(peer.Challenge(), h.challenge) {
return errors.New("Invalid challenge")
}
if !verifyId {
peer.SetId(nodeId)
} else {
if !peer.Id().Equals(nodeId) {
return fmt.Errorf("Invalid transports id on initial list")
}
}
peer.SetConnected(true)
peer.SetHandshakeDone(true)
if h.supportedFeatures != types.SupportedFeatures {
return fmt.Errorf("Remote node does not support required features")
}
err := mediator.AddPeer(peer)
if err != nil {
return err
}
if len(h.connectionUris) == 0 {
return nil
}
peerId, err := peer.Id().ToString()
if err != nil {
return err
}
for _, uri := range h.connectionUris {
uri.User = url.User(peerId)
}
peer.SetConnectionURIs(h.connectionUris)
logger.Info(fmt.Sprintf("[+] %s (%s)", peerId, peer.RenderLocationURI()))
err = mediator.ConnectToNode([]*url.URL{h.connectionUris[0]}, false, peer)
if err != nil {
return err
}
return nil
}
func (h *HandshakeDone) DecodeMessage(dec *msgpack.Decoder, message IncomingMessageDataSigned) error {
challenge, err := dec.DecodeBytes()
if err != nil {
return err
}
h.challenge = challenge
supportedFeatures, err := dec.DecodeInt()
if err != nil {
return err
}
h.supportedFeatures = supportedFeatures
connectionUris, err := utils.DecodeMsgpackURLArray(dec)
if err != nil {
return err
}
h.connectionUris = connectionUris
return nil
}