]>
Commit | Line | Data |
---|---|---|
6988a057 JH |
1 | package hotline |
2 | ||
3 | import ( | |
165b7ac9 | 4 | "bufio" |
6988a057 JH |
5 | "bytes" |
6 | "encoding/binary" | |
7 | "errors" | |
85767504 | 8 | "io" |
6988a057 JH |
9 | ) |
10 | ||
df2735b2 | 11 | type 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 | 18 | var HTXF = [4]byte{0x48, 0x54, 0x58, 0x46} // (HTXF) is the only supported transfer protocol |
6988a057 | 19 | |
df2735b2 JH |
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 | |
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 | |
7cd900d6 | 32 | const fileCopyBufSize = 4096 |
85767504 | 33 | |
7cd900d6 JH |
34 | func receiveFile(r io.Reader, targetFile, resForkFile, infoFork io.Writer) error { |
35 | var ffo flattenedFileObject | |
36 | if _, err := ffo.ReadFrom(r); err != nil { | |
85767504 JH |
37 | return err |
38 | } | |
39 | ||
7cd900d6 JH |
40 | // Write the information fork |
41 | _, err := infoFork.Write(ffo.FlatFileInformationFork.MarshalBinary()) | |
85767504 JH |
42 | if err != nil { |
43 | return err | |
44 | } | |
45 | ||
7cd900d6 | 46 | // read and write the data fork |
165b7ac9 | 47 | bw := bufio.NewWriterSize(targetFile, fileCopyBufSize) |
7cd900d6 | 48 | if _, err = io.CopyN(bw, r, ffo.dataSize()); err != nil { |
85767504 JH |
49 | return err |
50 | } | |
165b7ac9 JH |
51 | if err := bw.Flush(); err != nil { |
52 | return err | |
53 | } | |
85767504 | 54 | |
7cd900d6 JH |
55 | if ffo.FlatFileHeader.ForkCount == [2]byte{0, 3} { |
56 | if err := binary.Read(r, binary.BigEndian, &ffo.FlatFileResForkHeader); err != nil { | |
85767504 JH |
57 | return err |
58 | } | |
ba29c43b | 59 | |
7cd900d6 JH |
60 | bw = bufio.NewWriterSize(resForkFile, fileCopyBufSize) |
61 | _, err = io.CopyN(resForkFile, r, ffo.rsrcSize()) | |
62 | if err != nil { | |
85767504 JH |
63 | return err |
64 | } | |
7cd900d6 | 65 | if err := bw.Flush(); err != nil { |
ba29c43b JH |
66 | return err |
67 | } | |
7cd900d6 JH |
68 | } |
69 | return nil | |
70 | } | |
ba29c43b | 71 | |
7cd900d6 JH |
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 | } | |
85767504 | 77 | |
7cd900d6 JH |
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 | } | |
85767504 JH |
88 | if err != nil { |
89 | return err | |
90 | } | |
7cd900d6 JH |
91 | // totalSent += int64(bytesRead) |
92 | ||
93 | // fileTransfer.BytesSent += bytesRead | |
94 | ||
95 | if _, err := w.Write(rSendBuffer[:bytesRead]); err != nil { | |
165b7ac9 JH |
96 | return err |
97 | } | |
85767504 | 98 | } |
7cd900d6 | 99 | |
85767504 | 100 | } |