From: Jeff Halter Date: Tue, 21 Jun 2022 23:10:19 +0000 (-0700) Subject: Add support for server banner X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/commitdiff_plain/9067f2344057a247dab19e6ce6756cb7d560d992 Add support for server banner --- diff --git a/cmd/mobius-hotline-server/mobius/config/config.yaml b/cmd/mobius-hotline-server/mobius/config/config.yaml index 50c3fa3..a903023 100644 --- a/cmd/mobius-hotline-server/mobius/config/config.yaml +++ b/cmd/mobius-hotline-server/mobius/config/config.yaml @@ -4,8 +4,12 @@ Name: My Hotline server # Description of the server as it appears on the tracker Description: A default configured Hotline server running Mobius -# Server banner ID; currently implemented -BannerID: 0 +# Path to server banner image. Only known to work in the 1.8 clients. +# * The banner must be under 256K (262,140 bytes specifically) +# * The standard size for a banner is 468 pixels wide and 60 pixels tall. +# * The banner must be saved in the same folder this file. +# * The banner must be a jpg +BannerFile: "banner.jpg" # Path to the Files directory, by default in a subdirectory of the config root named Files FileRoot: Files diff --git a/hotline/config.go b/hotline/config.go index 55d68e9..d6d801e 100644 --- a/hotline/config.go +++ b/hotline/config.go @@ -3,7 +3,7 @@ package hotline type Config struct { Name string `yaml:"Name" validate:"required,max=50"` // Name used for Tracker registration Description string `yaml:"Description" validate:"required,max=200"` // Description used for Tracker registration - BannerID int `yaml:"BannerID"` // Unimplemented + BannerFile string `yaml:"BannerFile"` // Path to banner jpg FileRoot string `yaml:"FileRoot" validate:"required"` // Path to Files EnableTrackerRegistration bool `yaml:"EnableTrackerRegistration"` // Toggle Tracker Registration Trackers []string `yaml:"Trackers" validate:"dive,hostname_port"` // List of trackers that the server should register with diff --git a/hotline/field.go b/hotline/field.go index 2be4c4a..aef790d 100644 --- a/hotline/field.go +++ b/hotline/field.go @@ -23,6 +23,7 @@ const fieldOptions = 113 const fieldChatID = 114 const fieldChatSubject = 115 const fieldWaitingCount = 116 +const fieldBannerType = 152 const fieldVersion = 160 const fieldCommunityBannerID = 161 const fieldServerName = 162 diff --git a/hotline/file_transfer.go b/hotline/file_transfer.go index 90dbbe6..c7c1a62 100644 --- a/hotline/file_transfer.go +++ b/hotline/file_transfer.go @@ -12,6 +12,7 @@ const ( FileUpload = 1 FolderDownload = 2 FolderUpload = 3 + bannerDownload = 4 ) type FileTransfer struct { diff --git a/hotline/server.go b/hotline/server.go index 11ec21d..21b1316 100644 --- a/hotline/server.go +++ b/hotline/server.go @@ -591,7 +591,7 @@ func (s *Server) handleNewConnection(ctx context.Context, conn io.ReadWriteClose s.outbox <- c.NewReply(clientLogin, NewField(fieldVersion, []byte{0x00, 0xbe}), - NewField(fieldCommunityBannerID, []byte{0x00, 0x01}), + NewField(fieldCommunityBannerID, []byte{0, 0}), NewField(fieldServerName, []byte(s.Config.Name)), ) @@ -716,6 +716,10 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro ) switch fileTransfer.Type { + case bannerDownload: + if err := s.bannerDownload(rwc); err != nil { + return err + } case FileDownload: s.Stats.DownloadCounter += 1 diff --git a/hotline/transaction.go b/hotline/transaction.go index 077e6f3..ece2924 100644 --- a/hotline/transaction.go +++ b/hotline/transaction.go @@ -31,6 +31,7 @@ const ( tranNotifyChatSubject = 119 tranSetChatSubject = 120 tranAgreed = 121 + tranServerBanner = 122 tranGetFileNameList = 200 tranDownloadFile = 202 tranUploadFile = 203 @@ -42,7 +43,7 @@ const ( tranMakeFileAlias = 209 tranDownloadFldr = 210 // tranDownloadInfo = 211 TODO: implement file transfer queue - // tranDownloadBanner = 212 TODO: figure out what this is used for + tranDownloadBanner = 212 tranUploadFldr = 213 tranGetUserNameList = 300 tranNotifyChangeUser = 301 diff --git a/hotline/transaction_handlers.go b/hotline/transaction_handlers.go index cad3370..9f07fe1 100644 --- a/hotline/transaction_handlers.go +++ b/hotline/transaction_handlers.go @@ -231,6 +231,10 @@ var TransactionHandlers = map[uint16]TransactionType{ Name: "tranUserBroadcast", Handler: HandleUserBroadcast, }, + tranDownloadBanner: { + Name: "tranDownloadBanner", + Handler: HandleDownloadBanner, + }, } func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err error) { @@ -976,6 +980,10 @@ func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err er cc.Server.outbox <- t } + if cc.Server.Config.BannerFile != "" { + cc.Server.outbox <- *NewTransaction(tranServerBanner, cc.ID, NewField(fieldBannerType, []byte("JPEG"))) + } + res = append(res, cc.NewReply(t)) return res, err @@ -1927,3 +1935,33 @@ func HandleMakeAlias(cc *ClientConn, t *Transaction) (res []Transaction, err err res = append(res, cc.NewReply(t)) return res, err } + +func HandleDownloadBanner(cc *ClientConn, t *Transaction) (res []Transaction, err error) { + transactionRef := cc.Server.NewTransactionRef() + data := binary.BigEndian.Uint32(transactionRef) + + ft := &FileTransfer{ + ReferenceNumber: transactionRef, + Type: bannerDownload, + } + + fi, err := cc.Server.FS.Stat(filepath.Join(cc.Server.ConfigDir, cc.Server.Config.BannerFile)) + if err != nil { + return res, err + } + + size := make([]byte, 4) + binary.BigEndian.PutUint32(size, uint32(fi.Size())) + + cc.Server.mux.Lock() + defer cc.Server.mux.Unlock() + cc.Server.FileTransfers[data] = ft + + res = append(res, cc.NewReply(t, + NewField(fieldRefNum, transactionRef), + NewField(fieldTransferSize, size), + )) + + res = append(res, cc.NewReply(t)) + return res, err +} diff --git a/hotline/transfer.go b/hotline/transfer.go index 7333197..9d2a97f 100644 --- a/hotline/transfer.go +++ b/hotline/transfer.go @@ -6,6 +6,8 @@ import ( "encoding/binary" "errors" "io" + "os" + "path/filepath" ) type transfer struct { @@ -96,5 +98,14 @@ func sendFile(w io.Writer, r io.Reader, offset int) (err error) { return err } } +} + +func (s *Server) bannerDownload(w io.Writer) error { + bannerBytes, err := os.ReadFile(filepath.Join(s.ConfigDir, s.Config.BannerFile)) + if err != nil { + return err + } + _, err = w.Write(bannerBytes) + return err }