Skip to content

Commit

Permalink
FS|libshell|Client: Fixed connecting to server's repository
Browse files Browse the repository at this point in the history
The client must wait after mounting the server's repository so that
the connection is fully formed and the remote folders have been
populated.
  • Loading branch information
skyjake committed Nov 4, 2017
1 parent bdd3ae2 commit a269c15
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 11 deletions.
6 changes: 1 addition & 5 deletions doomsday/apps/client/src/network/serverlink.cpp
Expand Up @@ -430,11 +430,7 @@ void ServerLink::connectToServerAndChangeGameAsync(shell::ServerInfo info)
}

// The server makes certain packages available for clients to download.
d->downloader.mountServerRepository(info);

// Wait async until remote files have been populated so we can decide if
// anything needs to be downloaded.
Folder::afterPopulation([this, joinProfile, info] ()
d->downloader.mountServerRepository(info, [this, joinProfile, info] (filesys::Link const *)
{
// Now we know all the files that the server will be providing.
// If we are missing any of the packages, download a copy from the server.
Expand Down
7 changes: 5 additions & 2 deletions doomsday/sdk/libshell/include/de/shell/packagedownloader.h
Expand Up @@ -21,6 +21,7 @@

#include <de/Range>
#include <de/String>
#include <de/filesys/Link>
#include "ServerInfo"

namespace de {
Expand All @@ -38,9 +39,11 @@ class LIBSHELL_PUBLIC PackageDownloader
/**
* Mount a server's remote file repository.
*
* @param serverInfo Server information.
* @param serverInfo Server information.
* @param afterConnected Callback to call when the repository is connected and ready for use.
*/
void mountServerRepository(ServerInfo const &serverInfo);
void mountServerRepository(ServerInfo const &serverInfo,
std::function<void (filesys::Link const *)> afterConnected);

void unmountServerRepository();

Expand Down
39 changes: 35 additions & 4 deletions doomsday/sdk/libshell/src/packagedownloader.cpp
Expand Up @@ -36,20 +36,40 @@ static String const PATH_REMOTE_PACKS = "/remote/packs";
static String const PATH_REMOTE_SERVER = "/remote/server"; // local folder for RemoteFeed

DENG2_PIMPL(PackageDownloader)
, DENG2_OBSERVES(filesys::RemoteFeedRelay, Status)
, DENG2_OBSERVES(Asset, StateChange)
, DENG2_OBSERVES(RemoteFile, Download)
, DENG2_OBSERVES(Deletable, Deletion)
{
String fileRepository;
std::function<void (filesys::Link const *)> afterConnected;
bool isCancelled = false;
dint64 totalBytes = 0;
int numDownloads = 0;
AssetGroup downloads;
QHash<IDownloadable *, Rangei64> downloadBytes;
std::function<void ()> postDownloadCallback;

Impl(Public *i) : Base(i)
{}
Impl(Public *i) : Base(i) {}

void remoteRepositoryStatusChanged(String const &address,
filesys::RemoteFeedRelay::Status) override
{
if (address == fileRepository)
{
auto *relay = &filesys::RemoteFeedRelay::get();
relay->audienceForStatus() -= this;

// Populate remote folders before notifying so everything is ready to go.
Folder::afterPopulation([this, relay] ()
{
if (afterConnected)
{
afterConnected(relay->repository(fileRepository));
}
});
}
}

void downloadFile(File &file)
{
Expand Down Expand Up @@ -240,17 +260,28 @@ bool PackageDownloader::isActive() const
return !d->downloads.isEmpty() && !d->downloads.isReady();
}

void PackageDownloader::mountServerRepository(shell::ServerInfo const &info)
void PackageDownloader::mountServerRepository(shell::ServerInfo const &info,
std::function<void (filesys::Link const *)> afterConnected)
{
// The remote repository feature was added in 2.1. Trying to send a RemoteFeed
// request to an older server would just result in us getting immediately
// disconnected.

if (info.version() > Version(2, 1, 0, 2484))
{
auto &relay = filesys::RemoteFeedRelay::get();

d->fileRepository = filesys::NativeLink::URL_SCHEME + info.address().asText();
d->isCancelled = false;
filesys::RemoteFeedRelay::get().addRepository(d->fileRepository, PATH_REMOTE_SERVER);
relay.addRepository(d->fileRepository, PATH_REMOTE_SERVER);

// Notify after repository is available.
d->afterConnected = afterConnected;
relay.audienceForStatus() += d;
}
else if (afterConnected)
{
afterConnected(nullptr);
}
}

Expand Down

0 comments on commit a269c15

Please sign in to comment.