"math/rand"
"net"
"os"
- "path"
"path/filepath"
"runtime/debug"
"strings"
return nil
}
+func (s *Server) processOutbox() {
+ for {
+ t := <-s.outbox
+ go func() {
+ if err := s.sendTransaction(t); err != nil {
+ s.Logger.Errorw("error sending transaction", "err", err)
+ }
+ }()
+ }
+}
+
func (s *Server) Serve(ctx context.Context, ln net.Listener) error {
+ go s.processOutbox()
+
for {
conn, err := ln.Accept()
if err != nil {
s.Logger.Errorw("error accepting connection", "err", err)
}
+ connCtx := context.WithValue(ctx, contextKeyReq, requestCtx{
+ remoteAddr: conn.RemoteAddr().String(),
+ })
go func() {
- for {
- t := <-s.outbox
- go func() {
- if err := s.sendTransaction(t); err != nil {
- s.Logger.Errorw("error sending transaction", "err", err)
- }
- }()
- }
- }()
- go func() {
- if err := s.handleNewConnection(ctx, conn, conn.RemoteAddr().String()); err != nil {
+ if err := s.handleNewConnection(connCtx, conn, conn.RemoteAddr().String()); err != nil {
s.Logger.Infow("New client connection established", "RemoteAddr", conn.RemoteAddr())
if err == io.EOF {
s.Logger.Infow("Client disconnected", "RemoteAddr", conn.RemoteAddr())
return nil, err
}
- server.Agreement, err = os.ReadFile(configDir + agreementFile)
+ server.Agreement, err = os.ReadFile(filepath.Join(configDir, agreementFile))
if err != nil {
return nil, err
}
- if server.FlatNews, err = os.ReadFile(configDir + "MessageBoard.txt"); err != nil {
+ if server.FlatNews, err = os.ReadFile(filepath.Join(configDir, "MessageBoard.txt")); err != nil {
return nil, err
}
- if err := server.loadThreadedNews(configDir + "ThreadedNews.yaml"); err != nil {
+ if err := server.loadThreadedNews(filepath.Join(configDir, "ThreadedNews.yaml")); err != nil {
return nil, err
}
- if err := server.loadConfig(configDir + "config.yaml"); err != nil {
+ if err := server.loadConfig(filepath.Join(configDir, "config.yaml")); err != nil {
return nil, err
}
- if err := server.loadAccounts(configDir + "Users/"); err != nil {
+ if err := server.loadAccounts(filepath.Join(configDir, "Users/")); err != nil {
return nil, err
}
- server.Config.FileRoot = configDir + "Files/"
+ server.Config.FileRoot = filepath.Join(configDir, "Files")
*server.NextGuestID = 1
return err
}
err = ioutil.WriteFile(
- s.ConfigDir+"ThreadedNews.yaml",
+ filepath.Join(s.ConfigDir, "ThreadedNews.yaml"),
out,
0666,
)
return err
}
-func (s *Server) NewClientConn(conn net.Conn, remoteAddr string) *ClientConn {
+func (s *Server) NewClientConn(conn io.ReadWriteCloser, remoteAddr string) *ClientConn {
s.mux.Lock()
defer s.mux.Unlock()
}
s.Accounts[login] = &account
- return s.FS.WriteFile(s.ConfigDir+"Users/"+login+".yaml", out, 0666)
+ return s.FS.WriteFile(filepath.Join(s.ConfigDir, "Users", login+".yaml"), out, 0666)
}
func (s *Server) UpdateUser(login, newLogin, name, password string, access []byte) error {
// update renames the user login
if login != newLogin {
- err := os.Rename(s.ConfigDir+"Users/"+login+".yaml", s.ConfigDir+"Users/"+newLogin+".yaml")
+ err := os.Rename(filepath.Join(s.ConfigDir, "Users", login+".yaml"), filepath.Join(s.ConfigDir, "Users", newLogin+".yaml"))
if err != nil {
return err
}
if err != nil {
return err
}
- if err := os.WriteFile(s.ConfigDir+"Users/"+newLogin+".yaml", out, 0666); err != nil {
+
+ if err := os.WriteFile(filepath.Join(s.ConfigDir, "Users", newLogin+".yaml"), out, 0666); err != nil {
return err
}
delete(s.Accounts, login)
- return s.FS.Remove(s.ConfigDir + "Users/" + login + ".yaml")
+ return s.FS.Remove(filepath.Join(s.ConfigDir, "Users", login+".yaml"))
}
func (s *Server) connectedUsers() []Field {
// loadAccounts loads account data from disk
func (s *Server) loadAccounts(userDir string) error {
- matches, err := filepath.Glob(path.Join(userDir, "*.yaml"))
+ matches, err := filepath.Glob(filepath.Join(userDir, "*.yaml"))
if err != nil {
return err
}
*c.Flags = []byte{0, 2}
}
- s.Logger.Infow("Client connection received", "login", login, "version", *c.Version, "RemoteAddr", remoteAddr)
+ c.logger = s.Logger.With("remoteAddr", remoteAddr, "login", login)
+
+ c.logger.Infow("Client connection received", "version", fmt.Sprintf("%x", *c.Version))
s.outbox <- c.NewReply(clientLogin,
NewField(fieldVersion, []byte{0x00, 0xbe}),
if *c.Version == nil || bytes.Equal(*c.Version, nostalgiaVersion) {
c.Agreed = true
+ c.logger = c.logger.With("name", string(c.UserName))
+
c.notifyOthers(
*NewTransaction(
tranNotifyChangeUser, nil,
// into a slice of transactions
var transactions []Transaction
if transactions, tReadlen, err = readTransactions(tranBuff); err != nil {
- c.Server.Logger.Errorw("Error handling transaction", "err", err)
+ c.logger.Errorw("Error handling transaction", "err", err)
}
// iterate over all the transactions that were parsed from the byte slice and handle them
}
err = sendFile(wr, rFile, int(dataOffset))
+ if err != nil {
+ return err
+ }
if err := wr.Flush(); err != nil {
return err
return err
}
- defer func() { _ = file.Close() }()
-
s.Logger.Infow("File upload started", "transactionRef", fileTransfer.ReferenceNumber, "dstFile", destinationFile)
rForkWriter := io.Discard
return err
}
+ if err := file.Close(); err != nil {
+ return err
+ }
+
if err := s.FS.Rename(destinationFile+".incomplete", destinationFile); err != nil {
return err
}
return nil
})
+ if err != nil {
+ return err
+ }
+
case FolderUpload:
dstPath, err := readPath(s.Config.FileRoot, fileTransfer.FilePath, fileTransfer.FileName)
if err != nil {
)
if fu.IsFolder == [2]byte{0, 1} {
- if _, err := os.Stat(dstPath + "/" + fu.FormattedPath()); os.IsNotExist(err) {
- if err := os.Mkdir(dstPath+"/"+fu.FormattedPath(), 0777); err != nil {
+ if _, err := os.Stat(filepath.Join(dstPath, fu.FormattedPath())); os.IsNotExist(err) {
+ if err := os.Mkdir(filepath.Join(dstPath, fu.FormattedPath()), 0777); err != nil {
return err
}
}
nextAction := dlFldrActionSendFile
// Check if we have the full file already. If so, send dlFldrAction_NextFile to client to skip.
- _, err = os.Stat(dstPath + "/" + fu.FormattedPath())
+ _, err = os.Stat(filepath.Join(dstPath, fu.FormattedPath()))
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}
}
// Check if we have a partial file already. If so, send dlFldrAction_ResumeFile to client to resume upload.
- incompleteFile, err := os.Stat(dstPath + "/" + fu.FormattedPath() + incompleteFileSuffix)
+ incompleteFile, err := os.Stat(filepath.Join(dstPath, fu.FormattedPath()+incompleteFileSuffix))
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}
return err
}
- filePath := dstPath + "/" + fu.FormattedPath()
+ filePath := filepath.Join(dstPath, fu.FormattedPath())
hlFile, err := newFileWrapper(s.FS, filePath, 0)
if err != nil {