mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-14 18:57:07 -07:00
Ctrl Request
This commit is contained in:
parent
640889eea3
commit
7333044a19
6 changed files with 190 additions and 14 deletions
|
@ -29,6 +29,7 @@ typedef struct chiaki_ctrl_t
|
|||
{
|
||||
struct chiaki_session_t *session;
|
||||
ChiakiThread thread;
|
||||
int sock;
|
||||
} ChiakiCtrl;
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_start(ChiakiCtrl *ctrl, struct chiaki_session_t *session);
|
||||
|
|
|
@ -33,7 +33,6 @@ typedef struct chiaki_rpcrypt_t
|
|||
{
|
||||
uint8_t bright[CHIAKI_KEY_BYTES];
|
||||
uint8_t ambassador[CHIAKI_KEY_BYTES];
|
||||
struct hmac_ctx_st *hmac_ctx;
|
||||
} ChiakiRPCrypt;
|
||||
|
||||
CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *ambassador, const uint8_t *nonce, const uint8_t *morning);
|
||||
|
|
|
@ -31,13 +31,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define CHIAKI_RP_DID_SIZE 32
|
||||
|
||||
typedef struct chiaki_connect_info_t
|
||||
{
|
||||
const char *host;
|
||||
const char *regist_key;
|
||||
const char *ostype;
|
||||
char auth[0x10];
|
||||
const char *host; // null terminated
|
||||
const char *regist_key; // null terminated
|
||||
const char *ostype; // null terminated
|
||||
char auth[0x10]; // must be completely filled (pad with \0)
|
||||
uint8_t morning[0x10];
|
||||
uint8_t did[CHIAKI_RP_DID_SIZE];
|
||||
} ChiakiConnectInfo;
|
||||
|
||||
|
||||
|
@ -72,6 +76,7 @@ typedef void (*ChiakiEventCallback)(ChiakiEvent *event, void *user);
|
|||
|
||||
|
||||
|
||||
|
||||
typedef struct chiaki_session_t
|
||||
{
|
||||
struct
|
||||
|
@ -83,9 +88,11 @@ typedef struct chiaki_session_t
|
|||
char *ostype;
|
||||
char auth[CHIAKI_KEY_BYTES];
|
||||
uint8_t morning[CHIAKI_KEY_BYTES];
|
||||
uint8_t did[CHIAKI_RP_DID_SIZE];
|
||||
} connect_info;
|
||||
|
||||
uint8_t nonce[CHIAKI_KEY_BYTES];
|
||||
ChiakiRPCrypt rpcrypt;
|
||||
|
||||
ChiakiQuitReason quit_reason;
|
||||
|
||||
|
@ -109,6 +116,13 @@ static inline void chiaki_session_set_event_cb(ChiakiSession *session, ChiakiEve
|
|||
session->event_cb_user = user;
|
||||
}
|
||||
|
||||
static inline void chiaki_session_set_quit_reason(ChiakiSession *session, ChiakiQuitReason reason)
|
||||
{
|
||||
if(session->quit_reason != CHIAKI_QUIT_REASON_NONE)
|
||||
return;
|
||||
session->quit_reason = reason;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
151
lib/src/ctrl.c
151
lib/src/ctrl.c
|
@ -17,11 +17,14 @@
|
|||
|
||||
#include <chiaki/ctrl.h>
|
||||
#include <chiaki/session.h>
|
||||
#include <chiaki/base64.h>
|
||||
#include <chiaki/http.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define SESSION_CTRL_PORT 9295
|
||||
|
@ -47,11 +50,49 @@ static void *ctrl_thread_func(void *user)
|
|||
{
|
||||
ChiakiCtrl *ctrl = user;
|
||||
|
||||
ChiakiErrorCode err = ctrl_thread_connect(ctrl);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
chiaki_session_set_quit_reason(ctrl->session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct ctrl_response_t {
|
||||
bool server_type_valid;
|
||||
uint8_t rp_server_type[0x10];
|
||||
bool success;
|
||||
} CtrlResponse;
|
||||
|
||||
static void parse_ctrl_response(CtrlResponse *response, ChiakiHttpResponse *http_response)
|
||||
{
|
||||
memset(response, 0, sizeof(CtrlResponse));
|
||||
|
||||
if(http_response->code != 200)
|
||||
{
|
||||
response->success = false;
|
||||
return;
|
||||
}
|
||||
|
||||
response->success = true;
|
||||
response->server_type_valid = false;
|
||||
for(ChiakiHttpHeader *header=http_response->headers; header; header=header->next)
|
||||
{
|
||||
if(strcmp(header->key, "RP-Server-Type") == 0)
|
||||
{
|
||||
size_t server_type_size = sizeof(response->rp_server_type);
|
||||
chiaki_base64_decode(header->value, strlen(header->value) + 1, response->rp_server_type, &server_type_size);
|
||||
response->server_type_valid = server_type_size == sizeof(response->rp_server_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ChiakiErrorCode ctrl_thread_connect(ChiakiCtrl *ctrl)
|
||||
{
|
||||
ChiakiSession *session = ctrl->session;
|
||||
|
@ -72,21 +113,65 @@ static ChiakiErrorCode ctrl_thread_connect(ChiakiCtrl *ctrl)
|
|||
if(sock < 0)
|
||||
{
|
||||
CHIAKI_LOGE(&session->log, "Session ctrl socket creation failed.\n");
|
||||
if(session->quit_reason == CHIAKI_QUIT_REASON_NONE)
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_CTRL_UNKNOWN;
|
||||
chiaki_session_set_quit_reason(session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN);
|
||||
return CHIAKI_ERR_NETWORK;
|
||||
}
|
||||
|
||||
int r = connect(sock, sa, addr->ai_addrlen);
|
||||
free(sa);
|
||||
if(r < 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
CHIAKI_LOGE(&session->log, "Ctrl connect failed: %s\n", strerror(errsv));
|
||||
if(errsv == ECONNREFUSED)
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_SESSION_REQUEST_CONNECTION_REFUSED;
|
||||
else
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_NONE;
|
||||
close(sock);
|
||||
return CHIAKI_ERR_NETWORK;
|
||||
}
|
||||
|
||||
CHIAKI_LOGI(&session->log, "Connected to %s:%d\n", session->connect_info.hostname, SESSION_CTRL_PORT);
|
||||
|
||||
char request[512];
|
||||
|
||||
uint8_t auth_enc[CHIAKI_KEY_BYTES];
|
||||
ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 0, (uint8_t *)session->connect_info.auth, auth_enc, CHIAKI_KEY_BYTES);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto error;
|
||||
char auth_b64[CHIAKI_KEY_BYTES*2];
|
||||
err = chiaki_base64_encode(auth_enc, sizeof(auth_enc), auth_b64, sizeof(auth_b64));
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto error;
|
||||
|
||||
uint8_t did_enc[CHIAKI_RP_DID_SIZE];
|
||||
err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 1, (uint8_t *)session->connect_info.did, did_enc, CHIAKI_RP_DID_SIZE);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto error;
|
||||
char did_b64[CHIAKI_RP_DID_SIZE*2];
|
||||
err = chiaki_base64_encode(did_enc, sizeof(did_enc), did_b64, sizeof(did_b64));
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto error;
|
||||
|
||||
uint8_t ostype_enc[128];
|
||||
size_t ostype_len = strlen(session->connect_info.ostype) + 1;
|
||||
if(ostype_len > sizeof(ostype_enc))
|
||||
goto error;
|
||||
err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 2, (uint8_t *)session->connect_info.ostype, ostype_enc, ostype_len);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto error;
|
||||
char ostype_b64[256];
|
||||
err = chiaki_base64_encode(ostype_enc, ostype_len, ostype_b64, sizeof(ostype_b64));
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto error;
|
||||
|
||||
|
||||
static const char request_fmt[] =
|
||||
"GET /sce/rp/session/ctrl HTTP/1.1\r\n"
|
||||
"Host: %s:%d\r\n"
|
||||
"User-Agent: remoteplay Windows\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"RP-Auth: %s\r\n"
|
||||
"RP-Auth: %s\r\n"
|
||||
"RP-Version: 8.0\r\n"
|
||||
"RP-Did: %s\r\n"
|
||||
"RP-ControllerType: 3\r\n"
|
||||
|
@ -94,10 +179,64 @@ static ChiakiErrorCode ctrl_thread_connect(ChiakiCtrl *ctrl)
|
|||
"RP-OSType: %s\r\n"
|
||||
"RP-ConPath: 1\r\n\r\n";
|
||||
|
||||
uint8_t auth_enc[CHIAKI_KEY_BYTES];
|
||||
char buf[512];
|
||||
int request_len = snprintf(buf, sizeof(buf), request_fmt,
|
||||
session->connect_info.hostname, SESSION_CTRL_PORT, auth_b64, did_b64, ostype_b64);
|
||||
if(request_len < 0 || request_len >= sizeof(buf))
|
||||
goto error;
|
||||
|
||||
CHIAKI_LOGI(&session->log, "Sending ctrl request\n");
|
||||
|
||||
ssize_t sent = send(sock, buf, (size_t)request_len, 0);
|
||||
if(sent < 0)
|
||||
{
|
||||
CHIAKI_LOGE(&session->log, "Failed to send ctrl request\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
close(sock);
|
||||
size_t header_size;
|
||||
size_t received_size;
|
||||
err = chiaki_recv_http_header(sock, buf, sizeof(buf)-1, &header_size, &received_size);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
CHIAKI_LOGE(&session->log, "Failed to receive ctrl request response\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
buf[received_size] = '\0';
|
||||
|
||||
ChiakiHttpResponse http_response;
|
||||
err = chiaki_http_response_parse(&http_response, buf, header_size);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
CHIAKI_LOGE(&session->log, "Failed to parse ctrl request response\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
CtrlResponse response;
|
||||
parse_ctrl_response(&response, &http_response);
|
||||
chiaki_http_response_fini(&http_response);
|
||||
|
||||
if(!response.success)
|
||||
{
|
||||
err = CHIAKI_ERR_UNKNOWN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(response.server_type_valid)
|
||||
{
|
||||
ChiakiErrorCode err2 = chiaki_rpcrypt_decrypt(&session->rpcrypt, 0, response.rp_server_type, response.rp_server_type, sizeof(response.rp_server_type));
|
||||
response.server_type_valid = err2 == CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
if(!response.server_type_valid)
|
||||
CHIAKI_LOGE(&session->log, "No valid Server Type in ctrl response\n");
|
||||
|
||||
ctrl->sock = sock;
|
||||
close(sock); // TODO: remove
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
|
||||
error:
|
||||
close(sock);
|
||||
return err;
|
||||
}
|
|
@ -68,6 +68,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_init(ChiakiSession *session, Chiaki
|
|||
|
||||
memcpy(session->connect_info.auth, connect_info->auth, sizeof(session->connect_info.auth));
|
||||
memcpy(session->connect_info.morning, connect_info->morning, sizeof(session->connect_info.morning));
|
||||
memcpy(session->connect_info.did, connect_info->did, sizeof(session->connect_info.did));
|
||||
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
@ -114,6 +115,20 @@ static void *session_thread_func(void *arg)
|
|||
|
||||
CHIAKI_LOGI(&session->log, "Session request successful\n");
|
||||
|
||||
chiaki_rpcrypt_init(&session->rpcrypt, session->nonce, session->connect_info.morning);
|
||||
|
||||
usleep(10000);
|
||||
|
||||
CHIAKI_LOGI(&session->log, "Starting ctrl\n");
|
||||
|
||||
ChiakiErrorCode err = chiaki_ctrl_start(&session->ctrl, session);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto quit;
|
||||
|
||||
chiaki_ctrl_join(&session->ctrl);
|
||||
|
||||
CHIAKI_LOGI(&session->log, "Ctrl stopped\n");
|
||||
|
||||
ChiakiEvent quit_event;
|
||||
quit:
|
||||
quit_event.type = CHIAKI_EVENT_QUIT;
|
||||
|
@ -258,7 +273,7 @@ static bool session_thread_request_session(ChiakiSession *session)
|
|||
|
||||
size_t header_size;
|
||||
size_t received_size;
|
||||
ChiakiErrorCode err = chiaki_recv_http_header(session_sock, buf, sizeof(buf), &header_size, &received_size);
|
||||
ChiakiErrorCode err = chiaki_recv_http_header(session_sock, buf, sizeof(buf)-1, &header_size, &received_size);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
CHIAKI_LOGE(&session->log, "Failed to receive session request response\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue