name string
}
-const (
- userIdleSeconds = 300 // time in seconds before an inactive user is marked idle
- idleCheckInterval = 10 // time in seconds to check for idle users
- trackerUpdateFrequency = 300 // time in seconds between tracker re-registration
-)
-
var nostalgiaVersion = []byte{0, 0, 2, 0x2c} // version ID used by the Nostalgia client
+var frogblastVersion = []byte{0, 0, 0, 0xb9} // version ID used by the Frogblast 1.2.4 client
type Server struct {
Port int
NextGuestID *uint16
TrackerPassID [4]byte
- Stats *Stats
+
+ StatsMu sync.Mutex
+ Stats *Stats
FS FileStore // Storage backend to use for File storage
banList map[string]*time.Time
}
+func (s *Server) CurrentStats() Stats {
+ s.StatsMu.Lock()
+ defer s.StatsMu.Unlock()
+
+ stats := s.Stats
+ stats.CurrentlyConnected = len(s.Clients)
+
+ return *stats
+}
+
type PrivateChat struct {
Subject string
ClientConn map[uint16]*ClientConn
Logger: logger,
NextGuestID: new(uint16),
outbox: make(chan Transaction),
- Stats: &Stats{StartTime: time.Now()},
+ Stats: &Stats{Since: time.Now()},
ThreadedNews: &ThreadedNews{},
FS: FS,
banList: make(map[string]*time.Time),
}
// Used simplified hotline v1.2.3 login flow for clients that do not send login info in tranAgreed
- if c.Version == nil || bytes.Equal(c.Version, nostalgiaVersion) {
+ if c.Version == nil || bytes.Equal(c.Version, nostalgiaVersion) || bytes.Equal(c.Version, frogblastVersion) {
c.Agreed = true
c.logger = c.logger.With("name", string(c.UserName))
c.logger.Infow("Login successful", "clientVersion", fmt.Sprintf("%v", func() int { i, _ := byteToInt(c.Version); return i }()))
}
}
- c.Server.Stats.LoginCount += 1
+ c.Server.Stats.ConnectionCounter += 1
+ if len(s.Clients) > c.Server.Stats.ConnectionPeak {
+ c.Server.Stats.ConnectionPeak = len(s.Clients)
+ }
// Scan for new transactions and handle them as they come in.
for scanner.Scan() {
}
case FileDownload:
s.Stats.DownloadCounter += 1
+ s.Stats.DownloadsInProgress += 1
+ defer func() { s.Stats.DownloadsInProgress -= 1 }()
var dataOffset int64
if fileTransfer.fileResumeData != nil {
case FileUpload:
s.Stats.UploadCounter += 1
+ s.Stats.UploadsInProgress += 1
+ defer func() { s.Stats.UploadsInProgress -= 1 }()
var file *os.File
}
rLogger.Infow("File upload complete", "dstFile", fullPath)
+
case FolderDownload:
+ s.Stats.DownloadCounter += 1
+ s.Stats.DownloadsInProgress += 1
+ defer func() { s.Stats.DownloadsInProgress -= 1 }()
+
// Folder Download flow:
// 1. Get filePath from the transfer
// 2. Iterate over files
}
case FolderUpload:
+ s.Stats.UploadCounter += 1
+ s.Stats.UploadsInProgress += 1
+ defer func() { s.Stats.UploadsInProgress -= 1 }()
rLogger.Infow(
"Folder upload started",
"dstPath", fullPath,