2019-04-20 23:20:08 +00:00
|
|
|
package server
|
|
|
|
|
2020-01-18 22:04:26 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/mitchellh/colorstring"
|
2020-08-11 04:38:42 +00:00
|
|
|
"github.com/pterodactyl/wings/config"
|
|
|
|
"sync"
|
|
|
|
"sync/atomic"
|
|
|
|
"time"
|
2020-01-18 22:04:26 +00:00
|
|
|
)
|
2019-04-20 23:20:08 +00:00
|
|
|
|
2020-08-11 04:38:42 +00:00
|
|
|
type ConsoleThrottler struct {
|
|
|
|
sync.RWMutex
|
|
|
|
config.ConsoleThrottles
|
|
|
|
|
|
|
|
// The total number of activations that have occurred thus far.
|
|
|
|
activations uint64
|
|
|
|
|
|
|
|
// The total number of lines processed so far during the given time period.
|
|
|
|
lines uint64
|
|
|
|
|
|
|
|
lastIntervalTime *time.Time
|
|
|
|
lastDecayTime *time.Time
|
2019-04-20 23:20:08 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 04:38:42 +00:00
|
|
|
// Increments the number of activations for a server.
|
|
|
|
func (ct *ConsoleThrottler) AddActivation() uint64 {
|
|
|
|
ct.Lock()
|
|
|
|
defer ct.Unlock()
|
|
|
|
|
|
|
|
ct.activations += 1
|
|
|
|
|
|
|
|
return ct.activations
|
|
|
|
}
|
2019-04-20 23:20:08 +00:00
|
|
|
|
2020-08-11 04:38:42 +00:00
|
|
|
// Decrements the number of activations for a server.
|
|
|
|
func (ct *ConsoleThrottler) RemoveActivation() uint64 {
|
|
|
|
ct.Lock()
|
|
|
|
defer ct.Unlock()
|
2019-04-20 23:20:08 +00:00
|
|
|
|
2020-08-11 04:38:42 +00:00
|
|
|
if ct.activations == 0 {
|
|
|
|
return 0
|
2019-04-20 23:20:08 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 04:38:42 +00:00
|
|
|
ct.activations -= 1
|
|
|
|
|
|
|
|
return ct.activations
|
|
|
|
}
|
|
|
|
|
|
|
|
// Increment the total count of lines that we have processed so far.
|
|
|
|
func (ct *ConsoleThrottler) IncrementLineCount() uint64 {
|
|
|
|
return atomic.AddUint64(&ct.lines, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the line count to zero.
|
|
|
|
func (ct *ConsoleThrottler) ResetLineCount() {
|
|
|
|
atomic.SwapUint64(&ct.lines, 0)
|
2020-01-18 22:04:26 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 04:38:42 +00:00
|
|
|
// Handles output from a server's console. This code ensures that a server is not outputting
|
|
|
|
// an excessive amount of data to the console that could indicate a malicious or run-away process
|
|
|
|
// and lead to performance issues for other users.
|
|
|
|
//
|
|
|
|
// This was much more of a problem for the NodeJS version of the daemon which struggled to handle
|
|
|
|
// large volumes of output. However, this code is much more performant so I generally feel a lot
|
|
|
|
// better about it's abilities.
|
|
|
|
//
|
|
|
|
// However, extreme output is still somewhat of a DoS attack vector against this software since we
|
|
|
|
// are still logging it to the disk temporarily and will want to avoid dumping a huge amount of
|
|
|
|
// data all at once. These values are all configurable via the wings configuration file, however the
|
|
|
|
// defaults have been in the wild for almost two years at the time of this writing, so I feel quite
|
|
|
|
// confident in them.
|
|
|
|
func (ct *ConsoleThrottler) Handle() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the throttler instance for the server or creates a new one.
|
|
|
|
func (s *Server) Throttler() *ConsoleThrottler {
|
|
|
|
s.throttleLock.RLock()
|
|
|
|
|
|
|
|
if s.throttler == nil {
|
|
|
|
// Release the read lock so that we can acquire a normal lock on the process and
|
|
|
|
// make modifications to the throttler.
|
|
|
|
s.throttleLock.RUnlock()
|
|
|
|
|
|
|
|
s.throttleLock.Lock()
|
|
|
|
s.throttler = &ConsoleThrottler{
|
|
|
|
ConsoleThrottles: config.Get().Throttles,
|
|
|
|
}
|
|
|
|
s.throttleLock.Unlock()
|
|
|
|
|
|
|
|
return s.throttler
|
|
|
|
} else {
|
|
|
|
defer s.throttleLock.RUnlock()
|
|
|
|
return s.throttler
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-18 22:04:26 +00:00
|
|
|
// Sends output to the server console formatted to appear correctly as being sent
|
|
|
|
// from Wings.
|
|
|
|
func (s *Server) PublishConsoleOutputFromDaemon(data string) {
|
|
|
|
s.Events().Publish(
|
|
|
|
ConsoleOutputEvent,
|
|
|
|
colorstring.Color(fmt.Sprintf("[yellow][bold][Pterodactyl Daemon]:[default] %s", data)),
|
|
|
|
)
|
|
|
|
}
|