"fmt"
"github.com/go-playground/validator/v10"
"go.uber.org/zap"
+ "golang.org/x/text/encoding/charmap"
"gopkg.in/yaml.v3"
"io"
"io/fs"
type requestCtx struct {
remoteAddr string
- login string
- name string
}
+// Converts bytes from Mac Roman encoding to UTF-8
+var txtDecoder = charmap.Macintosh.NewDecoder()
+
+// Converts bytes from UTF-8 to Mac Roman encoding
+var txtEncoder = charmap.Macintosh.NewEncoder()
+
type Server struct {
+ NetInterface string
Port int
Accounts map[string]*Account
Agreement []byte
func (s *Server) ListenAndServe(ctx context.Context, cancelRoot context.CancelFunc) error {
s.Logger.Infow("Hotline server started",
"version", VERSION,
- "API port", fmt.Sprintf(":%v", s.Port),
- "Transfer port", fmt.Sprintf(":%v", s.Port+1),
+ "API port", fmt.Sprintf("%s:%v", s.NetInterface, s.Port),
+ "Transfer port", fmt.Sprintf("%s:%v", s.NetInterface, s.Port+1),
)
var wg sync.WaitGroup
wg.Add(1)
go func() {
- ln, err := net.Listen("tcp", fmt.Sprintf("%s:%v", "", s.Port))
+ ln, err := net.Listen("tcp", fmt.Sprintf("%s:%v", s.NetInterface, s.Port))
if err != nil {
s.Logger.Fatal(err)
}
wg.Add(1)
go func() {
- ln, err := net.Listen("tcp", fmt.Sprintf("%s:%v", "", s.Port+1))
+ ln, err := net.Listen("tcp", fmt.Sprintf("%s:%v", s.NetInterface, s.Port+1))
if err != nil {
s.Logger.Fatal(err)
-
}
s.Logger.Fatal(s.ServeFileTransfers(ctx, ln))
)
// NewServer constructs a new Server from a config dir
-func NewServer(configDir string, netPort int, logger *zap.SugaredLogger, FS FileStore) (*Server, error) {
+func NewServer(configDir, netInterface string, netPort int, logger *zap.SugaredLogger, fs FileStore) (*Server, error) {
server := Server{
+ NetInterface: netInterface,
Port: netPort,
Accounts: make(map[string]*Account),
Config: new(Config),
outbox: make(chan Transaction),
Stats: &Stats{Since: time.Now()},
ThreadedNews: &ThreadedNews{},
- FS: FS,
+ FS: fs,
banList: make(map[string]*time.Time),
}
return nil, err
}
- server.Config.FileRoot = filepath.Join(configDir, "Files")
+ // If the FileRoot is an absolute path, use it, otherwise treat as a relative path to the config dir.
+ if !filepath.IsAbs(server.Config.FileRoot) {
+ server.Config.FileRoot = filepath.Join(configDir, server.Config.FileRoot)
+ }
*server.NextGuestID = 1
c.Idle = true
flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(c.Flags)))
- flagBitmap.SetBit(flagBitmap, userFlagAway, 1)
+ flagBitmap.SetBit(flagBitmap, UserFlagAway, 1)
binary.BigEndian.PutUint16(c.Flags, uint16(flagBitmap.Int64()))
c.sendAll(
randID := make([]byte, 4)
rand.Read(randID)
- data := binary.BigEndian.Uint32(randID[:])
+ data := binary.BigEndian.Uint32(randID)
s.PrivateChats[data] = &PrivateChat{
ClientConn: make(map[uint16]*ClientConn),