mirror of https://github.com/RPCS3/rpcs3.git
Implement sceNpManagerGetTicketParam
This commit is contained in:
parent
072c289f5e
commit
4479d99a9a
|
@ -3351,7 +3351,7 @@ error_code sceNpManagerGetTicket(vm::ptr<void> buffer, vm::ptr<u32> bufferSize)
|
||||||
|
|
||||||
error_code sceNpManagerGetTicketParam(s32 paramId, vm::ptr<SceNpTicketParam> param)
|
error_code sceNpManagerGetTicketParam(s32 paramId, vm::ptr<SceNpTicketParam> param)
|
||||||
{
|
{
|
||||||
sceNp.todo("sceNpManagerGetTicketParam(paramId=%d, param=*0x%x)", paramId, param);
|
sceNp.notice("sceNpManagerGetTicketParam(paramId=%d, param=*0x%x)", paramId, param);
|
||||||
|
|
||||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||||
|
|
||||||
|
@ -3360,12 +3360,23 @@ error_code sceNpManagerGetTicketParam(s32 paramId, vm::ptr<SceNpTicketParam> par
|
||||||
return SCE_NP_ERROR_NOT_INITIALIZED;
|
return SCE_NP_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!param)
|
if (!param || paramId < SCE_NP_TICKET_PARAM_SERIAL_ID || paramId > SCE_NP_TICKET_PARAM_SUBJECT_DOB)
|
||||||
{
|
{
|
||||||
// TODO: check paramId
|
|
||||||
return SCE_NP_ERROR_INVALID_ARGUMENT;
|
return SCE_NP_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& ticket = nph.get_ticket();
|
||||||
|
|
||||||
|
if (ticket.empty())
|
||||||
|
{
|
||||||
|
return SCE_NP_ERROR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ticket.get_value(paramId, param))
|
||||||
|
{
|
||||||
|
return SCE_NP_ERROR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3380,7 +3391,7 @@ error_code sceNpManagerGetEntitlementIdList(vm::ptr<SceNpEntitlementId> entIdLis
|
||||||
return SCE_NP_ERROR_NOT_INITIALIZED;
|
return SCE_NP_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return not_an_error(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sceNpManagerGetEntitlementById(vm::cptr<char> entId, vm::ptr<SceNpEntitlement> ent)
|
error_code sceNpManagerGetEntitlementById(vm::cptr<char> entId, vm::ptr<SceNpEntitlement> ent)
|
||||||
|
|
|
@ -243,26 +243,26 @@ enum SceNpError : u32
|
||||||
SCE_NP_COMMUNITY_SERVER_ERROR_UNSPECIFIED = 0x8002a4ff,
|
SCE_NP_COMMUNITY_SERVER_ERROR_UNSPECIFIED = 0x8002a4ff,
|
||||||
|
|
||||||
// DRM
|
// DRM
|
||||||
SCE_NP_DRM_ERROR_OUT_OF_MEMORY = 0x80029501,
|
SCE_NP_DRM_ERROR_OUT_OF_MEMORY = 0x80029501,
|
||||||
SCE_NP_DRM_ERROR_INVALID_PARAM = 0x80029502,
|
SCE_NP_DRM_ERROR_INVALID_PARAM = 0x80029502,
|
||||||
SCE_NP_DRM_ERROR_SERVER_RESPONSE = 0x80029509,
|
SCE_NP_DRM_ERROR_SERVER_RESPONSE = 0x80029509,
|
||||||
SCE_NP_DRM_ERROR_NO_ENTITLEMENT = 0x80029513,
|
SCE_NP_DRM_ERROR_NO_ENTITLEMENT = 0x80029513,
|
||||||
SCE_NP_DRM_ERROR_BAD_ACT = 0x80029514,
|
SCE_NP_DRM_ERROR_BAD_ACT = 0x80029514,
|
||||||
SCE_NP_DRM_ERROR_BAD_FORMAT = 0x80029515,
|
SCE_NP_DRM_ERROR_BAD_FORMAT = 0x80029515,
|
||||||
SCE_NP_DRM_ERROR_NO_LOGIN = 0x80029516,
|
SCE_NP_DRM_ERROR_NO_LOGIN = 0x80029516,
|
||||||
SCE_NP_DRM_ERROR_INTERNAL = 0x80029517,
|
SCE_NP_DRM_ERROR_INTERNAL = 0x80029517,
|
||||||
SCE_NP_DRM_ERROR_BAD_PERM = 0x80029519,
|
SCE_NP_DRM_ERROR_BAD_PERM = 0x80029519,
|
||||||
SCE_NP_DRM_ERROR_UNKNOWN_VERSION = 0x8002951a,
|
SCE_NP_DRM_ERROR_UNKNOWN_VERSION = 0x8002951a,
|
||||||
SCE_NP_DRM_ERROR_TIME_LIMIT = 0x8002951b,
|
SCE_NP_DRM_ERROR_TIME_LIMIT = 0x8002951b,
|
||||||
SCE_NP_DRM_ERROR_DIFFERENT_ACCOUNT_ID = 0x8002951c,
|
SCE_NP_DRM_ERROR_DIFFERENT_ACCOUNT_ID = 0x8002951c,
|
||||||
SCE_NP_DRM_ERROR_DIFFERENT_DRM_TYPE = 0x8002951d,
|
SCE_NP_DRM_ERROR_DIFFERENT_DRM_TYPE = 0x8002951d,
|
||||||
SCE_NP_DRM_ERROR_SERVICE_NOT_STARTED = 0x8002951e,
|
SCE_NP_DRM_ERROR_SERVICE_NOT_STARTED = 0x8002951e,
|
||||||
SCE_NP_DRM_ERROR_BUSY = 0x80029520,
|
SCE_NP_DRM_ERROR_BUSY = 0x80029520,
|
||||||
SCE_NP_DRM_ERROR_LICENSE_NOT_FOUND = 0x80029521,
|
SCE_NP_DRM_ERROR_LICENSE_NOT_FOUND = 0x80029521,
|
||||||
SCE_NP_DRM_ERROR_IO = 0x80029525,
|
SCE_NP_DRM_ERROR_IO = 0x80029525,
|
||||||
SCE_NP_DRM_ERROR_FORMAT = 0x80029530,
|
SCE_NP_DRM_ERROR_FORMAT = 0x80029530,
|
||||||
SCE_NP_DRM_ERROR_FILENAME = 0x80029533,
|
SCE_NP_DRM_ERROR_FILENAME = 0x80029533,
|
||||||
SCE_NP_DRM_ERROR_K_LICENSEE = 0x80029534,
|
SCE_NP_DRM_ERROR_K_LICENSEE = 0x80029534,
|
||||||
|
|
||||||
// DRM Server
|
// DRM Server
|
||||||
SCE_NP_DRM_SERVER_ERROR_SERVICE_IS_END = 0x80029700,
|
SCE_NP_DRM_SERVER_ERROR_SERVICE_IS_END = 0x80029700,
|
||||||
|
@ -292,7 +292,7 @@ enum SceNpError : u32
|
||||||
SCE_NP_AUTH_EBUSY = 0x8002a00a,
|
SCE_NP_AUTH_EBUSY = 0x8002a00a,
|
||||||
SCE_NP_AUTH_EABORT = 0x8002a00c,
|
SCE_NP_AUTH_EABORT = 0x8002a00c,
|
||||||
SCE_NP_AUTH_EEXIST = 0x8002a014,
|
SCE_NP_AUTH_EEXIST = 0x8002a014,
|
||||||
SCE_NP_AUTH_EINVALID_ARGUMENT = 0x8002a015,
|
SCE_NP_AUTH_EINVALID_ARGUMENT = 0x8002a015,
|
||||||
|
|
||||||
// Auth extended
|
// Auth extended
|
||||||
SCE_NP_AUTH_ERROR_SERVICE_END = 0x8002a200,
|
SCE_NP_AUTH_ERROR_SERVICE_END = 0x8002a200,
|
||||||
|
@ -882,6 +882,30 @@ enum
|
||||||
SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST_LIMIT = 0x000b
|
SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST_LIMIT = 0x000b
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SCE_NP_TICKET_PARAM_SERIAL_ID = 0,
|
||||||
|
SCE_NP_TICKET_PARAM_ISSUER_ID = 1,
|
||||||
|
SCE_NP_TICKET_PARAM_ISSUED_DATE = 2,
|
||||||
|
SCE_NP_TICKET_PARAM_EXPIRE_DATE = 3,
|
||||||
|
SCE_NP_TICKET_PARAM_SUBJECT_ACCOUNT_ID = 4,
|
||||||
|
SCE_NP_TICKET_PARAM_SUBJECT_ONLINE_ID = 5,
|
||||||
|
SCE_NP_TICKET_PARAM_SUBJECT_REGION = 6,
|
||||||
|
SCE_NP_TICKET_PARAM_SUBJECT_DOMAIN = 7,
|
||||||
|
SCE_NP_TICKET_PARAM_SERVICE_ID = 8,
|
||||||
|
SCE_NP_TICKET_PARAM_SUBJECT_STATUS = 9,
|
||||||
|
SCE_NP_TICKET_PARAM_STATUS_DURATION = 10,
|
||||||
|
SCE_NP_TICKET_PARAM_SUBJECT_DOB = 11,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SCE_NP_TICKET_SERIAL_ID_SIZE = 20,
|
||||||
|
SCE_NP_SUBJECT_REGION_SIZE = 4,
|
||||||
|
SCE_NP_SUBJECT_DOMAIN_SIZE = 4,
|
||||||
|
SCE_NP_SERVICE_ID_SIZE = 24,
|
||||||
|
};
|
||||||
|
|
||||||
struct SceNpDrmKey
|
struct SceNpDrmKey
|
||||||
{
|
{
|
||||||
u8 keydata[16];
|
u8 keydata[16];
|
||||||
|
|
|
@ -47,9 +47,294 @@ LOG_CHANNEL(sceNp);
|
||||||
|
|
||||||
LOG_CHANNEL(rpcn_log, "rpcn");
|
LOG_CHANNEL(rpcn_log, "rpcn");
|
||||||
LOG_CHANNEL(nph_log, "NPHandler");
|
LOG_CHANNEL(nph_log, "NPHandler");
|
||||||
|
LOG_CHANNEL(ticket_log, "Ticket");
|
||||||
|
|
||||||
namespace np
|
namespace np
|
||||||
{
|
{
|
||||||
|
ticket::ticket(std::vector<u8>&& raw_data)
|
||||||
|
: raw_data(raw_data)
|
||||||
|
{
|
||||||
|
parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t ticket::size() const
|
||||||
|
{
|
||||||
|
return raw_data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8* ticket::data() const
|
||||||
|
{
|
||||||
|
return raw_data.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ticket::empty() const
|
||||||
|
{
|
||||||
|
return raw_data.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ticket::get_value(s32 param_id, vm::ptr<SceNpTicketParam> param) const
|
||||||
|
{
|
||||||
|
if (!parse_success)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (param_id)
|
||||||
|
{
|
||||||
|
case SCE_NP_TICKET_PARAM_SERIAL_ID:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[0];
|
||||||
|
if (node.len != SCE_NP_TICKET_SERIAL_ID_SIZE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(param->data, node.data.data_vec.data(), SCE_NP_TICKET_SERIAL_ID_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_ISSUER_ID:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[1];
|
||||||
|
param->ui32 = node.data.data_u32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_ISSUED_DATE:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[2];
|
||||||
|
param->ui64 = node.data.data_u64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_EXPIRE_DATE:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[3];
|
||||||
|
param->ui64 = node.data.data_u64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_SUBJECT_ACCOUNT_ID:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[4];
|
||||||
|
param->ui64 = node.data.data_u64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_SUBJECT_ONLINE_ID:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[5];
|
||||||
|
if (node.len != 0x20)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(param->data, node.data.data_vec.data(), 0x20);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_SUBJECT_REGION:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[6];
|
||||||
|
if (node.len != SCE_NP_SUBJECT_REGION_SIZE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(param->data, node.data.data_vec.data(), SCE_NP_SUBJECT_REGION_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_SUBJECT_DOMAIN:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[7];
|
||||||
|
if (node.len != SCE_NP_SUBJECT_DOMAIN_SIZE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(param->data, node.data.data_vec.data(), SCE_NP_SUBJECT_DOMAIN_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_SERVICE_ID:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[8];
|
||||||
|
if (node.len != SCE_NP_SERVICE_ID_SIZE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(param->data, node.data.data_vec.data(), SCE_NP_SERVICE_ID_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_SUBJECT_STATUS:
|
||||||
|
{
|
||||||
|
const auto& node = nodes[0].data.data_nodes[9];
|
||||||
|
param->ui32 = node.data.data_u32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCE_NP_TICKET_PARAM_STATUS_DURATION:
|
||||||
|
case SCE_NP_TICKET_PARAM_SUBJECT_DOB:
|
||||||
|
{
|
||||||
|
param->ui64 = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
sceNp.fatal("Invalid ticket param id requested!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ticket_data> ticket::parse_node(std::size_t index) const
|
||||||
|
{
|
||||||
|
if ((index + MIN_TICKET_DATA_SIZE) > size())
|
||||||
|
{
|
||||||
|
ticket_log.error("node didn't meet minimum size requirements");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ticket_data tdata{};
|
||||||
|
const auto* ptr = data() + index;
|
||||||
|
tdata.id = *reinterpret_cast<const be_t<u16>*>(ptr);
|
||||||
|
tdata.len = *reinterpret_cast<const be_t<u16>*>(ptr + 2);
|
||||||
|
const auto* data_ptr = data() + 4;
|
||||||
|
|
||||||
|
auto check_size = [&](std::size_t expected) -> bool
|
||||||
|
{
|
||||||
|
if ((index + MIN_TICKET_DATA_SIZE + expected) > size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (tdata.id)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (tdata.len != 0)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (tdata.len != 4 || !check_size(4))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
tdata.data.data_u32 = *reinterpret_cast<const be_t<u32>*>(data_ptr);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 7:
|
||||||
|
if (tdata.len != 8 || !check_size(8))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
tdata.data.data_u64 = *reinterpret_cast<const be_t<u64>*>(data_ptr);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
if (!check_size(tdata.len))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
tdata.data.data_vec = std::vector<u8>(tdata.len);
|
||||||
|
memcpy(tdata.data.data_vec.data(), data_ptr, tdata.len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ((tdata.id & 0x3000) == 0x3000)
|
||||||
|
{
|
||||||
|
if (!check_size(tdata.len))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t sub_index = 0;
|
||||||
|
tdata.data.data_nodes = {};
|
||||||
|
while (sub_index < tdata.len)
|
||||||
|
{
|
||||||
|
auto sub_node = parse_node(sub_index + index + 4);
|
||||||
|
if (!sub_node)
|
||||||
|
{
|
||||||
|
ticket_log.error("Failed to parse subnode at %d", sub_index + index + 4);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
sub_index += sub_node->len + MIN_TICKET_DATA_SIZE;
|
||||||
|
tdata.data.data_nodes.push_back(std::move(*sub_node));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ticket::parse()
|
||||||
|
{
|
||||||
|
nodes.clear();
|
||||||
|
parse_success = false;
|
||||||
|
|
||||||
|
if (size() < (sizeof(u32) * 2))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = *reinterpret_cast<const be_t<u32>*>(data());
|
||||||
|
if (version != 0x21010000)
|
||||||
|
{
|
||||||
|
ticket_log.error("Invalid version: 0x%08x", version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 given_size = *reinterpret_cast<const be_t<u32>*>(data() + 4);
|
||||||
|
if ((given_size + 8) != size())
|
||||||
|
{
|
||||||
|
ticket_log.error("Size mismatch (gs: %d vs s: %d)", given_size, size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t index = 8;
|
||||||
|
while (index < size())
|
||||||
|
{
|
||||||
|
auto node = parse_node(index);
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
ticket_log.error("Failed to parse node at index %d", index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += (node->len + MIN_TICKET_DATA_SIZE);
|
||||||
|
nodes.push_back(std::move(*node));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that everything expected is there
|
||||||
|
if (nodes.size() != 2)
|
||||||
|
{
|
||||||
|
ticket_log.error("Expected 2 blobs, found %d", nodes.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodes[0].id != 0x3000 && nodes[1].id != 0x3002)
|
||||||
|
{
|
||||||
|
ticket_log.error("The 2 blobs ids are incorrect");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodes[0].data.data_nodes.size() < 12)
|
||||||
|
{
|
||||||
|
ticket_log.error("Expected at least 12 sub-nodes, found %d", nodes[0].data.data_nodes.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& subnodes = nodes[0].data.data_nodes;
|
||||||
|
|
||||||
|
if (subnodes[0].id != 8 || subnodes[1].id != 1 || subnodes[2].id != 7 || subnodes[3].id != 7 ||
|
||||||
|
subnodes[4].id != 2 || subnodes[5].id != 4 || subnodes[6].id != 8 || subnodes[7].id != 4 ||
|
||||||
|
subnodes[8].id != 8 || subnodes[9].id != 1)
|
||||||
|
{
|
||||||
|
ticket_log.error("Mismatched node");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_success = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
np_handler::np_handler()
|
np_handler::np_handler()
|
||||||
{
|
{
|
||||||
g_fxo->need<named_thread<signaling_handler>>();
|
g_fxo->need<named_thread<signaling_handler>>();
|
||||||
|
|
|
@ -17,6 +17,45 @@
|
||||||
|
|
||||||
namespace np
|
namespace np
|
||||||
{
|
{
|
||||||
|
struct ticket_data
|
||||||
|
{
|
||||||
|
u16 id{}, len{};
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 data_u32{};
|
||||||
|
u64 data_u64{};
|
||||||
|
std::vector<u8> data_vec;
|
||||||
|
std::vector<ticket_data> data_nodes;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ticket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ticket() = default;
|
||||||
|
ticket(std::vector<u8>&& raw_data);
|
||||||
|
|
||||||
|
std::size_t size() const;
|
||||||
|
const u8* data() const;
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
|
bool get_value(s32 param_id, vm::ptr<SceNpTicketParam> param) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<ticket_data> parse_node(std::size_t index) const;
|
||||||
|
void parse();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr std::size_t MIN_TICKET_DATA_SIZE = 4;
|
||||||
|
|
||||||
|
std::vector<u8> raw_data;
|
||||||
|
|
||||||
|
bool parse_success = false;
|
||||||
|
u32 version{};
|
||||||
|
std::vector<ticket_data> nodes;
|
||||||
|
};
|
||||||
|
|
||||||
struct basic_event
|
struct basic_event
|
||||||
{
|
{
|
||||||
s32 event = 0;
|
s32 event = 0;
|
||||||
|
@ -121,10 +160,7 @@ namespace np
|
||||||
|
|
||||||
// Misc stuff
|
// Misc stuff
|
||||||
void req_ticket(u32 version, const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, const char* entitlement_id, u32 consumed_count);
|
void req_ticket(u32 version, const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, const char* entitlement_id, u32 consumed_count);
|
||||||
const std::vector<u8>& get_ticket() const
|
const ticket& get_ticket() const;
|
||||||
{
|
|
||||||
return current_ticket;
|
|
||||||
}
|
|
||||||
u32 add_players_to_history(vm::cptr<SceNpId> npids, u32 count);
|
u32 add_players_to_history(vm::cptr<SceNpId> npids, u32 count);
|
||||||
|
|
||||||
// For signaling
|
// For signaling
|
||||||
|
@ -207,7 +243,7 @@ namespace np
|
||||||
bool is_connected = false;
|
bool is_connected = false;
|
||||||
bool is_psn_active = false;
|
bool is_psn_active = false;
|
||||||
|
|
||||||
std::vector<u8> current_ticket;
|
ticket current_ticket;
|
||||||
|
|
||||||
// IP & DNS info
|
// IP & DNS info
|
||||||
std::string hostname = "localhost";
|
std::string hostname = "localhost";
|
||||||
|
|
|
@ -675,7 +675,12 @@ namespace np
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool np_handler::reply_req_ticket(u32 /*req_id*/, std::vector<u8>& reply_data)
|
const ticket& np_handler::get_ticket() const
|
||||||
|
{
|
||||||
|
return current_ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool np_handler::reply_req_ticket([[maybe_unused]] u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
auto ticket_raw = reply.get_rawdata();
|
auto ticket_raw = reply.get_rawdata();
|
||||||
|
@ -683,7 +688,7 @@ namespace np
|
||||||
if (reply.is_error())
|
if (reply.is_error())
|
||||||
return error_and_disconnect("Malformed reply to RequestTicket command");
|
return error_and_disconnect("Malformed reply to RequestTicket command");
|
||||||
|
|
||||||
current_ticket = std::move(ticket_raw);
|
current_ticket = ticket(std::move(ticket_raw));
|
||||||
auto ticket_size = static_cast<s32>(current_ticket.size());
|
auto ticket_size = static_cast<s32>(current_ticket.size());
|
||||||
|
|
||||||
if (manager_cb)
|
if (manager_cb)
|
||||||
|
|
Loading…
Reference in New Issue