diff --git a/core/chat/chat.go b/core/chat/chat.go index 179d602de..1fde109f0 100644 --- a/core/chat/chat.go +++ b/core/chat/chat.go @@ -20,7 +20,7 @@ func Start(getStatusFunc func() models.Status) error { go _server.Run() - log.Traceln("Chat server started with max connection count of", _server.maxClientCount) + log.Traceln("Chat server started with max connection count of", _server.maxSocketConnectionLimit) return nil } diff --git a/core/chat/concurrentConnections.go b/core/chat/concurrentConnections.go new file mode 100644 index 000000000..e96e78015 --- /dev/null +++ b/core/chat/concurrentConnections.go @@ -0,0 +1,24 @@ +// +build !freebsd + +package chat + +import ( + "syscall" + + log "github.com/sirupsen/logrus" +) + +func setSystemConcurrentConnectionLimit(limit int64) { + var rLimit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil { + panic(err) + } + + originalLimit := rLimit.Cur + rLimit.Cur = uint64(limit) + if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil { + panic(err) + } + + log.Traceln("Max process connection count changed from system limit of", originalLimit, "to", limit) +} diff --git a/core/chat/concurrentConnections_freebsd.go b/core/chat/concurrentConnections_freebsd.go new file mode 100644 index 000000000..acd2091fe --- /dev/null +++ b/core/chat/concurrentConnections_freebsd.go @@ -0,0 +1,24 @@ +// +build freebsd + +package chat + +import ( + "syscall" + + log "github.com/sirupsen/logrus" +) + +func setSystemConcurrentConnectionLimit(limit int64) { + var rLimit syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil { + panic(err) + } + + originalLimit := rLimit.Cur + rLimit.Cur = int64(limit) + if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil { + panic(err) + } + + log.Traceln("Max process connection count changed from system limit of", originalLimit, "to", limit) +} diff --git a/core/chat/server.go b/core/chat/server.go index d2dcf7afa..c85b9a8f3 100644 --- a/core/chat/server.go +++ b/core/chat/server.go @@ -21,10 +21,10 @@ import ( var _server *ChatServer type ChatServer struct { - mu sync.RWMutex - seq uint - clients map[uint]*ChatClient - maxClientCount uint + mu sync.RWMutex + seq uint + clients map[uint]*ChatClient + maxSocketConnectionLimit int64 // send outbound message payload to all clients outbound chan []byte @@ -37,12 +37,15 @@ type ChatServer struct { } func NewChat() *ChatServer { + maximumConcurrentConnectionLimit := getMaximumConcurrentConnectionLimit() + setSystemConcurrentConnectionLimit(maximumConcurrentConnectionLimit) + server := &ChatServer{ - clients: map[uint]*ChatClient{}, - outbound: make(chan []byte), - inbound: make(chan chatClientEvent), - unregister: make(chan uint), - maxClientCount: handleMaxConnectionCount(), + clients: map[uint]*ChatClient{}, + outbound: make(chan []byte), + inbound: make(chan chatClientEvent), + unregister: make(chan uint), + maxSocketConnectionLimit: maximumConcurrentConnectionLimit, } return server @@ -136,8 +139,8 @@ func (s *ChatServer) HandleClientConnection(w http.ResponseWriter, r *http.Reque } // Limit concurrent chat connections - if uint(len(s.clients)) >= s.maxClientCount { - log.Warnln("rejecting incoming client connection as it exceeds the max client count of", s.maxClientCount) + if int64(len(s.clients)) >= s.maxSocketConnectionLimit { + log.Warnln("rejecting incoming client connection as it exceeds the max client count of", s.maxSocketConnectionLimit) _, _ = w.Write([]byte(events.ErrorMaxConnectionsExceeded)) return } diff --git a/core/chat/utils.go b/core/chat/utils.go index 1e69b93e4..973b8f28d 100644 --- a/core/chat/utils.go +++ b/core/chat/utils.go @@ -1,29 +1,15 @@ package chat -import ( - "syscall" +import "syscall" - log "github.com/sirupsen/logrus" -) - -// Set the soft file handler limit as 70% of -// the max as the client connection limit. -func handleMaxConnectionCount() uint { +func getMaximumConcurrentConnectionLimit() int64 { var rLimit syscall.Rlimit if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil { panic(err) } - originalLimit := rLimit.Cur - // Set the limit to 70% of max so the machine doesn't die even if it's maxed out for some reason. - proposedLimit := int(float32(rLimit.Max) * 0.7) + // Return the limit to 70% of max so the machine doesn't die even if it's maxed out for some reason. + proposedLimit := int64(float32(rLimit.Max) * 0.7) - rLimit.Cur = uint64(proposedLimit) - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil { - panic(err) - } - - log.Traceln("Max process connection count increased from", originalLimit, "to", proposedLimit) - - return uint(float32(rLimit.Cur)) + return proposedLimit }