]>
Commit | Line | Data |
---|---|---|
1 | package hotline | |
2 | ||
3 | import ( | |
4 | "bufio" | |
5 | "bytes" | |
6 | "encoding/binary" | |
7 | "errors" | |
8 | "io" | |
9 | ) | |
10 | ||
11 | type transfer struct { | |
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 | ||
18 | var HTXF = [4]byte{0x48, 0x54, 0x58, 0x46} // (HTXF) is the only supported transfer protocol | |
19 | ||
20 | func (tf *transfer) Write(b []byte) (int, error) { | |
21 | if err := binary.Read(bytes.NewReader(b), binary.BigEndian, tf); err != nil { | |
22 | return 0, err | |
23 | } | |
24 | ||
25 | if tf.Protocol != HTXF { | |
26 | return 0, errors.New("invalid protocol") | |
27 | } | |
28 | ||
29 | return len(b), nil | |
30 | } | |
31 | ||
32 | const fileCopyBufSize = 4096 | |
33 | ||
34 | func receiveFile(r io.Reader, targetFile, resForkFile, infoFork io.Writer) error { | |
35 | var ffo flattenedFileObject | |
36 | if _, err := ffo.ReadFrom(r); err != nil { | |
37 | return err | |
38 | } | |
39 | ||
40 | // Write the information fork | |
41 | _, err := infoFork.Write(ffo.FlatFileInformationFork.MarshalBinary()) | |
42 | if err != nil { | |
43 | return err | |
44 | } | |
45 | ||
46 | // read and write the data fork | |
47 | bw := bufio.NewWriterSize(targetFile, fileCopyBufSize) | |
48 | if _, err = io.CopyN(bw, r, ffo.dataSize()); err != nil { | |
49 | return err | |
50 | } | |
51 | if err := bw.Flush(); err != nil { | |
52 | return err | |
53 | } | |
54 | ||
55 | if ffo.FlatFileHeader.ForkCount == [2]byte{0, 3} { | |
56 | if err := binary.Read(r, binary.BigEndian, &ffo.FlatFileResForkHeader); err != nil { | |
57 | return err | |
58 | } | |
59 | ||
60 | bw = bufio.NewWriterSize(resForkFile, fileCopyBufSize) | |
61 | _, err = io.CopyN(resForkFile, r, ffo.rsrcSize()) | |
62 | if err != nil { | |
63 | return err | |
64 | } | |
65 | if err := bw.Flush(); err != nil { | |
66 | return err | |
67 | } | |
68 | } | |
69 | return nil | |
70 | } | |
71 | ||
72 | func sendFile(w io.Writer, r io.Reader, offset int) (err error) { | |
73 | br := bufio.NewReader(r) | |
74 | if _, err := br.Discard(offset); err != nil { | |
75 | return err | |
76 | } | |
77 | ||
78 | rSendBuffer := make([]byte, 1024) | |
79 | for { | |
80 | var bytesRead int | |
81 | ||
82 | if bytesRead, err = br.Read(rSendBuffer); err == io.EOF { | |
83 | if _, err := w.Write(rSendBuffer[:bytesRead]); err != nil { | |
84 | return err | |
85 | } | |
86 | return nil | |
87 | } | |
88 | if err != nil { | |
89 | return err | |
90 | } | |
91 | // totalSent += int64(bytesRead) | |
92 | ||
93 | // fileTransfer.BytesSent += bytesRead | |
94 | ||
95 | if _, err := w.Write(rSendBuffer[:bytesRead]); err != nil { | |
96 | return err | |
97 | } | |
98 | } | |
99 | ||
100 | } |