]> git.r.bdr.sh - rbdr/mobius/blame - hotline/transfer.go
Merge pull request #39 from benabernathy/mobius_38
[rbdr/mobius] / hotline / transfer.go
CommitLineData
6988a057
JH
1package hotline
2
3import (
165b7ac9 4 "bufio"
6988a057
JH
5 "bytes"
6 "encoding/binary"
7 "errors"
85767504 8 "io"
6988a057
JH
9)
10
df2735b2 11type transfer struct {
6988a057
JH
12 Protocol [4]byte // "HTXF" 0x48545846
13 ReferenceNumber [4]byte // Unique ID generated for the transfer
14 DataSize [4]byte // File size
15 RSVD [4]byte // Not implemented in Hotline Protocol
16}
17
df2735b2 18var HTXF = [4]byte{0x48, 0x54, 0x58, 0x46} // (HTXF) is the only supported transfer protocol
6988a057 19
df2735b2
JH
20func (tf *transfer) Write(b []byte) (int, error) {
21 if err := binary.Read(bytes.NewReader(b), binary.BigEndian, tf); err != nil {
22 return 0, err
6988a057
JH
23 }
24
df2735b2
JH
25 if tf.Protocol != HTXF {
26 return 0, errors.New("invalid protocol")
6988a057
JH
27 }
28
df2735b2 29 return len(b), nil
6988a057 30}
85767504 31
165b7ac9 32const fileCopyBufSize = 524288 // 512k
85767504
JH
33func receiveFile(conn io.Reader, targetFile io.Writer, resForkFile io.Writer) error {
34 ffhBuf := make([]byte, 24)
ba29c43b 35 if _, err := io.ReadFull(conn, ffhBuf); err != nil {
85767504
JH
36 return err
37 }
38
39 var ffh FlatFileHeader
40 err := binary.Read(bytes.NewReader(ffhBuf), binary.BigEndian, &ffh)
41 if err != nil {
42 return err
43 }
44
45 ffifhBuf := make([]byte, 16)
ba29c43b 46 if _, err := io.ReadFull(conn, ffifhBuf); err != nil {
85767504
JH
47 return err
48 }
49
50 var ffifh FlatFileInformationForkHeader
51 err = binary.Read(bytes.NewReader(ffifhBuf), binary.BigEndian, &ffifh)
52 if err != nil {
53 return err
54 }
55
56 var ffif FlatFileInformationFork
57
58 dataLen := binary.BigEndian.Uint32(ffifh.DataSize[:])
59 ffifBuf := make([]byte, dataLen)
ba29c43b 60 if _, err := io.ReadFull(conn, ffifBuf); err != nil {
85767504
JH
61 return err
62 }
63 if err := ffif.UnmarshalBinary(ffifBuf); err != nil {
64 return err
65 }
66
67 var ffdfh FlatFileDataForkHeader
68 ffdfhBuf := make([]byte, 16)
ba29c43b 69 if _, err := io.ReadFull(conn, ffdfhBuf); err != nil {
85767504
JH
70 return err
71 }
72 err = binary.Read(bytes.NewReader(ffdfhBuf), binary.BigEndian, &ffdfh)
73 if err != nil {
74 return err
75 }
76
77 // this will be zero if the file only has a resource fork
78 fileSize := int(binary.BigEndian.Uint32(ffdfh.DataSize[:]))
79
165b7ac9
JH
80 bw := bufio.NewWriterSize(targetFile, fileCopyBufSize)
81 _, err = io.CopyN(bw, conn, int64(fileSize))
85767504
JH
82 if err != nil {
83 return err
84 }
165b7ac9
JH
85 if err := bw.Flush(); err != nil {
86 return err
87 }
85767504
JH
88
89 if ffh.ForkCount == [2]byte{0, 3} {
90 var resForkHeader FlatFileDataForkHeader
ba29c43b 91 if _, err := io.ReadFull(conn, resForkHeader.ForkType[:]); err != nil {
85767504
JH
92 return err
93 }
ba29c43b
JH
94
95 if _, err := io.ReadFull(conn, resForkHeader.CompressionType[:]); err != nil {
85767504
JH
96 return err
97 }
98
ba29c43b
JH
99 if _, err := io.ReadFull(conn, resForkHeader.RSVD[:]); err != nil {
100 return err
101 }
102
103 if _, err := io.ReadFull(conn, resForkHeader.DataSize[:]); err != nil {
104 return err
105 }
85767504 106
165b7ac9 107 bw = bufio.NewWriterSize(resForkFile, fileCopyBufSize)
ba29c43b 108 _, err = io.CopyN(resForkFile, conn, int64(binary.BigEndian.Uint32(resForkHeader.DataSize[:])))
85767504
JH
109 if err != nil {
110 return err
111 }
165b7ac9
JH
112 if err := bw.Flush(); err != nil {
113 return err
114 }
85767504
JH
115 }
116 return nil
117}