261 lines
9.5 KiB
Go
261 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.TransTypeWebApi,
|
|
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.TransTypeWebApi, &transact.TransHanderWrapper{
|
|
OnExecuteWrapper: transact.OnExecuteWrapper(func(tNode *transact.TransNode, ud interface{}) transact.TransExeResult {
|
|
logger.Logger.Trace("WorldSrvApi start TransTypeWebApi OnExecuteWrapper ")
|
|
tnp := &transact.TransNodeParam{
|
|
Tt: common.TransTypeWebApi,
|
|
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 TransTypeWebApi 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 TransTypeWebApi 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 TransTypeWebApi 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 TransTypeWebApi 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)
|
|
// 添加道具
|
|
admin.MyAdminApp.Route("/api/player/AddItem", 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
|
|
}
|