From: Jeff Halter Date: Thu, 9 Jun 2022 03:41:57 +0000 (-0700) Subject: Fix folder upload hang with resource forks X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/commitdiff_plain/ba29c43bb23de83c7715271e0830cb9f00e9e1c1 Fix folder upload hang with resource forks --- diff --git a/hotline/file_transfer.go b/hotline/file_transfer.go index 9e86bb8..4a93390 100644 --- a/hotline/file_transfer.go +++ b/hotline/file_transfer.go @@ -38,38 +38,6 @@ func (ft *FileTransfer) ItemCount() int { return int(binary.BigEndian.Uint16(ft.FolderItemCount)) } -// 00 28 // DataSize -// 00 00 // IsFolder -// 00 02 // PathItemCount -// -// 00 00 -// 09 -// 73 75 62 66 6f 6c 64 65 72 // "subfolder" -// -// 00 00 -// 15 -// 73 75 62 66 6f 6c 64 65 72 2d 74 65 73 74 66 69 6c 65 2d 35 6b // "subfolder-testfile-5k" -func readFolderUpload(buf []byte) folderUpload { - dataLen := binary.BigEndian.Uint16(buf[0:2]) - - fu := folderUpload{ - DataSize: [2]byte{buf[0], buf[1]}, // Size of this structure (not including data size element itself) - IsFolder: [2]byte{buf[2], buf[3]}, - PathItemCount: [2]byte{buf[4], buf[5]}, - FileNamePath: buf[6 : dataLen+2], - } - - return fu -} - -func (fu *folderUpload) UnmarshalBinary(b []byte) error { - fu.DataSize = [2]byte{b[0], b[1]} - fu.IsFolder = [2]byte{b[2], b[3]} - fu.PathItemCount = [2]byte{b[4], b[5]} - - return nil -} - type folderUpload struct { DataSize [2]byte IsFolder [2]byte diff --git a/hotline/server.go b/hotline/server.go index 33888e0..1a6d163 100644 --- a/hotline/server.go +++ b/hotline/server.go @@ -978,15 +978,26 @@ func (s *Server) handleFileTransfer(conn io.ReadWriteCloser) error { } fileSize := make([]byte, 4) - readBuffer := make([]byte, 1024) for i := 0; i < fileTransfer.ItemCount(); i++ { - // TODO: fix potential short read with io.ReadFull - _, err := conn.Read(readBuffer) - if err != nil { + s.Stats.UploadCounter += 1 + + var fu folderUpload + if _, err := io.ReadFull(conn, fu.DataSize[:]); err != nil { + return err + } + + if _, err := io.ReadFull(conn, fu.IsFolder[:]); err != nil { + return err + } + if _, err := io.ReadFull(conn, fu.PathItemCount[:]); err != nil { + return err + } + fu.FileNamePath = make([]byte, binary.BigEndian.Uint16(fu.DataSize[:])-4) + + if _, err := io.ReadFull(conn, fu.FileNamePath); err != nil { return err } - fu := readFolderUpload(readBuffer) s.Logger.Infow( "Folder upload continued", @@ -1073,7 +1084,7 @@ func (s *Server) handleFileTransfer(conn io.ReadWriteCloser) error { } case dlFldrActionSendFile: - if _, err := conn.Read(fileSize); err != nil { + if _, err := io.ReadFull(conn, fileSize); err != nil { return err } diff --git a/hotline/transfer.go b/hotline/transfer.go index 78bd888..4e6f79f 100644 --- a/hotline/transfer.go +++ b/hotline/transfer.go @@ -32,7 +32,7 @@ func (tf *transfer) Write(b []byte) (int, error) { const fileCopyBufSize = 524288 // 512k func receiveFile(conn io.Reader, targetFile io.Writer, resForkFile io.Writer) error { ffhBuf := make([]byte, 24) - if _, err := conn.Read(ffhBuf); err != nil { + if _, err := io.ReadFull(conn, ffhBuf); err != nil { return err } @@ -43,7 +43,7 @@ func receiveFile(conn io.Reader, targetFile io.Writer, resForkFile io.Writer) er } ffifhBuf := make([]byte, 16) - if _, err := conn.Read(ffifhBuf); err != nil { + if _, err := io.ReadFull(conn, ffifhBuf); err != nil { return err } @@ -57,7 +57,7 @@ func receiveFile(conn io.Reader, targetFile io.Writer, resForkFile io.Writer) er dataLen := binary.BigEndian.Uint32(ffifh.DataSize[:]) ffifBuf := make([]byte, dataLen) - if _, err := conn.Read(ffifBuf); err != nil { + if _, err := io.ReadFull(conn, ffifBuf); err != nil { return err } if err := ffif.UnmarshalBinary(ffifBuf); err != nil { @@ -66,7 +66,7 @@ func receiveFile(conn io.Reader, targetFile io.Writer, resForkFile io.Writer) er var ffdfh FlatFileDataForkHeader ffdfhBuf := make([]byte, 16) - if _, err := conn.Read(ffdfhBuf); err != nil { + if _, err := io.ReadFull(conn, ffdfhBuf); err != nil { return err } err = binary.Read(bytes.NewReader(ffdfhBuf), binary.BigEndian, &ffdfh) @@ -88,20 +88,24 @@ func receiveFile(conn io.Reader, targetFile io.Writer, resForkFile io.Writer) er if ffh.ForkCount == [2]byte{0, 3} { var resForkHeader FlatFileDataForkHeader - resForkBuf := make([]byte, 16) - resForkBufWrter := bufio.NewWriterSize(resForkFile, 16) - if _, err := io.CopyN(resForkBufWrter, conn, 16); err != nil { + if _, err := io.ReadFull(conn, resForkHeader.ForkType[:]); err != nil { return err } - err = binary.Read(bytes.NewReader(resForkBuf), binary.BigEndian, &resForkHeader) - if err != nil { + + if _, err := io.ReadFull(conn, resForkHeader.CompressionType[:]); err != nil { return err } - fileSize = int(binary.BigEndian.Uint32(resForkHeader.DataSize[:])) + if _, err := io.ReadFull(conn, resForkHeader.RSVD[:]); err != nil { + return err + } + + if _, err := io.ReadFull(conn, resForkHeader.DataSize[:]); err != nil { + return err + } bw = bufio.NewWriterSize(resForkFile, fileCopyBufSize) - _, err = io.CopyN(resForkFile, conn, int64(fileSize)) + _, err = io.CopyN(resForkFile, conn, int64(binary.BigEndian.Uint32(resForkHeader.DataSize[:]))) if err != nil { return err }