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