some adjustmentsfor server delivery and peer storage study
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is failing
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	continuous-integration/drone/push Build is failing
				
			This commit is contained in:
		@@ -3,11 +3,13 @@ package client
 | 
				
			|||||||
import "forge.redroom.link/yves/meowlib"
 | 
					import "forge.redroom.link/yves/meowlib"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type InternalUserMessage struct {
 | 
					type InternalUserMessage struct {
 | 
				
			||||||
	Outbound           bool                        `json:"outbound"`
 | 
						Outbound                bool                        `json:"outbound"`
 | 
				
			||||||
	Messagetype        string                      `json:"messagetype,omitempty"`
 | 
						Messagetype             string                      `json:"messagetype,omitempty"`
 | 
				
			||||||
	Message            string                      `json:"message,omitempty"`
 | 
						Message                 string                      `json:"message,omitempty"`
 | 
				
			||||||
	ConversationStatus *meowlib.ConversationStatus `json:"conversation_status,omitempty"`
 | 
						ConversationStatus      *meowlib.ConversationStatus `json:"conversation_status,omitempty"`
 | 
				
			||||||
	Contact            *meowlib.ContactCard        `json:"contact,omitempty"`
 | 
						Contact                 *meowlib.ContactCard        `json:"contact,omitempty"`
 | 
				
			||||||
 | 
						ServerDeliveryUuid      string                      `json:"server_delivery_uuid,omitempty"`
 | 
				
			||||||
 | 
						ServerDeliveryTimestamp int64                       `json:"server_delivery_timestamp,omitempty"`
 | 
				
			||||||
	//Group group
 | 
						//Group group
 | 
				
			||||||
	FilePaths       []string          `json:"file_paths,omitempty"`
 | 
						FilePaths       []string          `json:"file_paths,omitempty"`
 | 
				
			||||||
	CurrentLocation *meowlib.Location `json:"current_location,omitempty"`
 | 
						CurrentLocation *meowlib.Location `json:"current_location,omitempty"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,8 @@ type Peer struct {
 | 
				
			|||||||
	Blocked             bool     `json:"blocked,omitempty"`
 | 
						Blocked             bool     `json:"blocked,omitempty"`
 | 
				
			||||||
	MessageNotification string   `json:"message_notification,omitempty"`
 | 
						MessageNotification string   `json:"message_notification,omitempty"`
 | 
				
			||||||
	MatriochkaMode      bool     `json:"matriochka_mode,omitempty"`
 | 
						MatriochkaMode      bool     `json:"matriochka_mode,omitempty"`
 | 
				
			||||||
 | 
						ServerDeliveryInfo  bool     `json:"server_delivery_info,omitempty"`
 | 
				
			||||||
 | 
						CallsAllowed        bool     `json:"calls_allowed,omitempty"`
 | 
				
			||||||
	DirectMode          bool     `json:"direct_mode,omitempty"`
 | 
						DirectMode          bool     `json:"direct_mode,omitempty"`
 | 
				
			||||||
	DbIds               []string `json:"db_ids,omitempty"`
 | 
						DbIds               []string `json:"db_ids,omitempty"`
 | 
				
			||||||
	Type                string   `json:"type,omitempty"`
 | 
						Type                string   `json:"type,omitempty"`
 | 
				
			||||||
@@ -229,6 +231,9 @@ func (p *Peer) PackUserMessage(message []byte, signature []byte) *meowlib.Packed
 | 
				
			|||||||
	msg.Destination = p.ContactLookupKey
 | 
						msg.Destination = p.ContactLookupKey
 | 
				
			||||||
	msg.Payload = message
 | 
						msg.Payload = message
 | 
				
			||||||
	msg.Signature = signature
 | 
						msg.Signature = signature
 | 
				
			||||||
 | 
						if p.ServerDeliveryInfo {
 | 
				
			||||||
 | 
							msg.ServerDeliveryUuid = uuid.New().String()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return &msg
 | 
						return &msg
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,5 @@
 | 
				
			|||||||
package client
 | 
					package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"forge.redroom.link/yves/meowlib"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type PeerList []*Peer
 | 
					type PeerList []*Peer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pl *PeerList) GetFromPublicKey(publickey string) *Peer {
 | 
					func (pl *PeerList) GetFromPublicKey(publickey string) *Peer {
 | 
				
			||||||
@@ -43,7 +39,7 @@ func (pl *PeerList) GetFromName(name string) *Peer {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ! Wrong implementation, does not discriminate on different servers
 | 
					// ! Wrong implementation, does not discriminate on different servers
 | 
				
			||||||
func (pl *PeerList) GetConversationRequests() []*meowlib.ConversationRequest {
 | 
					/*func (pl *PeerList) GetConversationRequests() []*meowlib.ConversationRequest {
 | 
				
			||||||
	var list []*meowlib.ConversationRequest
 | 
						var list []*meowlib.ConversationRequest
 | 
				
			||||||
	for _, peer := range *pl {
 | 
						for _, peer := range *pl {
 | 
				
			||||||
		var cr meowlib.ConversationRequest
 | 
							var cr meowlib.ConversationRequest
 | 
				
			||||||
@@ -52,4 +48,4 @@ func (pl *PeerList) GetConversationRequests() []*meowlib.ConversationRequest {
 | 
				
			|||||||
		list = append(list, &cr)
 | 
							list = append(list, &cr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return list
 | 
						return list
 | 
				
			||||||
}
 | 
					}*/
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										171
									
								
								client/peerstorage.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								client/peerstorage.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
				
			|||||||
 | 
					package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Storage
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/sha256"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"forge.redroom.link/yves/meowlib"
 | 
				
			||||||
 | 
						"github.com/dgraph-io/badger"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PeerStorage struct {
 | 
				
			||||||
 | 
						DbFile string `json:"db_file,omitempty"`
 | 
				
			||||||
 | 
						db     *badger.DB
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Open a badger database from struct PeerStorage
 | 
				
			||||||
 | 
					func (ps *PeerStorage) open() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts := badger.DefaultOptions(filepath.Join(GetConfig().StoragePath, GetConfig().GetIdentity().Uuid, ps.DbFile))
 | 
				
			||||||
 | 
						opts.Logger = nil
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						ps.db, err = badger.Open(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Store function StorePeer stores a peer in a badger database with Peer.Uid as key
 | 
				
			||||||
 | 
					func (ps *PeerStorage) StorePeer(peer *Peer) error {
 | 
				
			||||||
 | 
						err := ps.open()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer ps.close()
 | 
				
			||||||
 | 
						// first marshal the Peer to bytes with protobuf
 | 
				
			||||||
 | 
						jsonsrv, err := json.Marshal(peer)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						password := GetConfig().memoryPassword
 | 
				
			||||||
 | 
						if peer.dbPassword != "" {
 | 
				
			||||||
 | 
							password = peer.dbPassword
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data, err := meowlib.SymEncrypt(password, jsonsrv)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						shakey := sha256.Sum256([]byte(peer.Uid))
 | 
				
			||||||
 | 
						key := shakey[:]
 | 
				
			||||||
 | 
						// then store it in the database
 | 
				
			||||||
 | 
						return ps.db.Update(func(txn *badger.Txn) error {
 | 
				
			||||||
 | 
							return txn.Set(key, data)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LoadPeer function loads a Peer from a badger database with Peer.GetUid() as key
 | 
				
			||||||
 | 
					func (ps *PeerStorage) LoadPeer(uid string, password string) (*Peer, error) {
 | 
				
			||||||
 | 
						var peer Peer
 | 
				
			||||||
 | 
						err := ps.open()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer ps.close()
 | 
				
			||||||
 | 
						shakey := sha256.Sum256([]byte(uid))
 | 
				
			||||||
 | 
						key := shakey[:]
 | 
				
			||||||
 | 
						err = ps.db.View(func(txn *badger.Txn) error {
 | 
				
			||||||
 | 
							item, err := txn.Get(key)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return item.Value(func(val []byte) error {
 | 
				
			||||||
 | 
								jsonsrv, err := meowlib.SymDecrypt(password, val)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return json.Unmarshal(jsonsrv, &peer)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return &peer, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeletePeer function deletes a Peer from a badger database with Peer.GetUid() as key
 | 
				
			||||||
 | 
					func (ps *PeerStorage) DeletePeer(uid string) error {
 | 
				
			||||||
 | 
						err := ps.open()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer ps.close()
 | 
				
			||||||
 | 
						shakey := sha256.Sum256([]byte(uid))
 | 
				
			||||||
 | 
						key := shakey[:]
 | 
				
			||||||
 | 
						return ps.db.Update(func(txn *badger.Txn) error {
 | 
				
			||||||
 | 
							return txn.Delete(key)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LoadAllPeers function loads all Peers from a badger database
 | 
				
			||||||
 | 
					func (ps *PeerStorage) LoadAllPeers(password string) ([]*Peer, error) {
 | 
				
			||||||
 | 
						var peers []*Peer
 | 
				
			||||||
 | 
						err := ps.open()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer ps.close()
 | 
				
			||||||
 | 
						err = ps.db.View(func(txn *badger.Txn) error {
 | 
				
			||||||
 | 
							opts := badger.DefaultIteratorOptions
 | 
				
			||||||
 | 
							opts.PrefetchSize = 10
 | 
				
			||||||
 | 
							it := txn.NewIterator(opts)
 | 
				
			||||||
 | 
							defer it.Close()
 | 
				
			||||||
 | 
							for it.Rewind(); it.Valid(); it.Next() {
 | 
				
			||||||
 | 
								item := it.Item()
 | 
				
			||||||
 | 
								var sc Peer
 | 
				
			||||||
 | 
								err := item.Value(func(val []byte) error {
 | 
				
			||||||
 | 
									jsonsrv, err := meowlib.SymDecrypt(password, val)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return json.Unmarshal(jsonsrv, &sc)
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									peers = append(peers, &sc)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return peers, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LoadPeersFromUids function loads Peers with id in []Uid parameter from a badger database
 | 
				
			||||||
 | 
					func (ps *PeerStorage) LoadPeersFromUids(uids []string, password string) ([]*Peer, error) {
 | 
				
			||||||
 | 
						var peers []*Peer
 | 
				
			||||||
 | 
						err := ps.open()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer ps.close()
 | 
				
			||||||
 | 
						err = ps.db.View(func(txn *badger.Txn) error {
 | 
				
			||||||
 | 
							for _, uid := range uids {
 | 
				
			||||||
 | 
								shakey := sha256.Sum256([]byte(uid))
 | 
				
			||||||
 | 
								key := shakey[:]
 | 
				
			||||||
 | 
								item, err := txn.Get(key)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var sc Peer
 | 
				
			||||||
 | 
								err = item.Value(func(val []byte) error {
 | 
				
			||||||
 | 
									jsonsrv, err := meowlib.SymDecrypt(password, val)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return json.Unmarshal(jsonsrv, &sc)
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									peers = append(peers, &sc)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return peers, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// close a badger database
 | 
				
			||||||
 | 
					func (ps *PeerStorage) close() {
 | 
				
			||||||
 | 
						ps.db.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										249
									
								
								messages.pb.go
									
									
									
									
									
								
							
							
						
						
									
										249
									
								
								messages.pb.go
									
									
									
									
									
								
							@@ -940,10 +940,11 @@ type PackedUserMessage struct {
 | 
				
			|||||||
	sizeCache     protoimpl.SizeCache
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
	unknownFields protoimpl.UnknownFields
 | 
						unknownFields protoimpl.UnknownFields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Destination     string  `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"`                 // the peer's current conversation lookup public key
 | 
						Destination        string  `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"`                                           // the peer's current conversation lookup public key
 | 
				
			||||||
	Payload         []byte  `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`                         // the message UserMessage encrypted with the destination peer's public key
 | 
						Payload            []byte  `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`                                                   // the message UserMessage encrypted with the destination peer's public key
 | 
				
			||||||
	Signature       []byte  `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"`                     // the payload signature with the client identity private key
 | 
						Signature          []byte  `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"`                                               // the payload signature with the client identity private key
 | 
				
			||||||
	ServerTimestamp []int64 `protobuf:"varint,4,rep,packed,name=serverTimestamp,proto3" json:"serverTimestamp,omitempty"` // server time stamp, might be several in matriochka mode
 | 
						ServerTimestamp    []int64 `protobuf:"varint,4,rep,packed,name=serverTimestamp,proto3" json:"serverTimestamp,omitempty"`                           // server time stamp, might be several in matriochka mode
 | 
				
			||||||
 | 
						ServerDeliveryUuid string  `protobuf:"bytes,5,opt,name=server_delivery_uuid,json=serverDeliveryUuid,proto3" json:"server_delivery_uuid,omitempty"` // message uuid, for server delivery tracking, omitted if not delivery tracking desired
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *PackedUserMessage) Reset() {
 | 
					func (x *PackedUserMessage) Reset() {
 | 
				
			||||||
@@ -1006,6 +1007,13 @@ func (x *PackedUserMessage) GetServerTimestamp() []int64 {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *PackedUserMessage) GetServerDeliveryUuid() string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.ServerDeliveryUuid
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ConversationStatus struct {
 | 
					type ConversationStatus struct {
 | 
				
			||||||
	state         protoimpl.MessageState
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
	sizeCache     protoimpl.SizeCache
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
@@ -1875,7 +1883,7 @@ var file_messages_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x64, 0x12, 0x2d, 0x0a, 0x12, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
 | 
						0x64, 0x12, 0x2d, 0x0a, 0x12, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
 | 
				
			||||||
	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69,
 | 
						0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69,
 | 
				
			||||||
	0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
 | 
						0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
 | 
				
			||||||
	0x22, 0x97, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4d,
 | 
						0x22, 0xc9, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4d,
 | 
				
			||||||
	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
 | 
						0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
 | 
				
			||||||
	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73,
 | 
						0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73,
 | 
				
			||||||
	0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c,
 | 
						0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c,
 | 
				
			||||||
@@ -1884,124 +1892,127 @@ var file_messages_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
 | 
						0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
 | 
				
			||||||
	0x12, 0x28, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
 | 
						0x12, 0x28, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
 | 
				
			||||||
	0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65,
 | 
						0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65,
 | 
				
			||||||
	0x72, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xb6, 0x02, 0x0a, 0x12, 0x43,
 | 
						0x72, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x65,
 | 
				
			||||||
	0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75,
 | 
						0x72, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x75, 0x75,
 | 
				
			||||||
	0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
 | 
						0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
 | 
				
			||||||
	0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x5f,
 | 
						0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x55, 0x75, 0x69, 0x64, 0x22, 0xb6, 0x02, 0x0a,
 | 
				
			||||||
	0x74, 0x6f, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61,
 | 
						0x12, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61,
 | 
				
			||||||
	0x6e, 0x73, 0x77, 0x65, 0x72, 0x54, 0x6f, 0x55, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x6c,
 | 
						0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
 | 
				
			||||||
	0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01,
 | 
						0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x6e, 0x73, 0x77, 0x65,
 | 
				
			||||||
	0x28, 0x04, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63,
 | 
						0x72, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
 | 
				
			||||||
	0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
 | 
						0x0c, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x54, 0x6f, 0x55, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a,
 | 
				
			||||||
	0x04, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
 | 
						0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03,
 | 
				
			||||||
	0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
 | 
						0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x71, 0x75, 0x65,
 | 
				
			||||||
	0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x06,
 | 
						0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
 | 
				
			||||||
	0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12,
 | 
						0x04, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69,
 | 
				
			||||||
	0x3e, 0x0a, 0x10, 0x6d, 0x79, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74,
 | 
						0x76, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69,
 | 
				
			||||||
	0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x6f, 0x77,
 | 
						0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64,
 | 
				
			||||||
	0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x43, 0x61, 0x72, 0x64, 0x52,
 | 
						0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
 | 
				
			||||||
	0x0e, 0x6d, 0x79, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12,
 | 
						0x64, 0x12, 0x3e, 0x0a, 0x10, 0x6d, 0x79, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x65,
 | 
				
			||||||
	0x32, 0x0a, 0x15, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x65,
 | 
						0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65,
 | 
				
			||||||
	0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13,
 | 
						0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x43, 0x61, 0x72,
 | 
				
			||||||
	0x70, 0x65, 0x65, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
 | 
						0x64, 0x52, 0x0e, 0x6d, 0x79, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74,
 | 
				
			||||||
	0x41, 0x63, 0x6b, 0x22, 0x4b, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04,
 | 
						0x79, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x69,
 | 
				
			||||||
	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
 | 
						0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x12, 0x2e, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
 | 
						0x52, 0x13, 0x70, 0x65, 0x65, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69,
 | 
				
			||||||
	0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74,
 | 
						0x74, 0x79, 0x41, 0x63, 0x6b, 0x22, 0x4b, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12,
 | 
				
			||||||
	0x61, 0x63, 0x74, 0x43, 0x61, 0x72, 0x64, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73,
 | 
						0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
 | 
				
			||||||
	0x22, 0x93, 0x04, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
 | 
						0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20,
 | 
				
			||||||
	0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
 | 
						0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f,
 | 
				
			||||||
	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
 | 
						0x6e, 0x74, 0x61, 0x63, 0x74, 0x43, 0x61, 0x72, 0x64, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65,
 | 
				
			||||||
	0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
 | 
						0x72, 0x73, 0x22, 0x93, 0x04, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61,
 | 
				
			||||||
	0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
 | 
						0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
 | 
				
			||||||
	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61,
 | 
						0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61,
 | 
				
			||||||
	0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x33,
 | 
						0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01,
 | 
				
			||||||
	0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
 | 
						0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
 | 
				
			||||||
	0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73,
 | 
						0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04,
 | 
				
			||||||
	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61,
 | 
						0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
 | 
				
			||||||
	0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x06,
 | 
						0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
 | 
				
			||||||
	0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43,
 | 
					 | 
				
			||||||
	0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x43, 0x61, 0x72, 0x64, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74,
 | 
					 | 
				
			||||||
	0x61, 0x63, 0x74, 0x12, 0x37, 0x0a, 0x0c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x53, 0x65, 0x72, 0x76,
 | 
					 | 
				
			||||||
	0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x6f, 0x77,
 | 
					 | 
				
			||||||
	0x6c, 0x69, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x72, 0x64, 0x52, 0x0c,
 | 
					 | 
				
			||||||
	0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x05,
 | 
					 | 
				
			||||||
	0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6d, 0x65,
 | 
					 | 
				
			||||||
	0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f,
 | 
					 | 
				
			||||||
	0x75, 0x70, 0x12, 0x23, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28,
 | 
					 | 
				
			||||||
	0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65,
 | 
					 | 
				
			||||||
	0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65,
 | 
					 | 
				
			||||||
	0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b,
 | 
					 | 
				
			||||||
	0x32, 0x11, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74,
 | 
					 | 
				
			||||||
	0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61,
 | 
					 | 
				
			||||||
	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x64, 0x61, 0x74, 0x61, 0x18,
 | 
					 | 
				
			||||||
	0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x64, 0x61, 0x74, 0x61, 0x12, 0x33,
 | 
					 | 
				
			||||||
	0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01,
 | 
					 | 
				
			||||||
	0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x49, 0x6e, 0x76,
 | 
					 | 
				
			||||||
	0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74,
 | 
					 | 
				
			||||||
	0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x64, 0x61, 0x74,
 | 
					 | 
				
			||||||
	0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69,
 | 
					 | 
				
			||||||
	0x62, 0x2e, 0x56, 0x69, 0x64, 0x65, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x52, 0x09, 0x76, 0x69, 0x64,
 | 
					 | 
				
			||||||
	0x65, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x22, 0x60, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1a,
 | 
					 | 
				
			||||||
	0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
 | 
					 | 
				
			||||||
	0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69,
 | 
					 | 
				
			||||||
	0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14,
 | 
					 | 
				
			||||||
	0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63,
 | 
					 | 
				
			||||||
	0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01,
 | 
					 | 
				
			||||||
	0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x74, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61,
 | 
					 | 
				
			||||||
	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
 | 
					 | 
				
			||||||
	0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69,
 | 
					 | 
				
			||||||
	0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69,
 | 
					 | 
				
			||||||
	0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64,
 | 
					 | 
				
			||||||
	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75,
 | 
					 | 
				
			||||||
	0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x04,
 | 
					 | 
				
			||||||
	0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x61, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x22, 0x9a,
 | 
					 | 
				
			||||||
	0x03, 0x0a, 0x09, 0x44, 0x62, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08,
 | 
					 | 
				
			||||||
	0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
 | 
					 | 
				
			||||||
	0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
 | 
					 | 
				
			||||||
	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04,
 | 
					 | 
				
			||||||
	0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
 | 
					 | 
				
			||||||
	0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
 | 
					 | 
				
			||||||
	0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65,
 | 
						0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65,
 | 
				
			||||||
	0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73,
 | 
						0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73,
 | 
				
			||||||
	0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74,
 | 
						0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74,
 | 
				
			||||||
	0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62,
 | 
						0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62,
 | 
				
			||||||
	0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x43, 0x61, 0x72, 0x64, 0x52, 0x07, 0x63, 0x6f,
 | 
						0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x43, 0x61, 0x72, 0x64, 0x52, 0x07, 0x63, 0x6f,
 | 
				
			||||||
	0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x06,
 | 
						0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x37, 0x0a, 0x0c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x53, 0x65,
 | 
				
			||||||
	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x47,
 | 
						0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65,
 | 
				
			||||||
	0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x66,
 | 
						0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x72, 0x64,
 | 
				
			||||||
	0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52,
 | 
						0x52, 0x0c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x24,
 | 
				
			||||||
	0x09, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x3c, 0x0a, 0x10, 0x63, 0x75,
 | 
						0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
 | 
				
			||||||
	0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08,
 | 
						0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67,
 | 
				
			||||||
	0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x4c,
 | 
						0x72, 0x6f, 0x75, 0x70, 0x12, 0x23, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20,
 | 
				
			||||||
	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
 | 
						0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x46, 0x69,
 | 
				
			||||||
	0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x64,
 | 
						0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0f, 0x63, 0x75, 0x72,
 | 
				
			||||||
	0x61, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x64, 0x61,
 | 
						0x72, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01,
 | 
				
			||||||
	0x74, 0x61, 0x12, 0x33, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
 | 
						0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x4c, 0x6f, 0x63,
 | 
				
			||||||
	0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62,
 | 
						0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x6f,
 | 
				
			||||||
	0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76,
 | 
						0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x64, 0x61, 0x74,
 | 
				
			||||||
	0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18,
 | 
						0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x64, 0x61, 0x74, 0x61,
 | 
				
			||||||
	0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0xaa, 0x01, 0x0a, 0x09,
 | 
						0x12, 0x33, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c,
 | 
				
			||||||
	0x56, 0x69, 0x64, 0x65, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c,
 | 
						0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x49,
 | 
				
			||||||
	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x72,
 | 
						0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74,
 | 
				
			||||||
	0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12,
 | 
						0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x64,
 | 
				
			||||||
	0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
 | 
						0x61, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6f, 0x77,
 | 
				
			||||||
	0x04, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x0b, 0x63,
 | 
						0x6c, 0x69, 0x62, 0x2e, 0x56, 0x69, 0x64, 0x65, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x52, 0x09, 0x76,
 | 
				
			||||||
	0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
 | 
						0x69, 0x64, 0x65, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x22, 0x60, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65,
 | 
				
			||||||
	0x32, 0x18, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x56, 0x69, 0x64, 0x65, 0x6f,
 | 
						0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
 | 
				
			||||||
	0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64,
 | 
						0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04,
 | 
				
			||||||
	0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x64, 0x69, 0x61,
 | 
						0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
 | 
				
			||||||
	0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65,
 | 
						0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
 | 
				
			||||||
	0x64, 0x69, 0x61, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x62, 0x0a, 0x0f, 0x56, 0x69, 0x64, 0x65,
 | 
						0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04,
 | 
				
			||||||
	0x6f, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x75,
 | 
						0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x74, 0x0a, 0x08, 0x4c, 0x6f,
 | 
				
			||||||
	0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75,
 | 
						0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01,
 | 
				
			||||||
	0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x65,
 | 
						0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61,
 | 
				
			||||||
	0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x68, 0x61,
 | 
						0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61,
 | 
				
			||||||
	0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
 | 
						0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74,
 | 
				
			||||||
	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x21, 0x5a, 0x1f,
 | 
						0x75, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69,
 | 
				
			||||||
	0x66, 0x6f, 0x72, 0x67, 0x65, 0x2e, 0x72, 0x65, 0x64, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x6c, 0x69,
 | 
						0x74, 0x75, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65,
 | 
				
			||||||
	0x6e, 0x6b, 0x2f, 0x79, 0x76, 0x65, 0x73, 0x2f, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x62,
 | 
						0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x61, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65,
 | 
				
			||||||
	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
						0x22, 0x9a, 0x03, 0x0a, 0x09, 0x44, 0x62, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a,
 | 
				
			||||||
 | 
						0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
 | 
				
			||||||
 | 
						0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79,
 | 
				
			||||||
 | 
						0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12,
 | 
				
			||||||
 | 
						0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61,
 | 
				
			||||||
 | 
						0x74, 0x61, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01,
 | 
				
			||||||
 | 
						0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e,
 | 
				
			||||||
 | 
						0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52,
 | 
				
			||||||
 | 
						0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61,
 | 
				
			||||||
 | 
						0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c,
 | 
				
			||||||
 | 
						0x69, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x43, 0x61, 0x72, 0x64, 0x52, 0x07,
 | 
				
			||||||
 | 
						0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70,
 | 
				
			||||||
 | 
						0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62,
 | 
				
			||||||
 | 
						0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1d, 0x0a,
 | 
				
			||||||
 | 
						0x0a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28,
 | 
				
			||||||
 | 
						0x09, 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x3c, 0x0a, 0x10,
 | 
				
			||||||
 | 
						0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
 | 
				
			||||||
 | 
						0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62,
 | 
				
			||||||
 | 
						0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65,
 | 
				
			||||||
 | 
						0x6e, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70,
 | 
				
			||||||
 | 
						0x70, 0x64, 0x61, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70,
 | 
				
			||||||
 | 
						0x64, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69,
 | 
				
			||||||
 | 
						0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c,
 | 
				
			||||||
 | 
						0x69, 0x62, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69,
 | 
				
			||||||
 | 
						0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f,
 | 
				
			||||||
 | 
						0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0xaa, 0x01,
 | 
				
			||||||
 | 
						0x0a, 0x09, 0x56, 0x69, 0x64, 0x65, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x75,
 | 
				
			||||||
 | 
						0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a,
 | 
				
			||||||
 | 
						0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6f,
 | 
				
			||||||
 | 
						0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20,
 | 
				
			||||||
 | 
						0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a,
 | 
				
			||||||
 | 
						0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03,
 | 
				
			||||||
 | 
						0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x56, 0x69, 0x64,
 | 
				
			||||||
 | 
						0x65, 0x6f, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x0b, 0x63, 0x72,
 | 
				
			||||||
 | 
						0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x64,
 | 
				
			||||||
 | 
						0x69, 0x61, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a,
 | 
				
			||||||
 | 
						0x6d, 0x65, 0x64, 0x69, 0x61, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x62, 0x0a, 0x0f, 0x56, 0x69,
 | 
				
			||||||
 | 
						0x64, 0x65, 0x6f, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x1a, 0x0a,
 | 
				
			||||||
 | 
						0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
 | 
				
			||||||
 | 
						0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61,
 | 
				
			||||||
 | 
						0x72, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73,
 | 
				
			||||||
 | 
						0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65,
 | 
				
			||||||
 | 
						0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x21,
 | 
				
			||||||
 | 
						0x5a, 0x1f, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x2e, 0x72, 0x65, 0x64, 0x72, 0x6f, 0x6f, 0x6d, 0x2e,
 | 
				
			||||||
 | 
						0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x79, 0x76, 0x65, 0x73, 0x2f, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69,
 | 
				
			||||||
 | 
						0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,9 +37,9 @@ message Invitation {
 | 
				
			|||||||
// structure for requesting incoming messages
 | 
					// structure for requesting incoming messages
 | 
				
			||||||
message ConversationRequest {  
 | 
					message ConversationRequest {  
 | 
				
			||||||
    string lookup_key = 1; // lookup key for a conversation
 | 
					    string lookup_key = 1; // lookup key for a conversation
 | 
				
			||||||
    // removed string lastServerUuidOK = 2;  //  Last Server message UUID received (send me all after that one)
 | 
					    bool delivery_request = 2; // look for for delivery tracking, key is implicit, "from" field is used
 | 
				
			||||||
    int64 send_timestamp = 2;
 | 
					    int64 send_timestamp = 3;
 | 
				
			||||||
    string lookup_signature = 3; // prove that I own the private key by signing that block
 | 
					    string lookup_signature = 4; // prove that I own the private key by signing that block
 | 
				
			||||||
} 
 | 
					} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message Meet {
 | 
					message Meet {
 | 
				
			||||||
@@ -136,6 +136,7 @@ message PackedUserMessage {
 | 
				
			|||||||
    bytes payload=2;  // the message UserMessage encrypted with the destination peer's public key
 | 
					    bytes payload=2;  // the message UserMessage encrypted with the destination peer's public key
 | 
				
			||||||
	bytes signature=3; // the payload signature with the client identity private key
 | 
						bytes signature=3; // the payload signature with the client identity private key
 | 
				
			||||||
    repeated int64 serverTimestamp=4; // server time stamp, might be several in matriochka mode
 | 
					    repeated int64 serverTimestamp=4; // server time stamp, might be several in matriochka mode
 | 
				
			||||||
 | 
					    string server_delivery_uuid=5; // message uuid, for server delivery tracking, omitted if not delivery tracking desired
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message ConversationStatus {
 | 
					message ConversationStatus {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,8 +119,13 @@ func (r *RedisRouter) storeMessage(msg *meowlib.ToServerMessage) (*meowlib.FromS
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		r.Client.ZAdd(usrmsg.Destination, redis.Z{Score: float64(time.Now().Unix()), Member: out})
 | 
							r.Client.ZAdd("msg:"+usrmsg.Destination, redis.Z{Score: float64(time.Now().Unix()), Member: out})
 | 
				
			||||||
		r.Client.Publish("ch:"+usrmsg.Destination, "!")
 | 
							r.Client.Publish("msgch:"+usrmsg.Destination, "!")
 | 
				
			||||||
 | 
							// if delivery tracking resquested, store the uid for the sender's key in delivery tracking
 | 
				
			||||||
 | 
							if usrmsg.ServerDeliveryUuid != "" {
 | 
				
			||||||
 | 
								r.Client.SAdd("dvyrq:"+usrmsg.ServerDeliveryUuid, redis.Z{Score: float64(time.Now().Unix()), Member: msg.From})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	from_server.UuidAck = msg.Uuid
 | 
						from_server.UuidAck = msg.Uuid
 | 
				
			||||||
	return &from_server, nil
 | 
						return &from_server, nil
 | 
				
			||||||
@@ -134,13 +139,15 @@ func (r *RedisRouter) checkForMessage(msg *meowlib.ToServerMessage) (*meowlib.Fr
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// todo check pull requests signature
 | 
				
			||||||
 | 
						// iterate over pull requests
 | 
				
			||||||
	for _, rq := range msg.PullRequest {
 | 
						for _, rq := range msg.PullRequest {
 | 
				
			||||||
		// get messages from redis
 | 
							// get messages from redis
 | 
				
			||||||
		msgcnt, err := r.Client.ZCount(rq.LookupKey, "-inf", "+inf").Result()
 | 
							msgcnt, err := r.Client.ZCount("msg:"+rq.LookupKey, "-inf", "+inf").Result()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		res, err := r.Client.ZPopMin(rq.LookupKey, msgcnt).Result()
 | 
							res, err := r.Client.ZPopMin("msg:"+rq.LookupKey, msgcnt).Result()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -156,8 +163,21 @@ func (r *RedisRouter) checkForMessage(msg *meowlib.ToServerMessage) (*meowlib.Fr
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			// add server timestamp
 | 
								// add server timestamp
 | 
				
			||||||
			usrmsg.ServerTimestamp = append(usrmsg.ServerTimestamp, int64(redismsg.Score))
 | 
								usrmsg.ServerTimestamp = append(usrmsg.ServerTimestamp, int64(redismsg.Score))
 | 
				
			||||||
 | 
					 | 
				
			||||||
			from_server.Chat = append(from_server.Chat, &usrmsg)
 | 
								from_server.Chat = append(from_server.Chat, &usrmsg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// if delivery requested, create, store and publish delivery message
 | 
				
			||||||
 | 
								res, err := r.Client.SPop("msg:" + usrmsg.ServerDeliveryUuid).Result()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if err != redis.Nil { // exit only if real error
 | 
				
			||||||
 | 
										return nil, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err != redis.Nil {
 | 
				
			||||||
 | 
									// create a delivery record
 | 
				
			||||||
 | 
									r.Client.ZAdd("dvy:"+res, redis.Z{Score: float64(time.Now().Unix()), Member: usrmsg.ServerDeliveryUuid})
 | 
				
			||||||
 | 
									// publish it in case of listener
 | 
				
			||||||
 | 
									r.Client.Publish("dvych:"+usrmsg.ServerDeliveryUuid, "!")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// if no messages check for invitationanswer payload
 | 
							// if no messages check for invitationanswer payload
 | 
				
			||||||
		if msgcnt == 0 {
 | 
							if msgcnt == 0 {
 | 
				
			||||||
@@ -182,7 +202,7 @@ func (r *RedisRouter) checkForMessage(msg *meowlib.ToServerMessage) (*meowlib.Fr
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func goSubscribeAndListen(client *redis.Client, key string, messages chan<- string, wg *sync.WaitGroup, done <-chan struct{}) {
 | 
					func goSubscribeAndListen(client *redis.Client, key string, messages chan<- string, wg *sync.WaitGroup, done <-chan struct{}) {
 | 
				
			||||||
	defer wg.Done()
 | 
						defer wg.Done()
 | 
				
			||||||
	pubsub := client.Subscribe("ch:" + key)
 | 
						pubsub := client.Subscribe("msgch:" + key)
 | 
				
			||||||
	defer pubsub.Close()
 | 
						defer pubsub.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create a new channel for the messages from this subscription
 | 
						// Create a new channel for the messages from this subscription
 | 
				
			||||||
@@ -218,6 +238,7 @@ func (r *RedisRouter) subscribe(msg *meowlib.ToServerMessage, timeout int) (*meo
 | 
				
			|||||||
	var wg sync.WaitGroup
 | 
						var wg sync.WaitGroup
 | 
				
			||||||
	done := make(chan struct{})
 | 
						done := make(chan struct{})
 | 
				
			||||||
	// extract lookup keys and subscribe
 | 
						// extract lookup keys and subscribe
 | 
				
			||||||
 | 
						// iterate over pull requests
 | 
				
			||||||
	for _, rq := range msg.PullRequest {
 | 
						for _, rq := range msg.PullRequest {
 | 
				
			||||||
		wg.Add(1)
 | 
							wg.Add(1)
 | 
				
			||||||
		// subscribe to the lookup key
 | 
							// subscribe to the lookup key
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user