]> git.r.bdr.sh - rbdr/mobius/blob - hotline/transfer.go
Add initial support for resource and info forks
[rbdr/mobius] / hotline / transfer.go
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 }