messages.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package protocol
  2. import "io"
  3. type request struct {
  4. name string
  5. offset uint64
  6. size uint32
  7. hash []byte
  8. }
  9. type header struct {
  10. version int
  11. msgID int
  12. msgType int
  13. }
  14. func encodeHeader(h header) uint32 {
  15. return uint32(h.version&0xf)<<28 +
  16. uint32(h.msgID&0xfff)<<16 +
  17. uint32(h.msgType&0xff)<<8
  18. }
  19. func decodeHeader(u uint32) header {
  20. return header{
  21. version: int(u>>28) & 0xf,
  22. msgID: int(u>>16) & 0xfff,
  23. msgType: int(u>>8) & 0xff,
  24. }
  25. }
  26. func (w *marshalWriter) writeHeader(h header) {
  27. w.writeUint32(encodeHeader(h))
  28. }
  29. func (w *marshalWriter) writeIndex(idx []FileInfo) {
  30. w.writeUint32(uint32(len(idx)))
  31. for _, f := range idx {
  32. w.writeString(f.Name)
  33. w.writeUint32(f.Flags)
  34. w.writeUint64(uint64(f.Modified))
  35. w.writeUint32(uint32(len(f.Blocks)))
  36. for _, b := range f.Blocks {
  37. w.writeUint32(b.Length)
  38. w.writeBytes(b.Hash)
  39. }
  40. }
  41. }
  42. func WriteIndex(w io.Writer, idx []FileInfo) (int, error) {
  43. mw := marshalWriter{w, 0, nil}
  44. mw.writeIndex(idx)
  45. return mw.tot, mw.err
  46. }
  47. func (w *marshalWriter) writeRequest(r request) {
  48. w.writeString(r.name)
  49. w.writeUint64(r.offset)
  50. w.writeUint32(r.size)
  51. w.writeBytes(r.hash)
  52. }
  53. func (w *marshalWriter) writeResponse(data []byte) {
  54. w.writeBytes(data)
  55. }
  56. func (r *marshalReader) readHeader() header {
  57. return decodeHeader(r.readUint32())
  58. }
  59. func (r *marshalReader) readIndex() []FileInfo {
  60. nfiles := r.readUint32()
  61. files := make([]FileInfo, nfiles)
  62. for i := range files {
  63. files[i].Name = r.readString()
  64. files[i].Flags = r.readUint32()
  65. files[i].Modified = int64(r.readUint64())
  66. nblocks := r.readUint32()
  67. blocks := make([]BlockInfo, nblocks)
  68. for j := range blocks {
  69. blocks[j].Length = r.readUint32()
  70. blocks[j].Hash = r.readBytes()
  71. }
  72. files[i].Blocks = blocks
  73. }
  74. return files
  75. }
  76. func ReadIndex(r io.Reader) ([]FileInfo, error) {
  77. mr := marshalReader{r, 0, nil}
  78. idx := mr.readIndex()
  79. return idx, mr.err
  80. }
  81. func (r *marshalReader) readRequest() request {
  82. var req request
  83. req.name = r.readString()
  84. req.offset = r.readUint64()
  85. req.size = r.readUint32()
  86. req.hash = r.readBytes()
  87. return req
  88. }
  89. func (r *marshalReader) readResponse() []byte {
  90. return r.readBytes()
  91. }