diff --git a/main.cpp b/main.cpp index 0235d84..522cf68 100644 --- a/main.cpp +++ b/main.cpp @@ -10,6 +10,8 @@ #include "ppapi/cpp/input_event.h" #include +#include +#include // Requests the NaCl module to connection to the server specified after the : #define MSG_START_REQUEST "startRequest" @@ -162,6 +164,8 @@ void MoonlightInstance::HandleMessage(const pp::Var& var_message) { MakeCert(callbackId, params); } else if (strcmp(method.c_str(), "pair") == 0) { HandlePair(callbackId, params); + } else if (strcmp(method.c_str(), "STUN") == 0) { + HandleSTUN(callbackId, params); } else { pp::Var response("Unhandled message received: " + method); PostMessage(response); @@ -277,6 +281,29 @@ void MoonlightInstance::PairCallback(int32_t /*result*/, int32_t callbackId, pp: PostMessage(ret); } +void MoonlightInstance::HandleSTUN(int32_t callbackId, pp::VarArray args) { + m_HttpThreadPool[m_HttpThreadPoolSequence++ % HTTP_HANDLER_THREADS]->message_loop().PostWork( + m_CallbackFactory.NewCallback(&MoonlightInstance::STUNCallback, callbackId, args)); +} + +void MoonlightInstance::STUNCallback(int32_t /*result*/, int32_t callbackId, pp::VarArray args) { + unsigned int wanAddr; + char addrStr[128] = {}; + + pp::VarDictionary ret; + ret.Set("callbackId", pp::Var(callbackId)); + ret.Set("type", pp::Var("resolve")); + + if (LiFindExternalAddressIP4("stun.stunprotocol.org", 3478, &wanAddr) == 0) { + inet_ntop(AF_INET, &wanAddr, addrStr, sizeof(addrStr)); + ret.Set("ret", pp::Var(addrStr)); + } else { + ret.Set("ret", pp::Var()); + } + + PostMessage(ret); +} + bool MoonlightInstance::Init(uint32_t argc, const char* argn[], const char* argv[]) { diff --git a/moonlight.hpp b/moonlight.hpp index 4f43413..7b311bc 100644 --- a/moonlight.hpp +++ b/moonlight.hpp @@ -97,7 +97,9 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { void HandleStartStream(int32_t callbackId, pp::VarArray args); void HandleStopStream(int32_t callbackId, pp::VarArray args); void HandleOpenURL(int32_t callbackId, pp::VarArray args); + void HandleSTUN(int32_t callbackId, pp::VarArray args); void PairCallback(int32_t /*result*/, int32_t callbackId, pp::VarArray args); + void STUNCallback(int32_t /*result*/, int32_t callbackId, pp::VarArray args); bool HandleInputEvent(const pp::InputEvent& event); void ReportMouseMovement(); diff --git a/static/js/index.js b/static/js/index.js index 6d6c649..43a8c45 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -107,6 +107,7 @@ function restoreUiAfterNaClLoad() { if (hosts[returneMdnsDiscoveredHost.serverUid] != null) { // if we're seeing a host we've already seen before, update it for the current local IP. hosts[returneMdnsDiscoveredHost.serverUid].address = returneMdnsDiscoveredHost.address; + hosts[returneMdnsDiscoveredHost.serverUid].updateExternalAddressIP4(); } else { // Host must be in the grid before starting background polling addHostToGrid(returneMdnsDiscoveredHost, true); @@ -405,6 +406,9 @@ function addHostToGrid(host, ismDNSDiscovered) { } $('#host-grid').append(outerDiv); hosts[host.serverUid] = host; + if (ismDNSDiscovered) { + hosts[host.serverUid].updateExternalAddressIP4(); + } } function removeClicked(host) { diff --git a/static/js/utils.js b/static/js/utils.js index 9a0ef2a..ee73f51 100644 --- a/static/js/utils.js +++ b/static/js/utils.js @@ -244,7 +244,14 @@ NvHTTP.prototype = { this.serverMajorVersion = parseInt(this.appVersion.substring(0, 1), 10); this.serverUid = $root.find('uniqueid').text().trim(); this.hostname = $root.find('hostname').text().trim(); - this.externalIP = $root.find('ExternalIP').text().trim(); + + var externIP = $root.find('ExternalIP').text().trim(); + if (externIP) { + // New versions of GFE don't have this field, so don't overwrite + // the one we found via STUN + this.externalIP = externIP; + } + try { // these aren't critical for functionality, and don't necessarily exist in older GFE versions. this.GfeVersion = $root.find('GfeVersion').text().trim(); this.gputype = $root.find('gputype').text().trim(); @@ -439,6 +446,18 @@ NvHTTP.prototype = { .then(this.refreshServerInfo()); }, + updateExternalAddressIP4: function() { + console.log('%c[utils.js, updateExternalAddressIP4]', 'color: gray;', 'Finding external IPv4 address for ' + this.hostname); + return sendMessage('STUN').then(function(addr) { + if (addr) { + this.externalIP = addr + console.log('%c[utils.js, updateExternalAddressIP4]', 'color: gray;', 'Found external IPv4 address: ' + this.hostname + ' -> ' + this.externalIP); + } else { + console.log('%c[utils.js, updateExternalAddressIP4]', 'color: gray;', 'External IPv4 address lookup failed'); + } + }.bind(this)) + }, + pair: function(randomNumber) { return this.refreshServerInfo().then(function() { if (this.paired)