package socketwrap import ( "os" "os/signal" "syscall" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/log" "github.com/elliotchance/orderedmap" ) var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40, 41} type ClientsManager struct { Clients *orderedmap.OrderedMap Register chan *Client Unregister chan *Client } func NewClientsManager() *ClientsManager { return &ClientsManager{ Register: make(chan *Client), Unregister: make(chan *Client), Clients: orderedmap.NewOrderedMap(), } } const MaxClients = 100 var LastActionsQueue = NewSyncQueue(15) func (h *ClientsManager) Run() { initActionQueue() sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, syscall.SIGTERM) var signalsReceived uint for { select { case client := <-h.Register: h.Clients.Set(client, true) if h.Clients.Len() > MaxClients { h.Clients.Delete(h.Clients.Front().Key) } case client := <-h.Unregister: if _, ok := h.Clients.Get(client); ok { h.Clients.Delete(client) close(client.Send) } case message := <-models.ActionChan: if isInOpTypes(opTypes, message.OpType) { filterUserPrivateInfo(message) LastActionsQueue.Push(message) for _, client := range h.Clients.Keys() { select { case client.(*Client).Send <- message: default: close(client.(*Client).Send) h.Clients.Delete(client) } } } case s := <-sig: log.Info("received signal", s) signalsReceived++ if signalsReceived < 2 { for _, client := range h.Clients.Keys() { h.Clients.Delete(client) client.(*Client).Close() } break } } } } func isInOpTypes(types []int, opType models.ActionType) bool { isFound := false for _, value := range types { if value == int(opType) { isFound = true break } } return isFound } func initActionQueue() { actions, err := models.GetLast20PublicFeeds(opTypes) if err == nil { for i := len(actions) - 1; i >= 0; i-- { user, err := models.GetUserByID(actions[i].UserID) if err == nil { if !user.IsOrganization() { filterUserPrivateInfo(actions[i]) LastActionsQueue.Push(actions[i]) } } } } } func filterUserPrivateInfo(action *models.Action) { action.Comment = nil if action.ActUser != nil { action.ActUser.Email = "" action.ActUser.Passwd = "" action.ActUser.PasswdHashAlgo = "" action.ActUser.PrivateKey = "" action.ActUser.PublicKey = "" action.ActUser.Salt = "" action.ActUser.FullName = "" action.ActUser.AvatarEmail = "" action.ActUser.IsAdmin = false action.ActUser.EmailNotificationsPreference = "" action.ActUser.IsOperator = false } }