2018-01-26 10:36:14 +00:00
|
|
|
/*
|
|
|
|
VitaShell
|
|
|
|
Copyright (C) 2015-2018, TheFloW
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "init.h"
|
|
|
|
#include "theme.h"
|
|
|
|
#include "language.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "adhoc_dialog.h"
|
2018-01-27 14:28:51 +00:00
|
|
|
#include "message_dialog.h"
|
2018-01-26 10:36:14 +00:00
|
|
|
#include "uncommon_dialog.h"
|
2018-01-27 14:28:51 +00:00
|
|
|
#include "io_process.h"
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
#define SHARE_MAGIC 0x574F4C46
|
|
|
|
#define SHARE_TYPE_FOLDER 0
|
|
|
|
#define SHARE_TYPE_FILE 1
|
|
|
|
|
|
|
|
// 700 KB/s
|
|
|
|
#define SOCKET_BUFSIZE 128 * 1024
|
|
|
|
#define SHARE_SIZE 4096
|
|
|
|
#define RECEIVE_WAIT 100 * 1000
|
|
|
|
|
|
|
|
#define PEERLIST_MAX 4
|
2018-01-26 10:36:14 +00:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int status;
|
2018-01-27 14:28:51 +00:00
|
|
|
int result;
|
|
|
|
int sel;
|
2018-01-26 10:36:14 +00:00
|
|
|
float x;
|
|
|
|
float y;
|
|
|
|
float width;
|
|
|
|
float height;
|
|
|
|
float scale;
|
|
|
|
} AdhocDialog;
|
|
|
|
|
|
|
|
static AdhocDialog adhoc_dialog;
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
static SceNetAdhocctlPeerInfo peer_list[PEERLIST_MAX];
|
|
|
|
static int peer_count = 0;
|
|
|
|
|
|
|
|
static SceNetAdhocctlPeerInfo server_peer_info;
|
|
|
|
static SceNetEtherAddr client_addr, server_addr;
|
|
|
|
static int client_socket = -1, server_socket = -1;
|
|
|
|
static SceUID client_waiting_thid = -1;
|
|
|
|
static int server_request_result = 0;
|
|
|
|
static char client_response[4];
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int magic;
|
|
|
|
int type;
|
|
|
|
size_t path_len;
|
|
|
|
uint64_t file_size;
|
|
|
|
} ShareInfo;
|
|
|
|
|
|
|
|
int adhocSend(int socket, const void *buf, int size) {
|
|
|
|
return sceNetAdhocPtpSend(socket, buf, &size, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int adhocRecv(int socket, void *buf, int *size) {
|
|
|
|
return sceNetAdhocPtpRecv(socket, buf, size, 0, SCE_NET_ADHOC_F_NONBLOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
int sendFile(const char *src_path, FileProcessParam *param) {
|
|
|
|
SceUID fdsrc = sceIoOpen(src_path, SCE_O_RDONLY, 0);
|
|
|
|
if (fdsrc < 0)
|
|
|
|
return fdsrc;
|
|
|
|
|
|
|
|
SceOff size = sceIoLseek(fdsrc, 0, SCE_SEEK_END);
|
|
|
|
sceIoLseek(fdsrc, 0, SCE_SEEK_SET);
|
|
|
|
|
|
|
|
// Send info
|
|
|
|
ShareInfo info;
|
|
|
|
info.magic = SHARE_MAGIC;
|
|
|
|
info.type = SHARE_TYPE_FILE;
|
|
|
|
info.path_len = strlen(src_path);
|
|
|
|
info.file_size = size;
|
|
|
|
int ret = adhocSend(client_socket, &info, sizeof(ShareInfo));
|
|
|
|
if (ret < 0) {
|
|
|
|
sceIoDclose(fdsrc);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send path
|
|
|
|
ret = adhocSend(client_socket, src_path, info.path_len);
|
|
|
|
if (ret < 0) {
|
|
|
|
sceIoDclose(fdsrc);
|
|
|
|
return ret;
|
|
|
|
}
|
2018-01-26 10:36:14 +00:00
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
void *buf = memalign(4096, SHARE_SIZE);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int read = sceIoRead(fdsrc, buf, SHARE_SIZE);
|
|
|
|
|
|
|
|
if (read < 0) {
|
|
|
|
free(buf);
|
|
|
|
sceIoClose(fdsrc);
|
|
|
|
return read;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
int sended = adhocSend(client_socket, buf, read);
|
|
|
|
if (sended < 0) {
|
|
|
|
free(buf);
|
|
|
|
sceIoClose(fdsrc);
|
|
|
|
return sended;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param) {
|
|
|
|
if (param->value)
|
|
|
|
(*param->value) += read;
|
|
|
|
|
|
|
|
if (param->SetProgress)
|
|
|
|
param->SetProgress(param->value ? *param->value : 0, param->max);
|
|
|
|
|
|
|
|
if (param->cancelHandler && param->cancelHandler()) {
|
|
|
|
free(buf);
|
|
|
|
sceIoClose(fdsrc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
sceIoClose(fdsrc);
|
|
|
|
|
|
|
|
return 1;
|
2018-01-26 10:36:14 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
int sendPath(const char *src_path, FileProcessParam *param) {
|
|
|
|
SceUID dfd = sceIoDopen(src_path);
|
|
|
|
if (dfd >= 0) {
|
|
|
|
// Send info
|
|
|
|
ShareInfo info;
|
|
|
|
info.magic = SHARE_MAGIC;
|
|
|
|
info.type = SHARE_TYPE_FOLDER;
|
|
|
|
info.path_len = strlen(src_path);
|
|
|
|
info.file_size = 0;
|
|
|
|
int ret = adhocSend(client_socket, &info, sizeof(ShareInfo));
|
|
|
|
if (ret < 0) {
|
|
|
|
sceIoDclose(dfd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send path
|
|
|
|
ret = adhocSend(client_socket, src_path, info.path_len);
|
|
|
|
if (ret < 0) {
|
|
|
|
sceIoDclose(dfd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param) {
|
|
|
|
if (param->value)
|
|
|
|
(*param->value) += DIRECTORY_SIZE;
|
|
|
|
|
|
|
|
if (param->SetProgress)
|
|
|
|
param->SetProgress(param->value ? *param->value : 0, param->max);
|
|
|
|
|
|
|
|
if (param->cancelHandler && param->cancelHandler()) {
|
|
|
|
sceIoDclose(dfd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
SceIoDirent dir;
|
|
|
|
memset(&dir, 0, sizeof(SceIoDirent));
|
|
|
|
|
|
|
|
res = sceIoDread(dfd, &dir);
|
|
|
|
if (res > 0) {
|
|
|
|
char *new_src_path = malloc(strlen(src_path) + strlen(dir.d_name) + 2);
|
2018-08-27 09:56:01 +00:00
|
|
|
snprintf(new_src_path, MAX_PATH_LENGTH, "%s%s%s", src_path, hasEndSlash(src_path) ? "" : "/", dir.d_name);
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (SCE_S_ISDIR(dir.d_stat.st_mode)) {
|
|
|
|
ret = sendPath(new_src_path, param);
|
|
|
|
} else {
|
|
|
|
ret = sendFile(new_src_path, param);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(new_src_path);
|
|
|
|
|
|
|
|
if (ret <= 0) {
|
|
|
|
sceIoDclose(dfd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (res > 0);
|
|
|
|
|
|
|
|
sceIoDclose(dfd);
|
|
|
|
} else {
|
|
|
|
return sendFile(src_path, param);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int send_thread(SceSize args_size, SendArguments *args) {
|
|
|
|
int res;
|
|
|
|
SceUID thid = -1;
|
|
|
|
|
|
|
|
// Lock power timers
|
2018-01-27 21:37:09 +00:00
|
|
|
powerLock();
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
// Set progress to 0%
|
|
|
|
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
|
|
|
|
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
|
|
|
|
|
|
|
|
FileListEntry *file_entry = fileListGetNthEntry(args->file_list, args->index);
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
FileListEntry *head = NULL;
|
|
|
|
FileListEntry *mark_entry_one = NULL;
|
|
|
|
|
|
|
|
if (fileListFindEntry(args->mark_list, file_entry->name)) { // On marked entry
|
|
|
|
count = args->mark_list->length;
|
|
|
|
head = args->mark_list->head;
|
|
|
|
} else {
|
|
|
|
count = 1;
|
|
|
|
mark_entry_one = fileListCopyEntry(file_entry);
|
|
|
|
head = mark_entry_one;
|
|
|
|
}
|
|
|
|
|
|
|
|
char path[MAX_PATH_LENGTH];
|
|
|
|
FileListEntry *mark_entry = NULL;
|
|
|
|
|
|
|
|
// Get paths info
|
|
|
|
uint64_t size = 0;
|
|
|
|
uint32_t folders = 0, files = 0;
|
|
|
|
|
|
|
|
mark_entry = head;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
2018-08-27 09:56:01 +00:00
|
|
|
snprintf(path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, mark_entry->name);
|
2018-01-27 14:28:51 +00:00
|
|
|
getPathInfo(path, &size, &folders, &files, NULL);
|
|
|
|
mark_entry = mark_entry->next;
|
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
// Send total size and path length of cwd
|
|
|
|
ShareInfo info;
|
|
|
|
info.magic = SHARE_MAGIC;
|
|
|
|
info.path_len = strlen(args->file_list->path);
|
|
|
|
info.file_size = size + folders * DIRECTORY_SIZE;
|
|
|
|
res = adhocSend(client_socket, &info, sizeof(ShareInfo));
|
2018-01-27 14:28:51 +00:00
|
|
|
if (res < 0) {
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update thread
|
2018-01-27 21:37:09 +00:00
|
|
|
thid = createStartUpdateThread(size + folders * DIRECTORY_SIZE, 1);
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
// Send process
|
|
|
|
uint64_t value = 0;
|
|
|
|
|
|
|
|
mark_entry = head;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
2018-08-27 09:56:01 +00:00
|
|
|
snprintf(path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, mark_entry->name);
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
FileProcessParam param;
|
|
|
|
param.value = &value;
|
|
|
|
param.max = folders + files;
|
|
|
|
param.SetProgress = SetProgress;
|
|
|
|
param.cancelHandler = cancelHandler;
|
2018-01-28 10:28:02 +00:00
|
|
|
res = sendPath(path, ¶m);
|
2018-01-27 14:28:51 +00:00
|
|
|
if (res <= 0) {
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mark_entry = mark_entry->next;
|
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
// In case server finished earlier
|
|
|
|
while (1) {
|
|
|
|
// Cancel
|
|
|
|
if (cancelHandler()) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = 0;
|
|
|
|
goto CANCELED;
|
2018-01-27 21:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t sync;
|
|
|
|
int len = sizeof(uint32_t);
|
2018-01-28 10:28:02 +00:00
|
|
|
res = adhocRecv(client_socket, &sync, &len);
|
2018-01-27 21:37:09 +00:00
|
|
|
if (res < 0 && res != SCE_ERROR_NET_ADHOC_WOULD_BLOCK) {
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 21:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sceKernelDelayThread(RECEIVE_WAIT);
|
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
// Set progress to 100%
|
|
|
|
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
|
|
|
|
sceKernelDelayThread(COUNTUP_WAIT);
|
|
|
|
|
|
|
|
// Close
|
|
|
|
sceMsgDialogClose();
|
|
|
|
|
|
|
|
setDialogStep(DIALOG_STEP_ADHOC_SENDED);
|
2018-01-28 10:28:02 +00:00
|
|
|
goto EXIT;
|
|
|
|
|
|
|
|
CANCELED:
|
|
|
|
closeWaitDialog();
|
|
|
|
setDialogStep(DIALOG_STEP_CANCELED);
|
|
|
|
errorDialog(res);
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
EXIT:
|
|
|
|
if (mark_entry_one)
|
|
|
|
free(mark_entry_one);
|
|
|
|
|
|
|
|
if (thid >= 0)
|
|
|
|
sceKernelWaitThreadEnd(thid, NULL, NULL);
|
|
|
|
|
|
|
|
// Unlock power timers
|
2018-01-27 21:37:09 +00:00
|
|
|
powerUnlock();
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
// Close sockets and disconnect
|
|
|
|
adhocCloseSockets();
|
|
|
|
sceNetCtlAdhocDisconnect();
|
2018-01-27 21:37:09 +00:00
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
return sceKernelExitDeleteThread(0);
|
2018-01-26 10:36:14 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
int receive_thread(SceSize args_size, ReceiveArguments *args) {
|
2018-01-28 10:28:02 +00:00
|
|
|
int res;
|
2018-01-27 14:28:51 +00:00
|
|
|
SceUID thid = -1;
|
|
|
|
uint64_t timeout;
|
|
|
|
|
|
|
|
// Lock power timers
|
2018-01-27 21:37:09 +00:00
|
|
|
powerLock();
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
// Set progress to 0%
|
|
|
|
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
|
|
|
|
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
// Receive total size and and path length of cwd
|
|
|
|
ShareInfo server_info;
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
// Cancel
|
|
|
|
if (cancelHandler()) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = 0;
|
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
int len = sizeof(ShareInfo);
|
2018-01-28 10:28:02 +00:00
|
|
|
res = adhocRecv(server_socket, &server_info, &len);
|
2018-01-27 14:28:51 +00:00
|
|
|
if (res < 0 && res != SCE_ERROR_NET_ADHOC_WOULD_BLOCK) {
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res == 0) {
|
2018-01-27 21:37:09 +00:00
|
|
|
// Wrong magic
|
|
|
|
if (server_info.magic != SHARE_MAGIC || server_info.path_len >= MAX_PATH_LENGTH) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = -1;
|
|
|
|
goto CANCELED;
|
2018-01-27 21:37:09 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sceKernelDelayThread(RECEIVE_WAIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update thread
|
2018-01-27 21:37:09 +00:00
|
|
|
thid = createStartUpdateThread(server_info.file_size, 1);
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
// Receive process
|
|
|
|
uint64_t value = 0;
|
2018-01-27 21:37:09 +00:00
|
|
|
while (value < server_info.file_size) {
|
2018-01-27 14:28:51 +00:00
|
|
|
ShareInfo info;
|
2018-01-27 21:37:09 +00:00
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
char path[MAX_PATH_LENGTH];
|
2018-01-27 21:37:09 +00:00
|
|
|
memset(path, 0, sizeof(path));
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
// Receive share info
|
|
|
|
while (1) {
|
|
|
|
// Cancel
|
|
|
|
if (cancelHandler()) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = 0;
|
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int len = sizeof(ShareInfo);
|
2018-01-28 10:28:02 +00:00
|
|
|
res = adhocRecv(server_socket, &info, &len);
|
2018-01-27 14:28:51 +00:00
|
|
|
if (res < 0 && res != SCE_ERROR_NET_ADHOC_WOULD_BLOCK) {
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
// Wrong magic
|
|
|
|
if (info.magic != SHARE_MAGIC || info.path_len >= MAX_PATH_LENGTH) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = -1;
|
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sceKernelDelayThread(RECEIVE_WAIT);
|
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
// Receive path
|
2018-01-27 14:28:51 +00:00
|
|
|
while (1) {
|
|
|
|
// Cancel
|
|
|
|
if (cancelHandler()) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = 0;
|
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
int len = (int)info.path_len;
|
2018-01-28 10:28:02 +00:00
|
|
|
res = adhocRecv(server_socket, path, &len);
|
2018-01-27 14:28:51 +00:00
|
|
|
if (res < 0 && res != SCE_ERROR_NET_ADHOC_WOULD_BLOCK) {
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sceKernelDelayThread(RECEIVE_WAIT);
|
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
// New path
|
|
|
|
char dst_path[MAX_PATH_LENGTH];
|
2018-08-27 09:56:01 +00:00
|
|
|
snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, path + server_info.path_len);
|
2018-01-27 21:37:09 +00:00
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
// Folder
|
|
|
|
if (info.type == SHARE_TYPE_FOLDER) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = sceIoMkdir(dst_path, 0777);
|
2018-01-27 21:37:09 +00:00
|
|
|
if (res < 0 && res != SCE_ERROR_ERRNO_EEXIST) {
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 21:37:09 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
value += DIRECTORY_SIZE;
|
2018-01-27 21:37:09 +00:00
|
|
|
SetProgress(value, server_info.file_size);
|
2018-01-27 14:28:51 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Receive file
|
2018-01-27 21:37:09 +00:00
|
|
|
if (info.type == SHARE_TYPE_FILE) {
|
|
|
|
SceUID fddst = sceIoOpen(dst_path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
|
|
|
|
if (fddst < 0) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = fddst;
|
|
|
|
goto CANCELED;
|
2018-01-27 21:37:09 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
void *buf = memalign(4096, SHARE_SIZE);
|
|
|
|
|
|
|
|
uint64_t recv_offset = 0;
|
|
|
|
while (recv_offset < info.file_size) {
|
|
|
|
// Cancel
|
|
|
|
if (cancelHandler()) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = 0;
|
2018-01-27 14:28:51 +00:00
|
|
|
free(buf);
|
2018-01-28 13:38:03 +00:00
|
|
|
sceIoClose(fddst);
|
|
|
|
sceIoRemove(dst_path);
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
uint64_t remain = info.file_size - recv_offset;
|
|
|
|
int len = (remain < SHARE_SIZE) ? (int)remain : SHARE_SIZE;
|
2018-01-28 10:28:02 +00:00
|
|
|
res = adhocRecv(server_socket, buf, &len);
|
2018-01-27 14:28:51 +00:00
|
|
|
if (res < 0 && res != SCE_ERROR_NET_ADHOC_WOULD_BLOCK) {
|
|
|
|
free(buf);
|
2018-01-28 13:38:03 +00:00
|
|
|
sceIoClose(fddst);
|
|
|
|
sceIoRemove(dst_path);
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res == 0) {
|
2018-01-27 21:37:09 +00:00
|
|
|
int written = sceIoWrite(fddst, buf, len);
|
|
|
|
if (written < 0) {
|
2018-01-28 10:28:02 +00:00
|
|
|
res = written;
|
2018-01-27 21:37:09 +00:00
|
|
|
free(buf);
|
2018-01-28 13:38:03 +00:00
|
|
|
sceIoClose(fddst);
|
|
|
|
sceIoRemove(dst_path);
|
2018-01-28 10:28:02 +00:00
|
|
|
goto CANCELED;
|
2018-01-27 21:37:09 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
recv_offset += len;
|
|
|
|
value += len;
|
2018-01-27 21:37:09 +00:00
|
|
|
SetProgress(value, server_info.file_size);
|
|
|
|
continue;
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
2018-01-27 21:37:09 +00:00
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
sceKernelDelayThread(RECEIVE_WAIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(buf);
|
2018-01-27 21:37:09 +00:00
|
|
|
sceIoClose(fddst);
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
// In case server finished earlier
|
|
|
|
uint32_t sync = 0x12345678;
|
|
|
|
adhocSend(server_socket, &sync, sizeof(uint32_t));
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
// Set progress to 100%
|
|
|
|
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
|
|
|
|
sceKernelDelayThread(COUNTUP_WAIT);
|
|
|
|
|
|
|
|
// Close
|
|
|
|
sceMsgDialogClose();
|
|
|
|
|
|
|
|
setDialogStep(DIALOG_STEP_ADHOC_RECEIVED);
|
2018-01-28 10:28:02 +00:00
|
|
|
goto EXIT;
|
|
|
|
|
|
|
|
CANCELED:
|
|
|
|
closeWaitDialog();
|
|
|
|
setDialogStep(DIALOG_STEP_CANCELED);
|
|
|
|
errorDialog(res);
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
EXIT:
|
|
|
|
if (thid >= 0)
|
|
|
|
sceKernelWaitThreadEnd(thid, NULL, NULL);
|
|
|
|
|
|
|
|
// Unlock power timers
|
2018-01-27 21:37:09 +00:00
|
|
|
powerUnlock();
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
// Close sockets and disconnect
|
|
|
|
adhocCloseSockets();
|
|
|
|
sceNetCtlAdhocDisconnect();
|
|
|
|
|
|
|
|
return sceKernelExitDeleteThread(0);
|
2018-01-26 10:36:14 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
int client_waiting_thread(SceSize args, void *argp) {
|
|
|
|
// Create PTP socket and wait for connection
|
|
|
|
sceNetAdhocctlGetEtherAddr(&client_addr);
|
2018-01-27 21:37:09 +00:00
|
|
|
client_socket = sceNetAdhocPtpListen(&client_addr, 1, SOCKET_BUFSIZE, RECEIVE_WAIT, 50, 1, 0);
|
2018-01-27 14:28:51 +00:00
|
|
|
if (client_socket < 0) {
|
|
|
|
server_request_result = client_socket;
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Establish PTP connection
|
|
|
|
SceUShort16 server_port;
|
|
|
|
server_socket = sceNetAdhocPtpAccept(client_socket, &server_addr, &server_port, 0, 0);
|
|
|
|
if (server_socket < 0) {
|
|
|
|
server_request_result = server_socket;
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we have successfully received a request from a server
|
|
|
|
int res = sceNetAdhocctlGetPeerInfo(&server_addr, sizeof(SceNetAdhocctlPeerInfo), &server_peer_info);
|
|
|
|
if (res < 0) {
|
|
|
|
server_request_result = res;
|
|
|
|
goto EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
server_request_result = 1;
|
|
|
|
|
|
|
|
EXIT:
|
|
|
|
return sceKernelExitDeleteThread(0);
|
2018-01-26 10:36:14 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 21:37:09 +00:00
|
|
|
void adhocAlertSockets() {
|
2018-01-27 14:28:51 +00:00
|
|
|
if (client_socket >= 0)
|
|
|
|
sceNetAdhocSetSocketAlert(client_socket, SCE_NET_ADHOC_F_ALERTALL);
|
2018-01-26 10:36:14 +00:00
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
if (server_socket >= 0)
|
2018-01-27 21:37:09 +00:00
|
|
|
sceNetAdhocSetSocketAlert(server_socket, SCE_NET_ADHOC_F_ALERTALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void adhocCloseSockets() {
|
|
|
|
adhocAlertSockets();
|
2018-01-27 14:28:51 +00:00
|
|
|
|
|
|
|
if (client_waiting_thid >= 0) {
|
|
|
|
sceKernelWaitThreadEnd(client_waiting_thid, NULL, NULL);
|
|
|
|
client_waiting_thid = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (client_socket >= 0) {
|
|
|
|
sceNetAdhocPtpClose(client_socket, 0);
|
|
|
|
client_socket = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (server_socket >= 0) {
|
|
|
|
sceNetAdhocPtpClose(server_socket, 0);
|
|
|
|
server_socket = -1;
|
2018-01-27 21:37:09 +00:00
|
|
|
}
|
2018-01-27 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int adhocUpdatePeerList() {
|
|
|
|
int buflen = 0;
|
|
|
|
sceNetAdhocctlGetPeerList(&buflen, NULL);
|
|
|
|
|
|
|
|
memset(peer_list, 0, PEERLIST_MAX * sizeof(SceNetAdhocctlPeerInfo));
|
|
|
|
peer_count = 0;
|
|
|
|
if (buflen > 0) {
|
|
|
|
if (buflen > PEERLIST_MAX * sizeof(SceNetAdhocctlPeerInfo)) {
|
|
|
|
buflen = PEERLIST_MAX * sizeof(SceNetAdhocctlPeerInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
peer_count = buflen / sizeof(SceNetAdhocctlPeerInfo);
|
|
|
|
sceNetAdhocctlGetPeerList(&buflen, peer_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
return peer_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int adhocSendServerResponse(char *response) {
|
|
|
|
return adhocSend(server_socket, response, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *adhocReceiveClientReponse() {
|
|
|
|
int len = 4;
|
|
|
|
adhocRecv(client_socket, client_response, &len);
|
|
|
|
return client_response;
|
|
|
|
}
|
|
|
|
|
|
|
|
int adhocReceiveServerRequest() {
|
|
|
|
return server_request_result;
|
|
|
|
}
|
2018-01-26 10:36:14 +00:00
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
char *adhocGetServerNickname() {
|
|
|
|
return (char *)server_peer_info.nickname.data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void adhocWaitingForServerRequest() {
|
|
|
|
server_request_result = 0;
|
|
|
|
|
|
|
|
client_waiting_thid = sceKernelCreateThread("client_waiting_thread", client_waiting_thread, 0x10000100, 0x4000, 0, 0, NULL);
|
|
|
|
if (client_waiting_thid >= 0)
|
|
|
|
sceKernelStartThread(client_waiting_thid, 0, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int getAdhocDialogStatus() {
|
|
|
|
return adhoc_dialog.status;
|
|
|
|
}
|
|
|
|
|
|
|
|
int initAdhocDialog() {
|
|
|
|
memset(&adhoc_dialog, 0, sizeof(AdhocDialog));
|
|
|
|
|
|
|
|
// Opening status
|
|
|
|
adhoc_dialog.result = ADHOC_DIALOG_RESULT_NONE;
|
|
|
|
adhoc_dialog.status = ADHOC_DIALOG_OPENING;
|
|
|
|
|
|
|
|
// Selector
|
|
|
|
adhoc_dialog.sel = 0;
|
|
|
|
|
|
|
|
// Width and height
|
|
|
|
adhoc_dialog.width = 340.0f;
|
|
|
|
adhoc_dialog.height = FONT_Y_SPACE * (PEERLIST_MAX + 1);
|
|
|
|
|
|
|
|
// For buttons
|
|
|
|
adhoc_dialog.height += 2.0f * FONT_Y_SPACE;
|
|
|
|
|
|
|
|
// Margin
|
|
|
|
adhoc_dialog.width += 2.0f * SHELL_MARGIN_X;
|
|
|
|
adhoc_dialog.height += 2.0f * SHELL_MARGIN_Y;
|
|
|
|
|
|
|
|
// Position
|
|
|
|
adhoc_dialog.x = ALIGN_CENTER(SCREEN_WIDTH, adhoc_dialog.width);
|
|
|
|
adhoc_dialog.y = ALIGN_CENTER(SCREEN_HEIGHT, adhoc_dialog.height);
|
|
|
|
|
|
|
|
// Align
|
|
|
|
int y_n = (int)((float)(adhoc_dialog.y - 2.0f) / FONT_Y_SPACE);
|
|
|
|
adhoc_dialog.y = (float)y_n * FONT_Y_SPACE + 2.0f;
|
|
|
|
|
|
|
|
// Scale
|
|
|
|
adhoc_dialog.scale = 0.0f;
|
|
|
|
|
|
|
|
// Reset
|
|
|
|
memset(peer_list, 0, PEERLIST_MAX * sizeof(SceNetAdhocctlPeerInfo));
|
|
|
|
peer_count = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void adhocDialogCtrl() {
|
|
|
|
adhocUpdatePeerList();
|
|
|
|
|
2018-09-17 07:25:33 +00:00
|
|
|
if (pressed_pad[PAD_ENTER]) {
|
2018-01-27 14:28:51 +00:00
|
|
|
if (peer_count > 0) {
|
|
|
|
SceNetAdhocctlPeerInfo *curr = peer_list;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < PEERLIST_MAX; i++) {
|
|
|
|
if (curr) {
|
|
|
|
if (adhoc_dialog.sel == i) {
|
|
|
|
memcpy(&client_addr, &curr->macAddr, sizeof(SceNetEtherAddr));
|
|
|
|
adhoc_dialog.result = ADHOC_DIALOG_RESULT_WAITING_FOR_RESPONSE;
|
|
|
|
adhoc_dialog.status = ADHOC_DIALOG_CLOSING;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
curr = curr->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pressed_pad[PAD_CANCEL]) {
|
|
|
|
sceNetCtlAdhocDisconnect();
|
|
|
|
adhoc_dialog.status = ADHOC_DIALOG_CLOSING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hold_pad[PAD_UP] || hold2_pad[PAD_LEFT_ANALOG_UP]) {
|
|
|
|
if (adhoc_dialog.sel > 0)
|
|
|
|
adhoc_dialog.sel--;
|
|
|
|
} else if (hold_pad[PAD_DOWN] || hold2_pad[PAD_LEFT_ANALOG_DOWN]) {
|
|
|
|
if (adhoc_dialog.sel < peer_count - 1)
|
|
|
|
adhoc_dialog.sel++;
|
|
|
|
}
|
|
|
|
|
2018-01-26 10:36:14 +00:00
|
|
|
// Easing out
|
|
|
|
if (adhoc_dialog.status == ADHOC_DIALOG_CLOSING) {
|
|
|
|
if (adhoc_dialog.scale > 0.0f) {
|
|
|
|
adhoc_dialog.scale -= easeOut(0.0f, adhoc_dialog.scale, 0.25f, 0.01f);
|
|
|
|
} else {
|
|
|
|
adhoc_dialog.status = ADHOC_DIALOG_CLOSED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adhoc_dialog.status == ADHOC_DIALOG_OPENING) {
|
|
|
|
if (adhoc_dialog.scale < 1.0f) {
|
|
|
|
adhoc_dialog.scale += easeOut(adhoc_dialog.scale, 1.0f, 0.25f, 0.01f);
|
|
|
|
} else {
|
|
|
|
adhoc_dialog.status = ADHOC_DIALOG_OPENED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
// Waiting state
|
|
|
|
if (adhoc_dialog.status == ADHOC_DIALOG_CLOSED) {
|
|
|
|
if (adhoc_dialog.result == ADHOC_DIALOG_RESULT_WAITING_FOR_RESPONSE) {
|
|
|
|
// Create PTP socket and start connection
|
|
|
|
sceNetAdhocctlGetEtherAddr(&server_addr);
|
2018-01-27 21:37:09 +00:00
|
|
|
client_socket = sceNetAdhocPtpOpen(&server_addr, 0, &client_addr, 1, SOCKET_BUFSIZE, RECEIVE_WAIT, 50, 0);
|
2018-01-27 14:28:51 +00:00
|
|
|
if (client_socket < 0) {
|
|
|
|
sceNetCtlAdhocDisconnect();
|
|
|
|
errorDialog(client_socket);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Establish PTP connection
|
|
|
|
/*int res = sceNetAdhocPtpConnect(client_socket, 0, SCE_NET_ADHOC_F_NONBLOCK);
|
|
|
|
if (res < 0) {
|
|
|
|
sceNetAdhocPtpClose(client_socket, 0);
|
|
|
|
sceNetCtlAdhocDisconnect();
|
|
|
|
errorDialog(res);
|
|
|
|
return;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
memset(client_response, 0, sizeof(client_response));
|
|
|
|
|
|
|
|
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_CANCEL, language_container[PLEASE_WAIT]);
|
|
|
|
setDialogStep(DIALOG_STEP_ADHOC_SEND_WAITING);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawAdhocDialog() {
|
|
|
|
if (adhoc_dialog.status == ADHOC_DIALOG_CLOSED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Dialog background
|
|
|
|
float dialog_width = vita2d_texture_get_width(dialog_image);
|
|
|
|
float dialog_height = vita2d_texture_get_height(dialog_image);
|
|
|
|
vita2d_draw_texture_scale_rotate_hotspot(dialog_image, adhoc_dialog.x + adhoc_dialog.width / 2.0f,
|
|
|
|
adhoc_dialog.y + adhoc_dialog.height / 2.0f,
|
|
|
|
adhoc_dialog.scale * (adhoc_dialog.width/dialog_width),
|
|
|
|
adhoc_dialog.scale * (adhoc_dialog.height/dialog_height),
|
|
|
|
0.0f, dialog_width / 2.0f, dialog_height / 2.0f);
|
|
|
|
|
2018-01-26 10:36:14 +00:00
|
|
|
if (adhoc_dialog.status == ADHOC_DIALOG_OPENED) {
|
|
|
|
float string_y = adhoc_dialog.y + SHELL_MARGIN_Y - 2.0f;
|
|
|
|
|
2018-01-27 14:28:51 +00:00
|
|
|
// Select PS Vita
|
|
|
|
pgf_draw_text(ALIGN_CENTER(SCREEN_WIDTH, pgf_text_width(language_container[ADHOC_SELECT_PSVITA])), string_y, DIALOG_COLOR, language_container[ADHOC_SELECT_PSVITA]);
|
|
|
|
string_y += FONT_Y_SPACE;
|
|
|
|
|
|
|
|
// Peer list
|
|
|
|
SceNetAdhocctlPeerInfo *curr = peer_list;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < PEERLIST_MAX; i++) {
|
|
|
|
if (curr) {
|
|
|
|
char *user = (char *)curr->nickname.data;
|
|
|
|
pgf_draw_text(ALIGN_CENTER(SCREEN_WIDTH, pgf_text_width(user)), string_y, (i == adhoc_dialog.sel) ? FOCUS_COLOR : DIALOG_COLOR, user);
|
|
|
|
curr = curr->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
string_y += FONT_Y_SPACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Buttons
|
|
|
|
char button_string[128];
|
|
|
|
sprintf(button_string, "%s %s %s %s", enter_button == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE ? CIRCLE : CROSS, language_container[OK],
|
|
|
|
enter_button == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE ? CROSS : CIRCLE, language_container[CANCEL]);
|
2018-01-26 10:36:14 +00:00
|
|
|
pgf_draw_text(ALIGN_CENTER(SCREEN_WIDTH, pgf_text_width(button_string)), string_y + FONT_Y_SPACE, DIALOG_COLOR, button_string);
|
|
|
|
}
|
2018-08-27 15:34:44 +00:00
|
|
|
}
|