Made the Steam class in STK and SSM more compatible. Improve error
handling, and cache frequently used values (e.g. name and id).
This commit is contained in:
parent
eb4989c2ef
commit
de795b766a
@ -1518,11 +1518,10 @@ int main(int argc, char *argv[] )
|
|||||||
|
|
||||||
Steam *steam = new Steam();
|
Steam *steam = new Steam();
|
||||||
bool steam_avail = steam->isSteamAvailable();
|
bool steam_avail = steam->isSteamAvailable();
|
||||||
std::string id = steam->getId();
|
std::string id = steam->getSteamID();
|
||||||
std::string name = steam->getName();
|
std::string name = steam->getUserName();
|
||||||
int n = steam->saveAvatarAs("test.png");
|
int n = steam->saveAvatarAs("test.png");
|
||||||
//std::vector<std::string> friends = steam->getFriends();
|
delete steam;
|
||||||
//std::string quit = steam->sendCommand("quit");
|
|
||||||
|
|
||||||
CrashReporting::installHandlers();
|
CrashReporting::installHandlers();
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
Steam::Steam()
|
Steam::Steam()
|
||||||
{
|
{
|
||||||
|
m_steam_available = false;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// Based on: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
|
// Based on: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
|
||||||
SECURITY_ATTRIBUTES sec_attr;
|
SECURITY_ATTRIBUTES sec_attr;
|
||||||
@ -40,47 +41,85 @@ Steam::Steam()
|
|||||||
if (!CreatePipe(&m_child_stdout_read, &m_child_stdout_write, &sec_attr, 0))
|
if (!CreatePipe(&m_child_stdout_read, &m_child_stdout_write, &sec_attr, 0))
|
||||||
{
|
{
|
||||||
Log::error("Steam", "Error creating StdoutRd CreatePipe");
|
Log::error("Steam", "Error creating StdoutRd CreatePipe");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the read handle to the pipe for STDOUT is not inherited.
|
// Ensure the read handle to the pipe for STDOUT is not inherited.
|
||||||
|
|
||||||
if (!SetHandleInformation(m_child_stdout_read, HANDLE_FLAG_INHERIT, 0))
|
if (!SetHandleInformation(m_child_stdout_read, HANDLE_FLAG_INHERIT, 0))
|
||||||
{
|
{
|
||||||
Log::error("Steam", "Stdout SetHandleInformation");
|
Log::error("Steam", "Stdout SetHandleInformation");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a pipe for the child process's STDIN.
|
// Create a pipe for the child process's STDIN.
|
||||||
if (!CreatePipe(&m_child_stdin_read, &m_child_stdin_write, &sec_attr, 0))
|
if (!CreatePipe(&m_child_stdin_read, &m_child_stdin_write, &sec_attr, 0))
|
||||||
{
|
{
|
||||||
Log::error("Steam", "Stdin CreatePipe");
|
Log::error("Steam", "Stdin CreatePipe");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the write handle to the pipe for STDIN is not inherited.
|
// Ensure the write handle to the pipe for STDIN is not inherited.
|
||||||
|
|
||||||
if (!SetHandleInformation(m_child_stdin_write, HANDLE_FLAG_INHERIT, 0))
|
if (!SetHandleInformation(m_child_stdin_write, HANDLE_FLAG_INHERIT, 0))
|
||||||
{
|
{
|
||||||
Log::error("Steam", "Stdin SetHandleInformation");
|
Log::error("Steam", "Stdin SetHandleInformation");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the child process.
|
// Create the child process.
|
||||||
|
|
||||||
createChildProcess();
|
if (!createChildProcess())
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Could not start ssm.exe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
std::string s = sendCommand("init");
|
||||||
|
if (s != "1")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Could not initialise Steam API.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = sendCommand("name");
|
||||||
|
m_user_name = decodeString(s);
|
||||||
|
if (m_user_name == "")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Can not get Steam user name.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = sendCommand("id");
|
||||||
|
m_steam_id = decodeString(s);
|
||||||
|
if (m_steam_id== "")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Can not get Steam id.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_steam_available = true;
|
||||||
} // Steam
|
} // Steam
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Terminates the child processes and shuts down the Steam API.
|
||||||
|
*/
|
||||||
Steam::~Steam()
|
Steam::~Steam()
|
||||||
{
|
{
|
||||||
|
std::string s = sendCommand("quit");
|
||||||
|
if (s != "quit")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Could not shutdown Steam process properly");
|
||||||
|
}
|
||||||
} // ~Steam
|
} // ~Steam
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
int Steam::createChildProcess()
|
/** Starts ssm.exe as a child process and sets up communication via pipes.
|
||||||
|
* \return True if the child process creation was successful.
|
||||||
|
*/
|
||||||
|
bool Steam::createChildProcess()
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
TCHAR command_line[] = TEXT("ssm.exe 1");
|
TCHAR command_line[] = TEXT("ssm.exe 1");
|
||||||
PROCESS_INFORMATION piProcInfo;
|
PROCESS_INFORMATION piProcInfo;
|
||||||
STARTUPINFO siStartInfo;
|
STARTUPINFO siStartInfo;
|
||||||
BOOL bSuccess = FALSE;
|
|
||||||
|
|
||||||
// Set up members of the PROCESS_INFORMATION structure.
|
// Set up members of the PROCESS_INFORMATION structure.
|
||||||
|
|
||||||
@ -98,7 +137,7 @@ int Steam::createChildProcess()
|
|||||||
|
|
||||||
// Create the child process.
|
// Create the child process.
|
||||||
|
|
||||||
bSuccess = CreateProcess(NULL,
|
bool success = CreateProcess(NULL,
|
||||||
command_line, // command line
|
command_line, // command line
|
||||||
NULL, // process security attributes
|
NULL, // process security attributes
|
||||||
NULL, // primary thread security attributes
|
NULL, // primary thread security attributes
|
||||||
@ -107,32 +146,31 @@ int Steam::createChildProcess()
|
|||||||
NULL, // use parent's environment
|
NULL, // use parent's environment
|
||||||
NULL, // use parent's current directory
|
NULL, // use parent's current directory
|
||||||
&siStartInfo, // STARTUPINFO pointer
|
&siStartInfo, // STARTUPINFO pointer
|
||||||
&piProcInfo); // receives PROCESS_INFORMATION
|
&piProcInfo) != 0; // receives PROCESS_INFORMATION
|
||||||
|
|
||||||
// If an error occurs, exit the application.
|
if (!success)
|
||||||
if (!bSuccess)
|
|
||||||
{
|
{
|
||||||
Log::error("Steam", "CreateProcess");
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Close handles to the child process and its primary thread.
|
// Close handles to the child process and its primary thread.
|
||||||
// Some applications might keep these handles to monitor the status
|
// Some applications might keep these handles to monitor the status
|
||||||
// of the child process, for example.
|
// of the child process, for example.
|
||||||
|
|
||||||
CloseHandle(piProcInfo.hProcess);
|
CloseHandle(piProcInfo.hProcess);
|
||||||
CloseHandle(piProcInfo.hThread);
|
CloseHandle(piProcInfo.hThread);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
} // createChildProcess
|
} // createChildProcess
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Reads a command from the input pipe.
|
||||||
|
*/
|
||||||
std::string Steam::getLine()
|
std::string Steam::getLine()
|
||||||
{
|
{
|
||||||
#define BUFSIZE 1024
|
#define BUFSIZE 1024
|
||||||
CHAR buffer[BUFSIZE];
|
char buffer[BUFSIZE];
|
||||||
DWORD bytes_read;
|
DWORD bytes_read;
|
||||||
// Read from pipe that is the standard output for child process.
|
// Read from pipe that is the standard output for child process.
|
||||||
bool success = ReadFile(m_child_stdout_read, buffer, BUFSIZE-1,
|
bool success = ReadFile(m_child_stdout_read, buffer, BUFSIZE-1,
|
||||||
@ -147,6 +185,9 @@ std::string Steam::getLine()
|
|||||||
} // getLine
|
} // getLine
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Sends a command to the SSM via a pipe, and reads the answer.
|
||||||
|
* \return Answer from SSM.
|
||||||
|
*/
|
||||||
std::string Steam::sendCommand(const std::string &command)
|
std::string Steam::sendCommand(const std::string &command)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@ -163,6 +204,12 @@ std::string Steam::sendCommand(const std::string &command)
|
|||||||
} // sendCommand
|
} // sendCommand
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** All answer strings from 'SSM' are in the form: "length string", i.e. the
|
||||||
|
* length of the string, followed by a space and then the actual strings.
|
||||||
|
* This allows for checking on some potential problems (e.g. if a pipe should
|
||||||
|
* only send part of the answer string - todo: handle this problem instead of
|
||||||
|
* ignoring it.
|
||||||
|
*/
|
||||||
std::string Steam::decodeString(const std::string &s)
|
std::string Steam::decodeString(const std::string &s)
|
||||||
{
|
{
|
||||||
std::vector<std::string> l = StringUtils::split(s, ' ');
|
std::vector<std::string> l = StringUtils::split(s, ' ');
|
||||||
@ -180,21 +227,21 @@ std::string Steam::decodeString(const std::string &s)
|
|||||||
/** Returns the steam user name. SSM returns 'N name" where N is
|
/** Returns the steam user name. SSM returns 'N name" where N is
|
||||||
* the length of the name.
|
* the length of the name.
|
||||||
*/
|
*/
|
||||||
std::string Steam::getName()
|
const std::string& Steam::getUserName()
|
||||||
{
|
{
|
||||||
std::string s = sendCommand("name");
|
assert(m_steam_available);
|
||||||
return decodeString(s);
|
return m_user_name;
|
||||||
} // getName
|
} // getUserName
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Returns a unique id (string) from steam. SSM returns 'N ID" where N is
|
/** Returns a unique id (string) from steam. SSM returns 'N ID" where N is
|
||||||
* the length of the ID.
|
* the length of the ID.
|
||||||
*/
|
*/
|
||||||
std::string Steam::getId()
|
const std::string& Steam::getSteamID()
|
||||||
{
|
{
|
||||||
std::string s = sendCommand("id");
|
assert(m_steam_available);
|
||||||
return decodeString(s);
|
return m_steam_id;
|
||||||
} // getId
|
} // getSteamID
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Returns a std::vector with the names of all friends. SSM returns a first
|
/** Returns a std::vector with the names of all friends. SSM returns a first
|
||||||
@ -214,6 +261,10 @@ std::vector<std::string> Steam::getFriends()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Instructs the SSM to save the avatar of the user with the specified
|
||||||
|
* filename. Note that the avatar is always saved in png format (independent
|
||||||
|
* on what is specified as filename).
|
||||||
|
*/
|
||||||
int Steam::saveAvatarAs(const std::string filename)
|
int Steam::saveAvatarAs(const std::string filename)
|
||||||
{
|
{
|
||||||
//std::string s = sendCommand(std::string("avatar ")+filename);
|
//std::string s = sendCommand(std::string("avatar ")+filename);
|
||||||
|
@ -34,6 +34,15 @@
|
|||||||
class Steam
|
class Steam
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
/** True if a connection to steam was made successfully. */
|
||||||
|
bool m_steam_available;
|
||||||
|
|
||||||
|
/** Steam user name. Only defined if m_steam_available. */
|
||||||
|
std::string m_user_name;
|
||||||
|
|
||||||
|
/** Unique steam id. */
|
||||||
|
std::string m_steam_id;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// Various handles for the window pipes
|
// Various handles for the window pipes
|
||||||
HANDLE m_child_stdin_read;
|
HANDLE m_child_stdin_read;
|
||||||
@ -41,24 +50,23 @@ private:
|
|||||||
HANDLE m_child_stdout_read;
|
HANDLE m_child_stdout_read;
|
||||||
HANDLE m_child_stdout_write;
|
HANDLE m_child_stdout_write;
|
||||||
|
|
||||||
int createChildProcess();
|
bool createChildProcess();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool m_steam_available;
|
|
||||||
std::string decodeString(const std::string &s);
|
std::string decodeString(const std::string &s);
|
||||||
std::string sendCommand(const std::string &command);
|
std::string sendCommand(const std::string &command);
|
||||||
std::string getLine();
|
std::string getLine();
|
||||||
public:
|
public:
|
||||||
Steam();
|
Steam();
|
||||||
~Steam();
|
~Steam();
|
||||||
std::string getName();
|
const std::string& getUserName();
|
||||||
std::string getId();
|
const std::string& getSteamID();
|
||||||
int saveAvatarAs(const std::string filename);
|
int saveAvatarAs(const std::string filename);
|
||||||
std::vector<std::string> getFriends();
|
std::vector<std::string> getFriends();
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns true if the connection to the Steam API was successful, i.e.
|
/** Returns true if the connection to the Steam API was successful, i.e.
|
||||||
* connection to steam worked, and SteamWorks API could be initialised. */
|
* connection to steam worked, and SteamWorks API could be initialised. */
|
||||||
bool isSteamAvailable() { return m_steam_available; }
|
bool isSteamAvailable() const { return m_steam_available; }
|
||||||
}; // class Steam
|
}; // class Steam
|
||||||
|
|
||||||
#endif // HEADER_STEAM_HPP
|
#endif // HEADER_STEAM_HPP
|
||||||
|
Loading…
Reference in New Issue
Block a user