few changes

This commit is contained in:
PaulCombal 2019-08-01 13:30:39 +02:00
parent 8d6cd4f2df
commit 2af360c3a2
8 changed files with 226 additions and 199 deletions

View File

@ -9,10 +9,7 @@
#include "types/Actions.h"
#include "SteamAppDAO.h"
#include "common/functions.h"
#include "common/yajlHelpers.h"
#define MAX_PATH 1000
#include "json/yajlHelpers.h"
MySteam::MySteam() {
@ -242,51 +239,23 @@ MySteam::refresh_icons() {
}
// => refresh_icons
std::vector<Achievement_t>
MySteam::get_achievements() {
std::vector<Achievement_t> achievements;
std::string response;
const unsigned char * buf;
size_t len;
if (m_ipc_socket == nullptr) {
std::cerr << "Connection to game is broken" << std::endl;
exit(0);
}
achievements.clear();
// TODO: these MySteam functions should probably be moved to a MyGameClient.cpp
// TODO: could push this handle generation handling down into a YAJL
// interfacing object
yajl_gen handle = yajl_gen_alloc(NULL);
//TODO: collect this encode_request routine better
// but cannot because commit_changes needs to keep map open
if (yajl_gen_map_open(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
exit(EXIT_FAILURE);
}
encode_request(handle, GET_ACHIEVEMENTS_STR);
if (yajl_gen_map_close(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
yajl_gen_get_buf(handle, &buf, &len);
response = m_ipc_socket->request_response(std::string((const char*)buf));
yajl_gen_free(handle);
std::string response = m_ipc_socket->request_response(make_get_achivements_request_string());
if (!decode_ack(response)) {
std::cerr << "Failed to receive ack!" << std::endl;
}
achievements = decode_achievements(response);
return achievements;
return decode_achievements(response);
}
// => get_achievements
/**
* Adds an achievement to the list of achievements to unlock/lock
@ -317,46 +286,19 @@ MySteam::remove_modification_ach(const std::string& ach_id) {
void
MySteam::commit_changes(void) {
std::vector<AchievementChange_t> changes;
std::string response;
const unsigned char * buf;
size_t len;
// Transform to AchievementChange_t
for ( const auto& [key, val] : m_pending_ach_modifications) {
std::cerr << "key " << key << "val " << val << std::endl;
changes.push_back( (AchievementChange_t){ key, val } );
}
//return;
yajl_gen handle = yajl_gen_alloc(NULL);
if (handle == NULL) {
std::cerr << "Failed to make handle" << std::endl;
return;
}
if (yajl_gen_map_open(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
encode_request(handle, STORE_ACHIEVEMENTS_STR);
encode_changes(handle, changes);
if (yajl_gen_map_close(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
yajl_gen_get_buf(handle, &buf, &len);
response = m_ipc_socket->request_response(std::string((const char*)buf));
yajl_gen_free(handle);
std::string response = m_ipc_socket->request_response(make_store_achivements_request_string(changes));
if (!decode_ack(response)) {
std::cerr << "Failed to store achievement changes!" << std::endl;
}
//reset current changes
// Clear all pending changes
m_pending_ach_modifications.clear();
}
// => commit_changes

View File

@ -0,0 +1,96 @@
#include "ProcessedGameServerRequest.h"
#include <iostream>
SAM_ACTION
str2action(const std::string& str) {
if (str == GET_ACHIEVEMENTS_STR)
{
return GET_ACHIEVEMENTS;
}
else if (str == STORE_ACHIEVEMENTS_STR)
{
return STORE_ACHIEVEMENTS;
}
else if (str == QUIT_GAME_STR)
{
return QUIT_GAME;
}
else {
return INVALID;
}
}
ProcessedGameServerRequest::ProcessedGameServerRequest(const std::string& request)
{
m_fulltree = yajl_tree_parse(request.c_str(), NULL, 0);
if (m_fulltree == NULL) {
std::cerr << "Parsing error";
exit(EXIT_FAILURE);
}
const char * path[] = { SAM_ACTION_STR, (const char*)0 };
const char * list_path[] = { ACHIEVEMENT_LIST_STR, (const char*)0 };
yajl_val v = yajl_tree_get(m_fulltree, path, yajl_t_string);
if (v == NULL || !YAJL_IS_STRING(v)) {
std::cerr << "failed to get " << SAM_ACTION_STR << std::endl;
exit(EXIT_FAILURE);
}
// Some Requests include a payload (eg STORE_ACHIEVEMENTS, we'll have to deal with it at some point)
switch (m_action = str2action(YAJL_GET_STRING(v)))
{
case STORE_ACHIEVEMENTS:
m_payload = yajl_tree_get(m_fulltree, list_path, yajl_t_array);
break;
default:
break;
}
}
ProcessedGameServerRequest::~ProcessedGameServerRequest()
{
yajl_tree_free(m_fulltree);
}
std::vector<AchievementChange_t>
ProcessedGameServerRequest::payload_to_ach_changes() const
{
std::vector<AchievementChange_t> changes;
const char * id_path[] = { ID_STR, (const char*)0 };
const char * achieved_path[] = { ACHIEVED_STR, (const char*)0 };
yajl_val *w = YAJL_GET_ARRAY(m_payload)->values;
size_t array_len = YAJL_GET_ARRAY(m_payload)->len;
changes.resize(array_len);
for(unsigned i = 0; i < array_len; i++) {
yajl_val cur_node = w[i];
yajl_val cur_val;
// TODO: pull these out into a decode_change()?
// verification is done via the type argument to yajl_tree_get
// and via YAJL_IS_* checks if type alone isn't sufficient
cur_val = yajl_tree_get(cur_node, id_path, yajl_t_string);
if (cur_val == NULL) {
std::cerr << "parsing error" << std::endl;
}
changes[i].id = YAJL_GET_STRING(cur_val);
// why is bool parsing weird
cur_val = yajl_tree_get(cur_node, achieved_path, yajl_t_any);
if (cur_val == NULL) {
std::cerr << "parsing error" << std::endl;
}
if (!YAJL_IS_TRUE(cur_val) && !YAJL_IS_FALSE(cur_val)) {
std::cerr << "bool parsing error" << std::endl;
}
changes[i].achieved = YAJL_IS_TRUE(cur_val);
}
return changes;
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <yajl/yajl_tree.h>
#include <vector>
#include "../types/Actions.h"
#include "../types/Achievement.h"
/**
* This is a serverside class
*/
class ProcessedGameServerRequest {
public:
ProcessedGameServerRequest(const std::string& request);
~ProcessedGameServerRequest();
SAM_ACTION getAction() const {return m_action;};
yajl_val getPayload() const {return m_payload;};
std::vector<AchievementChange_t> payload_to_ach_changes() const;
protected:
SAM_ACTION m_action;
yajl_val m_payload;
yajl_val m_fulltree;
};

View File

@ -3,28 +3,8 @@
#include <iostream>
#include <cstring>
#include "../types/ProcessedRequest.h"
#include "../types/Actions.h"
SAM_ACTION
str2action(const std::string& str) {
if (str == GET_ACHIEVEMENTS_STR)
{
return GET_ACHIEVEMENTS;
}
else if (str == STORE_ACHIEVEMENTS_STR)
{
return STORE_ACHIEVEMENTS;
}
else if (str == QUIT_GAME_STR)
{
return QUIT_GAME;
}
else {
return INVALID;
}
}
void
yajl_gen_string_wrap(yajl_gen handle, const char * a) {
if (yajl_gen_string(handle, (const unsigned char *)a, strlen(a)) != yajl_gen_status_ok) {
@ -52,8 +32,11 @@ decode_ack(std::string response) {
if (cur_val == NULL) {
std::cerr << "parsing error" << std::endl;
}
std::string ack_value = YAJL_GET_STRING(cur_val);
yajl_tree_free(node);
return std::string(SAM_ACK_STR) == YAJL_GET_STRING(cur_val);
return std::string(SAM_ACK_STR) == ack_value;
}
void
@ -62,29 +45,6 @@ encode_request(yajl_gen handle, const char * request) {
yajl_gen_string_wrap(handle, request);
}
ProcessedRequest
decode_request(std::string request) {
yajl_val node = yajl_tree_parse(request.c_str(), NULL, 0);
if (node == NULL) {
std::cerr << "Parsing error";
exit(EXIT_FAILURE);
}
const char * path[] = { SAM_ACTION_STR, (const char*)0 };
yajl_val v = yajl_tree_get(node, path, yajl_t_string);
if (v == NULL || !YAJL_IS_STRING(v)) {
std::cerr << "failed to get" << SAM_ACTION_STR << std::endl;
exit(EXIT_FAILURE);
}
// Some Requests include a payload (eg STORE_ACHIEVEMENTS, we'll have to deal with it at some point)
ProcessedRequest ret;
ret.action = str2action(YAJL_GET_STRING(v));
ret.payload = "TODODOD";
return ret;
}
/**
* Encode an individual achievement into a given YAJL handle
*/
@ -293,58 +253,76 @@ encode_changes(yajl_gen handle, std::vector<AchievementChange_t> changes) {
}
}
std::vector<AchievementChange_t>
decode_changes(std::string request) {
std::vector<AchievementChange_t> changes;
std::string
make_get_achivements_request_string() {
const unsigned char * buf;
size_t len;
std::string ret;
//parse request
yajl_val node = yajl_tree_parse(request.c_str(), NULL, 0);
if (node == NULL) {
std::cerr << "parsing error";
exit(EXIT_FAILURE);
yajl_gen handle = yajl_gen_alloc(NULL);
if (yajl_gen_map_open(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
// dumb defines for required interface for yajl_tree
const char * list_path[] = { ACHIEVEMENT_LIST_STR, (const char*)0 };
const char * id_path[] = { ID_STR, (const char*)0 };
const char * achieved_path[] = { ACHIEVED_STR, (const char*)0 };
yajl_val v = yajl_tree_get(node, list_path, yajl_t_array);
if (v == NULL) {
std::cerr << "parsing error" << std::endl;
encode_request(handle, GET_ACHIEVEMENTS_STR);
if (yajl_gen_map_close(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
yajl_val *w = YAJL_GET_ARRAY(v)->values;
size_t array_len = YAJL_GET_ARRAY(v)->len;
yajl_gen_get_buf(handle, &buf, &len);
ret = std::string((const char*)buf);
yajl_gen_free(handle);
changes.clear();
changes.resize(array_len);
for(unsigned i = 0; i < array_len; i++) {
yajl_val cur_node = w[i];
yajl_val cur_val;
// TODO: pull these out into a decode_change()?
// verification is done via the type argument to yajl_tree_get
// and via YAJL_IS_* checks if type alone isn't sufficient
cur_val = yajl_tree_get(cur_node, id_path, yajl_t_string);
if (cur_val == NULL) {
std::cerr << "parsing error" << std::endl;
}
changes[i].id = YAJL_GET_STRING(cur_val);
// why is bool parsing weird
cur_val = yajl_tree_get(cur_node, achieved_path, yajl_t_any);
if (cur_val == NULL) {
std::cerr << "parsing error" << std::endl;
}
if (!YAJL_IS_TRUE(cur_val) && !YAJL_IS_FALSE(cur_val)) {
std::cerr << "bool parsing error" << std::endl;
}
changes[i].achieved = YAJL_IS_TRUE(cur_val);
}
yajl_tree_free(node);
return changes;
return ret;
}
std::string
make_store_achivements_request_string(const std::vector<AchievementChange_t>& changes) {
const unsigned char * buf;
size_t len;
std::string ret;
yajl_gen handle = yajl_gen_alloc(NULL);
if (handle == NULL) {
std::cerr << "Failed to make handle" << std::endl;
}
if (yajl_gen_map_open(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
encode_request(handle, STORE_ACHIEVEMENTS_STR);
encode_changes(handle, changes);
if (yajl_gen_map_close(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
yajl_gen_get_buf(handle, &buf, &len);
ret = std::string((const char*)buf);
yajl_gen_free(handle);
return ret;
}
std::string
make_kill_server_request_string() {
std::string ret;
const unsigned char * buf;
size_t len;
yajl_gen handle = yajl_gen_alloc(NULL);
if (yajl_gen_map_open(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
encode_request(handle, QUIT_GAME_STR);
if (yajl_gen_map_close(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
yajl_gen_get_buf(handle, &buf, &len);
ret = std::string((const char*)buf);
yajl_gen_free(handle);
return ret;
}

View File

@ -6,7 +6,7 @@
#include <yajl/yajl_tree.h>
#include "../types/Achievement.h"
#include "../types/Actions.h"
#include "../types/ProcessedRequest.h"
#include "ProcessedGameServerRequest.h"
/**
* Encode a string into a YAJL handle and
@ -30,11 +30,6 @@ bool decode_ack(std::string response);
*/
void encode_request(yajl_gen handle, const char * request);
/**
* Decode a request
*/
ProcessedRequest decode_request(std::string request);
/**
* Encode an achievement vector into a given YAJL handle
* Encode an array at a time because decoding individual
@ -53,6 +48,25 @@ std::vector<Achievement_t> decode_achievements(std::string response);
void encode_changes(yajl_gen handle, std::vector<AchievementChange_t> changes);
/**
* To be used by the server
* Client will encode the desired changes in JSON
* Decode just achievement changes into a vector
*/
std::vector<AchievementChange_t> decode_changes(std::string request);
std::vector<AchievementChange_t> decode_changes(const ProcessedGameServerRequest& request);
/**
* Generate a GET_ACHIEVEMENTS request string
*/
std::string make_get_achivements_request_string();
/**
* Generate a STORE_ACHIEVEMENTS request string
*/
std::string make_store_achivements_request_string(const std::vector<AchievementChange_t>& changes);
/**
* Generate a KILL_SERVER request string
*/
std::string make_kill_server_request_string();

View File

@ -1,7 +1,6 @@
#include "MyClientSocket.h"
#include "../types/Actions.h"
#include <yajl/yajl_gen.h>
#include "../common/yajlHelpers.h"
#include "../json/yajlHelpers.h"
#include <thread>
#include <chrono>
@ -64,21 +63,7 @@ MyClientSocket::disconnect()
void
MyClientSocket::kill_server()
{
std::string response;
const unsigned char * buf;
size_t len;
yajl_gen handle = yajl_gen_alloc(NULL);
if (yajl_gen_map_open(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
encode_request(handle, QUIT_GAME_STR);
if (yajl_gen_map_close(handle) != yajl_gen_status_ok) {
std::cerr << "failed to make json" << std::endl;
}
yajl_gen_get_buf(handle, &buf, &len);
response = request_response(std::string((const char*)buf));
yajl_gen_free(handle);
std::string response = request_response( make_kill_server_request_string() );
if (!decode_ack(response)) {
std::cerr << "Failed to close game!" << std::endl;

View File

@ -2,8 +2,8 @@
#include <yajl/yajl_tree.h>
#include "MyGameSocket.h"
#include "../types/Actions.h"
#include "../common/yajlHelpers.h"
#include "../types/ProcessedRequest.h"
#include "../json/ProcessedGameServerRequest.h"
#include "../json/yajlHelpers.h"
MyGameSocket::MyGameSocket(AppId_t appid) :
MyServerSocket(appid),
@ -14,7 +14,7 @@ m_CallbackUserStatsReceived( this, &MyGameSocket::OnUserStatsReceived )
std::string
MyGameSocket::process_request(std::string request, bool& quit) {
ProcessedRequest r = decode_request(request);
ProcessedGameServerRequest r(request);
std::string ret;
const unsigned char * buf;
size_t len;
@ -25,14 +25,14 @@ MyGameSocket::process_request(std::string request, bool& quit) {
encode_ack(handle);
switch (r.action) {
switch (r.getAction()) {
case GET_ACHIEVEMENTS:
// Write achievements to handle
encode_achievements(handle, get_achievements());
break;
case STORE_ACHIEVEMENTS:
process_changes( decode_changes(request));
process_changes( r.payload_to_ach_changes() );
break;
case QUIT_GAME:

View File

@ -1,11 +0,0 @@
#pragma once
#include <string>
#include "Actions.h"
struct ProcessedRequest {
SAM_ACTION action;
std::string payload;
};
typedef struct ProcessedRequest ProcessedRequest;