Created
February 1, 2014 13:06
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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