X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/22c599abc18895f73e96095f35b71cf3357d41b4..c5d9af5aa4d9fb20316be45ab1b775bcf61bcad5:/hotline/server.go diff --git a/hotline/server.go b/hotline/server.go index e51f673..20ef49b 100644 --- a/hotline/server.go +++ b/hotline/server.go @@ -1,7 +1,6 @@ package hotline import ( - "bytes" "context" "encoding/binary" "errors" @@ -33,7 +32,6 @@ const ( ) type Server struct { - Interface string Port int Accounts map[string]*Account Agreement []byte @@ -115,13 +113,17 @@ func (s *Server) sendTransaction(t Transaction) error { if client == nil { return errors.New("invalid client") } - userName := string(*client.UserName) + userName := string(client.UserName) login := client.Account.Login handler := TransactionHandlers[requestNum] + b, err := t.MarshalBinary() + if err != nil { + return err + } var n int - if n, err = client.Connection.Write(t.Payload()); err != nil { + if n, err = client.Connection.Write(b); err != nil { return err } s.Logger.Debugw("Sent Transaction", @@ -168,8 +170,6 @@ func (s *Server) Serve(ctx context.Context, cancelRoot context.CancelFunc, ln ne const ( agreementFile = "Agreement.txt" - messageBoardFile = "MessageBoard.txt" - threadedNewsFile = "ThreadedNews.yaml" ) // NewServer constructs a new Server from a config dir @@ -290,7 +290,7 @@ func (s *Server) keepaliveHandler() { tranNotifyChangeUser, NewField(fieldUserID, *c.ID), NewField(fieldUserFlags, *c.Flags), - NewField(fieldUserName, *c.UserName), + NewField(fieldUserName, c.UserName), NewField(fieldUserIconID, *c.Icon), ) } @@ -323,7 +323,7 @@ func (s *Server) NewClientConn(conn net.Conn) *ClientConn { ID: &[]byte{0, 0}, Icon: &[]byte{0, 0}, Flags: &[]byte{0, 0}, - UserName: &[]byte{}, + UserName: []byte{}, Connection: conn, Server: s, Version: &[]byte{}, @@ -382,7 +382,7 @@ func (s *Server) connectedUsers() []Field { ID: *c.ID, Icon: *c.Icon, Flags: *c.Flags, - Name: string(*c.UserName), + Name: string(c.UserName), } connectedUsers = append(connectedUsers, NewField(fieldUsernameWithInfo, user.Payload())) } @@ -497,15 +497,19 @@ func (s *Server) handleNewConnection(conn net.Conn) error { // If authentication fails, send error reply and close connection if !c.Authenticate(login, encodedPassword) { - rep := c.NewErrReply(clientLogin, "Incorrect login.") - if _, err := conn.Write(rep.Payload()); err != nil { + t := c.NewErrReply(clientLogin, "Incorrect login.") + b, err := t.MarshalBinary() + if err != nil { + return err + } + if _, err := conn.Write(b); err != nil { return err } return fmt.Errorf("incorrect login") } if clientLogin.GetField(fieldUserName).Data != nil { - *c.UserName = clientLogin.GetField(fieldUserName).Data + c.UserName = clientLogin.GetField(fieldUserName).Data } if clientLogin.GetField(fieldUserIconID).Data != nil { @@ -538,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 @@ -622,7 +625,8 @@ func (s *Server) TransferFile(conn net.Conn) error { return err } - t, err := NewReadTransfer(buf) + var t transfer + _, err := t.Write(buf[:16]) if err != nil { return err } @@ -645,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 } @@ -675,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) @@ -726,7 +730,7 @@ func (s *Server) TransferFile(conn net.Conn) error { } case FolderDownload: // Folder Download flow: - // 1. Get filePath from the Transfer + // 1. Get filePath from the transfer // 2. Iterate over files // 3. For each file: // Send file header to client @@ -752,7 +756,8 @@ func (s *Server) TransferFile(conn net.Conn) error { // // This notifies the server to send the next item header - fh := NewFilePath(fileTransfer.FilePath) + var fh FilePath + _ = fh.UnmarshalBinary(fileTransfer.FilePath) fullFilePath := fmt.Sprintf("%v/%v", s.Config.FileRoot+fh.String(), string(fileTransfer.FileName)) basePathLen := len(fullFilePath) @@ -764,7 +769,7 @@ func (s *Server) TransferFile(conn net.Conn) error { i := 0 _ = filepath.Walk(fullFilePath+"/", func(path string, info os.FileInfo, _ error) error { i += 1 - subPath := path[basePathLen-2:] + subPath := path[basePathLen:] s.Logger.Infow("Sending fileheader", "i", i, "path", path, "fullFilePath", fullFilePath, "subPath", subPath, "IsDir", info.IsDir()) fileHeader := NewFileHeader(subPath, info.IsDir()) @@ -782,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 } @@ -793,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 { @@ -813,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 } @@ -824,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) @@ -888,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 { @@ -950,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) @@ -978,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.