diff --git a/gate/net/session.go b/gate/net/session.go index 60a1e267..35d445c8 100644 --- a/gate/net/session.go +++ b/gate/net/session.go @@ -190,7 +190,7 @@ func (k *KcpConnectManager) sendMsgHandle() { ServerMsg: serverMsg, }) } else if protoMsg.CmdId == cmd.ClientReconnectNotify { - tokenResetRsp, err := httpclient.Post[controller.TokenResetRsp]( + tokenResetRsp, err := httpclient.PostJson[controller.TokenResetRsp]( config.CONF.Hk4e.LoginSdkUrl+"/gate/token/reset?key=flswld", &controller.TokenResetReq{ PlayerId: session.userId, @@ -342,7 +342,7 @@ func (k *KcpConnectManager) getPlayerToken(req *proto.GetPlayerTokenReq, session EventMessage: uint32(kcp.EnetLoginUnfinished), } } - tokenVerifyRsp, err := httpclient.Post[controller.TokenVerifyRsp]( + tokenVerifyRsp, err := httpclient.PostJson[controller.TokenVerifyRsp]( config.CONF.Hk4e.LoginSdkUrl+"/gate/token/verify?key=flswld", &controller.TokenVerifyReq{ AccountId: req.AccountUid, diff --git a/pkg/httpclient/http_client.go b/pkg/httpclient/http_client.go index eecac0d3..a1fe7205 100644 --- a/pkg/httpclient/http_client.go +++ b/pkg/httpclient/http_client.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io" "net/http" + "strings" "time" ) @@ -15,17 +16,17 @@ func init() { Transport: &http.Transport{ DisableKeepAlives: true, }, - Timeout: time.Second * 60, + Timeout: time.Second * 10, } } -func Get[T any](url string, token string) (*T, error) { +func GetJson[T any](url string, authToken string) (*T, error) { req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } - if token != "" { - req.Header.Set("Authorization", "Bearer"+" "+token) + if authToken != "" { + req.Header.Set("Authorization", "Bearer"+" "+authToken) } rsp, err := httpClient.Do(req) if err != nil { @@ -44,7 +45,27 @@ func Get[T any](url string, token string) (*T, error) { return responseData, nil } -func Post[T any](url string, body any, token string) (*T, error) { +func GetRaw(url string, authToken string) (string, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return "", err + } + if authToken != "" { + req.Header.Set("Authorization", "Bearer"+" "+authToken) + } + rsp, err := httpClient.Do(req) + if err != nil { + return "", err + } + data, err := io.ReadAll(rsp.Body) + _ = rsp.Body.Close() + if err != nil { + return "", err + } + return string(data), nil +} + +func PostJson[T any](url string, body any, authToken string) (*T, error) { reqData, err := json.Marshal(body) if err != nil { return nil, err @@ -54,8 +75,8 @@ func Post[T any](url string, body any, token string) (*T, error) { return nil, err } req.Header.Set("Content-Type", "application/json") - if token != "" { - req.Header.Set("Authorization", "Bearer"+" "+token) + if authToken != "" { + req.Header.Set("Authorization", "Bearer"+" "+authToken) } rsp, err := httpClient.Do(req) if err != nil { @@ -73,3 +94,24 @@ func Post[T any](url string, body any, token string) (*T, error) { } return responseData, nil } + +func PostRaw(url string, body string, authToken string) (string, error) { + req, err := http.NewRequest("POST", url, strings.NewReader(body)) + if err != nil { + return "", err + } + req.Header.Set("Content-Type", "application/json") + if authToken != "" { + req.Header.Set("Authorization", "Bearer"+" "+authToken) + } + rsp, err := httpClient.Do(req) + if err != nil { + return "", err + } + rspData, err := io.ReadAll(rsp.Body) + _ = rsp.Body.Close() + if err != nil { + return "", err + } + return string(rspData), nil +} diff --git a/robot/cmd/main.go b/robot/cmd/main.go index e3d1529e..b54a1f21 100644 --- a/robot/cmd/main.go +++ b/robot/cmd/main.go @@ -3,6 +3,7 @@ package main import ( "os" "os/signal" + "strconv" "syscall" "time" @@ -11,6 +12,7 @@ import ( "hk4e/pkg/logger" "hk4e/protocol/cmd" "hk4e/protocol/proto" + "hk4e/robot/login" "hk4e/robot/net" "github.com/FlourishingWorld/dpdk-go/engine" @@ -28,7 +30,16 @@ func main() { time.Sleep(time.Second * 30) - session := net.NewSession("192.168.199.233:22222", make([]byte, 4096)) + dispatchInfo, err := login.GetDispatchInfo("https://hk4e.flswld.com", "?version=OSRELWin3.2.0") + if err != nil { + panic(err) + } + accountInfo, err := login.AccountLogin("https://hk4e.flswld.com", "flswld", "123456") + if err != nil { + panic(err) + } + gateAddr := dispatchInfo.GateIp + strconv.Itoa(int(dispatchInfo.GatePort)) + session := net.NewSession(gateAddr, dispatchInfo.DispatchKey, 30000) go func() { protoMsg := <-session.RecvChan logger.Debug("protoMsg: %v", protoMsg) @@ -42,9 +53,9 @@ func main() { SentMs: uint64(time.Now().UnixMilli()), }, PayloadMessage: &proto.GetPlayerTokenReq{ - AccountToken: "xxxxxx", - AccountUid: "10001", - KeyId: 0, + AccountToken: accountInfo.ComboToken, + AccountUid: strconv.Itoa(int(accountInfo.AccountId)), + KeyId: 5, ClientRandKey: "", }, } diff --git a/robot/login/http_login.go b/robot/login/http_login.go new file mode 100644 index 00000000..61e5e217 --- /dev/null +++ b/robot/login/http_login.go @@ -0,0 +1,126 @@ +package login + +import ( + "encoding/base64" + "encoding/json" + "strconv" + + "hk4e/dispatch/api" + "hk4e/pkg/httpclient" + "hk4e/pkg/logger" + "hk4e/pkg/random" + "hk4e/protocol/proto" + + "github.com/pkg/errors" + pb "google.golang.org/protobuf/proto" +) + +type DispatchInfo struct { + GateIp string + GatePort uint32 + DispatchKey []byte +} + +func GetDispatchInfo(url string, clientParam string) (*DispatchInfo, error) { + logger.Info("http get url: %v", url+"/query_region_list"+clientParam) + regionListBase64, err := httpclient.GetRaw(url+"/query_region_list"+clientParam, "") + if err != nil { + return nil, err + } + regionListData, err := base64.StdEncoding.DecodeString(regionListBase64) + if err != nil { + return nil, err + } + queryRegionListHttpRsp := new(proto.QueryRegionListHttpRsp) + err = pb.Unmarshal(regionListData, queryRegionListHttpRsp) + if err != nil { + return nil, err + } + logger.Info("region list: %v", queryRegionListHttpRsp.RegionList) + if len(queryRegionListHttpRsp.RegionList) == 0 { + return nil, errors.New("no region found") + } + selectRegion := queryRegionListHttpRsp.RegionList[0] + logger.Info("select region: %v", selectRegion) + logger.Info("http get url: %v", selectRegion.DispatchUrl+clientParam) + regionCurrBase64, err := httpclient.GetRaw(selectRegion.DispatchUrl+clientParam, "") + if err != nil { + return nil, err + } + regionCurrData, err := base64.StdEncoding.DecodeString(regionCurrBase64) + if err != nil { + return nil, err + } + queryCurrRegionHttpRsp := new(proto.QueryCurrRegionHttpRsp) + err = pb.Unmarshal(regionCurrData, queryCurrRegionHttpRsp) + if err != nil { + return nil, err + } + regionInfo := queryCurrRegionHttpRsp.RegionInfo + if regionInfo == nil { + return nil, errors.New("region info is nil") + } + ec2b, err := random.LoadEc2bKey(regionInfo.SecretKey) + if err != nil { + return nil, err + } + dispatchInfo := &DispatchInfo{ + GateIp: regionInfo.GateserverIp, + GatePort: regionInfo.GateserverPort, + DispatchKey: ec2b.XorKey(), + } + return dispatchInfo, nil +} + +type AccountInfo struct { + AccountId uint32 + Token string + ComboToken string +} + +func AccountLogin(url string, account string, password string) (*AccountInfo, error) { + loginAccountRequestJson := &api.LoginAccountRequestJson{ + Account: account, + Password: password, + IsCrypto: true, + } + logger.Info("http post url: %v", url+"/hk4e_global/mdk/shield/api/login") + loginResult, err := httpclient.PostJson[api.LoginResult](url+"/hk4e_global/mdk/shield/api/login", loginAccountRequestJson, "") + if err != nil { + return nil, err + } + if loginResult.Retcode != 0 { + logger.Error("login error msg: %v", loginResult.Message) + return nil, errors.New("login error") + } + accountId, err := strconv.Atoi(loginResult.Data.Account.Uid) + if err != nil { + return nil, err + } + loginTokenData := &api.LoginTokenData{ + Uid: loginResult.Data.Account.Uid, + Token: loginResult.Data.Account.Token, + } + loginTokenDataJson, err := json.Marshal(loginTokenData) + if err != nil { + return nil, err + } + comboTokenReq := &api.ComboTokenReq{ + Data: string(loginTokenDataJson), + } + logger.Info("http post url: %v", url+"/hk4e_global/combo/granter/login/v2/login") + comboTokenRsp, err := httpclient.PostJson[api.ComboTokenRsp](url+"/hk4e_global/combo/granter/login/v2/login", comboTokenReq, "") + if err != nil { + return nil, err + } + if comboTokenRsp.Retcode != 0 { + logger.Error("v2 login error msg: %v", comboTokenRsp.Message) + return nil, errors.New("v2 login error") + } + accountInfo := &AccountInfo{ + AccountId: uint32(accountId), + Token: loginResult.Data.Account.Token, + ComboToken: comboTokenRsp.Data.ComboToken, + } + return accountInfo, nil +} diff --git a/robot/net/session.go b/robot/net/session.go index c598a324..b6c35be1 100644 --- a/robot/net/session.go +++ b/robot/net/session.go @@ -1,6 +1,7 @@ package net import ( + "strconv" "time" hk4egatenet "hk4e/gate/net" @@ -21,8 +22,8 @@ type Session struct { useMagicSeed bool } -func NewSession(gateAddr string, dispatchKey []byte) (r *Session) { - conn, err := kcp.DialWithOptions(gateAddr, "0.0.0.0:30000") +func NewSession(gateAddr string, dispatchKey []byte, localPort int) (r *Session) { + conn, err := kcp.DialWithOptions(gateAddr, "0.0.0.0:"+strconv.Itoa(localPort)) if err != nil { logger.Error("kcp client conn to server error: %v", err) return @@ -92,7 +93,7 @@ func (s *Session) sendHandle() { _ = conn.Close() break } - kcpMsg := hk4egatenet.ProtoEncode(protoMsg, nil, nil) + kcpMsg := hk4egatenet.ProtoEncode(protoMsg, cmd.NewCmdProtoMap(), nil) if kcpMsg == nil { logger.Error("decode kcp msg is nil, convId: %v", convId) continue