mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-30 20:01:00 +00:00
http: Improve EBOOT.PBP handling.
At least when it works, we should use a better filename.
This commit is contained in:
parent
010da8080c
commit
2e5065a6f5
@ -120,81 +120,100 @@ bool RemoteISOFileSupported(const std::string &filename) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
static void RegisterDiscHandlers(http::Server *http, std::unordered_map<std::string, std::string> *paths) {
|
||||
for (std::string filename : g_Config.recentIsos) {
|
||||
static std::string RemotePathForRecent(const std::string &filename) {
|
||||
#ifdef _WIN32
|
||||
static const std::string sep = "\\/";
|
||||
static const std::string sep = "\\/";
|
||||
#else
|
||||
static const std::string sep = "/";
|
||||
static const std::string sep = "/";
|
||||
#endif
|
||||
size_t basepos = filename.find_last_of(sep);
|
||||
std::string basename = "/" + (basepos == filename.npos ? filename : filename.substr(basepos + 1));
|
||||
size_t basepos = filename.find_last_of(sep);
|
||||
std::string basename = "/" + (basepos == filename.npos ? filename : filename.substr(basepos + 1));
|
||||
|
||||
// Let's not serve directories, since they won't work. Only single files.
|
||||
// Maybe can do PBPs and other files later. Would be neat to stream virtual disc filesystems.
|
||||
if (RemoteISOFileSupported(basename)) {
|
||||
(*paths)[ReplaceAll(basename, " ", "%20")] = filename;
|
||||
}
|
||||
if (basename == "/EBOOT.PBP") {
|
||||
// Go up one more folder.
|
||||
size_t nextpos = filename.find_last_of(sep, basepos - 1);
|
||||
basename = "/" + (nextpos == filename.npos ? filename : filename.substr(nextpos + 1));
|
||||
}
|
||||
|
||||
auto handler = [paths](const http::Request &request) {
|
||||
std::string filename = (*paths)[request.resource()];
|
||||
s64 sz = File::GetFileSize(filename);
|
||||
// Let's not serve directories, since they won't work. Only single files.
|
||||
// Maybe can do PBPs and other files later. Would be neat to stream virtual disc filesystems.
|
||||
if (RemoteISOFileSupported(basename)) {
|
||||
return ReplaceAll(basename, " ", "%20");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string range;
|
||||
if (request.Method() == http::RequestHeader::HEAD) {
|
||||
request.WriteHttpResponseHeader("1.0", 200, sz, "application/octet-stream", "Accept-Ranges: bytes\r\n");
|
||||
} else if (request.GetHeader("range", &range)) {
|
||||
s64 begin = 0, last = 0;
|
||||
if (sscanf(range.c_str(), "bytes=%lld-%lld", &begin, &last) != 2) {
|
||||
request.WriteHttpResponseHeader("1.0", 400, -1, "text/plain");
|
||||
request.Out()->Push("Could not understand range request.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (begin < 0 || begin > last || last >= sz) {
|
||||
request.WriteHttpResponseHeader("1.0", 416, -1, "text/plain");
|
||||
request.Out()->Push("Range goes outside of file.");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = File::OpenCFile(filename, "rb");
|
||||
if (!fp || fseek(fp, begin, SEEK_SET) != 0) {
|
||||
request.WriteHttpResponseHeader("1.0", 500, -1, "text/plain");
|
||||
request.Out()->Push("File access failed.");
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s64 len = last - begin + 1;
|
||||
char contentRange[1024];
|
||||
sprintf(contentRange, "Content-Range: bytes %lld-%lld/%lld\r\n", begin, last, sz);
|
||||
request.WriteHttpResponseHeader("1.0", 206, len, "application/octet-stream", contentRange);
|
||||
|
||||
const size_t CHUNK_SIZE = 16 * 1024;
|
||||
char *buf = new char[CHUNK_SIZE];
|
||||
for (s64 pos = 0; pos < len; pos += CHUNK_SIZE) {
|
||||
s64 chunklen = std::min(len - pos, (s64)CHUNK_SIZE);
|
||||
if (fread(buf, chunklen, 1, fp) != 1)
|
||||
break;
|
||||
request.Out()->Push(buf, chunklen);
|
||||
}
|
||||
fclose(fp);
|
||||
delete [] buf;
|
||||
request.Out()->Flush();
|
||||
} else {
|
||||
request.WriteHttpResponseHeader("1.0", 418, -1, "text/plain");
|
||||
request.Out()->Push("This server only supports range requests.");
|
||||
static std::string LocalFromRemotePath(const std::string &path) {
|
||||
for (const std::string &filename : g_Config.recentIsos) {
|
||||
std::string basename = RemotePathForRecent(filename);
|
||||
if (basename == path) {
|
||||
return filename;
|
||||
}
|
||||
};
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
for (auto pair : *paths) {
|
||||
http->RegisterHandler(pair.first.c_str(), handler);
|
||||
static void DiscHandler(const http::Request &request) {
|
||||
std::string filename = LocalFromRemotePath(request.resource());
|
||||
s64 sz = File::GetFileSize(filename);
|
||||
|
||||
std::string range;
|
||||
if (request.Method() == http::RequestHeader::HEAD) {
|
||||
request.WriteHttpResponseHeader("1.0", 200, sz, "application/octet-stream", "Accept-Ranges: bytes\r\n");
|
||||
} else if (request.GetHeader("range", &range)) {
|
||||
s64 begin = 0, last = 0;
|
||||
if (sscanf(range.c_str(), "bytes=%lld-%lld", &begin, &last) != 2) {
|
||||
request.WriteHttpResponseHeader("1.0", 400, -1, "text/plain");
|
||||
request.Out()->Push("Could not understand range request.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (begin < 0 || begin > last || last >= sz) {
|
||||
request.WriteHttpResponseHeader("1.0", 416, -1, "text/plain");
|
||||
request.Out()->Push("Range goes outside of file.");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = File::OpenCFile(filename, "rb");
|
||||
if (!fp || fseek(fp, begin, SEEK_SET) != 0) {
|
||||
request.WriteHttpResponseHeader("1.0", 500, -1, "text/plain");
|
||||
request.Out()->Push("File access failed.");
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s64 len = last - begin + 1;
|
||||
char contentRange[1024];
|
||||
sprintf(contentRange, "Content-Range: bytes %lld-%lld/%lld\r\n", begin, last, sz);
|
||||
request.WriteHttpResponseHeader("1.0", 206, len, "application/octet-stream", contentRange);
|
||||
|
||||
const size_t CHUNK_SIZE = 16 * 1024;
|
||||
char *buf = new char[CHUNK_SIZE];
|
||||
for (s64 pos = 0; pos < len; pos += CHUNK_SIZE) {
|
||||
s64 chunklen = std::min(len - pos, (s64)CHUNK_SIZE);
|
||||
if (fread(buf, chunklen, 1, fp) != 1)
|
||||
break;
|
||||
request.Out()->Push(buf, chunklen);
|
||||
}
|
||||
fclose(fp);
|
||||
delete[] buf;
|
||||
request.Out()->Flush();
|
||||
} else {
|
||||
request.WriteHttpResponseHeader("1.0", 418, -1, "text/plain");
|
||||
request.Out()->Push("This server only supports range requests.");
|
||||
}
|
||||
}
|
||||
|
||||
static void RegisterDiscHandlers(http::Server *http) {
|
||||
for (const std::string &filename : g_Config.recentIsos) {
|
||||
std::string basename = RemotePathForRecent(filename);
|
||||
if (!basename.empty()) {
|
||||
http->RegisterHandler(basename.c_str(), &DiscHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,10 +221,9 @@ static void ExecuteWebServer() {
|
||||
setCurrentThreadName("HTTPServer");
|
||||
|
||||
auto http = new http::Server(new threading::NewThreadExecutor());
|
||||
std::unordered_map<std::string, std::string> discPaths;
|
||||
|
||||
if (serverFlags & (int)WebServerFlags::DISCS) {
|
||||
RegisterDiscHandlers(http, &discPaths);
|
||||
RegisterDiscHandlers(http);
|
||||
}
|
||||
if (serverFlags & (int)WebServerFlags::DEBUGGER) {
|
||||
http->RegisterHandler("/debugger", &HandleDebuggerRequest);
|
||||
|
Loading…
Reference in New Issue
Block a user