Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancel remote disc streaming connects faster #9478

Merged
merged 4 commits into from
Mar 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1175,16 +1175,20 @@ UI::EventReturn GameSettingsScreen::OnSysInfo(UI::EventParams &e) {

void DeveloperToolsScreen::CreateViews() {
using namespace UI;
root_ = new ScrollView(ORIENT_VERTICAL);
root_->SetTag("DevToolsSettings");
root_ = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
ScrollView *settingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
settingsScroll->SetTag("DevToolsSettings");
root_->Add(settingsScroll);

I18NCategory *di = GetI18NCategory("Dialog");
I18NCategory *dev = GetI18NCategory("Developer");
I18NCategory *gr = GetI18NCategory("Graphics");
I18NCategory *a = GetI18NCategory("Audio");
I18NCategory *sy = GetI18NCategory("System");

LinearLayout *list = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)));
AddStandardBack(root_);

LinearLayout *list = settingsScroll->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)));
list->SetSpacing(0);
list->Add(new ItemHeader(sy->T("General")));

Expand Down Expand Up @@ -1227,8 +1231,6 @@ void DeveloperToolsScreen::CreateViews() {
#if !defined(MOBILE_DEVICE)
list->Add(new Choice(dev->T("Create/Open textures.ini file for current game")))->OnClick.Handle(this, &DeveloperToolsScreen::OnOpenTexturesIniFile);
#endif
list->Add(new ItemHeader(""));
list->Add(new Choice(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
}

void DeveloperToolsScreen::onFinish(DialogResult result) {
Expand Down
89 changes: 58 additions & 31 deletions UI/RemoteISOScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static std::mutex serverStatusLock;
static std::condition_variable serverStatusCond;

static bool scanCancelled = false;
static bool scanAborted = false;

static void UpdateStatus(ServerStatus s) {
std::lock_guard<std::mutex> guard(serverStatusLock);
Expand All @@ -69,7 +70,7 @@ static void RegisterServer(int port) {
Buffer theVoid;

if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) {
if (http.Connect()) {
if (http.Connect(2, 20.0, &scanCancelled)) {
char resource[1024] = {};
std::string ip = fd_util::GetLocalIP(http.sock());
snprintf(resource, sizeof(resource) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port);
Expand Down Expand Up @@ -190,22 +191,34 @@ static bool FindServer(std::string &resultHost, int &resultPort) {
Buffer result;
int code = 500;

auto TryServer = [&](const std::string &host, int port) {
// Don't wait as long for a connect - we need a good connection for smooth streaming anyway.
// This way if it's down, we'll find the right one faster.
if (http.Resolve(host.c_str(), port) && http.Connect(1, 10.0, &scanCancelled)) {
http.Disconnect();
resultHost = host;
resultPort = port;
return true;
}

return false;
};

// Try last server first, if it is set
if (g_Config.iLastRemoteISOPort && g_Config.sLastRemoteISOServer != "" && http.Resolve(g_Config.sLastRemoteISOServer.c_str(), g_Config.iLastRemoteISOPort) && http.Connect()) {
http.Disconnect();
resultHost = g_Config.sLastRemoteISOServer;
resultPort = g_Config.iLastRemoteISOPort;
return true;
if (g_Config.iLastRemoteISOPort && g_Config.sLastRemoteISOServer != "") {
if (TryServer(g_Config.sLastRemoteISOServer.c_str(), g_Config.iLastRemoteISOPort)) {
return true;
}
}

//don't scan if in manual mode
if (g_Config.bRemoteISOManual) {
// Don't scan if in manual mode.
if (g_Config.bRemoteISOManual || scanCancelled) {
return false;
}

// Start by requesting a list of recent local ips for this network.
if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) {
if (http.Connect()) {
if (http.Connect(2, 20.0, &scanCancelled)) {
code = http.GET("/match/list", &result);
http.Disconnect();
}
Expand All @@ -230,18 +243,15 @@ static bool FindServer(std::string &resultHost, int &resultPort) {

std::vector<std::string> servers;
const json_value *entry = entries->first_child;
while (entry) {
while (entry && !scanCancelled) {
const char *host = entry->getString("ip", "");
int port = entry->getInt("p", 0);

char url[1024] = {};
snprintf(url, sizeof(url), "http://%s:%d", host, port);
servers.push_back(url);

if (http.Resolve(host, port) && http.Connect()) {
http.Disconnect();
resultHost = host;
resultPort = port;
if (TryServer(host, port)) {
return true;
}

Expand Down Expand Up @@ -271,7 +281,7 @@ static bool LoadGameList(const std::string &host, int port, std::vector<std::str

// Start by requesting the list of games from the server.
if (http.Resolve(host.c_str(), port)) {
if (http.Connect()) {
if (http.Connect(2, 20.0, &scanCancelled)) {
code = http.GET(subdir.c_str(), &result,responseHeaders);
http.Disconnect();
}
Expand Down Expand Up @@ -365,7 +375,7 @@ void RemoteISOScreen::CreateViews() {

Margins actionMenuMargins(0, 20, 15, 0);
Margins contentMargins(0, 20, 5, 5);
ViewGroup *leftColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, FILL_PARENT, 0.4f, contentMargins));
ViewGroup *leftColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 0.4f, contentMargins));
LinearLayout *leftColumnItems = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(WRAP_CONTENT, FILL_PARENT));
ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins));
LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL);
Expand All @@ -390,12 +400,12 @@ void RemoteISOScreen::CreateViews() {
Choice *settingsChoice = new Choice(sy->T("Settings"));
rightColumnItems->Add(settingsChoice)->OnClick.Handle(this, &RemoteISOScreen::HandleSettings);

rightColumnItems->Add(new Spacer(25.0));
rightColumnItems->Add(new Choice(di->T("Back"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);

root_ = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
root_->Add(leftColumn);
root_->Add(rightColumn);
LinearLayout *beforeBack = new LinearLayout(ORIENT_HORIZONTAL, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT));
beforeBack->Add(leftColumn);
beforeBack->Add(rightColumn);
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
root_->Add(beforeBack);
root_->Add(new Choice(di->T("Back"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);

leftColumn->Add(leftColumnItems);
rightColumn->Add(rightColumnItems);
Expand Down Expand Up @@ -441,6 +451,7 @@ UI::EventReturn RemoteISOScreen::HandleSettings(UI::EventParams &e) {

RemoteISOConnectScreen::RemoteISOConnectScreen() : status_(ScanStatus::SCANNING), nextRetry_(0.0) {
scanCancelled = false;
scanAborted = false;

scanThread_ = new std::thread([](RemoteISOConnectScreen *thiz) {
thiz->ExecuteScan();
Expand All @@ -455,6 +466,7 @@ RemoteISOConnectScreen::~RemoteISOConnectScreen() {
sleep_ms(1);
if (--maxWait < 0) {
// If it does ever wake up, it may crash... but better than hanging?
scanAborted = true;
break;
}
}
Expand All @@ -473,8 +485,6 @@ void RemoteISOConnectScreen::CreateViews() {

statusView_ = leftColumnItems->Add(new TextView(sy->T("RemoteISOScanning", "Scanning... click Share Games on your desktop"), new LinearLayoutParams(Margins(12, 5, 0, 5))));

// TODO: Here would be a good place for manual entry.

rightColumnItems->SetSpacing(0.0f);
rightColumnItems->Add(new Choice(sy->T("Cancel"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);

Expand Down Expand Up @@ -536,7 +546,7 @@ void RemoteISOConnectScreen::update() {

void RemoteISOConnectScreen::ExecuteScan() {
FindServer(host_, port_);
if (scanCancelled) {
if (scanAborted) {
return;
}

Expand All @@ -551,7 +561,7 @@ ScanStatus RemoteISOConnectScreen::GetStatus() {

void RemoteISOConnectScreen::ExecuteLoad() {
bool result = LoadGameList(host_, port_, games_);
if (scanCancelled) {
if (scanAborted) {
return;
}

Expand Down Expand Up @@ -639,13 +649,27 @@ void RemoteISOBrowseScreen::CreateViews() {
upgradeBar_ = 0;
}

RemoteISOSettingsScreen::RemoteISOSettingsScreen() {
serverRunning_ = RetrieveStatus() != ServerStatus::STOPPED;;
}

void RemoteISOSettingsScreen::update() {
UIDialogScreenWithBackground::update();

bool nowRunning = RetrieveStatus() != ServerStatus::STOPPED;
if (serverRunning_ != nowRunning) {
RecreateViews();
}
serverRunning_ = nowRunning;
}

void RemoteISOSettingsScreen::CreateViews() {
I18NCategory *di = GetI18NCategory("Dialog");
I18NCategory *n = GetI18NCategory("Networking");
I18NCategory *ms = GetI18NCategory("MainSettings");

ViewGroup *remoteisoSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
remoteisoSettingsScroll->SetTag("GameSettingsNetworking");
ViewGroup *remoteisoSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
remoteisoSettingsScroll->SetTag("RemoteISOSettings");
LinearLayout *remoteisoSettings = new LinearLayout(ORIENT_VERTICAL);
remoteisoSettings->SetSpacing(0);
remoteisoSettingsScroll->Add(remoteisoSettings);
Expand All @@ -659,12 +683,15 @@ void RemoteISOSettingsScreen::CreateViews() {
PopupTextInputChoice *remoteSubdir = remoteisoSettings->Add(new PopupTextInputChoice(&g_Config.sRemoteISOSubdir, n->T("Remote Subdirectory"), "", 255, screenManager()));
remoteSubdir->SetEnabledPtr(&g_Config.bRemoteISOManual);
remoteSubdir->OnChange.Handle(this, &RemoteISOSettingsScreen::OnChangeRemoteISOSubdir);
remoteisoSettings->Add(new PopupSliderChoice(&g_Config.iRemoteISOPort, 0, 65535, n->T("Local Server Port", "Local Server Port"), 100, screenManager()));

PopupSliderChoice *portChoice = new PopupSliderChoice(&g_Config.iRemoteISOPort, 0, 65535, n->T("Local Server Port", "Local Server Port"), 100, screenManager());
remoteisoSettings->Add(portChoice);
portChoice->SetDisabledPtr(&serverRunning_);
remoteisoSettings->Add(new Spacer(25.0));
remoteisoSettings->Add(new Choice(di->T("Back"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);

root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
root_->Add(remoteisoSettings);
root_->Add(remoteisoSettingsScroll);
AddStandardBack(root_);
}

UI::EventReturn RemoteISOSettingsScreen::OnChangeRemoteISOSubdir(UI::EventParams &e) {
Expand Down
5 changes: 4 additions & 1 deletion UI/RemoteISOScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,15 @@ class RemoteISOBrowseScreen : public MainScreen {
std::vector<std::string> games_;
};

class RemoteISOSettingsScreen : public UIScreenWithBackground {
class RemoteISOSettingsScreen : public UIDialogScreenWithBackground {
public:
RemoteISOSettingsScreen();

protected:
void update() override;
void CreateViews() override;

UI::EventReturn OnChangeRemoteISOSubdir(UI::EventParams &e);

bool serverRunning_ = false;
};
31 changes: 26 additions & 5 deletions ext/native/net/http_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ bool Connection::Resolve(const char *host, int port) {
return true;
}

bool Connection::Connect(int maxTries, double timeout) {
bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) {
if (port_ <= 0) {
ELOG("Bad port");
return false;
Expand Down Expand Up @@ -106,10 +106,26 @@ bool Connection::Connect(int maxTries, double timeout) {
}
}

struct timeval tv;
tv.tv_sec = floor(timeout);
tv.tv_usec = (timeout - floor(timeout)) * 1000000.0;
if (select(maxfd, NULL, &fds, NULL, &tv) > 0) {
int selectResult = 0;
long timeoutHalfSeconds = floor(2 * timeout);
while (timeoutHalfSeconds >= 0 && selectResult == 0) {
struct timeval tv;
tv.tv_sec = 0;
if (timeoutHalfSeconds > 0) {
// Wait up to 0.5 seconds between cancel checks.
tv.tv_usec = 500000;
} else {
// Wait the remaining <= 0.5 seconds. Possibly 0, but that's okay.
tv.tv_usec = (timeout - floor(2 * timeout) / 2) * 1000000.0;
}
--timeoutHalfSeconds;

selectResult = select(maxfd, nullptr, &fds, nullptr, &tv);
if (cancelConnect && *cancelConnect) {
break;
}
}
if (selectResult > 0) {
// Something connected. Pick the first one that did (if multiple.)
for (int sock : sockets) {
if ((intptr_t)sock_ == -1 && FD_ISSET(sock, &fds)) {
Expand All @@ -123,6 +139,11 @@ bool Connection::Connect(int maxTries, double timeout) {
// Great, now we're good to go.
return true;
}

if (cancelConnect && *cancelConnect) {
break;
}

sleep_ms(1);
}

Expand Down
4 changes: 2 additions & 2 deletions ext/native/net/http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Connection {
// Inits the sockaddr_in.
bool Resolve(const char *host, int port);

bool Connect(int maxTries = 2, double timeout = 20.0f);
bool Connect(int maxTries = 2, double timeout = 20.0f, bool *cancelConnect = nullptr);
void Disconnect();

// Only to be used for bring-up and debugging.
Expand Down Expand Up @@ -167,4 +167,4 @@ class Downloader {
std::vector<std::shared_ptr<Download>> downloads_;
};

} // http
} // http