mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2025-12-16 12:08:36 +00:00
Track client platform version
Client platform version can be retrieved live with /ids and is also recorded in the playerdetail module.
This commit is contained in:
parent
87e212c2c9
commit
d6b301c3e7
@ -17,15 +17,16 @@ public:
|
||||
if (idc == kidcLeaderboard) {
|
||||
LoginHandler handler;
|
||||
std::string d = base::StringEncoder::QueryEncode(gszDeviceId);
|
||||
std::string o(base::StringEncoder::QueryEncode(HostGetPlatformString()));
|
||||
const char *url;
|
||||
if (strlen(handler.StatsUsername()) == 0) {
|
||||
url = base::Format::ToString("%s?d=%s", kszLeaderboardUrl,
|
||||
d.c_str());
|
||||
url = base::Format::ToString("%s?d=%s&o=%s", kszLeaderboardUrl,
|
||||
d.c_str(), o.c_str());
|
||||
} else {
|
||||
std::string q = base::StringEncoder::QueryEncode(
|
||||
handler.StatsUsername());
|
||||
url = base::Format::ToString("%s?p=%s&d=%s", kszLeaderboardUrl,
|
||||
q.c_str(), d.c_str());
|
||||
url = base::Format::ToString("%s?p=%s&d=%s&o=%s", kszLeaderboardUrl,
|
||||
q.c_str(), d.c_str(), o.c_str());
|
||||
}
|
||||
HostInitiateWebView("Hostile Takeover Statistics", url);
|
||||
return;
|
||||
|
||||
@ -370,17 +370,18 @@ std::string ChooseServerForm::GetServiceUrl() {
|
||||
// protocol version
|
||||
|
||||
std::string deviceid(base::StringEncoder::QueryEncode(gszDeviceId));
|
||||
std::string os(base::StringEncoder::QueryEncode(HostGetPlatformString()));
|
||||
|
||||
const char *url;
|
||||
LoginHandler handler;
|
||||
if (handler.anonymous()) {
|
||||
url = base::Format::ToString("%s?x=%d&d=%s", kszServerInfoUrl,
|
||||
kdwProtocolCurrent, deviceid.c_str());
|
||||
url = base::Format::ToString("%s?x=%d&d=%s&o=%s", kszServerInfoUrl,
|
||||
kdwProtocolCurrent, deviceid.c_str(), os.c_str());
|
||||
} else {
|
||||
std::string player(base::StringEncoder::QueryEncode(
|
||||
handler.username()));
|
||||
url = base::Format::ToString("%s?x=%d&p=%s&d=%s", kszServerInfoUrl,
|
||||
kdwProtocolCurrent, player.c_str(), deviceid.c_str());
|
||||
url = base::Format::ToString("%s?x=%d&p=%s&d=%s&o=%s", kszServerInfoUrl,
|
||||
kdwProtocolCurrent, player.c_str(), deviceid.c_str(), os.c_str());
|
||||
}
|
||||
|
||||
return url;
|
||||
|
||||
@ -8822,6 +8822,7 @@ IChatController *HostGetChatController();
|
||||
|
||||
void HostInitiateWebView(const char *title, const char *url);
|
||||
const char *HostGenerateDeviceId();
|
||||
const char *HostGetPlatformString();
|
||||
|
||||
// Date
|
||||
|
||||
|
||||
@ -54,6 +54,10 @@ const char *HostGenerateDeviceId() {
|
||||
return base::Format::ToHex(hash, 16);
|
||||
}
|
||||
|
||||
const char *HostGetPlatformString() {
|
||||
return IPhone::GetPlatformString();
|
||||
}
|
||||
|
||||
void HostInitiateWebView(const char *title, const char *url) {
|
||||
return IPhone::InitiateWebView(title, url);
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ public:
|
||||
static const char *GetTempDir();
|
||||
static const char *GetCompletesDir();
|
||||
static const char *GetStaticUUID();
|
||||
static const char *GetPlatformString();
|
||||
static void InitiateAsk(const char *title, int max, const char *def,
|
||||
int keyboard, bool secure);
|
||||
static void GetAskString(char *psz, int cb);
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
char *m_pszTempDir;
|
||||
char *m_pszCompletesDir;
|
||||
char *m_pszUUID;
|
||||
char *m_pszPlatform;
|
||||
}
|
||||
@end
|
||||
|
||||
@ -193,6 +194,15 @@ IPhoneAppDelegate *g_appDelegate;
|
||||
strcpy(m_pszUUID, pszUUID);
|
||||
CFRelease(strUUID);
|
||||
|
||||
// Get the device platform string
|
||||
NSString *strPlatform = [NSString stringWithFormat:@"iOS %@",
|
||||
[[UIDevice currentDevice] systemVersion]];
|
||||
const char *pszPlatform = [strPlatform cStringUsingEncoding:
|
||||
[NSString defaultCStringEncoding]];
|
||||
m_pszPlatform = (char *)malloc(strlen(pszPlatform) + 1);
|
||||
strcpy(m_pszPlatform, pszPlatform);
|
||||
CFRelease(strPlatform);
|
||||
|
||||
// Set up a notification to restore sound when interrupted
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(handleAudioInterruption:)
|
||||
@ -255,6 +265,11 @@ IPhoneAppDelegate *g_appDelegate;
|
||||
return m_pszUUID;
|
||||
}
|
||||
|
||||
- (const char *)platformString
|
||||
{
|
||||
return m_pszPlatform;
|
||||
}
|
||||
|
||||
- (bool)isExiting
|
||||
{
|
||||
return m_fExiting;
|
||||
@ -463,6 +478,11 @@ const char *IPhone::GetStaticUUID()
|
||||
return [g_appDelegate staticUUID];
|
||||
}
|
||||
|
||||
const char *IPhone::GetPlatformString()
|
||||
{
|
||||
return [g_appDelegate platformString];
|
||||
}
|
||||
|
||||
bool IPhone::IsExiting()
|
||||
{
|
||||
return [g_appDelegate isExiting];
|
||||
|
||||
@ -178,7 +178,10 @@ dword LoginHandler::GetToken() {
|
||||
// Submit a simple blocking request to get the token
|
||||
|
||||
SimpleRequest req(gphttp);
|
||||
const char *url = base::Format::ToString("%s?a=%s&d=%s", kszAuthUrl, output, gszDeviceId);
|
||||
std::string d = base::StringEncoder::QueryEncode(gszDeviceId);
|
||||
std::string o(base::StringEncoder::QueryEncode(HostGetPlatformString()));
|
||||
const char *url = base::Format::ToString("%s?a=%s&d=%s&o=%s", kszAuthUrl, output,
|
||||
d.c_str(), o.c_str());
|
||||
req.SetTimeout(60);
|
||||
|
||||
char result[kcbTokenMax];
|
||||
|
||||
@ -23,6 +23,7 @@ static jmethodID getAndroidIDMethod;
|
||||
static jmethodID initiateAskMethod;
|
||||
static jmethodID initiateWebViewMethod;
|
||||
static jmethodID getAskStringMethod;
|
||||
static jmethodID getPlatformStringMethod;
|
||||
|
||||
namespace wi {
|
||||
|
||||
@ -71,6 +72,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
initiateWebViewMethod = env->GetStaticMethodID(NativeLibClass, "initiateWebView", "(Ljava/lang/String;)V");
|
||||
getAskStringMethod = env->GetStaticMethodID(NativeLibClass, "getAskString", "()Ljava/lang/String;");
|
||||
initiateAskMethod = env->GetStaticMethodID(NativeLibClass, "initiateAsk", "(Ljava/lang/String;ILjava/lang/String;II)V");
|
||||
getPlatformStringMethod = env->GetStaticMethodID(NativeLibClass, "getPlatformString", "()Ljava/lang/String;");
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
@ -335,6 +337,11 @@ void HostHelpers::InitiateWebView(const char *title, const char *url) {
|
||||
g_env->CallStaticVoidMethod(NativeLibClass, initiateWebViewMethod, jstrUrl);
|
||||
}
|
||||
|
||||
const char *HostHelpers::GetPlatformString() {
|
||||
jobject jstr = g_env->CallStaticObjectMethod(NativeLibClass, getPlatformStringMethod);
|
||||
return g_env->GetStringUTFChars((jstring)jstr, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
void HostHelpers::GameThreadStart(void *pv) {
|
||||
Log("Starting game...");
|
||||
|
||||
@ -118,4 +118,8 @@ public class NativeLib {
|
||||
static String getAskString() {
|
||||
return askString;
|
||||
}
|
||||
|
||||
static String getPlatformString() {
|
||||
return "Android " + android.os.Build.VERSION.RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +67,10 @@ const char *HostGenerateDeviceId() {
|
||||
return base::Format::ToHex(hash, 16);
|
||||
}
|
||||
|
||||
const char *HostGetPlatformString() {
|
||||
return HostHelpers::GetPlatformString();
|
||||
}
|
||||
|
||||
void HostInitiateWebView(const char *title, const char *url) {
|
||||
return HostHelpers::InitiateWebView(title, url);
|
||||
}
|
||||
|
||||
@ -51,6 +51,7 @@ public:
|
||||
static bool IsExiting();
|
||||
static void GameThreadStart(void *pv);
|
||||
static void DisplayInitComplete();
|
||||
static const char *GetPlatformString();
|
||||
|
||||
// TODO(darrinm): unused?
|
||||
static int main(int argc, char **argv);
|
||||
|
||||
@ -261,6 +261,10 @@ void HostHelpers::InitiateWebView(const char *title, const char *url) {
|
||||
[iphone initiateWebView:[NSString stringWithUTF8String:url] title:[NSString stringWithUTF8String:title]];
|
||||
}
|
||||
|
||||
const char *HostHelpers::GetPlatformString() {
|
||||
return [[iphone getPlatformString] cStringUsingEncoding:NSASCIIStringEncoding];
|
||||
}
|
||||
|
||||
void HostHelpers::GameThreadStart(void *pv) {
|
||||
Log("Starting game...");
|
||||
wi::GameMain((char *)"");
|
||||
|
||||
@ -20,4 +20,5 @@
|
||||
+ (void)presentView:(UIView *)view;
|
||||
- (void)forceDeviceIntoLandscape;
|
||||
- (int)deviceOS;
|
||||
- (NSString *)getPlatformString;
|
||||
@end
|
||||
|
||||
@ -146,4 +146,9 @@
|
||||
- (int)deviceOS {
|
||||
return DEVICE_OS;
|
||||
}
|
||||
|
||||
- (NSString *)getPlatformString {
|
||||
return [NSString stringWithFormat:@"iOS %@", [[UIDevice currentDevice] systemVersion]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -246,6 +246,14 @@ void HostHelpers::InitiateWebView(const char *title, const char *url) {
|
||||
HostHelpers::OpenUrl(url);
|
||||
}
|
||||
|
||||
const char *HostHelpers::GetPlatformString() {
|
||||
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
|
||||
NSString *versionString = [NSString stringWithFormat:@"MacOS %ld.%ld.%ld",
|
||||
version.majorVersion, version.minorVersion, version.patchVersion];
|
||||
|
||||
return [versionString cStringUsingEncoding:NSASCIIStringEncoding];
|
||||
}
|
||||
|
||||
void HostHelpers::GameThreadStart(void *pv) {
|
||||
Log("Starting game...");
|
||||
wi::GameMain((char *)"");
|
||||
|
||||
@ -268,7 +268,7 @@ dword XTransport::Login(const char *username, const char *token) {
|
||||
|
||||
// Login and wait synchronously for reply.
|
||||
SetState(XTS_LOGGINGIN);
|
||||
xpump_.Send(XMsgLogin::ToBuffer(username, token, gszDeviceId));
|
||||
xpump_.Send(XMsgLogin::ToBuffer(username, token, gszDeviceId, HostGetPlatformString()));
|
||||
|
||||
if (!WaitForStateChange()) {
|
||||
LOG() << "Timed out waiting for Login";
|
||||
|
||||
@ -148,7 +148,7 @@ typedef XMsg2<XMSG_HANDSHAKE> XMsgHandshake;
|
||||
typedef XMsg2<XMSG_HANDSHAKERESULT> XMsgHandshakeResult;
|
||||
typedef XMsg0<XMSG_ECHO> XMsgEcho;
|
||||
typedef XMsg1<XMSG_PROTOCOLERROR> XMsgProtocolError;
|
||||
typedef XMsgS3<XMSG_LOGIN, kcbUsernameMax, kcbTokenMax, kcbDidMax> XMsgLogin;
|
||||
typedef XMsgS4<XMSG_LOGIN, kcbUsernameMax, kcbTokenMax, kcbDidMax, kcbPlatformMax> XMsgLogin;
|
||||
typedef XMsg1<XMSG_LOGINRESULT> XMsgLoginResult;
|
||||
typedef XMsg0<XMSG_SIGNOUT> XMsgSignOut;
|
||||
typedef XMsg1<XMSG_SIGNOUTRESULT> XMsgSignOutResult;
|
||||
|
||||
@ -50,6 +50,7 @@ const int kcbTokenMax = 256;
|
||||
const int kcbDidMax = 34;
|
||||
const int kcbChatMax = 1024;
|
||||
const int kcbShowMessageMax = 512;
|
||||
const int kcbPlatformMax = 32;
|
||||
|
||||
// Side masks
|
||||
|
||||
|
||||
144
mpshared/xmsg.h
144
mpshared/xmsg.h
@ -610,6 +610,150 @@ struct XMsgS3 : public XMsg
|
||||
}
|
||||
};
|
||||
|
||||
const dword XMSGSIZE_STRING4_FIXED = XMSGSIZE_FIXED + sizeof(word) * 4;
|
||||
|
||||
template <dword ID, int SIZE0, int SIZE1, int SIZE2, int SIZE3>
|
||||
struct XMsgS4 : public XMsg
|
||||
{
|
||||
XMsgS4(const char *s0, const char *s1, const char *s2, const char *s3) : XMsg(ID) {
|
||||
strncpyz(s0_, s0, sizeof(s0_));
|
||||
strncpyz(s1_, s1, sizeof(s1_));
|
||||
strncpyz(s2_, s2, sizeof(s2_));
|
||||
strncpyz(s3_, s3, sizeof(s3_));
|
||||
}
|
||||
char s0_[SIZE0];
|
||||
char s1_[SIZE1];
|
||||
char s2_[SIZE2];
|
||||
char s3_[SIZE3];
|
||||
|
||||
#ifdef LOGGING
|
||||
virtual std::string ToString() {
|
||||
std::ostringstream ss;
|
||||
ss << XMsgLabels.Find(id_) << ", s0: " << s0_ << ", s1: " << s1_ <<
|
||||
", s2: " << s2_ << ", s3: " << s3_ << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
static base::ByteBuffer *ToBuffer(const char *s0, const char *s1,
|
||||
const char *s2, const char *s3) {
|
||||
word cbS0 = strlen(s0) + 1;
|
||||
char s0T[SIZE0];
|
||||
if (cbS0 > sizeof(s0T)) {
|
||||
strncpyz(s0T, s0, sizeof(s0T));
|
||||
s0 = s0T;
|
||||
cbS0 = sizeof(s0T);
|
||||
}
|
||||
word cbS1 = strlen(s1) + 1;
|
||||
char s1T[SIZE1];
|
||||
if (cbS1 > sizeof(s1T)) {
|
||||
strncpyz(s1T, s1, sizeof(s1T));
|
||||
s1 = s1T;
|
||||
cbS1 = sizeof(s1T);
|
||||
}
|
||||
word cbS2 = strlen(s2) + 1;
|
||||
char s2T[SIZE2];
|
||||
if (cbS2 > sizeof(s2T)) {
|
||||
strncpyz(s2T, s2, sizeof(s2T));
|
||||
s2 = s2T;
|
||||
cbS2 = sizeof(s2T);
|
||||
}
|
||||
word cbS3 = strlen(s3) + 1;
|
||||
char s3T[SIZE3];
|
||||
if (cbS3 > sizeof(s3T)) {
|
||||
strncpyz(s3T, s3, sizeof(s3T));
|
||||
s3 = s3T;
|
||||
cbS3 = sizeof(s3T);
|
||||
}
|
||||
dword cb = XMSGSIZE_STRING4_FIXED + cbS0 + cbS1 + cbS2 + cbS3;
|
||||
base::ByteBuffer *bb = new base::ByteBuffer(cb);
|
||||
bb->WriteWord(cb);
|
||||
bb->WriteByte(ID);
|
||||
bb->WriteWord(cbS0);
|
||||
bb->WriteBytes((const byte *)s0, cbS0);
|
||||
bb->WriteWord(cbS1);
|
||||
bb->WriteBytes((const byte *)s1, cbS1);
|
||||
bb->WriteWord(cbS2);
|
||||
bb->WriteBytes((const byte *)s2, cbS2);
|
||||
bb->WriteWord(cbS3);
|
||||
bb->WriteBytes((const byte *)s3, cbS3);
|
||||
if (bb->Length() != cb) {
|
||||
delete bb;
|
||||
return NULL;
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
static XMsgS4<ID, SIZE0, SIZE1, SIZE2, SIZE3> *FromBuffer(base::ByteBuffer& bb,
|
||||
dword cb) {
|
||||
dword cbSav = bb.Length();
|
||||
word w;
|
||||
if (!bb.ReadWord(&w)) {
|
||||
return NULL;
|
||||
}
|
||||
if (cb != (dword)w || w < XMSGSIZE_STRING4_FIXED ||
|
||||
w > XMSGSIZE_STRING4_FIXED + SIZE0 + SIZE1 + SIZE2 + SIZE3) {
|
||||
Assert();
|
||||
return NULL;
|
||||
}
|
||||
if (w - sizeof(word) > bb.Length()) {
|
||||
return NULL;
|
||||
}
|
||||
byte id = 0;
|
||||
bb.ReadByte(&id);
|
||||
if (id != ID) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
word cbS0 = 0;
|
||||
bb.ReadWord(&cbS0);
|
||||
if (cbS0 > SIZE0) {
|
||||
Assert();
|
||||
return NULL;
|
||||
}
|
||||
char s0[SIZE0];
|
||||
bb.ReadBytes((byte *)s0, cbS0);
|
||||
s0[cbS0 - 1] = 0;
|
||||
|
||||
word cbS1 = 0;
|
||||
bb.ReadWord(&cbS1);
|
||||
if (cbS1 > SIZE1) {
|
||||
Assert();
|
||||
return NULL;
|
||||
}
|
||||
char s1[SIZE1];
|
||||
bb.ReadBytes((byte *)s1, cbS1);
|
||||
s1[cbS1 - 1] = 0;
|
||||
|
||||
word cbS2 = 0;
|
||||
bb.ReadWord(&cbS2);
|
||||
if (cbS2 > SIZE2) {
|
||||
Assert();
|
||||
return NULL;
|
||||
}
|
||||
char s2[SIZE2];
|
||||
bb.ReadBytes((byte *)s2, cbS2);
|
||||
s2[cbS2 - 1] = 0;
|
||||
|
||||
word cbS3 = 0;
|
||||
bb.ReadWord(&cbS3);
|
||||
if (cbS3 > SIZE3) {
|
||||
Assert();
|
||||
return NULL;
|
||||
}
|
||||
char s3[SIZE3];
|
||||
bb.ReadBytes((byte *)s3, cbS3);
|
||||
s3[cbS3 - 1] = 0;
|
||||
|
||||
if (cbSav - bb.Length() != w) {
|
||||
Assert();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new XMsgS4<ID, SIZE0, SIZE1, SIZE2, SIZE3>(s0, s1, s2, s3);
|
||||
}
|
||||
};
|
||||
|
||||
const dword XMSGSIZE_DWORDSTRING_FIXED = XMSGSIZE_FIXED + sizeof(dword) +
|
||||
sizeof(word);
|
||||
|
||||
|
||||
@ -378,8 +378,8 @@ void XPump::DispatchXMsg(XMsg *pmsg) {
|
||||
case XMSG_LOGIN:
|
||||
{
|
||||
XMsgLogin *pmsgT = (XMsgLogin *)pmsg;
|
||||
// username, token, did
|
||||
notify_->OnLogin(pmsgT->s0_, pmsgT->s1_, pmsgT->s2_);
|
||||
// username, token, did, platform
|
||||
notify_->OnLogin(pmsgT->s0_, pmsgT->s1_, pmsgT->s2_, pmsgT->s3_);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@ -20,7 +20,8 @@ public:
|
||||
bool disconnect) { Assert(); }
|
||||
virtual void OnEcho() { Assert(); }
|
||||
virtual void OnProtocolError(dword error) { Assert(); }
|
||||
virtual void OnLogin(const char *username, const char *token, const char *did) { Assert(); }
|
||||
virtual void OnLogin(const char *username, const char *token, const char *did,
|
||||
const char *platform) { Assert(); }
|
||||
virtual void OnLoginResult(dword loginResult) { Assert(); }
|
||||
virtual void OnSignOut() { Assert(); }
|
||||
virtual void OnSignOutResult(dword result) { Assert(); }
|
||||
|
||||
@ -103,8 +103,10 @@ void Endpoint::OnHandshake(dword clientid, dword protocolid) {
|
||||
okecho_ = true;
|
||||
}
|
||||
|
||||
void Endpoint::OnLogin(const char *username, const char *token, const char *did) {
|
||||
LOG() << "username: " << username << " token: " << token << " did: " << did;
|
||||
void Endpoint::OnLogin(const char *username, const char *token,
|
||||
const char *did, const char *platform) {
|
||||
LOG() << "username: " << username << " token: " << token << " did: " << did
|
||||
<< " platform: " << platform;
|
||||
|
||||
if (!CheckState(ES_HANDSHAKESUCCESS)) {
|
||||
xpump_.Send(XMsgLoginResult::ToBuffer(knLoginResultFail));
|
||||
@ -130,6 +132,7 @@ void Endpoint::OnLogin(const char *username, const char *token, const char *did)
|
||||
UpdateDid(did);
|
||||
xpump_.Send(XMsgLoginResult::ToBuffer(knLoginResultAnonymousSuccess));
|
||||
anonymous_ = true;
|
||||
strncpyz(platform_, platform, sizeof(platform_));
|
||||
SetState(ES_READY);
|
||||
return;
|
||||
}
|
||||
@ -172,6 +175,7 @@ void Endpoint::OnLogin(const char *username, const char *token, const char *did)
|
||||
// Success. Transition to ES_READY
|
||||
xpump_.Send(XMsgLoginResult::ToBuffer(knLoginResultSuccess));
|
||||
anonymous_ = false;
|
||||
strncpyz(platform_, platform, sizeof(platform_));
|
||||
SetState(ES_READY);
|
||||
|
||||
// Moderators see unfiltered chat by default
|
||||
|
||||
@ -68,6 +68,7 @@ public:
|
||||
const char *did() { return did_; }
|
||||
dword roomid() { return roomid_; }
|
||||
dword gameid();
|
||||
const char *platform() { return platform_; }
|
||||
|
||||
std::vector<std::string>& old_names() { return old_names_; }
|
||||
|
||||
@ -88,7 +89,8 @@ private:
|
||||
// XPumpNotify overrides
|
||||
virtual void OnHandshake(dword clientid, dword protocolid);
|
||||
virtual void OnEcho();
|
||||
virtual void OnLogin(const char *username, const char *token, const char *did);
|
||||
virtual void OnLogin(const char *username, const char *token,
|
||||
const char *did, const char *platform);
|
||||
virtual void OnSignOut();
|
||||
virtual void OnLobbyJoin();
|
||||
virtual void OnLobbyCreateRoom(const char *name, const char *password);
|
||||
@ -134,6 +136,7 @@ private:
|
||||
std::string chat_fragment_;
|
||||
TokenBucket roomlimiter_;
|
||||
char did_[64];
|
||||
char platform_[32];
|
||||
};
|
||||
|
||||
STARTLABEL(EsLabels)
|
||||
|
||||
@ -891,8 +891,9 @@ std::vector<std::string> Game::GetIdsString(Endpoint *endpoint) {
|
||||
char ip[32];
|
||||
(*it)->xpump().socket()->GetRemoteAddress().IPAsString(ip,
|
||||
sizeof(ip));
|
||||
responses.push_back(base::Format::ToString("%s: id %d ip %s",
|
||||
(*it)->name(), server_.GetChatterId(endpoint, *it), ip));
|
||||
responses.push_back(base::Format::ToString("%s: id %d ip %s os %s",
|
||||
(*it)->name(), server_.GetChatterId(endpoint, *it), ip,
|
||||
(*it)->platform()));
|
||||
} else {
|
||||
responses.push_back(base::Format::ToString("%s: id %d",
|
||||
(*it)->name(), server_.GetChatterId(endpoint, *it)));
|
||||
|
||||
@ -242,10 +242,10 @@ std::vector<std::string> Lobby::GetIdsString(Endpoint *endpoint) {
|
||||
char ip[32];
|
||||
it->second->xpump().socket()->
|
||||
GetRemoteAddress().IPAsString(ip, sizeof(ip));
|
||||
responses.push_back(base::Format::ToString("%s: id %d ip %s",
|
||||
responses.push_back(base::Format::ToString("%s: id %d ip %s os %s",
|
||||
it->second->name(),
|
||||
it->second->server().GetChatterId(endpoint, it->second),
|
||||
ip));
|
||||
ip, it->second->platform()));
|
||||
} else {
|
||||
responses.push_back(base::Format::ToString("%s: id %d",
|
||||
it->second->name(),
|
||||
|
||||
@ -33,6 +33,7 @@ void Player::Init(Pid pid) {
|
||||
memset(alatr_, 0, sizeof(alatr_));
|
||||
memset(&ws_, 0, sizeof(ws_));
|
||||
memset(did_, 0, sizeof(did_));
|
||||
memset(platform_, 0, sizeof(platform_));
|
||||
}
|
||||
|
||||
void Player::SetEndpoint(Endpoint *endpoint) {
|
||||
@ -44,6 +45,7 @@ void Player::SetEndpoint(Endpoint *endpoint) {
|
||||
anonymous_ = endpoint->anonymous();
|
||||
address_ = endpoint->xpump().socket()->GetRemoteAddress();
|
||||
strncpyz(did_, endpoint->did(), sizeof(did_));
|
||||
strncpyz(platform_, endpoint->platform(), sizeof(platform_));
|
||||
lag_ = knLagNone;
|
||||
nLagState_ = knLagNone;
|
||||
tLagStart_ = 0;
|
||||
@ -184,6 +186,7 @@ void Player::GetPlayerStats(PlayerStats *ps) {
|
||||
ps->pid = pid_;
|
||||
address_.IPAsString(ps->ip, sizeof(ps->ip));
|
||||
strncpyz(ps->did, did_, sizeof(ps->did));
|
||||
strncpyz(ps->platform, platform_, sizeof(ps->platform));
|
||||
|
||||
// If this player was never used, then there are no stats for it
|
||||
if (!(wf_ & kfPlrInUse)) {
|
||||
|
||||
@ -15,6 +15,7 @@ struct PlayerStats {
|
||||
Pid pid;
|
||||
char ip[32];
|
||||
char did[64];
|
||||
char platform[32];
|
||||
WinStats ws;
|
||||
};
|
||||
|
||||
@ -53,6 +54,7 @@ public:
|
||||
void ClearLatencyRecords() { clatr_ = 0; }
|
||||
const LatencyRecord *GetLatencyRecord(int i);
|
||||
void SetDid(const char *did) { strncpyz(did_, did, sizeof(did_)); }
|
||||
void SetPlatform(const char *platform) { strncpyz(platform_, platform, sizeof(platform_)); }
|
||||
|
||||
long updates() { return updates_; }
|
||||
bool havestats() { return havestats_; }
|
||||
@ -83,6 +85,7 @@ private:
|
||||
bool anonymous_;
|
||||
char did_[64];
|
||||
SideMask allies_;
|
||||
char platform_[32];
|
||||
};
|
||||
|
||||
} // namespace wi
|
||||
|
||||
@ -81,10 +81,10 @@ std::vector<std::string> Room::GetIdsString(Endpoint *endpoint) {
|
||||
char ip[32];
|
||||
it->second->xpump().socket()->
|
||||
GetRemoteAddress().IPAsString(ip, sizeof(ip));
|
||||
responses.push_back(base::Format::ToString("%s: id %d ip %s",
|
||||
responses.push_back(base::Format::ToString("%s: id %d ip %s os %s",
|
||||
it->second->name(),
|
||||
it->second->server().GetChatterId(endpoint, it->second),
|
||||
ip));
|
||||
ip, it->second->platform()));
|
||||
} else {
|
||||
responses.push_back(base::Format::ToString("%s: id %d",
|
||||
it->second->name(),
|
||||
|
||||
@ -180,6 +180,7 @@ std::string StatsPoster::ToJson(const GameStats& s) {
|
||||
GenNum(g, "pid", s.player_stats[i].pid);
|
||||
GenString(g, "ip", s.player_stats[i].ip);
|
||||
GenString(g, "did", s.player_stats[i].did);
|
||||
GenString(g, "platform", s.player_stats[i].platform);
|
||||
|
||||
str = "winstats";
|
||||
yajl_gen_string(g, (const unsigned char *)str, strlen(str));
|
||||
|
||||
@ -23,22 +23,23 @@ class AuthUser(webapp.RequestHandler):
|
||||
password = ''
|
||||
t = None
|
||||
try:
|
||||
username,password,did = self.get_username_password_did()
|
||||
username,password,did,platform = self.get_username_password_did_platform()
|
||||
if self.authenticate(username, password, did):
|
||||
t = self.generate_token(username, config.AUTH_GOOD_SECRET)
|
||||
self.save_action(username, did)
|
||||
self.save_action(username, did, platform)
|
||||
else:
|
||||
t = self.generate_token(username, config.AUTH_BAD_SECRET)
|
||||
except:
|
||||
t = self.generate_token(username, config.AUTH_BAD_SECRET)
|
||||
self.response.out.write(t)
|
||||
|
||||
def get_username_password_did(self):
|
||||
def get_username_password_did_platform(self):
|
||||
d = base64.b64decode(self.request.get('a'))
|
||||
username = d[0:d.find('\0')]
|
||||
password = d[d.find('\0')+1:]
|
||||
did = self.request.get('d')
|
||||
return username,password,did
|
||||
platform = self.request.get('o')
|
||||
return username,password,did,platform
|
||||
|
||||
def generate_token(self, username, secret):
|
||||
a = {}
|
||||
@ -55,12 +56,12 @@ class AuthUser(webapp.RequestHandler):
|
||||
return False
|
||||
return m.password.lower() == md5(password).hexdigest().lower()
|
||||
|
||||
def save_action(self, username, did):
|
||||
def save_action(self, username, did, platform):
|
||||
try:
|
||||
player_name = username
|
||||
anonymous = False
|
||||
ip = self.request.remote_addr
|
||||
action = dict(action='auth')
|
||||
playerdetail.save(player_name, anonymous, did, ip, action)
|
||||
playerdetail.save(player_name, anonymous, did, ip, action, platform)
|
||||
except:
|
||||
pass
|
||||
|
||||
@ -33,6 +33,9 @@ AddGameStat json:
|
||||
{
|
||||
"name": "<string>",
|
||||
"pid": <integer>,
|
||||
"ip": "<string>",
|
||||
"did": "<string>",
|
||||
"platform": "<string>",
|
||||
"winstats": {
|
||||
"side_mask": <integer>,
|
||||
"side_mask_allies": <integer>,
|
||||
@ -418,7 +421,16 @@ class GameStats(wrap.DictWrap):
|
||||
dids[player_stat.name] = ''
|
||||
return dids
|
||||
|
||||
def save_actions(self, dids):
|
||||
def lookup_platforms(self):
|
||||
platforms = {}
|
||||
for player_stat in self.player_stats:
|
||||
if 'platform' in player_stat.__dict__ and len(player_stat.platform) != 0:
|
||||
platforms[player_stat.name] = player_stat.platform
|
||||
continue
|
||||
platforms[player_stat.name] = ''
|
||||
return platforms
|
||||
|
||||
def save_actions(self, dids, platforms):
|
||||
# For every legit player, add a player action
|
||||
for player_stat in self.player_stats:
|
||||
if player_stat.winstats.ff & kfwsComputer:
|
||||
@ -428,12 +440,16 @@ class GameStats(wrap.DictWrap):
|
||||
did = dids[player_name] if player_name in dids else ''
|
||||
ip = player_stat.ip if 'ip' in player_stat.__dict__ else ''
|
||||
action = dict(action='game', key=self.get_game_key_name())
|
||||
playerdetail.save(player_name, anonymous, did, ip, action)
|
||||
platform = platforms[player_name] if player_name in platforms else ''
|
||||
playerdetail.save(player_name, anonymous, did, ip, action, platform)
|
||||
|
||||
def save(self, update_player_stats=True, lookup_dids=True, save_actions=True):
|
||||
try:
|
||||
# Lookup dids if asked
|
||||
dids = self.lookup_dids() if lookup_dids else {}
|
||||
|
||||
# Lookup platforms
|
||||
platforms = self.lookup_platforms()
|
||||
|
||||
# If not saved, it's already in the db.
|
||||
if not db.run_in_transaction(self.add_txn, dids):
|
||||
@ -441,7 +457,7 @@ class GameStats(wrap.DictWrap):
|
||||
if update_player_stats:
|
||||
self.update_player_stats()
|
||||
if save_actions:
|
||||
self.save_actions(dids)
|
||||
self.save_actions(dids, platforms)
|
||||
return True
|
||||
except:
|
||||
# Save game in a special place for later analysis
|
||||
|
||||
@ -102,6 +102,7 @@ class Leaderboard(basehandler.BaseHandler):
|
||||
anon = False if p else True
|
||||
did = self.request.get('d')
|
||||
ip = self.request.remote_addr
|
||||
playerdetail.save(p, anon, did, ip, dict(action='leaderboard'))
|
||||
platform = self.request.get('o')
|
||||
playerdetail.save(p, anon, did, ip, dict(action='leaderboard'), platform)
|
||||
except:
|
||||
pass
|
||||
|
||||
@ -106,6 +106,7 @@ class PlayerActionModel(db.Model):
|
||||
ip_address = db.StringProperty()
|
||||
action = db.StringProperty()
|
||||
time_utc = db.IntegerProperty()
|
||||
platform = db.StringProperty()
|
||||
|
||||
# +++
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ class PlayerDetail(basehandler.BaseHandler):
|
||||
|
||||
history_table = {}
|
||||
history_table['title'] = 'History Table'
|
||||
history_table['columns'] = ['Time', 'Player', 'Did', 'Ip', 'Action']
|
||||
history_table['columns'] = ['Time', 'Player', 'Did', 'Ip', 'Platform', 'Action']
|
||||
history_table['rows'] = []
|
||||
for r in results:
|
||||
row = []
|
||||
@ -207,6 +207,7 @@ class PlayerDetail(basehandler.BaseHandler):
|
||||
row.append([(r.player_name, self.get_url(r.player_name))])
|
||||
row.append([(r.did, self.get_url(r.did))])
|
||||
row.append([(r.ip_address, self.get_url(r.ip_address))])
|
||||
row.append([(r.platform, '')])
|
||||
row.append([self.get_action_field(r)])
|
||||
history_table['rows'].append(row)
|
||||
tables.append(history_table)
|
||||
@ -268,7 +269,7 @@ class PlayerDetail(basehandler.BaseHandler):
|
||||
url = '%s?g=%s' % (config.GAMEDETAIL_URL, a['key'])
|
||||
return a['action'], url
|
||||
|
||||
def save(player_name, anonymous, did, ip, action):
|
||||
def save(player_name, anonymous, did, ip, action, platform):
|
||||
try:
|
||||
a = models.PlayerActionModel()
|
||||
a.player_name = player_name.lower()
|
||||
@ -277,6 +278,7 @@ def save(player_name, anonymous, did, ip, action):
|
||||
a.ip_address = ip
|
||||
a.action = json.dumps(action)
|
||||
a.time_utc = int(time.time())
|
||||
a.platform = platform
|
||||
a.put()
|
||||
except:
|
||||
pass
|
||||
|
||||
@ -39,17 +39,18 @@ class ServerInfo(webapp.RequestHandler):
|
||||
# Get did, check for banned dids
|
||||
ip = self.request.remote_addr
|
||||
did = self.request.get('d')
|
||||
platform = self.request.get('o')
|
||||
if did and self.is_banned_did(did):
|
||||
self.save_action(did, ip, True)
|
||||
self.save_action(did, ip, True, platform)
|
||||
return
|
||||
|
||||
# Check for banned ips
|
||||
if ip and self.is_banned_ip(ip):
|
||||
self.save_action(did, ip, True)
|
||||
self.save_action(did, ip, True, platform)
|
||||
return
|
||||
|
||||
# Not banned
|
||||
self.save_action(did, ip, False)
|
||||
self.save_action(did, ip, False, platform)
|
||||
|
||||
# Attempt to retrieve serverinfo from cache
|
||||
j = memcache.get(SERVERINFO_KEY)
|
||||
@ -120,12 +121,12 @@ class ServerInfo(webapp.RequestHandler):
|
||||
memcache.set(SERVERINFO_KEY, j, info['expires_utc'])
|
||||
return j
|
||||
|
||||
def save_action(self, did, ip, banned):
|
||||
def save_action(self, did, ip, banned, platform):
|
||||
try:
|
||||
p = self.request.get('p')
|
||||
anon = False if p else True
|
||||
d = dict(action='serverinfo', banned=banned)
|
||||
playerdetail.save(p, anon, did, ip, d)
|
||||
playerdetail.save(p, anon, did, ip, d, platform)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user