diff --git a/internal/protocol/message.go b/internal/protocol/message.go index ae04a9da..e0c66b9d 100644 --- a/internal/protocol/message.go +++ b/internal/protocol/message.go @@ -21,8 +21,10 @@ package protocol import "fmt" type IndexMessage struct { - Folder string // max:64 - Files []FileInfo + Folder string // max:64 + Files []FileInfo + Flags uint32 + Options []Option // max:64 } type FileInfo struct { @@ -150,14 +152,18 @@ func (b BlockInfo) String() string { } type RequestMessage struct { - Folder string // max:64 - Name string // max:8192 - Offset uint64 - Size uint32 + Folder string // max:64 + Name string // max:8192 + Offset uint64 + Size uint32 + Hash []byte // max:64 + Flags uint32 + Options []Option // max:64 } type ResponseMessage struct { - Data []byte + Data []byte + Error uint32 } type ClusterConfigMessage struct { @@ -194,6 +200,7 @@ type Option struct { type CloseMessage struct { Reason string // max:1024 + Code uint32 } type EmptyMessage struct{} diff --git a/internal/protocol/message_xdr.go b/internal/protocol/message_xdr.go index 948e63c3..da13111c 100644 --- a/internal/protocol/message_xdr.go +++ b/internal/protocol/message_xdr.go @@ -30,11 +30,21 @@ IndexMessage Structure: \ Zero or more FileInfo Structures \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Flags | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Number of Options | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/ / +\ Zero or more Option Structures \ +/ / ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ struct IndexMessage { string Folder<64>; FileInfo Files<>; + unsigned int Flags; + Option Options<64>; } */ @@ -75,6 +85,17 @@ func (o IndexMessage) encodeXDR(xw *xdr.Writer) (int, error) { return xw.Tot(), err } } + xw.WriteUint32(o.Flags) + if l := len(o.Options); l > 64 { + return xw.Tot(), xdr.ElementSizeExceeded("Options", l, 64) + } + xw.WriteUint32(uint32(len(o.Options))) + for i := range o.Options { + _, err := o.Options[i].encodeXDR(xw) + if err != nil { + return xw.Tot(), err + } + } return xw.Tot(), xw.Error() } @@ -96,6 +117,15 @@ func (o *IndexMessage) decodeXDR(xr *xdr.Reader) error { for i := range o.Files { (&o.Files[i]).decodeXDR(xr) } + o.Flags = xr.ReadUint32() + _OptionsSize := int(xr.ReadUint32()) + if _OptionsSize > 64 { + return xdr.ElementSizeExceeded("Options", _OptionsSize, 64) + } + o.Options = make([]Option, _OptionsSize) + for i := range o.Options { + (&o.Options[i]).decodeXDR(xr) + } return xr.Error() } @@ -412,6 +442,20 @@ RequestMessage Structure: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Size | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Length of Hash | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/ / +\ Hash (variable length) \ +/ / ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Flags | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Number of Options | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/ / +\ Zero or more Option Structures \ +/ / ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ struct RequestMessage { @@ -419,6 +463,9 @@ struct RequestMessage { string Name<8192>; unsigned hyper Offset; unsigned int Size; + opaque Hash<64>; + unsigned int Flags; + Option Options<64>; } */ @@ -458,6 +505,21 @@ func (o RequestMessage) encodeXDR(xw *xdr.Writer) (int, error) { xw.WriteString(o.Name) xw.WriteUint64(o.Offset) xw.WriteUint32(o.Size) + if l := len(o.Hash); l > 64 { + return xw.Tot(), xdr.ElementSizeExceeded("Hash", l, 64) + } + xw.WriteBytes(o.Hash) + xw.WriteUint32(o.Flags) + if l := len(o.Options); l > 64 { + return xw.Tot(), xdr.ElementSizeExceeded("Options", l, 64) + } + xw.WriteUint32(uint32(len(o.Options))) + for i := range o.Options { + _, err := o.Options[i].encodeXDR(xw) + if err != nil { + return xw.Tot(), err + } + } return xw.Tot(), xw.Error() } @@ -477,6 +539,16 @@ func (o *RequestMessage) decodeXDR(xr *xdr.Reader) error { o.Name = xr.ReadStringMax(8192) o.Offset = xr.ReadUint64() o.Size = xr.ReadUint32() + o.Hash = xr.ReadBytesMax(64) + o.Flags = xr.ReadUint32() + _OptionsSize := int(xr.ReadUint32()) + if _OptionsSize > 64 { + return xdr.ElementSizeExceeded("Options", _OptionsSize, 64) + } + o.Options = make([]Option, _OptionsSize) + for i := range o.Options { + (&o.Options[i]).decodeXDR(xr) + } return xr.Error() } @@ -493,10 +565,13 @@ ResponseMessage Structure: \ Data (variable length) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Error | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ struct ResponseMessage { opaque Data<>; + unsigned int Error; } */ @@ -527,6 +602,7 @@ func (o ResponseMessage) AppendXDR(bs []byte) ([]byte, error) { func (o ResponseMessage) encodeXDR(xw *xdr.Writer) (int, error) { xw.WriteBytes(o.Data) + xw.WriteUint32(o.Error) return xw.Tot(), xw.Error() } @@ -543,6 +619,7 @@ func (o *ResponseMessage) UnmarshalXDR(bs []byte) error { func (o *ResponseMessage) decodeXDR(xr *xdr.Reader) error { o.Data = xr.ReadBytes() + o.Error = xr.ReadUint32() return xr.Error() } @@ -940,10 +1017,13 @@ CloseMessage Structure: \ Reason (variable length) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Code | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ struct CloseMessage { string Reason<1024>; + unsigned int Code; } */ @@ -977,6 +1057,7 @@ func (o CloseMessage) encodeXDR(xw *xdr.Writer) (int, error) { return xw.Tot(), xdr.ElementSizeExceeded("Reason", l, 1024) } xw.WriteString(o.Reason) + xw.WriteUint32(o.Code) return xw.Tot(), xw.Error() } @@ -993,6 +1074,7 @@ func (o *CloseMessage) UnmarshalXDR(bs []byte) error { func (o *CloseMessage) decodeXDR(xr *xdr.Reader) error { o.Reason = xr.ReadStringMax(1024) + o.Code = xr.ReadUint32() return xr.Error() } diff --git a/internal/protocol/protocol.go b/internal/protocol/protocol.go index a6a4b8b4..e65d5e72 100644 --- a/internal/protocol/protocol.go +++ b/internal/protocol/protocol.go @@ -187,7 +187,10 @@ func (c *rawConnection) Index(folder string, idx []FileInfo) error { default: } c.idxMut.Lock() - c.send(-1, messageTypeIndex, IndexMessage{folder, idx}) + c.send(-1, messageTypeIndex, IndexMessage{ + Folder: folder, + Files: idx, + }) c.idxMut.Unlock() return nil } @@ -200,7 +203,10 @@ func (c *rawConnection) IndexUpdate(folder string, idx []FileInfo) error { default: } c.idxMut.Lock() - c.send(-1, messageTypeIndexUpdate, IndexMessage{folder, idx}) + c.send(-1, messageTypeIndexUpdate, IndexMessage{ + Folder: folder, + Files: idx, + }) c.idxMut.Unlock() return nil } @@ -222,7 +228,12 @@ func (c *rawConnection) Request(folder string, name string, offset int64, size i c.awaiting[id] = rc c.awaitingMut.Unlock() - ok := c.send(id, messageTypeRequest, RequestMessage{folder, name, uint64(offset), uint32(size)}) + ok := c.send(id, messageTypeRequest, RequestMessage{ + Folder: folder, + Name: name, + Offset: uint64(offset), + Size: uint32(size), + }) if !ok { return nil, ErrClosed } @@ -455,7 +466,9 @@ func (c *rawConnection) handleIndexUpdate(im IndexMessage) { func (c *rawConnection) handleRequest(msgID int, req RequestMessage) { data, _ := c.receiver.Request(c.id, req.Folder, req.Name, int64(req.Offset), int(req.Size)) - c.send(msgID, messageTypeResponse, ResponseMessage{data}) + c.send(msgID, messageTypeResponse, ResponseMessage{ + Data: data, + }) } func (c *rawConnection) handleResponse(msgID int, resp ResponseMessage) {