Handle messages in raw method as well
This commit is contained in:
parent
0a8bf4c10e
commit
28b2244fed
171
adapters.go
171
adapters.go
|
@ -22,8 +22,6 @@ import (
|
|||
|
||||
"github.com/status-im/status-protocol-go/datasync"
|
||||
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
|
||||
datasyncproto "github.com/vacp2p/mvds/protobuf"
|
||||
datasynctransport "github.com/vacp2p/mvds/transport"
|
||||
)
|
||||
|
||||
// Whisper message properties.
|
||||
|
@ -149,28 +147,22 @@ func (a *whisperAdapter) handleRetrievedMessages(messages []*whisper.ReceivedMes
|
|||
shhMessage := whisper.ToWhisperMessage(item)
|
||||
|
||||
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
|
||||
|
||||
hlogger.Debug("handling a received message")
|
||||
|
||||
err := a.handleMessageEncryption(context.Background(), shhMessage)
|
||||
if err != nil {
|
||||
hlogger.Debug("failed to handle an encryption message", zap.Error(err))
|
||||
}
|
||||
|
||||
statusMessages, err := a.handleDecodedMessages(shhMessage)
|
||||
statusMessages, err := a.handleMessages(shhMessage, true)
|
||||
if err != nil {
|
||||
hlogger.Info("failed to decode messages", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, statusMessage := range statusMessages {
|
||||
switch m := statusMessage.Message.(type) {
|
||||
switch m := statusMessage.ParsedMessage.(type) {
|
||||
case protocol.Message:
|
||||
m.ID = statusMessage.ID
|
||||
m.SigPubKey = statusMessage.SigPubKey
|
||||
m.SigPubKey = statusMessage.SigPubKey()
|
||||
decodedMessages = append(decodedMessages, &m)
|
||||
case protocol.PairMessage:
|
||||
fromOurDevice := isPubKeyEqual(statusMessage.SigPubKey, &a.privateKey.PublicKey)
|
||||
fromOurDevice := isPubKeyEqual(statusMessage.SigPubKey(), &a.privateKey.PublicKey)
|
||||
if !fromOurDevice {
|
||||
hlogger.Debug("received PairMessage from not our device, skipping")
|
||||
break
|
||||
|
@ -194,136 +186,81 @@ func (a *whisperAdapter) handleRetrievedMessages(messages []*whisper.ReceivedMes
|
|||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *whisperAdapter) RetrieveRawAll() (map[filter.Chat][]*whisper.Message, error) {
|
||||
func (a *whisperAdapter) RetrieveRawAll() (map[filter.Chat][]*protocol.StatusMessage, error) {
|
||||
chatWithMessages, err := a.transport.RetrieveRawAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger := a.logger.With(zap.String("site", "RetrieveRawAll"))
|
||||
result := make(map[filter.Chat][]*whisper.Message)
|
||||
result := make(map[filter.Chat][]*protocol.StatusMessage)
|
||||
|
||||
for chat, messages := range chatWithMessages {
|
||||
for _, message := range messages {
|
||||
shhMessage := whisper.ToWhisperMessage(message)
|
||||
err := a.handleMessageEncryption(context.Background(), shhMessage)
|
||||
statusMessages, err := a.handleMessages(shhMessage, false)
|
||||
if err != nil {
|
||||
logger.Warn("failed to handle an encryption message", zap.Error(err), zap.Binary("messageID", shhMessage.Hash))
|
||||
}
|
||||
result[chat] = append(result[chat], shhMessage)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *whisperAdapter) RetrieveRaw(filterID string) ([]*whisper.Message, error) {
|
||||
messages, err := a.transport.RetrieveRaw(filterID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger := a.logger.With(zap.String("site", "RetrieveRaw"))
|
||||
|
||||
var result []*whisper.Message
|
||||
|
||||
for _, message := range messages {
|
||||
shhMessage := whisper.ToWhisperMessage(message)
|
||||
err := a.handleMessageEncryption(context.Background(), shhMessage)
|
||||
if err != nil {
|
||||
logger.Warn("failed to handle an encryption message", zap.Error(err), zap.Binary("messageID", shhMessage.Hash))
|
||||
}
|
||||
result = append(result, shhMessage)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *whisperAdapter) addDatasyncPacket(publicKey *ecdsa.PublicKey, datasyncMessage datasyncproto.Payload) {
|
||||
packet := datasynctransport.Packet{
|
||||
Sender: datasyncpeer.PublicKeyToPeerID(*publicKey),
|
||||
Payload: datasyncMessage,
|
||||
}
|
||||
a.datasync.AddPacket(packet)
|
||||
}
|
||||
|
||||
// handleDecodedMessages expects an unencrypted whisper message as it's argument.
|
||||
// 1) Check if it's a datasync message
|
||||
// 2) If it's a datasync message it will handle each transmitted message separately
|
||||
// 3) if it's not a datasync message a single message will be handled
|
||||
// Fingerprinting datasync messages is a bit tricky, as they might unmarshal fine
|
||||
// because they are wrapped messages, so we need to check whether anything is
|
||||
// poulated in the fields.
|
||||
func (a *whisperAdapter) handleDecodedMessages(message *whisper.Message) ([]*protocol.StatusMessage, error) {
|
||||
var decodedMessages []*protocol.StatusMessage
|
||||
|
||||
logger := a.logger.With(zap.String("site", "decodeMessages"))
|
||||
hlogger := logger.With(zap.Binary("hash", message.Hash))
|
||||
|
||||
publicKey, err := crypto.UnmarshalPubkey(message.Sig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Try first with datasync
|
||||
datasyncMessage, err := protocol.UnwrapDatasync(message.Payload)
|
||||
|
||||
// If it failed to decode is not a protobuf message, if it successfully decoded but body is empty, is likedly a protobuf wrapped message
|
||||
if err != nil || !datasyncMessage.IsValid() {
|
||||
hlogger.Debug("Handling non-datasync message")
|
||||
// Not a datasync message
|
||||
decodedMessage, err := protocol.DecodeMessage(publicKey, message.Payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decodedMessages = append(decodedMessages, &decodedMessage)
|
||||
|
||||
} else {
|
||||
hlogger.Debug("Handling datasync message")
|
||||
// datasync message
|
||||
for _, message := range datasyncMessage.Messages {
|
||||
decodedMessage, err := protocol.DecodeMessage(publicKey, message.Body)
|
||||
if err != nil {
|
||||
hlogger.Error("failed to decode messages", zap.Error(err))
|
||||
// Log and continue
|
||||
logger.Info("failed to decode messages", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
// Addpacket to datasync if enabled
|
||||
|
||||
decodedMessages = append(decodedMessages, &decodedMessage)
|
||||
}
|
||||
if a.featureFlags.datasync {
|
||||
a.addDatasyncPacket(publicKey, datasyncMessage)
|
||||
}
|
||||
result[chat] = append(result[chat], statusMessages...)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return decodedMessages, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *whisperAdapter) handleMessageEncryption(ctx context.Context, message *whisper.Message) error {
|
||||
publicKey, err := crypto.UnmarshalPubkey(message.Sig)
|
||||
// handleMessages expects a whisper message as input, and it will go through
|
||||
// a series of transformations until the message is parsed into an application
|
||||
// layer message, or in case of Raw methods, the processing stops at the layer
|
||||
// before
|
||||
func (a *whisperAdapter) handleMessages(shhMessage *whisper.Message, applicationLayer bool) ([]*protocol.StatusMessage, error) {
|
||||
logger := a.logger.With(zap.String("site", "handleMessages"))
|
||||
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
|
||||
var statusMessage protocol.StatusMessage
|
||||
|
||||
err := statusMessage.HandleTransport(shhMessage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get signature")
|
||||
hlogger.Error("failed to handle transport layer message", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var protocolMessage encryption.ProtocolMessage
|
||||
|
||||
err = proto.Unmarshal(message.Payload, &protocolMessage)
|
||||
err = a.handleEncryptionLayer(context.Background(), &statusMessage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal ProtocolMessage")
|
||||
hlogger.Debug("failed to handle an encryption message", zap.Error(err))
|
||||
}
|
||||
|
||||
logger := a.logger.With(zap.String("site", "decryptMessage"))
|
||||
statusMessages, err := statusMessage.HandleDatasync(a.datasync)
|
||||
if err != nil {
|
||||
hlogger.Debug("failed to handle datasync message", zap.Error(err))
|
||||
|
||||
payload, err := a.protocol.HandleMessage(
|
||||
a.privateKey,
|
||||
publicKey,
|
||||
&protocolMessage,
|
||||
message.Hash,
|
||||
)
|
||||
}
|
||||
|
||||
for _, statusMessage := range statusMessages {
|
||||
err := statusMessage.HandleApplicationMetadata()
|
||||
if err != nil {
|
||||
hlogger.Error("failed to handle application metadata layer message", zap.Error(err))
|
||||
}
|
||||
|
||||
if applicationLayer {
|
||||
err = statusMessage.HandleApplication()
|
||||
if err != nil {
|
||||
hlogger.Error("failed to handle application layer message")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return statusMessages, nil
|
||||
}
|
||||
|
||||
func (a *whisperAdapter) handleEncryptionLayer(ctx context.Context, message *protocol.StatusMessage) error {
|
||||
publicKey := message.SigPubKey()
|
||||
|
||||
logger := a.logger.With(zap.String("site", "handleEncryptionLayer"))
|
||||
|
||||
err := message.HandleEncryption(a.privateKey, publicKey, a.protocol)
|
||||
if err == encryption.ErrDeviceNotFound {
|
||||
handleErr := a.handleErrDeviceNotFound(ctx, publicKey)
|
||||
if handleErr != nil {
|
||||
|
@ -334,9 +271,7 @@ func (a *whisperAdapter) handleMessageEncryption(ctx context.Context, message *w
|
|||
return errors.Wrap(err, "failed to process an encrypted message")
|
||||
}
|
||||
|
||||
message.Payload = payload
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (a *whisperAdapter) handleErrDeviceNotFound(ctx context.Context, publicKey *ecdsa.PublicKey) error {
|
||||
|
|
|
@ -121,10 +121,7 @@ func (s *AdaptersSuite) SetupTest() {
|
|||
datasyncpeers.NewMemoryPersistence(),
|
||||
)
|
||||
|
||||
datasync := &datasync.DataSync{
|
||||
Node: dataSyncNode,
|
||||
DataSyncNodeTransport: dataSyncTransport,
|
||||
}
|
||||
datasync := datasync.New(dataSyncNode, dataSyncTransport, true, logger)
|
||||
|
||||
s.a = newWhisperAdapter(
|
||||
s.privateKey,
|
||||
|
@ -150,20 +147,38 @@ func (s *AdaptersSuite) TestHandleDecodedMessagesSingle() {
|
|||
message.Sig = crypto.FromECDSAPub(&privateKey.PublicKey)
|
||||
message.Payload = encodedPayload
|
||||
|
||||
decodedMessage, err := s.a.handleDecodedMessages(message)
|
||||
decodedMessages, err := s.a.handleMessages(message, true)
|
||||
s.Require().NoError(err)
|
||||
expected := []*protocol.StatusMessage{
|
||||
&protocol.StatusMessage{
|
||||
ID: protocol.MessageID(&privateKey.PublicKey, encodedPayload),
|
||||
SigPubKey: &privateKey.PublicKey,
|
||||
Message: testMessageStruct,
|
||||
},
|
||||
}
|
||||
s.Require().Equal(expected, decodedMessage)
|
||||
s.Require().Equal(1, len(decodedMessages))
|
||||
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
|
||||
s.Require().Equal(&privateKey.PublicKey, decodedMessages[0].SigPubKey())
|
||||
s.Require().Equal(protocol.MessageID(&privateKey.PublicKey, encodedPayload), decodedMessages[0].ID)
|
||||
s.Require().Equal(testMessageStruct, decodedMessages[0].ParsedMessage)
|
||||
}
|
||||
|
||||
func (s *AdaptersSuite) TestHandleDecodedMessagesRaw() {
|
||||
|
||||
privateKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
encodedPayload, err := protocol.EncodeMessage(testMessageStruct)
|
||||
s.Require().NoError(err)
|
||||
|
||||
message := &whisper.Message{}
|
||||
message.Sig = crypto.FromECDSAPub(&privateKey.PublicKey)
|
||||
message.Payload = encodedPayload
|
||||
|
||||
decodedMessages, err := s.a.handleMessages(message, false)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(1, len(decodedMessages))
|
||||
s.Require().Equal(message, decodedMessages[0].TransportMessage)
|
||||
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
|
||||
s.Require().Equal(&privateKey.PublicKey, decodedMessages[0].SigPubKey())
|
||||
s.Require().Equal(protocol.MessageID(&privateKey.PublicKey, encodedPayload), decodedMessages[0].ID)
|
||||
s.Require().Equal(nil, decodedMessages[0].ParsedMessage)
|
||||
}
|
||||
|
||||
func (s *AdaptersSuite) TestHandleDecodedMessagesWrapped() {
|
||||
|
||||
relayerKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
|
@ -180,16 +195,14 @@ func (s *AdaptersSuite) TestHandleDecodedMessagesWrapped() {
|
|||
message.Sig = crypto.FromECDSAPub(&relayerKey.PublicKey)
|
||||
message.Payload = wrappedPayload
|
||||
|
||||
decodedMessage, err := s.a.handleDecodedMessages(message)
|
||||
decodedMessages, err := s.a.handleMessages(message, true)
|
||||
s.Require().NoError(err)
|
||||
expected := []*protocol.StatusMessage{
|
||||
&protocol.StatusMessage{
|
||||
ID: protocol.MessageID(&authorKey.PublicKey, encodedPayload),
|
||||
SigPubKey: &authorKey.PublicKey,
|
||||
Message: testMessageStruct,
|
||||
},
|
||||
}
|
||||
s.Require().Equal(expected, decodedMessage)
|
||||
|
||||
s.Require().Equal(1, len(decodedMessages))
|
||||
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
|
||||
s.Require().Equal(protocol.MessageID(&authorKey.PublicKey, encodedPayload), decodedMessages[0].ID)
|
||||
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
|
||||
s.Require().Equal(testMessageStruct, decodedMessages[0].ParsedMessage)
|
||||
}
|
||||
|
||||
func (s *AdaptersSuite) TestHandleDecodedMessagesDatasync() {
|
||||
|
@ -218,24 +231,20 @@ func (s *AdaptersSuite) TestHandleDecodedMessagesDatasync() {
|
|||
message.Sig = crypto.FromECDSAPub(&relayerKey.PublicKey)
|
||||
message.Payload = marshalledDataSyncMessage
|
||||
|
||||
decodedMessage, err := s.a.handleDecodedMessages(message)
|
||||
decodedMessages, err := s.a.handleMessages(message, true)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// We send two messages, the unwrapped one will be attributed to the relayer, while the wrapped one will be attributed to the author
|
||||
expected := []*protocol.StatusMessage{
|
||||
&protocol.StatusMessage{
|
||||
ID: protocol.MessageID(&relayerKey.PublicKey, encodedPayload),
|
||||
SigPubKey: &relayerKey.PublicKey,
|
||||
Message: testMessageStruct,
|
||||
},
|
||||
s.Require().Equal(2, len(decodedMessages))
|
||||
s.Require().Equal(&relayerKey.PublicKey, decodedMessages[0].SigPubKey())
|
||||
s.Require().Equal(protocol.MessageID(&relayerKey.PublicKey, encodedPayload), decodedMessages[0].ID)
|
||||
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
|
||||
s.Require().Equal(testMessageStruct, decodedMessages[0].ParsedMessage)
|
||||
|
||||
&protocol.StatusMessage{
|
||||
ID: protocol.MessageID(&authorKey.PublicKey, encodedPayload),
|
||||
SigPubKey: &authorKey.PublicKey,
|
||||
Message: testMessageStruct,
|
||||
},
|
||||
}
|
||||
s.Require().Equal(expected, decodedMessage)
|
||||
s.Require().Equal(&authorKey.PublicKey, decodedMessages[1].SigPubKey())
|
||||
s.Require().Equal(protocol.MessageID(&authorKey.PublicKey, encodedPayload), decodedMessages[1].ID)
|
||||
s.Require().Equal(encodedPayload, decodedMessages[1].DecryptedPayload)
|
||||
s.Require().Equal(testMessageStruct, decodedMessages[1].ParsedMessage)
|
||||
}
|
||||
|
||||
func (s *AdaptersSuite) TearDownTest() {
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: message.proto
|
||||
|
||||
package applicationmetadata
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
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.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Message struct {
|
||||
Signature []byte `protobuf:"bytes,4001,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
Payload []byte `protobuf:"bytes,4002,opt,name=payload,proto3" json:"payload,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
func (*Message) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_33c57e4bae7b9afd, []int{0}
|
||||
}
|
||||
|
||||
func (m *Message) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Message.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Message.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Message) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Message.Merge(m, src)
|
||||
}
|
||||
func (m *Message) XXX_Size() int {
|
||||
return xxx_messageInfo_Message.Size(m)
|
||||
}
|
||||
func (m *Message) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Message.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Message proto.InternalMessageInfo
|
||||
|
||||
func (m *Message) GetSignature() []byte {
|
||||
if m != nil {
|
||||
return m.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetPayload() []byte {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Message)(nil), "applicationmetadata.Message")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) }
|
||||
|
||||
var fileDescriptor_33c57e4bae7b9afd = []byte{
|
||||
// 112 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x4d, 0x2d, 0x2e,
|
||||
0x4e, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4e, 0x2c, 0x28, 0xc8, 0xc9,
|
||||
0x4c, 0x4e, 0x2c, 0xc9, 0xcc, 0xcf, 0xcb, 0x4d, 0x2d, 0x49, 0x4c, 0x49, 0x2c, 0x49, 0x54, 0x72,
|
||||
0xe6, 0x62, 0xf7, 0x85, 0xa8, 0x12, 0x92, 0xe5, 0xe2, 0x2c, 0xce, 0x4c, 0xcf, 0x4b, 0x2c, 0x29,
|
||||
0x2d, 0x4a, 0x95, 0x58, 0x28, 0xaf, 0xc0, 0xa8, 0xc1, 0x13, 0x84, 0x10, 0x11, 0x92, 0xe4, 0x62,
|
||||
0x2f, 0x48, 0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x91, 0x58, 0x04, 0x91, 0x84, 0xf1, 0x93, 0xd8, 0xc0,
|
||||
0x16, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x7f, 0x4a, 0x96, 0x71, 0x00, 0x00, 0x00,
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package statusproto;
|
||||
package applicationmetadata;
|
||||
|
||||
message StatusProtocolMessage {
|
||||
message Message {
|
||||
bytes signature = 4001;
|
||||
bytes payload = 4002;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package applicationmetadata
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
func (m *Message) RecoverKey() (*ecdsa.PublicKey, error) {
|
||||
if m.Signature == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
recoveredKey, err := crypto.SigToPub(
|
||||
crypto.Keccak256(m.Payload),
|
||||
m.Signature,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return recoveredKey, nil
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package applicationmetadata
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
//go:generate protoc --go_out=. ./message.proto
|
||||
|
||||
func Unmarshal(payload []byte) (*Message, error) {
|
||||
var message Message
|
||||
err := proto.Unmarshal(payload, &message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &message, nil
|
||||
}
|
|
@ -1,11 +1,67 @@
|
|||
package datasync
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"github.com/golang/protobuf/proto"
|
||||
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
|
||||
datasyncnode "github.com/vacp2p/mvds/node"
|
||||
datasyncproto "github.com/vacp2p/mvds/protobuf"
|
||||
datasynctransport "github.com/vacp2p/mvds/transport"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type DataSync struct {
|
||||
*datasyncnode.Node
|
||||
// DataSyncNodeTransport is the implemntation of the datasync transport interface
|
||||
*DataSyncNodeTransport
|
||||
logger *zap.Logger
|
||||
sendingEnabled bool
|
||||
}
|
||||
|
||||
func New(node *datasyncnode.Node, transport *DataSyncNodeTransport, sendingEnabled bool, logger *zap.Logger) *DataSync {
|
||||
return &DataSync{Node: node, DataSyncNodeTransport: transport, sendingEnabled: sendingEnabled, logger: logger}
|
||||
}
|
||||
|
||||
func (d *DataSync) Add(publicKey *ecdsa.PublicKey, datasyncMessage datasyncproto.Payload) {
|
||||
packet := datasynctransport.Packet{
|
||||
Sender: datasyncpeer.PublicKeyToPeerID(*publicKey),
|
||||
Payload: datasyncMessage,
|
||||
}
|
||||
d.DataSyncNodeTransport.AddPacket(packet)
|
||||
}
|
||||
|
||||
func (d *DataSync) Handle(sender *ecdsa.PublicKey, payload []byte) [][]byte {
|
||||
|
||||
var payloads [][]byte
|
||||
logger := d.logger.With(zap.String("site", "Handle"))
|
||||
|
||||
datasyncMessage, err := unwrap(payload)
|
||||
// If it failed to decode is not a protobuf message, if it successfully decoded but body is empty, is likedly a protobuf wrapped message
|
||||
if err != nil || !datasyncMessage.IsValid() {
|
||||
logger.Debug("handling non-datasync message", zap.Error(err), zap.Bool("datasyncMessage.IsValid()", datasyncMessage.IsValid()))
|
||||
// Not a datasync message, return unchanged
|
||||
payloads = append(payloads, payload)
|
||||
} else {
|
||||
logger.Debug("handling datasync message")
|
||||
// datasync message
|
||||
for _, message := range datasyncMessage.Messages {
|
||||
//copiedMessage := statusMessage.Copy()
|
||||
//copiedMessage.DataSyncLayerInfo.Payload = message.Body
|
||||
payloads = append(payloads, message.Body)
|
||||
}
|
||||
if d.sendingEnabled {
|
||||
d.Add(sender, datasyncMessage)
|
||||
}
|
||||
}
|
||||
|
||||
return payloads
|
||||
}
|
||||
|
||||
func unwrap(payload []byte) (datasyncPayload datasyncproto.Payload, err error) {
|
||||
err = proto.Unmarshal(payload, &datasyncPayload)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *DataSync) Stop() {
|
||||
d.Node.Stop()
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ func _1536754952_initial_schemaDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x44, 0xcf, 0x76, 0x71, 0x1f, 0x5e, 0x9a, 0x43, 0xd8, 0xcd, 0xb8, 0xc3, 0x70, 0xc3, 0x7f, 0xfc, 0x90, 0xb4, 0x25, 0x1e, 0xf4, 0x66, 0x20, 0xb8, 0x33, 0x7e, 0xb0, 0x76, 0x1f, 0xc, 0xc0, 0x75}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ func _1536754952_initial_schemaUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x90, 0x5a, 0x59, 0x3e, 0x3, 0xe2, 0x3c, 0x81, 0x42, 0xcd, 0x4c, 0x9a, 0xe8, 0xda, 0x93, 0x2b, 0x70, 0xa4, 0xd5, 0x29, 0x3e, 0xd5, 0xc9, 0x27, 0xb6, 0xb7, 0x65, 0xff, 0x0, 0xcb, 0xde}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func _1539249977_update_ratchet_infoDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xa4, 0xeb, 0xa0, 0xe6, 0xa0, 0xd4, 0x48, 0xbb, 0xad, 0x6f, 0x7d, 0x67, 0x8c, 0xbd, 0x25, 0xde, 0x1f, 0x73, 0x9a, 0xbb, 0xa8, 0xc9, 0x30, 0xb7, 0xa9, 0x7c, 0xaf, 0xb5, 0x1, 0x61, 0xdd}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ func _1539249977_update_ratchet_infoUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x8e, 0xbf, 0x6f, 0xa, 0xc0, 0xe1, 0x3c, 0x42, 0x28, 0x88, 0x1d, 0xdb, 0xba, 0x1c, 0x83, 0xec, 0xba, 0xd3, 0x5f, 0x5c, 0x77, 0x5e, 0xa7, 0x46, 0x36, 0xec, 0x69, 0xa, 0x4b, 0x17, 0x79}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ func _1540715431_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x9, 0x4, 0xe3, 0x76, 0x2e, 0xb8, 0x9, 0x23, 0xf0, 0x70, 0x93, 0xc4, 0x50, 0xe, 0x9d, 0x84, 0x22, 0x8c, 0x94, 0xd3, 0x24, 0x9, 0x9a, 0xc1, 0xa1, 0x48, 0x45, 0xfd, 0x40, 0x6e, 0xe6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func _1540715431_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc7, 0x4c, 0x36, 0x96, 0xdf, 0x16, 0x10, 0xa6, 0x27, 0x1a, 0x79, 0x8b, 0x42, 0x83, 0x23, 0xc, 0x7e, 0xb6, 0x3d, 0x2, 0xda, 0xa4, 0xb4, 0xd, 0x27, 0x55, 0xba, 0xdc, 0xb2, 0x88, 0x8f, 0xa6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ func _1541164797_add_installationsDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xfd, 0xe6, 0xd8, 0xca, 0x3b, 0x38, 0x18, 0xee, 0x0, 0x5f, 0x36, 0x9e, 0x1e, 0xd, 0x19, 0x3e, 0xb4, 0x73, 0x53, 0xe9, 0xa5, 0xac, 0xdd, 0xa1, 0x2f, 0xc7, 0x6c, 0xa8, 0xd9, 0xa, 0x88}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func _1541164797_add_installationsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2d, 0x18, 0x26, 0xb8, 0x88, 0x47, 0xdb, 0x83, 0xcc, 0xb6, 0x9d, 0x1c, 0x1, 0xae, 0x2f, 0xde, 0x97, 0x82, 0x3, 0x30, 0xa8, 0x63, 0xa1, 0x78, 0x4b, 0xa5, 0x9, 0x8, 0x75, 0xa2, 0x57, 0x81}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ func _1558084410_add_secretDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xb, 0x65, 0xdf, 0x59, 0xbf, 0xe9, 0x5, 0x5b, 0x6f, 0xd5, 0x3a, 0xb7, 0x57, 0xe8, 0x78, 0x38, 0x73, 0x53, 0x57, 0xf7, 0x24, 0x4, 0xe4, 0xa2, 0x49, 0x22, 0xa2, 0xc6, 0xfd, 0x80, 0xa4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ func _1558084410_add_secretUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x32, 0x36, 0x8e, 0x47, 0xb0, 0x8f, 0xc1, 0xc6, 0xf7, 0xc6, 0x9f, 0x2d, 0x44, 0x75, 0x2b, 0x26, 0xec, 0x6, 0xa0, 0x7b, 0xa5, 0xbd, 0xc8, 0x76, 0x8a, 0x82, 0x68, 0x2, 0x42, 0xb5, 0xf4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ func _1558588866_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1564125878, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x52, 0x34, 0x3c, 0x46, 0x4a, 0xf0, 0x72, 0x47, 0x6f, 0x49, 0x5c, 0xc7, 0xf9, 0x32, 0xce, 0xc4, 0x3d, 0xfd, 0x61, 0xa1, 0x8b, 0x8f, 0xf2, 0x31, 0x34, 0xde, 0x15, 0x49, 0xa6, 0xde, 0xb9}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ func _1558588866_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1564125858, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0xea, 0x64, 0x39, 0x61, 0x20, 0x83, 0x83, 0xb, 0x2e, 0x79, 0x64, 0xb, 0x53, 0xfa, 0xfe, 0xc6, 0xf7, 0x67, 0x42, 0xd3, 0x4f, 0xdc, 0x7e, 0x30, 0x32, 0xe8, 0x14, 0x41, 0xe9, 0xe7, 0x3b}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ func _1559627659_add_contact_codeDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x64, 0x6d, 0xce, 0x24, 0x42, 0x20, 0x8d, 0x4f, 0x37, 0xaa, 0x9d, 0xc, 0x57, 0x98, 0xc1, 0xd1, 0x1a, 0x34, 0xcd, 0x9f, 0x8f, 0x34, 0x86, 0xb3, 0xd3, 0xdc, 0xf1, 0x7d, 0xe5, 0x1b, 0x6e}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ func _1559627659_add_contact_codeUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0xf6, 0xc2, 0x62, 0x9c, 0xd2, 0xc9, 0x1e, 0xd8, 0xea, 0xaa, 0xea, 0x95, 0x8f, 0x89, 0x6a, 0x85, 0x5d, 0x9d, 0x99, 0x78, 0x3c, 0x90, 0x66, 0x99, 0x3e, 0x4b, 0x19, 0x62, 0xfb, 0x31, 0x4d}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ func _1561368210_add_installation_metadataDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xde, 0x3f, 0xd2, 0x4a, 0x50, 0x98, 0x56, 0xe3, 0xc0, 0xcd, 0x9d, 0xb0, 0x34, 0x3b, 0xe5, 0x62, 0x18, 0xb5, 0x20, 0xc9, 0x3e, 0xdc, 0x6a, 0x40, 0x36, 0x66, 0xea, 0x51, 0x8c, 0x71, 0xf5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ func _1561368210_add_installation_metadataUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x71, 0x8f, 0x29, 0xb1, 0xaa, 0xd6, 0xd1, 0x8c, 0x17, 0xef, 0x6c, 0xd5, 0x80, 0xb8, 0x2c, 0xc3, 0xfe, 0xec, 0x24, 0x4d, 0xc8, 0x25, 0xd3, 0xb4, 0xcd, 0xa9, 0xac, 0x63, 0x61, 0xb2, 0x9c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -420,7 +420,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564131660, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||
github.com/ethereum/go-ethereum v1.8.27
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
|
||||
github.com/leodido/go-urn v1.1.0 // indirect
|
||||
github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2
|
||||
github.com/pkg/errors v0.8.1
|
||||
|
|
2
go.sum
2
go.sum
|
@ -187,6 +187,8 @@ github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod
|
|||
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
|
||||
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
|
||||
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
|
|
14
messenger.go
14
messenger.go
|
@ -269,10 +269,7 @@ func NewMessenger(
|
|||
datasyncnode.BATCH,
|
||||
datasyncpeers.NewMemoryPersistence(),
|
||||
)
|
||||
datasync := &datasync.DataSync{
|
||||
Node: dataSyncNode,
|
||||
DataSyncNodeTransport: dataSyncTransport,
|
||||
}
|
||||
datasync := datasync.New(dataSyncNode, dataSyncTransport, c.featureFlags.datasync, logger)
|
||||
|
||||
adapter := newWhisperAdapter(identity, t, encryptionProtocol, datasync, c.featureFlags, logger)
|
||||
|
||||
|
@ -287,7 +284,7 @@ func NewMessenger(
|
|||
shutdownTasks: []func() error{
|
||||
database.Close,
|
||||
adapter.transport.Reset,
|
||||
func() error { datasync.Node.Stop(); return nil },
|
||||
func() error { datasync.Stop(); return nil },
|
||||
// Currently this often fails, seems like it's safe to ignore them
|
||||
// https://github.com/uber-go/zap/issues/328
|
||||
func() error { _ = logger.Sync; return nil },
|
||||
|
@ -557,15 +554,10 @@ func (m *Messenger) retrieveSaved(ctx context.Context, chatID string, c Retrieve
|
|||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (m *Messenger) RetrieveRawAll() (map[filter.Chat][]*whisper.Message, error) {
|
||||
func (m *Messenger) RetrieveRawAll() (map[filter.Chat][]*protocol.StatusMessage, error) {
|
||||
return m.adapter.RetrieveRawAll()
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (m *Messenger) RetrieveRawWithFilter(filterID string) ([]*whisper.Message, error) {
|
||||
return m.adapter.RetrieveRaw(filterID)
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (m *Messenger) LoadFilters(chats []*filter.Chat) ([]*filter.Chat, error) {
|
||||
return m.adapter.transport.LoadFilters(chats, m.featureFlags.genericDiscoveryTopicEnabled)
|
||||
|
|
|
@ -86,7 +86,7 @@ func _000001_initDownDbSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe8, 0x5f, 0xe0, 0x6, 0xfc, 0xed, 0xb7, 0xff, 0xb5, 0xf3, 0x33, 0x45, 0x1, 0x5b, 0x84, 0x80, 0x74, 0x60, 0x81, 0xa6, 0x8b, 0xb4, 0xd4, 0xad, 0x10, 0xa8, 0xb3, 0x61, 0x6f, 0xc5, 0x2f, 0xaa}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func _000001_initUpDbSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 840, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 840, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe7, 0x27, 0x96, 0x3b, 0x72, 0x81, 0x7d, 0xba, 0xa4, 0xfb, 0xf7, 0x4, 0xd, 0x6f, 0xc8, 0x30, 0xfe, 0x47, 0xe0, 0x9, 0xf, 0x43, 0x13, 0x6, 0x55, 0xfc, 0xee, 0x15, 0x69, 0x99, 0x53, 0x3f}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564131679, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ func _1561059285_add_whisper_keysDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0x31, 0x3f, 0xce, 0xfa, 0x44, 0x36, 0x1b, 0xb0, 0xec, 0x5d, 0xb, 0x90, 0xb, 0x21, 0x4f, 0xd5, 0xe5, 0x50, 0xed, 0xc7, 0x43, 0xdf, 0x83, 0xb4, 0x3a, 0xc1, 0x55, 0x2e, 0x53, 0x7c, 0x67}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func _1561059285_add_whisper_keysUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x25, 0x41, 0xc, 0x92, 0xdd, 0x9e, 0xff, 0x5d, 0xd0, 0x93, 0xe4, 0x24, 0x50, 0x29, 0xcf, 0xc6, 0xf7, 0x49, 0x3c, 0x73, 0xd9, 0x8c, 0xfa, 0xf2, 0xcf, 0xf6, 0x6f, 0xbc, 0x31, 0xe6, 0xf7, 0xe2}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1564131660, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x6a, 0xc1, 0xce, 0x94, 0xf6, 0xef, 0xf1, 0x97, 0x95, 0xb, 0x35, 0xaf, 0x5f, 0xe7, 0x5f, 0xac, 0x6e, 0xb8, 0xab, 0xba, 0xb5, 0x35, 0x97, 0x22, 0x36, 0x11, 0xce, 0x44, 0xfc, 0xfa, 0xac}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -5,17 +5,14 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/pkg/errors"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/golang/protobuf/proto"
|
||||
datasyncprotobuf "github.com/vacp2p/mvds/protobuf"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:generate protoc --go_out=. ./message.proto
|
||||
|
||||
const (
|
||||
// ContentTypeTextPlain means that the message contains plain text.
|
||||
ContentTypeTextPlain = "text/plain"
|
||||
|
@ -68,26 +65,6 @@ const (
|
|||
MessageRead Flags = 1 << iota
|
||||
)
|
||||
|
||||
// StatusMessage is any Status Protocol message.
|
||||
type StatusMessage struct {
|
||||
Message interface{}
|
||||
ID []byte `json:"-"`
|
||||
SigPubKey *ecdsa.PublicKey `json:"-"`
|
||||
}
|
||||
|
||||
func (m *StatusMessage) MarshalJSON() ([]byte, error) {
|
||||
type MessageAlias StatusMessage
|
||||
item := struct {
|
||||
*MessageAlias
|
||||
ID string `json:"id"`
|
||||
}{
|
||||
MessageAlias: (*MessageAlias)(m),
|
||||
ID: "0x" + hex.EncodeToString(m.ID),
|
||||
}
|
||||
|
||||
return json.Marshal(item)
|
||||
}
|
||||
|
||||
// Message is a chat message sent by an user.
|
||||
type Message struct {
|
||||
Text string `json:"text"` // TODO: why is this duplicated?
|
||||
|
@ -117,10 +94,6 @@ func (m *Message) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(item)
|
||||
}
|
||||
|
||||
func (m Message) Unread() bool {
|
||||
return !m.Flags.Has(MessageRead)
|
||||
}
|
||||
|
||||
// createTextMessage creates a Message.
|
||||
func createTextMessage(data []byte, lastClock int64, chatID, messageType string) Message {
|
||||
text := strings.TrimSpace(string(data))
|
||||
|
@ -147,17 +120,12 @@ func CreatePrivateTextMessage(data []byte, lastClock int64, chatID string) Messa
|
|||
return createTextMessage(data, lastClock, chatID, MessageTypePrivate)
|
||||
}
|
||||
|
||||
func unwrapMessage(data []byte) (*StatusProtocolMessage, error) {
|
||||
var message StatusProtocolMessage
|
||||
err := proto.Unmarshal(data, &message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &message, nil
|
||||
}
|
||||
func decodeTransitMessage(originalPayload []byte) (interface{}, error) {
|
||||
payload := make([]byte, len(originalPayload))
|
||||
copy(payload, originalPayload)
|
||||
// This modifies the payload
|
||||
buf := bytes.NewBuffer(payload)
|
||||
|
||||
func decodeTransitMessage(data []byte) (interface{}, error) {
|
||||
buf := bytes.NewBuffer(data)
|
||||
decoder := NewMessageDecoder(buf)
|
||||
value, err := decoder.Decode()
|
||||
if err != nil {
|
||||
|
@ -166,47 +134,6 @@ func decodeTransitMessage(data []byte) (interface{}, error) {
|
|||
return value, nil
|
||||
}
|
||||
|
||||
func UnwrapDatasync(payload []byte) (datasyncPayload datasyncprotobuf.Payload, err error) {
|
||||
err = proto.Unmarshal(payload, &datasyncPayload)
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMessage decodes a raw payload to StatusMessage struct.
|
||||
func DecodeMessage(transportPublicKey *ecdsa.PublicKey, data []byte) (message StatusMessage, err error) {
|
||||
transitMessage := data
|
||||
|
||||
// Getting a signature from transport message should happen only if
|
||||
// the signature was not defined in the payload itself.
|
||||
message.SigPubKey = transportPublicKey
|
||||
|
||||
statusProtocolMessage, err := unwrapMessage(data)
|
||||
if err == nil {
|
||||
// Wrapped message, extract transit and signature
|
||||
transitMessage = statusProtocolMessage.Payload
|
||||
if statusProtocolMessage.Signature != nil {
|
||||
recoveredKey, err := crypto.SigToPub(
|
||||
crypto.Keccak256(transitMessage),
|
||||
statusProtocolMessage.Signature,
|
||||
)
|
||||
if err != nil {
|
||||
return message, err
|
||||
}
|
||||
|
||||
message.SigPubKey = recoveredKey
|
||||
}
|
||||
}
|
||||
|
||||
message.ID = MessageID(message.SigPubKey, transitMessage)
|
||||
value, err := decodeTransitMessage(transitMessage)
|
||||
if err != nil {
|
||||
log.Printf("[message::DecodeMessage] could not decode message: %#x", message.ID)
|
||||
return message, err
|
||||
}
|
||||
message.Message = value
|
||||
|
||||
return message, nil
|
||||
}
|
||||
|
||||
// EncodeMessage encodes a Message using Transit serialization.
|
||||
func EncodeMessage(value Message) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
|
|
|
@ -20,24 +20,14 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func TestDecodeMessage(t *testing.T) {
|
||||
key, err := crypto.GenerateKey()
|
||||
func TestDecodeTransitMessage(t *testing.T) {
|
||||
val, err := decodeTransitMessage(testMessageBytes)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, err := DecodeMessage(&key.PublicKey, testMessageBytes)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, StatusMessage{
|
||||
Message: testMessageStruct,
|
||||
SigPubKey: &key.PublicKey,
|
||||
ID: MessageID(&key.PublicKey, testMessageBytes),
|
||||
}, val)
|
||||
require.EqualValues(t, testMessageStruct, val)
|
||||
}
|
||||
|
||||
func BenchmarkDecodeMessage(b *testing.B) {
|
||||
key, err := crypto.GenerateKey()
|
||||
require.NoError(b, err)
|
||||
|
||||
_, err = DecodeMessage(&key.PublicKey, testMessageBytes)
|
||||
func BenchmarkDecodeTransitMessage(b *testing.B) {
|
||||
_, err := decodeTransitMessage(testMessageBytes)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to decode message: %v", err)
|
||||
}
|
||||
|
@ -45,67 +35,16 @@ func BenchmarkDecodeMessage(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, _ = DecodeMessage(&key.PublicKey, testMessageBytes)
|
||||
_, _ = decodeTransitMessage(testMessageBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeMessage(t *testing.T) {
|
||||
key, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := EncodeMessage(testMessageStruct)
|
||||
require.NoError(t, err)
|
||||
require.NoError(b, err)
|
||||
// Decode it back to a struct because, for example, map encoding is non-deterministic
|
||||
// and it is not possible to compare bytes.
|
||||
val, err := DecodeMessage(&key.PublicKey, data)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, StatusMessage{
|
||||
Message: testMessageStruct,
|
||||
SigPubKey: &key.PublicKey,
|
||||
ID: MessageID(&key.PublicKey, data),
|
||||
}, val)
|
||||
}
|
||||
|
||||
func TestWrappedMessageWithSignature(t *testing.T) {
|
||||
key, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
transportKey, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := EncodeMessage(testMessageStruct)
|
||||
require.NoError(t, err)
|
||||
wrappedMessage, err := WrapMessageV1(data, key)
|
||||
require.NoError(t, err)
|
||||
// Decode it back to a struct because, for example, map encoding is non-deterministic
|
||||
// and it is not possible to compare bytes.
|
||||
val, err := DecodeMessage(&transportKey.PublicKey, wrappedMessage)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, StatusMessage{
|
||||
Message: testMessageStruct,
|
||||
ID: MessageID(&key.PublicKey, data),
|
||||
SigPubKey: &key.PublicKey,
|
||||
}, val)
|
||||
}
|
||||
|
||||
func TestWrappedMessageWithoutSignature(t *testing.T) {
|
||||
key, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := EncodeMessage(testMessageStruct)
|
||||
require.NoError(t, err)
|
||||
wrappedMessage, err := WrapMessageV1(data, nil)
|
||||
require.NoError(t, err)
|
||||
// Decode it back to a struct because, for example, map encoding is non-deterministic
|
||||
// and it is not possible to compare bytes.
|
||||
val, err := DecodeMessage(&key.PublicKey, wrappedMessage)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, StatusMessage{
|
||||
Message: testMessageStruct,
|
||||
SigPubKey: &key.PublicKey,
|
||||
ID: MessageID(&key.PublicKey, data),
|
||||
}, val)
|
||||
val, err := decodeTransitMessage(data)
|
||||
require.NoError(b, err)
|
||||
require.EqualValues(b, testMessageStruct, val)
|
||||
}
|
||||
|
||||
func TestMessageID(t *testing.T) {
|
||||
|
@ -119,24 +58,6 @@ func TestMessageID(t *testing.T) {
|
|||
require.Equal(t, expectedID, MessageID(&key.PublicKey, data))
|
||||
}
|
||||
|
||||
func TestMessageWrongPublicKey(t *testing.T) {
|
||||
key, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
wrongKey, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := EncodeMessage(testMessageStruct)
|
||||
require.NoError(t, err)
|
||||
wrappedMessage, err := WrapMessageV1(data, key)
|
||||
require.NoError(t, err)
|
||||
// Decode it back to a struct because, for example, map encoding is non-deterministic
|
||||
// and it is not possible to compare bytes.
|
||||
val, err := DecodeMessage(&key.PublicKey, wrappedMessage)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, val.ID, MessageID(&wrongKey.PublicKey, data), val)
|
||||
}
|
||||
|
||||
func TestTimestampInMs(t *testing.T) {
|
||||
ts := TimestampInMs(1555274502548) // random timestamp in milliseconds
|
||||
tt := ts.Time()
|
||||
|
|
|
@ -3,7 +3,6 @@ package statusproto
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -18,31 +17,17 @@ var (
|
|||
)
|
||||
|
||||
func TestDecodePairMessageMessage(t *testing.T) {
|
||||
key, err := crypto.GenerateKey()
|
||||
val, err := decodeTransitMessage(testPairMessageBytes)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, err := DecodeMessage(&key.PublicKey, testPairMessageBytes)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, StatusMessage{
|
||||
Message: testPairMessageStruct,
|
||||
SigPubKey: &key.PublicKey,
|
||||
ID: MessageID(&key.PublicKey, testPairMessageBytes),
|
||||
}, val)
|
||||
require.EqualValues(t, testPairMessageStruct, val)
|
||||
}
|
||||
|
||||
func TestEncodePairMessage(t *testing.T) {
|
||||
key, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := EncodePairMessage(testPairMessageStruct)
|
||||
require.NoError(t, err)
|
||||
// Decode it back to a struct because, for example, map encoding is non-deterministic
|
||||
// and it is not possible to compare bytes.
|
||||
val, err := DecodeMessage(&key.PublicKey, data)
|
||||
val, err := decodeTransitMessage(data)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, StatusMessage{
|
||||
Message: testPairMessageStruct,
|
||||
SigPubKey: &key.PublicKey,
|
||||
ID: MessageID(&key.PublicKey, data),
|
||||
}, val)
|
||||
require.EqualValues(t, testPairMessageStruct, val)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
package statusproto
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"github.com/pkg/errors"
|
||||
"log"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/status-im/status-protocol-go/applicationmetadata"
|
||||
"github.com/status-im/status-protocol-go/datasync"
|
||||
"github.com/status-im/status-protocol-go/encryption"
|
||||
whisper "github.com/status-im/whisper/whisperv6"
|
||||
)
|
||||
|
||||
// StatusMessage is any Status Protocol message.
|
||||
type StatusMessage struct {
|
||||
// TransportMessage is the parsed message received from the trasport layer, i.e the input
|
||||
TransportMessage *whisper.Message
|
||||
// ParsedMessage is the parsed message by the application layer, i.e the output
|
||||
ParsedMessage interface{}
|
||||
|
||||
// TransportPayload is the payload as received from the transport layer
|
||||
TransportPayload []byte
|
||||
// DecryptedPayload is the payload after having been processed by the encryption layer
|
||||
DecryptedPayload []byte
|
||||
|
||||
// ID is the canonical ID of the message
|
||||
ID []byte
|
||||
// Hash is the transport layer hash
|
||||
Hash []byte
|
||||
|
||||
// TransportLayerSigPubKey contains the public key provided by the transport layer
|
||||
TransportLayerSigPubKey *ecdsa.PublicKey
|
||||
// ApplicationMetadataLayerPubKey contains the public key provided by the application metadata layer
|
||||
ApplicationMetadataLayerSigPubKey *ecdsa.PublicKey
|
||||
}
|
||||
|
||||
// SigPubKey returns the most important signature, from the application layer to transport
|
||||
func (s *StatusMessage) SigPubKey() *ecdsa.PublicKey {
|
||||
if s.ApplicationMetadataLayerSigPubKey != nil {
|
||||
return s.ApplicationMetadataLayerSigPubKey
|
||||
}
|
||||
|
||||
return s.TransportLayerSigPubKey
|
||||
}
|
||||
|
||||
func (s *StatusMessage) Clone() (*StatusMessage, error) {
|
||||
copy := &StatusMessage{}
|
||||
|
||||
err := copier.Copy(©, s)
|
||||
return copy, err
|
||||
}
|
||||
|
||||
func (m *StatusMessage) HandleTransport(shhMessage *whisper.Message) error {
|
||||
publicKey, err := crypto.UnmarshalPubkey(shhMessage.Sig)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get signature")
|
||||
}
|
||||
|
||||
m.TransportMessage = shhMessage
|
||||
m.Hash = shhMessage.Hash
|
||||
m.TransportLayerSigPubKey = publicKey
|
||||
m.TransportPayload = shhMessage.Payload
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StatusMessage) HandleEncryption(myKey *ecdsa.PrivateKey, senderKey *ecdsa.PublicKey, enc *encryption.Protocol) error {
|
||||
// As we handle non-encrypted messages, we make sure that DecryptPayload
|
||||
// is set regardless of whether this step is successful
|
||||
m.DecryptedPayload = m.TransportPayload
|
||||
|
||||
var protocolMessage encryption.ProtocolMessage
|
||||
err := proto.Unmarshal(m.TransportPayload, &protocolMessage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal ProtocolMessage")
|
||||
}
|
||||
|
||||
payload, err := enc.HandleMessage(
|
||||
myKey,
|
||||
senderKey,
|
||||
&protocolMessage,
|
||||
m.Hash,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to handle Encryption message")
|
||||
}
|
||||
|
||||
m.DecryptedPayload = payload
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StatusMessage) HandleDatasync(datasync *datasync.DataSync) ([]*StatusMessage, error) {
|
||||
var statusMessages []*StatusMessage
|
||||
payloads := datasync.Handle(
|
||||
m.SigPubKey(),
|
||||
m.DecryptedPayload,
|
||||
)
|
||||
for _, payload := range payloads {
|
||||
message, err := m.Clone()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
message.DecryptedPayload = payload
|
||||
statusMessages = append(statusMessages, message)
|
||||
}
|
||||
return statusMessages, nil
|
||||
}
|
||||
|
||||
func (m *StatusMessage) HandleApplicationMetadata() error {
|
||||
message, err := applicationmetadata.Unmarshal(m.DecryptedPayload)
|
||||
// Not an applicationmetadata message, calculate ID using the previous
|
||||
// signature
|
||||
if err != nil {
|
||||
m.ID = MessageID(m.SigPubKey(), m.DecryptedPayload)
|
||||
return nil
|
||||
}
|
||||
|
||||
recoveredKey, err := message.RecoverKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.ApplicationMetadataLayerSigPubKey = recoveredKey
|
||||
m.DecryptedPayload = message.Payload
|
||||
m.ID = MessageID(m.SigPubKey(), m.DecryptedPayload)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (m *StatusMessage) HandleApplication() error {
|
||||
value, err := decodeTransitMessage(m.DecryptedPayload)
|
||||
if err != nil {
|
||||
log.Printf("[message::DecodeMessage] could not decode message: %#x", m.Hash)
|
||||
return err
|
||||
}
|
||||
m.ParsedMessage = value
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
guard 'gotest' do
|
||||
watch(%r{\.go$})
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Jinzhu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,100 @@
|
|||
# Copier
|
||||
|
||||
I am a copier, I copy everything from one to another
|
||||
|
||||
[![wercker status](https://app.wercker.com/status/9d44ad2d4e6253929c8fb71359effc0b/s/master "wercker status")](https://app.wercker.com/project/byKey/9d44ad2d4e6253929c8fb71359effc0b)
|
||||
|
||||
## Features
|
||||
|
||||
* Copy from field to field with same name
|
||||
* Copy from method to field with same name
|
||||
* Copy from field to method with same name
|
||||
* Copy from slice to slice
|
||||
* Copy from struct to slice
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Role string
|
||||
Age int32
|
||||
}
|
||||
|
||||
func (user *User) DoubleAge() int32 {
|
||||
return 2 * user.Age
|
||||
}
|
||||
|
||||
type Employee struct {
|
||||
Name string
|
||||
Age int32
|
||||
DoubleAge int32
|
||||
EmployeId int64
|
||||
SuperRule string
|
||||
}
|
||||
|
||||
func (employee *Employee) Role(role string) {
|
||||
employee.SuperRule = "Super " + role
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
user = User{Name: "Jinzhu", Age: 18, Role: "Admin"}
|
||||
users = []User{{Name: "Jinzhu", Age: 18, Role: "Admin"}, {Name: "jinzhu 2", Age: 30, Role: "Dev"}}
|
||||
employee = Employee{}
|
||||
employees = []Employee{}
|
||||
)
|
||||
|
||||
copier.Copy(&employee, &user)
|
||||
|
||||
fmt.Printf("%#v \n", employee)
|
||||
// Employee{
|
||||
// Name: "Jinzhu", // Copy from field
|
||||
// Age: 18, // Copy from field
|
||||
// DoubleAge: 36, // Copy from method
|
||||
// EmployeeId: 0, // Ignored
|
||||
// SuperRule: "Super Admin", // Copy to method
|
||||
// }
|
||||
|
||||
// Copy struct to slice
|
||||
copier.Copy(&employees, &user)
|
||||
|
||||
fmt.Printf("%#v \n", employees)
|
||||
// []Employee{
|
||||
// {Name: "Jinzhu", Age: 18, DoubleAge: 36, EmployeId: 0, SuperRule: "Super Admin"}
|
||||
// }
|
||||
|
||||
// Copy slice to slice
|
||||
employees = []Employee{}
|
||||
copier.Copy(&employees, &users)
|
||||
|
||||
fmt.Printf("%#v \n", employees)
|
||||
// []Employee{
|
||||
// {Name: "Jinzhu", Age: 18, DoubleAge: 36, EmployeId: 0, SuperRule: "Super Admin"},
|
||||
// {Name: "jinzhu 2", Age: 30, DoubleAge: 60, EmployeId: 0, SuperRule: "Super Dev"},
|
||||
// }
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
You can help to make the project better, check out [http://gorm.io/contribute.html](http://gorm.io/contribute.html) for things you can do.
|
||||
|
||||
# Author
|
||||
|
||||
**jinzhu**
|
||||
|
||||
* <http://github.com/jinzhu>
|
||||
* <wosmvp@gmail.com>
|
||||
* <http://twitter.com/zhangjinzhu>
|
||||
|
||||
## License
|
||||
|
||||
Released under the [MIT License](https://github.com/jinzhu/copier/blob/master/License).
|
|
@ -0,0 +1,189 @@
|
|||
package copier
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Copy copy things
|
||||
func Copy(toValue interface{}, fromValue interface{}) (err error) {
|
||||
var (
|
||||
isSlice bool
|
||||
amount = 1
|
||||
from = indirect(reflect.ValueOf(fromValue))
|
||||
to = indirect(reflect.ValueOf(toValue))
|
||||
)
|
||||
|
||||
if !to.CanAddr() {
|
||||
return errors.New("copy to value is unaddressable")
|
||||
}
|
||||
|
||||
// Return is from value is invalid
|
||||
if !from.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
fromType := indirectType(from.Type())
|
||||
toType := indirectType(to.Type())
|
||||
|
||||
// Just set it if possible to assign
|
||||
// And need to do copy anyway if the type is struct
|
||||
if fromType.Kind() != reflect.Struct && from.Type().AssignableTo(to.Type()) {
|
||||
to.Set(from)
|
||||
return
|
||||
}
|
||||
|
||||
if fromType.Kind() != reflect.Struct || toType.Kind() != reflect.Struct {
|
||||
return
|
||||
}
|
||||
|
||||
if to.Kind() == reflect.Slice {
|
||||
isSlice = true
|
||||
if from.Kind() == reflect.Slice {
|
||||
amount = from.Len()
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < amount; i++ {
|
||||
var dest, source reflect.Value
|
||||
|
||||
if isSlice {
|
||||
// source
|
||||
if from.Kind() == reflect.Slice {
|
||||
source = indirect(from.Index(i))
|
||||
} else {
|
||||
source = indirect(from)
|
||||
}
|
||||
// dest
|
||||
dest = indirect(reflect.New(toType).Elem())
|
||||
} else {
|
||||
source = indirect(from)
|
||||
dest = indirect(to)
|
||||
}
|
||||
|
||||
// check source
|
||||
if source.IsValid() {
|
||||
fromTypeFields := deepFields(fromType)
|
||||
//fmt.Printf("%#v", fromTypeFields)
|
||||
// Copy from field to field or method
|
||||
for _, field := range fromTypeFields {
|
||||
name := field.Name
|
||||
|
||||
if fromField := source.FieldByName(name); fromField.IsValid() {
|
||||
// has field
|
||||
if toField := dest.FieldByName(name); toField.IsValid() {
|
||||
if toField.CanSet() {
|
||||
if !set(toField, fromField) {
|
||||
if err := Copy(toField.Addr().Interface(), fromField.Interface()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// try to set to method
|
||||
var toMethod reflect.Value
|
||||
if dest.CanAddr() {
|
||||
toMethod = dest.Addr().MethodByName(name)
|
||||
} else {
|
||||
toMethod = dest.MethodByName(name)
|
||||
}
|
||||
|
||||
if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {
|
||||
toMethod.Call([]reflect.Value{fromField})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy from method to field
|
||||
for _, field := range deepFields(toType) {
|
||||
name := field.Name
|
||||
|
||||
var fromMethod reflect.Value
|
||||
if source.CanAddr() {
|
||||
fromMethod = source.Addr().MethodByName(name)
|
||||
} else {
|
||||
fromMethod = source.MethodByName(name)
|
||||
}
|
||||
|
||||
if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 {
|
||||
if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() {
|
||||
values := fromMethod.Call([]reflect.Value{})
|
||||
if len(values) >= 1 {
|
||||
set(toField, values[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if isSlice {
|
||||
if dest.Addr().Type().AssignableTo(to.Type().Elem()) {
|
||||
to.Set(reflect.Append(to, dest.Addr()))
|
||||
} else if dest.Type().AssignableTo(to.Type().Elem()) {
|
||||
to.Set(reflect.Append(to, dest))
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func deepFields(reflectType reflect.Type) []reflect.StructField {
|
||||
var fields []reflect.StructField
|
||||
|
||||
if reflectType = indirectType(reflectType); reflectType.Kind() == reflect.Struct {
|
||||
for i := 0; i < reflectType.NumField(); i++ {
|
||||
v := reflectType.Field(i)
|
||||
if v.Anonymous {
|
||||
fields = append(fields, deepFields(v.Type)...)
|
||||
} else {
|
||||
fields = append(fields, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
func indirect(reflectValue reflect.Value) reflect.Value {
|
||||
for reflectValue.Kind() == reflect.Ptr {
|
||||
reflectValue = reflectValue.Elem()
|
||||
}
|
||||
return reflectValue
|
||||
}
|
||||
|
||||
func indirectType(reflectType reflect.Type) reflect.Type {
|
||||
for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
|
||||
reflectType = reflectType.Elem()
|
||||
}
|
||||
return reflectType
|
||||
}
|
||||
|
||||
func set(to, from reflect.Value) bool {
|
||||
if from.IsValid() {
|
||||
if to.Kind() == reflect.Ptr {
|
||||
//set `to` to nil if from is nil
|
||||
if from.Kind() == reflect.Ptr && from.IsNil() {
|
||||
to.Set(reflect.Zero(to.Type()))
|
||||
return true
|
||||
} else if to.IsNil() {
|
||||
to.Set(reflect.New(to.Type().Elem()))
|
||||
}
|
||||
to = to.Elem()
|
||||
}
|
||||
|
||||
if from.Type().ConvertibleTo(to.Type()) {
|
||||
to.Set(from.Convert(to.Type()))
|
||||
} else if scanner, ok := to.Addr().Interface().(sql.Scanner); ok {
|
||||
err := scanner.Scan(from.Interface())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else if from.Kind() == reflect.Ptr {
|
||||
return set(to, from.Elem())
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
box: golang
|
||||
|
||||
build:
|
||||
steps:
|
||||
- setup-go-workspace
|
||||
|
||||
# Gets the dependencies
|
||||
- script:
|
||||
name: go get
|
||||
code: |
|
||||
go get
|
||||
|
||||
# Build the project
|
||||
- script:
|
||||
name: go build
|
||||
code: |
|
||||
go build ./...
|
||||
|
||||
# Test the project
|
||||
- script:
|
||||
name: go test
|
||||
code: |
|
||||
go test ./...
|
|
@ -57,6 +57,8 @@ github.com/huin/goupnp/soap
|
|||
github.com/huin/goupnp/ssdp
|
||||
# github.com/jackpal/go-nat-pmp v1.0.1
|
||||
github.com/jackpal/go-nat-pmp
|
||||
# github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
|
||||
github.com/jinzhu/copier
|
||||
# github.com/leodido/go-urn v1.1.0
|
||||
github.com/leodido/go-urn
|
||||
# github.com/lib/pq v1.0.0
|
||||
|
|
Loading…
Reference in New Issue