syntax = "proto3"; package protocol; import "repos/protobuf/gogoproto/gogo.proto"; option (gogoproto.goproto_getters_all) = false; option (gogoproto.sizer_all) = false; option (gogoproto.protosizer_all) = true; option (gogoproto.goproto_enum_stringer_all) = true; option (gogoproto.goproto_enum_prefix_all) = false; option (gogoproto.goproto_unkeyed_all) = false; option (gogoproto.goproto_unrecognized_all) = false; option (gogoproto.goproto_sizecache_all) = false; // --- Pre-auth --- message Hello { string device_name = 1; string client_name = 2; string client_version = 3; } // --- Header --- message Header { MessageType type = 1; MessageCompression compression = 2; } enum MessageType { CLUSTER_CONFIG = 0 [(gogoproto.enumvalue_customname) = "messageTypeClusterConfig"]; INDEX = 1 [(gogoproto.enumvalue_customname) = "messageTypeIndex"]; INDEX_UPDATE = 2 [(gogoproto.enumvalue_customname) = "messageTypeIndexUpdate"]; REQUEST = 3 [(gogoproto.enumvalue_customname) = "messageTypeRequest"]; RESPONSE = 4 [(gogoproto.enumvalue_customname) = "messageTypeResponse"]; DOWNLOAD_PROGRESS = 5 [(gogoproto.enumvalue_customname) = "messageTypeDownloadProgress"]; PING = 6 [(gogoproto.enumvalue_customname) = "messageTypePing"]; CLOSE = 7 [(gogoproto.enumvalue_customname) = "messageTypeClose"]; } enum MessageCompression { NONE = 0 [(gogoproto.enumvalue_customname) = "MessageCompressionNone"]; LZ4 = 1 [(gogoproto.enumvalue_customname) = "MessageCompressionLZ4"]; } // --- Actual messages --- // Cluster Config message ClusterConfig { repeated Folder folders = 1 [(gogoproto.nullable) = false]; } message Folder { string id = 1 [(gogoproto.customname) = "ID"]; string label = 2; bool read_only = 3; bool ignore_permissions = 4; bool ignore_delete = 5; bool disable_temp_indexes = 6; bool paused = 7; repeated Device devices = 16 [(gogoproto.nullable) = false]; } message Device { bytes id = 1 [(gogoproto.customname) = "ID", (gogoproto.customtype) = "DeviceID", (gogoproto.nullable) = false]; string name = 2; repeated string addresses = 3; Compression compression = 4; string cert_name = 5; int64 max_sequence = 6; bool introducer = 7; uint64 index_id = 8 [(gogoproto.customname) = "IndexID", (gogoproto.customtype) = "IndexID", (gogoproto.nullable) = false]; bool skip_introduction_removals = 9; } enum Compression { METADATA = 0 [(gogoproto.enumvalue_customname) = "CompressMetadata"]; NEVER = 1 [(gogoproto.enumvalue_customname) = "CompressNever"]; ALWAYS = 2 [(gogoproto.enumvalue_customname) = "CompressAlways"]; } // Index and Index Update message Index { string folder = 1; repeated FileInfo files = 2 [(gogoproto.nullable) = false]; } message IndexUpdate { string folder = 1; repeated FileInfo files = 2 [(gogoproto.nullable) = false]; } message FileInfo { option (gogoproto.goproto_stringer) = false; // The field ordering here optimizes for struct size / alignment -- // large types come before smaller ones. string name = 1; int64 size = 3; int64 modified_s = 5; uint64 modified_by = 12 [(gogoproto.customtype) = "ShortID", (gogoproto.nullable) = false]; Vector version = 9 [(gogoproto.nullable) = false]; int64 sequence = 10; repeated BlockInfo blocks = 16 [(gogoproto.nullable) = false]; string symlink_target = 17; bytes blocks_hash = 18; FileInfoType type = 2; uint32 permissions = 4; int32 modified_ns = 11; int32 block_size = 13 [(gogoproto.customname) = "RawBlockSize"]; // The local_flags fields stores flags that are relevant to the local // host only. It is not part of the protocol, doesn't get sent or // received (we make sure to zero it), nonetheless we need it on our // struct and to be able to serialize it to/from the database. uint32 local_flags = 1000; // The version_hash is an implementation detail and not part of the wire // format. bytes version_hash = 1001; bool deleted = 6; bool invalid = 7 [(gogoproto.customname) = "RawInvalid"]; bool no_permissions = 8; } enum FileInfoType { FILE = 0 [(gogoproto.enumvalue_customname) = "FileInfoTypeFile"]; DIRECTORY = 1 [(gogoproto.enumvalue_customname) = "FileInfoTypeDirectory"]; SYMLINK_FILE = 2 [(gogoproto.enumvalue_customname) = "FileInfoTypeDeprecatedSymlinkFile", deprecated = true]; SYMLINK_DIRECTORY = 3 [(gogoproto.enumvalue_customname) = "FileInfoTypeDeprecatedSymlinkDirectory", deprecated = true]; SYMLINK = 4 [(gogoproto.enumvalue_customname) = "FileInfoTypeSymlink"]; } message BlockInfo { option (gogoproto.goproto_stringer) = false; bytes hash = 3; int64 offset = 1; int32 size = 2; uint32 weak_hash = 4; } message Vector { repeated Counter counters = 1 [(gogoproto.nullable) = false]; } message Counter { uint64 id = 1 [(gogoproto.customname) = "ID", (gogoproto.customtype) = "ShortID", (gogoproto.nullable) = false]; uint64 value = 2; } // Request message Request { int32 id = 1 [(gogoproto.customname) = "ID"]; string folder = 2; string name = 3; int64 offset = 4; int32 size = 5; bytes hash = 6; bool from_temporary = 7; uint32 weak_hash = 8; } // Response message Response { int32 id = 1 [(gogoproto.customname) = "ID"]; bytes data = 2; ErrorCode code = 3; } enum ErrorCode { NO_ERROR = 0 [(gogoproto.enumvalue_customname) = "ErrorCodeNoError"]; GENERIC = 1 [(gogoproto.enumvalue_customname) = "ErrorCodeGeneric"]; NO_SUCH_FILE = 2 [(gogoproto.enumvalue_customname) = "ErrorCodeNoSuchFile"]; INVALID_FILE = 3 [(gogoproto.enumvalue_customname) = "ErrorCodeInvalidFile"]; } // DownloadProgress message DownloadProgress { string folder = 1; repeated FileDownloadProgressUpdate updates = 2 [(gogoproto.nullable) = false]; } message FileDownloadProgressUpdate { FileDownloadProgressUpdateType update_type = 1; string name = 2; Vector version = 3 [(gogoproto.nullable) = false]; repeated int32 block_indexes = 4 [packed=false]; int32 block_size = 5; } enum FileDownloadProgressUpdateType { APPEND = 0 [(gogoproto.enumvalue_customname) = "UpdateTypeAppend"]; FORGET = 1 [(gogoproto.enumvalue_customname) = "UpdateTypeForget"]; } // Ping message Ping { } // Close message Close { string reason = 1; }