Documentation ¶
Index ¶
- Constants
- Variables
- func CalcItemCount(filePath string) ([]byte, error)
- func CalcTotalSize(filePath string) ([]byte, error)
- func DecodeUserString(obfuText []byte) (clearText string)
- func EncodeFilePath(filePath string) []byte
- func Handshake(rw io.ReadWriter) error
- func ReadNewsPath(newsPath []byte) []string
- type Account
- type Bookmark
- type Client
- 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) NewErrReply(t *Transaction, errMsg string) Transaction
- func (cc *ClientConn) NewReply(t *Transaction, fields ...Field) Transaction
- func (cc *ClientConn) String() string
- type ClientPrefs
- type Config
- type DebugBuffer
- type Field
- type FileHeader
- type FileNameWithInfo
- type FilePath
- type FilePathItem
- type FileResumeData
- type FileStore
- type FileTransfer
- type FlatFileForkHeader
- type FlatFileHeader
- type FlatFileInformationFork
- type ForkInfoList
- 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 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 PrivateChat
- type Server
- func (s *Server) CurrentStats() Stats
- func (s *Server) DeleteUser(login string) error
- func (s *Server) GetNewsCatByPath(paths []string) map[string]NewsCategoryListData15
- func (s *Server) ListenAndServe(ctx context.Context, cancelRoot context.CancelFunc) error
- func (s *Server) NewClientConn(conn io.ReadWriteCloser, remoteAddr string) *ClientConn
- func (s *Server) NewPrivateChat(cc *ClientConn) []byte
- func (s *Server) NewUser(login, name, password string, access accessBitmap) error
- 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) UpdateUser(login, newLogin, name, password string, access accessBitmap) error
- type ServerInfoHeader
- type ServerRecord
- type Stats
- type ThreadedNews
- type TrackerHeader
- type TrackerRegistration
- type Transaction
- func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDelNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDelNewsItem(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDeleteFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDeleteUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDisconnectUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDownloadBanner(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDownloadFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetClientInfoText(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetMsgs(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetNewsArtData(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetNewsArtNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetNewsCatNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleGetUserNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleInviteNewChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleInviteToChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleJoinChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleKeepAlive(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleLeaveChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleListUsers(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleMakeAlias(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleMoveFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleNewFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleNewNewsCat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleNewNewsFldr(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleNewUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandlePostNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleRejectChatInvite(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleSetChatSubject(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleSetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleTranOldPostNews(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleUpdateUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func HandleUserBroadcast(cc *ClientConn, t *Transaction) (res []Transaction, err error)
- func NewTransaction(t int, clientID *[]byte, fields ...Field) *Transaction
- type TransactionType
- type UI
- type User
- type WriteCounter
Constants ¶
const ( FileDownload = 0 FileUpload = 1 FolderDownload = 2 FolderUpload = 3 )
File transfer types
const GuestAccount = "guest" // default account used when no login is provided for a connection
const VERSION = "0.10.4"
Variables ¶
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,
}
var TransactionHandlers = map[uint16]TransactionType{ // contains filtered or unexported fields }
Functions ¶
func CalcItemCount ¶
func CalcTotalSize ¶
func DecodeUserString ¶
DecodeUserString decodes an obfuscated user string from a client e.g. 98 8a 9a 8c 8b => "guest"
func EncodeFilePath ¶
func Handshake ¶
func Handshake(rw io.ReadWriter) error
Handshake After establishing TCP connection, both client and server start the handshake process in order to confirm that each of them comply with requirements of the other. The information provided in this initial data exchange identifies protocols, and their versions, used in the communication. In the case where, after inspection, the capabilities of one of the subjects do not comply with the requirements of the other, the connection is dropped.
The following information is sent to the server: Description Size Data Note Protocol ID 4 TRTP 0x54525450 Sub-protocol ID 4 HOTL User defined VERSION 2 1 Currently 1 Sub-version 2 2 User defined
The server replies with the following: Description Size Data Note Protocol ID 4 TRTP Error code 4 Error code returned by the server (0 = no error)
func ReadNewsPath ¶
TODO: re-implement as bufio.Scanner interface
Types ¶
type Account ¶
type Client ¶
type Client struct { DebugBuf *DebugBuffer Connection net.Conn Login *[]byte Password *[]byte Flags *[]byte ID *[]byte Version []byte UserAccess []byte UserList []User Logger *zap.SugaredLogger Handlers map[uint16]clientTHandler UI *UI Inbox chan *Transaction // contains filtered or unexported fields }
func (*Client) Disconnect ¶
func (*Client) HandleTransaction ¶
func (c *Client) HandleTransaction(t *Transaction) error
func (*Client) JoinServer ¶
JoinServer connects to a Hotline server and completes the login flow
func (*Client) Send ¶
func (c *Client) Send(t Transaction) error
type ClientConn ¶
type ClientConn struct { Connection io.ReadWriteCloser RemoteAddr string ID *[]byte Icon []byte Flags []byte UserName []byte Account *Account IdleTime int Server *Server Version []byte Idle bool AutoReply []byte Agreed bool // 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
func (*ClientConn) NewErrReply ¶
func (cc *ClientConn) NewErrReply(t *Transaction, errMsg string) Transaction
NewErrReply returns an error reply Transaction with errMsg
func (*ClientConn) NewReply ¶
func (cc *ClientConn) NewReply(t *Transaction, fields ...Field) Transaction
NewReply returns a reply Transaction with fields for the ClientConn
func (*ClientConn) String ¶ added in v0.7.0
func (cc *ClientConn) String() string
type ClientPrefs ¶
type ClientPrefs struct { Username string `yaml:"Username"` IconID int `yaml:"IconID"` Bookmarks []Bookmark `yaml:"Bookmarks"` Tracker string `yaml:"Tracker"` }
func (*ClientPrefs) AddBookmark ¶
func (cp *ClientPrefs) AddBookmark(name, addr, login, pass string) error
func (*ClientPrefs) IconBytes ¶
func (cp *ClientPrefs) IconBytes() []byte
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"` // 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 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 }
type DebugBuffer ¶
DebugBuffer wraps a *tview.TextView and adds a Sync() method to make it available as a Zap logger
func (*DebugBuffer) Sync ¶
func (db *DebugBuffer) Sync() error
Sync is a noop function that dataFile to satisfy the zapcore.WriteSyncer interface
type Field ¶
type FileHeader ¶
type FileHeader struct { Size []byte // Total size of FileHeader payload Type []byte // 0 for file, 1 for dir FilePath []byte // encoded file path }
func NewFileHeader ¶
func NewFileHeader(fileName string, isDir bool) FileHeader
func (*FileHeader) Payload ¶
func (fh *FileHeader) Payload() []byte
type FileNameWithInfo ¶
type FileNameWithInfo struct {
// contains filtered or unexported fields
}
func (*FileNameWithInfo) MarshalBinary ¶
func (f *FileNameWithInfo) MarshalBinary() (data []byte, err error)
func (*FileNameWithInfo) UnmarshalBinary ¶
func (f *FileNameWithInfo) UnmarshalBinary(data []byte) error
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 // Unused 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 { FileName []byte FilePath []byte ReferenceNumber []byte Type int TransferSize []byte FolderItemCount []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 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 []byte // Operating System used. ("AMAC" or "MWIN") TypeSignature []byte // File type signature CreatorSignature []byte // File creator signature Flags []byte PlatformFlags []byte RSVD []byte CreateDate []byte ModifyDate []byte NameScript []byte NameSize []byte // Length of file name (Maximum 128 characters) Name []byte // File name CommentSize []byte // Length of the comment Comment []byte // File comment }
func NewFlatFileInformationFork ¶
func NewFlatFileInformationFork(fileName string, modifyTime []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) MarshalBinary ¶ added in v0.6.0
func (ffif *FlatFileInformationFork) MarshalBinary() []byte
func (*FlatFileInformationFork) ReadNameSize ¶
func (ffif *FlatFileInformationFork) ReadNameSize() []byte
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 [4]byte // "DATA" or "MACR" DataSize [4]byte // offset from which to resume the transfer of data RSVDA [4]byte // Unused RSVDB [4]byte // Unused }
func NewForkInfoList ¶ added in v0.3.0
func NewForkInfoList(b []byte) *ForkInfoList
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 NewsArtData ¶
type NewsArtData struct { Title string `yaml:"Title"` Poster string `yaml:"Poster"` Date []byte `yaml:"Date"` // size 8 PrevArt []byte `yaml:"PrevArt"` // size 4 NextArt []byte `yaml:"NextArt"` // size 4 ParentArt []byte `yaml:"ParentArt"` // size 4 FirstChildArt []byte `yaml:"FirstChildArtArt"` // size 4 DataFlav []byte `yaml:"DataFlav"` // "text/plain" Data string `yaml:"Data"` }
NewsArtData represents single news article
func (*NewsArtData) DataSize ¶
func (art *NewsArtData) DataSize() []byte
type NewsArtList ¶
type NewsArtList struct { ID []byte // Size 4 TimeStamp []byte // Year (2 bytes), milliseconds (2 bytes) and seconds (4 bytes) ParentID []byte // Size 4 Flags []byte // Size 4 FlavorCount []byte // Size 2 // Title size 1 Title []byte // string // Poster size 1 // Poster Poster string Poster []byte FlavorList []NewsFlavorList // Flavor list… Optional (if flavor count > 0) ArticleSize []byte // Size 2 }
NewsArtList is a summarized version of a NewArtData record for display in list view
func (*NewsArtList) Payload ¶
func (nal *NewsArtList) Payload() []byte
type NewsArtListData ¶
type NewsArtListData struct { ID []byte `yaml:"ID"` // Size 4 Name []byte `yaml:"Name"` Description []byte `yaml:"Description"` // not used? NewsArtList []byte // List of articles Optional (if article count > 0) }
func (*NewsArtListData) Payload ¶
func (nald *NewsArtListData) Payload() []byte
type NewsCategoryListData15 ¶
type NewsCategoryListData15 struct { Type []byte `yaml:"Type"` // Size 2 ; Bundle (2) or category (3) Count []byte // Article or SubCategory count Size 2 NameSize byte Name string `yaml:"Name"` // Articles map[uint32]*NewsArtData `yaml:"Articles"` // Optional, if Type is Category SubCats map[string]NewsCategoryListData15 `yaml:"SubCats"` GUID []byte // Size 16 AddSN []byte // Size 4 DeleteSN []byte // Size 4 }
func ReadNewsCategoryListData ¶
func ReadNewsCategoryListData(payload []byte) NewsCategoryListData15
ReadNewsCategoryListData parses a byte slice into a NewsCategoryListData15 struct For use on the client side
func (*NewsCategoryListData15) GetNewsArtListData ¶
func (newscat *NewsCategoryListData15) GetNewsArtListData() NewsArtListData
func (*NewsCategoryListData15) MarshalBinary ¶
func (newscat *NewsCategoryListData15) MarshalBinary() (data []byte, err 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[uint16]*ClientConn }
type Server ¶
type Server struct { Port int Accounts map[string]*Account Agreement []byte Clients map[uint16]*ClientConn Config *Config ConfigDir string Logger *zap.SugaredLogger PrivateChatsMu sync.Mutex PrivateChats map[uint32]*PrivateChat NextGuestID *uint16 TrackerPassID [4]byte StatsMu sync.Mutex Stats *Stats FS FileStore // Storage backend to use for File storage ThreadedNews *ThreadedNews FlatNews []byte // contains filtered or unexported fields }
func NewServer ¶
func NewServer(configDir string, netPort int, logger *zap.SugaredLogger, FS FileStore) (*Server, error)
NewServer constructs a new Server from a config dir
func (*Server) CurrentStats ¶ added in v0.9.0
func (*Server) DeleteUser ¶
DeleteUser deletes the user account
func (*Server) GetNewsCatByPath ¶
func (s *Server) GetNewsCatByPath(paths []string) map[string]NewsCategoryListData15
func (*Server) ListenAndServe ¶
func (*Server) NewClientConn ¶
func (s *Server) NewClientConn(conn io.ReadWriteCloser, remoteAddr string) *ClientConn
func (*Server) NewPrivateChat ¶
func (s *Server) NewPrivateChat(cc *ClientConn) []byte
func (*Server) ServeFileTransfers ¶
func (*Server) UpdateUser ¶ added in v0.3.1
type ServerInfoHeader ¶
type ServerInfoHeader struct { MsgType [2]byte // always has value of 1 MsgDataSize [2]byte // Remaining size of request SrvCount [2]byte // Number of servers in the server list SrvCountDup [2]byte // Same as previous field ¯\_(ツ)_/¯ }
Message type 2 1 Sending list of servers Message data size 2 Remaining size of this request Number of servers 2 Number of servers in the server list Number of servers 2 Same as previous field
type ServerRecord ¶
type ServerRecord struct { 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 name DescriptionSize byte Description []byte }
func GetListing ¶
func GetListing(addr string) ([]ServerRecord, error)
func (*ServerRecord) Addr ¶
func (s *ServerRecord) Addr() string
type ThreadedNews ¶
type ThreadedNews struct {
Categories map[string]NewsCategoryListData15 `yaml:"Categories"`
}
type TrackerHeader ¶
type TrackerHeader struct { Protocol [4]byte // "HTRK" 0x4854524B Version [2]byte // Old protocol (1) or new (2) }
Reply received from the tracker starts with a header:
type TrackerRegistration ¶
type TrackerRegistration struct { Port [2]byte // Server listening port number UserCount int // Number of users connected to this particular server PassID []byte // Random number generated by the server Name string // Server name Description string // Description of the server }
TrackerRegistration represents the payload a Hotline server sends to a Tracker to register
func (*TrackerRegistration) Read ¶ added in v0.8.3
func (tr *TrackerRegistration) Read() []byte
TODO: reimplement as io.Reader
type Transaction ¶
type Transaction struct { Flags byte // Reserved (should be 0) IsReply byte // Request (0) or reply (1) Type []byte // Requested operation (user defined) ID []byte // Unique transaction ID (must be != 0) ErrorCode []byte // Used in the reply (user defined, 0 = no error) TotalSize []byte // Total data size for the transaction (all parts) DataSize []byte // Size of data in this transaction part. This allows splitting large transactions into smaller parts. ParamCount []byte // Number of the parameters for this transaction Fields []Field // contains filtered or unexported fields }
func HandleChatSend ¶
func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleDelNewsArt ¶
func HandleDelNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleDelNewsItem ¶
func HandleDelNewsItem(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleDelNewsItem deletes an existing threaded news folder or category from the server. Fields used in the request: 325 News path Fields used in the reply: None
func HandleDeleteFile ¶
func HandleDeleteFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleDeleteFile deletes a file or folder Fields used in the request: * 201 File name * 202 File path Fields used in the reply: none
func HandleDeleteUser ¶
func HandleDeleteUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleDisconnectUser ¶
func HandleDisconnectUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleDownloadBanner ¶ added in v0.6.0
func HandleDownloadBanner(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleDownloadBanner handles requests for a new banner from the server Fields used in the request: None Fields used in the reply: 107 fieldRefNum Used later for transfer 108 fieldTransferSize Size of data to be downloaded
func HandleDownloadFile ¶
func HandleDownloadFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleDownloadFolder ¶
func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error)
Download all files from the specified folder and sub-folders
func HandleGetClientInfoText ¶ added in v0.7.0
func HandleGetClientInfoText(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleGetClientInfoText returns user information for the specific user.
Fields used in the request: 103 User ID
Fields used in the reply: 102 User name 101 Data User info text string
func HandleGetFileInfo ¶
func HandleGetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleGetFileNameList ¶
func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleGetMsgs ¶
func HandleGetMsgs(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleGetMsgs returns the flat news data
func HandleGetNewsArtData ¶
func HandleGetNewsArtData(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleGetNewsArtNameList ¶
func HandleGetNewsArtNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
Fields used in the request: 325 News path Optional
Reply fields: 321 News article list data Optional
func HandleGetNewsCatNameList ¶
func HandleGetNewsCatNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleGetNewsCatNameList returns a list of news categories for a path Fields used in the request: 325 News path (Optional)
func HandleGetUser ¶
func HandleGetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleGetUserNameList ¶
func HandleGetUserNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleInviteNewChat ¶
func HandleInviteNewChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleInviteNewChat invites users to new private chat
func HandleInviteToChat ¶
func HandleInviteToChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleJoinChat ¶
func HandleJoinChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleJoinChat is sent from a v1.8+ Hotline client when the joins a private chat Fields used in the reply: * 115 Chat subject * 300 User name with info (Optional) * 300 (more user names with info)
func HandleKeepAlive ¶
func HandleKeepAlive(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleKeepAlive responds to keepalive transactions with an empty reply * HL 1.9.2 Client sends keepalive msg every 3 minutes * HL 1.2.3 Client doesn't send keepalives
func HandleLeaveChat ¶
func HandleLeaveChat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleLeaveChat is sent from a v1.8+ Hotline client when the user exits a private chat Fields used in the request:
- 114 fieldChatID
Reply is not expected.
func HandleListUsers ¶
func HandleListUsers(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleMakeAlias ¶ added in v0.2.0
func HandleMakeAlias(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleMakeAlias makes a filer alias using the specified path. Fields used in the request: 201 File name 202 File path 212 File new path Destination path
Fields used in the reply: None
func HandleMoveFile ¶
func HandleMoveFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleMoveFile moves files or folders. Note: seemingly not documented
func HandleNewFolder ¶
func HandleNewFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleNewNewsCat ¶
func HandleNewNewsCat(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleNewNewsFldr ¶
func HandleNewNewsFldr(cc *ClientConn, t *Transaction) (res []Transaction, err error)
Fields used in the request: 322 News category name 325 News path
func HandleNewUser ¶
func HandleNewUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleNewUser creates a new user account
func HandlePostNewsArt ¶
func HandlePostNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err error)
Request fields 325 News path 326 News article ID ID of the parent article? 328 News article title 334 News article flags 327 News article data flavor Currently “text/plain” 333 News article data
func HandleRejectChatInvite ¶
func HandleRejectChatInvite(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleSendInstantMsg ¶
func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleSendInstantMsg sends instant message to the user on the current server. Fields used in the request:
103 User ID 113 Options One of the following values: - User message (myOpt_UserMessage = 1) - Refuse message (myOpt_RefuseMessage = 2) - Refuse chat (myOpt_RefuseChat = 3) - Automatic response (myOpt_AutomaticResponse = 4)" 101 Data Optional 214 Quoting message Optional
Fields used in the reply: None
func HandleSetChatSubject ¶
func HandleSetChatSubject(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleSetChatSubject is sent from a v1.8+ Hotline client when the user sets a private chat subject Fields used in the request: * 114 Chat ID * 115 Chat subject Chat subject string Reply is not expected.
func HandleSetClientUserInfo ¶
func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleSetFileInfo ¶
func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleSetFileInfo updates a file or folder name and/or comment from the Get Info window Fields used in the request: * 201 File name * 202 File path Optional * 211 File new name Optional * 210 File comment Optional Fields used in the reply: None
func HandleSetUser ¶
func HandleSetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleTranAgreed ¶
func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err error)
func HandleTranOldPostNews ¶
func HandleTranOldPostNews(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleTranOldPostNews updates the flat news Fields used in this request: 101 Data
func HandleUpdateUser ¶ added in v0.3.1
func HandleUpdateUser(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleUpdateUser is used by the v1.5+ multi-user editor to perform account editing for multiple users at a time. An update can be a mix of these actions: * Create user * Delete user * Modify user (including renaming the account login)
The Transaction sent by the client includes one data field per user that was modified. This data field in turn contains another data field encoded in its payload with a varying number of sub fields depending on which action is performed. This seems to be the only place in the Hotline protocol where a data field contains another data field.
func HandleUploadFile ¶
func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleUploadFile Fields used in the request: 201 File name 202 File path 204 File transfer options "Optional Used only to resume download, currently has value 2" 108 File transfer size "Optional used if download is not resumed"
func HandleUploadFolder ¶
func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error)
Upload all files from the local folder and its subfolders to the specified path on the server Fields used in the request 201 File name 202 File path 108 transfer size Total size of all items in the folder 220 Folder item count 204 File transfer options "Optional Currently set to 1" (TODO: ??)
func HandleUserBroadcast ¶
func HandleUserBroadcast(cc *ClientConn, t *Transaction) (res []Transaction, err error)
HandleUserBroadcast sends an Administrator Message to all connected clients of the server
func NewTransaction ¶
func NewTransaction(t int, clientID *[]byte, fields ...Field) *Transaction
func (*Transaction) GetField ¶
func (t *Transaction) GetField(id int) Field
func (*Transaction) IsError ¶ added in v0.8.3
func (t *Transaction) IsError() bool
func (*Transaction) MarshalBinary ¶
func (t *Transaction) MarshalBinary() (data []byte, err error)
func (*Transaction) Size ¶
func (t *Transaction) Size() []byte
Size returns the total size of the transaction payload
type TransactionType ¶
type TransactionType struct { Handler func(*ClientConn, *Transaction) ([]Transaction, error) // function for handling the transaction type Name string // Name of transaction as it will appear in logging RequiredFields []requiredField }
type UI ¶
type UI struct { App *tview.Application Pages *tview.Pages HLClient *Client // contains filtered or unexported fields }
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
- ban.go
- client.go
- client_conn.go
- config.go
- field.go
- file_header.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
- news.go
- panic.go
- server.go
- stats.go
- time.go
- tracker.go
- transaction.go
- transaction_handlers.go
- transfer.go
- ui.go
- user.go
- version.go