From: Jeff Halter Date: Fri, 13 Aug 2021 02:00:13 +0000 (-0700) Subject: More cleanup X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/commitdiff_plain/c5d9af5aa4d9fb20316be45ab1b775bcf61bcad5?ds=sidebyside More cleanup --- diff --git a/hotline/account.go b/hotline/account.go index bcacc73..7368592 100644 --- a/hotline/account.go +++ b/hotline/account.go @@ -1,7 +1,6 @@ package hotline import ( - "encoding/binary" "github.com/jhalter/mobius/concat" ) @@ -14,41 +13,12 @@ type Account struct { Access *[]byte `yaml:"Access"` // 8 byte bitmap } -// Payload marshals an account to byte slice -// Example: -// 00 04 // fieldCount? -// 00 66 // 102 - fieldUserName -// 00 0d // 13 -// 61 64 6d 69 6e 69 73 74 72 61 74 6f 72 // administrator -// 00 69 // 105 fieldUserLogin (encoded) -// 00 05 // len -// 9e 9b 92 96 91 // encoded login name -// 00 6a // 106 fieldUserPassword -// 00 01 // len -// 78 -// 00 6e // fieldUserAccess -// 00 08 -// ff d3 cf ef ff 80 00 00 -func (a *Account) Payload() (out []byte) { - nameLen := make([]byte, 2) - binary.BigEndian.PutUint16(nameLen, uint16(len(a.Name))) - - loginLen := make([]byte, 2) - binary.BigEndian.PutUint16(loginLen, uint16(len(a.Login))) - +// MarshalBinary marshals an Account to byte slice +func (a *Account) MarshalBinary() (out []byte) { return concat.Slices( []byte{0x00, 0x3}, // param count -- always 3 - - []byte{0x00, 0x66}, // fieldUserName - nameLen, - []byte(a.Name), - - []byte{0x00, 0x69}, // fieldUserLogin - loginLen, - negateString([]byte(a.Login)), - - []byte{0x00, 0x6e}, // fieldUserAccess - []byte{0x00, 0x08}, - *a.Access, + NewField(fieldUserName, []byte(a.Name)).Payload(), + NewField(fieldUserLogin, negateString([]byte(a.Login))).Payload(), + NewField(fieldUserAccess, *a.Access).Payload(), ) } diff --git a/hotline/client.go b/hotline/client.go index dd113c9..cf88d8a 100644 --- a/hotline/client.go +++ b/hotline/client.go @@ -698,14 +698,6 @@ func (c *Client) HandleTransaction(t *Transaction) error { return nil } -func (c *Client) Connected() bool { - // c.Agreed == true && - if c.UserAccess != nil { - return true - } - return false -} - func (c *Client) Disconnect() error { err := c.Connection.Close() if err != nil { diff --git a/hotline/file_header.go b/hotline/file_header.go index 7e0df16..60c652e 100644 --- a/hotline/file_header.go +++ b/hotline/file_header.go @@ -27,15 +27,6 @@ func NewFileHeader(fileName string, isDir bool) FileHeader { return fh } -func (fh *FileHeader) Read(p []byte) (n int, err error) { - p = concat.Slices( - fh.Size, - fh.Type, - fh.FilePath, - ) - return len(p), nil -} - func (fh *FileHeader) Payload() []byte { return concat.Slices( fh.Size, diff --git a/hotline/file_path.go b/hotline/file_path.go index ae96e52..733dfaa 100644 --- a/hotline/file_path.go +++ b/hotline/file_path.go @@ -52,3 +52,12 @@ func (fp *FilePath) String() string { } return strings.Join(out, pathSeparator) } + +func ReadFilePath(filePathFieldData []byte) string { + var fp FilePath + err := fp.UnmarshalBinary(filePathFieldData) + if err != nil { + // TODO + } + return fp.String() +} diff --git a/hotline/file_transfer.go b/hotline/file_transfer.go index 46b0061..c0c2f87 100644 --- a/hotline/file_transfer.go +++ b/hotline/file_transfer.go @@ -1,6 +1,10 @@ package hotline -import "fmt" +import ( + "encoding/binary" + "fmt" + "strings" +) // File transfer types const ( @@ -27,3 +31,58 @@ func (ft *FileTransfer) String() string { return out } + +// 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 + PathItemCount [2]byte + FileNamePath []byte +} + +func (fu *folderUpload) FormattedPath() string { + pathItemLen := binary.BigEndian.Uint16(fu.PathItemCount[:]) + + var pathSegments []string + pathData := fu.FileNamePath + + for i := uint16(0); i < pathItemLen; i++ { + segLen := pathData[2] + pathSegments = append(pathSegments, string(pathData[3:3+segLen])) + pathData = pathData[3+segLen:] + } + + return strings.Join(pathSegments, pathSeparator) +} diff --git a/hotline/files.go b/hotline/files.go index bccab35..0c23334 100644 --- a/hotline/files.go +++ b/hotline/files.go @@ -43,9 +43,7 @@ func fileCreatorFromFilename(fn string) string { return code } -func getFileNameList(filePath string) ([]Field, error) { - var fields []Field - +func getFileNameList(filePath string) (fields []Field, err error) { files, err := ioutil.ReadDir(filePath) if err != nil { return fields, nil @@ -154,12 +152,3 @@ func EncodeFilePath(filePath string) []byte { return bytes } - -func ReadFilePath(filePathFieldData []byte) string { - var fp FilePath - err := fp.UnmarshalBinary(filePathFieldData) - if err != nil { - // TODO - } - return fp.String() -} diff --git a/hotline/flattened_file_object.go b/hotline/flattened_file_object.go index 8e2dbff..656cdd3 100644 --- a/hotline/flattened_file_object.go +++ b/hotline/flattened_file_object.go @@ -87,7 +87,7 @@ func (ffif FlatFileInformationFork) DataSize() []byte { } func (ffo flattenedFileObject) TransferSize() []byte { - payloadSize := len(ffo.Payload()) + payloadSize := len(ffo.BinaryMarshal()) dataSize := binary.BigEndian.Uint32(ffo.FlatFileDataForkHeader.DataSize) transferSize := make([]byte, 4) @@ -110,15 +110,6 @@ type FlatFileDataForkHeader struct { DataSize []byte } -func NewFlatFileDataForkHeader() FlatFileDataForkHeader { - return FlatFileDataForkHeader{ - ForkType: []byte("DATA"), - CompressionType: []byte{0, 0, 0, 0}, - RSVD: []byte{0, 0, 0, 0}, - // DataSize: []byte{0, 0, 0x03, 0xc3}, - } -} - // ReadFlattenedFileObject parses a byte slice into a flattenedFileObject func ReadFlattenedFileObject(bytes []byte) flattenedFileObject { nameSize := bytes[110:112] @@ -171,7 +162,7 @@ func ReadFlattenedFileObject(bytes []byte) flattenedFileObject { return ffo } -func (f flattenedFileObject) Payload() []byte { +func (f flattenedFileObject) BinaryMarshal() []byte { var out []byte out = append(out, f.FlatFileHeader.Format[:]...) out = append(out, f.FlatFileHeader.Version[:]...) diff --git a/hotline/server.go b/hotline/server.go index 8e0fb50..20ef49b 100644 --- a/hotline/server.go +++ b/hotline/server.go @@ -1,7 +1,6 @@ package hotline import ( - "bytes" "context" "encoding/binary" "errors" @@ -543,7 +542,6 @@ func (s *Server) handleNewConnection(conn net.Conn) error { c.Server.Stats.LoginCount += 1 const readBuffSize = 1024000 // 1KB - TODO: what should this be? - const maxTranSize = 1024000 tranBuff := make([]byte, 0) tReadlen := 0 // Infinite loop where take action on incoming client requests until the connection is closed @@ -651,7 +649,7 @@ func (s *Server) TransferFile(conn net.Conn) error { s.Logger.Infow("File download started", "filePath", fullFilePath, "transactionRef", fileTransfer.ReferenceNumber, "RemoteAddr", conn.RemoteAddr().String()) // Start by sending flat file object to client - if _, err := conn.Write(ffo.Payload()); err != nil { + if _, err := conn.Write(ffo.BinaryMarshal()); err != nil { return err } @@ -681,7 +679,7 @@ func (s *Server) TransferFile(conn net.Conn) error { } ffo := ReadFlattenedFileObject(buf) - payloadLen := len(ffo.Payload()) + payloadLen := len(ffo.BinaryMarshal()) fileSize := int(binary.BigEndian.Uint32(ffo.FlatFileDataForkHeader.DataSize)) destinationFile := s.Config.FileRoot + ReadFilePath(fileTransfer.FilePath) + "/" + string(fileTransfer.FileName) @@ -789,7 +787,6 @@ func (s *Server) TransferFile(conn net.Conn) error { // Read the client's Next Action request //TODO: Remove hardcoded behavior and switch behaviors based on the next action send if _, err := conn.Read(readBuffer); err != nil { - s.Logger.Errorf("error reading next action: %v", err) return err } @@ -800,7 +797,6 @@ func (s *Server) TransferFile(conn net.Conn) error { } splitPath := strings.Split(path, "/") - //strings.Join(splitPath[:len(splitPath)-1], "/") ffo, err := NewFlattenedFileObject(strings.Join(splitPath[:len(splitPath)-1], "/"), info.Name()) if err != nil { @@ -820,7 +816,7 @@ func (s *Server) TransferFile(conn net.Conn) error { } // Send file bytes to client - if _, err := conn.Write(ffo.Payload()); err != nil { + if _, err := conn.Write(ffo.BinaryMarshal()); err != nil { s.Logger.Error(err) return err } @@ -831,7 +827,7 @@ func (s *Server) TransferFile(conn net.Conn) error { } sendBuffer := make([]byte, 1048576) - totalBytesSent := len(ffo.Payload()) + totalBytesSent := len(ffo.BinaryMarshal()) for { bytesRead, err := file.Read(sendBuffer) @@ -895,10 +891,10 @@ func (s *Server) TransferFile(conn net.Conn) error { "RemoteAddr", conn.RemoteAddr().String(), "FormattedPath", fu.FormattedPath(), "IsFolder", fmt.Sprintf("%x", fu.IsFolder), - "PathItemCount", binary.BigEndian.Uint16(fu.PathItemCount), + "PathItemCount", binary.BigEndian.Uint16(fu.PathItemCount[:]), ) - if bytes.Equal(fu.IsFolder, []byte{0, 1}) { + if fu.IsFolder == [2]byte{0, 1} { if _, err := os.Stat(dstPath + "/" + fu.FormattedPath()); os.IsNotExist(err) { s.Logger.Infow("Target path does not exist; Creating...", "dstPath", dstPath) if err := os.Mkdir(dstPath+"/"+fu.FormattedPath(), 0777); err != nil { @@ -957,7 +953,7 @@ func transferFile(conn net.Conn, dst string) error { return err } ffo := ReadFlattenedFileObject(buf) - payloadLen := len(ffo.Payload()) + payloadLen := len(ffo.BinaryMarshal()) fileSize := int(binary.BigEndian.Uint32(ffo.FlatFileDataForkHeader.DataSize)) newFile, err := os.Create(dst) @@ -985,51 +981,6 @@ func transferFile(conn net.Conn, dst string) error { } } -// 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: buf[0:2], // Size of this structure (not including data size element itself) - IsFolder: buf[2:4], - PathItemCount: buf[4:6], - FileNamePath: buf[6 : dataLen+2], - } - - return fu -} - -type folderUpload struct { - DataSize []byte - IsFolder []byte - PathItemCount []byte - FileNamePath []byte -} - -func (fu *folderUpload) FormattedPath() string { - pathItemLen := binary.BigEndian.Uint16(fu.PathItemCount) - - var pathSegments []string - pathData := fu.FileNamePath - - for i := uint16(0); i < pathItemLen; i++ { - segLen := pathData[2] - pathSegments = append(pathSegments, string(pathData[3:3+segLen])) - pathData = pathData[3+segLen:] - } - - return strings.Join(pathSegments, pathSeparator) -} // sortedClients is a utility function that takes a map of *ClientConn and returns a sorted slice of the values. // The purpose of this is to ensure that the ordering of client connections is deterministic so that test assertions work. diff --git a/hotline/tracker.go b/hotline/tracker.go index e0cbe56..4ee192a 100644 --- a/hotline/tracker.go +++ b/hotline/tracker.go @@ -79,12 +79,12 @@ type ServerInfoHeader struct { } type ServerRecord struct { - IPAddr []byte - Port []byte - NumUsers []byte // Number of users connected to this particular server - Unused []byte + IPAddr [4]byte + Port [2]byte + NumUsers [2]byte // Number of users connected to this particular server + Unused [2]byte NameSize byte // Length of name string - Name []byte // Server’s name + Name []byte // Server name DescriptionSize byte Description []byte } @@ -165,11 +165,11 @@ func GetListing(addr string) ([]ServerRecord, error) { } func (s *ServerRecord) Read(b []byte) (n int, err error) { - s.IPAddr = b[0:4] - s.Port = b[4:6] - s.NumUsers = b[6:8] - s.NameSize = b[10] + copy(s.IPAddr[:], b[0:4]) + copy(s.Port[:], b[4:6]) + copy(s.NumUsers[:], b[6:8]) nameLen := int(b[10]) + s.Name = b[11 : 11+nameLen] s.DescriptionSize = b[11+nameLen] s.Description = b[12+nameLen : 12+nameLen+int(s.DescriptionSize)] @@ -177,14 +177,33 @@ func (s *ServerRecord) Read(b []byte) (n int, err error) { return 12 + nameLen + int(s.DescriptionSize), nil } +// +//func (s *ServerRecord) UnmarshalBinary(b []byte) (err error) { +// r := bytes.NewReader(b[:10]) +// if err := binary.Read(r, binary.BigEndian, s); err != nil { +// return err +// } +// +// copy(s.IPAddr[:], b[0:4]) +// s.Port = b[4:6] +// s.NumUsers = b[6:8] +// s.NameSize = b[10] +// nameLen := int(b[10]) +// s.Name = b[11 : 11+nameLen] +// s.DescriptionSize = b[11+nameLen] +// s.Description = b[12+nameLen : 12+nameLen+int(s.DescriptionSize)] +// +// return nil +//} + func (s *ServerRecord) PortInt() int { - data := binary.BigEndian.Uint16(s.Port) + data := binary.BigEndian.Uint16(s.Port[:]) return int(data) } func (s *ServerRecord) Addr() string { return fmt.Sprintf("%s:%s", - net.IP(s.IPAddr), - strconv.Itoa(int(binary.BigEndian.Uint16(s.Port))), + net.IP(s.IPAddr[:]), + strconv.Itoa(int(binary.BigEndian.Uint16(s.Port[:]))), ) } diff --git a/hotline/transaction_handlers.go b/hotline/transaction_handlers.go index 46f96eb..d7a77e2 100644 --- a/hotline/transaction_handlers.go +++ b/hotline/transaction_handlers.go @@ -644,7 +644,7 @@ func HandleListUsers(cc *ClientConn, t *Transaction) (res []Transaction, err err var userFields []Field // TODO: make order deterministic for _, acc := range cc.Server.Accounts { - userField := acc.Payload() + userField := acc.MarshalBinary() userFields = append(userFields, NewField(fieldData, userField)) } @@ -1240,7 +1240,10 @@ func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, er cc.Transfers[FolderDownload] = append(cc.Transfers[FolderDownload], fileTransfer) var fp FilePath - fp.UnmarshalBinary(t.GetField(fieldFilePath).Data) + err = fp.UnmarshalBinary(t.GetField(fieldFilePath).Data) + if err != nil { + return res, err + } fullFilePath := fmt.Sprintf("%v%v", cc.Server.Config.FileRoot+fp.String(), string(fileTransfer.FileName)) transferSize, err := CalcTotalSize(fullFilePath)