Use channels for decryption

This commit is contained in:
Xpl0itU 2023-07-23 12:49:37 +02:00
parent 5612a22027
commit 99887ad529
3 changed files with 51 additions and 26 deletions

View file

@ -148,6 +148,18 @@ struct FEntry {
uint16_t ContentID; uint16_t ContentID;
}; };
ProgressCallback progressCallback = NULL;
void set_progress_callback(ProgressCallback cb) {
progressCallback = cb;
}
void report_progress(int progress) {
if (progressCallback != NULL) {
progressCallback(progress);
}
}
static bool file_dump(const char *path, void *buf, size_t len) { static bool file_dump(const char *path, void *buf, size_t len) {
assert(buf != NULL); assert(buf != NULL);
assert(len != 0); assert(len != 0);
@ -346,7 +358,7 @@ out:
} }
#undef BLOCK_SIZE #undef BLOCK_SIZE
int cdecrypt_main(int argc, char **argv, int *progress) { int cdecrypt_main(int argc, char **argv) {
int r = EXIT_FAILURE; int r = EXIT_FAILURE;
char str[PATH_MAX], *tmd_path = NULL, *tik_path = NULL; char str[PATH_MAX], *tmd_path = NULL, *tik_path = NULL;
FILE *src = NULL; FILE *src = NULL;
@ -526,7 +538,7 @@ int cdecrypt_main(int argc, char **argv, int *progress) {
uint32_t level = 0; uint32_t level = 0;
for (uint32_t i = 1; i < entries; i++) { for (uint32_t i = 1; i < entries; i++) {
*progress = (i * 100) / entries; report_progress((i * 100) / entries);
if (level > 0) { if (level > 0) {
while ((level >= 1) && (l_entry[level - 1] == i)) while ((level >= 1) && (l_entry[level - 1] == i))
level--; level--;

View file

@ -1,3 +1,5 @@
#pragma once #pragma once
int cdecrypt_main(int argc, char **argv, int *progress); typedef void (*ProgressCallback)(int progress);
void set_progress_callback(ProgressCallback cb);
int cdecrypt_main(int argc, char **argv);

View file

@ -7,51 +7,62 @@ package wiiudownloader
#cgo LDFLAGS: -lcdecrypt #cgo LDFLAGS: -lcdecrypt
#include <cdecrypt.h> #include <cdecrypt.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h>
// Declare a separate C function that calls the Go function progressCallback
extern void callProgressCallback(int progress);
*/ */
import "C" import "C"
import ( import (
"fmt" "fmt"
"sync"
"time"
"unsafe" "unsafe"
) )
var ( //export callProgressCallback
wg sync.WaitGroup func callProgressCallback(progress C.int) {
decryptionDone = false progressChan <- int(progress)
decryptionError = false }
)
var progressChan = make(chan int)
func DecryptContents(path string, progress *ProgressWindow, deleteEncryptedContents bool) error { func DecryptContents(path string, progress *ProgressWindow, deleteEncryptedContents bool) error {
wg.Add(1) errorChan := make(chan error)
progressInt := 1 defer close(errorChan)
go runDecryption(path, &progressInt, deleteEncryptedContents)
go runDecryption(path, errorChan, deleteEncryptedContents)
progress.bar.SetText("Decrypting...") progress.bar.SetText("Decrypting...")
for !decryptionDone {
for progressInt := range progressChan {
progress.bar.SetFraction(float64(progressInt) / 100) progress.bar.SetFraction(float64(progressInt) / 100)
time.Sleep(500 * time.Millisecond)
} }
wg.Wait() if err := <-errorChan; err != nil {
return err
if decryptionError {
decryptionDone = false
decryptionError = false
return fmt.Errorf("decryption failed")
} }
return nil return nil
} }
func runDecryption(path string, progress *int, deleteEncryptedContents bool) { func runDecryption(path string, errorChan chan<- error, deleteEncryptedContents bool) {
defer wg.Done()
argv := make([]*C.char, 2) argv := make([]*C.char, 2)
argv[0] = C.CString("WiiUDownloader") argv[0] = C.CString("WiiUDownloader")
argv[1] = C.CString(path) argv[1] = C.CString(path)
if int(C.cdecrypt_main(2, (**C.char)(unsafe.Pointer(&argv[0])), (*C.int)(unsafe.Pointer(progress)))) != 0 { defer C.free(unsafe.Pointer(argv[0]))
decryptionError = true defer C.free(unsafe.Pointer(argv[1]))
// Register the C callback function with C
C.set_progress_callback(C.ProgressCallback(C.callProgressCallback))
if int(C.cdecrypt_main(2, (**C.char)(unsafe.Pointer(&argv[0])))) != 0 {
errorChan <- fmt.Errorf("decryption failed")
return
} }
if deleteEncryptedContents { if deleteEncryptedContents {
doDeleteEncryptedContents(path) doDeleteEncryptedContents(path)
} }
decryptionDone = true
close(progressChan) // Indicate the completion of the decryption process
errorChan <- nil
} }