//----------------------------------------------- Start Agent when a client is connected func StartAgent(sess *Session, in chan []byte, out *Buffer) { wg.Add(1) defer wg.Done() defer helper.PrintPanicStack() // init session sess.MQ = make(chan IPCObject, DEFAULT_MQ_SIZE) sess.ConnectTime = time.Now() sess.LastPacketTime = time.Now() // custom-sec timer, 60-sec custom_timer := make(chan int32, 1) timer.Add(-1, time.Now().Unix()+CUSTOM_TIMER, custom_timer) // cleanup work defer func() { close_work(sess) }() // the main message loop for { select { case msg, ok := <-in: // network protocol if !ok { return } sess.PacketTime = time.Now() if result := UserRequestProxy(sess, msg); result != nil { err := out.Send(result) if err != nil { helper.ERR("cannot send to client", err) return } } sess.LastPacketTime = sess.PacketTime sess.PacketCount++ // packet count case msg := <-sess.MQ: // internal IPC if result := IPCRequestProxy(sess, &msg); result != nil { err := out.Send(result) if err != nil { helper.ERR("cannot send ipc response", err) return } } case <-custom_timer: // 60-sec timer timer_work(sess) timer.Add(-1, time.Now().Unix()+CUSTOM_TIMER, custom_timer) case <-die: sess.Flag |= SESS_KICKED_OUT } // is the session been kicked out if sess.Flag&SESS_KICKED_OUT != 0 { return } } }
//----------------------------------------------- user's timer func timer_work(sess *Session) { if sess.Flag&SESS_LOGGED_IN == 0 { return } // SIGTERM check if atomic.LoadInt32(&SIGTERM) == 1 { sess.Flag |= SESS_KICKED_OUT helper.NOTICE("SIGTERM received, user exits.", sess.User.Id, sess.User.Name) } // limit rate of request per minute config := cfg.Get() rpm_limit, _ := strconv.ParseFloat(config["rpm_limit"], 32) rpm := float64(sess.PacketCount) / float64(time.Now().Unix()-sess.ConnectTime.Unix()) * 60 if rpm > rpm_limit { sess.Flag |= SESS_KICKED_OUT helper.ERR("user RPM too high", sess.User.Id, sess.User.Name, "RPM:", rpm) return } // try save the data _flush_work(sess) }