Skip to content

Commit

Permalink
Add raw TCP file transfer support
Browse files Browse the repository at this point in the history
  • Loading branch information
McCaulay committed Feb 28, 2023
1 parent 58d87eb commit cf2829b
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 46 deletions.
113 changes: 71 additions & 42 deletions src/downloader/Downloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,70 +7,98 @@ bool Downloader::download(const char* filepath, uint16_t port)
if (!server.listen(port))
return false;

// Show progress bar dialog
PS::Sce::MsgDialogProgressBar dialog = PS::Sce::MsgDialogProgressBar("Waiting for game file...");
dialog.open();
// Waiting for game file dialog
PS::Sce::MsgDialog::Initialize();
PS::Sce::MsgDialogUserMessage waitingDialog = PS::Sce::MsgDialogUserMessage("Waiting for game file...", PS::Sce::MsgDialog::ButtonType::NONE);
waitingDialog.open();

// Accept connection
PS::Debug.printf("Waiting for client connection...\n");
PS::TcpClient client = server.accept();

// Get magic
PS::Debug.printf("Waiting for magic...\n");
if (client.read<uint32_t>() != MAGIC)
return false;
// File download variables
size_t filesize = 0;
size_t offset = 0;
size_t headerSize = 0;

// Get filesize
PS::Debug.printf("Waiting for data size...\n");
size_t filesize = client.read<size_t>();
PS::Debug.printf("Download file of size: %llu\n", filesize);
// Check if file is sent with filesize
uint8_t magic[sizeof(uint32_t)];
client.read(magic, sizeof(uint32_t));
offset += sizeof(uint32_t);
if (*(uint32_t*)(magic) == MAGIC)
{
// Get filesize
filesize = client.read<size_t>();
offset += sizeof(size_t);
PS::Debug.printf("Download file of size: %llu\n", filesize);

headerSize = sizeof(uint32_t) + sizeof(size_t);
}

// Get file basename
const char* basename = PS::Filesystem::basename(filepath);
Downloader::setProgress(dialog, basename, 0, filesize);
// Close waiting for file dialog
waitingDialog.close();
PS::Sce::MsgDialog::Terminate();

// Show progress bar dialog
PS::Sce::MsgDialog::Initialize();
PS::Sce::MsgDialogProgressBar progressDialog = PS::Sce::MsgDialogProgressBar("Downloading game file...");
PS::Sce::MsgDialogUserMessage staticDialog = PS::Sce::MsgDialogUserMessage("Downloading game file...", PS::Sce::MsgDialog::ButtonType::NONE);;
if (filesize != 0)
{
progressDialog.open();
Downloader::setProgress(progressDialog, 0, filesize);
}
else
staticDialog.open();

// Write file to device
PS::Debug.printf("Opening %s\n", filepath);
int fd = PS::open(filepath, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
if (fd > 0)
{
// Write first 4 bytes if it was not the magic value
if (filesize == 0)
PS::writeAll(fd, magic, 4);

// Write file to disk from socket in chunks
uint32_t updateBar = 0;
char buffer[DOWNLOAD_CHUNK_SIZE];
for (uint64_t i = 0; i < filesize; i+= DOWNLOAD_CHUNK_SIZE)
while (true)
{
uint32_t readWriteSize = DOWNLOAD_CHUNK_SIZE;

// Set size for final read if we are at the end
if (i + readWriteSize > filesize)
readWriteSize = filesize % DOWNLOAD_CHUNK_SIZE;
size_t readCount = client.read(buffer, DOWNLOAD_CHUNK_SIZE);
offset += readCount;

size_t readCount = client.read(buffer, readWriteSize);
if (readCount != readWriteSize)
size_t writeCount = PS::writeAll(fd, buffer, readCount);
if (writeCount != readCount)
{
PS::Debug.printf("Failed to read from socket, read %llu, expected to read %llu\n", readCount, readWriteSize);
PS::notification("Failed to write file to disk!");
PS::Debug.printf("Failed to write file, wrote %llu, expected to write %llu\n", writeCount, readCount);
PS::close(fd);
client.disconnect();
server.disconnect();
dialog.close();
if (filesize != 0)
{
progressDialog.setValue(100);
progressDialog.close();
}
else
staticDialog.close();
PS::Sce::MsgDialog::Terminate();
return false;
}

size_t writeCount = PS::writeAll(fd, buffer, readWriteSize);
if (writeCount != readWriteSize)
// End of download
if (readCount != DOWNLOAD_CHUNK_SIZE)
{
PS::Debug.printf("Failed to write file, wrote %llu, expected to write %llu\n", writeCount, readWriteSize);
PS::close(fd);
client.disconnect();
server.disconnect();
dialog.close();
return false;
PS::Debug.printf("Downloaded %lu bytes\n", offset);
break;
}

// Update progress bar
if (updateBar == DOWNLOAD_BAR_UPDATE_FREQUENCY)
{
Downloader::setProgress(dialog, basename, i, filesize);
if (filesize != 0)
Downloader::setProgress(progressDialog, offset - headerSize, filesize);
updateBar = 0;
}
updateBar++;
Expand All @@ -82,22 +110,23 @@ bool Downloader::download(const char* filepath, uint16_t port)
PS::close(fd);
client.disconnect();
server.disconnect();
dialog.terminate();

// Validate filesize matches expected
size_t filesystemFilesize = PS::Filesystem::getFileSize(filepath);
if (filesystemFilesize != filesize)
if (filesize != 0)
{
PS::Debug.printf("Wrote a file which resulted in a different size to what was expected. %llu was wrote, however we expected to write %llu\n", filesystemFilesize, filesize);
return false;
progressDialog.setValue(100);
progressDialog.close();
}

else
staticDialog.close();
PS::Sce::MsgDialog::Terminate();

return true;
}

void Downloader::setProgress(PS::Sce::MsgDialogProgressBar dialog, const char* basename, size_t downloaded, size_t total)
void Downloader::setProgress(PS::Sce::MsgDialogProgressBar dialog, size_t downloaded, size_t total)
{
dialog.setMsg("Downloading %s...\n", basename);
if (total == 0)
return;

// Calculate percentage without float/double
uint64_t divident = downloaded * 100;
Expand Down
2 changes: 1 addition & 1 deletion src/downloader/Downloader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ class Downloader
public:
static bool download(const char* filepath, uint16_t port);
private:
static void setProgress(PS::Sce::MsgDialogProgressBar dialog, const char* basename, size_t downloaded, size_t total);
static void setProgress(PS::Sce::MsgDialogProgressBar dialog, size_t downloaded, size_t total);
};
5 changes: 2 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@ void main()
// Download ISO
if (!Downloader::download(filepath, SERVER_PORT))
{
PS::notification("Failed to download ISO");
PS::Debug.printf("Failed to download ISO\n");

// Disconnect from debug server
PS::Debug.disconnect();

// Restore corruption
PS::Breakout::restore();
return;
}
}
Expand Down Expand Up @@ -58,6 +56,7 @@ void main()
return;
}

PS::notification("Unexpected game code \"%s\"!", gameCode);
PS::Debug.printf("Unexpected game code (%s) length of %i, expecting %i\n", gameCode, PS2::strlen(gameCode), 10);

// Disconnect from debug server
Expand Down

0 comments on commit cf2829b

Please sign in to comment.