game_sync/mgrsrv/api/webapi_worldsrv.go

259 lines
9.5 KiB
Go

package api
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"sync"
"sync/atomic"
"time"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/admin"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/core/transact"
"mongo.games.com/goserver/core/utils"
"mongo.games.com/goserver/srvlib"
"mongo.games.com/game/common"
"mongo.games.com/game/model"
)
// API
// http://127.0.0.1:9595/api/Report/QueryOnlineReportList?ts=20141024000000&sign=41cc8cee8dd93f7dc70b6426cfd1029d
const (
WEBAPI_TRANSACTE_EVENT int = iota
WEBAPI_TRANSACTE_RESPONSE
)
var WebApiStats = new(sync.Map)
type ApiStats struct {
RunTimes int64 //执行次数
TotalRuningTime int64 //总执行时间
MaxRuningTime int64 //最长执行时间
TimeoutTimes int64 //执行超时次数
UnreachTimes int64 //不可达次数
}
func WorldSrvApi(rw http.ResponseWriter, req *http.Request) {
defer utils.DumpStackIfPanic("api.WorldSrvApi")
logger.Logger.Info("WorldSrvApi 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 {
logger.Logger.Info("Body err.", err)
webApiResponse(rw, nil /*map[string]interface{}{webapi.RESPONSE_STATE: webapi.STATE_ERR, webapi.RESPONSE_ERRMSG: "Post data is null!"}*/)
return
}
m := req.URL.Query()
timestamp := m.Get("nano")
if timestamp == "" {
logger.Logger.Info(req.RemoteAddr, " WorldSrvApi param error: nano not allow null")
return
}
sign := m.Get("sign")
if sign == "" {
logger.Logger.Info(req.RemoteAddr, " WorldSrvApi param error: sign not allow null")
return
}
startTime := time.Now().UnixNano()
args := fmt.Sprintf("%v;%v;%v;%v", common.Config.AppId, req.URL.Path, string(data), timestamp)
h := md5.New()
io.WriteString(h, args)
realSign := hex.EncodeToString(h.Sum(nil))
if realSign != sign && !common.Config.IsDevMode {
logger.Logger.Info(req.RemoteAddr, " srvCtrlMain sign error: expect ", realSign, " ; but get ", sign, " raw=", args)
webApiResponse(rw, nil /*map[string]interface{}{webapi.RESPONSE_STATE: webapi.STATE_ERR, webapi.RESPONSE_ERRMSG: "Sign error!"}*/)
return
}
var stats *ApiStats
if v, exist := WebApiStats.Load(req.URL.Path); exist {
stats = v.(*ApiStats)
} else {
stats = &ApiStats{}
WebApiStats.Store(req.URL.Path, stats)
}
var rep []byte
start := time.Now()
res := make(chan []byte, 1)
suc := core.CoreObject().SendCommand(&WebApiEvent{req: req, path: req.URL.Path, h: HandlerWrapper(func(event *WebApiEvent, data []byte) bool {
logger.Logger.Trace("WorldSrvApi start transcate")
tnp := &transact.TransNodeParam{
Tt: common.TransType_WebApi,
Ot: transact.TransOwnerType(common.GetSelfSrvType()),
Oid: common.GetSelfSrvId(),
AreaID: common.GetSelfAreaId(),
}
tNode := transact.DTCModule.StartTrans(tnp, event, transact.DefaultTransactTimeout) //超时时间30秒
if tNode != nil {
tNode.TransEnv.SetField(WEBAPI_TRANSACTE_EVENT, event)
tNode.Go(core.CoreObject())
}
return true
}), body: data, rawQuery: req.URL.RawQuery, res: res}, false)
if suc {
select {
case rep = <-res:
if rep != nil {
webApiResponse(rw, rep)
}
case <-time.After(ApiDefaultTimeout):
//rep = make(map[string]interface{})
//rep[webapi.RESPONSE_STATE] = webapi.STATE_ERR
//rep[webapi.RESPONSE_ERRMSG] = "proccess timeout!"
webApiResponse(rw, rep)
if stats != nil {
atomic.AddInt64(&stats.TimeoutTimes, 1)
}
}
} else {
webApiResponse(rw, nil)
if stats != nil {
atomic.AddInt64(&stats.UnreachTimes, 1)
}
}
ps := int64(time.Now().Sub(start) / time.Millisecond)
if stats != nil {
atomic.AddInt64(&stats.RunTimes, 1)
atomic.AddInt64(&stats.TotalRuningTime, ps)
if atomic.LoadInt64(&stats.MaxRuningTime) < ps {
atomic.StoreInt64(&stats.MaxRuningTime, ps)
}
}
result, err := json.Marshal(rep)
if err == nil {
log := model.NewAPILog(req.URL.Path, req.URL.RawQuery, string(data[:]), req.RemoteAddr, string(result[:]), startTime, ps)
LogChannelSington.WriteLog(log)
}
return
}
// --------------------------------------------------------------------------------------
func init() {
transact.RegisteHandler(common.TransType_WebApi, &transact.TransHanderWrapper{
OnExecuteWrapper: transact.OnExecuteWrapper(func(tNode *transact.TransNode, ud interface{}) transact.TransExeResult {
logger.Logger.Trace("WorldSrvApi start TransType_WebApi OnExecuteWrapper ")
tnp := &transact.TransNodeParam{
Tt: common.TransType_WebApi,
Ot: transact.TransOwnerType(srvlib.WorldServerType),
Oid: common.GetWorldSrvId(),
AreaID: common.GetSelfAreaId(),
Tct: transact.TransactCommitPolicy_TwoPhase,
}
if event, ok := ud.(*WebApiEvent); ok {
userData := &common.M2GWebApiRequest{Path: event.path, RawQuery: event.rawQuery, Body: event.body, ReqIp: event.req.RemoteAddr}
tNode.StartChildTrans(tnp, userData, transact.DefaultTransactTimeout)
pid := tNode.MyTnp.TId
cid := tnp.TId
logger.Logger.Tracef("WorldSrvApi start TransType_WebApi OnExecuteWrapper tid:%x childid:%x", pid, cid)
return transact.TransExeResult_Success
}
return transact.TransExeResult_Failed
}),
OnCommitWrapper: transact.OnCommitWrapper(func(tNode *transact.TransNode) transact.TransExeResult {
logger.Logger.Trace("WorldSrvApi start TransType_WebApi OnCommitWrapper")
event := tNode.TransEnv.GetField(WEBAPI_TRANSACTE_EVENT).(*WebApiEvent)
resp := tNode.TransEnv.GetField(WEBAPI_TRANSACTE_RESPONSE)
if ud, ok := resp.([]byte); ok {
event.Response(netlib.SkipHeaderGetRaw(ud))
return transact.TransExeResult_Success
}
event.Response(nil /*map[string]interface{}{webapi.RESPONSE_STATE: webapi.STATE_ERR, webapi.RESPONSE_ERRMSG: "execute failed!"}*/)
return transact.TransExeResult_Success
}),
OnRollBackWrapper: transact.OnRollBackWrapper(func(tNode *transact.TransNode) transact.TransExeResult {
logger.Logger.Trace("WorldSrvApi start TransType_WebApi OnRollBackWrapper")
event := tNode.TransEnv.GetField(WEBAPI_TRANSACTE_EVENT).(*WebApiEvent)
resp := tNode.TransEnv.GetField(WEBAPI_TRANSACTE_RESPONSE)
if ud, ok := resp.([]byte); ok {
event.Response(netlib.SkipHeaderGetRaw(ud))
return transact.TransExeResult_Success
}
event.Response(nil /*map[string]interface{}{webapi.RESPONSE_STATE: webapi.STATE_ERR, webapi.RESPONSE_ERRMSG: "execute failed!"}*/)
return transact.TransExeResult_Success
}),
OnChildRespWrapper: transact.OnChildRespWrapper(func(tNode *transact.TransNode, hChild transact.TransNodeID, retCode int, ud interface{}) transact.TransExeResult {
logger.Logger.Tracef("WorldSrvApi start TransType_WebApi OnChildRespWrapper ret:%v childid:%x", retCode, hChild)
tNode.TransEnv.SetField(WEBAPI_TRANSACTE_RESPONSE, ud)
return transact.TransExeResult(retCode)
}),
})
// 查询在线玩家列表,筛选,排序
admin.MyAdminApp.Route("/api/Report/QueryOnlineReportList", WorldSrvApi)
// 在线统计
admin.MyAdminApp.Route("/api/Report/OnlineReportTotal", WorldSrvApi)
// 加减金币钻石
admin.MyAdminApp.Route("/api/game/AddCoinByIdAndPT", WorldSrvApi)
// 查询玩家信息
admin.MyAdminApp.Route("/api/Player/PlayerData", WorldSrvApi)
// 查询多个玩家信息
admin.MyAdminApp.Route("/api/Player/MorePlayerData", WorldSrvApi)
// 踢下线
admin.MyAdminApp.Route("/api/Player/KickPlayer", WorldSrvApi)
// 黑白名单调控
admin.MyAdminApp.Route("/api/Player/WhiteBlackControl", WorldSrvApi)
// 设置黑名单
admin.MyAdminApp.Route("/api/Player/BlackBySnId", WorldSrvApi)
// 修改玩家内存属性
admin.MyAdminApp.Route("/api/Cache/UpdatePlayerElement", WorldSrvApi)
// 水池相关
admin.MyAdminApp.Route("/api/game/QueryGamePoolByGameId", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/QueryAllGamePool", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/RefreshGamePool", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/UpdateGamePool", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/ResetGamePool", WorldSrvApi)
// 邮箱相关
admin.MyAdminApp.Route("/api/game/CreateShortMessage", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/QueryShortMessageList", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/DeleteShortMessage", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/DeleteAllShortMessage", WorldSrvApi)
// 获取房间列表
admin.MyAdminApp.Route("/api/Cache/ListRoom", WorldSrvApi)
// 获取房间信息
admin.MyAdminApp.Route("/api/Cache/GetRoom", WorldSrvApi)
// 销毁房间
admin.MyAdminApp.Route("/api/Cache/DestroyRoom", WorldSrvApi)
// 兑换物品
admin.MyAdminApp.Route("/api/Customer/UpExchangeStatus", WorldSrvApi)
// 3方平台
admin.MyAdminApp.Route("/api/thd/UpdatePlayerCoin", WorldSrvApi)
// 兑换卷
admin.MyAdminApp.Route("/api/game/CreateJYB", WorldSrvApi)
admin.MyAdminApp.Route("/api/game/UpdateJYB", WorldSrvApi)
// 支付回调
admin.MyAdminApp.Route("/api/pay/CallbackPayment", WorldSrvApi)
// 资源变更(给所有玩家发送消息)
admin.MyAdminApp.Route("/api/game/resource", WorldSrvApi)
// 修改手机号
admin.MyAdminApp.Route("/api/player/update_tel", WorldSrvApi)
// 删除账号
admin.MyAdminApp.Route("/api/player/delete", WorldSrvApi)
}
func Stats() map[string]ApiStats {
stats := make(map[string]ApiStats)
WebApiStats.Range(func(k, v interface{}) bool {
if s, ok := v.(*ApiStats); ok {
ss := *s //计数可能不精准
stats[k.(string)] = ss
}
return true
})
return stats
}