Skip to content

Instantly share code, notes, and snippets.

@yaakov-h
Created February 1, 2014 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yaakov-h/8752161 to your computer and use it in GitHub Desktop.
Save yaakov-h/8752161 to your computer and use it in GitHub Desktop.
Proof of concept code for connecting to the Steam In-Home Streaming Remote Client control system.
#include <iostream>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <netinet/in.h>
#include <assert.h>
#include <unistd.h>
uint32_t remote_ip_addr = PUT YOUR REMOTE IP HERE AS AN INT. EG 192.168.0.4 is 0xc0A80004
uint16_t remote_port = PUT YOUR REMOTE PORT NUMBER HERE
uint8_t steam_psk[] = { PUT YOUR PSK HERE AS A BYTE ARRAY };
unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len)
{
printf("Got PSK identity hint \"%s\"\n", hint);
if (sizeof(steam_psk) > max_psk_len)
{
printf("Steam PSK is too long: %lu > %u\n", sizeof(steam_psk), max_psk_len);
return -1;
}
printf("Sending Steam Remote Client PSK...\n");
memcpy(psk, steam_psk, sizeof(steam_psk));
return sizeof(steam_psk);
}
struct steam_protocol_header
{
uint32_t uLength;
uint32_t uMagic;
};
struct steam_body_header
{
uint32_t eMsg;
};
const uint32_t kSteamProtocolMagic = 0x31305456; // 'VT01' big-endian
int main(int argc, const char * argv[])
{
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_CTX * sslContext = SSL_CTX_new(TLSv1_2_client_method());
SSL_CTX_set_psk_client_callback(sslContext, psk_client_callback);
int cipherList = SSL_CTX_set_cipher_list(sslContext, "PSK-AES128-CBC-SHA");
assert(cipherList != 0);
SSL * ssl = SSL_new(sslContext);
struct sockaddr_in in = {};
in.sin_addr.s_addr = htonl(remote_ip_addr);
in.sin_family = AF_INET;
in.sin_len = sizeof(in);
in.sin_port = htons(remote_port_num);
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
assert(sock >= 0);
SSL_set_fd(ssl, sock);
int connect = ::connect(sock, (sockaddr *)&in, in.sin_len);
assert(connect >= 0);
connect = SSL_connect(ssl);
if (connect < 0)
{
unsigned long err = ERR_get_error(); // SSL_get_error(ssl, connect);
printf("Error in SSL_connect: %lu - %s %s %s\n", err, ERR_lib_error_string(err), ERR_func_error_string(err), ERR_reason_error_string(err));
}
bool connected = true;
do
{
struct steam_protocol_header hdr = {};
int iRead = SSL_read(ssl, &hdr, sizeof(hdr));
if (iRead < sizeof(hdr))
{
connected = false;
close(sock);
fprintf(stderr, "Recieved only %u bytes, expected minimum of %lu\n", iRead, sizeof(hdr));
connected = false;
continue;
}
if (hdr.uMagic != kSteamProtocolMagic)
{
connected = false;
close(sock);
fprintf(stderr, "Expected magic %u but got magic %u\n", kSteamProtocolMagic, hdr.uMagic);
connected = false;
continue;
}
char * data = reinterpret_cast<char *>(malloc(hdr.uLength));
iRead = 0;
do
{
iRead += SSL_read(ssl, data + iRead, hdr.uLength - iRead);
// TODO: error handling on the -1 return case
} while (iRead < hdr.uLength);
struct steam_body_header * bodyHdr = reinterpret_cast<struct steam_body_header *>(data);
printf("Got message %u\n", bodyHdr->eMsg & ~0x80000000);
free(data);
} while (connected);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment