game_sync/mgrsrv/api/webapi_srctrl.go

272 lines
8.0 KiB
Go

package api
import (
"io"
"mongo.games.com/game/common"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
msg_proto "mongo.games.com/game/protocol/message"
"mongo.games.com/game/protocol/server"
"mongo.games.com/game/protocol/webapi"
"mongo.games.com/goserver/core/admin"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/goserver/core/utils"
"mongo.games.com/goserver/srvlib"
"mongo.games.com/goserver/srvlib/protocol"
srvlibprotocol "mongo.games.com/goserver/srvlib/protocol"
"net/http"
"os/exec"
"strconv"
"time"
)
//-------------------------------切换状态-------------------------------------------------------
func ServerStateSwitch(rw http.ResponseWriter, data []byte) {
pack := &webapi.SAServerStateSwitch{}
var gs webapi.ASServerStateSwitch
err := proto.Unmarshal(data, &gs)
if err != nil {
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "proto.Unmarshal is err:" + err.Error()
by, _ := proto.Marshal(pack)
webApiResponse(rw, by)
return
}
if gs.SrvId == 0 || gs.SrvType == 0 {
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "SrvCtrlStateSwitch failed SrvId or SrvType is zero."
by, _ := proto.Marshal(pack)
webApiResponse(rw, by)
return
}
s := srvlib.ServerSessionMgrSington.GetSession(common.GetSelfAreaId(), int(gs.SrvType), int(gs.SrvId))
logger.Logger.Trace("srvCtrl_StateSwitch enter")
if s != nil {
ctrlPacket := &server.ServerCtrl{
CtrlCode: proto.Int32(common.SrvCtrlStateSwitchCode),
}
proto.SetDefaults(ctrlPacket)
s.Send(int(server.SSPacketID_PACKET_MS_SRVCTRL), ctrlPacket, true)
pack.Tag = webapi.TagCode_SUCCESS
pack.Msg = "Server is changed."
rep, _ := proto.Marshal(pack)
webApiResponse(rw, rep)
return
}
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "[stateswitch] no find " + strconv.Itoa(int(gs.SrvId)) + "-" + strconv.Itoa(int(gs.SrvType)) + " server"
rep, _ := proto.Marshal(pack)
webApiResponse(rw, rep)
}
func SrvCtrlClose(rw http.ResponseWriter, data []byte) {
logger.Logger.Trace("srvCtrl_Close enter")
msg := &webapi.ASSrvCtrlClose{}
pack := &webapi.SASrvCtrlClose{
Tag: webapi.TagCode_SUCCESS,
}
err := proto.Unmarshal(data, msg)
if err != nil {
pack.Msg = "Unmarshal CtrlClose" + err.Error()
rep, _ := proto.Marshal(pack)
webApiResponse(rw, rep)
return
}
ctrlPacket := &server.ServerCtrl{
CtrlCode: proto.Int32(common.SrvCtrlCloseCode),
}
proto.SetDefaults(ctrlPacket)
var closeType []int
srvType := int(msg.SrvType)
if msg.SrvType == 0 {
closeType = append(closeType, srvlib.GameServerType, srvlib.GateServerType, srvlib.WorldServerType)
} else if srvType == srvlib.GameServerType || srvType == srvlib.GateServerType || srvType == srvlib.WorldServerType {
closeType = append(closeType, int(msg.SrvType))
}
for _, serverType := range closeType {
srvlib.ServerSessionMgrSington.Broadcast(int(server.SSPacketID_PACKET_MS_SRVCTRL), ctrlPacket, common.GetSelfAreaId(), serverType)
}
pack.Msg = "success"
rep, _ := proto.Marshal(pack)
webApiResponse(rw, rep)
}
func srvCtrlExecShell(shell string) bool {
cmd := exec.Command(shell)
if cmd == nil {
logger.Logger.Info("srvCtrlExecShell exec.Command(", shell, ") failed")
return false
}
logger.Logger.Info("srvCtrlExecShell exec.Command(", shell, ")")
stdout, err := cmd.StdoutPipe()
if err != nil {
logger.Logger.Info("srvCtrlExecShell.cmd.StdoutPipe() error:", err)
return false
}
stderr, err := cmd.StderrPipe()
if err != nil {
logger.Logger.Info("srvCtrlExecShell.cmd.StderrPipe() error:", err)
return false
}
err = cmd.Start()
if err != nil {
logger.Logger.Info("srvCtrlExecShell.cmd.Start()", err)
return false
}
ber, err := io.ReadAll(stderr)
if err != nil {
logger.Logger.Info("srvCtrlExecShell.io.ReadAll(stderr)", err)
return false
}
logger.Logger.Info("stderr=", string(ber[:]))
bsr, err := io.ReadAll(stdout)
if err != nil {
logger.Logger.Info("srvCtrlExecShell.io.ReadAll(stdout)", err)
return false
}
logger.Logger.Info("stdout=", string(bsr[:]))
err = cmd.Wait()
if err != nil {
logger.Logger.Info("srvCtrlExecShell.cmd.Wait()", err)
return false
}
return true
}
func SrvCtrlStartScript(rw http.ResponseWriter, data []byte) {
logger.Logger.Trace("srvCtrl_Start enter")
msg := &webapi.ASSrvCtrlStartScript{}
pack := &webapi.SASrvCtrlStartScript{
Tag: webapi.TagCode_SUCCESS,
}
err := proto.Unmarshal(data, msg)
if err != nil {
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "Unmarshal ASSrvCtrlStartScript is err:" + err.Error()
r, _ := proto.Marshal(pack)
webApiResponse(rw, r)
return
}
if srvCtrlExecShell(Config.StartScript) {
pack.Msg = "Start success"
} else {
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "Start failed"
}
rep, _ := proto.Marshal(pack)
webApiResponse(rw, rep)
}
func SrvApi(rw http.ResponseWriter, req *http.Request) {
defer utils.DumpStackIfPanic("api.SrvCtrlApi")
logger.Logger.Info("srvCtrl_StateSwitch receive:", req.URL.Path, req.URL.RawQuery)
if common.RequestCheck(req, model.GameParamData.WhiteHttpAddr) == false {
logger.Logger.Info("RemoteAddr [%v] require api.", req.RemoteAddr)
return
}
data, err := io.ReadAll(req.Body)
if err != nil {
webApiResponse(rw, nil)
return
}
switch req.URL.Path {
case "/api/Ctrl/ServerStateSwitch":
ServerStateSwitch(rw, data)
case "/api/Ctrl/SrvCtrlClose":
SrvCtrlClose(rw, data)
case "/api/Ctrl/SrvCtrlStartScript":
SrvCtrlStartScript(rw, data)
case "/api/Ctrl/SrvCtrlNotice":
SrvCtrlNotice(rw, data)
}
}
var noticeMap = make(map[timer.TimerHandle]struct{})
func SrvCtrlNotice(rw http.ResponseWriter, data []byte) {
logger.Logger.Trace("SrvCtrlNotice")
pack := &webapi.SASrvCtrlNotice{}
msg := &webapi.ASSrvCtrlNotice{}
err := proto.Unmarshal(data, msg)
if err != nil {
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "Unmarshal ASSrvCtrlNotice is err:" + err.Error()
r, _ := proto.Marshal(pack)
webApiResponse(rw, r)
return
}
if msg.OpNotice == 1 {
logger.Logger.Trace("srvCtrl_StopNotice enter")
for h, _ := range noticeMap {
timer.StopTimer(h)
}
noticeMap = make(map[timer.TimerHandle]struct{})
pack.Tag = webapi.TagCode_SUCCESS
pack.Msg = "stop all notice success"
r, _ := proto.Marshal(pack)
webApiResponse(rw, r)
return
}
logger.Logger.Trace("srvCtrl_Notice enter")
if msg.Notice == "" {
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "Notice is nil"
r, _ := proto.Marshal(pack)
webApiResponse(rw, r)
return
}
noticePacket := &server.ServerNotice{
Text: proto.String(msg.GetNotice()),
}
proto.SetDefaults(noticePacket)
sc := &protocol.BCSessionUnion{
Bccs: &protocol.BCClientSession{},
}
broadcast, err := BroadcastMaker.CreateBroadcastPacket(sc, int(msg_proto.MSGPacketID_PACKET_SC_NOTICE), noticePacket)
if err != nil || broadcast == nil {
pack.Tag = webapi.TagCode_FAILED
pack.Msg = "send notice failed(inner error)"
r, _ := proto.Marshal(pack)
webApiResponse(rw, r)
return
}
funcNotice := func() {
srvlib.ServerSessionMgrSington.Broadcast(int(srvlibprotocol.SrvlibPacketID_PACKET_SS_BROADCAST), broadcast, common.GetSelfAreaId(), srvlib.GateServerType)
}
funcNotice()
h, b := timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
funcNotice()
return true
}), nil, time.Second*time.Duration(msg.GetInterval()), int(msg.GetTimes()))
if b {
noticeMap[h] = struct{}{}
}
pack.Tag = webapi.TagCode_SUCCESS
pack.Msg = "send notice success"
r, _ := proto.Marshal(pack)
webApiResponse(rw, r)
}
// --------------------------------------------------------------------------------------
func init() {
//切换状态
admin.MyAdminApp.Route("/api/Ctrl/ServerStateSwitch", SrvApi)
//获取服务器列表
admin.MyAdminApp.Route("/api/Ctrl/ListServerStates", WorldSrvApi)
//关服
admin.MyAdminApp.Route("/api/Ctrl/SrvCtrlClose", SrvApi)
//执行脚本
admin.MyAdminApp.Route("/api/Ctrl/SrvCtrlStartScript", SrvApi)
//发送 停止 公告
admin.MyAdminApp.Route("/api/Ctrl/SrvCtrlNotice", SrvApi)
//重置Etcd
admin.MyAdminApp.Route("/api/Ctrl/ResetEtcdData", WorldSrvApi)
}