Documentation
¶
Overview ¶
Package hotline provides Hotline client and server implementations.
Index ¶
- Constants
- Variables
- func CalcItemCount(filePath string) ([]byte, error)
- func CalcTotalSize(filePath string) ([]byte, error)
- func DownloadFolderHandler(rwc io.ReadWriter, fullPath string, fileTransfer *FileTransfer, ...) error
- func DownloadHandler(w io.Writer, fullPath string, fileTransfer *FileTransfer, fs FileStore, ...) error
- func EncodeFilePath(filePath string) []byte
- func EncodeString(clearText []byte) []byte
- func FieldScanner(data []byte, _ bool) (advance int, token []byte, err error)
- func FileTypeFromFilename(filename string) fileType
- func HashAndSalt(pwd []byte) string
- func ReadPath(fileRoot string, filePath, fileName []byte) (fullPath string, err error)
- func UploadFolderHandler(rwc io.ReadWriter, fullPath string, fileTransfer *FileTransfer, ...) error
- func UploadHandler(rwc io.ReadWriter, fullPath string, fileTransfer *FileTransfer, ...) error
- func WithConfig(config Config) func(s *Server)
- func WithInterface(netInterface string) func(s *Server)
- func WithLogger(logger *slog.Logger) func(s *Server)
- func WithPort(port int) func(s *Server)
- func WithTLS(tlsConfig *tls.Config, port int) func(s *Server)
- func WithTrackerRegistrar(registrar TrackerRegistrar) func(s *Server)
- type AccessBitmap
- type Account
- type AccountManager
- type BanMgr
- type ChatID
- type ChatManager
- type Client
- func (c *Client) Connect(address, login, passwd string) (err error)
- func (c *Client) Disconnect() error
- func (c *Client) HandleFunc(tranType [2]byte, handler ClientHandler)
- func (c *Client) HandleTransaction(ctx context.Context, t *Transaction) error
- func (c *Client) HandleTransactions(ctx context.Context) error
- func (c *Client) Handshake() error
- func (c *Client) Send(t Transaction) error
- type ClientConn
- func (cc *ClientConn) Authenticate(login string, password []byte) bool
- func (cc *ClientConn) Authorize(access int) bool
- func (cc *ClientConn) Disconnect()
- func (cc *ClientConn) FileRoot() string
- func (cc *ClientConn) NewErrReply(t *Transaction, errMsg string) []Transaction
- func (cc *ClientConn) NewFileTransfer(transferType FileTransferType, fileroot string, ...) *FileTransfer
- func (cc *ClientConn) NewReply(t *Transaction, fields ...Field) Transaction
- func (cc *ClientConn) NotifyOthers(t Transaction) (trans []Transaction)
- func (cc *ClientConn) SendAll(t [2]byte, fields ...Field)
- func (cc *ClientConn) String() string
- type ClientFileTransferMgr
- type ClientHandler
- type ClientID
- type ClientManager
- type ClientPrefs
- type ClientTHandler
- type ClientTransaction
- type Config
- type Counter
- type Dialer
- type Field
- type FieldType
- type File
- type FileHeader
- type FileNameWithInfo
- type FileNameWithInfoHeader
- type FilePath
- type FilePathItem
- type FileResumeData
- type FileStore
- type FileTransfer
- type FileTransferID
- type FileTransferMgr
- type FileTransferType
- type FlatFileForkHeader
- type FlatFileHeader
- type FlatFileInformationFork
- func (ffif *FlatFileInformationFork) DataSize() []byte
- func (ffif *FlatFileInformationFork) FriendlyCreator() []byte
- func (ffif *FlatFileInformationFork) FriendlyType() []byte
- func (ffif *FlatFileInformationFork) Read(p []byte) (int, error)
- func (ffif *FlatFileInformationFork) ReadNameSize() []byte
- func (ffif *FlatFileInformationFork) SetComment(comment []byte) error
- func (ffif *FlatFileInformationFork) Size() [4]byte
- func (ffif *FlatFileInformationFork) UnmarshalBinary(b []byte) error
- func (ffif *FlatFileInformationFork) Write(p []byte) (int, error)
- type ForkInfoList
- type ForkType
- type HandlerFunc
- type Logger
- type MemChatManager
- func (cm *MemChatManager) GetSubject(id ChatID) string
- func (cm *MemChatManager) Join(id ChatID, cc *ClientConn)
- func (cm *MemChatManager) Leave(id ChatID, clientID [2]byte)
- func (cm *MemChatManager) Members(id ChatID) []*ClientConn
- func (cm *MemChatManager) New(cc *ClientConn) ChatID
- func (cm *MemChatManager) SetSubject(id ChatID, subject string)
- type MemClientMgr
- type MemFileTransferMgr
- type MockChatManager
- func (m *MockChatManager) GetSubject(id ChatID) string
- func (m *MockChatManager) Join(id ChatID, cc *ClientConn)
- func (m *MockChatManager) Leave(id ChatID, clientID [2]byte)
- func (m *MockChatManager) Members(id ChatID) []*ClientConn
- func (m *MockChatManager) New(cc *ClientConn) ChatID
- func (m *MockChatManager) SetSubject(id ChatID, subject string)
- type MockClientMgr
- type MockFileInfo
- type MockFileStore
- func (mfs *MockFileStore) Create(name string) (*os.File, error)
- func (mfs *MockFileStore) Mkdir(name string, perm os.FileMode) error
- func (mfs *MockFileStore) Open(name string) (*os.File, error)
- func (mfs *MockFileStore) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error)
- func (mfs *MockFileStore) ReadFile(name string) ([]byte, error)
- func (mfs *MockFileStore) Remove(name string) error
- func (mfs *MockFileStore) RemoveAll(name string) error
- func (mfs *MockFileStore) Rename(oldpath, newpath string) error
- func (mfs *MockFileStore) Stat(name string) (os.FileInfo, error)
- func (mfs *MockFileStore) Symlink(oldname, newname string) error
- func (mfs *MockFileStore) WriteFile(name string, data []byte, perm fs.FileMode) error
- type MockThreadNewsMgr
- func (m *MockThreadNewsMgr) CreateGrouping(newsPath []string, name string, itemType [2]byte) error
- func (m *MockThreadNewsMgr) DeleteArticle(newsPath []string, articleID uint32, recursive bool) error
- func (m *MockThreadNewsMgr) DeleteNewsItem(newsPath []string) error
- func (m *MockThreadNewsMgr) GetArticle(newsPath []string, articleID uint32) *NewsArtData
- func (m *MockThreadNewsMgr) GetCategories(paths []string) []NewsCategoryListData15
- func (m *MockThreadNewsMgr) ListArticles(newsPath []string) (NewsArtListData, error)
- func (m *MockThreadNewsMgr) NewsItem(newsPath []string) NewsCategoryListData15
- func (m *MockThreadNewsMgr) PostArticle(newsPath []string, parentArticleID uint32, article NewsArtData) error
- type NewsArtData
- type NewsArtList
- type NewsArtListData
- type NewsCategoryListData15
- type NewsFlavorList
- type OSFileStore
- func (fs *OSFileStore) Create(name string) (*os.File, error)
- func (fs *OSFileStore) Mkdir(name string, perm os.FileMode) error
- func (fs *OSFileStore) Open(name string) (*os.File, error)
- func (fs *OSFileStore) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error)
- func (fs *OSFileStore) ReadFile(name string) ([]byte, error)
- func (fs *OSFileStore) Remove(name string) error
- func (fs *OSFileStore) RemoveAll(name string) error
- func (fs *OSFileStore) Rename(oldpath string, newpath string) error
- func (fs *OSFileStore) Stat(name string) (os.FileInfo, error)
- func (fs *OSFileStore) Symlink(oldname, newname string) error
- func (fs *OSFileStore) WriteFile(name string, data []byte, perm fs.FileMode) error
- type Option
- type PrivateChat
- type RealDialer
- type RealTrackerRegistrar
- type Server
- func (s *Server) CurrentStats() map[string]interface{}
- func (s *Server) HandleFunc(tranType [2]byte, handler HandlerFunc)
- func (s *Server) ListenAndServe(ctx context.Context) error
- func (s *Server) NewClientConn(conn io.ReadWriteCloser, remoteAddr string) *ClientConn
- func (s *Server) SendAll(t TranType, fields ...Field)
- func (s *Server) Serve(ctx context.Context, ln net.Listener) error
- func (s *Server) ServeFileTransfers(ctx context.Context, ln net.Listener) error
- func (s *Server) ServeFileTransfersWithTLS(ctx context.Context, ln net.Listener) error
- func (s *Server) ServeWithTLS(ctx context.Context, ln net.Listener) error
- func (s *Server) Shutdown(msg []byte)
- type ServerConfig
- type ServerInfoHeader
- type ServerRecord
- type Stats
- type ThreadedNews
- type ThreadedNewsMgr
- type Time
- type TrackerHeader
- type TrackerRegistrar
- type TrackerRegistration
- type TranType
- type Transaction
- type User
- type UserFlags
- type WriteCounter
Constants ¶
const ( AccessDeleteFile = 0 // File System Maintenance: Can Delete Files AccessUploadFile = 1 // File System Maintenance: Can Upload Files AccessDownloadFile = 2 // File System Maintenance: Can Download Files AccessRenameFile = 3 // File System Maintenance: Can Rename Files AccessMoveFile = 4 // File System Maintenance: Can Move Files AccessCreateFolder = 5 // File System Maintenance: Can Create Folders AccessDeleteFolder = 6 // File System Maintenance: Can Delete Folders AccessRenameFolder = 7 // File System Maintenance: Can Rename Folders AccessMoveFolder = 8 // File System Maintenance: Can Move Folders AccessReadChat = 9 // Chat: Can Read Chat AccessSendChat = 10 // Chat: Can Send Chat AccessOpenChat = 11 // Chat: Can Initial Private Chat AccessCloseChat = 12 // Present in the Hotline 1.9 protocol documentation, but seemingly unused AccessShowInList = 13 // Present in the Hotline 1.9 protocol documentation, but seemingly unused AccessCreateUser = 14 // User Maintenance: Can Create Accounts AccessDeleteUser = 15 // User Maintenance: Can Delete Accounts AccessOpenUser = 16 // User Maintenance: Can Read Accounts AccessModifyUser = 17 // User Maintenance: Can Modify Accounts AccessChangeOwnPass = 18 // Present in the Hotline 1.9 protocol documentation, but seemingly unused AccessNewsReadArt = 20 // News: Can Read Articles AccessNewsPostArt = 21 // News: Can Post Articles AccessDisconUser = 22 // User Maintenance: Can Disconnect Users (Note: Turns username red in user list) AccessCannotBeDiscon = 23 // User Maintenance: Cannot be Disconnected AccessGetClientInfo = 24 // User Maintenance: Can Get User Info AccessUploadAnywhere = 25 // File System Maintenance: Can Upload Anywhere AccessAnyName = 26 // Miscellaneous: Can User Any Name AccessNoAgreement = 27 // Miscellaneous: Don't Show Agreement AccessSetFileComment = 28 // File System Maintenance: Can Comment Files AccessSetFolderComment = 29 // File System Maintenance: Can Comment Folders AccessViewDropBoxes = 30 // File System Maintenance: Can View Drop Boxes AccessMakeAlias = 31 // File System Maintenance: Can Make Aliases AccessBroadcast = 32 // Messaging: Can Broadcast AccessNewsDeleteArt = 33 // News: Can Delete Articles AccessNewsCreateCat = 34 // News: Can Create Categories AccessNewsDeleteCat = 35 // News: Can Delete Categories AccessNewsCreateFldr = 36 // News: Can Create News Bundles AccessNewsDeleteFldr = 37 // News: Can Delete News Bundles AccessUploadFolder = 38 // File System Maintenance: Can Upload Folders AccessDownloadFolder = 39 // File System Maintenance: Can Download Folders AccessSendPrivMsg = 40 // Messaging: Can Send Messages (Note: 1.9 protocol doc incorrectly says this is bit 19) )
const ( DlFldrActionSendFile = 1 DlFldrActionResumeFile = 2 DlFldrActionNextFile = 3 )
Folder download actions. Send by the client to indicate the next action the server should take for a folder download.
const ( FileDownload = FileTransferType(0) FileUpload = FileTransferType(1) FolderDownload = FileTransferType(2) FolderUpload = FileTransferType(3) BannerDownload = FileTransferType(4) )
const ( IncompleteFileSuffix = ".incomplete" InfoForkNameTemplate = ".info_%s" // template string for info fork filenames RsrcForkNameTemplate = ".rsrc_%s" // template string for resource fork filenames )
const ( StatCurrentlyConnected = iota StatDownloadsInProgress StatUploadsInProgress StatWaitingDownloads StatConnectionPeak StatConnectionCounter StatDownloadCounter StatUploadCounter )
Stat counter keys
const ( UserFlagAway = 0 // User is away UserFlagAdmin = 1 // User is admin UserFlagRefusePM = 2 // User refuses private messages UserFlagRefusePChat = 3 // User refuses private chat )
User flags are stored as a 2 byte bitmap and represent various user states
const ( UserOptRefusePM = 0 // User has "Refuse private messages" pref set UserOptRefuseChat = 1 // User has "Refuse private chat" pref set UserOptAutoResponse = 2 // User has "Automatic response" pref set )
User options are sent from clients and represent options set in the client's preferences.
const BanDuration = 30 * time.Minute
BanDuration is the length of time for temporary bans.
const GuestAccount = "guest" // default account used when no login is provided for a connection
const LimitChatMsg = 8192
The total size of a chat message data field is 8192 bytes.
const NewsDateFormat = "Jan02 15:04" // Jun23 20:49
const NewsTemplate = `From %s (%s):
%s
__________________________________________________________`
Variables ¶
var ( FieldError = FieldType{0x00, 0x64} // 100 FieldData = FieldType{0x00, 0x65} // 101 FieldUserName = FieldType{0x00, 0x66} // 102 FieldUserID = FieldType{0x00, 0x67} // 103 FieldUserIconID = FieldType{0x00, 0x68} // 104 FieldUserLogin = FieldType{0x00, 0x69} // 105 FieldUserPassword = FieldType{0x00, 0x6A} // 106 FieldRefNum = FieldType{0x00, 0x6B} // 107 FieldTransferSize = FieldType{0x00, 0x6C} // 108 FieldChatOptions = FieldType{0x00, 0x6D} // 109 FieldUserAccess = FieldType{0x00, 0x6E} // 110 FieldUserFlags = FieldType{0x00, 0x70} // 112 FieldOptions = FieldType{0x00, 0x71} // 113 FieldChatID = FieldType{0x00, 0x72} // 114 FieldChatSubject = FieldType{0x00, 0x73} // 115 FieldWaitingCount = FieldType{0x00, 0x74} // 116 FieldBannerType = FieldType{0x00, 0x98} // 152 FieldNoServerAgreement = FieldType{0x00, 0x98} // 152 FieldVersion = FieldType{0x00, 0xA0} // 160 FieldCommunityBannerID = FieldType{0x00, 0xA1} // 161 FieldServerName = FieldType{0x00, 0xA2} // 162 FieldFileNameWithInfo = FieldType{0x00, 0xC8} // 200 FieldFileName = FieldType{0x00, 0xC9} // 201 FieldFilePath = FieldType{0x00, 0xCA} // 202 FieldFileResumeData = FieldType{0x00, 0xCB} // 203 FieldFileTransferOptions = FieldType{0x00, 0xCC} // 204 FieldFileTypeString = FieldType{0x00, 0xCD} // 205 FieldFileCreatorString = FieldType{0x00, 0xCE} // 206 FieldFileSize = FieldType{0x00, 0xCF} // 207 FieldFileCreateDate = FieldType{0x00, 0xD0} // 208 FieldFileModifyDate = FieldType{0x00, 0xD1} // 209 FieldFileComment = FieldType{0x00, 0xD2} // 210 FieldFileNewName = FieldType{0x00, 0xD3} // 211 FieldFileNewPath = FieldType{0x00, 0xD4} // 212 FieldFileType = FieldType{0x00, 0xD5} // 213 FieldQuotingMsg = FieldType{0x00, 0xD6} // 214 FieldAutomaticResponse = FieldType{0x00, 0xD7} // 215 FieldFolderItemCount = FieldType{0x00, 0xDC} // 220 FieldUsernameWithInfo = FieldType{0x01, 0x2C} // 300 FieldNewsArtListData = FieldType{0x01, 0x41} // 321 FieldNewsCatName = FieldType{0x01, 0x42} // 322 FieldNewsCatListData15 = FieldType{0x01, 0x43} // 323 FieldNewsPath = FieldType{0x01, 0x45} // 325 FieldNewsArtID = FieldType{0x01, 0x46} // 326 FieldNewsArtDataFlav = FieldType{0x01, 0x47} // 327 FieldNewsArtTitle = FieldType{0x01, 0x48} // 328 FieldNewsArtPoster = FieldType{0x01, 0x49} // 329 FieldNewsArtDate = FieldType{0x01, 0x4A} // 330 FieldNewsArtPrevArt = FieldType{0x01, 0x4B} // 331 FieldNewsArtNextArt = FieldType{0x01, 0x4C} // 332 FieldNewsArtData = FieldType{0x01, 0x4D} // 333 FieldNewsArtParentArt = FieldType{0x01, 0x4F} // 335 FieldNewsArt1stChildArt = FieldType{0x01, 0x50} // 336 FieldNewsArtRecurseDel = FieldType{0x01, 0x51} // 337 )
List of Hotline protocol field types taken from the official 1.9 protocol document
var ( ForkTypeDATA = ForkType{0x44, 0x41, 0x54, 0x41} // DATA: Data fork ForkTypeINFO = ForkType{0x49, 0x4E, 0x46, 0x4F} // INFO: Information fork ForkTypeMACR = ForkType{0x4d, 0x41, 0x43, 0x52} // MACR: Mac resource fork )
var ( FormatFILP = [4]byte{0x46, 0x49, 0x4c, 0x50} // Flattened file format: "FILP" FormatRFLT = [4]byte{0x52, 0x46, 0x4C, 0x54} // File resume format: "RFLT" (?) PlatformAMAC = [4]byte{0x41, 0x4D, 0x41, 0x43} // Mac platform: "AMAC" PlatformMWIN = [4]byte{0x4D, 0x57, 0x49, 0x4E} // Windows platform: "MWIN" )
var ( NewsBundle = [2]byte{0, 2} NewsCategory = [2]byte{0, 3} )
var ( NewsFlavor = []byte("text/plain") // NewsFlavor is always "text/plain" NewsFlavorCount = []byte{0, 1} // NewsFlavorCount is always 1 )
var ( TranError = TranType{0x00, 0x00} // 0 TranGetMsgs = TranType{0x00, 0x65} // 101 TranNewMsg = TranType{0x00, 0x66} // 102 TranOldPostNews = TranType{0x00, 0x67} // 103 TranServerMsg = TranType{0x00, 0x68} // 104 TranChatSend = TranType{0x00, 0x69} // 105 TranChatMsg = TranType{0x00, 0x6A} // 106 TranLogin = TranType{0x00, 0x6B} // 107 TranSendInstantMsg = TranType{0x00, 0x6C} // 108 TranShowAgreement = TranType{0x00, 0x6D} // 109 TranDisconnectUser = TranType{0x00, 0x6E} // 110 TranDisconnectMsg = TranType{0x00, 0x6F} // 111 TranInviteNewChat = TranType{0x00, 0x70} // 112 TranInviteToChat = TranType{0x00, 0x71} // 113 TranRejectChatInvite = TranType{0x00, 0x72} // 114 TranJoinChat = TranType{0x00, 0x73} // 115 TranLeaveChat = TranType{0x00, 0x74} // 116 TranNotifyChatChangeUser = TranType{0x00, 0x75} // 117 TranNotifyChatDeleteUser = TranType{0x00, 0x76} // 118 TranNotifyChatSubject = TranType{0x00, 0x77} // 119 TranSetChatSubject = TranType{0x00, 0x78} // 120 TranAgreed = TranType{0x00, 0x79} // 121 TranServerBanner = TranType{0x00, 0x7A} // 122 TranGetFileNameList = TranType{0x00, 0xC8} // 200 TranDownloadFile = TranType{0x00, 0xCA} // 202 TranUploadFile = TranType{0x00, 0xCB} // 203 TranNewFolder = TranType{0x00, 0xCD} // 205 TranDeleteFile = TranType{0x00, 0xCC} // 204 TranGetFileInfo = TranType{0x00, 0xCE} // 206 TranSetFileInfo = TranType{0x00, 0xCF} // 207 TranMoveFile = TranType{0x00, 0xD0} // 208 TranMakeFileAlias = TranType{0x00, 0xD1} // 209 TranDownloadFldr = TranType{0x00, 0xD2} // 210 TranDownloadInfo = TranType{0x00, 0xD3} // 211 TranDownloadBanner = TranType{0x00, 0xD4} // 212 TranUploadFldr = TranType{0x00, 0xD5} // 213 TranGetUserNameList = TranType{0x01, 0x2C} // 300 TranNotifyChangeUser = TranType{0x01, 0x2D} // 301 TranNotifyDeleteUser = TranType{0x01, 0x2E} // 302 TranGetClientInfoText = TranType{0x01, 0x2F} // 303 TranSetClientUserInfo = TranType{0x01, 0x30} // 304 TranListUsers = TranType{0x01, 0x5C} // 348 TranUpdateUser = TranType{0x01, 0x5D} // 349 TranNewUser = TranType{0x01, 0x5E} // 350 TranDeleteUser = TranType{0x01, 0x5F} // 351 TranGetUser = TranType{0x01, 0x60} // 352 TranSetUser = TranType{0x01, 0x61} // 353 TranUserAccess = TranType{0x01, 0x62} // 354 TranUserBroadcast = TranType{0x01, 0x63} // 355 TranGetNewsCatNameList = TranType{0x01, 0x72} // 370 TranGetNewsArtNameList = TranType{0x01, 0x73} // 371 TranDelNewsItem = TranType{0x01, 0x7C} // 380 TranNewNewsFldr = TranType{0x01, 0x7D} // 381 TranNewNewsCat = TranType{0x01, 0x7E} // 382 TranGetNewsArtData = TranType{0x01, 0x90} // 400 TranPostNewsArt = TranType{0x01, 0x9A} // 410 TranDelNewsArt = TranType{0x01, 0x9B} // 411 TranKeepAlive = TranType{0x01, 0xF4} // 500 )
var ClientHandshake = []byte{
0x54, 0x52, 0x54, 0x50,
0x48, 0x4f, 0x54, 0x4c,
0x00, 0x01,
0x00, 0x02,
}
var HTXF = [4]byte{0x48, 0x54, 0x58, 0x46} // (HTXF) is the only supported transfer protocol
var ServerHandshake = []byte{
0x54, 0x52, 0x54, 0x50,
0x00, 0x00, 0x00, 0x00,
}
Functions ¶
func CalcItemCount ¶
CalcItemCount recurses through a file path and counts the number of non-hidden files.
func CalcTotalSize ¶
func DownloadFolderHandler ¶ added in v0.13.0
func DownloadFolderHandler(rwc io.ReadWriter, fullPath string, fileTransfer *FileTransfer, fileStore FileStore, rLogger *slog.Logger, preserveForks bool) error
func DownloadHandler ¶ added in v0.13.0
func EncodeFilePath ¶
func EncodeString ¶ added in v0.13.0
EncodeString takes []byte s containing cleartext and rotates by 255 into obfuscated cleartext. The Hotline protocol uses this format for sending passwords over network. Not secure, but hey, it was the 90s!
func FieldScanner ¶ added in v0.13.0
FieldScanner implements bufio.SplitFunc for parsing byte slices into complete tokens
func FileTypeFromFilename ¶ added in v0.19.0
func FileTypeFromFilename(filename string) fileType
func HashAndSalt ¶ added in v0.13.0
HashAndSalt generates a password hash from a users obfuscated plaintext password
func UploadFolderHandler ¶ added in v0.13.0
func UploadFolderHandler(rwc io.ReadWriter, fullPath string, fileTransfer *FileTransfer, fileStore FileStore, rLogger *slog.Logger, preserveForks bool) error
func UploadHandler ¶ added in v0.13.0
func UploadHandler(rwc io.ReadWriter, fullPath string, fileTransfer *FileTransfer, fileStore FileStore, rLogger *slog.Logger, preserveForks bool) error
func WithConfig ¶ added in v0.13.0
func WithInterface ¶ added in v0.13.0
WithInterface optionally sets a specific interface to listen on.
func WithLogger ¶ added in v0.13.0
func WithTrackerRegistrar ¶ added in v0.19.0
func WithTrackerRegistrar(registrar TrackerRegistrar) func(s *Server)
WithTrackerRegistrar optionally sets a custom tracker registrar (useful for testing).
Types ¶
type AccessBitmap ¶ added in v0.13.0
type AccessBitmap [8]byte
func (*AccessBitmap) IsSet ¶ added in v0.13.0
func (bits *AccessBitmap) IsSet(i int) bool
func (AccessBitmap) MarshalYAML ¶ added in v0.17.0
func (bits AccessBitmap) MarshalYAML() (interface{}, error)
func (*AccessBitmap) Set ¶ added in v0.13.0
func (bits *AccessBitmap) Set(i int)
func (*AccessBitmap) UnmarshalYAML ¶ added in v0.17.0
func (bits *AccessBitmap) UnmarshalYAML(unmarshal func(interface{}) error) error
type Account ¶
type Account struct {
Login string `yaml:"Login"`
Name string `yaml:"Name"`
Password string `yaml:"Password"`
Access AccessBitmap `yaml:"Access"`
FileRoot string `yaml:"FileRoot"`
// contains filtered or unexported fields
}
func NewAccount ¶ added in v0.13.0
func NewAccount(login, name, password string, access AccessBitmap) *Account
type AccountManager ¶ added in v0.13.0
type AccountManager interface {
Create(account Account) error
Update(account Account, newLogin string) error
Get(login string) *Account
List() []Account
Delete(login string) error
}
AccountManager provides an interface for managing user accounts, including creation, retrieval, updates, and deletion operations.
type ChatManager ¶ added in v0.13.0
type ChatManager interface {
New(cc *ClientConn) ChatID
GetSubject(id ChatID) string
Join(id ChatID, cc *ClientConn)
Leave(id ChatID, clientID [2]byte)
SetSubject(id ChatID, subject string)
Members(id ChatID) []*ClientConn
}
type Client ¶
type Client struct {
Connection net.Conn
Logger Logger
Pref *ClientPrefs
Handlers map[[2]byte]ClientHandler
UserList []User
// contains filtered or unexported fields
}
func (*Client) Connect ¶ added in v0.10.19
JoinServer connects to a Hotline server and completes the login flow
func (*Client) Disconnect ¶
func (*Client) HandleFunc ¶ added in v0.10.20
func (c *Client) HandleFunc(tranType [2]byte, handler ClientHandler)
func (*Client) HandleTransaction ¶
func (c *Client) HandleTransaction(ctx context.Context, t *Transaction) error
func (*Client) HandleTransactions ¶ added in v0.10.19
func (*Client) Send ¶
func (c *Client) Send(t Transaction) error
type ClientConn ¶
type ClientConn struct {
Connection io.ReadWriteCloser
RemoteAddr string
ID ClientID
Icon []byte // TODO: make fixed size of 2
Version []byte // TODO: make fixed size of 2
FlagsMU sync.Mutex // TODO: move into UserFlags struct
Flags UserFlags
UserName []byte
Account *Account
IdleTime int
Server *Server // TODO: consider adding methods to interact with server
AutoReply []byte
ClientFileTransferMgr ClientFileTransferMgr
Logger *slog.Logger
// contains filtered or unexported fields
}
ClientConn represents a client connected to a Server
func (*ClientConn) Authenticate ¶
func (cc *ClientConn) Authenticate(login string, password []byte) bool
func (*ClientConn) Authorize ¶
func (cc *ClientConn) Authorize(access int) bool
Authorize checks if the user account has the specified permission
func (*ClientConn) Disconnect ¶
func (cc *ClientConn) Disconnect()
Disconnect notifies other clients that a client has disconnected and closes the connection.
func (*ClientConn) FileRoot ¶ added in v0.14.0
func (cc *ClientConn) FileRoot() string
func (*ClientConn) NewErrReply ¶
func (cc *ClientConn) NewErrReply(t *Transaction, errMsg string) []Transaction
NewErrReply returns an error reply Transaction with errMsg
func (*ClientConn) NewFileTransfer ¶ added in v0.13.0
func (cc *ClientConn) NewFileTransfer(transferType FileTransferType, fileroot string, fileName, filePath, size []byte) *FileTransfer
func (*ClientConn) NewReply ¶
func (cc *ClientConn) NewReply(t *Transaction, fields ...Field) Transaction
NewReply returns a reply Transaction with fields for the ClientConn
func (*ClientConn) NotifyOthers ¶
func (cc *ClientConn) NotifyOthers(t Transaction) (trans []Transaction)
NotifyOthers sends transaction t to other clients connected to the server
func (*ClientConn) SendAll ¶ added in v0.13.0
func (cc *ClientConn) SendAll(t [2]byte, fields ...Field)
func (*ClientConn) String ¶ added in v0.7.0
func (cc *ClientConn) String() string
type ClientFileTransferMgr ¶ added in v0.13.0
type ClientFileTransferMgr struct {
// contains filtered or unexported fields
}
func NewClientFileTransferMgr ¶ added in v0.13.0
func NewClientFileTransferMgr() ClientFileTransferMgr
func (*ClientFileTransferMgr) Add ¶ added in v0.13.0
func (cftm *ClientFileTransferMgr) Add(ftType FileTransferType, ft *FileTransfer)
func (*ClientFileTransferMgr) Delete ¶ added in v0.13.0
func (cftm *ClientFileTransferMgr) Delete(ftType FileTransferType, id FileTransferID)
func (*ClientFileTransferMgr) Get ¶ added in v0.13.0
func (cftm *ClientFileTransferMgr) Get(ftType FileTransferType) []FileTransfer
type ClientHandler ¶ added in v0.10.20
type ClientHandler func(context.Context, *Client, *Transaction) ([]Transaction, error)
type ClientManager ¶ added in v0.13.0
type ClientManager interface {
List() []*ClientConn // Returns list of sorted clients
Get(id ClientID) *ClientConn
Add(cc *ClientConn)
Delete(id ClientID)
}
type ClientPrefs ¶
type ClientPrefs struct {
Username string `yaml:"Username"`
IconID int `yaml:"IconID"`
Tracker string `yaml:"Tracker"`
EnableBell bool `yaml:"EnableBell"`
}
func (*ClientPrefs) IconBytes ¶
func (cp *ClientPrefs) IconBytes() []byte
type ClientTHandler ¶ added in v0.10.19
type ClientTHandler interface {
Handle(*Client, *Transaction) ([]Transaction, error)
}
type ClientTransaction ¶ added in v0.10.19
type ClientTransaction struct {
Name string
Handler func(*Client, *Transaction) ([]Transaction, error)
}
func (ClientTransaction) Handle ¶ added in v0.10.19
func (ch ClientTransaction) Handle(cc *Client, t *Transaction) ([]Transaction, error)
type Config ¶
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
BannerFile string `yaml:"BannerFile" validate:"omitempty,bannerext"` // Path to Banner jpg or gif
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
NewsDelimiter string `yaml:"NewsDelimiter"` // String used to separate news posts
NewsDateFormat string `yaml:"NewsDateFormat"` // Go template string to customize news date format
MaxDownloads int `yaml:"MaxDownloads"` // Global simultaneous download limit
MaxDownloadsPerClient int `yaml:"MaxDownloadsPerClient"` // Per client simultaneous download limit
MaxConnectionsPerIP int `yaml:"MaxConnectionsPerIP"` // Max connections per IP
PreserveResourceForks bool `yaml:"PreserveResourceForks"` // Enable preservation of file info and resource forks in sidecar files
IgnoreFiles []string `yaml:"IgnoreFiles"` // List of regular expression for filtering files from the file list
EnableBonjour bool `yaml:"EnableBonjour"` // Enable service announcement on local network with Bonjour
}
type Field ¶
type Field struct {
Type FieldType // Type of field
FieldSize [2]byte // Size of the data field
Data []byte // Field data
// contains filtered or unexported fields
}
func GetFileNameList ¶ added in v0.13.0
func (*Field) DecodeInt ¶ added in v0.13.0
DecodeInt decodes the field bytes to an int. The official Hotline clients will send uint32s as 2 bytes if possible, but some third party clients such as Frogblast and Heildrun will always send 4 bytes
func (*Field) DecodeNewsPath ¶ added in v0.13.0
DecodeNewsPath decodes the field data to a news path. Example News Path data for a Category nested under two Bundles: 00000000 00 03 00 00 10 54 6f 70 20 4c 65 76 65 6c 20 42 |.....Top Level B| 00000010 75 6e 64 6c 65 00 00 13 53 65 63 6f 6e 64 20 4c |undle...Second L| 00000020 65 76 65 6c 20 42 75 6e 64 6c 65 00 00 0f 4e 65 |evel Bundle...Ne| 00000030 73 74 65 64 20 43 61 74 65 67 6f 72 79 |sted Category|
func (*Field) DecodeObfuscatedString ¶ added in v0.13.0
type FieldType ¶ added in v0.18.4
type FieldType [2]byte
FieldType represents a Hotline protocol field type identifier
type File ¶ added in v0.19.1
type File struct {
Name string // Name of the file
Ffo *flattenedFileObject
// contains filtered or unexported fields
}
File encapsulates the data, info, and resource forks of a Hotline file and provides methods to manage the files.
func (*File) Delete ¶ added in v0.19.1
Delete a file and its associated metadata files if they exist
func (*File) InfoForkWriter ¶ added in v0.19.1
func (f *File) InfoForkWriter() (io.WriteCloser, error)
func (*File) Move ¶ added in v0.19.1
Move a file and its associated meta files to newPath. Meta files include: * Partially uploaded file ending with .incomplete * Resource fork starting with .rsrc_ * Info fork starting with .info During Move of the meta files, os.ErrNotExist is ignored as these files may legitimately not exist.
type FileHeader ¶
type FileHeader struct {
Size [2]byte // Total size of FileHeader payload
Type [2]byte // 0 for file, 1 for dir
FilePath []byte // encoded file path
// contains filtered or unexported fields
}
func NewFileHeader ¶
func NewFileHeader(fileName string, isDir bool) FileHeader
type FileNameWithInfo ¶
type FileNameWithInfo struct {
FileNameWithInfoHeader
Name []byte // File Name
// contains filtered or unexported fields
}
type FileNameWithInfoHeader ¶ added in v0.13.0
type FileNameWithInfoHeader struct {
Type [4]byte // File type code
Creator [4]byte // File creator code
FileSize [4]byte // File Size in bytes
RSVD [4]byte
NameScript [2]byte // ??
NameSize [2]byte // Length of Name field
}
FileNameWithInfoHeader contains the fixed length fields of FileNameWithInfo
type FilePath ¶
type FilePath struct {
ItemCount [2]byte
Items []FilePathItem
}
func (*FilePath) IsDropbox ¶ added in v0.2.0
IsDropbox checks if a FilePath matches the special drop box folder type
func (*FilePath) IsUploadDir ¶ added in v0.2.0
type FilePathItem ¶
FilePathItem represents the file or directory portion of a delimited file path (e.g. foo and bar in "/foo/bar") Example bytes: 00 00 09 73 75 62 66 6f 6c 64 65 72 "subfolder"
type FileResumeData ¶ added in v0.3.0
type FileResumeData struct {
Format [4]byte // "RFLT"
Version [2]byte // Always 1
RSVD [34]byte // Present in the Hotline protocol docs, but unused. Left here for documentation purposes.
ForkCount [2]byte // Length of ForkInfoList. Either 2 or 3 depending on whether file has a resource fork
ForkInfoList []ForkInfoList
}
FileResumeData is sent when a client or server would like to resume a transfer from an offset
func NewFileResumeData ¶ added in v0.3.0
func NewFileResumeData(list []ForkInfoList) *FileResumeData
func (*FileResumeData) BinaryMarshal ¶ added in v0.3.0
func (frd *FileResumeData) BinaryMarshal() ([]byte, error)
func (*FileResumeData) UnmarshalBinary ¶ added in v0.3.0
func (frd *FileResumeData) UnmarshalBinary(b []byte) error
type FileStore ¶
type FileStore interface {
Create(name string) (*os.File, error)
Mkdir(name string, perm os.FileMode) error
Open(name string) (*os.File, error)
OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error)
Remove(name string) error
RemoveAll(path string) error
Rename(oldpath string, newpath string) error
Stat(name string) (fs.FileInfo, error)
Symlink(oldname, newname string) error
WriteFile(name string, data []byte, perm fs.FileMode) error
ReadFile(name string) ([]byte, error)
}
type FileTransfer ¶
type FileTransfer struct {
FileRoot string
FileName []byte
FilePath []byte
RefNum [4]byte
Type FileTransferType
TransferSize []byte
FolderItemCount []byte
FileResumeData *FileResumeData
Options []byte
ClientConn *ClientConn
// contains filtered or unexported fields
}
func (*FileTransfer) ItemCount ¶ added in v0.3.0
func (ft *FileTransfer) ItemCount() int
func (*FileTransfer) String ¶
func (ft *FileTransfer) String() string
String returns a string representation of a file transfer and its progress for display in the GetInfo window Example: MasterOfOrionII1.4.0. 0% 197.9M
type FileTransferID ¶ added in v0.13.0
type FileTransferID [4]byte
type FileTransferMgr ¶ added in v0.13.0
type FileTransferMgr interface {
Add(ft *FileTransfer)
Get(id FileTransferID) *FileTransfer
Delete(id FileTransferID)
}
type FlatFileForkHeader ¶ added in v0.6.0
type FlatFileHeader ¶
type FlatFileHeader struct {
Format [4]byte // Always "FILP"
Version [2]byte // Always 1
RSVD [16]byte // Always empty zeros
ForkCount [2]byte // Number of forks, either 2 or 3 if there is a resource fork
}
FlatFileHeader is the first section of a "Flattened File Object". All fields have static values.
type FlatFileInformationFork ¶
type FlatFileInformationFork struct {
Platform [4]byte // Operating System used. ("AMAC" or "MWIN")
TypeSignature [4]byte // File type signature
CreatorSignature [4]byte // File creator signature
Flags [4]byte
PlatformFlags [4]byte
RSVD [32]byte
CreateDate [8]byte
ModifyDate [8]byte
NameScript [2]byte
NameSize [2]byte // Length of file name (Maximum 128 characters)
Name []byte // File name
CommentSize [2]byte // Length of the comment
Comment []byte // File comment
// contains filtered or unexported fields
}
func NewFlatFileInformationFork ¶
func NewFlatFileInformationFork(fileName string, modifyTime [8]byte, typeSignature string, creatorSignature string) FlatFileInformationFork
func (*FlatFileInformationFork) DataSize ¶
func (ffif *FlatFileInformationFork) DataSize() []byte
DataSize calculates the size of the flat file information fork, which is 72 bytes for the fixed length fields plus the length of the Name + Comment
func (*FlatFileInformationFork) FriendlyCreator ¶ added in v0.13.0
func (ffif *FlatFileInformationFork) FriendlyCreator() []byte
func (*FlatFileInformationFork) FriendlyType ¶ added in v0.13.0
func (ffif *FlatFileInformationFork) FriendlyType() []byte
func (*FlatFileInformationFork) Read ¶ added in v0.13.0
func (ffif *FlatFileInformationFork) Read(p []byte) (int, error)
func (*FlatFileInformationFork) ReadNameSize ¶
func (ffif *FlatFileInformationFork) ReadNameSize() []byte
func (*FlatFileInformationFork) SetComment ¶ added in v0.13.0
func (ffif *FlatFileInformationFork) SetComment(comment []byte) error
func (*FlatFileInformationFork) Size ¶ added in v0.6.0
func (ffif *FlatFileInformationFork) Size() [4]byte
func (*FlatFileInformationFork) UnmarshalBinary ¶ added in v0.2.1
func (ffif *FlatFileInformationFork) UnmarshalBinary(b []byte) error
type ForkInfoList ¶ added in v0.3.0
type ForkInfoList struct {
Fork ForkType // "DATA", "INFO", or "MACR"
DataSize [4]byte // offset from which to resume the transfer of data
RSVDA [4]byte // Present in the Hotline protocol docs, but unused. Left here for documentation purposes.
RSVDB [4]byte // Present in the Hotline protocol docs, but unused. Left here for documentation purposes.
}
func NewForkInfoList ¶ added in v0.3.0
func NewForkInfoList(b []byte) *ForkInfoList
type ForkType ¶ added in v0.19.0
type ForkType [4]byte
ForkType represents a 4-byte fork type identifier
type HandlerFunc ¶ added in v0.10.19
type HandlerFunc func(*ClientConn, *Transaction) []Transaction
HandlerFunc is the signature of a func to handle a Hotline transaction.
type MemChatManager ¶ added in v0.13.0
type MemChatManager struct {
// contains filtered or unexported fields
}
func NewMemChatManager ¶ added in v0.13.0
func NewMemChatManager() *MemChatManager
func (*MemChatManager) GetSubject ¶ added in v0.13.0
func (cm *MemChatManager) GetSubject(id ChatID) string
func (*MemChatManager) Join ¶ added in v0.13.0
func (cm *MemChatManager) Join(id ChatID, cc *ClientConn)
func (*MemChatManager) Leave ¶ added in v0.13.0
func (cm *MemChatManager) Leave(id ChatID, clientID [2]byte)
func (*MemChatManager) Members ¶ added in v0.13.0
func (cm *MemChatManager) Members(id ChatID) []*ClientConn
func (*MemChatManager) New ¶ added in v0.13.0
func (cm *MemChatManager) New(cc *ClientConn) ChatID
func (*MemChatManager) SetSubject ¶ added in v0.13.0
func (cm *MemChatManager) SetSubject(id ChatID, subject string)
type MemClientMgr ¶ added in v0.13.0
type MemClientMgr struct {
// contains filtered or unexported fields
}
func NewMemClientMgr ¶ added in v0.13.0
func NewMemClientMgr() *MemClientMgr
func (*MemClientMgr) Add ¶ added in v0.13.0
func (cm *MemClientMgr) Add(cc *ClientConn)
func (*MemClientMgr) Delete ¶ added in v0.13.0
func (cm *MemClientMgr) Delete(id ClientID)
func (*MemClientMgr) Get ¶ added in v0.13.0
func (cm *MemClientMgr) Get(id ClientID) *ClientConn
func (*MemClientMgr) List ¶ added in v0.13.0
func (cm *MemClientMgr) List() []*ClientConn
List returns slice of sorted clients.
type MemFileTransferMgr ¶ added in v0.13.0
type MemFileTransferMgr struct {
// contains filtered or unexported fields
}
func NewMemFileTransferMgr ¶ added in v0.13.0
func NewMemFileTransferMgr() *MemFileTransferMgr
func (*MemFileTransferMgr) Add ¶ added in v0.13.0
func (ftm *MemFileTransferMgr) Add(ft *FileTransfer)
func (*MemFileTransferMgr) Delete ¶ added in v0.13.0
func (ftm *MemFileTransferMgr) Delete(id FileTransferID)
func (*MemFileTransferMgr) Get ¶ added in v0.13.0
func (ftm *MemFileTransferMgr) Get(id FileTransferID) *FileTransfer
type MockChatManager ¶ added in v0.13.0
func (*MockChatManager) GetSubject ¶ added in v0.13.0
func (m *MockChatManager) GetSubject(id ChatID) string
func (*MockChatManager) Join ¶ added in v0.13.0
func (m *MockChatManager) Join(id ChatID, cc *ClientConn)
func (*MockChatManager) Leave ¶ added in v0.13.0
func (m *MockChatManager) Leave(id ChatID, clientID [2]byte)
func (*MockChatManager) Members ¶ added in v0.13.0
func (m *MockChatManager) Members(id ChatID) []*ClientConn
func (*MockChatManager) New ¶ added in v0.13.0
func (m *MockChatManager) New(cc *ClientConn) ChatID
func (*MockChatManager) SetSubject ¶ added in v0.13.0
func (m *MockChatManager) SetSubject(id ChatID, subject string)
type MockClientMgr ¶ added in v0.13.0
func (*MockClientMgr) Add ¶ added in v0.13.0
func (m *MockClientMgr) Add(cc *ClientConn)
func (*MockClientMgr) Delete ¶ added in v0.13.0
func (m *MockClientMgr) Delete(id ClientID)
func (*MockClientMgr) Get ¶ added in v0.13.0
func (m *MockClientMgr) Get(id ClientID) *ClientConn
func (*MockClientMgr) List ¶ added in v0.13.0
func (m *MockClientMgr) List() []*ClientConn
type MockFileInfo ¶ added in v0.6.0
func (*MockFileInfo) IsDir ¶ added in v0.6.0
func (mfi *MockFileInfo) IsDir() bool
func (*MockFileInfo) ModTime ¶ added in v0.6.0
func (mfi *MockFileInfo) ModTime() time.Time
func (*MockFileInfo) Mode ¶ added in v0.6.0
func (mfi *MockFileInfo) Mode() fs.FileMode
func (*MockFileInfo) Name ¶ added in v0.6.0
func (mfi *MockFileInfo) Name() string
func (*MockFileInfo) Size ¶ added in v0.6.0
func (mfi *MockFileInfo) Size() int64
func (*MockFileInfo) Sys ¶ added in v0.6.0
func (mfi *MockFileInfo) Sys() interface{}
type MockFileStore ¶
func (*MockFileStore) Create ¶ added in v0.2.1
func (mfs *MockFileStore) Create(name string) (*os.File, error)
func (*MockFileStore) Open ¶ added in v0.0.13
func (mfs *MockFileStore) Open(name string) (*os.File, error)
func (*MockFileStore) ReadFile ¶ added in v0.6.0
func (mfs *MockFileStore) ReadFile(name string) ([]byte, error)
func (*MockFileStore) Remove ¶ added in v0.2.0
func (mfs *MockFileStore) Remove(name string) error
func (*MockFileStore) RemoveAll ¶ added in v0.6.0
func (mfs *MockFileStore) RemoveAll(name string) error
func (*MockFileStore) Rename ¶ added in v0.6.0
func (mfs *MockFileStore) Rename(oldpath, newpath string) error
func (*MockFileStore) Symlink ¶ added in v0.2.0
func (mfs *MockFileStore) Symlink(oldname, newname string) error
type MockThreadNewsMgr ¶ added in v0.13.0
func (*MockThreadNewsMgr) CreateGrouping ¶ added in v0.13.0
func (m *MockThreadNewsMgr) CreateGrouping(newsPath []string, name string, itemType [2]byte) error
func (*MockThreadNewsMgr) DeleteArticle ¶ added in v0.13.0
func (m *MockThreadNewsMgr) DeleteArticle(newsPath []string, articleID uint32, recursive bool) error
func (*MockThreadNewsMgr) DeleteNewsItem ¶ added in v0.13.0
func (m *MockThreadNewsMgr) DeleteNewsItem(newsPath []string) error
func (*MockThreadNewsMgr) GetArticle ¶ added in v0.13.0
func (m *MockThreadNewsMgr) GetArticle(newsPath []string, articleID uint32) *NewsArtData
func (*MockThreadNewsMgr) GetCategories ¶ added in v0.13.0
func (m *MockThreadNewsMgr) GetCategories(paths []string) []NewsCategoryListData15
func (*MockThreadNewsMgr) ListArticles ¶ added in v0.13.0
func (m *MockThreadNewsMgr) ListArticles(newsPath []string) (NewsArtListData, error)
func (*MockThreadNewsMgr) NewsItem ¶ added in v0.13.0
func (m *MockThreadNewsMgr) NewsItem(newsPath []string) NewsCategoryListData15
func (*MockThreadNewsMgr) PostArticle ¶ added in v0.13.0
func (m *MockThreadNewsMgr) PostArticle(newsPath []string, parentArticleID uint32, article NewsArtData) error
type NewsArtData ¶
type NewsArtData struct {
Title string `yaml:"Title"`
Poster string `yaml:"Poster"`
Date [8]byte `yaml:"Date,flow"`
PrevArt [4]byte `yaml:"PrevArt,flow"`
NextArt [4]byte `yaml:"NextArt,flow"`
ParentArt [4]byte `yaml:"ParentArt,flow"`
FirstChildArt [4]byte `yaml:"FirstChildArtArt,flow"`
DataFlav []byte `yaml:"-"` // MIME type string. Always "text/plain".
Data string `yaml:"Data"`
}
NewsArtData represents an individual news article.
func (*NewsArtData) DataSize ¶
func (art *NewsArtData) DataSize() [2]byte
type NewsArtList ¶
type NewsArtList struct {
ID [4]byte
TimeStamp [8]byte // Year (2 bytes), milliseconds (2 bytes) and seconds (4 bytes)
ParentID [4]byte
Flags [4]byte
FlavorCount [2]byte
// Title size 1
Title []byte // string
// Poster size 1
// Poster Poster string
Poster []byte
FlavorList []NewsFlavorList
// Flavor list… Optional (if flavor count > 0)
ArticleSize [2]byte // Size 2
// contains filtered or unexported fields
}
NewsArtList is a summarized version of a NewArtData record for display in list view
type NewsArtListData ¶
type NewsArtListData struct {
ID [4]byte `yaml:"Type"`
Name []byte `yaml:"Name"`
Description []byte `yaml:"Description"` // not used?
NewsArtList []byte // List of articles Optional (if article count > 0)
Count int
// contains filtered or unexported fields
}
type NewsCategoryListData15 ¶
type NewsCategoryListData15 struct {
Type [2]byte `yaml:"Type,flow"` // Bundle (2) or category (3)
Name string `yaml:"Name"`
Articles map[uint32]*NewsArtData `yaml:"Articles"` // Optional, if Type is Category
SubCats map[string]NewsCategoryListData15 `yaml:"SubCats"`
GUID [16]byte `yaml:"-"` // What does this do? Undocumented and seeming unused.
AddSN [4]byte `yaml:"-"` // What does this do? Undocumented and seeming unused.
DeleteSN [4]byte `yaml:"-"` // What does this do? Undocumented and seeming unused.
// contains filtered or unexported fields
}
func (*NewsCategoryListData15) GetNewsArtListData ¶
func (newscat *NewsCategoryListData15) GetNewsArtListData() (NewsArtListData, error)
type NewsFlavorList ¶
type NewsFlavorList struct {
}
type OSFileStore ¶
type OSFileStore struct{}
func (*OSFileStore) Create ¶ added in v0.2.1
func (fs *OSFileStore) Create(name string) (*os.File, error)
func (*OSFileStore) Open ¶ added in v0.0.13
func (fs *OSFileStore) Open(name string) (*os.File, error)
func (*OSFileStore) ReadFile ¶ added in v0.6.0
func (fs *OSFileStore) ReadFile(name string) ([]byte, error)
func (*OSFileStore) Remove ¶ added in v0.2.0
func (fs *OSFileStore) Remove(name string) error
func (*OSFileStore) RemoveAll ¶ added in v0.6.0
func (fs *OSFileStore) RemoveAll(name string) error
func (*OSFileStore) Rename ¶ added in v0.6.0
func (fs *OSFileStore) Rename(oldpath string, newpath string) error
func (*OSFileStore) Symlink ¶ added in v0.2.0
func (fs *OSFileStore) Symlink(oldname, newname string) error
type PrivateChat ¶
type PrivateChat struct {
Subject string
ClientConn map[[2]byte]*ClientConn
}
type RealDialer ¶ added in v0.13.0
type RealDialer struct{}
RealDialer is the real implementation of the Dialer interface
type RealTrackerRegistrar ¶ added in v0.19.0
type RealTrackerRegistrar struct {
// contains filtered or unexported fields
}
RealTrackerRegistrar implements TrackerRegistrar using the real network operations
func NewRealTrackerRegistrar ¶ added in v0.19.0
func NewRealTrackerRegistrar() *RealTrackerRegistrar
func (*RealTrackerRegistrar) Register ¶ added in v0.19.0
func (r *RealTrackerRegistrar) Register(tracker string, registration *TrackerRegistration) error
type Server ¶
type Server struct {
NetInterface string
Port int
Config Config
Logger *slog.Logger
TrackerPassID [4]byte
Stats Counter
FS FileStore // Storage backend to use for File storage
Agreement io.ReadSeeker
Banner []byte
FileTransferMgr FileTransferMgr
ChatMgr ChatManager
ClientMgr ClientManager
AccountManager AccountManager
ThreadedNewsMgr ThreadedNewsMgr
BanList BanMgr
MessageBoard io.ReadWriteSeeker
Redis *redis.Client
// TrackerRegistrar handles tracker registration (injectable for testing)
TrackerRegistrar TrackerRegistrar
TLSConfig *tls.Config
TLSPort int
// contains filtered or unexported fields
}
func (*Server) CurrentStats ¶ added in v0.9.0
func (*Server) HandleFunc ¶ added in v0.13.0
func (s *Server) HandleFunc(tranType [2]byte, handler HandlerFunc)
func (*Server) NewClientConn ¶
func (s *Server) NewClientConn(conn io.ReadWriteCloser, remoteAddr string) *ClientConn
func (*Server) ServeFileTransfers ¶
func (*Server) ServeFileTransfersWithTLS ¶ added in v0.20.0
func (*Server) ServeWithTLS ¶ added in v0.20.0
type ServerConfig ¶ added in v0.13.0
type ServerConfig struct {
}
type ServerInfoHeader ¶
type ServerInfoHeader struct {
MsgType [2]byte // Always has value of 1
MsgDataSize [2]byte // Remaining size of request
SrvCount [2]byte // Total number of servers across all batches
BatchSize [2]byte // Number of servers in the current batch
}
ServerInfoHeader represents a batch header in the tracker response. The tracker protocol splits large server lists into batches, with each batch preceded by its own ServerInfoHeader. The first header indicates the total number of servers across all batches, and each header (including the first) indicates how many servers are in the current batch.
Example flow for 106 servers split into batches:
- First ServerInfoHeader: SrvCount=106, BatchSize=97
- Read 97 ServerRecords
- Second ServerInfoHeader: SrvCount=106, BatchSize=9
- Read 9 ServerRecords (total: 106)
type ServerRecord ¶
type ServerRecord struct {
IPAddr [4]byte
Port [2]byte
NumUsers [2]byte // Number of users connected to this particular server
TLSPort [2]byte
NameSize byte // Length of Name string
Name []byte // Server Name
DescriptionSize byte
Description []byte
}
ServerRecord is a tracker listing for a single server
func GetListing ¶
func GetListing(conn io.ReadWriteCloser) ([]ServerRecord, error)
func (*ServerRecord) Addr ¶
func (s *ServerRecord) Addr() string
type ThreadedNews ¶
type ThreadedNews struct {
Categories map[string]NewsCategoryListData15 `yaml:"Categories"`
}
ThreadedNews contains the top level of threaded news categories, bundles, and articles.
type ThreadedNewsMgr ¶ added in v0.13.0
type ThreadedNewsMgr interface {
ListArticles(newsPath []string) (NewsArtListData, error)
GetArticle(newsPath []string, articleID uint32) *NewsArtData
DeleteArticle(newsPath []string, articleID uint32, recursive bool) error
PostArticle(newsPath []string, parentArticleID uint32, article NewsArtData) error
CreateGrouping(newsPath []string, name string, t [2]byte) error
GetCategories(paths []string) []NewsCategoryListData15
NewsItem(newsPath []string) NewsCategoryListData15
DeleteNewsItem(newsPath []string) error
}
type Time ¶ added in v0.13.0
type Time [8]byte
func NewTime ¶ added in v0.13.0
NewTime converts a time.Time to the 8 byte Hotline time format: Year (2 bytes), milliseconds (2 bytes) and seconds (4 bytes)
type TrackerHeader ¶
type TrackerHeader struct {
Protocol [4]byte // "HTRK" 0x4854524B
Version [2]byte // Old protocol (1) or new (2)
}
TrackerHeader is sent in reply Reply received from the tracker starts with a header:
type TrackerRegistrar ¶ added in v0.19.0
type TrackerRegistrar interface {
Register(tracker string, registration *TrackerRegistration) error
}
TrackerRegistrar interface for tracker registration operations
type TrackerRegistration ¶
type TrackerRegistration struct {
Port [2]byte // Server's listening TCP port number
UserCount int // Number of users connected to this particular server
TLSPort [2]byte // TLSPort
PassID [4]byte // Random number generated by the server
Name string // Server Name
Description string // Description of the server
Password string // Tracker password, if required by tracker
// contains filtered or unexported fields
}
TrackerRegistration represents the payload a Hotline server sends to a Tracker to register
type Transaction ¶
type Transaction struct {
Flags byte // Reserved (should be 0)
IsReply byte // Request (0) or reply (1)
Type TranType // Requested operation (user defined)
ID [4]byte // Unique transaction ID (must be != 0)
ErrorCode [4]byte // Used in the reply (user defined, 0 = no error)
TotalSize [4]byte // Total data size for the fields in this transaction.
DataSize [4]byte // Size of data in this transaction part. This allows splitting large transactions into smaller parts.
ParamCount [2]byte // Number of the parameters for this transaction
Fields []Field
ClientID ClientID // Internal identifier for target client
// contains filtered or unexported fields
}
func NewTransaction ¶
func NewTransaction(t TranType, clientID ClientID, fields ...Field) Transaction
NewTransaction creates a new Transaction with the specified type, client, and optional fields.
func (*Transaction) GetField ¶
func (t *Transaction) GetField(id FieldType) *Field
func (*Transaction) Read ¶ added in v0.13.0
func (t *Transaction) Read(p []byte) (int, error)
Read implements the io.Reader interface for Transaction
func (*Transaction) Size ¶
func (t *Transaction) Size() []byte
Size returns the total size of the transaction payload
func (*Transaction) Write ¶ added in v0.8.3
func (t *Transaction) Write(p []byte) (n int, err error)
Write implements io.Writer interface for Transaction. Transactions read from the network are read as complete tokens with a bufio.Scanner, so the arg p is guaranteed to have the full byte payload of a complete transaction.
type User ¶
type WriteCounter ¶ added in v0.7.0
type WriteCounter struct {
Total int64 // Total # of bytes written
// contains filtered or unexported fields
}
WriteCounter counts the number of bytes written to it.
Source Files
¶
- access.go
- account.go
- account_manager.go
- ban.go
- chat.go
- client.go
- client_conn.go
- client_manager.go
- config.go
- doc.go
- field.go
- file_name_with_info.go
- file_path.go
- file_resume_data.go
- file_store.go
- file_transfer.go
- file_types.go
- file_wrapper.go
- files.go
- flattened_file_object.go
- handshake.go
- logger.go
- message_board.go
- news.go
- panic.go
- server.go
- stats.go
- time.go
- tracker.go
- transaction.go
- transaction_handlers.go
- transfer.go
- user.go