aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/mobius-hotline-server/mobius/config/config.yaml8
-rw-r--r--hotline/config.go2
-rw-r--r--hotline/field.go1
-rw-r--r--hotline/file_transfer.go1
-rw-r--r--hotline/server.go6
-rw-r--r--hotline/transaction.go3
-rw-r--r--hotline/transaction_handlers.go38
-rw-r--r--hotline/transfer.go11
8 files changed, 65 insertions, 5 deletions
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
}