Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
ziqian zhang
Grasscutter
Commits
edd0bccf
Commit
edd0bccf
authored
Apr 24, 2022
by
Melledy
Committed by
GitHub
Apr 24, 2022
Browse files
Merge pull request #167 from memetrollsXD/development
Try to fix "No SSL cert found bind exception"
parents
bce8fb00
8066b164
Changes
2
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
edd0bccf
...
@@ -45,6 +45,9 @@ tmp/
...
@@ -45,6 +45,9 @@ tmp/
.loadpath
.loadpath
.recommenders
.recommenders
# VSCode
.vscode
# Grasscutter
# Grasscutter
resources/*
resources/*
logs/*
logs/*
...
@@ -55,4 +58,4 @@ GM Handbook.txt
...
@@ -55,4 +58,4 @@ GM Handbook.txt
config.json
config.json
mitmdump.exe
mitmdump.exe
grasscutter.jar
grasscutter.jar
mongod.exe
mongod.exe
\ No newline at end of file
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
edd0bccf
...
@@ -38,47 +38,48 @@ public final class DispatchServer {
...
@@ -38,47 +38,48 @@ public final class DispatchServer {
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
private
final
Gson
gson
;
private
final
Gson
gson
;
private
final
String
defaultServerName
=
"os_usa"
;
private
final
String
defaultServerName
=
"os_usa"
;
public
String
regionListBase64
;
public
String
regionListBase64
;
public
HashMap
<
String
,
RegionData
>
regions
;
public
HashMap
<
String
,
RegionData
>
regions
;
public
DispatchServer
()
{
public
DispatchServer
()
{
this
.
regions
=
new
HashMap
<
String
,
RegionData
>();
this
.
regions
=
new
HashMap
<
String
,
RegionData
>();
this
.
address
=
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
,
Grasscutter
.
getConfig
().
getDispatchOptions
().
Port
);
this
.
address
=
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
,
Grasscutter
.
getConfig
().
getDispatchOptions
().
Port
);
this
.
gson
=
new
GsonBuilder
().
create
();
this
.
gson
=
new
GsonBuilder
().
create
();
this
.
loadQueries
();
this
.
loadQueries
();
this
.
initRegion
();
this
.
initRegion
();
}
}
public
InetSocketAddress
getAddress
()
{
public
InetSocketAddress
getAddress
()
{
return
address
;
return
address
;
}
}
public
Gson
getGsonFactory
()
{
public
Gson
getGsonFactory
()
{
return
gson
;
return
gson
;
}
}
public
QueryCurrRegionHttpRsp
getCurrRegion
()
{
public
QueryCurrRegionHttpRsp
getCurrRegion
()
{
// Needs to be fixed by having the game servers connect to the dispatch server.
// Needs to be fixed by having the game servers connect to the dispatch server.
if
(
Grasscutter
.
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
if
(
Grasscutter
.
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
return
regions
.
get
(
defaultServerName
).
parsedRegionQuery
;
return
regions
.
get
(
defaultServerName
).
parsedRegionQuery
;
}
}
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] Unsupported run mode for getCurrRegion()"
);
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] Unsupported run mode for getCurrRegion()"
);
return
null
;
return
null
;
}
}
public
void
loadQueries
()
{
public
void
loadQueries
()
{
File
file
;
File
file
;
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_region_list.txt"
);
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_region_list.txt"
);
if
(
file
.
exists
())
{
if
(
file
.
exists
())
{
query_region_list
=
new
String
(
FileUtils
.
read
(
file
));
query_region_list
=
new
String
(
FileUtils
.
read
(
file
));
}
else
{
}
else
{
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] query_region_list not found! Using default region list."
);
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] query_region_list not found! Using default region list."
);
}
}
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_cur_region.txt"
);
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_cur_region.txt"
);
if
(
file
.
exists
())
{
if
(
file
.
exists
())
{
query_cur_region
=
new
String
(
FileUtils
.
read
(
file
));
query_cur_region
=
new
String
(
FileUtils
.
read
(
file
));
...
@@ -91,40 +92,58 @@ public final class DispatchServer {
...
@@ -91,40 +92,58 @@ public final class DispatchServer {
try
{
try
{
byte
[]
decoded
=
Base64
.
getDecoder
().
decode
(
query_region_list
);
byte
[]
decoded
=
Base64
.
getDecoder
().
decode
(
query_region_list
);
QueryRegionListHttpRsp
rl
=
QueryRegionListHttpRsp
.
parseFrom
(
decoded
);
QueryRegionListHttpRsp
rl
=
QueryRegionListHttpRsp
.
parseFrom
(
decoded
);
byte
[]
decoded2
=
Base64
.
getDecoder
().
decode
(
query_cur_region
);
byte
[]
decoded2
=
Base64
.
getDecoder
().
decode
(
query_cur_region
);
QueryCurrRegionHttpRsp
regionQuery
=
QueryCurrRegionHttpRsp
.
parseFrom
(
decoded2
);
QueryCurrRegionHttpRsp
regionQuery
=
QueryCurrRegionHttpRsp
.
parseFrom
(
decoded2
);
List
<
RegionSimpleInfo
>
servers
=
new
ArrayList
<
RegionSimpleInfo
>();
List
<
RegionSimpleInfo
>
servers
=
new
ArrayList
<
RegionSimpleInfo
>();
List
<
String
>
usedNames
=
new
ArrayList
<
String
>();
// List to check for potential naming conflicts
List
<
String
>
usedNames
=
new
ArrayList
<
String
>();
// List to check for potential naming conflicts
if
(
Grasscutter
.
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
// Automatically add the game server if in hybrid mode
if
(
Grasscutter
.
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
// Automatically add the game server if in
// hybrid mode
RegionSimpleInfo
server
=
RegionSimpleInfo
.
newBuilder
()
RegionSimpleInfo
server
=
RegionSimpleInfo
.
newBuilder
()
.
setName
(
"os_usa"
)
.
setName
(
"os_usa"
)
.
setTitle
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
Name
)
.
setTitle
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
Name
)
.
setType
(
"DEV_PUBLIC"
)
.
setType
(
"DEV_PUBLIC"
)
.
setDispatchUrl
(
"http"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
FrontHTTPS
?
"s"
:
""
)
+
"://"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
)
+
":"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicPort
!=
0
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicPort
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
Port
)
+
"/query_cur_region_"
+
defaultServerName
)
.
setDispatchUrl
(
"http"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
FrontHTTPS
?
"s"
:
""
)
+
"://"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
)
+
":"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicPort
!=
0
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicPort
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
Port
)
+
"/query_cur_region_"
+
defaultServerName
)
.
build
();
.
build
();
usedNames
.
add
(
defaultServerName
);
usedNames
.
add
(
defaultServerName
);
servers
.
add
(
server
);
servers
.
add
(
server
);
RegionInfo
serverRegion
=
regionQuery
.
getRegionInfo
().
toBuilder
()
RegionInfo
serverRegion
=
regionQuery
.
getRegionInfo
().
toBuilder
()
.
setIp
((
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getGameServerOptions
().
Ip
:
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicIp
))
.
setIp
((
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicIp
.
isEmpty
()
.
setPort
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicPort
!=
0
?
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicPort
:
Grasscutter
.
getConfig
().
getGameServerOptions
().
Port
)
?
Grasscutter
.
getConfig
().
getGameServerOptions
().
Ip
.
setSecretKey
(
ByteString
.
copyFrom
(
FileUtils
.
read
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
)))
:
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicIp
))
.
setPort
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicPort
!=
0
?
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicPort
:
Grasscutter
.
getConfig
().
getGameServerOptions
().
Port
)
.
setSecretKey
(
ByteString
.
copyFrom
(
FileUtils
.
read
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
)))
.
build
();
.
build
();
QueryCurrRegionHttpRsp
parsedRegionQuery
=
regionQuery
.
toBuilder
().
setRegionInfo
(
serverRegion
).
build
();
QueryCurrRegionHttpRsp
parsedRegionQuery
=
regionQuery
.
toBuilder
().
setRegionInfo
(
serverRegion
).
build
();
regions
.
put
(
defaultServerName
,
new
RegionData
(
parsedRegionQuery
,
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
())));
regions
.
put
(
defaultServerName
,
new
RegionData
(
parsedRegionQuery
,
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
())));
}
else
{
}
else
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
getGameServers
().
length
==
0
)
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
getGameServers
().
length
==
0
)
{
Grasscutter
.
getLogger
().
error
(
"[Dispatch] There are no game servers available. Exiting due to unplayable state."
);
Grasscutter
.
getLogger
()
.
error
(
"[Dispatch] There are no game servers available. Exiting due to unplayable state."
);
System
.
exit
(
1
);
System
.
exit
(
1
);
}
}
}
}
for
(
Config
.
DispatchServerOptions
.
RegionInfo
regionInfo
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
getGameServers
())
{
for
(
Config
.
DispatchServerOptions
.
RegionInfo
regionInfo
:
Grasscutter
.
getConfig
().
getDispatchOptions
()
if
(
usedNames
.
contains
(
regionInfo
.
Name
))
{
.
getGameServers
())
{
if
(
usedNames
.
contains
(
regionInfo
.
Name
))
{
Grasscutter
.
getLogger
().
error
(
"Region name already in use."
);
Grasscutter
.
getLogger
().
error
(
"Region name already in use."
);
continue
;
continue
;
}
}
...
@@ -132,7 +151,12 @@ public final class DispatchServer {
...
@@ -132,7 +151,12 @@ public final class DispatchServer {
.
setName
(
regionInfo
.
Name
)
.
setName
(
regionInfo
.
Name
)
.
setTitle
(
regionInfo
.
Title
)
.
setTitle
(
regionInfo
.
Title
)
.
setType
(
"DEV_PUBLIC"
)
.
setType
(
"DEV_PUBLIC"
)
.
setDispatchUrl
(
"http"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
FrontHTTPS
?
"s"
:
""
)
+
"://"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
)
+
":"
+
getAddress
().
getPort
()
+
"/query_cur_region_"
+
regionInfo
.
Name
)
.
setDispatchUrl
(
"http"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
FrontHTTPS
?
"s"
:
""
)
+
"://"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
)
+
":"
+
getAddress
().
getPort
()
+
"/query_cur_region_"
+
regionInfo
.
Name
)
.
build
();
.
build
();
usedNames
.
add
(
regionInfo
.
Name
);
usedNames
.
add
(
regionInfo
.
Name
);
servers
.
add
(
server
);
servers
.
add
(
server
);
...
@@ -140,26 +164,28 @@ public final class DispatchServer {
...
@@ -140,26 +164,28 @@ public final class DispatchServer {
RegionInfo
serverRegion
=
regionQuery
.
getRegionInfo
().
toBuilder
()
RegionInfo
serverRegion
=
regionQuery
.
getRegionInfo
().
toBuilder
()
.
setIp
(
regionInfo
.
Ip
)
.
setIp
(
regionInfo
.
Ip
)
.
setPort
(
regionInfo
.
Port
)
.
setPort
(
regionInfo
.
Port
)
.
setSecretKey
(
ByteString
.
copyFrom
(
FileUtils
.
read
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
)))
.
setSecretKey
(
ByteString
.
copyFrom
(
FileUtils
.
read
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
)))
.
build
();
.
build
();
QueryCurrRegionHttpRsp
parsedRegionQuery
=
regionQuery
.
toBuilder
().
setRegionInfo
(
serverRegion
).
build
();
QueryCurrRegionHttpRsp
parsedRegionQuery
=
regionQuery
.
toBuilder
().
setRegionInfo
(
serverRegion
).
build
();
regions
.
put
(
regionInfo
.
Name
,
new
RegionData
(
parsedRegionQuery
,
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
())));
regions
.
put
(
regionInfo
.
Name
,
new
RegionData
(
parsedRegionQuery
,
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
())));
}
}
QueryRegionListHttpRsp
regionList
=
QueryRegionListHttpRsp
.
newBuilder
()
QueryRegionListHttpRsp
regionList
=
QueryRegionListHttpRsp
.
newBuilder
()
.
addAllServers
(
servers
)
.
addAllServers
(
servers
)
.
setClientSecretKey
(
rl
.
getClientSecretKey
())
.
setClientSecretKey
(
rl
.
getClientSecretKey
())
.
setClientCustomConfigEncrypted
(
rl
.
getClientCustomConfigEncrypted
())
.
setClientCustomConfigEncrypted
(
rl
.
getClientCustomConfigEncrypted
())
.
setEnableLoginPc
(
true
)
.
setEnableLoginPc
(
true
)
.
build
();
.
build
();
this
.
regionListBase64
=
Base64
.
getEncoder
().
encodeToString
(
regionList
.
toByteString
().
toByteArray
());
this
.
regionListBase64
=
Base64
.
getEncoder
().
encodeToString
(
regionList
.
toByteString
().
toByteArray
());
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"[Dispatch] Error while initializing region info!"
,
e
);
Grasscutter
.
getLogger
().
error
(
"[Dispatch] Error while initializing region info!"
,
e
);
}
}
}
}
private
HttpServer
safelyCreateServer
(
InetSocketAddress
address
)
{
private
HttpServer
safelyCreateServer
(
InetSocketAddress
address
)
{
try
{
try
{
return
HttpServer
.
create
(
address
,
0
);
return
HttpServer
.
create
(
address
,
0
);
...
@@ -167,7 +193,8 @@ public final class DispatchServer {
...
@@ -167,7 +193,8 @@ public final class DispatchServer {
Grasscutter
.
getLogger
().
error
(
"Unable to bind to port: "
+
getAddress
().
getPort
()
+
" (HTTP)"
);
Grasscutter
.
getLogger
().
error
(
"Unable to bind to port: "
+
getAddress
().
getPort
()
+
" (HTTP)"
);
}
catch
(
Exception
exception
)
{
}
catch
(
Exception
exception
)
{
Grasscutter
.
getLogger
().
error
(
"Unable to start HTTP server."
,
exception
);
Grasscutter
.
getLogger
().
error
(
"Unable to start HTTP server."
,
exception
);
}
return
null
;
}
return
null
;
}
}
public
void
start
()
throws
Exception
{
public
void
start
()
throws
Exception
{
...
@@ -177,13 +204,39 @@ public final class DispatchServer {
...
@@ -177,13 +204,39 @@ public final class DispatchServer {
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
KeystorePath
))
{
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
KeystorePath
))
{
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
getDispatchOptions
().
KeystorePassword
.
toCharArray
();
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
getDispatchOptions
().
KeystorePassword
.
toCharArray
();
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
KeyManagerFactory
_kmf
;
ks
.
load
(
fis
,
keystorePassword
);
try
{
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"SunX509"
);
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
kmf
.
init
(
ks
,
keystorePassword
);
ks
.
load
(
fis
,
keystorePassword
);
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"SunX509"
);
sslContext
.
init
(
kmf
.
getKeyManagers
(),
null
,
null
);
_kmf
=
kmf
;
kmf
.
init
(
ks
,
keystorePassword
);
}
catch
(
Exception
originalEx
)
{
try
{
// try to initialize kmf with the default password
char
[]
defaultPassword
=
"123456"
.
toCharArray
();
Grasscutter
.
getLogger
()
.
warn
(
"[Dispatch] Unable to load keystore. Trying default keystore password..."
);
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
ks
.
load
(
fis
,
defaultPassword
);
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"SunX509"
);
kmf
.
init
(
ks
,
defaultPassword
);
_kmf
=
kmf
;
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] The default keystore password was loaded successfully. Please consider setting the password in config.json."
);
}
catch
(
Exception
ignored
)
{
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] Error while loading keystore!"
);
// don't care about the exception for the "123456" default password attempt
originalEx
.
printStackTrace
();
throw
originalEx
;
}
}
sslContext
.
init
(
_kmf
.
getKeyManagers
(),
null
,
null
);
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
server
=
httpsServer
;
server
=
httpsServer
;
}
catch
(
BindException
ignored
)
{
}
catch
(
BindException
ignored
)
{
...
@@ -197,16 +250,17 @@ public final class DispatchServer {
...
@@ -197,16 +250,17 @@ public final class DispatchServer {
}
else
{
}
else
{
server
=
this
.
safelyCreateServer
(
this
.
getAddress
());
server
=
this
.
safelyCreateServer
(
this
.
getAddress
());
}
}
if
(
server
==
null
)
if
(
server
==
null
)
throw
new
NullPointerException
(
"An HTTP server was not created."
);
throw
new
NullPointerException
(
"An HTTP server was not created."
);
server
.
createContext
(
"/"
,
t
->
responseHTML
(
t
,
"Hello"
));
server
.
createContext
(
"/"
,
t
->
responseHTML
(
t
,
"Hello"
));
// Dispatch
// Dispatch
server
.
createContext
(
"/query_region_list"
,
t
->
{
server
.
createContext
(
"/query_region_list"
,
t
->
{
// Log
// Log
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s request: query_region_list"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
()
.
info
(
String
.
format
(
"[Dispatch] Client %s request: query_region_list"
,
t
.
getRemoteAddress
()));
responseHTML
(
t
,
regionListBase64
);
responseHTML
(
t
,
regionListBase64
);
});
});
...
@@ -215,7 +269,8 @@ public final class DispatchServer {
...
@@ -215,7 +269,8 @@ public final class DispatchServer {
server
.
createContext
(
"/query_cur_region_"
+
regionName
,
t
->
{
server
.
createContext
(
"/query_cur_region_"
+
regionName
,
t
->
{
String
regionCurrentBase64
=
regions
.
get
(
regionName
).
Base64
;
String
regionCurrentBase64
=
regions
.
get
(
regionName
).
Base64
;
// Log
// Log
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"Client %s request: query_cur_region_%s"
,
t
.
getRemoteAddress
(),
regionName
));
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"Client %s request: query_cur_region_%s"
,
t
.
getRemoteAddress
(),
regionName
));
// Create a response form the request query parameters
// Create a response form the request query parameters
URI
uri
=
t
.
getRequestURI
();
URI
uri
=
t
.
getRequestURI
();
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
...
@@ -233,7 +288,8 @@ public final class DispatchServer {
...
@@ -233,7 +288,8 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
}
catch
(
Exception
ignored
)
{
}
}
catch
(
Exception
ignored
)
{
}
// Create response json
// Create response json
if
(
requestData
==
null
)
{
if
(
requestData
==
null
)
{
...
@@ -241,16 +297,19 @@ public final class DispatchServer {
...
@@ -241,16 +297,19 @@ public final class DispatchServer {
}
}
LoginResultJson
responseData
=
new
LoginResultJson
();
LoginResultJson
responseData
=
new
LoginResultJson
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
()
.
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in"
,
t
.
getRemoteAddress
()));
// Login
// Login
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
// Check if account exists, else create a new one.
// Check if account exists, else create a new one.
if
(
account
==
null
)
{
if
(
account
==
null
)
{
// Account doesnt exist, so we can either auto create it if the config value is set
// Account doesnt exist, so we can either auto create it if the config value is
// set
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
AutomaticallyCreateAccounts
)
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
AutomaticallyCreateAccounts
)
{
// This account has been created AUTOMATICALLY. There will be no permissions added.
// This account has been created AUTOMATICALLY. There will be no permissions
// added.
account
=
DatabaseHelper
.
createAccountWithId
(
requestData
.
account
,
0
);
account
=
DatabaseHelper
.
createAccountWithId
(
requestData
.
account
,
0
);
if
(
account
!=
null
)
{
if
(
account
!=
null
)
{
...
@@ -259,19 +318,23 @@ public final class DispatchServer {
...
@@ -259,19 +318,23 @@ public final class DispatchServer {
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account %s created"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
Grasscutter
.
getLogger
()
.
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account %s created"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
else
{
}
else
{
responseData
.
retcode
=
-
201
;
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found, create failed."
;
responseData
.
message
=
"Username not found, create failed."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account create failed"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account create failed"
,
t
.
getRemoteAddress
()));
}
}
}
else
{
}
else
{
responseData
.
retcode
=
-
201
;
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found."
;
responseData
.
message
=
"Username not found."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account no found"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
().
info
(
String
}
.
format
(
"[Dispatch] Client %s failed to log in: Account no found"
,
t
.
getRemoteAddress
()));
}
}
else
{
}
else
{
// Account was found, log the player in
// Account was found, log the player in
responseData
.
message
=
"OK"
;
responseData
.
message
=
"OK"
;
...
@@ -279,7 +342,8 @@ public final class DispatchServer {
...
@@ -279,7 +342,8 @@ public final class DispatchServer {
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
}
responseJSON
(
t
,
responseData
);
responseJSON
(
t
,
responseData
);
...
@@ -291,31 +355,35 @@ public final class DispatchServer {
...
@@ -291,31 +355,35 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
}
catch
(
Exception
ignored
)
{
}
}
catch
(
Exception
ignored
)
{
}
// Create response json
// Create response json
if
(
requestData
==
null
)
{
if
(
requestData
==
null
)
{
return
;
return
;
}
}
LoginResultJson
responseData
=
new
LoginResultJson
();
LoginResultJson
responseData
=
new
LoginResultJson
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in via token"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
()
.
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in via token"
,
t
.
getRemoteAddress
()));
// Login
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
// Test
// Test
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
responseData
.
retcode
=
-
111
;
responseData
.
retcode
=
-
111
;
responseData
.
message
=
"Game account cache information error"
;
responseData
.
message
=
"Game account cache information error"
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in via token"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
()
.
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in via token"
,
t
.
getRemoteAddress
()));
}
else
{
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in via token as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in via token as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
}
responseJSON
(
t
,
responseData
);
responseJSON
(
t
,
responseData
);
...
@@ -327,113 +395,112 @@ public final class DispatchServer {
...
@@ -327,113 +395,112 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
}
catch
(
Exception
ignored
)
{
}
}
catch
(
Exception
ignored
)
{
}
// Create response json
// Create response json
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
return
;
return
;
}
}
LoginTokenData
loginData
=
getGsonFactory
().
fromJson
(
requestData
.
data
,
LoginTokenData
.
class
);
// Get login data
LoginTokenData
loginData
=
getGsonFactory
().
fromJson
(
requestData
.
data
,
LoginTokenData
.
class
);
// Get login
// data
ComboTokenResJson
responseData
=
new
ComboTokenResJson
();
ComboTokenResJson
responseData
=
new
ComboTokenResJson
();
// Login
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
loginData
.
uid
);
Account
account
=
DatabaseHelper
.
getAccountById
(
loginData
.
uid
);
// Test
// Test
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
responseData
.
retcode
=
-
201
;
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Wrong session key."
;
responseData
.
message
=
"Wrong session key."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to exchange combo token"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to exchange combo token"
,
t
.
getRemoteAddress
()));
}
else
{
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
message
=
"OK"
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s succeed to exchange combo token"
,
t
.
getRemoteAddress
()));
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s succeed to exchange combo token"
,
t
.
getRemoteAddress
()));
}
}
responseJSON
(
t
,
responseData
);
responseJSON
(
t
,
responseData
);
});
});
// Agreement and Protocol
// Agreement and Protocol
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
"/hk4e_global/mdk/agreement/api/getAgreementInfos"
,
"/hk4e_global/mdk/agreement/api/getAgreementInfos"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}"
)
);
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
"/hk4e_global/combo/granter/api/compareProtocolVersion"
,
"/hk4e_global/combo/granter/api/compareProtocolVersion"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}"
)
);
// Game data
// Game data
server
.
createContext
(
// hk4e-api-os.hoyoverse.com
server
.
createContext
(
// hk4e-api-os.hoyoverse.com
"/common/hk4e_global/announcement/api/getAlertPic"
,
"/common/hk4e_global/announcement/api/getAlertPic"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}"
)
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}"
));
);
server
.
createContext
(
// hk4e-api-os.hoyoverse.com
server
.
createContext
(
// hk4e-api-os.hoyoverse.com
"/common/hk4e_global/announcement/api/getAlertAnn"
,
"/common/hk4e_global/announcement/api/getAlertAnn"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":true}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":true}}"
)
);
server
.
createContext
(
// hk4e-api-os.hoyoverse.com
server
.
createContext
(
// hk4e-api-os.hoyoverse.com
"/common/hk4e_global/announcement/api/getAnnList"
,
"/common/hk4e_global/announcement/api/getAnnList"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"list\":[],\"total\":0,\"type_list\":[],\"alert\":false,\"alert_id\":0,\"timezone\":0,\"t\":\""
+
System
.
currentTimeMillis
()
+
"\"}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"list\":[],\"total\":0,\"type_list\":[],\"alert\":false,\"alert_id\":0,\"timezone\":0,\"t\":\""
+
System
.
currentTimeMillis
()
+
"\"}}"
));
server
.
createContext
(
// hk4e-api-os-static.hoyoverse.com
server
.
createContext
(
// hk4e-api-os-static.hoyoverse.com
"/common/hk4e_global/announcement/api/getAnnContent"
,
"/common/hk4e_global/announcement/api/getAnnContent"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"list\":[],\"total\":0}}"
)
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"list\":[],\"total\":0}}"
));
);
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
"/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier"
,
"/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}"
)
);
// Captcha
// Captcha
server
.
createContext
(
// api-account-os.hoyoverse.com
server
.
createContext
(
// api-account-os.hoyoverse.com
"/account/risky/api/check"
,
"/account/risky/api/check"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"c8820f246a5241ab9973f71df3ddd791\",\"action\":\"\",\"geetest\":{\"challenge\":\"\",\"gt\":\"\",\"new_captcha\":0,\"success\":1}}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"c8820f246a5241ab9973f71df3ddd791\",\"action\":\"\",\"geetest\":{\"challenge\":\"\",\"gt\":\"\",\"new_captcha\":0,\"success\":1}}}"
)
);
// Config
// Config
server
.
createContext
(
// sdk-os-static.hoyoverse.com
server
.
createContext
(
// sdk-os-static.hoyoverse.com
"/combo/box/api/config/sdk/combo"
,
"/combo/box/api/config/sdk/combo"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"disable_email_bind_skip\":\"false\",\"email_bind_remind_interval\":\"7\",\"email_bind_remind\":\"true\"}}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"disable_email_bind_skip\":\"false\",\"email_bind_remind_interval\":\"7\",\"email_bind_remind\":\"true\"}}}"
)
);
server
.
createContext
(
// hk4e-sdk-os-static.hoyoverse.com
server
.
createContext
(
// hk4e-sdk-os-static.hoyoverse.com
"/hk4e_global/combo/granter/api/getConfig"
,
"/hk4e_global/combo/granter/api/getConfig"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}"
)
);
server
.
createContext
(
// hk4e-sdk-os-static.hoyoverse.com
server
.
createContext
(
// hk4e-sdk-os-static.hoyoverse.com
"/hk4e_global/mdk/shield/api/loadConfig"
,
"/hk4e_global/mdk/shield/api/loadConfig"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}"
)
);
// Test api?
// Test api?
server
.
createContext
(
// abtest-api-data-sg.hoyoverse.com
server
.
createContext
(
// abtest-api-data-sg.hoyoverse.com
"/data_abtest_api/config/experiment/list"
,
"/data_abtest_api/config/experiment/list"
,
new
DispatchHttpJsonHandler
(
"{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}"
)
new
DispatchHttpJsonHandler
(
);
"{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}"
)
);
// Log Server
// Log Server
server
.
createContext
(
// log-upload-os.mihoyo.com
server
.
createContext
(
// log-upload-os.mihoyo.com
"/log/sdk/upload"
,
"/log/sdk/upload"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
));
);
server
.
createContext
(
// log-upload-os.mihoyo.com
server
.
createContext
(
// log-upload-os.mihoyo.com
"/sdk/upload"
,
"/sdk/upload"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
));
);
server
.
createContext
(
// /perf/config/verify?device_id=xxx&platform=x&name=xxx
server
.
createContext
(
// /perf/config/verify?device_id=xxx&platform=x&name=xxx
"/perf/config/verify"
,
"/perf/config/verify"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
));
);
// Logging servers
// Logging servers
server
.
createContext
(
// overseauspider.yuanshen.com
server
.
createContext
(
// overseauspider.yuanshen.com
"/log"
,
"/log"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
));
);
server
.
createContext
(
// log-upload-os.mihoyo.com
server
.
createContext
(
// log-upload-os.mihoyo.com
"/crash/dataUpload"
,
"/crash/dataUpload"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
server
.
createContext
(
"/gacha"
,
t
->
responseHTML
(
t
,
server
.
createContext
(
"/gacha"
,
t
->
responseHTML
(
t
,
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
));
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
));
// Start server
// Start server
server
.
start
();
server
.
start
();
...
@@ -456,12 +523,12 @@ public final class DispatchServer {
...
@@ -456,12 +523,12 @@ public final class DispatchServer {
// Set the response header status and length
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
//Write the response string
//
Write the response string
OutputStream
os
=
t
.
getResponseBody
();
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
write
(
response
.
getBytes
());
os
.
close
();
os
.
close
();
}
}
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
Map
<
String
,
String
>
result
=
new
HashMap
<>();
Map
<
String
,
String
>
result
=
new
HashMap
<>();
if
(
qs
==
null
)
{
if
(
qs
==
null
)
{
...
@@ -481,7 +548,8 @@ public final class DispatchServer {
...
@@ -481,7 +548,8 @@ public final class DispatchServer {
if
(
eqPos
<
0
||
eqPos
>
next
)
{
if
(
eqPos
<
0
||
eqPos
>
next
)
{
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
next
),
"utf-8"
),
""
);
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
next
),
"utf-8"
),
""
);
}
else
{
}
else
{
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
eqPos
),
"utf-8"
),
URLDecoder
.
decode
(
qs
.
substring
(
eqPos
+
1
,
next
),
"utf-8"
));
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
eqPos
),
"utf-8"
),
URLDecoder
.
decode
(
qs
.
substring
(
eqPos
+
1
,
next
),
"utf-8"
));
}
}
}
catch
(
UnsupportedEncodingException
e
)
{
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
RuntimeException
(
e
);
// will never happen, utf-8 support is mandatory for java
throw
new
RuntimeException
(
e
);
// will never happen, utf-8 support is mandatory for java
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment